---初始化后台管理web页面项目

This commit is contained in:
2025-08-20 14:39:30 +08:00
parent ad49711a7e
commit 87545a8baf
2057 changed files with 282864 additions and 213 deletions

View File

@ -0,0 +1,45 @@
import { httpRequest } from '/@/api/sys/api';
import { getToken } from '/@/utils/auth';
export default function () {
async function changeApiOptions(val) {
if (val.path) {
try {
const headers = { Authorization: `Bearer ${getToken()}` };
if (val.requestHeaderConfigs.length > 0) {
val.requestHeaderConfigs.forEach((element) => {
if (element.name) headers[element.name] = element.value;
});
}
let path = val.path;
if (val.requestParamsConfigs.length > 0) {
path += '?';
val.requestParamsConfigs.forEach((element) => {
if (element.name) path += `${element.name}=${element.value}&`;
});
}
const apiData = {};
if (val.requestBodyConfigs.length > 0) {
val.requestBodyConfigs.forEach((element) => {
if (element.name) apiData[element.name] = element.value;
});
}
const res = await httpRequest(
{
requestUrl: path,
requestType: val.method,
},
{
headers,
data: apiData,
},
);
return res;
} catch (error) {}
}
}
return {
changeApiOptions,
};
}

View File

@ -0,0 +1,89 @@
import { ref, computed, ComputedRef, unref } from 'vue';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { screenMap, sizeEnum, screenEnum } from '/@/enums/breakpointEnum';
let globalScreenRef: ComputedRef<sizeEnum | undefined>;
let globalWidthRef: ComputedRef<number>;
let globalRealWidthRef: ComputedRef<number>;
export interface CreateCallbackParams {
screen: ComputedRef<sizeEnum | undefined>;
width: ComputedRef<number>;
realWidth: ComputedRef<number>;
screenEnum: typeof screenEnum;
screenMap: Map<sizeEnum, number>;
sizeEnum: typeof sizeEnum;
}
export function useBreakpoint() {
return {
screenRef: computed(() => unref(globalScreenRef)),
widthRef: globalWidthRef,
screenEnum,
realWidthRef: globalRealWidthRef,
};
}
// Just call it once
export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void) {
const screenRef = ref<sizeEnum>(sizeEnum.XL);
const realWidthRef = ref(window.innerWidth);
function getWindowWidth() {
const width = document.body.clientWidth;
const xs = screenMap.get(sizeEnum.XS)!;
const sm = screenMap.get(sizeEnum.SM)!;
const md = screenMap.get(sizeEnum.MD)!;
const lg = screenMap.get(sizeEnum.LG)!;
const xl = screenMap.get(sizeEnum.XL)!;
if (width < xs) {
screenRef.value = sizeEnum.XS;
} else if (width < sm) {
screenRef.value = sizeEnum.SM;
} else if (width < md) {
screenRef.value = sizeEnum.MD;
} else if (width < lg) {
screenRef.value = sizeEnum.LG;
} else if (width < xl) {
screenRef.value = sizeEnum.XL;
} else {
screenRef.value = sizeEnum.XXL;
}
realWidthRef.value = width;
}
useEventListener({
el: window,
name: 'resize',
listener: () => {
getWindowWidth();
resizeFn();
},
// wait: 100,
});
getWindowWidth();
globalScreenRef = computed(() => unref(screenRef));
globalWidthRef = computed((): number => screenMap.get(unref(screenRef)!)!);
globalRealWidthRef = computed((): number => unref(realWidthRef));
function resizeFn() {
fn?.({
screen: globalScreenRef,
width: globalWidthRef,
realWidth: globalRealWidthRef,
screenEnum,
screenMap,
sizeEnum,
});
}
resizeFn();
return {
screenRef: globalScreenRef,
screenEnum,
widthRef: globalWidthRef,
realWidthRef: globalRealWidthRef,
};
}

View File

@ -0,0 +1,11 @@
import mitt from '../../utils/mitt';
const bus = new mitt();
export default function () {
return {
bus,
FLOW_PROCESSED: 'flow_processed',
FORM_LIST_MODIFIED: 'form_list_modified',
CREATE_FLOW: 'create_flow'
};
}

View File

@ -0,0 +1,58 @@
import type { Ref } from 'vue';
import { ref, watch, unref } from 'vue';
import { useThrottleFn, useDebounceFn } from '@vueuse/core';
export type RemoveEventFn = () => void;
export interface UseEventParams {
el?: Element | Ref<Element | undefined> | Window | any;
name: string;
listener: EventListener;
options?: boolean | AddEventListenerOptions;
autoRemove?: boolean;
isDebounce?: boolean;
wait?: number;
}
export function useEventListener({
el = window,
name,
listener,
options,
autoRemove = true,
isDebounce = true,
wait = 80,
}: UseEventParams): { removeEvent: RemoveEventFn } {
/* eslint-disable-next-line */
let remove: RemoveEventFn = () => {};
const isAddRef = ref(false);
if (el) {
const element = ref(el as Element) as Ref<Element>;
const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait);
const realHandler = wait ? handler : listener;
const removeEventListener = (e: Element) => {
isAddRef.value = true;
e.removeEventListener(name, realHandler, options);
};
const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options);
const removeWatch = watch(
element,
(v, _ov, cleanUp) => {
if (v) {
!unref(isAddRef) && addEventListener(v);
cleanUp(() => {
autoRemove && removeEventListener(v);
});
}
},
{ immediate: true },
);
remove = () => {
removeEventListener(element.value);
removeWatch();
};
}
return { removeEvent: remove };
}

