194 lines
7.7 KiB
TypeScript
194 lines
7.7 KiB
TypeScript
'use client';
|
||
|
||
import * as React from 'react';
|
||
import { useQuery } from '@tanstack/react-query';
|
||
import { useTRPC, useTRPCClient } from '@fenghuo/client';
|
||
import { EliteDataTable } from './elite-data-table';
|
||
import { EliteSheet } from './elite-sheet';
|
||
import { useProfile } from './profile-provider';
|
||
import { toast } from '@nice/ui/components/sonner';
|
||
import { exportEliteFormToExcel } from '@/lib/profile/utils';;
|
||
import type { RouterOutputs } from '@fenghuo/client';
|
||
|
||
type ExportEliteFormResult = RouterOutputs['profile']['findElite'];
|
||
|
||
export function ProfileElite() {
|
||
const trpc = useTRPC();
|
||
const trpcClient = useTRPCClient();
|
||
const { handleViewDetail, handleAddEmployee } = useProfile();
|
||
|
||
// Sheet 状态管理 - 修改状态结构
|
||
const [sheetOpen, setSheetOpen] = React.useState(false);
|
||
const [sheetTitle, setSheetTitle] = React.useState<string>('');
|
||
const [sheetProfessionId, setSheetProfessionId] = React.useState<string | undefined>();
|
||
const [sheetStationId, setSheetStationId] = React.useState<string | undefined>();
|
||
|
||
// 筛选状态
|
||
const [selectedProfessionIds, setSelectedProfessionIds] = React.useState<string[]>([]);
|
||
const [selectedStationIds, setSelectedStationIds] = React.useState<string[]>([]);
|
||
const [selectedDutyLevels, setSelectedDutyLevels] = React.useState<number[]>([]);
|
||
const [searchKeyword, setSearchKeyword] = React.useState<string>('');
|
||
|
||
// 分页状态
|
||
const [currentPage, setCurrentPage] = React.useState(1);
|
||
const [pageSize, setPageSize] = React.useState(5);
|
||
|
||
// 导出状态
|
||
const [isExporting, setIsExporting] = React.useState(false);
|
||
|
||
// 使用tRPC调用findElite获取数据,传入筛选和分页参数
|
||
const { data: eliteData, isLoading, error } = useQuery({
|
||
...trpc.profile.findElite.queryOptions({
|
||
professionIds: selectedProfessionIds.length > 0 ? selectedProfessionIds : undefined,
|
||
stationIds: selectedStationIds.length > 0 ? selectedStationIds : undefined,
|
||
dutyLevels: selectedDutyLevels.length > 0 ? selectedDutyLevels : undefined,
|
||
searchKeyword: searchKeyword.trim() || undefined,
|
||
page: currentPage,
|
||
pageSize: pageSize,
|
||
}),
|
||
});
|
||
|
||
// 当筛选条件改变时,重置到第一页
|
||
React.useEffect(() => {
|
||
setCurrentPage(1);
|
||
}, [selectedProfessionIds, selectedStationIds, selectedDutyLevels, searchKeyword]);
|
||
|
||
// 处理查看详情的点击事件
|
||
const handleViewPersonDetail = (personId: string) => {
|
||
handleViewDetail(personId);
|
||
// setSheetOpen(false);
|
||
};
|
||
|
||
// 处理专业点击事件 - 修改为使用专业ID
|
||
const handleProfessionClick = (professionName: string, professionId: string) => {
|
||
setSheetTitle(professionName);
|
||
setSheetProfessionId(professionId);
|
||
setSheetStationId(undefined); // 清除台站ID
|
||
setSheetOpen(true);
|
||
};
|
||
|
||
// 处理台站点击事件 - 新增
|
||
const handleStationClick = (professionName: string, stationId: string, professionId: string) => {
|
||
setSheetTitle(professionName);
|
||
setSheetProfessionId(professionId);
|
||
setSheetStationId(stationId);
|
||
setSheetOpen(true);
|
||
};
|
||
|
||
// 处理分页变化
|
||
const handlePageChange = (page: number) => {
|
||
setCurrentPage(page);
|
||
};
|
||
|
||
// 处理每页大小变化
|
||
const handlePageSizeChange = (newPageSize: number) => {
|
||
setPageSize(newPageSize);
|
||
setCurrentPage(1); // 重置到第一页
|
||
};
|
||
|
||
// 处理导出全部数据
|
||
const handleExportTable = async () => {
|
||
if (isExporting) return;
|
||
setIsExporting(true);
|
||
toast.loading('正在导出表格...', { id: 'export-all-loading' });
|
||
|
||
try {
|
||
// 使用专门的导出接口获取所有数据
|
||
const result: ExportEliteFormResult = await trpcClient.profile.findElite.query({
|
||
page: 1,
|
||
pageSize: 1000
|
||
});
|
||
|
||
// 使用前端工具函数导出 Excel
|
||
await exportEliteFormToExcel(result.data, result.columns);
|
||
|
||
toast.success(`导出全部数据成功`, { id: 'export-all-loading' });
|
||
} catch (error: any) {
|
||
toast.error(`导出失败: ${error.message}`, { id: 'export-all-loading' });
|
||
} finally {
|
||
setIsExporting(false);
|
||
}
|
||
};
|
||
|
||
const handleExportFilteredTable = async () => {
|
||
if (isExporting) return;
|
||
setIsExporting(true);
|
||
toast.loading('正在导出表格...', { id: 'export-filtered-loading' });
|
||
|
||
try {
|
||
// 使用专门的导出接口获取所有数据
|
||
const result: ExportEliteFormResult = await trpcClient.profile.findElite.query({
|
||
page: 1,
|
||
pageSize: 1000,
|
||
professionIds: selectedProfessionIds.length > 0 ? selectedProfessionIds : undefined,
|
||
stationIds: selectedStationIds.length > 0 ? selectedStationIds : undefined,
|
||
dutyLevels: selectedDutyLevels.length > 0 ? selectedDutyLevels : undefined,
|
||
searchKeyword: searchKeyword.trim() || undefined
|
||
});
|
||
|
||
// 使用前端工具函数导出 Excel
|
||
await exportEliteFormToExcel(result.data, result.columns);
|
||
|
||
toast.success(`导出筛选数据成功`, { id: 'export-filtered-loading' });
|
||
} catch (error: any) {
|
||
toast.error(`导出失败: ${error.message}`, { id: 'export-filtered-loading' });
|
||
} finally {
|
||
setIsExporting(false);
|
||
}
|
||
}
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="flex items-center justify-center h-64">
|
||
<div className="text-center">
|
||
<p className="text-red-500 mb-2">加载失败</p>
|
||
<p className="text-sm text-muted-foreground">{error.message}</p>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<EliteDataTable
|
||
data={eliteData?.data || []}
|
||
isLoading={isLoading}
|
||
onViewDetail={handleViewPersonDetail}
|
||
onProfessionClick={handleProfessionClick}
|
||
onStationClick={handleStationClick} // 新增台站点击处理
|
||
onAddEmployee={handleAddEmployee}
|
||
onExportTable={handleExportTable}
|
||
onExportFilteredTable={handleExportFilteredTable}
|
||
isExporting={isExporting}
|
||
// 筛选相关props
|
||
selectedProfessionIds={selectedProfessionIds}
|
||
onProfessionIdsChange={setSelectedProfessionIds}
|
||
selectedStationIds={selectedStationIds}
|
||
onStationIdsChange={setSelectedStationIds}
|
||
selectedDutyLevels={selectedDutyLevels}
|
||
onDutyLevelsChange={setSelectedDutyLevels}
|
||
// 搜索相关props
|
||
searchKeyword={searchKeyword}
|
||
onSearchKeywordChange={setSearchKeyword}
|
||
// 分页相关props
|
||
currentPage={eliteData?.currentPage || 1}
|
||
totalPages={eliteData?.totalPages || 1}
|
||
totalCount={eliteData?.totalCount || 0}
|
||
pageSize={eliteData?.pageSize || 10}
|
||
hasNextPage={eliteData?.hasNextPage || false}
|
||
hasPreviousPage={eliteData?.hasPreviousPage || false}
|
||
onPageChange={handlePageChange}
|
||
onPageSizeChange={handlePageSizeChange}
|
||
/>
|
||
|
||
<EliteSheet
|
||
open={sheetOpen}
|
||
onOpenChange={setSheetOpen}
|
||
title={sheetTitle}
|
||
professionId={sheetProfessionId}
|
||
stationId={sheetStationId}
|
||
onViewDetail={handleViewPersonDetail}
|
||
/>
|
||
</div>
|
||
);
|
||
} |