feat: 优化路由 搭建赛事管理页面基础 处理部分样式问题 完成赛事列表页面搭建
This commit is contained in:
@@ -7,4 +7,6 @@ export * from './useAuth';
|
||||
export * from './useWebSocket';
|
||||
export * from './useBasicLayout';
|
||||
export * from './useBreadcrumb';
|
||||
export * from './useThrottleFn';
|
||||
export * from './useContainerSize';
|
||||
export * from './useContext';
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { ref, onMounted, onUnmounted, type Ref } from 'vue';
|
||||
|
||||
/**
|
||||
* 监听容器尺寸变化,返回动态 width/height 给 Table 的 scroll 属性使用。
|
||||
*
|
||||
* 基于 ResizeObserver,窗口缩放 / 侧边栏收起展开 / 筛选区折叠 等任何导致
|
||||
* 容器尺寸变化的行为都会自动触发重新计算,无需额外处理。
|
||||
*
|
||||
* 用法:
|
||||
* ```ts
|
||||
* const { containerRef, width, height } = useContainerSize();
|
||||
* // <div ref={containerRef}>
|
||||
* // <Table scroll={{ x: width.value, y: height.value }} />
|
||||
* // </div>
|
||||
* ```
|
||||
*
|
||||
* @param headerOffset 从容器高度中扣除的表头偏移量,默认 45
|
||||
*/
|
||||
export function useContainerSize(options?: { headerOffset?: number }) {
|
||||
const { headerOffset = 45 } = options ?? {};
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null) as Ref<HTMLElement | null>;
|
||||
const width = ref(0);
|
||||
const height = ref(0);
|
||||
|
||||
let observer: ResizeObserver | null = null;
|
||||
|
||||
const updateSize = () => {
|
||||
const el = containerRef.value;
|
||||
if (!el) return;
|
||||
width.value = el.clientWidth;
|
||||
height.value = Math.max(el.clientHeight - headerOffset, 200);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
updateSize();
|
||||
const el = containerRef.value;
|
||||
if (!el) return;
|
||||
|
||||
observer = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const w = entry.contentRect.width;
|
||||
const h = entry.contentRect.height;
|
||||
if (w !== width.value) width.value = w;
|
||||
if (h !== height.value) height.value = Math.max(h - headerOffset, 200);
|
||||
}
|
||||
});
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
onUnmounted(() => observer?.disconnect());
|
||||
|
||||
return { containerRef, width, height };
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// src/hooks/useDebounce.ts
|
||||
import { watch, onUnmounted } from 'vue';
|
||||
import { watch, onUnmounted, Ref } from 'vue';
|
||||
import { useState } from './useState';
|
||||
|
||||
export interface UseDebounceOptions {
|
||||
@@ -8,14 +8,11 @@ export interface UseDebounceOptions {
|
||||
maxWait?: number;
|
||||
}
|
||||
|
||||
export function useDebounce<T>(
|
||||
source: any, // Ref<T>
|
||||
options: number | UseDebounceOptions = {},
|
||||
) {
|
||||
export function useDebounce<T>(source: Ref<T>, options: number | UseDebounceOptions = {}) {
|
||||
const config = typeof options === 'number' ? { delay: options } : options;
|
||||
const { delay = 300, immediate = false, maxWait } = config;
|
||||
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(source.value);
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(source.value as T);
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
let timer: any = null;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**
|
||||
* 节流函数封装
|
||||
* @param fn 需要节流的函数
|
||||
* @param delay 节流间隔时间(ms),默认 500
|
||||
* @returns 返回节流后的函数,连续调用时只会在每个 delay 周期内执行一次
|
||||
*/
|
||||
export function useThrottleFn<T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
delay: number = 500,
|
||||
): T & { cancel: () => void } {
|
||||
const lastTime = ref<number>(0);
|
||||
let timer: any = null;
|
||||
|
||||
const throttled = function (this: any, ...args: any[]) {
|
||||
const now = Date.now();
|
||||
const remaining = delay - (now - lastTime.value);
|
||||
|
||||
if (remaining <= 0) {
|
||||
// 冷却时间已过,立即执行
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
lastTime.value = now;
|
||||
fn.apply(this, args);
|
||||
} else if (!timer) {
|
||||
// 冷却时间未过,延后执行
|
||||
timer = setTimeout(() => {
|
||||
lastTime.value = Date.now();
|
||||
timer = null;
|
||||
fn.apply(this, args);
|
||||
}, remaining);
|
||||
}
|
||||
} as T & { cancel: () => void };
|
||||
|
||||
throttled.cancel = () => {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
};
|
||||
|
||||
return throttled;
|
||||
}
|
||||
Reference in New Issue
Block a user