|
@@ -11,6 +11,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@
|
|
|
import { Skeleton } from '@d8d/shared-ui-components/components/ui/skeleton';
|
|
import { Skeleton } from '@d8d/shared-ui-components/components/ui/skeleton';
|
|
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@d8d/shared-ui-components/components/ui/dialog';
|
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@d8d/shared-ui-components/components/ui/dialog';
|
|
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@d8d/shared-ui-components/components/ui/form';
|
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@d8d/shared-ui-components/components/ui/form';
|
|
|
|
|
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@d8d/shared-ui-components/components/ui/select';
|
|
|
import { useForm } from 'react-hook-form';
|
|
import { useForm } from 'react-hook-form';
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
import { toast } from 'sonner';
|
|
import { toast } from 'sonner';
|
|
@@ -20,7 +21,8 @@ import { CreateDisabledPersonSchema, UpdateDisabledPersonSchema } from '@d8d/all
|
|
|
import type { CreateDisabledPersonRequest, UpdateDisabledPersonRequest } from '../api/disabilityClient';
|
|
import type { CreateDisabledPersonRequest, UpdateDisabledPersonRequest } from '../api/disabilityClient';
|
|
|
import { DISABILITY_TYPES, getDisabilityTypeLabel } from '@d8d/allin-enums';
|
|
import { DISABILITY_TYPES, getDisabilityTypeLabel } from '@d8d/allin-enums';
|
|
|
import { DISABILITY_LEVELS, getDisabilityLevelLabel } from '@d8d/allin-enums';
|
|
import { DISABILITY_LEVELS, getDisabilityLevelLabel } from '@d8d/allin-enums';
|
|
|
-import { AreaSelectForm } from '@d8d/area-management-ui/components';
|
|
|
|
|
|
|
+import { BankNameSelector } from '@d8d/bank-name-management-ui';
|
|
|
|
|
+import { ProvinceSelect, AreaSelectForm } from '@d8d/area-management-ui';
|
|
|
import PhotoUploadField, { type PhotoItem } from './PhotoUploadField';
|
|
import PhotoUploadField, { type PhotoItem } from './PhotoUploadField';
|
|
|
import PhotoPreview from './PhotoPreview';
|
|
import PhotoPreview from './PhotoPreview';
|
|
|
import BankCardManagement, { type BankCardItem } from './BankCardManagement';
|
|
import BankCardManagement, { type BankCardItem } from './BankCardManagement';
|
|
@@ -31,11 +33,17 @@ interface DisabilityPersonSearchParams {
|
|
|
page: number;
|
|
page: number;
|
|
|
limit: number;
|
|
limit: number;
|
|
|
search: string;
|
|
search: string;
|
|
|
|
|
+ bankNameId?: number;
|
|
|
|
|
+ cardType?: string;
|
|
|
|
|
+ disabilityType?: string;
|
|
|
|
|
+ disabilityLevel?: string;
|
|
|
|
|
+ province?: string;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const DisabilityPersonManagement: React.FC = () => {
|
|
const DisabilityPersonManagement: React.FC = () => {
|
|
|
const [searchParams, setSearchParams] = useState<DisabilityPersonSearchParams>({ page: 1, limit: 10, search: '' });
|
|
const [searchParams, setSearchParams] = useState<DisabilityPersonSearchParams>({ page: 1, limit: 10, search: '' });
|
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
|
|
+
|
|
|
const [isCreateForm, setIsCreateForm] = useState(true);
|
|
const [isCreateForm, setIsCreateForm] = useState(true);
|
|
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
|
const [personToDelete, setPersonToDelete] = useState<number | null>(null);
|
|
const [personToDelete, setPersonToDelete] = useState<number | null>(null);
|
|
@@ -84,15 +92,38 @@ const DisabilityPersonManagement: React.FC = () => {
|
|
|
defaultValues: {}
|
|
defaultValues: {}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+
|
|
|
// 数据查询
|
|
// 数据查询
|
|
|
const { data, isLoading, refetch } = useQuery({
|
|
const { data, isLoading, refetch } = useQuery({
|
|
|
queryKey: ['disabled-persons', searchParams],
|
|
queryKey: ['disabled-persons', searchParams],
|
|
|
queryFn: async () => {
|
|
queryFn: async () => {
|
|
|
|
|
+ const queryParams: any = {
|
|
|
|
|
+ skip: (searchParams.page - 1) * searchParams.limit,
|
|
|
|
|
+ take: searchParams.limit
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 添加筛选参数
|
|
|
|
|
+ if (searchParams.search) {
|
|
|
|
|
+ queryParams.keyword = searchParams.search;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (searchParams.bankNameId) {
|
|
|
|
|
+ queryParams.bankNameId = searchParams.bankNameId;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (searchParams.cardType) {
|
|
|
|
|
+ queryParams.cardType = searchParams.cardType;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (searchParams.disabilityType) {
|
|
|
|
|
+ queryParams.disabilityType = searchParams.disabilityType;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (searchParams.disabilityLevel) {
|
|
|
|
|
+ queryParams.disabilityLevel = searchParams.disabilityLevel;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (searchParams.province) {
|
|
|
|
|
+ queryParams.province = searchParams.province;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const res = await disabilityClientManager.get().getAllDisabledPersons.$get({
|
|
const res = await disabilityClientManager.get().getAllDisabledPersons.$get({
|
|
|
- query: {
|
|
|
|
|
- skip: (searchParams.page - 1) * searchParams.limit,
|
|
|
|
|
- take: searchParams.limit
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ query: queryParams
|
|
|
});
|
|
});
|
|
|
if (res.status !== 200) throw new Error('获取残疾人列表失败');
|
|
if (res.status !== 200) throw new Error('获取残疾人列表失败');
|
|
|
return await res.json();
|
|
return await res.json();
|
|
@@ -430,6 +461,20 @@ const DisabilityPersonManagement: React.FC = () => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // 重置筛选条件
|
|
|
|
|
+ const handleResetFilters = () => {
|
|
|
|
|
+ setSearchParams({
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ limit: searchParams.limit,
|
|
|
|
|
+ search: '',
|
|
|
|
|
+ bankNameId: undefined,
|
|
|
|
|
+ cardType: undefined,
|
|
|
|
|
+ disabilityType: undefined,
|
|
|
|
|
+ disabilityLevel: undefined,
|
|
|
|
|
+ province: undefined
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<div className="space-y-6">
|
|
<div className="space-y-6">
|
|
|
<Card>
|
|
<Card>
|
|
@@ -439,22 +484,120 @@ const DisabilityPersonManagement: React.FC = () => {
|
|
|
</CardHeader>
|
|
</CardHeader>
|
|
|
<CardContent>
|
|
<CardContent>
|
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center justify-between mb-6">
|
|
|
- <form onSubmit={handleSearch} className="flex items-center space-x-2">
|
|
|
|
|
- <Input
|
|
|
|
|
- placeholder="搜索姓名或身份证号"
|
|
|
|
|
- value={searchParams.search}
|
|
|
|
|
- onChange={(e) => setSearchParams({ ...searchParams, search: e.target.value })}
|
|
|
|
|
- className="w-64"
|
|
|
|
|
- />
|
|
|
|
|
- <Button type="submit" size="sm">
|
|
|
|
|
- <Search className="h-4 w-4 mr-2" />
|
|
|
|
|
- 搜索
|
|
|
|
|
|
|
+ <div className="flex-1">
|
|
|
|
|
+ <form onSubmit={handleSearch} className="flex flex-col space-y-4">
|
|
|
|
|
+ {/* 关键词搜索行 */}
|
|
|
|
|
+ <div className="flex items-center space-x-2">
|
|
|
|
|
+ <Input
|
|
|
|
|
+ placeholder="搜索姓名或身份证号"
|
|
|
|
|
+ value={searchParams.search}
|
|
|
|
|
+ onChange={(e) => setSearchParams({ ...searchParams, search: e.target.value })}
|
|
|
|
|
+ className="w-64"
|
|
|
|
|
+ data-testid="keyword-search-input"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Button type="submit" size="sm">
|
|
|
|
|
+ <Search className="h-4 w-4 mr-2" />
|
|
|
|
|
+ 搜索
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button type="button" variant="outline" size="sm" onClick={handleResetFilters}>
|
|
|
|
|
+ 重置筛选
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 筛选条件行 */}
|
|
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3">
|
|
|
|
|
+ {/* 银行卡类别筛选 */}
|
|
|
|
|
+ <div className="space-y-1">
|
|
|
|
|
+ <Label htmlFor="bank-name-filter" className="text-xs">银行卡类别</Label>
|
|
|
|
|
+ <BankNameSelector
|
|
|
|
|
+ value={searchParams.bankNameId}
|
|
|
|
|
+ onChange={(value) => setSearchParams({ ...searchParams, bankNameId: value, page: 1 })}
|
|
|
|
|
+ placeholder="选择银行"
|
|
|
|
|
+ className="w-full"
|
|
|
|
|
+ testId="bank-name-filter"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 残疾类型筛选 */}
|
|
|
|
|
+ <div className="space-y-1">
|
|
|
|
|
+ <Label htmlFor="disability-type-filter" className="text-xs">残疾类型</Label>
|
|
|
|
|
+ <Select
|
|
|
|
|
+ value={searchParams.disabilityType || 'all'}
|
|
|
|
|
+ onValueChange={(value) => setSearchParams({ ...searchParams, disabilityType: value === 'all' ? undefined : value, page: 1 })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <SelectTrigger id="disability-type-filter" data-testid="disability-type-filter" className="w-full">
|
|
|
|
|
+ <SelectValue placeholder="选择残疾类型" />
|
|
|
|
|
+ </SelectTrigger>
|
|
|
|
|
+ <SelectContent>
|
|
|
|
|
+ <SelectItem value="all">全部</SelectItem>
|
|
|
|
|
+ {DISABILITY_TYPES.map((type) => (
|
|
|
|
|
+ <SelectItem key={type} value={getDisabilityTypeLabel(type)}>
|
|
|
|
|
+ {getDisabilityTypeLabel(type)}
|
|
|
|
|
+ </SelectItem>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </SelectContent>
|
|
|
|
|
+ </Select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 残疾级别筛选 */}
|
|
|
|
|
+ <div className="space-y-1">
|
|
|
|
|
+ <Label htmlFor="disability-level-filter" className="text-xs">残疾级别</Label>
|
|
|
|
|
+ <Select
|
|
|
|
|
+ value={searchParams.disabilityLevel || 'all'}
|
|
|
|
|
+ onValueChange={(value) => setSearchParams({ ...searchParams, disabilityLevel: value === 'all' ? undefined : value, page: 1 })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <SelectTrigger id="disability-level-filter" data-testid="disability-level-filter" className="w-full">
|
|
|
|
|
+ <SelectValue placeholder="选择残疾级别" />
|
|
|
|
|
+ </SelectTrigger>
|
|
|
|
|
+ <SelectContent>
|
|
|
|
|
+ <SelectItem value="all">全部</SelectItem>
|
|
|
|
|
+ {DISABILITY_LEVELS.map((level) => (
|
|
|
|
|
+ <SelectItem key={level} value={getDisabilityLevelLabel(level)}>
|
|
|
|
|
+ {getDisabilityLevelLabel(level)}
|
|
|
|
|
+ </SelectItem>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </SelectContent>
|
|
|
|
|
+ </Select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 居住省份筛选 */}
|
|
|
|
|
+ <div className="space-y-1">
|
|
|
|
|
+ <Label htmlFor="province-filter" className="text-xs">居住省份</Label>
|
|
|
|
|
+ <ProvinceSelect
|
|
|
|
|
+ value={searchParams.province || ''}
|
|
|
|
|
+ onChange={(value) => setSearchParams({ ...searchParams, province: value || undefined, page: 1 })}
|
|
|
|
|
+ placeholder="选择省份"
|
|
|
|
|
+ className="w-full"
|
|
|
|
|
+ data-testid="province-filter"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 银行卡类型筛选 */}
|
|
|
|
|
+ <div className="space-y-1">
|
|
|
|
|
+ <Label htmlFor="card-type-filter" className="text-xs">银行卡类型</Label>
|
|
|
|
|
+ <Select
|
|
|
|
|
+ value={searchParams.cardType || 'all'}
|
|
|
|
|
+ onValueChange={(value) => setSearchParams({ ...searchParams, cardType: value === 'all' ? undefined : value, page: 1 })}
|
|
|
|
|
+ >
|
|
|
|
|
+ <SelectTrigger id="card-type-filter" data-testid="card-type-filter" className="w-full">
|
|
|
|
|
+ <SelectValue placeholder="选择银行卡类型" />
|
|
|
|
|
+ </SelectTrigger>
|
|
|
|
|
+ <SelectContent>
|
|
|
|
|
+ <SelectItem value="all">全部</SelectItem>
|
|
|
|
|
+ <SelectItem value="一类卡">一类卡</SelectItem>
|
|
|
|
|
+ <SelectItem value="二类卡">二类卡</SelectItem>
|
|
|
|
|
+ </SelectContent>
|
|
|
|
|
+ </Select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="ml-4">
|
|
|
|
|
+ <Button onClick={handleCreateOpen} data-testid="add-disabled-person-button">
|
|
|
|
|
+ <Plus className="h-4 w-4 mr-2" />
|
|
|
|
|
+ 新增残疾人
|
|
|
</Button>
|
|
</Button>
|
|
|
- </form>
|
|
|
|
|
- <Button onClick={handleCreateOpen} data-testid="add-disabled-person-button">
|
|
|
|
|
- <Plus className="h-4 w-4 mr-2" />
|
|
|
|
|
- 新增残疾人
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
{isLoading ? (
|
|
{isLoading ? (
|