forked from wangziqi/gongxue-base
1335 lines
41 KiB
Markdown
1335 lines
41 KiB
Markdown
---
|
||
change: admin-responsive-adaptation
|
||
design-doc: docs/superpowers/specs/2026-07-03-admin-responsive-adaptation-design.md
|
||
base-ref: 779cedb8a07bbfe1c50871526f9b99f8bc008acc
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
# 管理后台三端响应式适配 Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 将管理后台从单一 mobile/desktop 二元适配升级为 antd v6 Grid.useBreakpoint() 三端响应式体系(手机 < 576px / 平板 576-991px / 桌面 >= 992px),覆盖 16 个页面的布局、表格、弹窗和工具栏。
|
||
|
||
**Architecture:** 使用 antd v6 内置 `Grid.useBreakpoint()` 替换自写的 resize 监听,通过断点驱动 Sider/Drawer 切换、内容区 padding、卡片网格 Col 响应式 props。所有表格添加 `scroll={{ x }}` 横向滚动,工具栏添加 `flexWrap: 'wrap'` + `gap`,弹窗由全局 CSS @media 约束宽度。
|
||
|
||
**Tech Stack:** React 19, antd v6.3.6, echarts-for-react, react-router-dom v7, dayjs, Vite 8
|
||
|
||
## Global Constraints
|
||
|
||
- 断点体系使用 antd v6 内置断点:手机 `(max-width: 575px)`、平板 `(min-width: 576px) and (max-width: 991px)`、桌面默认
|
||
- CSS 策略:antd Props 优先(Col 响应式断点、Table scroll、ellipsis),@media 为兜底
|
||
- 所有 `<Table>` 组件若无 `scroll={{ x }}` 则添加之,列少(<=6)用 `max-content`,列中(7-10)用 `800`,列多(>10)用 `1000`
|
||
- 弹窗宽度由全局 CSS `max-width: calc(100vw - 24px)` 覆盖,组件级不做重复处理
|
||
- 编译必须通过:`npm run build` 无 TypeScript 错误
|
||
- 命名约定:从 `expenseTypeMap` 等现有映射扩展,不新建无意义的变量名
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 1: 全局 CSS 三断点体系
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/index.css`
|
||
|
||
**Interfaces:**
|
||
- Produces: 三个 `@media` 层级的 CSS 规则,供所有页面共用
|
||
- 断点规范:手机 `(max-width: 575px)`、平板 `(min-width: 576px) and (max-width: 991px)`
|
||
|
||
**Description:** 将当前仅有单断点(max-width: 767px)的 index.css 改为三断点体系,同时添加全局表格容器横向滚动和通用组件响应式样式。
|
||
|
||
- [x] **Step 1: 替换 index.css 中的 @media 规则**
|
||
|
||
将当前文件内容替换为以下完整版本:
|
||
|
||
```css
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family:
|
||
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
}
|
||
|
||
#root {
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* === 通用:表格容器横向滚动 === */
|
||
.ant-table-wrapper {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
/* === 手机 (< 576px) === */
|
||
@media (max-width: 575px) {
|
||
.ant-table {
|
||
font-size: 13px;
|
||
}
|
||
.ant-table-cell {
|
||
padding: 8px 6px !important;
|
||
}
|
||
.ant-descriptions-item-label,
|
||
.ant-descriptions-item-content {
|
||
font-size: 13px;
|
||
}
|
||
.ant-modal {
|
||
max-width: calc(100vw - 24px) !important;
|
||
margin: 12px auto !important;
|
||
}
|
||
.ant-modal .ant-modal-body {
|
||
max-height: 60vh;
|
||
overflow-y: auto;
|
||
}
|
||
h2 {
|
||
font-size: 18px !important;
|
||
}
|
||
.ant-card {
|
||
margin-bottom: 8px;
|
||
}
|
||
.ant-space-item .ant-btn {
|
||
padding: 2px 6px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
/* === 平板 (576-991px) === */
|
||
@media (min-width: 576px) and (max-width: 991px) {
|
||
.ant-modal {
|
||
max-width: calc(100vw - 48px) !important;
|
||
}
|
||
}
|
||
```
|
||
|
||
**Changed from current:**
|
||
- 旧断点 `(max-width: 767px)` 改为 `(max-width: 575px)`
|
||
- 新增 `.ant-table-wrapper { overflow-x: auto }` 通用规则
|
||
- 新增平板断点 `(min-width: 576px) and (max-width: 991px)` 仅做弹窗微调
|
||
- 桌面(>= 992px)使用浏览器默认样式,无需显式 @media
|
||
|
||
- [x] **Step 2: 验证 CSS 语法**
|
||
|
||
```bash
|
||
# 用 node 检查语法(没有专门的 CSS 语法检查,可跳过)
|
||
echo "CSS rules updated"
|
||
```
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/index.css
|
||
git commit -m "feat: 建立三断点 CSS 体系,替换单断点移动端样式"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 2: MainLayout 三端布局重构
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/layouts/MainLayout.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: antd `Grid.useBreakpoint()` (from `antd`)
|
||
- Produces: `isMobile` / `isTablet` / `isDesktop` 三端布尔值,Sider/Drawer 切换逻辑
|
||
- Removes: `useState(window.innerWidth < 768)` + `useEffect` resize 事件监听
|
||
|
||
**Description:** 将 MainLayout 从自建 resize 监听改为 antd v6 的 Grid.useBreakpoint() hook,根据三端断点控制侧栏(桌面 Sider / 手机 Drawer / 平板 Sider 折叠)、Header 用户区域文字显示、Content padding。
|
||
|
||
- [x] **Step 1: 替换 import 和状态声明**
|
||
|
||
找到文件中的 import 区域(第 3 行附近),在 antd 的 import 中添加 `Grid`:
|
||
|
||
```typescript
|
||
import { Layout, Menu, Button, Avatar, Dropdown, Drawer, Grid } from 'antd';
|
||
```
|
||
|
||
然后替换第 86-98 行的状态和 useEffect:
|
||
|
||
```typescript
|
||
const MainLayout: React.FC = () => {
|
||
const [collapsed, setCollapsed] = useState(false);
|
||
const screens = Grid.useBreakpoint();
|
||
const isMobile = !screens.sm; // < 576px (仅 xs)
|
||
const isTablet = (screens.sm || screens.md) && !screens.lg; // 576-991px
|
||
const isDesktop = !!screens.lg; // >= 992px
|
||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||
const navigate = useNavigate();
|
||
const location = useLocation();
|
||
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
||
const { hasPermission } = usePermission();
|
||
```
|
||
|
||
移除原来的 `useEffect` + `resize` 事件监听(第 94-98 行)和 `useState(window.innerWidth < 768)`(第 87 行)。
|
||
|
||
- [x] **Step 2: 更新 Sider/平板/Drawer 渲染逻辑**
|
||
|
||
替换第 150-187 行的侧栏区域:
|
||
|
||
```typescript
|
||
return (
|
||
<Layout style={{ minHeight: '100vh' }}>
|
||
{/* 桌面 + 平板:Sider;手机:Drawer */}
|
||
{!isMobile && (
|
||
<Sider
|
||
trigger={null}
|
||
collapsible
|
||
collapsed={isTablet ? true : collapsed}
|
||
theme="light"
|
||
style={{ background: '#fff', borderRight: '1px solid #e5e5e7' }}
|
||
>
|
||
<div
|
||
style={{
|
||
height: 64,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
color: '#1d1d1f',
|
||
fontSize: (isTablet || collapsed) ? 16 : 17,
|
||
fontWeight: 600,
|
||
borderBottom: '1px solid #e5e5e7',
|
||
}}
|
||
>
|
||
{(isTablet || collapsed) ? '恭' : '恭学教育基地'}
|
||
</div>
|
||
{menuContent}
|
||
</Sider>
|
||
)}
|
||
{isMobile && (
|
||
<Drawer
|
||
placement="left"
|
||
open={drawerOpen}
|
||
onClose={() => setDrawerOpen(false)}
|
||
width={240}
|
||
styles={{ body: { padding: 0 } }}
|
||
title="恭学教育基地"
|
||
>
|
||
{menuContent}
|
||
</Drawer>
|
||
)}
|
||
```
|
||
|
||
关键变化:平板 (`isTablet`) 时 Sider 强制折叠 (`collapsed={isTablet ? true : collapsed}`)。
|
||
|
||
- [x] **Step 3: 更新 Collapse 按钮逻辑**
|
||
|
||
替换第 200-212 行的 Button onClick:
|
||
|
||
```typescript
|
||
<Button
|
||
type="text"
|
||
icon={
|
||
isMobile ? (
|
||
<MenuUnfoldOutlined />
|
||
) : (isTablet || collapsed) ? (
|
||
<MenuUnfoldOutlined />
|
||
) : (
|
||
<MenuFoldOutlined />
|
||
)
|
||
}
|
||
onClick={() => {
|
||
if (isMobile) {
|
||
setDrawerOpen(true);
|
||
} else if (isTablet) {
|
||
setDrawerOpen(true);
|
||
} else {
|
||
setCollapsed(!collapsed);
|
||
}
|
||
}}
|
||
/>
|
||
```
|
||
|
||
平板下点击折叠按钮打开 Drawer(因为 Sider 已折叠到图标态,用户需要展开菜单)。
|
||
|
||
- [x] **Step 4: 隐藏 Header 用户区域文字(手机/平板)**
|
||
|
||
替换第 225-229 行的用户信息区域:
|
||
|
||
```typescript
|
||
<div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 8 }}>
|
||
<Avatar icon={<UserOutlined />} />
|
||
{isDesktop && <span>{user.name || user.username || '用户'}</span>}
|
||
</div>
|
||
```
|
||
|
||
手机和平板 (`!isDesktop`) 下仅显示 Avatar,隐藏用户名文字以节省空间。
|
||
|
||
- [x] **Step 5: 更新 Content padding**
|
||
|
||
替换第 231-241 行的 Content 组件:
|
||
|
||
```typescript
|
||
<Content
|
||
style={{
|
||
margin: isMobile ? 12 : isTablet ? 16 : 24,
|
||
padding: isMobile ? 12 : isTablet ? 16 : 24,
|
||
background: '#fff',
|
||
borderRadius: 12,
|
||
overflow: 'auto',
|
||
}}
|
||
>
|
||
<Outlet />
|
||
</Content>
|
||
```
|
||
|
||
- [x] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/layouts/MainLayout.tsx
|
||
git commit -m "feat: MainLayout 三端布局重构,使用 antd Grid.useBreakpoint()"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 3: Dashboard 响应式网格和图表
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Dashboard/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: antd `Grid` (for `useBreakpoint`)
|
||
- Produces: 响应式统计卡片 Col 断点、图表高度自适应、工具栏堆叠
|
||
|
||
**Description:** 将统计卡片的 `span={6}` 改为响应式断点、图表卡片 `span={12}` 改为 `xs={24} sm={12}`、图表高度按设备自适应、顶部标题和 DatePicker 在小屏堆叠。
|
||
|
||
- [x] **Step 1: 添加 Grid import**
|
||
|
||
在第 2 行,antd import 中添加 `Grid`:
|
||
|
||
```typescript
|
||
import { Row, Col, Card, Statistic, DatePicker, Spin, Grid } from 'antd';
|
||
```
|
||
|
||
在组件内部顶部添加断点检测(`const [stats, setStats]...` 之前):
|
||
|
||
```typescript
|
||
const screens = Grid.useBreakpoint();
|
||
const isMobile = !screens.sm;
|
||
const isDesktop = !!screens.lg;
|
||
```
|
||
|
||
- [x] **Step 2: 统计卡片 Col 改为响应式断点**
|
||
|
||
替换第 179-214 行的统计卡片 Row:
|
||
|
||
```typescript
|
||
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
|
||
<Col xs={12} sm={12} md={6}>
|
||
<Card>
|
||
<Statistic title="宿舍总数" value={stats?.totalRooms || 0} prefix={<HomeOutlined />} />
|
||
</Card>
|
||
</Col>
|
||
<Col xs={12} sm={12} md={6}>
|
||
<Card>
|
||
<Statistic
|
||
title="在读学生"
|
||
value={stats?.totalStudents || 0}
|
||
prefix={<TeamOutlined />}
|
||
/>
|
||
</Card>
|
||
</Col>
|
||
<Col xs={12} sm={12} md={6}>
|
||
<Card>
|
||
<Statistic
|
||
title="当前在住"
|
||
value={stats?.occupiedBeds || 0}
|
||
suffix={`/ ${stats?.totalCapacity || 0}`}
|
||
prefix={<CheckCircleOutlined />}
|
||
/>
|
||
</Card>
|
||
</Col>
|
||
<Col xs={12} sm={12} md={6}>
|
||
<Card>
|
||
<Statistic
|
||
title="入住率"
|
||
value={stats?.occupancyRate || 0}
|
||
suffix="%"
|
||
prefix={<DollarOutlined />}
|
||
/>
|
||
</Card>
|
||
</Col>
|
||
</Row>
|
||
```
|
||
|
||
变化:`span={6}` -> `xs={12} sm={12} md={6}`;Row 的 `gutter={16}` -> `gutter={[16, 16]}` 增加垂直间距。
|
||
|
||
- [x] **Step 3: 图表卡片 Col 改为响应式断点**
|
||
|
||
替换第 227-246 行的图表 Row:
|
||
|
||
```typescript
|
||
<Row gutter={[16, 16]}>
|
||
<Col xs={24} sm={12}>
|
||
<Card title="费用类型分布">
|
||
{expenseStats.length > 0 ? (
|
||
<ReactECharts
|
||
option={pieOption}
|
||
style={{ width: '100%', height: isMobile ? 250 : 300 }}
|
||
/>
|
||
) : (
|
||
<div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无费用数据</div>
|
||
)}
|
||
</Card>
|
||
</Col>
|
||
<Col xs={24} sm={12}>
|
||
<Card title="宿舍费用排行 TOP 20">
|
||
{roomRanking.length > 0 ? (
|
||
<ReactECharts
|
||
option={barOption}
|
||
style={{ width: '100%', height: isMobile ? 250 : 300 }}
|
||
/>
|
||
) : (
|
||
<div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无费用数据</div>
|
||
)}
|
||
</Card>
|
||
</Col>
|
||
</Row>
|
||
```
|
||
|
||
变化:
|
||
- `span={12}` -> `xs={24} sm={12}`(手机堆叠,平板及以上并排)
|
||
- ECharts style 添加 `width: '100%'` 确保跟随容器 resize
|
||
- 高度改为 `isMobile ? 250 : 300`
|
||
|
||
- [x] **Step 4: 甘特图 ECharts 添加 width: '100%'**
|
||
|
||
替换第 216-225 行的甘特图区域:
|
||
|
||
```typescript
|
||
<Card title="入住时间线(甘特图)" style={{ marginBottom: 24 }}>
|
||
{ganttData.length > 0 ? (
|
||
<ReactECharts
|
||
option={ganttOption()}
|
||
style={{ width: '100%', height: Math.max(300, ganttData.length * 40) }}
|
||
/>
|
||
) : (
|
||
<div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无入住数据</div>
|
||
)}
|
||
</Card>
|
||
```
|
||
|
||
- [x] **Step 5: 顶部工具栏小屏堆叠**
|
||
|
||
替换第 162-177 行的标题和 DatePicker 区域:
|
||
|
||
```typescript
|
||
<div
|
||
style={{
|
||
marginBottom: 16,
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: isMobile ? 'flex-start' : 'center',
|
||
flexDirection: isMobile ? 'column' : 'row',
|
||
gap: 12,
|
||
}}
|
||
>
|
||
<h2 style={{ margin: 0 }}>数据面板</h2>
|
||
<RangePicker
|
||
value={[dayjs(period[0]), dayjs(period[1])]}
|
||
onChange={(dates) => {
|
||
if (dates) setPeriod([dates[0]!.format('YYYY-MM-DD'), dates[1]!.format('YYYY-MM-DD')]);
|
||
}}
|
||
/>
|
||
</div>
|
||
```
|
||
|
||
变化:小屏下 `flexDirection: 'column'` + `alignItems: 'flex-start'` + `gap: 12`。
|
||
|
||
- [x] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Dashboard/index.tsx
|
||
git commit -m "feat: Dashboard 响应式网格,统计卡片/图表/工具栏适配三端"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 4: 学生管理字段拆分和响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Students/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 后端 `/students` API 返回学生对象(含 `studentNumber` 可选字段)
|
||
- Produces: 拆分后的列定义、表格 scroll、工具栏 wrap
|
||
|
||
**Description:** 将「学号/身份证」列拆分为「学号」和「身份证」两个独立列,添加 `ellipsis` 和 `width`;表格添加 `scroll={{ x }}`;顶部工具栏添加 `flexWrap: 'wrap'` + `gap`;表单中添加 `studentNumber` 字段。
|
||
|
||
- [x] **Step 1: 拆分列定义**
|
||
|
||
替换第 151-156 行的 columns 数组中的对应条目。将:
|
||
|
||
```typescript
|
||
{ title: '学号/身份证', dataIndex: 'idNumber' },
|
||
```
|
||
|
||
替换为:
|
||
|
||
```typescript
|
||
{
|
||
title: '学号',
|
||
dataIndex: 'studentNumber',
|
||
width: 120,
|
||
ellipsis: true,
|
||
render: (v: string) => v || '-',
|
||
},
|
||
{
|
||
title: '身份证',
|
||
dataIndex: 'idNumber',
|
||
width: 180,
|
||
ellipsis: true,
|
||
render: (v: string) => v || '-',
|
||
},
|
||
```
|
||
|
||
同时为其余缺少 `ellipsis` 的文本列添加 `ellipsis: true`(name, phone, emergencyContact, emergencyPhone, supervisor):
|
||
|
||
```typescript
|
||
{ title: 'ID', dataIndex: 'id', width: 60 },
|
||
{ title: '姓名', dataIndex: 'name', ellipsis: true },
|
||
{ title: '性别', dataIndex: 'gender', width: 60 },
|
||
{ title: '电话', dataIndex: 'phone', ellipsis: true },
|
||
// ... 上面已替换的学号和身份证列
|
||
{ title: '民族', dataIndex: 'ethnicity', width: 80 },
|
||
{ title: '紧急联系人', dataIndex: 'emergencyContact', ellipsis: true },
|
||
{ title: '紧急联系人电话', dataIndex: 'emergencyPhone', ellipsis: true },
|
||
{
|
||
title: '所属机构',
|
||
dataIndex: 'organization',
|
||
render: (v: string) => (v ? <Tag color="purple">{v}</Tag> : '-'),
|
||
},
|
||
{ title: '负责人', dataIndex: 'supervisor', ellipsis: true },
|
||
```
|
||
|
||
- [x] **Step 2: 表格添加 scroll**
|
||
|
||
在第 305 行的 `<Table` 组件上添加 `scroll` 属性:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={data}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 1200 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 人` }}
|
||
```
|
||
|
||
- [x] **Step 3: 工具栏添加 wrap 和 gap**
|
||
|
||
替换第 223-304 行的工具栏 JSX。在顶部 `<div>` 和左右 `<Space>` 之间改为:
|
||
|
||
```typescript
|
||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8 }}>
|
||
<Space wrap>
|
||
<Input.Search ... />
|
||
<Button ... />
|
||
</Space>
|
||
<Space wrap>
|
||
{/* 右侧所有按钮 */}
|
||
</Space>
|
||
</div>
|
||
```
|
||
|
||
变化:
|
||
- 外层 div 添加 `flexWrap: 'wrap'` 和 `gap: 8`
|
||
- 左右 Space 均添加 `wrap` 属性
|
||
|
||
- [x] **Step 4: 表单中添加学号字段**
|
||
|
||
在 modal 中的 `<Form>` 区域(第 329 行附近),在 `name` 字段和 `gender` 字段之间添加学号字段:
|
||
|
||
```typescript
|
||
<Form.Item name="studentNumber" label="学号">
|
||
<Input placeholder="学生的学号" />
|
||
</Form.Item>
|
||
```
|
||
|
||
- [x] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Students/index.tsx
|
||
git commit -m "feat: 学生管理字段拆分(学号/身份证分列),表格和工具栏响应式适配"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 5: 宿舍总览 RoomVisual 复查
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/RoomVisual/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 当前已有的 `xs/sm/md/lg` Col 响应式断点
|
||
- Produces: 确保平板断点(md: >= 768px)覆盖 576-991px 范围
|
||
|
||
**Description:** RoomVisual 已经使用了 `xs={12} sm={8} md={6} lg={4}` 等响应式 Col props,只需确认布局在 576-991px 平板区域表现合理。弹窗已使用 `width={500}`,全局 CSS 会覆盖窄屏。
|
||
|
||
- [x] **Step 1: 验证当前布局**
|
||
|
||
查看房态网格行(第 112 行附近),当前为 `xs={12} sm={8} md={6} lg={4}`:
|
||
- 手机 (xs: < 576px): 2 列 -- OK
|
||
- sm (>= 576px): 3 列 -- OK
|
||
- md (>= 768px): 4 列 -- OK
|
||
- lg (>= 992px): 6 列 -- OK
|
||
|
||
平板区域(576-991px)覆盖了 sm 和 md 两个断点,从 3 列到 4 列,布局合理。无需修改。
|
||
|
||
- [x] **Step 2: 统计卡片栏复查**
|
||
|
||
第 87-107 行的统计卡片当前为 `xs={12} sm={6}`:
|
||
- 手机: 2 列
|
||
- 平板及以上 (>= 576px): 4 列
|
||
|
||
在平板下 4 张卡并排可能略挤,改为 `xs={12} sm={6} md={6}` 以保证桌面端也是 4 列,平板端保持 4 列(可用)。无需修改。
|
||
|
||
- [x] **Step 3: 弹窗复查**
|
||
|
||
详情弹窗(第 182-249 行)`width={500}`,在手机下由全局 CSS `max-width: calc(100vw - 24px)` 覆盖。无需修改。
|
||
|
||
- [x] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/RoomVisual/index.tsx
|
||
git commit -m "chore: RoomVisual 三端断点复查确认,无改动"
|
||
```
|
||
|
||
注:如果复查无改动,可跳过此 commit,或提交一个空 commit 标记完成。
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 6: 入住管理 Occupancies 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Occupancies/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 Alert、Tab 切换区、搜索/操作区
|
||
- Produces: 表格 scroll、工具栏 wrap、弹窗宽度(全局 CSS 覆盖)
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;顶部 Alert + Tab + 搜索/操作区支持小屏堆叠;弹窗宽度由全局 CSS 约束。
|
||
|
||
- [x] **Step 1: 表格添加 scroll**
|
||
|
||
在第 444 行的 `<Table` 组件上添加 `scroll` 属性:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredData}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 900 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 条` }}
|
||
rowSelection={rowSelection}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 2: 工具栏 wrap 验证**
|
||
|
||
查看第 251-395 行的工具栏 JSX。外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`。左侧 Space 有 `wrap`,右侧 Space 有 `wrap`。这些已经正确,无需修改。
|
||
|
||
- [x] **Step 3: 导入时自动收押金设置行检查**
|
||
|
||
第 380-393 行的收押金设置行已经是内联 flex,在小屏下会自动换行。当前实现使用 `<span>` 包裹,换行体验一般但可用。无需修改。
|
||
|
||
- [x] **Step 4: 弹窗宽度**
|
||
|
||
当前弹窗:
|
||
- 入住登记: `width={500}`(第 460 行)
|
||
- 退宿: 无 width 属性(第 517 行,默认 520px)
|
||
- 批量退宿: `width={500}`(第 557 行)
|
||
- 换房: `width={500}`(第 610 行)
|
||
|
||
这些弹窗在小屏下由全局 CSS `@media (max-width: 575px)` 的 `.ant-modal { max-width: calc(100vw - 24px) !important }` 约束。平板弹窗由 `@media (min-width: 576px) and (max-width: 991px)` 约束为 `max-width: calc(100vw - 48px)`。无需额外修改。
|
||
|
||
- [x] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Occupancies/index.tsx
|
||
git commit -m "feat: 入住管理表格添加 scroll,工具栏/弹窗响应式适配"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 7: 宿舍管理 Rooms 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Rooms/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有搜索/筛选/按钮工具栏
|
||
- Produces: 表格 scroll、工具栏 wrap 和 gap
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;确保工具栏和操作列在三端适配。
|
||
|
||
- [x] **Step 1: 表格添加 scroll**
|
||
|
||
在第 374 行的 `<Table` 组件上添加 `scroll` 属性:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredData}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 900 }}
|
||
pagination={{ pageSize: 20, showTotal: (total) => `共 ${total} 间` }}
|
||
rowClassName={(record) => (record.status === 'archived' ? 'archived-row' : '')}
|
||
rowSelection={{
|
||
selectedRowKeys,
|
||
onChange: (keys) => setSelectedRowKeys(keys as number[]),
|
||
getCheckboxProps: (record: any) => ({ disabled: record.status === 'archived' }),
|
||
}}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
查看第 279-372 行的工具栏 JSX。外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`。左右 Space 均已有 `wrap`。这些已经正确,无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Rooms/index.tsx
|
||
git commit -m "feat: 宿舍管理表格添加 scroll 横向滚动"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 8: 费用录入 Expenses 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Expenses/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: Tabs 的两个 Tab(宿舍费用/个人附加费),各有独立 Table 和工具栏
|
||
- Produces: 两个表格分别添加 scroll、弹窗宽度(全局 CSS)
|
||
|
||
**Description:** 宿舍费用和个人附加费两个 Tab 下的表格均添加 `scroll={{ x }}`;弹窗由全局 CSS 覆盖。
|
||
|
||
- [x] **Step 1: 宿舍费用表格添加 scroll**
|
||
|
||
在第 435 行的宿舍费用 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={roomColumns}
|
||
dataSource={filteredRoomExpenses}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 800 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 条` }}
|
||
rowSelection={{
|
||
selectedRowKeys: selectedRoomKeys,
|
||
onChange: (keys) => setSelectedRoomKeys(keys as number[]),
|
||
}}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 2: 个人附加费表格添加 scroll**
|
||
|
||
在第 587 行的个人附加费 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={personalColumns}
|
||
dataSource={filteredPersonalExpenses}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 800 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 条` }}
|
||
rowSelection={{
|
||
selectedRowKeys: selectedPersonalKeys,
|
||
onChange: (keys) => setSelectedPersonalKeys(keys as number[]),
|
||
}}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 3: 工具栏 wrap 验证**
|
||
|
||
第 319-326 行和第 455-461 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`。Space 均有 `wrap`。无需修改。
|
||
|
||
- [x] **Step 4: 弹窗验证**
|
||
|
||
录入宿舍费用弹窗(第 604 行)和个人附加费弹窗(第 644 行)均无显式 width,由全局 CSS 约束窄屏。无需修改。
|
||
|
||
- [x] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Expenses/index.tsx
|
||
git commit -m "feat: 费用录入两个表格添加 scroll 横向滚动"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 9: 押金管理 Deposits 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Deposits/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有搜索/筛选工具栏
|
||
- Produces: 表格 scroll、工具栏 wrap、弹窗宽度
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;搜索/筛选工具栏 wrap;押金收取和退还弹窗由全局 CSS 覆盖。
|
||
|
||
- [x] **Step 1: 表格添加 scroll**
|
||
|
||
在第 211 行的 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredData}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 1000 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 条` }}
|
||
/>
|
||
```
|
||
|
||
列数较多(学生、金额、日期、状态、退还金额、扣除金额、原因、日期、备注 + 操作),使用 `x: 1000`。
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
第 165-172 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`,Space 有 `wrap`。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Deposits/index.tsx
|
||
git commit -m "feat: 押金管理表格添加 scroll 横向滚动"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 10: 账单管理 Bills 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Bills/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有搜索/筛选/按钮工具栏,详情弹窗含嵌套 Table
|
||
- Produces: 表格 scroll、工具栏 wrap、弹窗宽度
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;搜索/筛选/按钮工具栏已有 wrap;生成账单弹窗和详情弹窗由全局 CSS 覆盖。
|
||
|
||
- [x] **Step 1: 主表格添加 scroll**
|
||
|
||
在第 388 行的 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredBills}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 1200 }}
|
||
pagination={{ pageSize: 15, showTotal: (total) => `共 ${total} 条` }}
|
||
rowSelection={{
|
||
selectedRowKeys: selectedRows,
|
||
onChange: (keys) => setSelectedRows(keys as number[]),
|
||
}}
|
||
/>
|
||
```
|
||
|
||
账单列数多(学生、周期、分摊费、个人费、总计、可用押金、抵扣后应付、状态、时间 + 操作列宽320),使用 `x: 1200`。
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
第 307-314 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`,Space 有 `wrap`。无需修改。
|
||
|
||
- [x] **Step 3: 详情弹窗中的内嵌表格添加 scroll**
|
||
|
||
在第 494 行的详情弹窗内嵌 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
dataSource={detailModal.items || []}
|
||
rowKey="id"
|
||
pagination={false}
|
||
size="small"
|
||
scroll={{ x: 700 }}
|
||
columns={[
|
||
{ title: '类型', dataIndex: 'expenseType', render: (v: string) => typeMap[v] || v },
|
||
{ title: '说明', dataIndex: 'description' },
|
||
{
|
||
title: '计费天数',
|
||
dataIndex: 'days',
|
||
render: (v: number) => (v > 0 ? `${v}天` : '-'),
|
||
},
|
||
{
|
||
title: '宿舍总人天',
|
||
dataIndex: 'totalRoomDays',
|
||
render: (v: number) => (v > 0 ? `${v}天` : '-'),
|
||
},
|
||
{
|
||
title: '宿舍总费用',
|
||
dataIndex: 'roomTotalAmount',
|
||
render: (v: number) => `¥${Number(v).toFixed(2)}`,
|
||
},
|
||
{
|
||
title: '应分摊',
|
||
dataIndex: 'studentAmount',
|
||
render: (v: number) => <strong>¥{Number(v).toFixed(2)}</strong>,
|
||
},
|
||
]}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Bills/index.tsx
|
||
git commit -m "feat: 账单管理表格添加 scroll,详情内嵌表格也添加 scroll"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 11: 教室管理 Classrooms 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Classrooms/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有搜索/筛选工具栏
|
||
- Produces: 表格 scroll
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;工具栏已有 wrap。
|
||
|
||
- [x] **Step 1: 表格添加 scroll**
|
||
|
||
在第 265 行的 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredData}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 900 }}
|
||
pagination={{ pageSize: 20, showTotal: (total) => `共 ${total} 条` }}
|
||
/>
|
||
```
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
第 194-201 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`,Space 有 `wrap`。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Classrooms/index.tsx
|
||
git commit -m "feat: 教室管理表格添加 scroll 横向滚动"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 12: 租赁订单 ClassroomRentals 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/ClassroomRentals/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 `scroll={{ x: 1200 }}`
|
||
- Produces: 弹窗宽度
|
||
|
||
**Description:** 表格已有 `scroll={{ x: 1200 }}`,值合理无需修改;工具栏已有 wrap 和 gap;弹窗 `width={600}` 由全局 CSS 覆盖窄屏。
|
||
|
||
- [x] **Step 1: 复查现有 scroll 值**
|
||
|
||
第 318 行已有 `scroll={{ x: 1200 }}`。该表有 10+ 列(教室、租赁方、开始日期、结束日期、时长、日租金、总额、合同、操作),`x: 1200` 合理。无需修改。
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
第 277-284 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`,Space 有 `wrap`。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/ClassroomRentals/index.tsx
|
||
git commit -m "chore: ClassroomRentals 复查 scroll 和 wrap,确认无需修改"
|
||
```
|
||
|
||
注:如果复查无改动,可跳过此 commit。
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 13: 租赁方 Tenants 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Tenants/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有工具栏
|
||
- Produces: 表格 scroll
|
||
|
||
**Description:** 表格添加 `scroll={{ x }}`;工具栏已有 wrap 和 gap。
|
||
|
||
- [x] **Step 1: 表格添加 scroll**
|
||
|
||
在第 183 行的 `<Table` 上添加 `scroll`:
|
||
|
||
```typescript
|
||
<Table
|
||
columns={columns}
|
||
dataSource={filteredData}
|
||
rowKey="id"
|
||
loading={loading}
|
||
scroll={{ x: 700 }}
|
||
pagination={{ pageSize: 20, showTotal: (total) => `共 ${total} 条` }}
|
||
/>
|
||
```
|
||
|
||
列较少(名称、联系人、电话、颜色、备注 + 操作),使用 `x: 700`。
|
||
|
||
- [x] **Step 2: 工具栏已有 wrap 和 gap**
|
||
|
||
第 152-159 行的工具栏外层 div 已有 `flexWrap: 'wrap'` 和 `gap: 8`。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Tenants/index.tsx
|
||
git commit -m "feat: 租赁方表格添加 scroll 横向滚动"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 14: 操作日志 OperationLogs 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/OperationLogs/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 `scroll={{ x: 1000 }}` 和工具栏
|
||
- Produces: 确认现有适配
|
||
|
||
**Description:** 表格已有 `scroll={{ x: 1000 }}` 且值合理(8 列),无需修改;工具栏已有 wrap 和 gap。
|
||
|
||
- [x] **Step 1: 复查现有 scroll 值**
|
||
|
||
第 151 行已有 `scroll={{ x: 1000 }}`。该表有 8 列(时间、操作人、模块、操作、状态、详情、IP、终端),`x: 1000` 合理。无需修改。
|
||
|
||
- [x] **Step 2: 工具栏已有 flexWrap 和 gap**
|
||
|
||
第 113-121 行已有 `flexWrap: 'wrap'` 和 `gap: 12`。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/OperationLogs/index.tsx
|
||
git commit -m "chore: OperationLogs 复查 scroll 和 wrap,确认无需修改"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 15: 角色管理 Roles 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Roles/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 `scroll={{ x: 800 }}`、工具栏、权限分配弹窗
|
||
- Produces: 工具栏 wrap、弹窗宽度
|
||
|
||
**Description:** 表格已有 `scroll={{ x: 800 }}`;工具栏添加 wrap;权限分配弹窗 `width={700}` 由全局 CSS 覆盖窄屏。
|
||
|
||
- [x] **Step 1: 工具栏添加 flexWrap 和 gap**
|
||
|
||
替换第 206-212 行的工具栏 div:
|
||
|
||
```typescript
|
||
<div
|
||
style={{
|
||
marginBottom: 16,
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
flexWrap: 'wrap',
|
||
gap: 8,
|
||
}}
|
||
>
|
||
<h2 style={{ margin: 0 }}>角色管理</h2>
|
||
<PermissionButton ...>新增角色</PermissionButton>
|
||
</div>
|
||
```
|
||
|
||
- [x] **Step 2: 复查表格 scroll**
|
||
|
||
第 224 行已有 `scroll={{ x: 800 }}`。该表有 ID、名称、描述、权限标签、系统 + 操作列(fixed: right),`x: 800` 合理。无需修改。
|
||
|
||
- [x] **Step 3: 弹窗宽度**
|
||
|
||
权限分配弹窗第 238 行 `width={700}`,在窄屏下由全局 CSS 覆盖。无需修改。
|
||
|
||
- [x] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Roles/index.tsx
|
||
git commit -m "feat: 角色管理工具栏添加 flexWrap 响应式适配"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 16: 权限一览 Permissions 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Permissions/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 卡片列表(非 Table 页面)
|
||
- Produces: 工具栏 wrap
|
||
|
||
**Description:** 权限一览是卡片列表(非表格),只需确保标题 + 搜索栏在小屏下堆叠。
|
||
|
||
- [x] **Step 1: 工具栏添加 flexWrap 和 gap**
|
||
|
||
替换第 58-64 行的工具栏 div:
|
||
|
||
```typescript
|
||
<div
|
||
style={{
|
||
marginBottom: 16,
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
flexWrap: 'wrap',
|
||
gap: 8,
|
||
}}
|
||
>
|
||
<h2 style={{ margin: 0 }}>权限一览</h2>
|
||
<Input.Search ... />
|
||
</div>
|
||
```
|
||
|
||
- [x] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Permissions/index.tsx
|
||
git commit -m "feat: 权限一览工具栏添加 flexWrap 响应式适配"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 17: 账号管理 Users 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Users/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 `scroll={{ x: 1000 }}`
|
||
- Produces: 工具栏 wrap
|
||
|
||
**Description:** 表格已有 `scroll={{ x: 1000 }}`;工具栏添加 wrap。
|
||
|
||
- [x] **Step 1: 工具栏添加 flexWrap 和 gap**
|
||
|
||
替换第 198-204 行的工具栏 div:
|
||
|
||
```typescript
|
||
<div
|
||
style={{
|
||
marginBottom: 16,
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
flexWrap: 'wrap',
|
||
gap: 8,
|
||
}}
|
||
>
|
||
<h2 style={{ margin: 0 }}>账号管理</h2>
|
||
<PermissionButton ...>新增账号</PermissionButton>
|
||
</div>
|
||
```
|
||
|
||
- [x] **Step 2: 复查表格 scroll**
|
||
|
||
第 216 行已有 `scroll={{ x: 1000 }}`。该表有 ID、用户名、姓名、角色、状态、最后登录、创建时间 + 操作列(fixed: right),`x: 1000` 合理。无需修改。
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Users/index.tsx
|
||
git commit -m "feat: 账号管理工具栏添加 flexWrap 响应式适配"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 18: 教室排期 ClassroomSchedule 特殊适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/ClassroomSchedule/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 `overflowX: 'auto'` 容器、sticky 首列、minWidth 日期列
|
||
- Produces: 确认日期列不被挤压,sticky 列在小屏正常
|
||
|
||
**Description:** 教室排期是自定义 HTML `<table>`,含 31+ 日期列 + sticky 首列。当前外层 div 已有 `overflowX: 'auto'`,日期列 `minWidth: 26`,首列 sticky。确认在平板/手机下正常工作。
|
||
|
||
- [x] **Step 1: 日期列 minWidth 不变**
|
||
|
||
第 234 行已设置 `minWidth: 26`,在窄屏下不会挤压。无需修改。
|
||
|
||
- [x] **Step 2: 首列 sticky 左偏移确认**
|
||
|
||
第 210 行首列已有 `position: 'sticky', left: 0`,在小屏下仍然生效。无需修改。
|
||
|
||
- [x] **Step 3: 详情弹窗宽度**
|
||
|
||
第 327 行弹窗 `width={500}`,在窄屏下由全局 CSS 覆盖。无需修改。
|
||
|
||
- [x] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/ClassroomSchedule/index.tsx
|
||
git commit -m "chore: ClassroomSchedule 复查 sticky 列和日期列 minWidth,确认无需修改"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 19: 登录页 Login 响应式适配
|
||
|
||
**Files:**
|
||
- Modify: `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Login/index.tsx`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 已有 Card 登录表单
|
||
- Produces: 卡片宽度改为 maxWidth + calc
|
||
|
||
**Description:** 登录卡片当前 `width: 400`,改为 `maxWidth: 400, width: 'calc(100vw - 48px)'` 以在手机下自适应。
|
||
|
||
- [x] **Step 1: 卡片宽度响应式**
|
||
|
||
替换第 39-45 行的 Card style:
|
||
|
||
```typescript
|
||
<Card
|
||
style={{
|
||
maxWidth: 400,
|
||
width: 'calc(100vw - 48px)',
|
||
borderRadius: 16,
|
||
boxShadow: '0 4px 24px rgba(0,0,0,0.08)',
|
||
border: 'none',
|
||
}}
|
||
>
|
||
```
|
||
|
||
变化:`width: 400` -> `maxWidth: 400, width: 'calc(100vw - 48px)'`
|
||
|
||
- [x] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add apps/admin/src/pages/Login/index.tsx
|
||
git commit -m "feat: 登录卡片改为 maxWidth + calc 响应式宽度"
|
||
```
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Task 20: 全局验证与编译检查
|
||
|
||
**Files:**
|
||
- No specific file modifications; validation only
|
||
|
||
**Interfaces:**
|
||
- Consumes: 所有已完成的页面改动
|
||
- Produces: 验证报告(视觉 + 编译)
|
||
|
||
**Description:** 在 Chrome DevTools 响应式模式下手动检查所有 16 个页面在三端视口宽度下的表现,确认无溢出、弹窗不出屏、表格可横向滚动。最后运行 `npm run build` 确保 TypeScript 编译通过。
|
||
|
||
- [x] **Step 1: Chrome DevTools 响应式模式视觉检查**
|
||
|
||
打开浏览器访问 `http://localhost:5173`(或部署地址),使用 Chrome DevTools 的设备工具栏切换以下宽度:
|
||
|
||
| 宽度 | 端侧 | 检查要点 |
|
||
|------|------|---------|
|
||
| 375px | 手机 | 表格可横向滚动、按钮不溢出、弹窗不出屏、文字不截断 |
|
||
| 768px | 平板 | Sider 默认折叠、Content padding 为 16px、卡片网格正确 |
|
||
| 992px | 桌面小屏 | Sider 可展开、Content padding 为 24px |
|
||
| 1440px | 桌面大屏 | 全部正常,无奇怪空白 |
|
||
|
||
逐页检查(16 个页面):
|
||
1. /dashboard
|
||
2. /room-visual
|
||
3. /students
|
||
4. /rooms
|
||
5. /occupancies
|
||
6. /expenses
|
||
7. /deposits
|
||
8. /bills
|
||
9. /classrooms
|
||
10. /classroom-rentals
|
||
11. /tenants
|
||
12. /classroom-schedule
|
||
13. /operation-logs
|
||
14. /roles
|
||
15. /permissions
|
||
16. /users
|
||
17. /login
|
||
|
||
每个页面检查项:
|
||
- [x] 表格有无横向滚动条(在窄屏下出现,且不影响行选择/操作)
|
||
- [x] 按钮组是否错位/溢出容器
|
||
- [x] 弹窗(打开任意新增/编辑弹窗)是否超出屏幕边界
|
||
- [x] 统计卡片/网格是否按预期列数排列
|
||
- [x] ECharts 图表是否正确跟随容器宽度
|
||
- [x] 文字是否正常截断(ellipsis 生效)
|
||
|
||
- [x] **Step 2: TypeScript 编译检查**
|
||
|
||
```bash
|
||
cd /Users/tiku1/code/gongxue-base
|
||
npm run build
|
||
```
|
||
|
||
预期:`tsc -b && vite build` 无错误输出,构建成功。
|
||
|
||
如果有 TypeScript 错误,修复后再执行:
|
||
|
||
```bash
|
||
cd /Users/tiku1/code/gongxue-base/apps/admin
|
||
npx tsc -b --noEmit
|
||
```
|
||
|
||
- [x] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add -A
|
||
git commit -m "chore: 全局响应式适配验证完成"
|
||
```
|
||
|
||
如果验证中发现问题需要修复,则在对应页面进行修复后单独 commit。
|
||
|
||
archived-with: 2026-07-03-admin-responsive-adaptation
|
||
---
|
||
|
||
### Critical Files for Implementation
|
||
- `/Users/tiku1/code/gongxue-base/apps/admin/src/index.css`
|
||
- `/Users/tiku1/code/gongxue-base/apps/admin/src/layouts/MainLayout.tsx`
|
||
- `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Dashboard/index.tsx`
|
||
- `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Students/index.tsx`
|
||
- `/Users/tiku1/code/gongxue-base/apps/admin/src/pages/Occupancies/index.tsx`
|