更新
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import type { func } from '../type';
|
||||
|
||||
export const isUndefined = function (input: any) {
|
||||
return typeof input === 'undefined';
|
||||
};
|
||||
|
||||
export const isPlainObject = function (input: any) {
|
||||
// 注意不能使用以下方式判断,因为IE9/IE10下,对象的__proto__是 undefined
|
||||
// return isObject(input) && input.__proto__ === Object.prototype;
|
||||
if (typeof input !== 'object' || input === null) {
|
||||
return false;
|
||||
}
|
||||
const proto = Object.getPrototypeOf(input);
|
||||
if (proto === null) { // edge case Object.create(null)
|
||||
return true;
|
||||
}
|
||||
let baseProto = proto;
|
||||
while (Object.getPrototypeOf(baseProto) !== null) {
|
||||
baseProto = Object.getPrototypeOf(baseProto);
|
||||
}
|
||||
// 原型链第一个和最后一个比较
|
||||
return proto === baseProto;
|
||||
};
|
||||
|
||||
export const isArray = function (input: any) {
|
||||
if (typeof Array.isArray === 'function') {
|
||||
return Array.isArray(input);
|
||||
}
|
||||
return (Object as any).prototype.toString.call(input).match(/^\[object (.*)\]$/)[1].toLowerCase() === 'array';
|
||||
};
|
||||
|
||||
export const isPrivateKey = function (key: string) {
|
||||
return key.startsWith('_');
|
||||
};
|
||||
|
||||
export const isUrl = function (url: string) {
|
||||
return /^(https?:\/\/(([a-zA-Z0-9]+-?)+[a-zA-Z0-9]+\.)+[a-zA-Z]+)(:\d+)?(\/.*)?(\?.*)?(#.*)?$/.test(url);
|
||||
};
|
||||
|
||||
export const calculateTimeAgo = function (dateTimeStamp: number, t: func): string {
|
||||
const minute = 1000 * 60;
|
||||
const hour = minute * 60;
|
||||
const day = hour * 24;
|
||||
const week = day * 7;
|
||||
const now = new Date().getTime();
|
||||
const diffValue = now - dateTimeStamp;
|
||||
let result = '';
|
||||
|
||||
if (diffValue < 0) {
|
||||
return result;
|
||||
}
|
||||
const minC = diffValue / minute;
|
||||
const hourC = diffValue / hour;
|
||||
const dayC = diffValue / day;
|
||||
const weekC = diffValue / week;
|
||||
if (weekC >= 1 && weekC <= 4) {
|
||||
result = ` ${parseInt(`${weekC}`, 10)} ${t('time.周')}${t('time.前')}`;
|
||||
} else if (dayC >= 1 && dayC <= 6) {
|
||||
result = ` ${parseInt(`${dayC}`, 10)} ${t('time.天')}${t('time.前')}`;
|
||||
} else if (hourC >= 1 && hourC <= 23) {
|
||||
result = ` ${parseInt(`${hourC}`, 10)} ${t('time.小时')}${t('time.前')}`;
|
||||
} else if (minC >= 1 && minC <= 59) {
|
||||
result = ` ${parseInt(`${minC}`, 10)} ${t('time.分钟')}${t('time.前')}`;
|
||||
} else if (diffValue >= 0 && diffValue <= minute) {
|
||||
result = `${t('time.刚刚')}`;
|
||||
} else {
|
||||
const dateTime = new Date();
|
||||
dateTime.setTime(dateTimeStamp);
|
||||
const _year = dateTime.getFullYear();
|
||||
const _month = dateTime.getMonth() + 1 < 10 ? `0${dateTime.getMonth() + 1}` : dateTime.getMonth() + 1;
|
||||
const _date = dateTime.getDate() < 10 ? `0${dateTime.getDate()}` : dateTime.getDate();
|
||||
result = `${_year}-${_month}-${_date}`;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export function formatTime(secondTime: number) {
|
||||
const time: number = secondTime;
|
||||
let newTime = '';
|
||||
let hour: number | string;
|
||||
let minute: number | string;
|
||||
let seconds: any;
|
||||
if (time >= 3600) {
|
||||
hour = parseInt(`${time / 3600}`, 10) < 10 ? `0${parseInt(`${time / 3600}`, 10)}` : parseInt(`${time / 3600}`, 10);
|
||||
minute = parseInt(`${(time % 60) / 60}`, 10) < 10 ? `0${parseInt(`${(time % 60) / 60}`, 10)}` : parseInt(`${(time % 60) / 60}`, 10);
|
||||
seconds = time % 3600 < 10 ? `0${time % 3600}` : time % 3600;
|
||||
if (seconds > 60) {
|
||||
minute = parseInt(`${seconds / 60}`, 10) < 10 ? `0${parseInt(`${seconds / 60}`, 10)}` : parseInt(`${seconds / 60}`, 10);
|
||||
seconds = seconds % 60 < 10 ? `0${seconds % 60}` : seconds % 60;
|
||||
}
|
||||
newTime = `${hour}:${minute}:${seconds}`;
|
||||
} else if (time >= 60 && time < 3600) {
|
||||
minute = parseInt(`${time / 60}`, 10) < 10 ? `0${parseInt(`${time / 60}`, 10)}` : parseInt(`${time / 60}`, 10);
|
||||
seconds = time % 60 < 10 ? `0${time % 60}` : time % 60;
|
||||
newTime = `00:${minute}:${seconds}`;
|
||||
} else if (time < 60) {
|
||||
seconds = time < 10 ? `0${time}` : time;
|
||||
newTime = `00:00:${seconds}`;
|
||||
}
|
||||
return newTime;
|
||||
}
|
||||
|
||||
// Determine if it is a JSON string
|
||||
export function isJSON(str: string) {
|
||||
if (typeof str === 'string') {
|
||||
try {
|
||||
const data = JSON.parse(str);
|
||||
if (data) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine if it is a JSON string
|
||||
export const JSONToObject = function (str: string) {
|
||||
if (!str || !isJSON(str)) {
|
||||
return str;
|
||||
}
|
||||
return JSON.parse(str);
|
||||
};
|
||||
|
||||
// formate file size
|
||||
export const formateFileSize = function (fileSize: number) {
|
||||
let ret = '';
|
||||
if (fileSize >= 1024 * 1024) {
|
||||
ret = `${(fileSize / (1024 * 1024)).toFixed(2)} Mb`;
|
||||
} else if (fileSize >= 1024) {
|
||||
ret = `${(fileSize / 1024).toFixed(2)} Kb`;
|
||||
} else {
|
||||
ret = `${fileSize.toFixed(2)}B`;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* 重试函数, catch 时,重试
|
||||
*
|
||||
* @param {Promise} promise 需重试的函数
|
||||
* @param {number} num 需要重试的次数
|
||||
* @param {number} time 间隔时间(s)
|
||||
* @returns {Promise<any>} im 接口的 response 原样返回
|
||||
*/
|
||||
export const retryPromise = (promise: Promise<any>, num = 6, time = 0.5) => {
|
||||
let n = num;
|
||||
const func = () => promise;
|
||||
return func()
|
||||
.catch((error: any) => {
|
||||
if (n === 0) {
|
||||
throw error;
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
func();
|
||||
clearTimeout(timer);
|
||||
n--;
|
||||
}, time * 1000);
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
declare const wx: any;
|
||||
declare const qq: any;
|
||||
declare const tt: any;
|
||||
declare const swan: any;
|
||||
declare const my: any;
|
||||
declare const jd: any;
|
||||
declare const uni: any;
|
||||
declare const window: any;
|
||||
|
||||
export const IN_WX_MINI_APP_DESK = (typeof wx !== 'undefined' && typeof wx.getSystemInfoSync === 'function' && (wx.getSystemInfoSync().platform === 'mac' || wx.getSystemInfoSync().platform === 'windows'));
|
||||
export const IN_WX_MINI_APP = (typeof wx !== 'undefined' && typeof wx.getSystemInfoSync === 'function' && Boolean(wx.getSystemInfoSync().fontSizeSetting)) || IN_WX_MINI_APP_DESK;
|
||||
export const IN_QQ_MINI_APP = (typeof qq !== 'undefined' && typeof qq.getSystemInfoSync === 'function' && Boolean(qq.getSystemInfoSync().fontSizeSetting));
|
||||
export const IN_TT_MINI_APP = (typeof tt !== 'undefined' && typeof tt.getSystemInfoSync === 'function' && Boolean(tt.getSystemInfoSync().fontSizeSetting));
|
||||
export const IN_BAIDU_MINI_APP = (typeof swan !== 'undefined' && typeof swan.getSystemInfoSync === 'function' && Boolean(swan.getSystemInfoSync().fontSizeSetting));
|
||||
export const IN_ALIPAY_MINI_APP = (typeof my !== 'undefined' && typeof my.getSystemInfoSync === 'function' && Boolean(my.getSystemInfoSync().fontSizeSetting));
|
||||
export const IN_JD_MINI_APP = (typeof jd !== 'undefined' && typeof jd.getSystemInfoSync === 'function');
|
||||
export const IN_UNI_NATIVE_APP = (typeof uni !== 'undefined' && typeof window === 'undefined');
|
||||
// eslint-disable-next-line @stylistic/max-len
|
||||
export const IN_MINI_APP = IN_WX_MINI_APP || IN_QQ_MINI_APP || IN_TT_MINI_APP || IN_BAIDU_MINI_APP || IN_ALIPAY_MINI_APP || IN_JD_MINI_APP || IN_UNI_NATIVE_APP;
|
||||
export const IN_UNI_APP = (typeof uni !== 'undefined');
|
||||
export const IN_BROWSER = (function () {
|
||||
if (typeof uni !== 'undefined') {
|
||||
return !IN_MINI_APP;
|
||||
}
|
||||
return (typeof window !== 'undefined') && !IN_MINI_APP;
|
||||
})();
|
||||
|
||||
// runtime env
|
||||
export const APP_NAMESPACE = (() => {
|
||||
if (IN_QQ_MINI_APP) {
|
||||
return qq;
|
||||
}
|
||||
if (IN_TT_MINI_APP) {
|
||||
return tt;
|
||||
}
|
||||
if (IN_BAIDU_MINI_APP) {
|
||||
return swan;
|
||||
}
|
||||
if (IN_ALIPAY_MINI_APP) {
|
||||
return my;
|
||||
}
|
||||
if (IN_WX_MINI_APP) {
|
||||
return wx;
|
||||
}
|
||||
if (IN_UNI_NATIVE_APP) {
|
||||
return uni;
|
||||
}
|
||||
if (IN_JD_MINI_APP) {
|
||||
return jd;
|
||||
}
|
||||
if (IN_BROWSER) {
|
||||
return window;
|
||||
}
|
||||
return {};
|
||||
})();
|
||||
|
||||
const USER_AGENT = (IN_BROWSER && window && window.navigator && window.navigator.userAgent) || '';
|
||||
const IS_ANDROID = /Android/i.test(USER_AGENT);
|
||||
const IS_WIN_PHONE = /(?:Windows Phone)/.test(USER_AGENT);
|
||||
const IS_SYMBIAN = /(?:SymbianOS)/.test(USER_AGENT);
|
||||
const IS_IOS = /iPad/i.test(USER_AGENT) || /iPhone/i.test(USER_AGENT) || /iPod/i.test(USER_AGENT);
|
||||
|
||||
export const IS_H5 = IS_ANDROID || IS_WIN_PHONE || IS_SYMBIAN || IS_IOS;
|
||||
|
||||
export const IS_PC = IN_BROWSER && !IS_H5;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { isPlainObject } from './common-utils';
|
||||
|
||||
const isEmpty = function (input: any) {
|
||||
// Null and Undefined...
|
||||
if (input === null || typeof (input) === 'undefined') return true;
|
||||
// Booleans...
|
||||
if (typeof input === 'boolean') return false;
|
||||
// Numbers...
|
||||
if (typeof input === 'number') return input === 0;
|
||||
// Strings...
|
||||
if (typeof input === 'string') return input.length === 0;
|
||||
// Functions...
|
||||
if (typeof input === 'function') return input.length === 0;
|
||||
// Arrays...
|
||||
if (Array.isArray(input)) return input.length === 0;
|
||||
// Errors...
|
||||
if (input instanceof Error) return input.message === '';
|
||||
// plain object
|
||||
if (isPlainObject(input)) {
|
||||
for (const key in input) {
|
||||
if (Object.prototype.hasOwnProperty.call(input, key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export default isEmpty;
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { func } from '../type';
|
||||
|
||||
class Middleware {
|
||||
private cache: func[];
|
||||
private middlewares: func[];
|
||||
private options: any;
|
||||
constructor() {
|
||||
this.cache = [];
|
||||
this.middlewares = [];
|
||||
this.options = null; // 缓存options
|
||||
}
|
||||
|
||||
use(fn: func) {
|
||||
if (typeof fn !== 'function') {
|
||||
console.error('middleware must be a function');
|
||||
}
|
||||
this.cache.push(fn);
|
||||
return this;
|
||||
}
|
||||
|
||||
next(): any {
|
||||
if (this.middlewares && this.middlewares.length > 0) {
|
||||
const ware: any = this.middlewares.shift();
|
||||
return ware.call(this, this.options, this.next.bind(this));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} options - 数据的入口
|
||||
* @returns {Function}
|
||||
*/
|
||||
run(options: any): any {
|
||||
this.middlewares = this.cache.map(fn => fn);
|
||||
this.options = options; // 缓存数据
|
||||
return this.next();
|
||||
}
|
||||
}
|
||||
|
||||
export default Middleware;
|
||||
@@ -0,0 +1,85 @@
|
||||
import { IN_MINI_APP, APP_NAMESPACE } from './env';
|
||||
|
||||
/**
|
||||
* storage 中写入一条数据。若key已存在,则会覆盖已有数据。
|
||||
* @param {String} key - 缓存的key
|
||||
* @param {*} value - 任何可JSON序列化的数据
|
||||
* @param {Boolean} withPrefix 是否需要拼接 prefix 和 key,默认为 true,即需要拼接。
|
||||
*/
|
||||
export function setStorageItem(key: string, value: any, withPrefix = true) {
|
||||
const realKey = withPrefix ? _getKey(key) : key;
|
||||
_setStorageSync(realKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取storage中的一条数据
|
||||
* @param {String} key - 缓存的key
|
||||
* @param {Boolean} withPrefix 是否需要拼接 prefix 和 key,默认为 true,即需要拼接。
|
||||
* @returns {any} 返回指定key的数据
|
||||
*/
|
||||
export function getStorageItem(key: string, withPrefix = true): any {
|
||||
try {
|
||||
const realKey: string = withPrefix ? _getKey(key) : key;
|
||||
return _getStorageSync(realKey);
|
||||
} catch (error) {
|
||||
console.warn('Storage.getStorageItem error:', error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定key的数据
|
||||
* @param {String} key - 缓存的key
|
||||
* @param {Boolean} withPrefix 是否需要拼接 prefix 和 key,默认为 true,即需要拼接。
|
||||
*/
|
||||
export function removeStorageItem(key: string, withPrefix = true) {
|
||||
try {
|
||||
const realKey = withPrefix ? _getKey(key) : key;
|
||||
_removeStorageSync(realKey);
|
||||
} catch (error) {
|
||||
console.warn('Storage.removeStorageItem error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function _setStorageSync(key: string, data: string) {
|
||||
if (IN_MINI_APP) {
|
||||
APP_NAMESPACE.setStorageSync(key, data);
|
||||
} else if (_canIUseCookies()) {
|
||||
localStorage.setItem(key, JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
function _getStorageSync(key: string): any {
|
||||
if (IN_MINI_APP) {
|
||||
return APP_NAMESPACE.getStorageSync(key);
|
||||
}
|
||||
if (_canIUseCookies()) {
|
||||
const data: any = localStorage.getItem(key);
|
||||
if (data !== 'undefined') {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function _removeStorageSync(key: string) {
|
||||
if (IN_MINI_APP) {
|
||||
APP_NAMESPACE.removeStorageSync(key);
|
||||
} else if (_canIUseCookies()) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
function _getKey(key: string) {
|
||||
return `chat_engine_${key}`;
|
||||
}
|
||||
|
||||
// 如果用户选择 block cookies,此时访问 localStorage 浏览器会抛错
|
||||
// Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document
|
||||
// 通过 navigator.cookieEnabled 短路逻辑规避
|
||||
function _canIUseCookies() {
|
||||
// When the browser is configured to block third-party cookies, and navigator.cookieEnabled is invoked inside a third-party iframe,
|
||||
// it returns true in Safari, Edge Spartan and IE (while trying to set a cookie in such scenario would fail).
|
||||
// It returns false in Firefox and Chromium-based browsers.
|
||||
return navigator && navigator.cookieEnabled && localStorage;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* eslint-disable prefer-rest-params */
|
||||
import type { ITUIChatEngine } from '../interface/engine';
|
||||
import Middleware from './middleware';
|
||||
import { ERROR_CODE_ENGINE, ERROR_MSG_ENGINE } from '../const';
|
||||
|
||||
export default function validateInitialization(
|
||||
TUIChatEngine: ITUIChatEngine,
|
||||
target: any,
|
||||
APIList: object,
|
||||
) {
|
||||
const obj = Object.create(null);
|
||||
Object.keys(APIList).forEach((api) => {
|
||||
if (!target[api]) {
|
||||
return;
|
||||
}
|
||||
obj[api] = target[api];
|
||||
|
||||
const validateMiddleware = new Middleware();
|
||||
target[api] = function () {
|
||||
const args = Array.from(arguments);
|
||||
validateMiddleware
|
||||
.use((options: any, next: any) => {
|
||||
if (TUIChatEngine.isInited) {
|
||||
return next();
|
||||
}
|
||||
return Promise.reject({
|
||||
code: ERROR_CODE_ENGINE.NOT_INIT,
|
||||
message: `${api} | ${ERROR_MSG_ENGINE.NOT_INIT}`,
|
||||
});
|
||||
})
|
||||
.use((options: any) => obj[api].apply(target, options));
|
||||
return validateMiddleware.run(args);
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user