vite-uni-dev-tool
Version:
vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试
733 lines (620 loc) • 18.6 kB
text/typescript
import type { DevTool } from '../type';
import { DEV_TOOL_INFO } from '../const';
import {
isNil,
isNumber,
setValueByPath,
getLanIp,
getMicroAppIp,
getWifiIp,
isBoolean,
} from '../utils/index';
import { backup } from '../core';
import { getDevToolInfo, setDevToolInfo } from '../devToolInfo';
/** 数据存储中心 */
export class DevStore {
/** 状态数据 */
private state: DevTool.WindowData = {
consoleList: [],
networkList: [],
storageList: [],
routeList: [],
vuexList: {},
piniaList: {},
deviceInfo: {},
windowInfo: {},
systemInfo: {},
appInfo: {},
wsList: [],
netWorkStatus: {},
uploadList: [],
eventList: [],
eventCount: {
on: 0,
once: 0,
emit: 0,
off: 0,
},
captureScreenList: [],
};
/** 调试配置 */
private devToolOptions: DevTool.DevToolOptions | undefined;
/** 日志最大值 */
private uploadMaxSize = 1000;
/** 日志最大值 */
private consoleMaxSize = 1000;
/** 网络最大值 */
private networkMaxSize = 1000;
/** ws数据最大值 */
private wsDataMaxSize = 1000;
/** 事件列表最大值 */
private eventListMaxSize = 1000;
/** 截屏最大值 */
private captureScreenMaxSize = 1000;
/** 缓存最大值 */
cacheMaxSize = 8 * 1024 * 1024 * 10;
private vuexStore: any;
private piniaStore: any;
private uploadTaskMap = new Map<number | string, UniApp.UploadTask>();
private requestIndex = -1;
private uploadIndex = -1;
/** 是否显示按钮 */
private devToolVisible = false;
/** 是否销毁 */
private devToolDestroy = false;
/** 是否开启拦截Promise reject错误 */
enableInterceptPromiseReject = false;
private zIndex = 1000;
constructor() {
const { devToolDestroy = false, devToolButtonVisible = false } =
uni.getStorageSync(DEV_TOOL_INFO);
this.devToolDestroy = devToolDestroy;
this.devToolVisible = devToolButtonVisible;
}
setDevToolVisible(visible: boolean) {
this.devToolVisible = visible;
setDevToolInfo({
devToolButtonVisible: visible,
});
}
getDevToolVisible() {
return this.devToolVisible;
}
setWindowInfo(windowInfo: Record<string, any>) {
this.state.windowInfo = windowInfo;
}
setDeviceInfo(deviceInfo: Record<string, any>) {
this.state.deviceInfo = deviceInfo;
}
setSystemInfo(systemInfo: Record<string, any>) {
this.state.systemInfo = systemInfo;
}
setNetWorkStatus(netWorkStatus: Record<string, any>) {
this.state.netWorkStatus = netWorkStatus;
}
setVuexList(vuexList: Record<string, any>) {
this.state.vuexList = vuexList;
}
setPiniaList(piniaList: Record<string, any>) {
this.state.piniaList = {
...(this.state.piniaList || {}),
...piniaList,
};
}
setRequestIndex(index: number) {
this.requestIndex = index;
return this.requestIndex;
}
getDevToolOptions() {
return this.devToolOptions;
}
getRequestIndex() {
return this.requestIndex;
}
setUploadIndex(index: number) {
this.uploadIndex = index;
return this.uploadIndex;
}
getUploadIndex() {
return this.uploadIndex;
}
setDevToolOptions(options: DevTool.DevToolOptions) {
this.devToolOptions = options;
this.uploadMaxSize = options.uploadMaxSize || 1000;
this.consoleMaxSize = options.consoleMaxSize || 1000;
this.networkMaxSize = options.networkMaxSize || 1000;
this.wsDataMaxSize = options.wsDataMaxSize || 1000;
this.cacheMaxSize = options.cacheMaxSize || 8 * 1024 * 1024 * 10;
this.eventListMaxSize = options.eventListMaxSize || 1000;
this.captureScreenMaxSize = options.captureScreenMaxSize || 1000;
this.zIndex = options.zIndex || 1000;
const { devToolButtonVisible } = getDevToolInfo();
this.devToolVisible = isBoolean(devToolButtonVisible)
? devToolButtonVisible
: (options.initShowDevTool ?? true);
this.setDevToolVisible(this.devToolVisible);
const pages =
options.pagesJson?.pages.map((page) => {
const isNav = options.pagesJson?.tabBar?.list?.some(
(nav) => nav.pagePath === page.path,
);
return {
...page,
type: isNav ? 'nav' : 'main',
};
}) ?? [];
// 处理 subPackages
options.pagesJson?.subPackages?.forEach((pack) => {
pack.pages.forEach((page) => {
const p = {
...page,
path: `${pack.root}/${page.path}`,
type: 'sub',
};
pages.push(p);
});
});
this.setRouteList(pages);
}
async getDevData() {
const networkType = await uni.getNetworkType();
const systemInfo = uni.getSystemInfoSync();
const deviceInfo = uni.getDeviceInfo();
const windowInfo = uni.getWindowInfo();
const appInfo = {
...(await uni.getAppBaseInfo()),
// #ifndef H5
...(await uni.getAppAuthorizeSetting()),
// #endif
};
const ip = getWifiIp() || getLanIp() || (await getMicroAppIp());
return {
...this.state,
systemInfo,
deviceInfo,
windowInfo,
devToolVisible: this.getDevToolVisible(),
appInfo,
netWorkStatus: {
ip,
...networkType,
isConnected: networkType.networkType !== 'none',
},
};
}
updateStore(data: { key: string; _oldKey: string; value: any }) {
const { key, _oldKey, value } = data;
if (_oldKey !== key) {
uni.removeStorageSync(_oldKey);
this.state.storageList = this.state.storageList?.filter(
(item) => item.key === _oldKey,
);
}
uni.setStorageSync(key, value);
this.state.storageList?.push({
key,
_oldKey,
value,
});
return this.state.storageList;
}
updateVuexStore(data: Record<string, any>) {
try {
// 更改vuex数据
Object.assign(this.vuexStore?.state ?? {}, data);
} catch (error) {
console.error('[DevTool] updateVuexStore error', error);
}
// 更新vuexList
this.setVuexList({
...(this.vuexStore?.state ?? {}),
});
return this.state.vuexList;
}
setPiniaStore(piniaStore: any) {
this.piniaStore = piniaStore;
}
updatePiniaStore(data: Record<string, any>) {
try {
if (!this.piniaStore) {
console.error('[DevTool] updatePiniaStore piniaStore is undefined');
return {};
}
const [key, value] = Object.entries(data)[0];
if (isNil(key)) {
console.error('[DevTool] updatePiniaStore key is undefined or null');
return {};
}
setValueByPath(this.piniaStore.state.value, key, value);
this.setPiniaList({
...(this.piniaStore.state.value ?? {}),
});
} catch (error) {
console.error('[DevTool] updatePiniaStore error', error);
}
return this.state.piniaList ?? {};
}
getExportData(exports: {
exportLog: boolean;
exportNetwork: boolean;
exportStorage: boolean;
exportWebSocket: boolean;
exportUpload: boolean;
exportWindow: boolean;
exportDevice: boolean;
exportSystem: boolean;
}) {
const data: DevTool.WindowData = {};
if (exports.exportLog) {
data['consoleList'] = this.state.consoleList;
}
if (exports.exportNetwork) {
data['networkList'] = this.state.networkList;
}
if (exports.exportStorage) {
data['storageList'] = this.state.storageList;
data['vuexList'] = this.state.vuexList;
data['piniaList'] = this.state.piniaList;
}
if (exports.exportUpload) {
data['uploadList'] = this.state.uploadList;
}
if (exports.exportWebSocket) {
data['wsList'] = this.state.wsList;
}
if (exports.exportWindow) {
data['windowInfo'] = this.state.windowInfo;
}
if (exports.exportDevice) {
data['deviceInfo'] = this.state.deviceInfo;
}
if (exports.exportSystem) {
data['systemInfo'] = this.state.systemInfo;
}
return data;
}
clearConsoleList() {
this.state.consoleList = [];
}
clearDevCache() {
this.state.consoleList = [];
this.state.networkList = [];
this.state.wsList = [];
this.state.uploadList = [];
this.state.eventList = [];
this.state.eventCount = {
on: 0,
once: 0,
emit: 0,
off: 0,
};
}
clearAll() {
this.state.consoleList = [];
this.state.networkList = [];
this.state.storageList = [];
this.state.routeList = [];
this.state.wsList = [];
this.state.uploadList = [];
this.state.vuexList = {};
this.state.piniaList = {};
this.state.deviceInfo = {};
this.state.windowInfo = {};
this.state.systemInfo = {};
this.state.netWorkStatus = {};
this.state.appInfo = {};
this.state.eventList = [];
this.state.eventCount = {
on: 0,
once: 0,
emit: 0,
off: 0,
};
this.state.captureScreenList = [];
}
addUploadTask(index: number | string, task: UniApp.UploadTask) {
this.uploadTaskMap.set(index, task);
}
removeUploadTask(index: number | string) {
this.uploadTaskMap.delete(index);
}
clearUploadTask() {
this.uploadTaskMap.clear();
}
clearWsList() {
this.state.wsList = [];
}
updateWsList(item: DevTool.WS) {
if (!this.getDevToolVisible()) {
return [];
}
const index =
this.state?.wsList?.findIndex((w) => w.url === item.url) ?? -1;
if (index > -1) {
if (this.state.wsList?.[index]) {
const ws = this.state.wsList[index];
ws.headers = item.headers ?? ws.headers;
ws.readyState = item.readyState ?? ws.readyState;
ws.method = item.method ?? ws.method;
ws.protocols = item.protocols ?? ws.protocols;
ws.message = [
...(this.state.wsList[index].message ?? []),
...(item.message ?? []),
];
const max = this.wsDataMaxSize;
const len = ws?.message?.length ?? 0;
if (Array.isArray(ws?.message) && len > max) {
ws?.message?.splice(0, len - max);
}
}
} else {
this.state.wsList?.push(item);
}
return this.state.wsList;
}
clearWsMessage(url: string) {
const wsIndex =
this.state?.wsList?.findIndex((item) => item.url === url) ?? -1;
if (wsIndex === -1) return;
if (this.state.wsList?.[wsIndex]) {
this.state.wsList[wsIndex].message = [];
}
}
clearStorageList() {
this.state.storageList = [];
uni.clearStorage();
return this.state.storageList;
}
setStorageList(items: DevTool.StorageItem[]) {
if (!this.getDevToolVisible()) return;
this.state.storageList = items;
return this.state.storageList;
}
removeStorage(key: string) {
this.state.storageList =
this.state.storageList?.filter((item) => item.key !== key) ?? [];
uni.removeStorageSync(key);
return this.state.storageList;
}
addStorage(data: { key: string; value: any }) {
const { key, value } = data;
this.state.storageList?.unshift({
key,
_oldKey: key,
value,
});
uni.setStorageSync(key, value);
return this.state.storageList;
}
refreshStore() {
const { keys } = uni.getStorageInfoSync();
this.state.storageList = keys.map((key) => {
const value = uni.getStorageSync(key);
return {
key,
_oldKey: key,
value,
};
});
return this.state.storageList;
}
updateStoreList(addItems: DevTool.StorageItem[]) {
const cur = addItems[0];
const index =
this.state.storageList?.findIndex((item) => item.key === cur._oldKey) ??
-1;
if (index > -1 && addItems.length === 1) {
if (this.state.storageList?.[index]) {
this.state.storageList[index] = addItems[0];
}
} else {
this.state.storageList?.push(...addItems);
}
return this.state.storageList;
}
setRouteList(pages: DevTool.Page[], currentPath?: string) {
if (!this.getDevToolVisible()) return;
const currentP = currentPath || pages?.[0]?.path || '';
this.state.routeList = pages.map((item, index) => {
return {
type: item.type,
path: item.path,
style: item.style,
index:
item.path === currentP && index === 0
? 4
: item.path === currentP
? 3
: index === 0
? 2
: 1,
name: item.style.navigationBarTitleText || '无名',
};
});
return this.state.routeList;
}
getRouteList() {
return this.state.routeList;
}
updateCurrentPagePath(path: string) {
if (!this.getDevToolVisible()) return;
path = path === '/' ? (this.state.routeList?.[0]?.path ?? path) : path;
this.state.routeList =
this.state.routeList?.map((item, index) => {
return {
type: item.type,
path: item.path,
style: item.style,
index:
item.path === path && index === 0
? 4
: item.path === path
? 3
: index === 0
? 2
: 1,
name: item.style.navigationBarTitleText || '无名',
};
}) ?? [];
return this.state.routeList;
}
setConsoleList(items: DevTool.ConsoleItem[]) {
if (!this.getDevToolVisible()) return;
if (
(this.state?.consoleList?.length ?? 0) + items.length >
this.consoleMaxSize
) {
this.state.consoleList = [];
}
this.state.consoleList = items;
}
updateConsoleList(addItems: DevTool.ConsoleItem[], index?: number) {
if (!this.getDevToolVisible()) return;
if (isNumber(index) && index > -1 && addItems.length === 1) {
if (this.state.consoleList?.[index]) {
this.state.consoleList[index] = addItems[0];
}
} else {
if (
(this.state?.consoleList?.length ?? 0) + addItems.length >
this.cacheMaxSize
) {
this.state.consoleList?.splice(
0,
this.state.consoleList.length - this.cacheMaxSize - addItems.length,
);
}
this.state?.consoleList?.push(...addItems);
}
return this.state.consoleList;
}
clearNetworkList() {
this.state.networkList = [];
}
setNetworkList(items: DevTool.NetworkItem[]) {
if (!this.getDevToolVisible()) return;
if (
(this.state?.networkList?.length ?? 0) + items.length >
this.networkMaxSize
) {
this.state.networkList = [];
}
this.state.networkList = items;
}
updateNetworkList(addItems: DevTool.NetworkItem[], index?: number) {
if (isNumber(index) && index > -1) {
if (this.state?.networkList?.[index]) {
this.state.networkList[index] = addItems[0];
}
} else {
const max = this.networkMaxSize;
const len = this.state?.networkList?.length ?? 0;
if (len + addItems.length > max) {
this.state.networkList?.splice(0, len - max - addItems.length);
}
this.state?.networkList?.push(...addItems);
}
return this.state.networkList;
}
updateUploadList(addItems: DevTool.UploadItem[], index?: number) {
if (isNumber(index) && index > -1 && addItems.length === 1) {
if (this.state.uploadList?.[index]) {
this.state.uploadList[index] = {
...this.state.uploadList[index],
...addItems[0],
};
} else {
const max = this.uploadMaxSize;
const len = this.state?.uploadList?.length ?? 0;
if (len + addItems.length > max) {
this.state.uploadList?.splice(0, len - max - addItems.length);
}
this.state.uploadList?.push(addItems[0]);
}
}
return this.state.uploadList;
}
clearUploadList() {
this.state.uploadList = [];
}
setDevToolDestroy(destroy: boolean) {
this.devToolDestroy = destroy;
setDevToolInfo({
devToolDestroy: destroy,
});
}
getDevToolDestroy() {
const { devToolDestroy = false } = uni.getStorageSync(DEV_TOOL_INFO);
return this.devToolDestroy ?? devToolDestroy;
}
getCurrentPagePath() {
let pages = getCurrentPages();
let item = pages[pages.length - 1];
if (item && item.route) {
return item.route;
}
return '';
}
/**
* 新增事件
*
* @param {DevTool.EventItem} event
* @memberof DevStore
*/
addEventItem(event: DevTool.EventItem) {
if (!this.state.eventList) {
this.state.eventList = [];
}
this.state.eventList?.push(event);
}
/**
* 增加注册事件的数量
*
* @param {DevTool.EventCountKey} type
* @memberof DevStore
*/
updateUniEventCount(type: DevTool.EventCountKey) {
if (!this.state.eventCount) {
this.state.eventCount = {
on: 0,
once: 0,
emit: 0,
off: 0,
};
}
this.state.eventCount[type] = this.state.eventCount[type] + 1;
}
updateUniEventList(evenList: DevTool.EventItem[]) {
const len = this.state.eventList?.length ?? 0;
const max = this.eventListMaxSize;
if (len + evenList.length > max) {
this.state.eventList?.splice(0, len - max - evenList.length);
}
this.state.eventList?.push(...evenList);
return this.state.eventList;
}
uniEventClear() {
this.state.eventCount = {
on: 0,
once: 0,
emit: 0,
off: 0,
};
this.state.eventList = [];
}
updateCaptureScreenList(captureScreenList: DevTool.CaptureScreenItem[]) {
const len = this.state.captureScreenList?.length ?? 0;
const max = this.captureScreenMaxSize;
if (len + captureScreenList.length > max) {
this.state.captureScreenList?.splice(
0,
len - max - captureScreenList.length,
);
}
this.state.captureScreenList?.push(...captureScreenList);
return this.state.captureScreenList;
}
clearCaptureScreenList() {
this.state.captureScreenList = [];
}
}