from fastapi import APIRouter import pyecharts from pyecharts import options as opts from pyecharts.charts import Bar, Line from pyecharts.faker import Faker from pyecharts.globals import CurrentConfig import json import os # 创建 APIRouter 实例 router = APIRouter(prefix="/bigscreen", tags=["大屏展示"]) # 配置使用自定义的 ECharts 路径 CurrentConfig.ONLINE_HOST = "https://gcore.jsdelivr.net/npm/echarts@6.0.0/dist/" # 定义一个 helloWorld 路由 @router.get("/") async def root(): return {"message": "Welcome to YunNan Education World!"} # 生成图表配置的函数 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 # 读取人口数据 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() # 筛选出州市级数据(排除县级数据) # 正确的格式是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"] # 提取城市名称和人口数据 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] # 创建柱状图 c = ( Bar() .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( title_opts=opts.TitleOpts( title=f"云南省各州市人口分布图({year}年)", pos_top="1%", # 调整标题位置到顶部1% pos_left="center" ), tooltip_opts=opts.TooltipOpts( trigger="axis", axis_pointer_type="shadow" ), legend_opts=opts.LegendOpts( pos_top="8%", # 调整图例位置到标题下方 pos_right="5%" ), 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 ) ) .set_series_opts( label_opts=opts.LabelOpts(is_show=False), markline_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(type_="average", name="平均值")] ) ) ) # 获取图表的选项配置 options_str = c.dump_options_with_quotes() # 将字符串转换为 JSON 对象 options_json = json.loads(options_str) return options_json # 生成城镇化率图表配置 def generate_urbanization_rate_chart_config(): # 加载人口数据 population_data = load_population_data() # 筛选出州市级数据(排除县级数据) # 排除省级数据(如云南省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"] # 提取城市名称和城镇化率数据 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( title_opts=opts.TitleOpts( title="云南省各州市城镇化率变化趋势", pos_top="1%", # 调整标题位置到顶部1% pos_left="center" ), tooltip_opts=opts.TooltipOpts(trigger="axis"), legend_opts=opts.LegendOpts( pos_top="8%", # 调整图例位置到标题下方 pos_right="5%" ), 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}