Files
YunNanProject/Routes/BigScreen.py

214 lines
7.4 KiB
Python
Raw Normal View History

2025-09-10 15:07:50 +08:00
from fastapi import APIRouter
2025-09-10 15:11:25 +08:00
import pyecharts
from pyecharts import options as opts
2025-09-10 15:21:56 +08:00
from pyecharts.charts import Bar, Line
2025-09-10 15:11:25 +08:00
from pyecharts.faker import Faker
from pyecharts.globals import CurrentConfig
import json
2025-09-10 15:21:56 +08:00
import os
2025-09-10 15:07:50 +08:00
# 创建 APIRouter 实例
router = APIRouter(prefix="/bigscreen", tags=["大屏展示"])
2025-09-10 15:11:25 +08:00
# 配置使用自定义的 ECharts 路径
CurrentConfig.ONLINE_HOST = "https://gcore.jsdelivr.net/npm/echarts@6.0.0/dist/"
2025-09-10 15:07:50 +08:00
# 定义一个 helloWorld 路由
2025-09-10 15:21:56 +08:00
@router.get("/")
async def root():
return {"message": "Welcome to YunNan Education World!"}
2025-09-10 15:07:50 +08:00
2025-09-10 15:11:25 +08:00
# 生成图表配置的函数
def generate_bar_chart_config():
c = (
Bar()
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="Bar-MarkLine自定义"))
.set_series_opts(
label_opts=opts.LabelOpts(is_show=False),
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(y=50, name="yAxis=50")]
),
)
)
# 获取图表的选项配置,使用 dump_options_with_quotes 方法获取可以直接序列化的选项
options_str = c.dump_options_with_quotes()
# 将字符串转换为 JSON 对象
options_json = json.loads(options_str)
return options_json
# 定义一个返回图表配置的路由
@router.get("/chart/bar")
async def get_bar_chart_config():
"""
获取柱状图配置
"""
chart_config = generate_bar_chart_config()
return chart_config
2025-09-10 15:21:56 +08:00
# 读取人口数据
def load_population_data():
try:
# 获取当前文件所在目录的父目录然后找到Data文件夹
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(current_dir)
data_path = os.path.join(project_root, "Data", "RenKou.json")
with open(data_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data
except Exception as e:
print(f"读取人口数据出错: {e}")
return []
# 生成人口数据图表配置
def generate_population_chart_config(year="2024"):
# 加载人口数据
population_data = load_population_data()
# 筛选出州市级数据(排除县级数据)
2025-09-10 15:36:46 +08:00
# 正确的格式是9位数字以000结尾且第5-6位为00表示州市级
cities = [item for item in population_data if len(item["area_code"]) == 9 and item["area_code"].endswith("000") and item["area_code"][4:6] == "00"]
2025-09-10 15:21:56 +08:00
# 提取城市名称和人口数据
city_names = [city["area_name"] for city in cities]
total_populations = [city["total_population"].get(year, 0) for city in cities]
urban_populations = [city["urban_population"].get(year, 0) for city in cities]
rural_populations = [city["rural_population"].get(year, 0) for city in cities]
# 创建柱状图
2025-09-10 15:11:25 +08:00
c = (
Bar()
2025-09-10 15:21:56 +08:00
.add_xaxis(city_names)
.add_yaxis("总人口", total_populations, stack="stack1")
.add_yaxis("城镇人口", urban_populations, stack="stack1")
.add_yaxis("农村人口", rural_populations, stack="stack1")
.set_global_opts(
2025-09-10 15:36:46 +08:00
title_opts=opts.TitleOpts(
title=f"云南省各州市人口分布图({year}年)",
pos_top="1%", # 调整标题位置到顶部1%
pos_left="center"
),
2025-09-10 15:21:56 +08:00
tooltip_opts=opts.TooltipOpts(
trigger="axis",
axis_pointer_type="shadow"
),
2025-09-10 15:36:46 +08:00
legend_opts=opts.LegendOpts(
pos_top="8%", # 调整图例位置到标题下方
pos_right="5%"
),
2025-09-10 15:21:56 +08:00
datazoom_opts=[opts.DataZoomOpts()],
xaxis_opts=opts.AxisOpts(
axislabel_opts=opts.LabelOpts(rotate=45)
),
yaxis_opts=opts.AxisOpts(
name="人口数量(万人)",
name_location="middle",
name_gap=40
)
)
2025-09-10 15:11:25 +08:00
.set_series_opts(
label_opts=opts.LabelOpts(is_show=False),
markline_opts=opts.MarkLineOpts(
2025-09-10 15:21:56 +08:00
data=[opts.MarkLineItem(type_="average", name="平均值")]
)
2025-09-10 15:11:25 +08:00
)
)
# 获取图表的选项配置
options_str = c.dump_options_with_quotes()
# 将字符串转换为 JSON 对象
options_json = json.loads(options_str)
return options_json
2025-09-10 15:21:56 +08:00
# 生成城镇化率图表配置
def generate_urbanization_rate_chart_config():
# 加载人口数据
population_data = load_population_data()
# 筛选出州市级数据(排除县级数据)
2025-09-10 15:36:46 +08:00
# 排除省级数据(如云南省530000000)和县级数据,只保留州市级数据
cities = [item for item in population_data if len(item["area_code"]) == 9 and item["area_code"].endswith("000") and item["area_code"][4:6] == "00" and item["area_code"][2:8] != "000000"]
2025-09-10 15:21:56 +08:00
# 提取城市名称和城镇化率数据
city_names = [city["area_name"] for city in cities]
# 创建折线图
line = (
Line()
.add_xaxis(city_names)
)
# 添加各年份的城镇化率数据
years = ["2020", "2021", "2022", "2023", "2024"]
for year in years:
urbanization_rates = [city["urbanization_rate"].get(year, 0) for city in cities]
line.add_yaxis(f"{year}", urbanization_rates,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]))
line.set_global_opts(
2025-09-10 15:36:46 +08:00
title_opts=opts.TitleOpts(
title="云南省各州市城镇化率变化趋势",
pos_top="1%", # 调整标题位置到顶部1%
pos_left="center"
),
2025-09-10 15:21:56 +08:00
tooltip_opts=opts.TooltipOpts(trigger="axis"),
2025-09-10 15:36:46 +08:00
legend_opts=opts.LegendOpts(
pos_top="8%", # 调整图例位置到标题下方
pos_right="5%"
),
2025-09-10 15:21:56 +08:00
datazoom_opts=[opts.DataZoomOpts()],
xaxis_opts=opts.AxisOpts(
axislabel_opts=opts.LabelOpts(rotate=45)
),
yaxis_opts=opts.AxisOpts(
name="城镇化率(%",
name_location="middle",
name_gap=40,
min_=0,
max_=100
)
)
# 获取图表的选项配置
options_str = line.dump_options_with_quotes()
# 将字符串转换为 JSON 对象
options_json = json.loads(options_str)
return options_json
# 定义一个返回人口数据图表配置的路由
@router.get("/population/chart/{year}")
async def get_population_chart_config(year: str = "2024"):
"""
获取人口数据图表配置
"""
chart_config = generate_population_chart_config(year)
return chart_config
# 定义一个返回城镇化率图表配置的路由
@router.get("/population/urbanization")
async def get_urbanization_rate_chart_config():
"""
获取城镇化率图表配置
"""
chart_config = generate_urbanization_rate_chart_config()
return chart_config
# 定义一个返回人口数据原始数据的路由
@router.get("/population/data")
async def get_population_data():
"""
获取人口数据原始数据
"""
population_data = load_population_data()
return {"data": population_data}