xiaoyi
2026-10-30 9de39f19ba57206c2283c7680e0e5c36f59647a8
fix(dashboard): 修复首页 pageSize 超限报错,优化 BI 大屏自适应

## 1. 修复首页报错「每页条数最大值为 200」
出勤指标/库存模块分页查询用了 pageSize: 500,超过后端 PAGE_SIZE_MAX=200,
导致进入首页直接报错。改为 200(当前数据量 83 条,足够覆盖)。

## 2. BI 大屏自适应优化

原问题:
- chart-row 用 minmax(380px, 1fr),360px 手机屏会横向溢出
- kpi-row 用 minmax(190px, 1fr),窄屏同样溢出
- 只有 768px 一个断点,平板/笔记本/4K 大屏都没有适配
- 4K 屏下单卡被拉得过宽,图表变形

改动:
- 网格列宽改用 minmax(min(100%, Npx), 1fr),任何宽度都不会溢出
- 补齐 6 档断点:
· ≥1921px(4K):加大间距与字号,图表列宽 460px
· 1600-1920px(宽屏):加宽内边距
· ≤1280px(笔记本):隐藏状态标签与副标题,给标题区让位
· ≤1024px(平板竖):头部换行,图表列宽降到 300px
· ≤768px(手机):KPI 两列、图表单列、图标与字号缩小、隐藏实时徽标
· ≤400px(小屏手机):KPI 单列

图表缩放依赖 vben EchartsUI 自带的 ResizeObserver,容器变化时自动 resize。

## 验证
- 首页 summary 接口 code=0 正常
- 考勤汇总 pageSize=200 返回 83 条正常
- BI 大屏 5 个,人资办公大屏菜单已放开
- 构建通过,已部署生产,前端 200
已修改2个文件
57 ■■■■■ 文件已修改
src/views/bi/dashboard/index.vue 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dashboard/analytics/modules/hr-stock-cards.vue 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bi/dashboard/index.vue
@@ -479,7 +479,7 @@
.kpi-row {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr));
  gap: 12px; margin-bottom: 16px;
}
@@ -548,7 +548,7 @@
.chart-row {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
@@ -633,13 +633,54 @@
:deep(.ant-empty-description) { color: var(--text-muted); }
/* ======== 响应式 ======== */
/* 大屏 / 4K:放大间距与字号,图表列宽加大 */
@media (min-width: 1921px) {
  .bi-dashboard { padding: 24px 32px; }
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
  .chart-row { grid-template-columns: repeat(auto-fit, minmax(460px, 1fr)); }
  .kpi-value { font-size: 28px; }
}
/* 宽屏 */
@media (min-width: 1600px) and (max-width: 1920px) {
  .bi-dashboard { padding: 20px 26px; }
}
/* 笔记本 / 平板横屏:头部空间紧张时压缩 */
@media (max-width: 1280px) {
  .dash-status-tags { display: none; }
  .dash-title-group p { display: none; }
}
/* 平板竖屏 */
@media (max-width: 1024px) {
  .bi-dashboard { padding: 14px; }
  .dash-header { flex-wrap: wrap; gap: 10px; }
  .dash-header-divider { display: none; }
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); }
  .chart-row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
}
/* 手机 */
@media (max-width: 768px) {
  .bi-dashboard { padding: 10px; }
  .dash-header { flex-wrap: wrap; }
  .dash-header { flex-wrap: wrap; gap: 8px; }
  .dash-header-divider { display: none; }
  .kpi-row { grid-template-columns: 1fr 1fr; }
  .chart-row { grid-template-columns: 1fr; }
  .dash-header-right { width: 100%; justify-content: space-between; }
  .dash-live-badge { display: none; }
  .kpi-row { grid-template-columns: 1fr 1fr; gap: 8px; }
  .kpi-card { padding: 10px 12px; gap: 8px; }
  .kpi-icon { width: 32px; height: 32px; font-size: 15px; }
  .kpi-value { font-size: 18px; }
  .kpi-label { font-size: 10px; }
  .chart-row { grid-template-columns: 1fr; gap: 10px; }
  .chart-row > div { grid-column: 1 / -1 !important; }
  .kpi-value { font-size: 20px; }
}
/* 超窄屏(小屏手机) */
@media (max-width: 400px) {
  .kpi-row { grid-template-columns: 1fr; }
}
</style>
src/views/dashboard/analytics/modules/hr-stock-cards.vue
@@ -41,7 +41,7 @@
  try {
    const res = await getAttendanceSummaryPage({
      pageNo: 1,
      pageSize: 500,
      pageSize: 200,
      yearMonth: currentYearMonth(),
    } as any);
    const list = res?.list ?? [];
@@ -75,7 +75,7 @@
  if (!canViewStock.value) return;
  stockLoading.value = true;
  try {
    const res = await getMaterialStockPage({ pageNo: 1, pageSize: 500 } as any);
    const res = await getMaterialStockPage({ pageNo: 1, pageSize: 200 } as any);
    const list = res?.list ?? [];
    stockKinds.value = res?.total ?? list.length;
    stockAvailable.value = Number(list.reduce((s: number, r: any) => s + Number(r.availableQuantity ?? 0), 0).toFixed(0));