perf: 同步精简版代码
This commit is contained in:
@@ -3,7 +3,7 @@ import {
|
||||
resultType,
|
||||
PureHttpError,
|
||||
RequestMethods,
|
||||
PureHttpResoponse,
|
||||
PureHttpResponse,
|
||||
PureHttpRequestConfig
|
||||
} from "./types.d";
|
||||
import qs from "qs";
|
||||
@@ -91,7 +91,7 @@ class PureHttp {
|
||||
private httpInterceptorsResponse(): void {
|
||||
const instance = PureHttp.axiosInstance;
|
||||
instance.interceptors.response.use(
|
||||
(response: PureHttpResoponse) => {
|
||||
(response: PureHttpResponse) => {
|
||||
const $config = response.config;
|
||||
// 关闭进度条动画
|
||||
NProgress.done();
|
||||
|
4
src/utils/http/types.d.ts
vendored
4
src/utils/http/types.d.ts
vendored
@@ -18,13 +18,13 @@ export interface PureHttpError extends AxiosError {
|
||||
isCancelRequest?: boolean;
|
||||
}
|
||||
|
||||
export interface PureHttpResoponse extends AxiosResponse {
|
||||
export interface PureHttpResponse extends AxiosResponse {
|
||||
config: PureHttpRequestConfig;
|
||||
}
|
||||
|
||||
export interface PureHttpRequestConfig extends AxiosRequestConfig {
|
||||
beforeRequestCallback?: (request: PureHttpRequestConfig) => void;
|
||||
beforeResponseCallback?: (response: PureHttpResoponse) => void;
|
||||
beforeResponseCallback?: (response: PureHttpResponse) => void;
|
||||
}
|
||||
|
||||
export default class PureHttp {
|
||||
|
@@ -94,8 +94,9 @@ export const isServer = typeof window === "undefined";
|
||||
|
||||
export const isClient = !isServer;
|
||||
|
||||
export function isUrl(path: string): boolean {
|
||||
export function isUrl<T>(path: T): boolean {
|
||||
const reg =
|
||||
/(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
|
||||
// @ts-expect-error
|
||||
return reg.test(path);
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
export const openLink = (link: string) => {
|
||||
export const openLink = <T>(link: T): void => {
|
||||
const $a: HTMLElement = document.createElement("a");
|
||||
// @ts-expect-error
|
||||
$a.setAttribute("href", link);
|
||||
$a.setAttribute("target", "_blank");
|
||||
$a.setAttribute("rel", "noreferrer noopener");
|
||||
|
54
src/utils/loaders/index.ts
Normal file
54
src/utils/loaders/index.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
interface ProxyLoader {
|
||||
loadCss(src: string): any;
|
||||
loadScript(src: string): Promise<any>;
|
||||
loadScriptConcurrent(src: Array<string>): Promise<any>;
|
||||
}
|
||||
|
||||
class loaderProxy implements ProxyLoader {
|
||||
constructor() {}
|
||||
|
||||
protected scriptLoaderCache: Array<string> = [];
|
||||
|
||||
public loadCss = (src: string): any => {
|
||||
const element: HTMLLinkElement = document.createElement("link");
|
||||
element.rel = "stylesheet";
|
||||
element.href = src;
|
||||
document.body.appendChild(element);
|
||||
};
|
||||
|
||||
public loadScript = async (src: string): Promise<any> => {
|
||||
if (this.scriptLoaderCache.includes(src)) {
|
||||
return src;
|
||||
} else {
|
||||
const element: HTMLScriptElement = document.createElement("script");
|
||||
element.src = src;
|
||||
document.body.appendChild(element);
|
||||
element.onload = () => {
|
||||
return this.scriptLoaderCache.push(src);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
public loadScriptConcurrent = async (
|
||||
srcList: Array<string>
|
||||
): Promise<any> => {
|
||||
if (Array.isArray(srcList)) {
|
||||
const len: number = srcList.length;
|
||||
if (len > 0) {
|
||||
let count = 0;
|
||||
srcList.map(src => {
|
||||
if (src) {
|
||||
this.loadScript(src).then(() => {
|
||||
count++;
|
||||
if (count === len) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const loader = new loaderProxy();
|
@@ -1,3 +1,5 @@
|
||||
import type { FunctionArgs } from "@vueuse/core";
|
||||
|
||||
export const hasClass = (ele: RefType<any>, cls: string): any => {
|
||||
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
||||
};
|
||||
@@ -40,3 +42,16 @@ export const toggleClass = (
|
||||
className = className.replace(clsName, "");
|
||||
targetEl.className = flag ? `${className} ${clsName} ` : className;
|
||||
};
|
||||
|
||||
export function useRafThrottle<T extends FunctionArgs>(fn: T): T {
|
||||
let locked = false;
|
||||
// @ts-ignore
|
||||
return function (...args) {
|
||||
if (locked) return;
|
||||
locked = true;
|
||||
window.requestAnimationFrame(() => {
|
||||
fn.apply(this, args);
|
||||
locked = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
226
src/utils/print.ts
Normal file
226
src/utils/print.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
interface PrintFunction {
|
||||
extendOptions: Function;
|
||||
getStyle: Function;
|
||||
setDomHeight: Function;
|
||||
toPrint: Function;
|
||||
}
|
||||
|
||||
const Print = function (dom, options?: object): PrintFunction {
|
||||
options = options || {};
|
||||
// @ts-expect-error
|
||||
if (!(this instanceof Print)) return new Print(dom, options);
|
||||
this.conf = {
|
||||
styleStr: "",
|
||||
// Elements that need to dynamically get and set the height
|
||||
setDomHeightArr: [],
|
||||
// Echart dom List
|
||||
echartDomArr: [],
|
||||
// Callback before printing
|
||||
printBeforeFn: null,
|
||||
// Callback after printing
|
||||
printDoneCallBack: null
|
||||
};
|
||||
for (const key in this.conf) {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (key && options.hasOwnProperty(key)) {
|
||||
this.conf[key] = options[key];
|
||||
}
|
||||
}
|
||||
if (typeof dom === "string") {
|
||||
this.dom = document.querySelector(dom);
|
||||
} else {
|
||||
this.dom = this.isDOM(dom) ? dom : dom.$el;
|
||||
}
|
||||
if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) {
|
||||
this.setDomHeight(this.conf.setDomHeightArr);
|
||||
}
|
||||
this.init();
|
||||
};
|
||||
|
||||
Print.prototype = {
|
||||
/**
|
||||
* init
|
||||
*/
|
||||
init: function (): void {
|
||||
const content = this.getStyle() + this.getHtml();
|
||||
this.writeIframe(content);
|
||||
},
|
||||
/**
|
||||
* Configuration property extension
|
||||
* @param {Object} obj
|
||||
* @param {Object} obj2
|
||||
*/
|
||||
extendOptions: function <T>(obj, obj2: T): T {
|
||||
for (const k in obj2) {
|
||||
obj[k] = obj2[k];
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
/**
|
||||
Copy all styles of the original page
|
||||
*/
|
||||
getStyle: function (): string {
|
||||
let str = "";
|
||||
const styles: NodeListOf<Element> = document.querySelectorAll("style,link");
|
||||
for (let i = 0; i < styles.length; i++) {
|
||||
str += styles[i].outerHTML;
|
||||
}
|
||||
str += `<style>.no-print{display:none;}${this.conf.styleStr}</style>`;
|
||||
return str;
|
||||
},
|
||||
// form assignment
|
||||
getHtml: function (): Element {
|
||||
const inputs = document.querySelectorAll("input");
|
||||
const selects = document.querySelectorAll("select");
|
||||
const textareas = document.querySelectorAll("textarea");
|
||||
for (let k = 0; k < inputs.length; k++) {
|
||||
if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
|
||||
if (inputs[k].checked == true) {
|
||||
inputs[k].setAttribute("checked", "checked");
|
||||
} else {
|
||||
inputs[k].removeAttribute("checked");
|
||||
}
|
||||
} else if (inputs[k].type == "text") {
|
||||
inputs[k].setAttribute("value", inputs[k].value);
|
||||
} else {
|
||||
inputs[k].setAttribute("value", inputs[k].value);
|
||||
}
|
||||
}
|
||||
|
||||
for (let k2 = 0; k2 < textareas.length; k2++) {
|
||||
if (textareas[k2].type == "textarea") {
|
||||
textareas[k2].innerHTML = textareas[k2].value;
|
||||
}
|
||||
}
|
||||
|
||||
for (let k3 = 0; k3 < selects.length; k3++) {
|
||||
if (selects[k3].type == "select-one") {
|
||||
const child = selects[k3].children;
|
||||
for (const i in child) {
|
||||
if (child[i].tagName == "OPTION") {
|
||||
// @ts-ignore
|
||||
if (child[i].selected == true) {
|
||||
child[i].setAttribute("selected", "selected");
|
||||
} else {
|
||||
child[i].removeAttribute("selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.dom.outerHTML;
|
||||
},
|
||||
/**
|
||||
create iframe
|
||||
*/
|
||||
writeIframe: function (content) {
|
||||
let w: Document | Window;
|
||||
let doc: Document;
|
||||
const iframe: HTMLIFrameElement = document.createElement("iframe");
|
||||
const f: HTMLIFrameElement = document.body.appendChild(iframe);
|
||||
iframe.id = "myIframe";
|
||||
iframe.setAttribute(
|
||||
"style",
|
||||
"position:absolute;width:0;height:0;top:-10px;left:-10px;"
|
||||
);
|
||||
// eslint-disable-next-line prefer-const
|
||||
w = f.contentWindow || f.contentDocument;
|
||||
// eslint-disable-next-line prefer-const
|
||||
doc = f.contentDocument || f.contentWindow.document;
|
||||
doc.open();
|
||||
doc.write(content);
|
||||
doc.close();
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const _this = this;
|
||||
iframe.onload = function (): void {
|
||||
// Before popping, callback
|
||||
if (_this.conf.printBeforeFn) {
|
||||
_this.conf.printBeforeFn({ doc });
|
||||
}
|
||||
|
||||
_this.drawEchartImg(doc).then(() => {
|
||||
_this.toPrint(w);
|
||||
setTimeout(function () {
|
||||
document.body.removeChild(iframe);
|
||||
// After popup, callback
|
||||
if (_this.conf.printDoneCallBack) {
|
||||
_this.conf.printDoneCallBack();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
};
|
||||
},
|
||||
/**
|
||||
* echarts printing
|
||||
* @param {Object} doc iframe window
|
||||
*/
|
||||
drawEchartImg(doc): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) {
|
||||
this.conf.echartDomArr.forEach(e => {
|
||||
const dom = doc.querySelector("#" + e.$el.id);
|
||||
const img = new Image();
|
||||
const w = dom.offsetWidth + "px";
|
||||
const H = dom.offsetHeight + "px";
|
||||
|
||||
img.style.width = w;
|
||||
img.style.height = H;
|
||||
img.src = e.imgSrc;
|
||||
dom.innerHTML = "";
|
||||
dom.appendChild(img);
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
/**
|
||||
Print
|
||||
*/
|
||||
toPrint: function (frameWindow): void {
|
||||
try {
|
||||
setTimeout(function () {
|
||||
frameWindow.focus();
|
||||
try {
|
||||
if (!frameWindow.document.execCommand("print", false, null)) {
|
||||
frameWindow.print();
|
||||
}
|
||||
} catch (e) {
|
||||
frameWindow.print();
|
||||
}
|
||||
frameWindow.close();
|
||||
}, 10);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
isDOM:
|
||||
typeof HTMLElement === "object"
|
||||
? function (obj) {
|
||||
return obj instanceof HTMLElement;
|
||||
}
|
||||
: function (obj) {
|
||||
return (
|
||||
obj &&
|
||||
typeof obj === "object" &&
|
||||
obj.nodeType === 1 &&
|
||||
typeof obj.nodeName === "string"
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Set the height of the specified dom element by getting the existing height of the dom element and setting
|
||||
* @param {Array} arr
|
||||
*/
|
||||
setDomHeight(arr) {
|
||||
if (arr && arr.length) {
|
||||
arr.forEach(name => {
|
||||
const domArr = document.querySelectorAll(name);
|
||||
domArr.forEach(dom => {
|
||||
dom.style.height = dom.offsetHeight + "px";
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Print;
|
35
src/utils/resize/index.ts
Normal file
35
src/utils/resize/index.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
|
||||
const isServer = typeof window === "undefined";
|
||||
|
||||
const resizeHandler = (entries: any[]): void => {
|
||||
for (const entry of entries) {
|
||||
const listeners = entry.target.__resizeListeners__ || [];
|
||||
if (listeners.length) {
|
||||
listeners.forEach((fn: () => any) => {
|
||||
fn();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const addResizeListener = (element: any, fn: () => any): any => {
|
||||
if (isServer) return;
|
||||
if (!element.__resizeListeners__) {
|
||||
element.__resizeListeners__ = [];
|
||||
element.__ro__ = new ResizeObserver(resizeHandler);
|
||||
element.__ro__.observe(element);
|
||||
}
|
||||
element.__resizeListeners__.push(fn);
|
||||
};
|
||||
|
||||
export const removeResizeListener = (element: any, fn: () => any): any => {
|
||||
if (!element || !element.__resizeListeners__) return;
|
||||
element.__resizeListeners__.splice(
|
||||
element.__resizeListeners__.indexOf(fn),
|
||||
1
|
||||
);
|
||||
if (!element.__resizeListeners__.length) {
|
||||
element.__ro__.disconnect();
|
||||
}
|
||||
};
|
116
src/utils/watermark.ts
Normal file
116
src/utils/watermark.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import {
|
||||
ref,
|
||||
Ref,
|
||||
unref,
|
||||
shallowRef,
|
||||
onBeforeUnmount,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { isDef } from "/@/utils/is";
|
||||
import { useRafThrottle } from "/@/utils/operate";
|
||||
import { addResizeListener, removeResizeListener } from "/@/utils/resize";
|
||||
|
||||
const domSymbol = Symbol("watermark-dom");
|
||||
|
||||
type attr = {
|
||||
font?: string;
|
||||
fillStyle?: string;
|
||||
};
|
||||
|
||||
export function useWatermark(
|
||||
appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>
|
||||
) {
|
||||
const func = useRafThrottle(function () {
|
||||
const el = unref(appendEl);
|
||||
if (!el) return;
|
||||
const { clientHeight: height, clientWidth: width } = el;
|
||||
updateWatermark({ height, width });
|
||||
});
|
||||
const id = domSymbol.toString();
|
||||
const watermarkEl = shallowRef<HTMLElement>();
|
||||
|
||||
const clear = () => {
|
||||
const domId = unref(watermarkEl);
|
||||
watermarkEl.value = undefined;
|
||||
const el = unref(appendEl);
|
||||
if (!el) return;
|
||||
domId && el.removeChild(domId);
|
||||
removeResizeListener(el, func);
|
||||
};
|
||||
|
||||
function createBase64(str: string, attr?: attr) {
|
||||
const can = document.createElement("canvas");
|
||||
const width = 300;
|
||||
const height = 240;
|
||||
Object.assign(can, { width, height });
|
||||
|
||||
const cans = can.getContext("2d");
|
||||
if (cans) {
|
||||
cans.rotate((-20 * Math.PI) / 120);
|
||||
cans.font = attr?.font ?? "15px Reggae One";
|
||||
cans.fillStyle = attr?.fillStyle ?? "rgba(0, 0, 0, 0.15)";
|
||||
cans.textAlign = "left";
|
||||
cans.textBaseline = "middle";
|
||||
cans.fillText(str, width / 20, height);
|
||||
}
|
||||
return can.toDataURL("image/png");
|
||||
}
|
||||
|
||||
function updateWatermark(
|
||||
options: {
|
||||
width?: number;
|
||||
height?: number;
|
||||
str?: string;
|
||||
attr?: attr;
|
||||
} = {}
|
||||
) {
|
||||
const el = unref(watermarkEl);
|
||||
if (!el) return;
|
||||
if (isDef(options.width)) {
|
||||
el.style.width = `${options.width}px`;
|
||||
}
|
||||
if (isDef(options.height)) {
|
||||
el.style.height = `${options.height}px`;
|
||||
}
|
||||
if (isDef(options.str)) {
|
||||
el.style.background = `url(${createBase64(
|
||||
options.str,
|
||||
options.attr
|
||||
)}) left top repeat`;
|
||||
}
|
||||
}
|
||||
|
||||
const createWatermark = (str: string, attr?: attr) => {
|
||||
if (unref(watermarkEl)) {
|
||||
updateWatermark({ str, attr });
|
||||
return id;
|
||||
}
|
||||
const div = document.createElement("div");
|
||||
watermarkEl.value = div;
|
||||
div.id = id;
|
||||
div.style.pointerEvents = "none";
|
||||
div.style.top = "0px";
|
||||
div.style.left = "0px";
|
||||
div.style.position = "absolute";
|
||||
div.style.zIndex = "100000";
|
||||
const el = unref(appendEl);
|
||||
if (!el) return id;
|
||||
const { clientHeight: height, clientWidth: width } = el;
|
||||
updateWatermark({ str, width, height, attr });
|
||||
el.appendChild(div);
|
||||
return id;
|
||||
};
|
||||
|
||||
function setWatermark(str: string, attr?: attr) {
|
||||
createWatermark(str, attr);
|
||||
addResizeListener(document.documentElement, func);
|
||||
const instance = getCurrentInstance();
|
||||
if (instance) {
|
||||
onBeforeUnmount(() => {
|
||||
clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { setWatermark, clear };
|
||||
}
|
Reference in New Issue
Block a user