View File

@ -0,0 +1,48 @@
import { Ref, watchEffect, ref } from 'vue';
interface IntersectionObserverProps {
target: Ref<Element | null | undefined>;
root?: Ref<any>;
onIntersect: IntersectionObserverCallback;
rootMargin?: string;
threshold?: number;
}
export function useIntersectionObserver({
target,
root,
onIntersect,
rootMargin = '0px',
threshold = 0.1,
}: IntersectionObserverProps) {
let cleanup = () => {};
const observer: Ref<Nullable<IntersectionObserver>> = ref(null);
const stopEffect = watchEffect(() => {
cleanup();
observer.value = new IntersectionObserver(onIntersect, {
root: root ? root.value : null,
rootMargin,
threshold,
});
const current = target.value;
current && observer.value.observe(current);
cleanup = () => {
if (observer.value) {
observer.value.disconnect();
target.value && observer.value.unobserve(target.value);
}
};
});
return {
observer,
stop: () => {
cleanup();
stopEffect();
},
};
}

View File

@ -0,0 +1,65 @@
import type { Ref } from 'vue';
import { ref, onMounted, watch, onUnmounted } from 'vue';
import { isWindow, isObject } from '/@/utils/is';
import { useThrottleFn } from '@vueuse/core';
export function useScroll(
refEl: Ref<Element | Window | null>,
options?: {
wait?: number;
leading?: boolean;
trailing?: boolean;
},
) {
const refX = ref(0);
const refY = ref(0);
let handler = () => {
if (isWindow(refEl.value)) {
refX.value = refEl.value.scrollX;
refY.value = refEl.value.scrollY;
} else if (refEl.value) {
refX.value = (refEl.value as Element).scrollLeft;
refY.value = (refEl.value as Element).scrollTop;
}
};
if (isObject(options)) {
let wait = 0;
if (options.wait && options.wait > 0) {
wait = options.wait;
Reflect.deleteProperty(options, 'wait');
}
handler = useThrottleFn(handler, wait);
}
let stopWatch: () => void;
onMounted(() => {
stopWatch = watch(
refEl,
(el, prevEl, onCleanup) => {
if (el) {
el.addEventListener('scroll', handler);
} else if (prevEl) {
prevEl.removeEventListener('scroll', handler);
}
onCleanup(() => {
refX.value = refY.value = 0;
el && el.removeEventListener('scroll', handler);
});
},
{ immediate: true },
);
});
onUnmounted(() => {
refEl.value && refEl.value.removeEventListener('scroll', handler);
});
function stop() {
stopWatch && stopWatch();
}
return { refX, refY, stop };
}

View File

@ -0,0 +1,59 @@
import { isFunction, isUnDef } from '/@/utils/is';
import { ref, unref } from 'vue';
export interface ScrollToParams {
el: any;
to: number;
duration?: number;
callback?: () => any;
}
const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
t /= d / 2;
if (t < 1) {
return (c / 2) * t * t + b;
}
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
};
const move = (el: HTMLElement, amount: number) => {
el.scrollTop = amount;
};
const position = (el: HTMLElement) => {
return el.scrollTop;
};
export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams) {
const isActiveRef = ref(false);
const start = position(el);
const change = to - start;
const increment = 20;
let currentTime = 0;
duration = isUnDef(duration) ? 500 : duration;
const animateScroll = function () {
if (!unref(isActiveRef)) {
return;
}
currentTime += increment;
const val = easeInOutQuad(currentTime, start, change, duration);
move(el, val);
if (currentTime < duration && unref(isActiveRef)) {
requestAnimationFrame(animateScroll);
} else {
if (callback && isFunction(callback)) {
callback();
}
}
};
const run = () => {
isActiveRef.value = true;
animateScroll();
};
const stop = () => {
isActiveRef.value = false;
};
return { start: run, stop };
}

View File

@ -0,0 +1,35 @@
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
interface WindowSizeOptions {
once?: boolean;
immediate?: boolean;
listenerOptions?: AddEventListenerOptions | boolean;
}
export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOptions) {
let handler = () => {
fn();
};
const handleSize = useDebounceFn(handler, wait);
handler = handleSize;
const start = () => {
if (options && options.immediate) {
handler();
}
window.addEventListener('resize', handler);
};
const stop = () => {
window.removeEventListener('resize', handler);
};
tryOnMounted(() => {
start();
});
tryOnUnmounted(() => {
stop();
});
return [start, stop];
}