|
|
@@ -18,16 +18,8 @@ export interface StatisticsProps {
|
|
|
}
|
|
|
|
|
|
const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
- // 状态:选中的残疾类型
|
|
|
- const [selectedDisabilityType, setSelectedDisabilityType] = useState<any>(null)
|
|
|
- // 状态:时间筛选(年-月)
|
|
|
+ // 状态:时间筛选(年-月)- 静态占位符
|
|
|
const [timeFilter, setTimeFilter] = useState({ year: 2023, month: 11 })
|
|
|
- // 状态:部门筛选(占位符)
|
|
|
- const [departmentFilter, setDepartmentFilter] = useState<string>('')
|
|
|
- // 状态:下钻省份(户籍分布)
|
|
|
- const [drillDownProvince, setDrillDownProvince] = useState<string | null>(null)
|
|
|
- // 状态:图表类型切换
|
|
|
- const [chartType, setChartType] = useState<'bar' | 'pie'>('bar')
|
|
|
// 状态:图表懒加载控制 - 哪些图表已经加载
|
|
|
const [loadedCharts, setLoadedCharts] = useState<Set<string>>(new Set(['disability', 'gender'])) // 默认加载前两个关键图表
|
|
|
|
|
|
@@ -57,72 +49,12 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
}
|
|
|
}, [])
|
|
|
|
|
|
- // 处理残疾类型图表点击
|
|
|
- const handleDisabilityTypeClick = (item: any) => {
|
|
|
- setSelectedDisabilityType(item)
|
|
|
- // 在实际应用中,这里可以显示模态框或跳转到详情页
|
|
|
- console.log('点击残疾类型:', item)
|
|
|
- }
|
|
|
-
|
|
|
- // 处理时间筛选变化
|
|
|
+ // 处理时间筛选变化(静态占位符)
|
|
|
const handleTimeFilterChange = (newYear: number, newMonth: number) => {
|
|
|
setTimeFilter({ year: newYear, month: newMonth })
|
|
|
- // 注意:当前API不支持时间筛选参数,此处仅为前端交互演示
|
|
|
console.log('时间筛选变更:', newYear, '年', newMonth, '月')
|
|
|
}
|
|
|
|
|
|
- // 处理部门筛选变化
|
|
|
- const handleDepartmentFilterChange = (department: string) => {
|
|
|
- setDepartmentFilter(department)
|
|
|
- // 注意:当前API不支持部门筛选参数,此处仅为前端交互演示
|
|
|
- console.log('部门筛选变更:', department)
|
|
|
- }
|
|
|
-
|
|
|
- // 处理省份点击(下钻功能)
|
|
|
- const handleProvinceClick = (province: string) => {
|
|
|
- setDrillDownProvince(province)
|
|
|
- console.log('下钻省份:', province)
|
|
|
- }
|
|
|
-
|
|
|
- // 处理返回省份列表
|
|
|
- const handleBackToProvinces = () => {
|
|
|
- setDrillDownProvince(null)
|
|
|
- }
|
|
|
-
|
|
|
- // 处理图表类型切换
|
|
|
- const handleChartTypeToggle = () => {
|
|
|
- setChartType(chartType === 'bar' ? 'pie' : 'bar')
|
|
|
- }
|
|
|
-
|
|
|
- // 模拟城市数据(下钻演示)
|
|
|
- const getMockCityData = (province: string) => {
|
|
|
- const mockData: Record<string, Array<{key: string, value: number, percentage: number}>> = {
|
|
|
- '江苏省': [
|
|
|
- { key: '南京市', value: 15, percentage: 30 },
|
|
|
- { key: '苏州市', value: 12, percentage: 24 },
|
|
|
- { key: '无锡市', value: 8, percentage: 16 },
|
|
|
- { key: '常州市', value: 6, percentage: 12 },
|
|
|
- { key: '其他', value: 9, percentage: 18 }
|
|
|
- ],
|
|
|
- '浙江省': [
|
|
|
- { key: '杭州市', value: 18, percentage: 36 },
|
|
|
- { key: '宁波市', value: 10, percentage: 20 },
|
|
|
- { key: '温州市', value: 7, percentage: 14 },
|
|
|
- { key: '其他', value: 15, percentage: 30 }
|
|
|
- ],
|
|
|
- '广东省': [
|
|
|
- { key: '广州市', value: 22, percentage: 44 },
|
|
|
- { key: '深圳市', value: 18, percentage: 36 },
|
|
|
- { key: '其他', value: 10, percentage: 20 }
|
|
|
- ]
|
|
|
- }
|
|
|
- return mockData[province] || [
|
|
|
- { key: '城市A', value: 10, percentage: 40 },
|
|
|
- { key: '城市B', value: 8, percentage: 32 },
|
|
|
- { key: '其他', value: 7, percentage: 28 }
|
|
|
- ]
|
|
|
- }
|
|
|
-
|
|
|
// 获取残疾类型分布数据
|
|
|
const { data: disabilityData, isLoading: isLoadingDisability } = useQuery({
|
|
|
queryKey: ['statistics', 'disability-type-distribution'],
|
|
|
@@ -216,25 +148,12 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
placeholder={true}
|
|
|
/>
|
|
|
|
|
|
- {/* 数据筛选区域 */}
|
|
|
+ {/* 数据筛选区域 - 对应原型第880-886行 */}
|
|
|
<View className="mb-4 pt-4">
|
|
|
<View className="flex justify-between items-center mb-3">
|
|
|
<Text className="font-semibold text-gray-700">数据统计</Text>
|
|
|
- <View className="flex items-center space-x-2">
|
|
|
- <View
|
|
|
- className="flex items-center bg-blue-50 rounded-lg px-3 py-1 active:bg-blue-100"
|
|
|
- onClick={() => {
|
|
|
- // 数据导出功能演示
|
|
|
- console.log('导出数据')
|
|
|
- // 在实际应用中,这里可以触发数据导出
|
|
|
- alert('数据导出功能演示:此功能需要API支持才能导出实际数据')
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text className="text-sm text-blue-600 mr-1">导出数据</Text>
|
|
|
- <Text className="fas fa-download text-blue-500 text-xs"></Text>
|
|
|
- </View>
|
|
|
<View
|
|
|
- className="flex items-center bg-gray-100 rounded-lg px-3 py-1 active:bg-gray-200"
|
|
|
+ className="flex items-center bg-gray-100 rounded-lg px-3 py-1"
|
|
|
onClick={() => {
|
|
|
// 简单的时间选择器交互演示
|
|
|
const newMonth = timeFilter.month === 11 ? 12 : 11
|
|
|
@@ -245,53 +164,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
<Text className="fas fa-chevron-down text-gray-500"></Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
- </View>
|
|
|
-
|
|
|
- {/* 部门筛选器(占位符) */}
|
|
|
- <View className="flex items-center bg-gray-50 rounded-lg px-3 py-2">
|
|
|
- <Text className="text-sm text-gray-600 mr-3">部门筛选:</Text>
|
|
|
- <View className="flex space-x-2">
|
|
|
- {['全部', '技术部', '市场部', '人力资源部'].map((dept) => (
|
|
|
- <View
|
|
|
- key={dept}
|
|
|
- className={`px-3 py-1 rounded-full text-sm ${departmentFilter === dept ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'}`}
|
|
|
- onClick={() => handleDepartmentFilterChange(dept === '全部' ? '' : dept)}
|
|
|
- >
|
|
|
- <Text>{dept}</Text>
|
|
|
- </View>
|
|
|
- ))}
|
|
|
- </View>
|
|
|
- </View>
|
|
|
-
|
|
|
- {/* 筛选状态提示 */}
|
|
|
- {(departmentFilter || timeFilter.month !== 11 || timeFilter.year !== 2023) && (
|
|
|
- <View className="mt-2 p-2 bg-blue-50 rounded-lg">
|
|
|
- <Text className="text-xs text-blue-700">
|
|
|
- 当前筛选:{timeFilter.year}年{timeFilter.month}月
|
|
|
- {departmentFilter && ` | 部门:${departmentFilter}`}
|
|
|
- (注:当前API不支持筛选参数,仅前端交互演示)
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- )}
|
|
|
- </View>
|
|
|
-
|
|
|
- {/* 图表类型切换 */}
|
|
|
- <View className="flex justify-end items-center mb-3">
|
|
|
- <Text className="text-sm text-gray-600 mr-2">图表类型:</Text>
|
|
|
- <View className="flex bg-gray-100 rounded-lg p-1">
|
|
|
- <View
|
|
|
- className={`px-3 py-1 rounded-md ${chartType === 'bar' ? 'bg-white shadow-sm' : ''}`}
|
|
|
- onClick={() => setChartType('bar')}
|
|
|
- >
|
|
|
- <Text className={`text-sm ${chartType === 'bar' ? 'text-blue-600 font-medium' : 'text-gray-600'}`}>柱状图</Text>
|
|
|
- </View>
|
|
|
- <View
|
|
|
- className={`px-3 py-1 rounded-md ${chartType === 'pie' ? 'bg-white shadow-sm' : ''}`}
|
|
|
- onClick={() => setChartType('pie')}
|
|
|
- >
|
|
|
- <Text className={`text-sm ${chartType === 'pie' ? 'text-blue-600 font-medium' : 'text-gray-600'}`}>饼图</Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
</View>
|
|
|
|
|
|
{/* 统计卡片 */}
|
|
|
@@ -337,9 +209,8 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
return (
|
|
|
<View
|
|
|
key={item.key}
|
|
|
- className="chart-bar absolute bottom-0 bg-blue-500 rounded-t-lg active:bg-blue-600 touch-manipulation"
|
|
|
+ className="chart-bar absolute bottom-0 bg-blue-500 rounded-t-lg"
|
|
|
style={{ left: `${left}px`, height: `${height}px`, width: '30px', minHeight: '8px' }}
|
|
|
- onClick={() => handleDisabilityTypeClick(item)}
|
|
|
/>
|
|
|
)
|
|
|
})}
|
|
|
@@ -352,26 +223,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
</View>
|
|
|
))}
|
|
|
</View>
|
|
|
- {/* 数据表格展示 */}
|
|
|
- <View className="mt-4 border-t pt-3">
|
|
|
- <Text className="font-medium text-gray-700 mb-2">详细数据表格</Text>
|
|
|
- <View className="overflow-x-auto">
|
|
|
- <View className="min-w-full">
|
|
|
- <View className="flex border-b py-2">
|
|
|
- <Text className="flex-1 font-medium text-gray-600">残疾类型</Text>
|
|
|
- <Text className="flex-1 font-medium text-gray-600">人数</Text>
|
|
|
- <Text className="flex-1 font-medium text-gray-600">百分比</Text>
|
|
|
- </View>
|
|
|
- {stats.map((item: any) => (
|
|
|
- <View key={item.key} className="flex border-b py-2">
|
|
|
- <Text className="flex-1 text-gray-800">{item.key}</Text>
|
|
|
- <Text className="flex-1 text-gray-600">{item.value}人</Text>
|
|
|
- <Text className="flex-1 text-gray-600">{item.percentage}%</Text>
|
|
|
- </View>
|
|
|
- ))}
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
</>
|
|
|
)
|
|
|
} else {
|
|
|
@@ -381,45 +232,6 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
)}
|
|
|
</View>
|
|
|
|
|
|
- {/* 选中的残疾类型详情 */}
|
|
|
- {selectedDisabilityType && (
|
|
|
- <View className="card bg-blue-50 p-4 mb-4 rounded-lg border border-blue-200">
|
|
|
- <View className="flex justify-between items-center mb-2">
|
|
|
- <Text className="font-semibold text-blue-800">选中的残疾类型详情</Text>
|
|
|
- <View
|
|
|
- className="w-6 h-6 rounded-full bg-blue-100 flex items-center justify-center"
|
|
|
- onClick={() => setSelectedDisabilityType(null)}
|
|
|
- >
|
|
|
- <Text className="text-blue-500 text-xs">×</Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- <View className="grid grid-cols-2 gap-3">
|
|
|
- <View>
|
|
|
- <Text className="text-sm text-gray-600">残疾类型</Text>
|
|
|
- <Text className="font-medium text-gray-800">{selectedDisabilityType.key}</Text>
|
|
|
- </View>
|
|
|
- <View>
|
|
|
- <Text className="text-sm text-gray-600">人数</Text>
|
|
|
- <Text className="font-medium text-gray-800">{selectedDisabilityType.value}人</Text>
|
|
|
- </View>
|
|
|
- <View>
|
|
|
- <Text className="text-sm text-gray-600">百分比</Text>
|
|
|
- <Text className="font-medium text-gray-800">{selectedDisabilityType.percentage}%</Text>
|
|
|
- </View>
|
|
|
- <View>
|
|
|
- <Text className="text-sm text-gray-600">占比说明</Text>
|
|
|
- <Text className="font-medium text-gray-800">
|
|
|
- {selectedDisabilityType.percentage >= 50 ? '主要残疾类型' :
|
|
|
- selectedDisabilityType.percentage >= 20 ? '常见残疾类型' : '少数残疾类型'}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- <Text className="text-xs text-blue-600 mt-2">
|
|
|
- 提示:点击其他图表项可查看详情,点击×关闭
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- )}
|
|
|
-
|
|
|
{/* 性别分布 */}
|
|
|
<View className="card bg-white p-4 mb-4 rounded-lg shadow-sm">
|
|
|
<Text className="font-semibold text-gray-700 mb-3">性别分布</Text>
|
|
|
@@ -437,7 +249,7 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
<View key={item.key} className="bar-container flex flex-col items-center">
|
|
|
<Text className="bar-value text-sm font-semibold mb-1">{item.value}人</Text>
|
|
|
<View
|
|
|
- className="bar rounded-t-lg active:opacity-80 touch-manipulation"
|
|
|
+ className="bar rounded-t-lg"
|
|
|
style={{ height: `${height}px`, width: '40px', backgroundColor: color, minHeight: '4px' }}
|
|
|
/>
|
|
|
<Text className="bar-label text-xs text-gray-500 mt-2">
|