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

194 lines
7.7 KiB
TypeScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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>
);
}