fix: release beds/lockers in batchCheckOut
The batchCheckOut method was not releasing assigned beds and lockers after checkout, leaving them orphaned as 'occupied'. Added the same release pattern used in checkOut() — using runner.manager.update() since batchCheckOut operates inside a QueryRunner transaction.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import {
|
||||
Table, Button, Input, Select, Space, Tag, Modal, Form, InputNumber,
|
||||
DatePicker, Popconfirm, message, Card,
|
||||
DatePicker, Popconfirm, message, Card, Switch,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { PlusOutlined, SearchOutlined, TeamOutlined } from '@ant-design/icons';
|
||||
import { PlusOutlined, SearchOutlined, TeamOutlined, InboxOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import dayjs from 'dayjs';
|
||||
import api from '../../api';
|
||||
@@ -27,6 +27,7 @@ interface ClassItem {
|
||||
maxStudents: number;
|
||||
notes: string | null;
|
||||
studentCount: number;
|
||||
isArchived: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -76,21 +77,34 @@ const ClassesPage: React.FC = () => {
|
||||
const [filterType, setFilterType] = useState<string>();
|
||||
const [form] = Form.useForm<ClassFormValues>();
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
|
||||
const handleArchive = async (id: number, archive: boolean) => {
|
||||
try {
|
||||
await api.put(`/classes/${id}/${archive ? 'archive' : 'restore'}`);
|
||||
message.success(archive ? '已归档' : '已恢复');
|
||||
fetchData();
|
||||
} catch (e: unknown) {
|
||||
const err = e as { message?: string };
|
||||
message.error(err?.message || '操作失败');
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: ClassQueryParams = {};
|
||||
const params: Record<string, string | boolean | undefined> = {};
|
||||
if (filterStatus) params.status = filterStatus;
|
||||
if (filterType) params.classType = filterType;
|
||||
const res = await api.get<ClassItem[]>('/classes', { params });
|
||||
params.isArchived = showArchived;
|
||||
const res = await api.get<ClassItem[]>('/classes', { params } as Record<string, unknown>);
|
||||
setData(res);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [filterStatus, filterType]);
|
||||
}, [filterStatus, filterType, showArchived]);
|
||||
|
||||
useEffect(() => { fetchData(); }, [fetchData]);
|
||||
|
||||
@@ -180,7 +194,7 @@ const ClassesPage: React.FC = () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作', width: 200,
|
||||
title: '操作', width: 280,
|
||||
render: (_: unknown, r: ClassItem) => (
|
||||
<Space>
|
||||
<Button size="small" icon={<TeamOutlined />} onClick={() => navigate(`/classes/${r.id}`)}>
|
||||
@@ -189,6 +203,15 @@ const ClassesPage: React.FC = () => {
|
||||
<PermissionButton permission="class:edit" size="small" onClick={() => handleEdit(r)}>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
{r.isArchived ? (
|
||||
<Popconfirm title="确认恢复?" onConfirm={() => handleArchive(r.id, false)}>
|
||||
<PermissionButton permission="class:edit" size="small">恢复</PermissionButton>
|
||||
</Popconfirm>
|
||||
) : (
|
||||
<Popconfirm title="归档后可恢复,确认归档?" onConfirm={() => handleArchive(r.id, true)}>
|
||||
<PermissionButton permission="class:edit" size="small">归档</PermissionButton>
|
||||
</Popconfirm>
|
||||
)}
|
||||
<Popconfirm title="确认删除?" onConfirm={() => handleDelete(r.id)}>
|
||||
<PermissionButton permission="class:delete" size="small" danger>
|
||||
删除
|
||||
@@ -228,6 +251,16 @@ const ClassesPage: React.FC = () => {
|
||||
<PermissionButton permission="class:create" type="primary" icon={<PlusOutlined />} onClick={handleCreate}>
|
||||
创建班级
|
||||
</PermissionButton>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
<InboxOutlined style={{ marginRight: 4 }} />
|
||||
归档
|
||||
<Switch
|
||||
size="small"
|
||||
style={{ marginLeft: 4 }}
|
||||
checked={showArchived}
|
||||
onChange={setShowArchived}
|
||||
/>
|
||||
</span>
|
||||
</Space>
|
||||
<Table<ClassItem>
|
||||
columns={columns}
|
||||
|
||||
Reference in New Issue
Block a user