feat: 重构各业务模块管理页面与服务

This commit is contained in:
2026-08-05 17:12:00 +08:00
parent 80e6fccf05
commit fd39e1686a
163 changed files with 18409 additions and 13449 deletions

View File

@@ -0,0 +1,146 @@
import React from 'react';
import { Button, DatePicker, Input, InputNumber, Space, Switch, Tooltip, Upload } from 'antd';
import {
DownloadOutlined,
ExportOutlined,
PlusOutlined,
UploadOutlined,
} from '@ant-design/icons';
import type { Dayjs } from 'dayjs';
import PermissionButton from '../../components/PermissionButton';
import type { OccupancyView } from '../archive-view';
const { RangePicker } = DatePicker;
export const OccupanciesToolbar: React.FC<{
viewMode: OccupancyView;
onChangeViewMode: (mode: OccupancyView) => void;
onSearch: (value: string) => void;
dateRange: [Dayjs | null, Dayjs | null] | null;
onChangeDateRange: (dates: [Dayjs | null, Dayjs | null] | null) => void;
canCheckIn: boolean;
onCheckIn: () => void;
onImport: (options: any) => void;
autoDeposit: boolean;
onAutoDepositChange: (value: boolean) => void;
depositAmount: number;
onDepositAmountChange: (value: number) => void;
onDownloadTemplate: () => void;
onExport: () => void;
}> = ({
viewMode,
onChangeViewMode,
onSearch,
dateRange,
onChangeDateRange,
canCheckIn,
onCheckIn,
onImport,
autoDeposit,
onAutoDepositChange,
depositAmount,
onDepositAmountChange,
onDownloadTemplate,
onExport,
}) => {
return (
<div className="responsive-toolbar">
<Space wrap className="responsive-toolbar__group">
<Button
type={viewMode === 'active' ? 'primary' : 'default'}
onClick={() => onChangeViewMode('active')}
>
</Button>
<Button
type={viewMode === 'all' ? 'primary' : 'default'}
onClick={() => onChangeViewMode('all')}
>
</Button>
<Button
type={viewMode === 'archived' ? 'primary' : 'default'}
onClick={() => onChangeViewMode('archived')}
>
</Button>
<Input.Search
placeholder="搜索学生姓名或房间号"
onSearch={onSearch}
allowClear
style={{ width: 200 }}
/>
<RangePicker
value={dateRange}
onChange={(dates) => onChangeDateRange(dates ? [dates[0], dates[1]] : null)}
placeholder={['入住开始', '入住结束']}
style={{ width: 240 }}
/>
</Space>
<Space wrap className="responsive-toolbar__group">
{viewMode !== 'archived' ? (
<PermissionButton
permission="occupancy:checkin"
type="primary"
icon={<PlusOutlined />}
onClick={onCheckIn}
>
</PermissionButton>
) : null}
{viewMode !== 'archived' && canCheckIn ? (
<>
<Upload accept=".xlsx,.xls" showUploadList={false} customRequest={onImport}>
<Tooltip title="按手机号关联学生,并自动创建缺失的学生、宿舍和入住记录">
<Button type="primary" ghost icon={<UploadOutlined />}>
</Button>
</Tooltip>
</Upload>
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13 }}>
<Switch size="small" checked={autoDeposit} onChange={onAutoDepositChange} />
{autoDeposit && (
<Space.Compact>
<InputNumber
size="small"
min={0}
value={depositAmount}
onChange={(v) => onDepositAmountChange(v || 500)}
style={{ width: 60 }}
/>
<span
style={{
padding: '0 8px',
display: 'flex',
alignItems: 'center',
border: '1px solid #d9d9d9',
backgroundColor: '#fafafa',
fontSize: 12,
}}
>
</span>
</Space.Compact>
)}
</span>
</>
) : null}
{viewMode !== 'archived' ? (
<PermissionButton
permission="occupancy:view"
icon={<DownloadOutlined />}
onClick={onDownloadTemplate}
>
</PermissionButton>
) : null}
{viewMode !== 'archived' ? (
<PermissionButton permission="occupancy:view" icon={<ExportOutlined />} onClick={onExport}>
</PermissionButton>
) : null}
</Space>
</div>
);
};