From 0f4435b51c549baa254f8c74c086d71d01036383 Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Wed, 21 Jan 2026 09:59:09 +0800 Subject: [PATCH] 'commit' --- Controller/YltAnalyticsController.py | 78 +++++++++++------- .../YltAnalyticsController.cpython-310.pyc | Bin 18760 -> 18795 bytes Util/LlmUtil.py | 1 + Util/__pycache__/LlmUtil.cpython-310.pyc | Bin 1997 -> 2012 bytes static/css/dashboard.css | 34 ++++---- static/dashboard.html | 1 - static/douyin.html | 40 ++++++++- static/js/dashboard.js | 35 ++++++-- static/js/douyin.js | 48 ++++++----- 9 files changed, 158 insertions(+), 79 deletions(-) diff --git a/Controller/YltAnalyticsController.py b/Controller/YltAnalyticsController.py index 7b4c1f2..ab4e150 100644 --- a/Controller/YltAnalyticsController.py +++ b/Controller/YltAnalyticsController.py @@ -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 } diff --git a/Controller/__pycache__/YltAnalyticsController.cpython-310.pyc b/Controller/__pycache__/YltAnalyticsController.cpython-310.pyc index e94bf766eeb0a3d4ac445b06dd05cd7c1f2eb426..8d47fd43cf3021733bdabd54e608cc54f9e164a7 100644 GIT binary patch delta 3119 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 Q$|yg*c@y;T$Xy-(16xKGi~s-t delta 3002 zcmZuzdvH`|6~E{1`1GU<)e3q6rXevcZvDS9SKU(FX*n$p}v6hZ*XQ;KP?Ko8#X+cNObM8%>itf(+ z?fK5*JLfy!Ip^-5r{VN8_)|WgTcXd!igcnydEP(Z$}6CygPxQ0s24z_Ty3yJJnLFK zsoQ5|#rh;b7F(PQdkwZ5R}Lp`0KHpM;#Yo+Z= zGj83byNjiaNB1bwIN-!b+QpLMDwcG&O)8c&yY88SCdneTN^|l_2Pu%Dsi1gF;n=`f zspim}noIF2zP*xeSu0I}`OSETrHoH!x7#u{qW!v;=na`XJ#X#+623XNeIA7rP;8le z#gPeq9Bv7P8!)|2l6%K4E55Af6U&H{f|(N*OADnYDU+`UIj~G{>@ZQReO~v^x-}2k z1Q$w*e@cE5KpGRwRiytz`)1v`P4_E#Gp6Q4x>xrpff;#ouN2Pj$0c+vcnd+!sl>E+ zRMik`nYWB#DFYCMWo&14zs`^O~L0S3Q<;I zGjG#JO8xZPLch3@AS~zPy5+c9JZ~%LakUP|N8@*=v3-n0s+B7xOs$qOoQR`Zhsi9a>ZLj;-R`|RX;1$cgHOn!;epWFw5#;P@3bnYBvnCU& zmb0jF4L{9%8>Yrbm2iQW^)^hJ8K_~SPKGrE5mzjkjB<|Dh)<1UBCbX;u8t?Qh%=Qo zW66OMaVfFgl*O2)Mm$W$?i`M)<0BD2FLtKJF*-z^G%V+h4X9vhBf$VYYDAK@)0v&J zT@HZN;siH1WqLpcKha)!5v{$ncEYEi1mr#PzixK2o|QOW`daDhg#gLOhW05U8?PJ$ z*&>7eI&REf@okb}tLO_tZ_42ublu;84K`#c_yZ;q<#DFW^Y_o_qwj zBYP=$6WC+K#zEmPyd6%7t%cvJq?je#N|198#)ftco4E|)DD%1bahoU!Em*XZ$qlUM zz<4?t8>0JU)*!=#7zj0#e1%D)He5^v3BnHK^1@N^?NF5`!=#ZnU7QP*!C~>&P$%4* zZ74ct^L&Pd>;U_-o|0-uXa~_b=UuUc7X4BRv4=$)MQ`OM=okAdABNv#YZk8oh=|du zB6z~c#$#0_@P_zNRT<1?&sVvj>>wL)i{MiXoEiKs!}l1T7T1^5!*@hob(QTIVyqH( zRM)^WVsG`^@_VuvUfLM?KI=Wp@B@bD7>d;*0fVwpVF!NbIdIw=;$NvPbHx0nUhDFW*~rjyO51k{HsA!IHBisL#0T z!!F#%GRv;`ZlO2qfEUD@4Gr*m*0-V`n%K-JxtvW+CleaJ#tg%&!?45i%y@%$u%%Gh0QwXzX@C%(M09^T15zH*BUN5$o)&2U_-YhD~a%XY^Yj7%7} zYV_JW%wxCa*gGyBX|64$Q8zw<4>NZGLAb=Yrif)Yp2B0|t>#L&C@d`pZhn-65$8x^ zl*ZIZ8vn=!Ty6NSc&VjT{s6?)miyt7n7UQTYm(ICUW0_-cUC1|$KO~;e$^5+aMGyIg{XW3U<%V6?B zqI2XU=b#gf#Bg^wfb+R9PH2?a4O^U;--oIB2z9ZY`z7 zk`!GjW#tuCJjHOD;RM4k7=9`4YcGfW;z)ZNbc*-dH-IFXI{Jbiu&|UM40ws@4~_gB z>IemfDL;6XdGsQeCRT{nj$6d#jw=pa&&)@~rPYf-6@kvK@{7cXxOXQt^Zloyan4U% zQC91G%uEpegN^@55cZlL|G*5R%y^ssF=gHjnJ8v!=X@sceO7ve;TpqrhW!lxW+1=3W2(y}%sgDdKtYDsvc!HB*Ct{*e_fXi?wxiQlMjk-cCT=;dn&hUk~r60N>lLt?k!)KAs*#9!apwa@WzqnGjLoQBPFwh?_v#!w16vvI_RCq98P56eEz&l*5$E9L3BC5@XI` z2?5b8Ijp&CQEa*FQS7-KQ5--yz7+OU&J>PRt`trn&6UcX!kx;K#+Aa8!rQ_c#k;XC oij9$b@=dlp4!$ByphZRUlfBqW1$cl=4h9ZJ9wrVZ5k?gj0Ey!rmH+?% delta 139 zcmcb^f0my&pO=@50SK-u7GyF^qChlL4r4A;6cZze&78v=0-{-R zSaMmTSaaE;*mBvU*nx6E0rsSJC!?)D}^V8w}mx|XJcCw8za}` dhirMwyhWOm!`VyuK$dba@Gx;Oi7=|L007)C8+-r& diff --git a/static/css/dashboard.css b/static/css/dashboard.css index 304addb..d34460d 100644 --- a/static/css/dashboard.css +++ b/static/css/dashboard.css @@ -10,7 +10,7 @@ --success-color: #10b981; --table-header-bg: #0f172a; --table-row-hover: #334155; - --scrollbar-thumb: #475569; + --scrollbar-thumb: #334155; --scrollbar-track: #0f172a; } @@ -230,7 +230,7 @@ body { .ai-box { flex: 1; - background-color: rgba(15, 23, 42, 0.3); + background-color: #243347; border-radius: 8px; border: 1px solid var(--card-border); padding: 16px; @@ -240,6 +240,7 @@ body { color: #cbd5e1; scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); } /* Markdown & LaTeX Rendering */ @@ -249,6 +250,7 @@ body { line-height: 1.8; word-wrap: break-word; color: #cbd5e1; + background-color: transparent !important; } .markdown-body h1, .markdown-body h2, .markdown-body h3, @@ -257,37 +259,40 @@ body { margin-bottom: 16px; font-weight: 600; line-height: 1.25; - color: var(--text-primary); + color: var(--text-primary) !important; + background-color: transparent !important; } .markdown-body h1 { font-size: 1.8em; border-bottom: 1px solid var(--card-border); padding-bottom: 0.3em; } .markdown-body h2 { font-size: 1.4em; border-bottom: 1px solid var(--card-border); padding-bottom: 0.3em; } .markdown-body h3 { font-size: 1.2em; } -.markdown-body p { margin-top: 0; margin-bottom: 16px; } +.markdown-body p { margin-top: 0; margin-bottom: 16px; background-color: transparent !important; } .markdown-body ul, .markdown-body ol { padding-left: 2em; margin-top: 0; margin-bottom: 16px; + background-color: transparent !important; } -.markdown-body li { margin: 0.25em 0; } +.markdown-body li { margin: 0.25em 0; background-color: transparent !important; } -.markdown-body strong { font-weight: 600; color: #fff; } +.markdown-body strong { font-weight: 600; color: #fff !important; background-color: transparent !important; } .markdown-body blockquote { padding: 0 1em; color: #94a3b8; border-left: 0.25em solid #3b82f6; margin: 0 0 16px 0; + background-color: transparent !important; } .markdown-body code { padding: 0.2em 0.4em; margin: 0; font-size: 85%; - background-color: rgba(148, 163, 184, 0.1); + background-color: rgba(59, 130, 246, 0.1) !important; border-radius: 6px; font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; } @@ -303,11 +308,7 @@ body { border-collapse: collapse; margin-top: 0; margin-bottom: 16px; -} - -.markdown-body table th { - font-weight: 600; - background-color: rgba(15, 23, 42, 0.8); + background-color: transparent !important; } .markdown-body table th, @@ -316,13 +317,18 @@ body { border: 1px solid var(--card-border); } +.markdown-body table th { + font-weight: 600; + background-color: #334155 !important; +} + .markdown-body table tr { - background-color: transparent; + background-color: transparent !important; border-top: 1px solid var(--card-border); } .markdown-body table tr:nth-child(2n) { - background-color: rgba(30, 41, 59, 0.3); + background-color: rgba(51, 65, 85, 0.3) !important; } /* LaTeX Styles */ diff --git a/static/dashboard.html b/static/dashboard.html index 1d118fa..aec05a7 100644 --- a/static/dashboard.html +++ b/static/dashboard.html @@ -5,7 +5,6 @@ 分时电价分析 - 驿来特AI智能大脑 -
diff --git a/static/douyin.html b/static/douyin.html index 22c7833..f57b4f7 100644 --- a/static/douyin.html +++ b/static/douyin.html @@ -45,7 +45,7 @@

⚡ AI正在阅读您的知识库并提炼精华,请稍候...

-
+
|