fix(admin): 通知分页、登录过期提示、附件打开反馈与导出统一 loading

- 通知中心改为游标分页 + 加载更多,历史通知不再被 50 条上限截断;
  加载失败显示错误态与重试
- AI 流式请求 401 被登出时,登录页提示"登录已过期",不再无声踢出
- AI 附件/引用来源打开失败时给出明确错误提示,不再"点了没反应"
- 新增 useDownload hook:统一导出/下载的防重复、loading 与成功/失败反馈;
  接入学生/账单/房间/入住/费用五个页面的模板下载与导出按钮
- 学生页移除不检查响应状态的私有下载实现,统一走 downloadBlob
This commit is contained in:
2026-08-07 17:33:58 +08:00
parent 67435e46ca
commit 00e2bc5acf
14 changed files with 320 additions and 153 deletions

View File

@@ -25,6 +25,7 @@ import { useOccupancyMutations } from './useOccupancyMutations';
import { QueryErrorState } from '../../components/QueryState';
import { NextStepHint } from '../../components/NextStepHint';
import { useVisibleRefetch } from '../../hooks/usePageVisible';
import { useDownload } from '../../hooks/useDownload';
interface StudentLookupRow {
id: number;
@@ -452,6 +453,9 @@ const OccupanciesPage: React.FC = () => {
[selectedRowKeys, viewMode],
);
const { downloading: templateDownloading, run: runTemplateDownload } = useDownload();
const { downloading: exportDownloading, run: runExportDownload } = useDownload();
return (
<div>
<Alert
@@ -513,17 +517,21 @@ const OccupanciesPage: React.FC = () => {
depositAmount={depositAmount}
onDepositAmountChange={setDepositAmount}
onDownloadTemplate={() => {
void import('../../utils/download').then(({ downloadBlob }) =>
downloadBlob('/occupancies/template', '入住名单导入模板.xlsx').catch(() => message.error('下载失败')),
);
}}
onExport={() => {
void import('../../utils/download').then(({ downloadBlob }) => {
const params = viewMode === 'active' ? '?active=true' : '';
const filename = viewMode === 'active' ? '在住记录.xlsx' : '全部入住记录.xlsx';
downloadBlob('/occupancies/export' + params, filename).catch(() => message.error('导出失败'));
void runTemplateDownload('/occupancies/template', '入住名单导入模板.xlsx', {
successMsg: '模板已下载',
errorMsg: '下载失败',
});
}}
templateLoading={templateDownloading}
onExport={() => {
const params = viewMode === 'active' ? '?active=true' : '';
const filename = viewMode === 'active' ? '在住记录.xlsx' : '全部入住记录.xlsx';
void runExportDownload('/occupancies/export' + params, filename, {
successMsg: '入住记录已导出',
errorMsg: '导出失败',
});
}}
exportLoading={exportDownloading}
/>
{nextStepHint === 'billing' && (
<NextStepHint