From 47a43b98806bed953788cc62d48a2512f85ba3dc Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Thu, 27 Aug 2026 00:53:40 -0600 Subject: [PATCH] =?UTF-8?q?fix(=E6=8F=90=E4=BA=A4=E5=88=97=E8=A1=A8):=20?= =?UTF-8?q?=E8=BD=AC=E5=9C=88=E5=9C=88=E5=BB=B6=E8=BF=9F=20300ms=20?= =?UTF-8?q?=E5=87=BA=E7=8E=B0=EF=BC=8C=E5=BF=AB=E8=AF=B7=E6=B1=82=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E9=97=AA=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 翻页、切筛选大多一百毫秒内就回来了,转圈圈闪一下再切数据比直接切更晃眼。 给 loading 加一层延迟:只有真的慢到 300ms 以上才显示。 是**单向**延迟 —— 只推迟「显示」,请求一结束立刻收掉,不留尾巴(用 refDebounced 之类的双向去抖会在数据到了之后还多转 300ms)。 没有用 n-spin 的 delay:n-data-table 压根不走 n-spin,它渲染的是内部的 _internal/loading,直接由 loading 控制、没有 delay 参数。要用内置的就得把表格 包进 再去掉 :loading —— 那会换掉加载样式,还会丢掉 loading 时锁住排序/分页交互(DataTable 里那个 `disabled: this.loading`)。 这几行就是 n-spin 内部同样的写法,理由写在注释里了。 验证:headless chromium 走 CDP,只给 /api/submissions 加延迟(给全站加延迟的话 dev 模式几百个模块请求全被拖慢,页面根本起不来,第一次就是这么测出假结果的), 每 120ms 采一次 DOM: API 不加延迟 转圈圈全程没出现,表格直接 0 行 → 5 行 API +800ms 表格 291ms 挂上 → 654ms 转圈圈出现(挂载后约 300ms) → 1138ms 数据到位 → 1381ms 收掉 Co-Authored-By: Claude Opus 5 --- apps/web/src/oj/submission/list.vue | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/web/src/oj/submission/list.vue b/apps/web/src/oj/submission/list.vue index 99dc856..d475c76 100644 --- a/apps/web/src/oj/submission/list.vue +++ b/apps/web/src/oj/submission/list.vue @@ -64,6 +64,31 @@ const todayCount = ref(0) // 没有它的话,等接口这段时间表格就是一片空白,连转圈都没有 const loading = ref(false) +/** + * 转圈圈延迟出现。翻页、切筛选大多在一百毫秒内就回来了,直接切数据比「闪一下 + * 转圈再切」看着稳;只有真的慢到 300ms 以上才值得给个反馈。 + * + * 注意是**单向**延迟:只推迟「显示」,一旦请求结束立刻收掉,不留尾巴。 + * + * 为什么不用 n-spin 的 delay:n-data-table 压根不走 n-spin,它渲染的是内部的 + * _internal/loading,直接由 loading 控制、没有 delay 参数。要用内置的就得把表格 + * 包进 再去掉 :loading —— 那会换掉加载样式,还会丢掉 + * loading 时锁住排序/分页交互(DataTable 里那个 `disabled: this.loading`)。 + * 下面这几行就是 n-spin 内部同样的写法(watchEffect + setTimeout + 清理)。 + */ +const LOADING_DELAY = 300 +const showLoading = ref(false) +let loadingTimer: ReturnType | undefined +watch(loading, (value) => { + clearTimeout(loadingTimer) + if (!value) { + showLoading.value = false + return + } + loadingTimer = setTimeout(() => (showLoading.value = true), LOADING_DELAY) +}) +onUnmounted(() => clearTimeout(loadingTimer)) + // 使用分页 composable const { query, clearQuery } = usePagination({ username: useRouteQuery("username", "").value, @@ -506,14 +531,14 @@ const flowchartColumns = computed(() => { :bordered="false" :columns="flowchartColumns" :data="flowcharts" - :loading="loading" + :loading="showLoading" />