casualroom/apps/fenghuo/web/components/profile/profile-elite.tsx

194 lines
7.7 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
'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>
);
}