|
@@ -4,13 +4,14 @@ import Taro from '@tarojs/taro'
|
|
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
|
import { YongrenTabBarLayout } from '@/components/YongrenTabBarLayout'
|
|
import { YongrenTabBarLayout } from '@/components/YongrenTabBarLayout'
|
|
|
import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
|
|
import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
|
|
|
-import { ColumnChart, BarChart, PieChart, RingChart } from '@d8d/mini-charts'
|
|
|
|
|
import { enterpriseStatisticsClient } from '@/api/enterpriseStatisticsClient'
|
|
import { enterpriseStatisticsClient } from '@/api/enterpriseStatisticsClient'
|
|
|
import type {
|
|
import type {
|
|
|
EmploymentCountResponse,
|
|
EmploymentCountResponse,
|
|
|
AverageSalaryResponse,
|
|
AverageSalaryResponse,
|
|
|
EmploymentRateResponse
|
|
EmploymentRateResponse
|
|
|
} from '@/types/statisticsTypes'
|
|
} from '@/types/statisticsTypes'
|
|
|
|
|
+import Echarts from 'taro-react-echarts'
|
|
|
|
|
+import echarts from '@/assets/js/echarts.js'
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 类型守卫:检查响应是否为成功的数据响应
|
|
* 类型守卫:检查响应是否为成功的数据响应
|
|
@@ -74,38 +75,9 @@ const mergeProvinceData = (stats: any[]) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 数据转换工具:将API统计数据转换为柱状图格式
|
|
|
|
|
- * 优先使用中文名称的 province,如果是数字ID则从 key 提取
|
|
|
|
|
- * 修复:合并相同省份的数据,人数显示为整数
|
|
|
|
|
|
|
+ * Echarts 柱状图颜色配置
|
|
|
*/
|
|
*/
|
|
|
-const convertToColumnData = (stats: any[]) => {
|
|
|
|
|
- console.debug('[convertToColumnData] Input stats:', JSON.stringify(stats))
|
|
|
|
|
-
|
|
|
|
|
- // 先合并相同省份的数据
|
|
|
|
|
- const mergedStats = mergeProvinceData(stats)
|
|
|
|
|
-
|
|
|
|
|
- const result = {
|
|
|
|
|
- categories: mergedStats.map(item => item.province),
|
|
|
|
|
- series: [{
|
|
|
|
|
- name: '人数',
|
|
|
|
|
- data: mergedStats.map(item => item.value)
|
|
|
|
|
- }]
|
|
|
|
|
- }
|
|
|
|
|
- console.debug('[convertToColumnData] Merged stats:', JSON.stringify(mergedStats))
|
|
|
|
|
- console.debug('[convertToColumnData] Output categories:', result.categories)
|
|
|
|
|
- console.debug('[convertToColumnData] Output series:', result.series)
|
|
|
|
|
- return result
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * 数据转换工具:将API统计数据转换为饼图格式
|
|
|
|
|
- * 修复:人数显示为整数
|
|
|
|
|
- */
|
|
|
|
|
-const convertToPieData = (stats: any[]) =>
|
|
|
|
|
- stats.map(item => ({
|
|
|
|
|
- name: item.key,
|
|
|
|
|
- data: Math.round(item.value || 0)
|
|
|
|
|
- }))
|
|
|
|
|
|
|
+const BAR_COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899']
|
|
|
|
|
|
|
|
export interface StatisticsProps {
|
|
export interface StatisticsProps {
|
|
|
// 组件属性定义(目前为空)
|
|
// 组件属性定义(目前为空)
|
|
@@ -279,6 +251,192 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
gcTime: 10 * 60 * 1000 // 缓存时间10分钟
|
|
gcTime: 10 * 60 * 1000 // 缓存时间10分钟
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 渲染柱状图(垂直)
|
|
|
|
|
+ */
|
|
|
|
|
+ const renderBarChart = (stats: any[]) => {
|
|
|
|
|
+ const mergedStats = mergeProvinceData(stats)
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Echarts
|
|
|
|
|
+ echarts={echarts}
|
|
|
|
|
+ option={{
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: mergedStats.map(item => item.province),
|
|
|
|
|
+ axisLabel: {
|
|
|
|
|
+ interval: 0,
|
|
|
|
|
+ rotate: 30
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ minInterval: 1
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '人数',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: mergedStats.map(item => item.value),
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#3b82f6'
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ position: 'top',
|
|
|
|
|
+ formatter: '{c}'
|
|
|
|
|
+ }
|
|
|
|
|
+ }]
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ height: '280px' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 渲染横向柱状图
|
|
|
|
|
+ */
|
|
|
|
|
+ const renderHorizontalBarChart = (stats: any[]) => {
|
|
|
|
|
+ const mergedStats = mergeProvinceData(stats)
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Echarts
|
|
|
|
|
+ echarts={echarts}
|
|
|
|
|
+ option={{
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ minInterval: 1
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: mergedStats.map(item => item.province)
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '人数',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: mergedStats.map(item => item.value),
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: (params: any) => BAR_COLORS[params.dataIndex % BAR_COLORS.length]
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ position: 'right',
|
|
|
|
|
+ formatter: '{c}'
|
|
|
|
|
+ }
|
|
|
|
|
+ }]
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ height: `${Math.max(280, mergedStats.length * 50)}px` }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 渲染饼图
|
|
|
|
|
+ */
|
|
|
|
|
+ const renderPieChart = (stats: any[]) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Echarts
|
|
|
|
|
+ echarts={echarts}
|
|
|
|
|
+ option={{
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item',
|
|
|
|
|
+ formatter: '{b}: {c} ({d}%)'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ orient: 'vertical',
|
|
|
|
|
+ right: 10,
|
|
|
|
|
+ top: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '人数',
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: '60%',
|
|
|
|
|
+ center: ['35%', '50%'],
|
|
|
|
|
+ data: stats.map(item => ({
|
|
|
|
|
+ name: item.key,
|
|
|
|
|
+ value: Math.round(item.value || 0)
|
|
|
|
|
+ })),
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ shadowBlur: 10,
|
|
|
|
|
+ shadowOffsetX: 0,
|
|
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ formatter: '{b}: {c}'
|
|
|
|
|
+ }
|
|
|
|
|
+ }]
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ height: '280px' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 渲染环形图
|
|
|
|
|
+ */
|
|
|
|
|
+ const renderDoughnutChart = (stats: any[]) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Echarts
|
|
|
|
|
+ echarts={echarts}
|
|
|
|
|
+ option={{
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item',
|
|
|
|
|
+ formatter: '{b}: {c} ({d}%)'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ orient: 'vertical',
|
|
|
|
|
+ right: 10,
|
|
|
|
|
+ top: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '人数',
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: ['40%', '70%'],
|
|
|
|
|
+ center: ['35%', '50%'],
|
|
|
|
|
+ data: stats.map(item => ({
|
|
|
|
|
+ name: item.key,
|
|
|
|
|
+ value: Math.round(item.value || 0)
|
|
|
|
|
+ })),
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ shadowBlur: 10,
|
|
|
|
|
+ shadowOffsetX: 0,
|
|
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ formatter: '{b}: {c}'
|
|
|
|
|
+ }
|
|
|
|
|
+ }]
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ height: '280px' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<YongrenTabBarLayout activeKey="statistics">
|
|
<YongrenTabBarLayout activeKey="statistics">
|
|
|
<ScrollView
|
|
<ScrollView
|
|
@@ -351,30 +509,11 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
const stats = getStats(disabilityData)
|
|
const stats = getStats(disabilityData)
|
|
|
- if (stats.length > 0) {
|
|
|
|
|
- const chartData = convertToColumnData(stats)
|
|
|
|
|
- return (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <ColumnChart
|
|
|
|
|
- canvasId="disability-type-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- categories={chartData.categories}
|
|
|
|
|
- series={chartData.series}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- yAxis: {
|
|
|
|
|
- min: 0,
|
|
|
|
|
- format: (val: number) => Number.isInteger(val) ? val.toString() : '',
|
|
|
|
|
- },
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- )
|
|
|
|
|
- } else {
|
|
|
|
|
- return <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return stats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderBarChart(stats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
})()}
|
|
})()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
@@ -384,32 +523,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
{isLoadingGender ? (
|
|
{isLoadingGender ? (
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
- const genderStats = getStats(genderData)
|
|
|
|
|
- return genderStats.length > 0 ? (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <ColumnChart
|
|
|
|
|
- canvasId="gender-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- categories={genderStats.map(s => s.key)}
|
|
|
|
|
- series={[{
|
|
|
|
|
- name: '人数',
|
|
|
|
|
- data: genderStats.map(s => s.value || 0)
|
|
|
|
|
- }]}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6', '#ec4899'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- yAxis: {
|
|
|
|
|
- min: 0,
|
|
|
|
|
- format: (val: number) => Number.isInteger(val) ? val.toString() : '',
|
|
|
|
|
- },
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- ) : (
|
|
|
|
|
- <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
- )
|
|
|
|
|
- })()}
|
|
|
|
|
|
|
+ const genderStats = getStats(genderData)
|
|
|
|
|
+ return genderStats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderBarChart(genderStats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
|
|
+ })()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
{/* 年龄分布 */}
|
|
{/* 年龄分布 */}
|
|
@@ -418,36 +538,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
{isLoadingAge ? (
|
|
{isLoadingAge ? (
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
- const ageStats = getStats(ageData)
|
|
|
|
|
- return ageStats.length > 0 ? (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <PieChart
|
|
|
|
|
- canvasId="age-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- series={convertToPieData(ageStats)}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- extra: {
|
|
|
|
|
- pie: {
|
|
|
|
|
- activeRadius: 15,
|
|
|
|
|
- labelWidth: 18,
|
|
|
|
|
- borderWidth: 2,
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- legend: {
|
|
|
|
|
- show: true,
|
|
|
|
|
- position: "right",
|
|
|
|
|
- lineHeight: 22
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- ) : (
|
|
|
|
|
- <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
- )
|
|
|
|
|
- })()}
|
|
|
|
|
|
|
+ const ageStats = getStats(ageData)
|
|
|
|
|
+ return ageStats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderPieChart(ageStats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
|
|
+ })()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
{/* 户籍省份分布 */}
|
|
{/* 户籍省份分布 */}
|
|
@@ -456,52 +553,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
{isLoadingHousehold ? (
|
|
{isLoadingHousehold ? (
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
- const stats = getStats(householdData)
|
|
|
|
|
- // 详细调试信息
|
|
|
|
|
- console.log('📊 [户籍省份分布] 原始 API 数据:', JSON.stringify(householdData, null, 2))
|
|
|
|
|
- console.log('📊 [户籍省份分布] stats 数组:', JSON.stringify(stats, null, 2))
|
|
|
|
|
- if (stats.length > 0) {
|
|
|
|
|
- const chartData = convertToColumnData(stats)
|
|
|
|
|
- console.log('📊 [户籍省份分布] 转换后的 categories:', chartData.categories)
|
|
|
|
|
- console.log('📊 [户籍省份分布] 转换后的 series:', JSON.stringify(chartData.series, null, 2))
|
|
|
|
|
- // 检查每个 stat 项的 province 值
|
|
|
|
|
- stats.forEach((item, index) => {
|
|
|
|
|
- console.log(`📊 [户籍省份分布] stat[${index}]:`, {
|
|
|
|
|
- key: item.key,
|
|
|
|
|
- province: item.province,
|
|
|
|
|
- isNumericProvince: item.province ? /^\d+$/.test(item.province) : 'N/A'
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- return (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <BarChart
|
|
|
|
|
- canvasId="household-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- categories={chartData.categories}
|
|
|
|
|
- series={chartData.series}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- xAxis: {
|
|
|
|
|
- disableGrid: true,
|
|
|
|
|
- tofix: 0, // X 轴显示整数(人数)
|
|
|
|
|
- splitNumber: 1, // 只生成 2 个刻度(min 和 max)
|
|
|
|
|
- min: 0, // 确保 X 轴从 0 开始,让柱状图正常显示
|
|
|
|
|
- },
|
|
|
|
|
- extra: {
|
|
|
|
|
- bar: {
|
|
|
|
|
- width: 45,
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- )
|
|
|
|
|
- } else {
|
|
|
|
|
- return <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
|
|
|
|
|
- }
|
|
|
|
|
- })()}
|
|
|
|
|
|
|
+ const stats = getStats(householdData)
|
|
|
|
|
+ return stats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderHorizontalBarChart(stats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4 mt-3">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
|
|
+ })()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
{/* 在职状态统计 */}
|
|
{/* 在职状态统计 */}
|
|
@@ -510,38 +568,13 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
{isLoadingJobStatus ? (
|
|
{isLoadingJobStatus ? (
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
- const stats = getStats(jobStatusData)
|
|
|
|
|
- if (stats.length > 0) {
|
|
|
|
|
- return (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <RingChart
|
|
|
|
|
- canvasId="job-status-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- ringWidth={0.75}
|
|
|
|
|
- series={convertToPieData(stats)}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6', '#f59e0b', '#ef4444', '#10b981'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- legend: {
|
|
|
|
|
- show: true,
|
|
|
|
|
- position: "right",
|
|
|
|
|
- lineHeight: 25
|
|
|
|
|
- },
|
|
|
|
|
- extra: {
|
|
|
|
|
- ring: {
|
|
|
|
|
- activeRadius: 15,
|
|
|
|
|
- labelWidth: 18,
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- )
|
|
|
|
|
- } else {
|
|
|
|
|
- return <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
- }
|
|
|
|
|
- })()}
|
|
|
|
|
|
|
+ const stats = getStats(jobStatusData)
|
|
|
|
|
+ return stats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderDoughnutChart(stats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
|
|
+ })()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
{/* 薪资分布 */}
|
|
{/* 薪资分布 */}
|
|
@@ -550,65 +583,15 @@ const Statistics: React.FC<StatisticsProps> = () => {
|
|
|
{isLoadingSalary ? (
|
|
{isLoadingSalary ? (
|
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
<Text className="text-gray-500 text-center py-4">加载中...</Text>
|
|
|
) : (() => {
|
|
) : (() => {
|
|
|
- const stats = getStats(salaryData)
|
|
|
|
|
- if (stats.length > 0) {
|
|
|
|
|
- const chartData = convertToColumnData(stats)
|
|
|
|
|
- return (
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <BarChart
|
|
|
|
|
- canvasId="salary-chart"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={320}
|
|
|
|
|
- categories={chartData.categories}
|
|
|
|
|
- series={chartData.series}
|
|
|
|
|
- config={{
|
|
|
|
|
- color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
|
|
|
|
|
- dataLabel: true,
|
|
|
|
|
- xAxis: {
|
|
|
|
|
- disableGrid: true,
|
|
|
|
|
- tofix: 0, // X 轴显示整数(人数)
|
|
|
|
|
- splitNumber: 1, // 只生成 2 个刻度(min 和 max)
|
|
|
|
|
- min: 0, // 确保 X 轴从 0 开始,让柱状图正常显示
|
|
|
|
|
- },
|
|
|
|
|
- extra: {
|
|
|
|
|
- bar: {
|
|
|
|
|
- width: 50,
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- )
|
|
|
|
|
- } else {
|
|
|
|
|
- return <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
- }
|
|
|
|
|
- })()}
|
|
|
|
|
|
|
+ const stats = getStats(salaryData)
|
|
|
|
|
+ return stats.length > 0 ? (
|
|
|
|
|
+ <View className="mt-3">{renderHorizontalBarChart(stats)}</View>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Text className="text-gray-500 text-center py-4">暂无数据</Text>
|
|
|
|
|
+ )
|
|
|
|
|
+ })()}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
|
|
|
- {/* PieChartFCExample 测试组件 */}
|
|
|
|
|
- {/* <View className="card bg-white p-4 mb-4 rounded-lg shadow-sm flex flex-col">
|
|
|
|
|
- <Text className="font-semibold text-gray-700">饼图示例测试 (PieChartFCExample)</Text>
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <PieChartFCExample
|
|
|
|
|
- canvasId="pie-chart-fc-example-test"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={400}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- </View> */}
|
|
|
|
|
-
|
|
|
|
|
- {/* RingChartFCExample 测试组件 */}
|
|
|
|
|
- {/* <View className="card bg-white p-4 mb-4 rounded-lg shadow-sm flex flex-col">
|
|
|
|
|
- <Text className="font-semibold text-gray-700">环形图示例测试 (RingChartFCExample)</Text>
|
|
|
|
|
- <View className="mt-3">
|
|
|
|
|
- <RingChartFCExample
|
|
|
|
|
- canvasId="ring-chart-fc-example-test"
|
|
|
|
|
- width={650}
|
|
|
|
|
- height={400}
|
|
|
|
|
- />
|
|
|
|
|
- </View>
|
|
|
|
|
- </View> */}
|
|
|
|
|
-
|
|
|
|
|
</ScrollView>
|
|
</ScrollView>
|
|
|
</YongrenTabBarLayout>
|
|
</YongrenTabBarLayout>
|
|
|
)
|
|
)
|