diff --git a/Model/RenkouModel.py b/Model/RenkouModel.py index e69de29..7c54d12 100644 --- a/Model/RenkouModel.py +++ b/Model/RenkouModel.py @@ -0,0 +1,133 @@ +import json +import os +from pyecharts import options as opts +from pyecharts.charts import Bar, Line +from pyecharts.globals import CurrentConfig + +# 配置使用自定义的ECharts路径 +CurrentConfig.ONLINE_HOST = "https://gcore.jsdelivr.net/npm/echarts@6.0.0/dist/" + +class RenkouModel: + @staticmethod + 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 [] + + @staticmethod + def generate_population_chart_config(year="2024"): + # 加载人口数据 + population_data = RenkouModel.load_population_data() + + # 筛选出州市级数据 + 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] + 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%", + 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() + return json.loads(options_str) + + @staticmethod + def generate_urbanization_rate_chart_config(): + # 加载人口数据 + population_data = RenkouModel.load_population_data() + + # 筛选出州市级数据 + 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%", + 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() + return json.loads(options_str) \ No newline at end of file diff --git a/Model/__pycache__/RenkouModel.cpython-310.pyc b/Model/__pycache__/RenkouModel.cpython-310.pyc new file mode 100644 index 0000000..f63dc9d Binary files /dev/null and b/Model/__pycache__/RenkouModel.cpython-310.pyc differ diff --git a/Model/__pycache__/__init__.cpython-310.pyc b/Model/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..39b0c8d Binary files /dev/null and b/Model/__pycache__/__init__.cpython-310.pyc differ diff --git a/Routes/BigScreen.py b/Routes/BigScreen.py index 489cf85..78e3ac6 100644 --- a/Routes/BigScreen.py +++ b/Routes/BigScreen.py @@ -1,213 +1,27 @@ 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 +from Model.RenkouModel import RenkouModel -# 创建 APIRouter 实例 +# 创建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 + return RenkouModel.generate_population_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 + return RenkouModel.generate_population_chart_config(year) -# 定义一个返回城镇化率图表配置的路由 @router.get("/population/urbanization") async def get_urbanization_rate_chart_config(): - """ - 获取城镇化率图表配置 - """ - chart_config = generate_urbanization_rate_chart_config() - return chart_config + return RenkouModel.generate_urbanization_rate_chart_config() -# 定义一个返回人口数据原始数据的路由 @router.get("/population/data") async def get_population_data(): - """ - 获取人口数据原始数据 - """ - population_data = load_population_data() - return {"data": population_data} + return {"data": RenkouModel.load_population_data()} diff --git a/Routes/__pycache__/BigScreen.cpython-310.pyc b/Routes/__pycache__/BigScreen.cpython-310.pyc index 858b390..3e407be 100644 Binary files a/Routes/__pycache__/BigScreen.cpython-310.pyc and b/Routes/__pycache__/BigScreen.cpython-310.pyc differ diff --git a/static/T1_Bar.html b/static/T1_Bar.html index 6a9f4bc..5c86cd4 100644 --- a/static/T1_Bar.html +++ b/static/T1_Bar.html @@ -30,19 +30,15 @@ -
-

云南省各州市城镇化率变化趋势

-
-
点击"加载图表"按钮获取数据