|
|
@@ -25,7 +25,7 @@ import { AlertCircle } from 'lucide-react';
|
|
|
import { AreaSelect } from '@d8d/area-management-ui';
|
|
|
import { Form } from '@d8d/shared-ui-components/components/ui/form';
|
|
|
import { useForm } from 'react-hook-form';
|
|
|
-import { disabilityClient } from '../api/disabilityClient';
|
|
|
+import { disabilityClientManager } from '../api/disabilityClient';
|
|
|
import type {
|
|
|
DisabledPersonData,
|
|
|
AreaSelection,
|
|
|
@@ -68,7 +68,7 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
|
|
|
const { data, isLoading, refetch } = useQuery({
|
|
|
queryKey: ['disabled-persons-search', searchParams],
|
|
|
queryFn: async () => {
|
|
|
- const response = await disabilityClient.searchDisabledPersons.$get({
|
|
|
+ const response = await disabilityClientManager.get().searchDisabledPersons.$get({
|
|
|
query: {
|
|
|
keyword: searchParams.keyword || '',
|
|
|
skip: ((searchParams.page || 1) - 1) * (searchParams.pageSize || 10),
|
|
|
@@ -85,7 +85,7 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
|
|
|
const { data: allData, isLoading: isLoadingAll } = useQuery({
|
|
|
queryKey: ['disabled-persons-all', searchParams.page, searchParams.pageSize],
|
|
|
queryFn: async () => {
|
|
|
- const response = await disabilityClient.getAllDisabledPersons.$get({
|
|
|
+ const response = await disabilityClientManager.get().getAllDisabledPersons.$get({
|
|
|
query: {
|
|
|
skip: ((searchParams.page || 1) - 1) * (searchParams.pageSize || 10),
|
|
|
take: searchParams.pageSize || 10,
|
|
|
@@ -210,14 +210,15 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
|
|
|
return (
|
|
|
<>
|
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
|
- <DialogContent className="max-w-6xl max-h-[80vh] overflow-hidden flex flex-col">
|
|
|
+ <DialogContent className="max-w-6xl max-h-[90vh] overflow-hidden flex flex-col w-[95vw] sm:w-full h-[90vh] sm:h-auto">
|
|
|
<DialogHeader>
|
|
|
<DialogTitle>选择残疾人</DialogTitle>
|
|
|
</DialogHeader>
|
|
|
|
|
|
- {/* 搜索区域 */}
|
|
|
+ {/* 搜索区域 - 响应式设计 */}
|
|
|
<div className="space-y-4 p-4 border rounded-lg">
|
|
|
- <div className="grid grid-cols-4 gap-4">
|
|
|
+ {/* 第一行:基本信息搜索 - 响应式网格 */}
|
|
|
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
|
<div className="space-y-2">
|
|
|
<Label htmlFor="name">姓名</Label>
|
|
|
<Input
|
|
|
@@ -272,19 +273,21 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div className="grid grid-cols-4 gap-4">
|
|
|
- <div className="space-y-2">
|
|
|
- <Label>省份/城市</Label>
|
|
|
- {/* AreaSelect需要Form上下文,所以包装在Form中 */}
|
|
|
- <Form {...form}>
|
|
|
- <AreaSelect
|
|
|
- value={areaSelection}
|
|
|
- onChange={setAreaSelection}
|
|
|
- data-testid="area-select"
|
|
|
- />
|
|
|
- </Form>
|
|
|
- </div>
|
|
|
+ {/* 第二行:区域选择器单独一行 */}
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Label>省份/城市/区县</Label>
|
|
|
+ {/* AreaSelect需要Form上下文,所以包装在Form中 */}
|
|
|
+ <Form {...form}>
|
|
|
+ <AreaSelect
|
|
|
+ value={areaSelection}
|
|
|
+ onChange={setAreaSelection}
|
|
|
+ data-testid="area-select"
|
|
|
+ />
|
|
|
+ </Form>
|
|
|
+ </div>
|
|
|
|
|
|
+ {/* 第三行:其他筛选条件和操作按钮 - 响应式网格 */}
|
|
|
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
|
<div className="space-y-2">
|
|
|
<Label htmlFor="disabilityType">残疾类型</Label>
|
|
|
<Select
|
|
|
@@ -332,90 +335,109 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
|
|
|
</Select>
|
|
|
</div>
|
|
|
|
|
|
- <div className="flex items-end space-x-2">
|
|
|
- <Button onClick={handleSearch} data-testid="search-button">
|
|
|
+ {/* 在移动端隐藏空列 */}
|
|
|
+ <div className="hidden lg:block"></div>
|
|
|
+
|
|
|
+ <div className="flex items-end space-x-2 sm:col-span-2 lg:col-span-1">
|
|
|
+ <Button onClick={handleSearch} data-testid="search-button" className="flex-1 sm:flex-none">
|
|
|
搜索
|
|
|
</Button>
|
|
|
- <Button variant="outline" onClick={handleResetSearch} data-testid="reset-button">
|
|
|
+ <Button variant="outline" onClick={handleResetSearch} data-testid="reset-button" className="flex-1 sm:flex-none">
|
|
|
重置
|
|
|
</Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- {/* 表格区域 */}
|
|
|
- <div className="flex-1 overflow-auto">
|
|
|
+ {/* 表格区域 - 响应式设计 */}
|
|
|
+ <div className="flex-1 flex flex-col min-h-0">
|
|
|
{isLoadingData ? (
|
|
|
<div className="flex items-center justify-center h-64">
|
|
|
<div className="text-center">加载中...</div>
|
|
|
</div>
|
|
|
) : personsData?.data && personsData.data.length > 0 ? (
|
|
|
<>
|
|
|
- <div className="border rounded-md">
|
|
|
- <Table data-testid="disabled-persons-table">
|
|
|
- <TableHeader>
|
|
|
- <TableRow>
|
|
|
- {mode === 'multiple' && (
|
|
|
- <TableHead className="w-12">
|
|
|
- <Checkbox
|
|
|
- checked={selectedPersons.length === personsData.data.length}
|
|
|
- onCheckedChange={(checked) => {
|
|
|
- if (checked) {
|
|
|
- const selectablePersons = personsData.data.filter(
|
|
|
- (person: DisabledPersonData) => !disabledIds.includes(person.id)
|
|
|
- );
|
|
|
- setSelectedPersons(selectablePersons);
|
|
|
- } else {
|
|
|
- setSelectedPersons([]);
|
|
|
- }
|
|
|
- }}
|
|
|
- aria-label="全选"
|
|
|
- />
|
|
|
- </TableHead>
|
|
|
- )}
|
|
|
- {columns.map((column) => (
|
|
|
- <TableHead key={column.key}>{column.label}</TableHead>
|
|
|
- ))}
|
|
|
- </TableRow>
|
|
|
- </TableHeader>
|
|
|
- <TableBody>
|
|
|
- {personsData.data.map((person: DisabledPersonData) => (
|
|
|
- <TableRow
|
|
|
- key={person.id}
|
|
|
- onClick={() => mode === 'single' && handleSelectPerson(person)}
|
|
|
- className={mode === 'single' ? 'cursor-pointer hover:bg-muted' : ''}
|
|
|
- data-testid={`table-row-${person.id}`}
|
|
|
- >
|
|
|
+ {/* 移动端提示 */}
|
|
|
+ <div className="lg:hidden mb-2 text-sm text-muted-foreground">
|
|
|
+ <p>提示:表格可以左右滑动查看所有列</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 表格容器 - 支持水平和垂直滚动 */}
|
|
|
+ <div className="flex-1 border rounded-md overflow-hidden flex flex-col min-h-0">
|
|
|
+ <div className="overflow-x-auto overflow-y-auto flex-1">
|
|
|
+ <Table data-testid="disabled-persons-table" className="min-w-full">
|
|
|
+ <TableHeader>
|
|
|
+ <TableRow>
|
|
|
{mode === 'multiple' && (
|
|
|
- <TableCell>
|
|
|
+ <TableHead className="w-12 sticky left-0 bg-background z-10">
|
|
|
<Checkbox
|
|
|
- checked={selectedPersons.some(p => p.id === person.id)}
|
|
|
+ checked={selectedPersons.length === personsData.data.length}
|
|
|
onCheckedChange={(checked) => {
|
|
|
if (checked) {
|
|
|
- setSelectedPersons([...selectedPersons, person]);
|
|
|
+ const selectablePersons = personsData.data.filter(
|
|
|
+ (person: DisabledPersonData) => !disabledIds.includes(person.id)
|
|
|
+ );
|
|
|
+ setSelectedPersons(selectablePersons);
|
|
|
} else {
|
|
|
- setSelectedPersons(selectedPersons.filter(p => p.id !== person.id));
|
|
|
+ setSelectedPersons([]);
|
|
|
}
|
|
|
}}
|
|
|
- disabled={disabledIds.includes(person.id)}
|
|
|
- aria-label="选择"
|
|
|
+ aria-label="全选"
|
|
|
/>
|
|
|
- </TableCell>
|
|
|
+ </TableHead>
|
|
|
)}
|
|
|
- <TableCell>{person.name}</TableCell>
|
|
|
- <TableCell>{person.gender}</TableCell>
|
|
|
- <TableCell>{person.idCard}</TableCell>
|
|
|
- <TableCell>{person.disabilityId}</TableCell>
|
|
|
- <TableCell>{person.phone}</TableCell>
|
|
|
- <TableCell>{person.province}</TableCell>
|
|
|
- <TableCell>{person.city}</TableCell>
|
|
|
- <TableCell>{person.disabilityType}</TableCell>
|
|
|
- <TableCell>{person.disabilityLevel}</TableCell>
|
|
|
- <TableCell>{person.isInBlackList === 1 ? '是' : '否'}</TableCell>
|
|
|
+ {columns.map((column, index) => (
|
|
|
+ <TableHead
|
|
|
+ key={column.key}
|
|
|
+ className={`
|
|
|
+ ${index === 0 ? 'sticky left-0 bg-background z-10' : ''}
|
|
|
+ ${['province', 'city', 'disabilityType', 'disabilityLevel', 'blacklist'].includes(column.key) ? 'hidden lg:table-cell' : ''}
|
|
|
+ `}
|
|
|
+ >
|
|
|
+ {column.label}
|
|
|
+ </TableHead>
|
|
|
+ ))}
|
|
|
</TableRow>
|
|
|
- ))}
|
|
|
- </TableBody>
|
|
|
- </Table>
|
|
|
+ </TableHeader>
|
|
|
+ <TableBody>
|
|
|
+ {personsData.data.map((person: DisabledPersonData) => (
|
|
|
+ <TableRow
|
|
|
+ key={person.id}
|
|
|
+ onClick={() => mode === 'single' && handleSelectPerson(person)}
|
|
|
+ className={mode === 'single' ? 'cursor-pointer hover:bg-muted' : ''}
|
|
|
+ data-testid={`table-row-${person.id}`}
|
|
|
+ >
|
|
|
+ {mode === 'multiple' && (
|
|
|
+ <TableCell className="sticky left-0 bg-background z-10">
|
|
|
+ <Checkbox
|
|
|
+ checked={selectedPersons.some(p => p.id === person.id)}
|
|
|
+ onCheckedChange={(checked) => {
|
|
|
+ if (checked) {
|
|
|
+ setSelectedPersons([...selectedPersons, person]);
|
|
|
+ } else {
|
|
|
+ setSelectedPersons(selectedPersons.filter(p => p.id !== person.id));
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ disabled={disabledIds.includes(person.id)}
|
|
|
+ aria-label="选择"
|
|
|
+ />
|
|
|
+ </TableCell>
|
|
|
+ )}
|
|
|
+ <TableCell className="sticky left-0 bg-background z-10">{person.name}</TableCell>
|
|
|
+ <TableCell>{person.gender}</TableCell>
|
|
|
+ <TableCell>{person.idCard}</TableCell>
|
|
|
+ <TableCell>{person.disabilityId}</TableCell>
|
|
|
+ <TableCell>{person.phone}</TableCell>
|
|
|
+ <TableCell className="hidden lg:table-cell">{person.province}</TableCell>
|
|
|
+ <TableCell className="hidden lg:table-cell">{person.city}</TableCell>
|
|
|
+ <TableCell className="hidden lg:table-cell">{person.disabilityType}</TableCell>
|
|
|
+ <TableCell className="hidden lg:table-cell">{person.disabilityLevel}</TableCell>
|
|
|
+ <TableCell className="hidden lg:table-cell">{person.isInBlackList === 1 ? '是' : '否'}</TableCell>
|
|
|
+ </TableRow>
|
|
|
+ ))}
|
|
|
+ </TableBody>
|
|
|
+ </Table>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<DataTablePagination
|
|
|
currentPage={searchParams.page || 1}
|