This commit is contained in:
HuangHai
2026-01-21 09:59:09 +08:00
parent 2fda6f0dcf
commit 0f4435b51c
9 changed files with 158 additions and 79 deletions

View File

@@ -86,7 +86,7 @@ async def get_operators_price_trends(days: int = 7):
model = YltAnalyticsModel()
rows = await model.get_operators_price_trends(days)
# 数据结构: { operator: { date_str: [sums_of_24h, counts_of_24h] } }
# 数据结构: { operator: { datetime_str: [sums_of_price, counts_of_station] } }
trend_data = {}
for op in operators:
trend_data[op] = {}
@@ -95,47 +95,65 @@ async def get_operators_price_trends(days: int = 7):
op = row.get("operator")
if op not in trend_data:
continue
d_str = str(row.get("date_str"))
schedule_json = row.get("schedule_json")
if d_str not in trend_data[op]:
trend_data[op][d_str] = {"sums": [0.0] * 24, "counts": [0] * 24}
# 将日期和 schedule_json 展开为 24 小时的数据点
d_str = str(row.get("date_str"))
# 将 2026-01-21 转换为 01/21
try:
date_parts = d_str.split('-')
display_date = date_parts[1] + '/' + date_parts[2]
except:
display_date = d_str
schedule_json = row.get("schedule_json")
series = extract_hourly_prices_from_schedule(schedule_json)
for i in range(24):
v = series[i]
for hour in range(24):
v = series[hour]
if v is not None:
trend_data[op][d_str]["sums"][i] += float(v)
trend_data[op][d_str]["counts"][i] += 1
# 使用原始日期 YYYY-MM-DD 用于排序,显示时由前端或后端格式化
# 这里我们构造一个带补全的时间字符串,方便自然排序
dt_key = f"{d_str} {hour:02d}:00"
if dt_key not in trend_data[op]:
trend_data[op][dt_key] = {"sum": 0.0, "count": 0, "display": f"{display_date} {hour:02d}:00"}
trend_data[op][dt_key]["sum"] += float(v)
trend_data[op][dt_key]["count"] += 1
# 转换为 ECharts 友好格式
# 1. 获取所有日期并排序
all_dates = sorted(list(set(str(row.get("date_str")) for row in rows)))
# 1. 获取所有时间点并排序
all_time_keys = set()
for op in operators:
all_time_keys.update(trend_data[op].keys())
sorted_keys = sorted(list(all_time_keys))
# 2. 为每个运营商计算每天的平均价格24小时的平均值
# 2. 提取显示用的标签
display_dates = []
if sorted_keys:
# 从任意一个存在的运营商数据中获取 display 标签
first_op = operators[0]
for key in sorted_keys:
# 找到包含该 key 的 display 标签
label = key # fallback
for op in operators:
if key in trend_data[op]:
label = trend_data[op][key]["display"]
break
display_dates.append(label)
# 3. 为每个运营商构建完整的时间序列数据
series_result = []
for op in operators:
op_trend = []
for d in all_dates:
if d in trend_data[op]:
day_stats = trend_data[op][d]
day_avg_sum = 0.0
day_hour_count = 0
for i in range(24):
if day_stats["counts"][i] > 0:
day_avg_sum += (day_stats["sums"][i] / day_stats["counts"][i])
day_hour_count += 1
if day_hour_count > 0:
op_trend.append(round(day_avg_sum / day_hour_count, 4))
else:
op_trend.append(None)
op_data = []
for key in sorted_keys:
if key in trend_data[op]:
stats = trend_data[op][key]
op_data.append(round(stats["sum"] / stats["count"], 4))
else:
op_trend.append(None)
series_result.append({"name": op, "data": op_trend})
op_data.append(None)
series_result.append({"name": op, "data": op_data})
return {
"dates": all_dates,
"dates": display_dates,
"series": series_result
}