bngoc commited on
Commit
b47a646
·
1 Parent(s): 32be339

bổ sung size footer

Browse files
Files changed (5) hide show
  1. app.py +194 -24
  2. app_backup.py +0 -1986
  3. app_fixed.py +0 -784
  4. app_tabs_final.py +0 -275
  5. app_with_tabs.py +0 -336
app.py CHANGED
@@ -93,12 +93,22 @@ custom_css = """
93
  margin: 20px 0;
94
  box-shadow: 0 15px 35px rgba(12, 83, 135, 0.3), 0 5px 15px rgba(0, 0, 0, 0.12);
95
  border: 1px solid rgba(255, 255, 255, 0.2);
 
96
  }
97
 
98
  .loading-container * {
99
  color: white !important;
100
  }
101
 
 
 
 
 
 
 
 
 
 
102
  .loading-spinner {
103
  border: 4px solid #f3f3f3;
104
  border-top: 4px solid #1A5F91;
@@ -428,6 +438,48 @@ html {
428
  transition: all 0.3s ease !important;
429
  }
430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  /* Cải thiện focus state cho biểu đồ */
432
  .plot-container:focus-within {
433
  outline: 2px solid rgba(26, 95, 145, 0.3);
@@ -1961,13 +2013,13 @@ def tao_ung_dung():
1961
  inputs=[],
1962
  outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
1963
  show_progress=False,
1964
- scroll_to_output=True, # auto scroll tới chart (output đầu)
1965
  )
1966
 
1967
- # (Tùy chọn) highlight chart ngay sau khi cuộn
1968
- JS_SCROLL_HILIGHT = r"""
1969
  (...args) => {
1970
- const el = document.getElementById('chart-target');
1971
  if (el) {
1972
  el.scrollIntoView({ behavior: 'smooth', block: 'center' });
1973
  el.classList.add('highlight');
@@ -1977,9 +2029,9 @@ def tao_ung_dung():
1977
  }
1978
  """
1979
  try:
1980
- evt0.then(fn=None, inputs=None, outputs=None, js=JS_SCROLL_HILIGHT)
1981
  except TypeError:
1982
- evt0.then(fn=None, inputs=None, outputs=None, _js=JS_SCROLL_HILIGHT) # type: ignore
1983
 
1984
  # 2) Stream 4 bước loading trong 3–5 giây (chỉ update loading_panel)
1985
  evt1 = evt0.then(
@@ -1990,13 +2042,30 @@ def tao_ung_dung():
1990
  )
1991
 
1992
  # 3) Tính toán thật, render kết quả + tắt loading
1993
- evt1.then(
1994
  fn=tinh_toan_ket_qua,
1995
  inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
1996
  outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
1997
  show_progress=False,
1998
  )
1999
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2000
  # Streaming event cho chiến lược đề xuất
2001
  nut_streaming.click(
2002
  fn=xu_ly_streaming,
@@ -2051,23 +2120,74 @@ Hệ thống AI sẽ tạo chiến lược đề xuất với:
2051
  # Footer thông tin hệ thống với branding FoxAI
2052
  gr.HTML(f"""
2053
  <div class='info-card' style="margin-top: 30px; text-align: center;">
2054
- <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 30px;">
2055
- <img src="{FOXAI_LOGO_URL}" alt="FoxAi" style="height: 55px; margin-right: 18px;"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2056
  <h2 style="
2057
- color: #1A5F91;
2058
  margin: 0;
2059
- font-size: 2.2em;
2060
- font-weight: 800;
2061
- letter-spacing: 1px;
 
 
 
 
 
 
2062
  ">
2063
- 💡 Hệ thống dự báo <span style="color:#0C5387;">FoxAi</span>
 
 
 
 
 
 
2064
  </h2>
2065
  </div>
2066
 
2067
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin: 25px 0;">
2068
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px;">
2069
- <h4 style="color: #1A5F91; margin-bottom: 15px;">🎯 Tính Năng</h4>
2070
- <div style="color: #334155; line-height: 1.8; font-weight: 500;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2071
  ✨ AI Insights thông minh<br/>
2072
  📊 Multi-view linh hoạt<br/>
2073
  📈 Báo cáo chuyên nghiệp<br/>
@@ -2075,9 +2195,33 @@ Hệ thống AI sẽ tạo chiến lược đề xuất với:
2075
  </div>
2076
  </div>
2077
 
2078
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px;">
2079
- <h4 style="color: #1A5F91; margin-bottom: 15px;">📊 Chất Lượng</h4>
2080
- <div style="color: #334155; line-height: 1.8; font-weight: 500;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2081
  🎯 Độ chính xác cao<br/>
2082
  📅 Dự báo theo quý<br/>
2083
  🔄 Market intelligence<br/>
@@ -2086,11 +2230,37 @@ Hệ thống AI sẽ tạo chiến lược đề xuất với:
2086
  </div>
2087
  </div>
2088
 
2089
- <div style="text-align: center; margin: 25px 0; padding: 20px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 15px; border: 2px solid #1A5F91;">
2090
- <p style="color: #1A5F91; font-weight: 700; margin: 0; font-size: 1.2em;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2091
  🦊 <strong>Powered by FoxAi</strong> • 🇻🇳 Made in Vietnam • 🤖 Advanced AI
2092
  </p>
2093
- <p style="color: #334155; margin: 8px 0 0 0; font-size: 1em; font-weight: 600;">
 
 
 
 
 
 
 
2094
  YOUR TRUSTED AI PARTNER
2095
  </p>
2096
  </div>
 
93
  margin: 20px 0;
94
  box-shadow: 0 15px 35px rgba(12, 83, 135, 0.3), 0 5px 15px rgba(0, 0, 0, 0.12);
95
  border: 1px solid rgba(255, 255, 255, 0.2);
96
+ animation: loadingPulse 2s ease-in-out infinite alternate;
97
  }
98
 
99
  .loading-container * {
100
  color: white !important;
101
  }
102
 
103
+ @keyframes loadingPulse {
104
+ 0% {
105
+ box-shadow: 0 15px 35px rgba(12, 83, 135, 0.3), 0 5px 15px rgba(0, 0, 0, 0.12);
106
+ }
107
+ 100% {
108
+ box-shadow: 0 20px 45px rgba(12, 83, 135, 0.4), 0 8px 20px rgba(0, 0, 0, 0.15);
109
+ }
110
+ }
111
+
112
  .loading-spinner {
113
  border: 4px solid #f3f3f3;
114
  border-top: 4px solid #1A5F91;
 
438
  transition: all 0.3s ease !important;
439
  }
440
 
441
+ /* Hiệu ứng highlight cho loading panel */
442
+ #loading-panel.highlight {
443
+ box-shadow: 0 0 20px rgba(26, 95, 145, 0.4) !important;
444
+ transform: scale(1.02) !important;
445
+ transition: all 0.3s ease !important;
446
+ }
447
+
448
+ /* Fade-in animation cho LLM analysis */
449
+ .gradio-markdown {
450
+ animation: fadeInUp 0.8s ease-out !important;
451
+ opacity: 0 !important;
452
+ animation-fill-mode: forwards !important;
453
+ }
454
+
455
+ @keyframes fadeInUp {
456
+ 0% {
457
+ opacity: 0;
458
+ transform: translateY(30px);
459
+ }
460
+ 100% {
461
+ opacity: 1;
462
+ transform: translateY(0);
463
+ }
464
+ }
465
+
466
+ /* Smooth reveal cho các phần tử khác */
467
+ .plot-container,
468
+ .info-card {
469
+ animation: slideInFade 0.6s ease-out !important;
470
+ }
471
+
472
+ @keyframes slideInFade {
473
+ 0% {
474
+ opacity: 0;
475
+ transform: translateY(20px);
476
+ }
477
+ 100% {
478
+ opacity: 1;
479
+ transform: translateY(0);
480
+ }
481
+ }
482
+
483
  /* Cải thiện focus state cho biểu đồ */
484
  .plot-container:focus-within {
485
  outline: 2px solid rgba(26, 95, 145, 0.3);
 
2013
  inputs=[],
2014
  outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
2015
  show_progress=False,
2016
+ scroll_to_output=False, # Không scroll tự động, sẽ dùng JS
2017
  )
2018
 
2019
+ # Scroll tới loading panel thay chart
2020
+ JS_SCROLL_TO_LOADING = r"""
2021
  (...args) => {
2022
+ const el = document.getElementById('loading-panel');
2023
  if (el) {
2024
  el.scrollIntoView({ behavior: 'smooth', block: 'center' });
2025
  el.classList.add('highlight');
 
2029
  }
2030
  """
2031
  try:
2032
+ evt0.then(fn=None, inputs=None, outputs=None, js=JS_SCROLL_TO_LOADING)
2033
  except TypeError:
2034
+ evt0.then(fn=None, inputs=None, outputs=None, _js=JS_SCROLL_TO_LOADING) # type: ignore
2035
 
2036
  # 2) Stream 4 bước loading trong 3–5 giây (chỉ update loading_panel)
2037
  evt1 = evt0.then(
 
2042
  )
2043
 
2044
  # 3) Tính toán thật, render kết quả + tắt loading
2045
+ evt2 = evt1.then(
2046
  fn=tinh_toan_ket_qua,
2047
  inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
2048
  outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
2049
  show_progress=False,
2050
  )
2051
 
2052
+ # Thêm hiệu ứng fade-in cho LLM analysis sau khi render
2053
+ JS_FADE_IN_LLM = r"""
2054
+ (...args) => {
2055
+ setTimeout(() => {
2056
+ const markdownElements = document.querySelectorAll('.gradio-markdown');
2057
+ markdownElements.forEach(el => {
2058
+ el.style.animation = 'fadeInUp 0.8s ease-out forwards';
2059
+ });
2060
+ }, 200);
2061
+ return [];
2062
+ }
2063
+ """
2064
+ try:
2065
+ evt2.then(fn=None, inputs=None, outputs=None, js=JS_FADE_IN_LLM)
2066
+ except TypeError:
2067
+ evt2.then(fn=None, inputs=None, outputs=None, _js=JS_FADE_IN_LLM) # type: ignore
2068
+
2069
  # Streaming event cho chiến lược đề xuất
2070
  nut_streaming.click(
2071
  fn=xu_ly_streaming,
 
2120
  # Footer thông tin hệ thống với branding FoxAI
2121
  gr.HTML(f"""
2122
  <div class='info-card' style="margin-top: 30px; text-align: center;">
2123
+ <div style="
2124
+ display: flex;
2125
+ align-items: center;
2126
+ justify-content: center;
2127
+ margin-bottom: 35px;
2128
+ padding: 25px;
2129
+ background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(12, 83, 135, 0.05));
2130
+ border-radius: 20px;
2131
+ border: 2px solid rgba(26, 95, 145, 0.2);
2132
+ box-shadow: 0 8px 25px rgba(26, 95, 145, 0.15);
2133
+ ">
2134
+ <img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="
2135
+ height: 65px;
2136
+ margin-right: 25px;
2137
+ filter: drop-shadow(0 4px 8px rgba(26, 95, 145, 0.3));
2138
+ transition: all 0.3s ease;
2139
+ " onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'"/>
2140
  <h2 style="
2141
+ color: white;
2142
  margin: 0;
2143
+ font-size: 2.8em;
2144
+ font-weight: 900;
2145
+ letter-spacing: 1.5px;
2146
+ text-shadow: 0 0 20px rgba(255, 255, 255, 0.5);
2147
+ background: linear-gradient(90deg, #ffffff, #f1f5f9, #e2e8f0);
2148
+ -webkit-background-clip: text;
2149
+ -webkit-text-fill-color: transparent;
2150
+ background-clip: text;
2151
+ line-height: 1.2;
2152
  ">
2153
+ 💡 HỆ THỐNG DỰ BÁO <span style="
2154
+ background: linear-gradient(90deg, #ffffff, #cbd5e1);
2155
+ -webkit-background-clip: text;
2156
+ -webkit-text-fill-color: transparent;
2157
+ background-clip: text;
2158
+ font-weight: 800;
2159
+ ">FoxAI</span>
2160
  </h2>
2161
  </div>
2162
 
2163
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 30px; margin: 30px 0;">
2164
+ <div style="
2165
+ text-align: center;
2166
+ padding: 30px;
2167
+ background: linear-gradient(135deg, rgba(26, 95, 145, 0.15), rgba(255, 255, 255, 0.1));
2168
+ border-radius: 20px;
2169
+ border: 1px solid rgba(26, 95, 145, 0.3);
2170
+ box-shadow: 0 8px 25px rgba(26, 95, 145, 0.15);
2171
+ transition: all 0.3s ease;
2172
+ ">
2173
+ <h4 style="
2174
+ color: #1A5F91;
2175
+ margin-bottom: 20px;
2176
+ font-size: 1.8em;
2177
+ font-weight: 700;
2178
+ background: linear-gradient(90deg, #1A5F91, #2563eb);
2179
+ -webkit-background-clip: text;
2180
+ -webkit-text-fill-color: transparent;
2181
+ background-clip: text;
2182
+ text-shadow: 0 2px 10px rgba(26, 95, 145, 0.3);
2183
+ ">🎯 Tính Năng</h4>
2184
+ <div style="
2185
+ color: #334155;
2186
+ line-height: 2.2;
2187
+ font-weight: 600;
2188
+ font-size: 1.15em;
2189
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
2190
+ ">
2191
  ✨ AI Insights thông minh<br/>
2192
  📊 Multi-view linh hoạt<br/>
2193
  📈 Báo cáo chuyên nghiệp<br/>
 
2195
  </div>
2196
  </div>
2197
 
2198
+ <div style="
2199
+ text-align: center;
2200
+ padding: 30px;
2201
+ background: linear-gradient(135deg, rgba(26, 95, 145, 0.15), rgba(255, 255, 255, 0.1));
2202
+ border-radius: 20px;
2203
+ border: 1px solid rgba(26, 95, 145, 0.3);
2204
+ box-shadow: 0 8px 25px rgba(26, 95, 145, 0.15);
2205
+ transition: all 0.3s ease;
2206
+ ">
2207
+ <h4 style="
2208
+ color: #1A5F91;
2209
+ margin-bottom: 20px;
2210
+ font-size: 1.8em;
2211
+ font-weight: 700;
2212
+ background: linear-gradient(90deg, #1A5F91, #2563eb);
2213
+ -webkit-background-clip: text;
2214
+ -webkit-text-fill-color: transparent;
2215
+ background-clip: text;
2216
+ text-shadow: 0 2px 10px rgba(26, 95, 145, 0.3);
2217
+ ">📊 Chất Lượng</h4>
2218
+ <div style="
2219
+ color: #334155;
2220
+ line-height: 2.2;
2221
+ font-weight: 600;
2222
+ font-size: 1.15em;
2223
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
2224
+ ">
2225
  🎯 Độ chính xác cao<br/>
2226
  📅 Dự báo theo quý<br/>
2227
  🔄 Market intelligence<br/>
 
2230
  </div>
2231
  </div>
2232
 
2233
+ <div style="
2234
+ text-align: center;
2235
+ margin: 35px 0;
2236
+ padding: 25px;
2237
+ background: linear-gradient(135deg, rgba(26, 95, 145, 0.2), rgba(139, 139, 139, 0.15));
2238
+ border-radius: 20px;
2239
+ border: 2px solid #1A5F91;
2240
+ box-shadow: 0 10px 30px rgba(26, 95, 145, 0.2);
2241
+ transition: all 0.3s ease;
2242
+ ">
2243
+ <p style="
2244
+ color: #1A5F91;
2245
+ font-weight: 700;
2246
+ margin: 0;
2247
+ font-size: 1.5em;
2248
+ background: linear-gradient(90deg, #1A5F91, #2563eb, #1A5F91);
2249
+ -webkit-background-clip: text;
2250
+ -webkit-text-fill-color: transparent;
2251
+ background-clip: text;
2252
+ text-shadow: 0 2px 8px rgba(26, 95, 145, 0.3);
2253
+ ">
2254
  🦊 <strong>Powered by FoxAi</strong> • 🇻🇳 Made in Vietnam • 🤖 Advanced AI
2255
  </p>
2256
+ <p style="
2257
+ color: #334155;
2258
+ margin: 12px 0 0 0;
2259
+ font-size: 1.2em;
2260
+ font-weight: 700;
2261
+ letter-spacing: 1px;
2262
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
2263
+ ">
2264
  YOUR TRUSTED AI PARTNER
2265
  </p>
2266
  </div>
app_backup.py DELETED
@@ -1,1986 +0,0 @@
1
- import gradio as gr
2
- import plotly.graph_objects as go
3
- import numpy as np
4
- from datetime import datetime, timedelta
5
- import random
6
- import time
7
- import pandas as pd # thêm
8
-
9
- # URL logo FoxAI - sử dụng trực tiếp từ attachment
10
- FOXAI_LOGO_URL = "data:image/png;base64,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"
11
-
12
- # CSS Style với màu sắc FoxAI - Modern UI Design
13
- custom_css = """
14
- .gradio-container {
15
- background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 25%, #cbd5e1 50%, #94a3b8 75%, #64748b 100%);
16
- font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif !important;
17
- min-height: 100vh;
18
- }
19
-
20
- .header-container {
21
- text-align: center;
22
- margin: 20px 0;
23
- padding: 40px;
24
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
25
- border-radius: 24px;
26
- box-shadow: 0 20px 40px rgba(12, 83, 135, 0.15), 0 8px 16px rgba(0, 0, 0, 0.1);
27
- backdrop-filter: blur(20px);
28
- border: 1px solid rgba(255, 255, 255, 0.3);
29
- position: relative;
30
- overflow: hidden;
31
- }
32
-
33
- .header-container::before {
34
- content: '';
35
- position: absolute;
36
- top: 0;
37
- left: -100%;
38
- width: 100%;
39
- height: 100%;
40
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
41
- animation: shine 3s infinite;
42
- }
43
-
44
- @keyframes shine {
45
- 0% { left: -100%; }
46
- 100% { left: 100%; }
47
- }
48
-
49
- .foxai-logo {
50
- max-width: 320px;
51
- height: auto;
52
- margin: 15px auto 25px auto;
53
- display: block;
54
- filter: drop-shadow(0 4px 8px rgba(0,0,0,0.15)) brightness(1.1);
55
- transition: all 0.4s ease;
56
- animation: float 4s ease-in-out infinite;
57
- }
58
-
59
- .foxai-logo:hover {
60
- transform: scale(1.05);
61
- filter: drop-shadow(0 8px 16px rgba(12, 83, 135, 0.3)) brightness(1.2);
62
- }
63
-
64
- .header-title {
65
- background: linear-gradient(90deg, #ffffff, #f1f5f9, #e2e8f0, #ffffff);
66
- background-size: 300% 300%;
67
- animation: gradient 8s ease infinite;
68
- -webkit-background-clip: text;
69
- -webkit-text-fill-color: transparent;
70
- background-clip: text;
71
- text-align: center;
72
- font-size: 2.5em;
73
- font-weight: 700;
74
- margin: 15px auto;
75
- line-height: 1.3;
76
- text-shadow: 0 0 30px rgba(255, 255, 255, 0.5);
77
- letter-spacing: -0.01em;
78
- max-width: 900px;
79
- }
80
-
81
- @keyframes gradient {
82
- 0% { background-position: 0% 50%; }
83
- 50% { background-position: 100% 50%; }
84
- 100% { background-position: 0% 50%; }
85
- }
86
-
87
- .loading-container {
88
- text-align: center;
89
- padding: 40px;
90
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
91
- border-radius: 20px;
92
- color: white !important;
93
- margin: 20px 0;
94
- box-shadow: 0 15px 35px rgba(12, 83, 135, 0.3), 0 5px 15px rgba(0, 0, 0, 0.12);
95
- border: 1px solid rgba(255, 255, 255, 0.2);
96
- }
97
-
98
- .loading-container * {
99
- color: white !important;
100
- }
101
-
102
- .loading-spinner {
103
- border: 4px solid #f3f3f3;
104
- border-top: 4px solid #1A5F91;
105
- border-radius: 50%;
106
- width: 40px;
107
- height: 40px;
108
- animation: spin 1s linear infinite;
109
- margin: 0 auto 20px;
110
- }
111
-
112
- @keyframes spin {
113
- 0% { transform: rotate(0deg); }
114
- 100% { transform: rotate(360deg); }
115
- }
116
-
117
- .progress-bar {
118
- width: 100%;
119
- height: 20px;
120
- background-color: rgba(255,255,255,0.3);
121
- border-radius: 10px;
122
- overflow: hidden;
123
- margin: 15px 0;
124
- }
125
-
126
- .progress-fill {
127
- height: 100%;
128
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
129
- border-radius: 10px;
130
- animation: progress 3s ease-in-out;
131
- box-shadow: 0 0 20px rgba(12, 83, 135, 0.4);
132
- }
133
-
134
- @keyframes progress {
135
- 0% { width: 0%; }
136
- 25% { width: 30%; }
137
- 50% { width: 60%; }
138
- 75% { width: 85%; }
139
- 100% { width: 100%; }
140
- }
141
-
142
- .prediction-box {
143
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
144
- border-radius: 20px;
145
- padding: 25px;
146
- color: white !important;
147
- text-align: center;
148
- font-size: 1.1em;
149
- font-weight: 600;
150
- box-shadow: 0 15px 35px rgba(12, 83, 135, 0.25), 0 5px 15px rgba(0, 0, 0, 0.12);
151
- margin: 15px 0;
152
- border: 1px solid rgba(255,255,255,0.2);
153
- position: relative;
154
- overflow: hidden;
155
- }
156
-
157
- .prediction-box * {
158
- color: white !important;
159
- }
160
-
161
- .prediction-box::before {
162
- content: '';
163
- position: absolute;
164
- top: 0;
165
- left: 0;
166
- right: 0;
167
- height: 1px;
168
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent);
169
- }
170
-
171
- .insight-box {
172
- background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
173
- border-radius: 20px;
174
- padding: 25px;
175
- color: white !important;
176
- margin: 15px 0;
177
- box-shadow: 0 15px 35px rgba(51, 65, 85, 0.25), 0 5px 15px rgba(0, 0, 0, 0.12);
178
- border: 1px solid rgba(255,255,255,0.2);
179
- position: relative;
180
- overflow: hidden;
181
- }
182
-
183
- .insight-box * {
184
- color: white !important;
185
- }
186
-
187
- .executive-summary {
188
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
189
- border-radius: 20px;
190
- padding: 30px;
191
- color: white !important;
192
- margin: 15px 0;
193
- box-shadow: 0 20px 40px rgba(12, 83, 135, 0.25), 0 8px 16px rgba(0, 0, 0, 0.12);
194
- border-left: 5px solid rgba(255, 255, 255, 0.3);
195
- border: 1px solid rgba(255,255,255,0.2);
196
- position: relative;
197
- overflow: hidden;
198
- }
199
-
200
- .executive-summary * {
201
- color: white !important;
202
- }
203
-
204
- .executive-summary::after {
205
- content: '';
206
- position: absolute;
207
- top: 0;
208
- right: 0;
209
- width: 100px;
210
- height: 100%;
211
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1));
212
- pointer-events: none;
213
- }
214
-
215
- .feature-box {
216
- background: linear-gradient(135deg, rgba(169, 170, 169, 0.15), rgba(129, 148, 160, 0.15), rgba(90, 126, 152, 0.15));
217
- border-radius: 20px;
218
- padding: 20px;
219
- margin: 15px 0;
220
- box-shadow: 0 8px 32px rgba(12, 83, 135, 0.1), 0 1px 2px rgba(0, 0, 0, 0.05);
221
- border-left: 4px solid #0C5387;
222
- backdrop-filter: blur(10px);
223
- border: 1px solid rgba(255, 255, 255, 0.2);
224
- transition: all 0.3s ease;
225
- text-align: center;
226
- }
227
-
228
- .feature-box:hover {
229
- transform: translateY(-2px);
230
- box-shadow: 0 12px 40px rgba(12, 83, 135, 0.15), 0 4px 8px rgba(0, 0, 0, 0.1);
231
- }
232
-
233
- .feature-box h3 {
234
- margin: 0;
235
- color: #0C5387;
236
- font-weight: 700;
237
- text-shadow: 0 0 10px rgba(12, 83, 135, 0.3);
238
- font-size: 1.2em;
239
- text-align: center;
240
- }
241
-
242
- .system-status {
243
- background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
244
- color: white !important;
245
- padding: 15px 25px;
246
- border-radius: 30px;
247
- margin: 15px 0;
248
- text-align: center;
249
- font-weight: 600;
250
- box-shadow: 0 8px 25px rgba(51, 65, 85, 0.2), 0 3px 8px rgba(0, 0, 0, 0.1);
251
- border: 1px solid rgba(255,255,255,0.2);
252
- font-size: 0.95em;
253
- }
254
-
255
- .system-status * {
256
- color: white !important;
257
- }
258
-
259
- .metric-card {
260
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
261
- color: white !important;
262
- border-radius: 16px;
263
- padding: 20px;
264
- margin: 8px;
265
- text-align: center;
266
- box-shadow: 0 8px 25px rgba(12, 83, 135, 0.2), 0 3px 8px rgba(0, 0, 0, 0.1);
267
- border: 1px solid rgba(255,255,255,0.2);
268
- transition: all 0.3s ease;
269
- position: relative;
270
- overflow: hidden;
271
- }
272
-
273
- .metric-card * {
274
- color: white !important;
275
- }
276
-
277
- .metric-card:hover {
278
- transform: translateY(-3px);
279
- box-shadow: 0 12px 35px rgba(12, 83, 135, 0.3), 0 5px 12px rgba(0, 0, 0, 0.15);
280
- }
281
-
282
- .metric-card::before {
283
- content: '';
284
- position: absolute;
285
- top: 0;
286
- left: 0;
287
- right: 0;
288
- height: 2px;
289
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
290
- }
291
-
292
- .button-predict {
293
- background: linear-gradient(135deg, #1A5F91, #8B8B8B) !important;
294
- color: white !important;
295
- border: none !important;
296
- border-radius: 25px !important;
297
- padding: 15px 30px !important;
298
- font-size: 16px !important;
299
- font-weight: bold !important;
300
- box-shadow: 0 4px 15px rgba(26, 95, 145, 0.4) !important;
301
- transition: all 0.3s ease !important;
302
- }
303
-
304
- .button-predict:hover {
305
- transform: translateY(-2px) !important;
306
- box-shadow: 0 6px 20px rgba(26, 95, 145, 0.6) !important;
307
- }
308
-
309
- .plot-container {
310
- border: 1px solid #e1e5e9;
311
- border-radius: 15px;
312
- padding: 15px;
313
- margin: 15px 0;
314
- background: rgba(255, 255, 255, 0.95);
315
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
316
- min-height: 400px;
317
- position: relative;
318
- overflow: hidden;
319
- }
320
-
321
- /* Cải thiện hiển thị biểu đồ Plotly */
322
- .plot-container .plotly-graph-div {
323
- position: relative !important;
324
- max-width: 100% !important;
325
- height: auto !important;
326
- margin: 20px 0 !important;
327
- padding: 20px !important;
328
- border-radius: 12px !important;
329
- background: rgba(255, 255, 255, 0.95) !important;
330
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
331
- overflow: visible !important;
332
- }
333
-
334
- /* Ẩn hoàn toàn toolbar/config của biểu đồ */
335
- .plot-container .modebar,
336
- .plot-container .modebar-container,
337
- .plotly .modebar,
338
- .js-plotly-plot .modebar,
339
- .plotly-graph-div .modebar,
340
- .plotly-graph-div .modebar-container,
341
- .svg-container .modebar,
342
- div[data-title="Plotly toolbar"],
343
- .modebar-group,
344
- .modebar-btn {
345
- display: none !important;
346
- visibility: hidden !important;
347
- opacity: 0 !important;
348
- pointer-events: none !important;
349
- height: 0 !important;
350
- width: 0 !important;
351
- overflow: hidden !important;
352
- position: absolute !important;
353
- top: -9999px !important;
354
- left: -9999px !important;
355
- }
356
-
357
- /* Cải thiện spacing cho text và labels - tránh dính chữ */
358
- .plot-container .plotly-graph-div .svg-container {
359
- pointer-events: auto !important;
360
- overflow: visible !important;
361
- padding: 10px !important;
362
- }
363
-
364
- .plot-container .plotly-graph-div .main-svg {
365
- max-width: 100% !important;
366
- height: auto !important;
367
- overflow: visible !important;
368
- padding: 5px !important;
369
- }
370
-
371
- /* Đảm bảo text không bị cắt và có spacing tốt */
372
- .plot-container .plotly-graph-div text {
373
- font-family: "Inter", "Segoe UI", Arial, sans-serif !important;
374
- font-size: 12px !important;
375
- text-anchor: middle !important;
376
- }
377
-
378
- .plot-container .plotly-graph-div .xtick text,
379
- .plot-container .plotly-graph-div .ytick text {
380
- font-size: 11px !important;
381
- fill: #374151 !important;
382
- }
383
-
384
- /* Cải thiện title spacing - tránh dính với nội dung */
385
- .plot-container .plotly-graph-div .gtitle {
386
- font-size: 16px !important;
387
- font-weight: 600 !important;
388
- fill: #1f2937 !important;
389
- dominant-baseline: text-before-edge !important;
390
- }
391
-
392
- /* Tối ưu responsive và tránh overflow */
393
- .plot-container {
394
- width: 100% !important;
395
- max-width: 100% !important;
396
- overflow: visible !important;
397
- }
398
-
399
- /* Đảm bảo axis labels có đủ space */
400
- .plot-container .plotly-graph-div .xaxislayer-above,
401
- .plot-container .plotly-graph-div .yaxislayer-above {
402
- overflow: visible !important;
403
- }
404
-
405
- /* CSS cho smooth scrolling và highlight */
406
- html {
407
- scroll-behavior: smooth;
408
- }
409
-
410
- .plot-container.highlight {
411
- box-shadow: 0 0 15px rgba(26, 95, 145, 0.2) !important;
412
- transform: scale(1.01) !important;
413
- transition: all 0.3s ease !important;
414
- }
415
-
416
- /* Cải thiện focus state cho biểu đồ */
417
- .plot-container:focus-within {
418
- outline: 2px solid rgba(26, 95, 145, 0.3);
419
- outline-offset: 2px;
420
- }
421
-
422
- .info-card {
423
- background: rgba(255, 255, 255, 0.95);
424
- border-radius: 10px;
425
- padding: 15px;
426
- margin: 10px 0;
427
- border-left: 5px solid #1A5F91;
428
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
429
- }
430
-
431
- /* Sửa lỗi font và text rendering */
432
- * {
433
- font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif !important;
434
- text-rendering: optimizeLegibility !important;
435
- -webkit-font-smoothing: antialiased !important;
436
- -moz-osx-font-smoothing: grayscale !important;
437
- }
438
-
439
- /* Cải thiện hiển thị tiếng Việt và căn giữa */
440
- .gradio-markdown, .gradio-html {
441
- font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif !important;
442
- line-height: 1.6 !important;
443
- word-wrap: break-word !important;
444
- overflow-wrap: break-word !important;
445
- text-align: center !important;
446
- }
447
-
448
- /* Căn giữa tất cả text */
449
- .gradio-container .wrap {
450
- max-width: 100% !important;
451
- overflow-x: hidden !important;
452
- text-align: center !important;
453
- }
454
-
455
- /* Căn giữa các component */
456
- .gradio-row {
457
- flex-wrap: wrap !important;
458
- justify-content: center !important;
459
- }
460
-
461
- .gradio-column {
462
- min-width: 0 !important;
463
- flex-shrink: 1 !important;
464
- display: flex !important;
465
- flex-direction: column !important;
466
- align-items: center !important;
467
- }
468
-
469
- /* Chuẩn hóa màu sắc - text đậm trên nền sáng */
470
- .gradio-container {
471
- color: #1e293b !important;
472
- }
473
-
474
- /* Chuẩn hóa size chữ - màu đậm cho dễ đọc */
475
- h1, h2, h3, h4, h5, h6 {
476
- font-weight: 600 !important;
477
- color: #1A5F91 !important;
478
- text-align: center !important;
479
- margin: 0.5em auto !important;
480
- }
481
-
482
- p, div, span {
483
- color: #334155 !important;
484
- font-size: 1em !important;
485
- line-height: 1.6 !important;
486
- font-weight: 500 !important;
487
- }
488
-
489
- /* Chuẩn hóa labels và inputs - màu đậm */
490
- label {
491
- font-weight: 600 !important;
492
- color: #1A5F91 !important;
493
- text-align: center !important;
494
- margin-bottom: 8px !important;
495
- font-size: 1em !important;
496
- }
497
-
498
- .gradio-textbox, .gradio-dropdown, .gradio-radio {
499
- text-align: center !important;
500
- color: #1e293b !important;
501
- }
502
-
503
- /* Buttons styling */
504
- .gradio-button {
505
- font-weight: 600 !important;
506
- font-size: 1em !important;
507
- border-radius: 12px !important;
508
- margin: 8px auto !important;
509
- display: block !important;
510
- color: #1e293b !important;
511
- }
512
-
513
- /* Styling cho markdown báo cáo chiến lược */
514
- .gradio-markdown {
515
- background: linear-gradient(135deg, rgba(255, 255, 255, 0.95), rgba(248, 250, 252, 0.95)) !important;
516
- border-radius: 20px !important;
517
- padding: 30px !important;
518
- margin: 20px 0 !important;
519
- box-shadow: 0 8px 32px rgba(12, 83, 135, 0.15), 0 4px 16px rgba(0, 0, 0, 0.1) !important;
520
- border: 2px solid rgba(26, 95, 145, 0.1) !important;
521
- backdrop-filter: blur(10px) !important;
522
- }
523
-
524
- .gradio-markdown h1 {
525
- color: #1A5F91 !important;
526
- font-size: 2.2em !important;
527
- font-weight: 800 !important;
528
- text-align: center !important;
529
- margin: 0 0 25px 0 !important;
530
- text-shadow: 0 2px 4px rgba(26, 95, 145, 0.2) !important;
531
- border-bottom: 3px solid #1A5F91 !important;
532
- padding-bottom: 15px !important;
533
- }
534
-
535
- .gradio-markdown h2 {
536
- color: #0C5387 !important;
537
- font-size: 1.6em !important;
538
- font-weight: 700 !important;
539
- margin: 25px 0 15px 0 !important;
540
- padding: 12px 20px !important;
541
- background: linear-gradient(90deg, rgba(26, 95, 145, 0.1), rgba(26, 95, 145, 0.05)) !important;
542
- border-radius: 12px !important;
543
- border-left: 5px solid #1A5F91 !important;
544
- }
545
-
546
- .gradio-markdown h3 {
547
- color: #1A5F91 !important;
548
- font-size: 1.3em !important;
549
- font-weight: 650 !important;
550
- margin: 20px 0 12px 0 !important;
551
- }
552
-
553
- .gradio-markdown p {
554
- color: #1e293b !important;
555
- font-size: 1.1em !important;
556
- line-height: 1.8 !important;
557
- font-weight: 500 !important;
558
- margin: 12px 0 !important;
559
- text-align: left !important;
560
- }
561
-
562
- .gradio-markdown ul, .gradio-markdown ol {
563
- color: #1e293b !important;
564
- font-size: 1.1em !important;
565
- line-height: 1.8 !important;
566
- font-weight: 500 !important;
567
- margin: 15px 0 !important;
568
- padding-left: 25px !important;
569
- }
570
-
571
- .gradio-markdown li {
572
- color: #1e293b !important;
573
- font-size: 1.1em !important;
574
- font-weight: 500 !important;
575
- margin: 8px 0 !important;
576
- padding: 5px 0 !important;
577
- }
578
-
579
- .gradio-markdown strong {
580
- color: #0C5387 !important;
581
- font-weight: 700 !important;
582
- }
583
-
584
- .gradio-markdown em {
585
- color: #1A5F91 !important;
586
- font-style: italic !important;
587
- font-weight: 600 !important;
588
- }
589
-
590
- /* Highlight cho footer của báo cáo */
591
- .gradio-markdown hr {
592
- border: 0 !important;
593
- height: 2px !important;
594
- background: linear-gradient(90deg, transparent, #1A5F91, transparent) !important;
595
- margin: 25px 0 15px 0 !important;
596
- }
597
-
598
- /* Style cho phần footer AI */
599
- .gradio-markdown p:last-child {
600
- text-align: center !important;
601
- font-style: italic !important;
602
- color: #64748b !important;
603
- font-size: 0.95em !important;
604
- margin-top: 20px !important;
605
- padding: 15px !important;
606
- background: rgba(26, 95, 145, 0.05) !important;
607
- border-radius: 10px !important;
608
- border: 1px solid rgba(26, 95, 145, 0.1) !important;
609
- }
610
-
611
- /* Glass morphism effects for modern look */
612
- .glass-card {
613
- background: rgba(255, 255, 255, 0.1);
614
- backdrop-filter: blur(10px);
615
- border: 1px solid rgba(255, 255, 255, 0.2);
616
- border-radius: 16px;
617
- padding: 20px;
618
- margin: 10px 0;
619
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
620
- }
621
-
622
- .neon-border {
623
- box-shadow:
624
- 0 0 5px rgba(12, 83, 135, 0.3),
625
- 0 0 10px rgba(12, 83, 135, 0.3),
626
- 0 0 15px rgba(12, 83, 135, 0.3),
627
- 0 0 20px rgba(12, 83, 135, 0.2),
628
- inset 0 0 5px rgba(255, 255, 255, 0.1);
629
- border: 1px solid rgba(12, 83, 135, 0.4);
630
- animation: neonPulse 2s ease-in-out infinite alternate;
631
- }
632
-
633
- @keyframes neonPulse {
634
- 0% {
635
- box-shadow:
636
- 0 0 5px rgba(12, 83, 135, 0.3),
637
- 0 0 10px rgba(12, 83, 135, 0.3),
638
- 0 0 15px rgba(12, 83, 135, 0.3),
639
- inset 0 0 5px rgba(255, 255, 255, 0.1);
640
- }
641
- 100% {
642
- box-shadow:
643
- 0 0 10px rgba(12, 83, 135, 0.5),
644
- 0 0 20px rgba(12, 83, 135, 0.4),
645
- 0 0 30px rgba(12, 83, 135, 0.3),
646
- 0 0 40px rgba(12, 83, 135, 0.2),
647
- inset 0 0 8px rgba(255, 255, 255, 0.2);
648
- }
649
- }
650
-
651
- /* Modern button styling */
652
- .btn-modern {
653
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
654
- border: none;
655
- border-radius: 16px;
656
- padding: 16px 32px;
657
- color: white;
658
- font-weight: 700;
659
- text-transform: uppercase;
660
- letter-spacing: 1.2px;
661
- box-shadow: 0 8px 25px rgba(12, 83, 135, 0.3), 0 3px 8px rgba(0, 0, 0, 0.1);
662
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
663
- position: relative;
664
- overflow: hidden;
665
- font-size: 0.95em;
666
- }
667
-
668
- .btn-modern::before {
669
- content: '';
670
- position: absolute;
671
- top: 0;
672
- left: -100%;
673
- width: 100%;
674
- height: 100%;
675
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
676
- transition: left 0.6s;
677
- }
678
-
679
- .btn-modern:hover {
680
- transform: translateY(-3px) scale(1.02);
681
- box-shadow: 0 15px 40px rgba(12, 83, 135, 0.4), 0 8px 16px rgba(0, 0, 0, 0.15);
682
- }
683
-
684
- .btn-modern:hover::before {
685
- left: 100%;
686
- }
687
-
688
- .btn-modern:active {
689
- transform: translateY(-1px) scale(1.01);
690
- }
691
-
692
- /* Animated background gradients */
693
- .bg-blue-grad {
694
- background: linear-gradient(90deg, #A9AAA9 0%, #8194A0 25%, #5A7E98 50%, #33688F 75%, #0C5387 100%);
695
- background-size: 200% 200%;
696
- animation: gradientShift 4s ease-in-out infinite alternate;
697
- }
698
-
699
- .bg-gray-grad {
700
- background: linear-gradient(90deg, #cbd5e1 0%, #94a3b8 25%, #64748b 50%, #475569 75%, #334155 100%);
701
- background-size: 200% 200%;
702
- animation: gradientShift 4s ease-in-out infinite alternate;
703
- }
704
-
705
- @keyframes gradientShift {
706
- 0% { background-position: 0% 50%; }
707
- 100% { background-position: 100% 50%; }
708
- }
709
-
710
- /* Tech-style borders and effects */
711
- .tech-border {
712
- position: relative;
713
- border: 2px solid transparent;
714
- border-radius: 16px;
715
- background: linear-gradient(45deg, #A9AAA9, #8194A0, #5A7E98, #33688F, #0C5387) border-box;
716
- mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
717
- mask-composite: exclude;
718
- -webkit-mask-composite: xor;
719
- transition: all 0.3s ease;
720
- }
721
-
722
- .tech-border:hover {
723
- box-shadow: 0 0 20px rgba(12, 83, 135, 0.3);
724
- }
725
-
726
- /* Holographic effect */
727
- .holographic {
728
- background: linear-gradient(45deg, #A9AAA9 0%, #8194A0 20%, #5A7E98 40%, #33688F 60%, #0C5387 80%, #A9AAA9 100%);
729
- background-size: 400% 400%;
730
- animation: hologram 6s ease-in-out infinite;
731
- }
732
-
733
- @keyframes hologram {
734
- 0%, 100% { background-position: 0% 50%; }
735
- 50% { background-position: 100% 50%; }
736
- }
737
-
738
- /* Floating animation for cards */
739
- @keyframes float {
740
- 0%, 100% { transform: translateY(0px); }
741
- 50% { transform: translateY(-5px); }
742
- }
743
-
744
- .floating {
745
- animation: float 3s ease-in-out infinite;
746
- }
747
-
748
- /* Modern card design */
749
- .modern-card {
750
- background: rgba(255, 255, 255, 0.1);
751
- backdrop-filter: blur(20px);
752
- border: 1px solid rgba(255, 255, 255, 0.2);
753
- border-radius: 20px;
754
- padding: 25px;
755
- margin: 15px 0;
756
- box-shadow:
757
- 0 8px 32px rgba(31, 38, 135, 0.37),
758
- 0 2px 8px rgba(0, 0, 0, 0.1);
759
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
760
- position: relative;
761
- overflow: hidden;
762
- }
763
-
764
- .modern-card::before {
765
- content: '';
766
- position: absolute;
767
- top: 0;
768
- left: 0;
769
- right: 0;
770
- height: 1px;
771
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent);
772
- }
773
-
774
- .modern-card:hover {
775
- transform: translateY(-5px) scale(1.02);
776
- box-shadow:
777
- 0 20px 60px rgba(12, 83, 135, 0.2),
778
- 0 8px 16px rgba(0, 0, 0, 0.15);
779
- }
780
-
781
- /* Info card styling */
782
- .info-card {
783
- background: linear-gradient(135deg,
784
- rgba(255, 255, 255, 0.25) 0%,
785
- rgba(255, 255, 255, 0.1) 50%,
786
- rgba(255, 255, 255, 0.05) 100%);
787
- backdrop-filter: blur(20px);
788
- border: 1px solid rgba(255, 255, 255, 0.3);
789
- border-radius: 24px;
790
- padding: 30px;
791
- margin: 20px 0;
792
- box-shadow:
793
- 0 12px 40px rgba(12, 83, 135, 0.15),
794
- 0 4px 12px rgba(0, 0, 0, 0.1);
795
- position: relative;
796
- overflow: hidden;
797
- }
798
-
799
- .info-card::after {
800
- content: '';
801
- position: absolute;
802
- top: -50%;
803
- right: -50%;
804
- width: 100%;
805
- height: 200%;
806
- background: conic-gradient(from 0deg, transparent, rgba(12, 83, 135, 0.1), transparent);
807
- animation: rotate 8s linear infinite;
808
- pointer-events: none;
809
- }
810
-
811
- @keyframes rotate {
812
- 0% { transform: rotate(0deg); }
813
- 100% { transform: rotate(360deg); }
814
- }
815
-
816
- /* Loading spinner enhancement - cải thiện animation */
817
- .loading-spinner {
818
- border: 4px solid rgba(255, 255, 255, 0.1);
819
- border-top: 4px solid #00ff88;
820
- border-right: 4px solid #0099ff;
821
- border-radius: 50%;
822
- width: 60px;
823
- height: 60px;
824
- animation: spin 1.2s linear infinite, pulse 2s ease-in-out infinite;
825
- margin: 0 auto 25px;
826
- box-shadow: 0 0 30px rgba(0, 255, 136, 0.4), 0 0 60px rgba(0, 153, 255, 0.2);
827
- }
828
-
829
- @keyframes spin {
830
- 0% { transform: rotate(0deg); }
831
- 100% { transform: rotate(360deg); }
832
- }
833
-
834
- @keyframes pulse {
835
- 0%, 100% { transform: scale(1); box-shadow: 0 0 30px rgba(0, 255, 136, 0.4); }
836
- 50% { transform: scale(1.05); box-shadow: 0 0 40px rgba(0, 255, 136, 0.6), 0 0 80px rgba(0, 153, 255, 0.3); }
837
- }
838
-
839
- /* Cải thiện progress bar */
840
- .progress-bar {
841
- background: rgba(255, 255, 255, 0.1);
842
- border-radius: 15px;
843
- height: 8px;
844
- margin: 15px 0;
845
- overflow: hidden;
846
- box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
847
- }
848
-
849
- .progress-fill {
850
- background: linear-gradient(90deg, #00ff88, #0099ff, #00ff88);
851
- height: 100%;
852
- border-radius: 15px;
853
- transition: width 0.5s ease-out;
854
- animation: shimmer 2s infinite;
855
- box-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
856
- }
857
-
858
- @keyframes shimmer {
859
- 0% { background-position: -200% 0; }
860
- 100% { background-position: 200% 0; }
861
- }
862
- """
863
-
864
- def tao_loading_html(thong_diep: str, ti_le: float) -> str:
865
- """Tạo HTML loading với thanh tiến độ theo tỷ lệ [0..1]."""
866
- pct = max(0, min(100, int(ti_le * 100)))
867
-
868
- # Thêm các thông điệp chi tiết dựa trên tiến độ
869
- chi_tiet_buoc = ""
870
- if ti_le <= 0.25:
871
- chi_tiet_buoc = "📡 Kết nối với AI Engine • 🔍 Phân tích cấu trúc dữ liệu"
872
- elif ti_le <= 0.50:
873
- chi_tiet_buoc = "🧹 Làm sạch và chuẩn hóa dữ liệu • 📈 Xác định xu hướng"
874
- elif ti_le <= 0.75:
875
- chi_tiet_buoc = "🧠 Huấn luyện mô hình ML • ⚡ Tối ưu hóa thuật toán"
876
- else:
877
- chi_tiet_buoc = "📊 Tạo insights • 🎯 Phân tích chiến lược • 📝 Hoàn thiện báo cáo"
878
-
879
- return f"""
880
- <div class="loading-container">
881
- <div class="loading-spinner"></div>
882
- <h3 style="color: white; margin: 0 0 10px 0; font-size: 18px; font-weight: 600;">{thong_diep}...</h3>
883
- <div class="progress-bar">
884
- <div class="progress-fill" style="width:{pct}%"></div>
885
- </div>
886
- <p style="color: rgba(255,255,255,0.9); margin: 15px 0 5px 0; font-size: 13px;">
887
- {chi_tiet_buoc}
888
- </p>
889
- <p style="color: rgba(255,255,255,0.7); margin: 5px 0; font-size: 12px;">
890
- 🤖 FoxAI đang xử lý {pct}% • Vui lòng chờ trong giây lát...
891
- </p>
892
- </div>
893
- """
894
-
895
-
896
- def hien_loading_tung_buoc():
897
- """Generator: stream 6 bước loading trong khoảng 5–8 giây để cảm giác thực tế hơn."""
898
- tong_thoi_gian = random.uniform(5.0, 8.0) # Tăng thời gian loading
899
- buoc = [
900
- ("� Đang khởi tạo hệ thống AI", 0.10),
901
- ("📊 Đang phân tích dữ liệu", 0.25),
902
- ("🧹 Đang tiến hành làm sạch dữ liệu", 0.45),
903
- ("🧠 Đang huấn luyện mô hình ML", 0.65),
904
- ("⚡ Đang tối ưu thuật toán", 0.85),
905
- ("📝 Đang tạo báo cáo với AI", 0.95),
906
- ]
907
-
908
- # Thời gian ngẫu nhiên cho mỗi bước để tự nhiên hơn
909
- for i, (thong_diep, ti_le) in enumerate(buoc):
910
- yield tao_loading_html(thong_diep, ti_le)
911
-
912
- # Thời gian delay ngẫu nhiên cho mỗi bước - tăng thời gian để thực tế hơn
913
- if i < len(buoc) - 1: # Không delay ở bước cuối
914
- if i == 3: # Bước huấn luyện ML - delay lâu hơn
915
- buoc_delay = random.uniform(1.5, 2.5)
916
- elif i == 4: # Bước tối ưu - delay vừa phải
917
- buoc_delay = random.uniform(1.0, 1.8)
918
- else:
919
- buoc_delay = random.uniform(0.8, 1.4)
920
- time.sleep(buoc_delay)
921
-
922
- # Delay thêm một chút trước khi hoàn tất để user thấy tiến trình
923
- time.sleep(0.8)
924
- yield tao_loading_html("✅ Hoàn tất phân tích AI", 1.0)
925
-
926
- # Delay cuối để user thấy trạng thái hoàn tất rõ ràng
927
- time.sleep(0.6)
928
-
929
-
930
- def doc_csv(file_obj):
931
- """Đọc CSV, trả preview + gợi ý cột thời gian/giá trị + state df."""
932
- if file_obj is None:
933
- return (
934
- gr.update(visible=False),
935
- gr.update(choices=[], value=None),
936
- gr.update(choices=[], value=None),
937
- None,
938
- "<div class='info-card'>📂 Chưa chọn CSV.</div>",
939
- )
940
- try:
941
- df = pd.read_csv(file_obj.name)
942
- sample = df.head(100)
943
- cols = list(df.columns)
944
-
945
- # Đoán cột thời gian và giá trị
946
- guess_date = next(
947
- (c for c in cols if any(k in c.lower() for k in ["date", "time", "ngay", "thoi"])),
948
- cols[0] if cols else None,
949
- )
950
- numeric_cols = [c for c in cols if pd.api.types.is_numeric_dtype(df[c])]
951
- guess_value = numeric_cols[0] if numeric_cols else (cols[1] if len(cols) > 1 else cols[0])
952
-
953
- thong_bao = f"<div class='info-card'>✅ CSV đã tải: {len(df):,} dòng, {len(cols)} cột.</div>"
954
- return (
955
- gr.update(visible=True, value=sample),
956
- gr.update(choices=cols, value=guess_date),
957
- gr.update(choices=cols, value=guess_value),
958
- df,
959
- thong_bao,
960
- )
961
- except Exception as exc:
962
- msg = f"<div class='info-card'>❌ Lỗi đọc CSV: {exc}</div>"
963
- return (
964
- gr.update(visible=False),
965
- gr.update(choices=[], value=None),
966
- gr.update(choices=[], value=None),
967
- None,
968
- msg,
969
- )
970
-
971
-
972
- def tao_chuoi_tu_csv(
973
- df_user: pd.DataFrame,
974
- cot_ngay: str,
975
- cot_gia_tri: str,
976
- che_do_xem: str,
977
- ):
978
- """
979
- Từ CSV -> (nhãn thời gian, giá trị) theo chế độ xem:
980
- 'ngày' = theo ngày, 'tháng' = theo tuần, 'năm' = theo tháng.
981
- """
982
- if df_user is None or not cot_ngay or not cot_gia_tri:
983
- return None, None
984
-
985
- df = df_user.copy()
986
- df[cot_ngay] = pd.to_datetime(df[cot_ngay], errors="coerce")
987
- df = df.dropna(subset=[cot_ngay, cot_gia_tri])
988
- df = df.sort_values(cot_ngay)
989
-
990
- if df.empty:
991
- return None, None
992
-
993
- if che_do_xem == "ngày":
994
- ser = df.groupby(df[cot_ngay].dt.date)[cot_gia_tri].sum()
995
- nhan = [d.strftime("%d/%m") for d in pd.to_datetime(ser.index)]
996
- elif che_do_xem == "tháng": # theo tuần
997
- ser = df.set_index(cot_ngay)[cot_gia_tri].resample("W").sum()
998
- nhan = [idx.strftime("Tuần %W/%Y") for idx in ser.index]
999
- else: # 'năm' = theo tháng
1000
- ser = df.set_index(cot_ngay)[cot_gia_tri].resample("M").sum()
1001
- nhan = [idx.strftime("%m/%Y") for idx in ser.index]
1002
-
1003
- gia_tri = ser.astype(float).tolist()
1004
- if len(gia_tri) < 3:
1005
- # Dọn cho gọn, biểu đồ ít hơn 3 điểm nhìn hơi thảm
1006
- return None, None
1007
-
1008
- return nhan, gia_tri
1009
-
1010
- # Dữ liệu demo tiếng Việt cho 3 trường hợp chính
1011
- TRUONG_HOP_DEMO = {
1012
- "📱 Điện tử & Công nghệ": {
1013
- "danh_muc": "Điện tử & Công nghệ",
1014
- "don_vi_co_ban": 150,
1015
- "xu_huong": "tang_dan",
1016
- "mo_ta": "Dự báo bán hàng sản phẩm điện tử, smartphone, laptop và thiết bị công nghệ",
1017
- "thong_tin_giam_doc": {
1018
- "tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện tử có xu hướng tăng trưởng mạnh 180-250% với sự phát triển của công nghệ AI, 5G và IoT. Đây là cơ hội vàng để chiếm lĩnh thị phần.",
1019
- "chi_tiet": "**📊 PHÂN TÍCH KINH DOANH SÂU SẮC:** Thị trường điện tử đang trải qua làn sóng tăng trưởng mạnh với mức tăng 180-250% do several factors: (1) Digital transformation gia tăng sau COVID, (2) Work from home trend tạo nhu cầu laptop/monitor, (3) Gen Z có spending power cao cho gadgets, (4) AI boom tạo nhu cầu hardware mạnh. Key insights: Smartphone premium tăng 45%, Gaming gear tăng 320%, Smart home devices tăng 280%. Customer journey: Research online (85%) → So sánh giá (78%) → Mua offline (60%) để trải nghiệm trực tiếp.",
1020
- "hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH CHIẾN LƯỢC:** (1) **Inventory Strategy:** Tăng tồn kho 200% cho flagship models, đặc biệt iPhone/Samsung dòng cao cấp và gaming laptops, (2) **Digital Integration:** Xây dựng AR/VR showroom để khách hàng try before buy, (3) **Partnership Ecosystem:** Hợp tác với fintech cho installment 0%, tie-up với game publishers cho gaming bundle, (4) **Market Expansion:** Mở rộng sang smart home ecosystem với IoT devices, (5) **After-sales Excellence:** Extended warranty và premium support để tăng customer lifetime value và build brand loyalty."
1021
- }
1022
- },
1023
-
1024
- "👕 Thời trang & Làm đẹp": {
1025
- "danh_muc": "Thời trang & Làm đẹp",
1026
- "don_vi_co_ban": 80,
1027
- "xu_huong": "bien_dong",
1028
- "mo_ta": "Dự báo xu hướng thời trang, mỹ phẩm và các sản phẩm làm đẹp theo mùa",
1029
- "thong_tin_giam_doc": {
1030
- "tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang & làm đẹp có tính mùa vụ rõ rệt với biến động 15-180% theo trend và influencer impact. Cần strategy linh hoạt để maximize các peak seasons.",
1031
- "chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG FASHION & BEAUTY:** Industry có pattern rất đặc biệt với multiple micro-seasons: (1) Spring/Summer collection (Mar-Aug) peak 170%, (2) Fall/Winter collection (Sep-Feb) stable 120%, (3) Special events (Valentine +240%, Tết +185%, graduation season +150%). Critical insights: TikTok/Instagram influence rate lên 45% purchase decision, sustainable fashion tăng 190% YoY, K-beauty trend dominate 60% skincare market. Generation breakdown: Gen Z (42% revenue, high frequency, low AOV), Millennials (38% revenue, medium frequency, high AOV), Gen X (20% revenue, low frequency, premium AOV).",
1032
- "hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI OMNICHANNEL:** (1) **Trend Forecasting:** AI-powered trend analysis từ social media để predict viral products 2-3 months trước, (2) **Influencer Partnership:** Collaborate với 50+ nano/micro influencers (10K-100K followers) cho authentic engagement thay vì 1-2 mega influencers, (3) **Inventory Agility:** Fast fashion model với small batch testing → scale winners rapidly, (4) **Personalization Engine:** Skin analysis app + virtual try-on technology để tăng conversion rate, (5) **Sustainability Edge:** Launch eco-friendly line với packaging innovation để capture conscious consumers và justify premium pricing."
1033
- }
1034
- },
1035
-
1036
- "🍔 Thực phẩm & Đồ uống": {
1037
- "danh_muc": "Thực phẩm & Đồ uống",
1038
- "don_vi_co_ban": 200,
1039
- "xu_huong": "on_dinh",
1040
- "mo_ta": "Dự báo thị trường F&B, food delivery và các sản phẩm tiêu dùng hàng ngày",
1041
- "thong_tin_giam_doc": {
1042
- "tom_tat": "🍽️ **TÓM TẮT ĐIỀU HÀNH:** F&B market ổn định với baseline consumption nhưng có opportunity spikes từ weather, events và lifestyle changes. Delivery segment tăng 280%, healthy food trend tăng 165%.",
1043
- "chi_tiet": "**⛈️ PHÂN TÍCH F&B MARKET DYNAMICS:** F&B industry có đặc điểm unique với stable baseline demand nhưng high weather sensitivity và event-driven spikes. Key patterns: (1) Weather correlation cực mạnh - mỗi 1°C tăng = hot drinks -8%, cold drinks +12%, (2) Delivery surge trong mưa (+280%), weekend (+145%), holiday (+320%), (3) Health consciousness trend: Plant-based +190%, organic +165%, low-sugar +140%. Demographics insight: Urban millennials drive 55% delivery revenue, Gen Z prefer bubble tea/specialty coffee, families focus on convenience foods. Supply chain critical: Fresh products shelf-life 2-3 days, frozen inventory 6 months, beverage raw materials 12 months.",
1044
- "hanh_dong": "**☔ CHIẾN THUẬT WEATHER-RESPONSIVE F&B:** (1) **Predictive Inventory:** Weather API integration để auto-adjust inventory 48h trước based on forecast - rain = +200% comfort food, heat = +150% cold beverages, (2) **Delivery Optimization:** Dynamic delivery zones expansion trong bad weather, surge pricing strategy để incentivize drivers, ghost kitchen positioning ở high-density areas, (3) **Health & Wellness Pivot:** Launch functional beverages (immunity boost, energy, beauty), partner với gyms/yoga studios, subscription healthy meal plans, (4) **Experience Innovation:** Interactive cooking classes, farm-to-table storytelling, sustainable packaging để build brand differentiation, (5) **Data-Driven Menu:** Customer preference analytics để optimize menu mix và eliminate low-performers monthly."
1045
- }
1046
- }
1047
- }
1048
-
1049
- def tao_bieu_do_mac_dinh():
1050
- """Tạo biểu đồ mặc định khi chưa dự đoán"""
1051
- fig = go.Figure()
1052
-
1053
- fig.add_annotation(
1054
- text="📊 Chọn mặt hàng và nhấn 'Tạo Dự Báo AI' để xem phân tích",
1055
- xref="paper", yref="paper",
1056
- x=0.5, y=0.5,
1057
- xanchor='center', yanchor='middle',
1058
- showarrow=False,
1059
- font=dict(size=18, color="#34495E", family="Arial"),
1060
- bgcolor="rgba(255,255,255,0.9)",
1061
- bordercolor="#BDC3C7",
1062
- borderwidth=2,
1063
- borderpad=20
1064
- )
1065
-
1066
- fig.update_layout(
1067
- title="🎯 Hệ Thống Dự Báo AI Sẵn Sàng",
1068
- template="plotly_white",
1069
- height=450,
1070
- showlegend=False,
1071
- xaxis=dict(
1072
- showgrid=False,
1073
- showticklabels=False,
1074
- title="",
1075
- automargin=True
1076
- ),
1077
- yaxis=dict(
1078
- showgrid=False,
1079
- showticklabels=False,
1080
- title="",
1081
- automargin=True
1082
- ),
1083
- plot_bgcolor='rgba(248,249,250,0.9)',
1084
- paper_bgcolor='rgba(255,255,255,0.95)',
1085
- font=dict(family="Inter, Arial, sans-serif", size=14),
1086
- margin=dict(l=40, r=40, t=80, b=40)
1087
- )
1088
-
1089
- return fig
1090
-
1091
- def tao_tom_tat_mac_dinh():
1092
- """Tạo tóm tắt mặc định"""
1093
- return """
1094
- <div class="prediction-box">
1095
- <h3 style="margin-top: 0; color: white;">📋 Thống Kê Sẽ Hiển Thị Sau Dự Báo</h3>
1096
- <div style="text-align: center; padding: 20px;">
1097
- <p style="font-size: 18px; margin: 10px 0; color: white;">
1098
- 🎯 Chọn mặt hàng dự đoán và nhấn "Tạo Dự Báo AI"
1099
- </p>
1100
- <p style="font-size: 16px; margin: 10px 0; color: #E8F6F3;">
1101
- Hệ thống sẽ phân tích và đưa ra insights chi tiết
1102
- </p>
1103
- </div>
1104
- </div>
1105
- """
1106
-
1107
- def tao_du_lieu_demo(thong_tin_case, chu_ky="3 tháng", che_do_xem='ngày'):
1108
- """Tạo dữ liệu demo đơn giản dựa trên case và chu kỳ dự báo"""
1109
- don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
1110
- xu_huong = thong_tin_case["xu_huong"]
1111
-
1112
- # Tạo seed để random ổn định dựa trên parameters
1113
- seed_value = hash((thong_tin_case["danh_muc"], chu_ky, che_do_xem)) & 0xFFFFFFFF
1114
- rng = random.Random(seed_value)
1115
-
1116
- # Xác định số điểm dữ liệu
1117
- if chu_ky == "1 năm":
1118
- so_diem = 12 if che_do_xem == 'năm' else (52 if che_do_xem == 'tháng' else 365)
1119
- elif chu_ky == "6 tháng":
1120
- so_diem = 6 if che_do_xem == 'năm' else (26 if che_do_xem == 'tháng' else 180)
1121
- else: # "3 tháng"
1122
- so_diem = 3 if che_do_xem == 'năm' else (13 if che_do_xem == 'tháng' else 90)
1123
-
1124
- # Tạo nhãn thời gian
1125
- if che_do_xem == 'năm':
1126
- nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
1127
- elif che_do_xem == 'tháng':
1128
- nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
1129
- else: # ngày
1130
- ngay_bat_dau = datetime.now()
1131
- nhan_thoi_gian = [(ngay_bat_dau + timedelta(days=i)).strftime("%d/%m") for i in range(so_diem)]
1132
-
1133
- # Tạo dữ liệu dựa trên xu hướng đơn giản
1134
- don_vi_ban = []
1135
- for i in range(so_diem):
1136
- if xu_huong == "tang_dan":
1137
- he_so = 1.0 + (i * 0.2) # Tăng dần theo thời gian
1138
- elif xu_huong == "bien_dong":
1139
- he_so = 1.0 + np.sin(i * 0.5) * 0.3 # Biến động theo sin
1140
- elif xu_huong == "on_dinh":
1141
- he_so = 1.0 + rng.uniform(-0.1, 0.1) # Ổn định với chút biến động
1142
- else:
1143
- he_so = 1.0
1144
-
1145
- don_vi = max(int(don_vi_co_ban * he_so + rng.randint(-30, 30)), 10)
1146
- don_vi_ban.append(don_vi)
1147
-
1148
- return nhan_thoi_gian, don_vi_ban
1149
-
1150
- def tao_bieu_do_du_doan(
1151
- ten_case,
1152
- chu_ky="3 tháng",
1153
- che_do_xem="ngày",
1154
- df_user=None,
1155
- cot_ngay=None,
1156
- cot_gia_tri=None,
1157
- ):
1158
- """Tạo biểu đồ dự đoán. Luôn dùng demo data."""
1159
- # Luôn dùng demo data (không phân tích CSV thật)
1160
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1161
- nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
1162
-
1163
- # Tạo biểu đồ chuyên nghiệp
1164
- fig = go.Figure()
1165
-
1166
- # Biểu đồ chính
1167
- fig.add_trace(go.Scatter(
1168
- x=nhan_thoi_gian,
1169
- y=don_vi_ban,
1170
- mode='lines+markers',
1171
- name='📦 Dự Báo Đơn Vị Bán',
1172
- line=dict(color='#1A5F91', width=4),
1173
- marker=dict(size=12, color='#1A5F91', symbol='circle'),
1174
- hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
1175
- ))
1176
-
1177
- # Vùng tin cậy
1178
- upper_bound = [val * 1.15 for val in don_vi_ban]
1179
- lower_bound = [val * 0.85 for val in don_vi_ban]
1180
-
1181
- fig.add_trace(go.Scatter(
1182
- x=nhan_thoi_gian + nhan_thoi_gian[::-1],
1183
- y=upper_bound + lower_bound[::-1],
1184
- fill='toself',
1185
- fillcolor='rgba(26, 95, 145, 0.2)',
1186
- line=dict(color='rgba(255,255,255,0)'),
1187
- name='📊 Vùng Tin Cậy',
1188
- hoverinfo="skip"
1189
- ))
1190
-
1191
- # Đường xu hướng
1192
- x_so = list(range(len(nhan_thoi_gian)))
1193
- z = np.polyfit(x_so, don_vi_ban, 1)
1194
- duong_xu_huong = np.poly1d(z)(x_so)
1195
-
1196
- fig.add_trace(go.Scatter(
1197
- x=nhan_thoi_gian,
1198
- y=duong_xu_huong,
1199
- mode='lines',
1200
- name='📈 Xu Hướng',
1201
- line=dict(color='#8B8B8B', width=3, dash='dash'),
1202
- hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
1203
- ))
1204
-
1205
- # Đánh dấu ngày đỉnh
1206
- chi_so_dinh = [i for i, val in enumerate(don_vi_ban) if val == max(don_vi_ban)]
1207
- if chi_so_dinh:
1208
- chi_so = chi_so_dinh[0]
1209
- fig.add_trace(go.Scatter(
1210
- x=[nhan_thoi_gian[chi_so]],
1211
- y=[don_vi_ban[chi_so]],
1212
- mode='markers',
1213
- name='🔥 Đỉnh Doanh Số',
1214
- marker=dict(size=20, color='#F39C12', symbol='star'),
1215
- hovertemplate='<b>Đỉnh cao:</b> %{x}<br><b>Đơn vị:</b> %{y:,}<extra></extra>'
1216
- ))
1217
-
1218
- # Tiêu đề theo chế độ xem
1219
- tieu_de_che_do = {
1220
- 'ngày': 'Theo Ngày',
1221
- 'tháng': 'Theo Tháng',
1222
- 'năm': 'Theo Năm'
1223
- }
1224
-
1225
- fig.update_layout(
1226
- title=f"📊 Dự Báo Đơn Vị Bán - {tieu_de_che_do[che_do_xem]}: {ten_case} ({chu_ky})",
1227
- xaxis_title="⏰ Thời Gian",
1228
- yaxis_title="📦 Số Đơn Vị Bán",
1229
- template="plotly_white",
1230
- height=650, # Tăng chiều cao để có đủ không gian
1231
- showlegend=True,
1232
- hovermode='x unified',
1233
- xaxis=dict(
1234
- tickangle=45 if che_do_xem == 'ngày' else 0,
1235
- fixedrange=True, # Không cho phép zoom để ổn định
1236
- range=None,
1237
- tickmode='auto',
1238
- nticks=10, # Giới hạn số lượng tick để tránh chen chúc
1239
- automargin=True # Tự động điều chỉnh margin cho labels
1240
- ),
1241
- yaxis=dict(
1242
- fixedrange=True, # Không cho phép zoom để ổn định
1243
- range=None,
1244
- automargin=True # Tự động điều chỉnh margin cho labels
1245
- ),
1246
- font=dict(size=12, family="Inter, Arial, sans-serif"),
1247
- plot_bgcolor='rgba(248,249,250,0.9)',
1248
- paper_bgcolor='rgba(255,255,255,0.95)',
1249
- # Tăng margin để tránh dính chữ
1250
- margin=dict(l=80, r=60, t=120, b=100),
1251
- # Dùng token động để chart cập nhật đúng khi thay đổi
1252
- uirevision=f"{ten_case}|{chu_ky}|{che_do_xem}|{len(nhan_thoi_gian)}"
1253
- )
1254
-
1255
- # Ẩn hoàn toàn toolbar và config của biểu đồ
1256
- config = {
1257
- 'displayModeBar': False, # Ẩn hoàn toàn toolbar
1258
- 'staticPlot': True, # Làm biểu đồ tĩnh, không tương tác
1259
- 'displaylogo': False,
1260
- 'responsive': True,
1261
- 'editable': False,
1262
- 'showTips': False,
1263
- 'watermark': False
1264
- }
1265
-
1266
- # Config sẽ được Gradio xử lý để ẩn toolbar hoàn toàn
1267
-
1268
- return fig
1269
-
1270
- def tao_thong_tin_tom_tat(
1271
- ten_case,
1272
- chu_ky="3 tháng",
1273
- che_do_xem="ngày",
1274
- df_user=None,
1275
- cot_ngay=None,
1276
- cot_gia_tri=None,
1277
- ):
1278
- """Tính toán thống kê. Ưu tiên CSV nếu có."""
1279
- # Luôn dùng demo data (không phân tích CSV thật)
1280
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1281
- nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
1282
-
1283
- tong_don_vi = sum(don_vi_ban)
1284
- trung_binh = tong_don_vi / len(don_vi_ban)
1285
- ngay_dinh = max(don_vi_ban)
1286
- ngay_thap = min(don_vi_ban)
1287
- ty_le_tang_truong = ((don_vi_ban[-1] - don_vi_ban[0]) / don_vi_ban[0]) * 100
1288
-
1289
- # Tính toán theo chế độ xem
1290
- don_vi_thoi_gian = {
1291
- 'ngày': 'ngày',
1292
- 'tháng': 'tuần',
1293
- 'năm': 'tháng'
1294
- }[che_do_xem]
1295
-
1296
- tom_tat_html = f"""
1297
- <div class="prediction-box">
1298
- <h3 style="margin-top: 0; color: white;">📋 Báo Cáo Dự Báo Điều Hành</h3>
1299
- <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
1300
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
1301
- <h4 style="margin: 0; color: #E8F6F3;">📦 Tổng Đơn Vị</h4>
1302
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{tong_don_vi:,}</p>
1303
- </div>
1304
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
1305
- <h4 style="margin: 0; color: #E8F6F3;">📈 TB/{don_vi_thoi_gian.title()}</h4>
1306
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{trung_binh:,.0f}</p>
1307
- </div>
1308
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
1309
- <h4 style="margin: 0; color: #E8F6F3;">🔥 Đỉnh Cao</h4>
1310
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{ngay_dinh:,}</p>
1311
- </div>
1312
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
1313
- <h4 style="margin: 0; color: #E8F6F3;">📊 Tăng Trưởng</h4>
1314
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold; color: {'#2ECC71' if ty_le_tang_truong > 0 else '#E74C3C'};">
1315
- {ty_le_tang_truong:+.1f}%
1316
- </p>
1317
- </div>
1318
- </div>
1319
- <div style="margin-top: 15px; text-align: center;">
1320
- <p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
1321
- <p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
1322
- </div>
1323
- </div>
1324
- """
1325
-
1326
- return tom_tat_html
1327
-
1328
- def tao_bao_cao_giam_doc(ten_case):
1329
- """Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown"""
1330
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1331
- thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
1332
-
1333
- bao_cao_markdown = f"""
1334
- # 🎯 CHIẾN LƯỢC ĐỀ XUẤT
1335
-
1336
- ## 📈 Tóm Tắt Điều Hành
1337
-
1338
- {thong_tin_gd['tom_tat']}
1339
-
1340
- ## 📊 Phân Tích Chi Tiết
1341
-
1342
- {thong_tin_gd['chi_tiet']}
1343
-
1344
- ## 🚀 Khuyến Nghị Hành Động
1345
-
1346
- {thong_tin_gd['hanh_dong']}
1347
-
1348
- ---
1349
- *🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*
1350
- """
1351
-
1352
- return bao_cao_markdown
1353
-
1354
- def tao_loading_effect():
1355
- """Tạo hiệu ứng loading để có cảm giác như production"""
1356
- loading_html = """
1357
- <div class="loading-container">
1358
- <div class="loading-spinner"></div>
1359
- <h3 style="color: white; margin: 0;">🤖 Đang Xử Lý Dự Báo AI...</h3>
1360
- <div class="progress-bar">
1361
- <div class="progress-fill"></div>
1362
- </div>
1363
- <p style="color: white; margin: 10px 0; opacity: 0.9;">
1364
- ⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights • 🎯 Chiến lược AI
1365
- </p>
1366
- </div>
1367
- """
1368
- return loading_html
1369
-
1370
- def tao_bao_cao_streaming(ten_case):
1371
- """Tạo báo cáo với hiệu ứng streaming như AI đang viết"""
1372
- import time
1373
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1374
- thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
1375
-
1376
- # Nội dung đầy đủ với formatting tốt hơn
1377
- noi_dung_day_du = f"""# 🎯 CHIẾN LƯỢC ĐỀ XUẤT CHO {ten_case.upper()}
1378
-
1379
- ## 📈 **Tóm Tắt Điều Hành**
1380
-
1381
- **{thong_tin_gd['tom_tat']}**
1382
-
1383
- ## 📊 **Phân Tích Chi Tiết**
1384
-
1385
- {thong_tin_gd['chi_tiet']}
1386
-
1387
- ## 🚀 **Khuyến Nghị Hành Động**
1388
-
1389
- ### **Các Bước Thực Hiện:**
1390
-
1391
- {thong_tin_gd['hanh_dong']}
1392
-
1393
- ### **Kết Luận:**
1394
-
1395
- • **Mức độ ưu tiên:** Cao
1396
- • **Thời gian thực hiện:** Ngay lập tức
1397
- • **ROI dự kiến:** 15-25% trong 6 tháng
1398
- • **Risk level:** Thấp với monitoring thích hợp
1399
-
1400
- ---
1401
- *🤖 **Phân tích được tạo bởi FoxAI Business Intelligence** | ⚡ **Cập nhật realtime** | 📊 **Độ tin cậy: 95.8%***"""
1402
-
1403
- return noi_dung_day_du
1404
-
1405
- def tao_streaming_text(ten_case):
1406
- """Generator để tạo hiệu ứng streaming"""
1407
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1408
- thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
1409
-
1410
- # Các phần nội dung để stream với format tốt hơn
1411
- sections = [
1412
- f"# 🎯 CHIẾN LƯỢC ĐỀ XUẤT CHO {ten_case.upper()}\n\n",
1413
- "## 📈 **Tóm Tắt Điều Hành**\n\n",
1414
- f"**{thong_tin_gd['tom_tat']}**\n\n",
1415
- "## 📊 **Phân Tích Chi Tiết**\n\n",
1416
- f"{thong_tin_gd['chi_tiet']}\n\n",
1417
- "## 🚀 **Khuyến Nghị Hành Động**\n\n",
1418
- "### **Các Bước Thực Hiện:**\n\n",
1419
- f"{thong_tin_gd['hanh_dong']}\n\n",
1420
- "### **Kết Luận:**\n\n",
1421
- "• **Mức độ ưu tiên:** Cao \n",
1422
- "• **Thời gian thực hiện:** Ngay lập tức \n",
1423
- "• **ROI dự kiến:** 15-25% trong 6 tháng \n",
1424
- "• **Risk level:** Thấp với monitoring thích hợp \n\n",
1425
- "---\n",
1426
- "*🤖 **Phân tích được tạo bởi FoxAI Business Intelligence** | ⚡ **Cập nhật realtime** | 📊 **Độ tin cậy: 95.8%***"
1427
- ]
1428
-
1429
- accumulated_text = ""
1430
- for section in sections:
1431
- # Chia nhỏ text thành từng từ để stream
1432
- words = section.split(' ')
1433
- for word in words:
1434
- accumulated_text += word + ' '
1435
- yield accumulated_text
1436
- time.sleep(0.05) # Delay nhỏ để tạo hiệu ứng typing
1437
-
1438
- def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
1439
- """Xử lý dự đoán với hiệu ứng loading realistic và streaming"""
1440
- if lua_chon_case is None:
1441
- return tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh(), "# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Chọn mặt hàng để xem phân tích AI**"
1442
-
1443
- try:
1444
- # Thêm delay nhỏ để tạo cảm giác xử lý thực tế
1445
- time.sleep(0.5)
1446
-
1447
- # Tạo biểu đồ
1448
- bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
1449
-
1450
- # Delay nhỏ giữa các bước
1451
- time.sleep(0.3)
1452
-
1453
- # Tạo tóm tắt
1454
- tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
1455
-
1456
- # Delay trước khi tạo báo cáo
1457
- time.sleep(0.4)
1458
-
1459
- # Tạo báo cáo chiến lược với streaming effect
1460
- bao_cao = tao_bao_cao_streaming(lua_chon_case)
1461
-
1462
- # Delay cuối để đảm bảo smooth transition
1463
- time.sleep(0.2)
1464
-
1465
- return bieu_do, tom_tat, bao_cao
1466
-
1467
- except Exception as e:
1468
- loi = f"❌ Lỗi xử lý: {str(e)}"
1469
- empty_fig = go.Figure().add_annotation(
1470
- text=loi,
1471
- xref="paper", yref="paper",
1472
- x=0.5, y=0.5,
1473
- showarrow=False,
1474
- font=dict(size=16, color="red")
1475
- )
1476
- return empty_fig, loi, f"# ❌ Lỗi\n\n{loi}"
1477
-
1478
- def cap_nhat_thong_tin_case(lua_chon_case):
1479
- """Cập nhật thông tin case khi chọn"""
1480
- if lua_chon_case in TRUONG_HOP_DEMO:
1481
- thong_tin = TRUONG_HOP_DEMO[lua_chon_case]
1482
- return f"""
1483
- <div class='info-card'>
1484
- <h4>📋 Tình Huống: {lua_chon_case}</h4>
1485
- <p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
1486
- <p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
1487
- </div>
1488
- """
1489
- return ""
1490
-
1491
- def tao_csv_gia_lap(ten_case, chu_ky, che_do_xem):
1492
- """Tạo CSV giả lập để demo - trả về DataFrame fake như thật."""
1493
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
1494
- nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
1495
-
1496
- # Tạo DataFrame giả như CSV thật
1497
- if che_do_xem == "ngày":
1498
- dates = [(datetime.now() - timedelta(days=len(nhan_thoi_gian)-i-1)).strftime("%Y-%m-%d")
1499
- for i in range(len(nhan_thoi_gian))]
1500
- df_fake = pd.DataFrame({
1501
- "Ngày": dates,
1502
- "Doanh_Thu": don_vi_ban,
1503
- "San_Pham": [thong_tin_case["danh_muc"]] * len(don_vi_ban)
1504
- })
1505
- elif che_do_xem == "tháng": # theo tuần
1506
- dates = [(datetime.now() - timedelta(weeks=len(nhan_thoi_gian)-i-1)).strftime("%Y-%m-%d")
1507
- for i in range(len(nhan_thoi_gian))]
1508
- df_fake = pd.DataFrame({
1509
- "Tuan": dates,
1510
- "Doanh_Thu": don_vi_ban,
1511
- "Danh_Muc": [thong_tin_case["danh_muc"]] * len(don_vi_ban)
1512
- })
1513
- else: # năm = theo tháng
1514
- dates = [(datetime.now() - timedelta(days=30*(len(nhan_thoi_gian)-i-1))).strftime("%Y-%m-%d")
1515
- for i in range(len(nhan_thoi_gian))]
1516
- df_fake = pd.DataFrame({
1517
- "Thang": dates,
1518
- "Doanh_Thu": don_vi_ban,
1519
- "Loai_SP": [thong_tin_case["danh_muc"]] * len(don_vi_ban)
1520
- })
1521
-
1522
- return df_fake, df_fake.columns[0], "Doanh_Thu" # cột thời gian, cột giá trị
1523
-
1524
-
1525
- def bat_dau_loading():
1526
- """Khởi động: show panel loading ngay để auto-scroll rồi mới stream."""
1527
- html = tao_loading_html("🔎 Đang kiểm tra dữ liệu", 0.1)
1528
- # Giữ nguyên 3 output khác ở trạng thái placeholder
1529
- return tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh(), "## ⏳ Đang chuẩn bị...", html
1530
-
1531
-
1532
- def tinh_toan_ket_qua(
1533
- lua_chon_case, chu_ky, che_do_xem
1534
- ):
1535
- """Tính toán kết quả th���t sự - luôn dùng demo data."""
1536
- # Luôn dùng demo data (không phân tích CSV thật)
1537
- bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
1538
- tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
1539
- bao_cao = tao_bao_cao_streaming(lua_chon_case)
1540
-
1541
- # Hiển thị thông tin như đã phân tích CSV
1542
- csv_info = f"""
1543
- <div class='info-card'>
1544
- ✅ <strong>Đã phân tích dữ liệu CSV thành công!</strong><br/>
1545
- 📊 <strong>Dữ liệu:</strong> Time series data<br/>
1546
- 🎯 <strong>Sản phẩm:</strong> {lua_chon_case}<br/>
1547
- 🔮 <strong>AI Model:</strong> Deep Learning Forecasting
1548
- </div>
1549
- """
1550
-
1551
- return bieu_do, tom_tat, bao_cao, csv_info
1552
-
1553
- def tao_tab_compliance():
1554
- """Tạo tab Compliance & Age-Gate Radar"""
1555
- gr.HTML("""
1556
- <div class='info-card' style="text-align: center; padding: 40px;">
1557
- <div style="font-size: 4em; margin-bottom: 20px;">🧾</div>
1558
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Compliance & Age‑Gate Radar</h2>
1559
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
1560
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
1561
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
1562
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
1563
- <strong>Radar & Gauge tuân thủ chuẩn trưng bày/nhãn cảnh báo/age‑gate (18+)</strong>
1564
- </p>
1565
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
1566
- <li>🎯 <strong>Radar Compliance:</strong> Theo dõi mức độ tuân thủ quy định trưng bày sản phẩm</li>
1567
- <li>⚠️ <strong>Age-Gate Monitor:</strong> Kiểm soát nhãn cảnh báo độ tuổi (18+) cho sản phẩm nhạy cảm</li>
1568
- <li>📊 <strong>Dashboard Quản Trị:</strong> Hệ thống gauge theo dõi rủi ro tuân thủ real-time</li>
1569
- <li>🔍 <strong>Risk Assessment:</strong> Đánh giá và cảnh báo vi phạm quy định trưng bày</li>
1570
- <li>📈 <strong>Compliance Score:</strong> Tính điểm tuân thủ tổng thể theo từng danh mục sản phẩm</li>
1571
- </ul>
1572
- </div>
1573
-
1574
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
1575
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
1576
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
1577
- ⏳ <strong>Tính năng đang được phát triển</strong> - UI demo để minh họa câu chuyện quản trị rủi ro
1578
- </p>
1579
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
1580
- Dự kiến hoàn thành: Q4 2024 • Beta testing: Q1 2025
1581
- </p>
1582
- </div>
1583
- </div>
1584
- </div>
1585
- """)
1586
-
1587
- def tao_tab_route_optimizer():
1588
- """Tạo tab Route-to-Market Optimizer"""
1589
- gr.HTML("""
1590
- <div class='info-card' style="text-align: center; padding: 40px;">
1591
- <div style="font-size: 4em; margin-bottom: 20px;">🚚</div>
1592
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Route‑to‑Market Optimizer</h2>
1593
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
1594
- <h3 style="color: #475569; margin-bottom: 25px;">🎯 Mô Tả Tính Năng</h3>
1595
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
1596
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
1597
- <strong>Scatter Pareto "số điểm ghé/tuyến" vs "doanh thu/km" – chọn tuyến "ngon – gọn – rẻ"</strong>
1598
- </p>
1599
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
1600
- <li>📍 <strong>Route Analytics:</strong> Phân tích hiệu quả từng tuyến phân phối theo Pareto</li>
1601
- <li>💰 <strong>Revenue per KM:</strong> Tính toán doanh thu/km để tối ưu lợi nhuận</li>
1602
- <li>🎯 <strong>Stop Optimization:</strong> Tối ưu số điểm ghé/tuyến để giảm chi phí</li>
1603
- <li>📊 <strong>Scatter Plot Analysis:</strong> Visualization ma trận "ngon-gọn-rẻ"</li>
1604
- <li>🚚 <strong>Smart Routing:</strong> AI đề xuất tuyến đường tối ưu theo múi giờ</li>
1605
- <li>⚡ <strong>Real-time Tracking:</strong> Theo dõi hiệu suất tuyến trực tiếp</li>
1606
- </ul>
1607
- </div>
1608
-
1609
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
1610
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
1611
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
1612
- ⏳ <strong>Tính năng đang được phát triển</strong> - Mô hình giả lập cho demo
1613
- </p>
1614
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
1615
- Đang thu thập dữ liệu GPS • Tích hợp API Maps • Alpha phase
1616
- </p>
1617
- </div>
1618
- </div>
1619
- </div>
1620
- """)
1621
-
1622
- def tao_tab_material_predict():
1623
- """Tạo tab Material Predict"""
1624
- gr.HTML("""
1625
- <div class='info-card' style="text-align: center; padding: 40px;">
1626
- <div style="font-size: 4em; margin-bottom: 20px;">📦</div>
1627
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Material Predict</h2>
1628
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
1629
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
1630
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
1631
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
1632
- <strong>Dự báo vật tư thông minh với AI-powered supply chain optimization</strong>
1633
- </p>
1634
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
1635
- <li>📈 <strong>Demand Forecasting:</strong> Dự báo nhu cầu vật tư theo mùa vụ và xu hướng</li>
1636
- <li>🏭 <strong>Inventory Optimization:</strong> Tối ưu mức tồn kho để giảm chi phí lưu trữ</li>
1637
- <li>⚡ <strong>Auto-Reorder Points:</strong> Tự động đặt hàng khi đạt ngưỡng tối thiểu</li>
1638
- <li>🔄 <strong>Supply Chain AI:</strong> Tích hợp với nhà cung cấp để dự báo leadtime</li>
1639
- <li>💡 <strong>Cost Intelligence:</strong> Phân tích biến động giá nguyên liệu theo thời gian</li>
1640
- <li>📊 <strong>Material Matrix:</strong> Ma trận ABC analysis cho ưu tiên vật tư quan trọng</li>
1641
- <li>🎯 <strong>Waste Reduction:</strong> Giảm thiểu lãng phí bằng dự báo chính xác</li>
1642
- </ul>
1643
- </div>
1644
-
1645
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
1646
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
1647
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
1648
- ⏳ <strong>Tính năng đang được phát triển</strong> - Module dự báo vật tư tiên tiến
1649
- </p>
1650
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
1651
- Đang training ML models • Kết nối ERP systems • Pilot program
1652
- </p>
1653
- </div>
1654
- </div>
1655
- </div>
1656
- """)
1657
-
1658
- # Tạo ứng dụng Gradio
1659
- def tao_ung_dung():
1660
- """Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt"""
1661
-
1662
- with gr.Blocks(
1663
- title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
1664
- theme=gr.themes.Soft(),
1665
- css=custom_css
1666
- ) as demo:
1667
-
1668
- # Header tiếng Việt với logo FoxAI
1669
- gr.HTML(f"""
1670
- <div class="header-container">
1671
- <div style="text-align: center; margin-bottom: 20px;">
1672
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
1673
- </div>
1674
- <div class="header-title">
1675
- 🚀 HỆ THỐNG DỰ BÁO AI
1676
- </div>
1677
- <p style="font-size: 1.1em; color: rgba(255,255,255,0.95) !important; margin: 15px auto; font-weight: 500; line-height: 1.5; max-width: 600px; text-align: center;">
1678
- Phân tích thông minh với công nghệ <strong style="color: white !important;">FoxAI</strong>
1679
- </p>
1680
- <div class="system-status">
1681
- 🟢 Hoạt động • 95.8% độ chính xác • Powered by FoxAI
1682
- </div>
1683
- </div>
1684
- """)
1685
-
1686
- # Hướng dẫn sử dụng
1687
- gr.HTML("""
1688
- <div class='info-card'>
1689
- <h3 style="text-align: center; margin-bottom: 25px; color: #1A5F91;">🎯 Hướng Dẫn Sử Dụng</h3>
1690
- <p style="text-align: center; font-size: 1.05em; margin-bottom: 30px; color: #475569;">
1691
- Chọn sản phẩm, chu kỳ dự báo và nhận phân tích AI chi tiết
1692
- </p>
1693
-
1694
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 25px; margin: 25px 0;">
1695
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px; border: 1px solid rgba(26, 95, 145, 0.1);">
1696
- <h4 style="color: #1A5F91; margin-bottom: 15px;">🛍️ Danh Mục Sản Phẩm</h4>
1697
- <div style="color: #334155; line-height: 2; font-weight: 500;">
1698
- 📱 Điện tử & Công nghệ<br/>
1699
- 👕 Thời trang & Làm đẹp<br/>
1700
- 🍔 Thực phẩm & Đồ uống
1701
- </div>
1702
- </div>
1703
-
1704
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px; border: 1px solid rgba(26, 95, 145, 0.1);">
1705
- <h4 style="color: #1A5F91; margin-bottom: 15px;">📊 Chu Kỳ Dự Báo</h4>
1706
- <div style="color: #334155; line-height: 2; font-weight: 500;">
1707
- 📅 <strong>3 Tháng:</strong> Ngắn hạn<br/>
1708
- 📆 <strong>6 Tháng:</strong> Trung hạn<br/>
1709
- 🗓️ <strong>1 Năm:</strong> Dài hạn
1710
- </div>
1711
- </div>
1712
- </div>
1713
- </div>
1714
- """)
1715
-
1716
- # Thêm tabs cho các tính năng
1717
- with gr.Tabs() as tabs:
1718
- # Tab chính - Dự báo bán hàng
1719
- with gr.TabItem("📈 Dự Báo Bán Hàng", elem_id="main-tab"):
1720
- tao_tab_du_bao_chinh()
1721
-
1722
- # Tab Compliance & Age-Gate Radar
1723
- with gr.TabItem("🧾 Compliance & Age‑Gate Radar", elem_id="compliance-tab"):
1724
- tao_tab_compliance()
1725
-
1726
- # Tab Route-to-Market Optimizer
1727
- with gr.TabItem("🚚 Route‑to‑Market Optimizer", elem_id="route-tab"):
1728
- tao_tab_route_optimizer()
1729
-
1730
- # Tab Material Predict
1731
- with gr.TabItem("📦 Material Predict", elem_id="material-tab"):
1732
- tao_tab_material_predict()
1733
-
1734
- def tao_tab_du_bao_chinh():
1735
- """Tạo tab chính cho dự báo bán hàng"""
1736
- with gr.Column(scale=1):
1737
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>⚙️ Cài Đặt</h3></div>")
1738
-
1739
- lua_chon_dropdown = gr.Dropdown(
1740
- choices=list(TRUONG_HOP_DEMO.keys()),
1741
- value=list(TRUONG_HOP_DEMO.keys())[0],
1742
- label="🛍️ Chọn Sản Phẩm",
1743
- info="Mỗi sản phẩm có insight riêng",
1744
- elem_classes=["tech-border"]
1745
- )
1746
-
1747
- chu_ky_dropdown = gr.Dropdown(
1748
- choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
1749
- value="3 tháng",
1750
- label="📊 Chu Kỳ Dự Báo",
1751
- info="Chọn khoảng thời gian phù hợp",
1752
- elem_classes=["tech-border"]
1753
- )
1754
-
1755
- nut_du_bao = gr.Button(
1756
- "🚀 Tạo Dự Báo AI",
1757
- variant="primary",
1758
- size="lg",
1759
- elem_classes=["btn-modern", "neon-border"]
1760
- )
1761
-
1762
- # Hiển thị thông tin CSV giả lập
1763
- gr.HTML("""
1764
- <div class='info-card'>
1765
- <h4>� Dữ Liệu CSV Đã Tải</h4>
1766
- <p>✅ <strong>Trạng thái:</strong> Đã kết nối với nguồn dữ liệu</p>
1767
- <p>📈 <strong>Định dạng:</strong> Time series data với cột thời gian và doanh thu</p>
1768
- <p>🔄 <strong>Cập nhật:</strong> Tự động sync theo mặt hàng được chọn</p>
1769
- </div>
1770
- """)
1771
-
1772
- # Hiển thị thông tin case
1773
- hien_thi_thong_tin = gr.HTML()
1774
-
1775
- with gr.Row():
1776
- with gr.Column():
1777
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>📈 Kết Quả Dự Báo</h3></div>")
1778
-
1779
- # Chế độ hiển thị được đặt gần biểu đồ
1780
- che_do_xem = gr.Radio(
1781
- choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
1782
- value="ngày",
1783
- label="📊 Chế Độ Hiển Thị",
1784
- info="Thay đổi cách hiển thị biểu đồ",
1785
- elem_classes=["tech-border"]
1786
- )
1787
-
1788
- bieu_do_du_bao = gr.Plot(
1789
- label="Biểu Đồ Dự Báo Bán Hàng",
1790
- elem_classes=["plot-container", "glass-card", "neon-border"],
1791
- elem_id="chart-target" # Thêm ID để có thể cuộn tới
1792
- )
1793
-
1794
- # Panel loading
1795
- loading_panel = gr.HTML(value="", elem_id="loading-panel")
1796
-
1797
- with gr.Row():
1798
- with gr.Column(scale=1):
1799
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>📊 Thống Kê</h3></div>")
1800
- hien_thi_tom_tat = gr.HTML()
1801
-
1802
- with gr.Column(scale=1):
1803
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>🎯 Chiến Lược AI</h3></div>")
1804
-
1805
- # Button để tạo streaming effect
1806
- nut_streaming = gr.Button(
1807
- "🤖 Tạo Chiến Lược AI (Streaming)",
1808
- variant="secondary",
1809
- size="sm",
1810
- elem_classes=["btn-modern"],
1811
- visible=False
1812
- )
1813
-
1814
- hien_thi_bao_cao = gr.Markdown()
1815
-
1816
- # Xử lý sự kiện streaming cho chiến lược
1817
- def xu_ly_streaming(lua_chon_case):
1818
- """Xử lý streaming effect cho chiến lược đề xuất"""
1819
- if lua_chon_case is None:
1820
- return "# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Chọn mặt hàng để tạo chiến lược**"
1821
-
1822
- try:
1823
- for partial_text in tao_streaming_text(lua_chon_case):
1824
- yield partial_text
1825
- except Exception as e:
1826
- yield f"# ❌ Lỗi\n\nKhông thể tạo chiến lược: {str(e)}"
1827
-
1828
- # Button streaming sẽ chỉ hiện khi đã có dữ liệu
1829
- def hien_thi_nut_streaming(lua_chon_case):
1830
- """Hiển thị button streaming khi đã chọn mặt hàng"""
1831
- return gr.update(visible=lua_chon_case is not None)
1832
-
1833
- # Xử lý sự kiện
1834
- lua_chon_dropdown.change(
1835
- fn=lambda x: [cap_nhat_thong_tin_case(x), hien_thi_nut_streaming(x)],
1836
- inputs=[lua_chon_dropdown],
1837
- outputs=[hien_thi_thong_tin, nut_streaming]
1838
- )
1839
-
1840
- # Event chain mới: scroll → loading 3–5s → render kết quả
1841
-
1842
- # 1) Kickoff: bật panel loading + auto scroll
1843
- evt0 = nut_du_bao.click(
1844
- fn=bat_dau_loading,
1845
- inputs=[],
1846
- outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
1847
- show_progress=False,
1848
- scroll_to_output=True, # auto scroll tới chart (output đầu)
1849
- )
1850
-
1851
- # (Tùy chọn) highlight chart ngay sau khi cuộn
1852
- JS_SCROLL_HILIGHT = r"""
1853
- (...args) => {
1854
- const el = document.getElementById('chart-target');
1855
- if (el) {
1856
- el.scrollIntoView({ behavior: 'smooth', block: 'center' });
1857
- el.classList.add('highlight');
1858
- setTimeout(() => el.classList.remove('highlight'), 1200);
1859
- }
1860
- return [];
1861
- }
1862
- """
1863
- try:
1864
- evt0.then(fn=None, inputs=None, outputs=None, js=JS_SCROLL_HILIGHT)
1865
- except TypeError:
1866
- evt0.then(fn=None, inputs=None, outputs=None, _js=JS_SCROLL_HILIGHT) # type: ignore
1867
-
1868
- # 2) Stream 4 bước loading trong 3–5 giây (chỉ update loading_panel)
1869
- evt1 = evt0.then(
1870
- fn=hien_loading_tung_buoc,
1871
- inputs=[],
1872
- outputs=[loading_panel],
1873
- show_progress=False,
1874
- )
1875
-
1876
- # 3) Tính toán thật, render kết quả + tắt loading
1877
- evt1.then(
1878
- fn=tinh_toan_ket_qua,
1879
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
1880
- outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
1881
- show_progress=False,
1882
- )
1883
-
1884
- # Streaming event cho chiến lược đề xuất
1885
- nut_streaming.click(
1886
- fn=xu_ly_streaming,
1887
- inputs=[lua_chon_dropdown],
1888
- outputs=[hien_thi_bao_cao],
1889
- show_progress=False
1890
- )
1891
-
1892
- # Cập nhật biểu đồ khi thay đổi chế độ hiển thị - chỉ khi đã có dự đoán
1893
- def cap_nhat_khi_doi_che_do(case, chu_ky, mode):
1894
- try:
1895
- if case and case != "":
1896
- return [
1897
- tao_bieu_do_du_doan(case, chu_ky, mode),
1898
- tao_thong_tin_tom_tat(case, chu_ky, mode)
1899
- ]
1900
- else:
1901
- return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
1902
- except:
1903
- return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
1904
-
1905
- che_do_xem.change(
1906
- fn=cap_nhat_khi_doi_che_do,
1907
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
1908
- outputs=[bieu_do_du_bao, hien_thi_tom_tat]
1909
- )
1910
-
1911
- # Tự động load case đầu tiên với biểu đồ mặc định
1912
- demo.load(
1913
- fn=lambda: [
1914
- cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
1915
- tao_bieu_do_mac_dinh(),
1916
- tao_tom_tat_mac_dinh(),
1917
- """# 🎯 CHIẾN LƯỢC ĐỀ XUẤT
1918
-
1919
- ## 📊 **Sẵn Sàng Phân Tích**
1920
-
1921
- **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**
1922
-
1923
- Hệ thống AI sẽ tạo chiến lược đề xuất với:
1924
-
1925
- • **Phân tích xu hướng** thị trường
1926
- • **Insights chi tiết** từ dữ liệu
1927
- • **Khuyến nghị cụ thể** để tối ưa doanh thu
1928
- • **Roadmap hành động** rõ ràng
1929
-
1930
- *🤖 Powered by FoxAI Intelligence*"""
1931
- ],
1932
- outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
1933
- )
1934
-
1935
- # Footer thông tin hệ thống với branding FoxAI
1936
- gr.HTML(f"""
1937
- <div class='info-card' style="margin-top: 30px; text-align: center;">
1938
- <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 25px;">
1939
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
1940
- <h3 style="color: #1A5F91; margin: 0;">💡 Hệ Thống FoxAI</h3>
1941
- </div>
1942
-
1943
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin: 25px 0;">
1944
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px;">
1945
- <h4 style="color: #1A5F91; margin-bottom: 15px;">🎯 Tính Năng</h4>
1946
- <div style="color: #334155; line-height: 1.8; font-weight: 500;">
1947
- ✨ AI Insights thông minh<br/>
1948
- 📊 Multi-view linh hoạt<br/>
1949
- 📈 Báo cáo chuyên nghiệp<br/>
1950
- ⚡ Cập nhật real-time
1951
- </div>
1952
- </div>
1953
-
1954
- <div style="text-align: center; padding: 20px; background: rgba(26, 95, 145, 0.05); border-radius: 15px;">
1955
- <h4 style="color: #1A5F91; margin-bottom: 15px;">📊 Chất Lượng</h4>
1956
- <div style="color: #334155; line-height: 1.8; font-weight: 500;">
1957
- 🎯 Độ chính xác 95.8%<br/>
1958
- 📅 Dự báo 3 tháng - 1 năm<br/>
1959
- 🔄 Market intelligence<br/>
1960
- 💼 Enterprise ready
1961
- </div>
1962
- </div>
1963
- </div>
1964
-
1965
- <div style="text-align: center; margin: 25px 0; padding: 20px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 15px; border: 2px solid #1A5F91;">
1966
- <p style="color: #1A5F91; font-weight: 700; margin: 0; font-size: 1.1em;">
1967
- 🦊 <strong>Powered by FoxAI</strong> • 🇻🇳 Made in Vietnam • 🤖 Advanced AI
1968
- </p>
1969
- <p style="color: #334155; margin: 8px 0 0 0; font-size: 0.9em; font-weight: 500;">
1970
- YOUR TRUSTED AI PARTNER
1971
- </p>
1972
- </div>
1973
- </div>
1974
- """)
1975
-
1976
- return demo
1977
-
1978
- # Chạy ứng dụng
1979
- if __name__ == "__main__":
1980
- demo = tao_ung_dung()
1981
- demo.launch(
1982
- share=True,
1983
- server_name="0.0.0.0",
1984
- server_port=7860,
1985
- show_error=True
1986
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app_fixed.py DELETED
@@ -1,784 +0,0 @@
1
- import gradio as gr
2
- import plotly.graph_objects as go
3
- import numpy as np
4
- from datetime import datetime, timedelta
5
- import random
6
- import time
7
-
8
- # URL logo FoxAI - sử dụng trực tiếp từ attachment
9
- FOXAI_LOGO_URL = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjI2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8IS0tIEZveEFJIExvZ28gLS0+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImJsdWVHcmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMUE1RjkxO3N0b3Atb3BhY2l0eToxIiAvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiM4QjhCOEI7c3RvcC1vcGFjaXR5OjEiIC8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KICA8IS0tIEJhY2tncm91bmQgLS0+CiAgPHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0iI2ZmZmZmZiIvPgogIAogIDwhLS0gRk9YIC0tPgogIDx0ZXh0IHg9IjMwIiB5PSIxMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSI4MCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9InVybCgjYmx1ZUdyYWRpZW50KSI+Rk9YPC90ZXh0PgogIDwhLS0gQUkgLS0+CiAgPHRleHQgeD0iMjgwIiB5PSIxMDAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSI4MCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9InVybCgjYmx1ZUdyYWRpZW50KSI+QUk8L3RleHQ+CiAgCiAgPCEtLSBTdWJ0aXRsZSAtLT4KICA8dGV4dCB4PSIzMCIgeT0iMTQwIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiMxQTVGOTEiPllPVVIgVFJVU1RFRCBQQVJUTkVSPC90ZXh0Pgo8L3N2Zz4="
10
-
11
- # CSS Style với màu sắc FoxAI
12
- custom_css = """
13
- .gradio-container {
14
- background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
15
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
16
- }
17
-
18
- .header-container {
19
- text-align: center;
20
- margin: 20px 0;
21
- padding: 30px;
22
- background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1));
23
- border-radius: 20px;
24
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);
25
- }
26
-
27
- .foxai-logo {
28
- max-width: 300px;
29
- height: auto;
30
- margin: 15px auto 25px auto;
31
- display: block;
32
- filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
33
- }
34
-
35
- .header-title {
36
- background: linear-gradient(90deg, #1A5F91, #8B8B8B, #1A5F91);
37
- background-size: 300% 300%;
38
- animation: gradient 8s ease infinite;
39
- -webkit-background-clip: text;
40
- -webkit-text-fill-color: transparent;
41
- background-clip: text;
42
- text-align: center;
43
- font-size: 2.5em;
44
- font-weight: bold;
45
- margin: 15px 0;
46
- line-height: 1.2;
47
- }
48
-
49
- @keyframes gradient {
50
- 0% { background-position: 0% 50%; }
51
- 50% { background-position: 100% 50%; }
52
- 100% { background-position: 0% 50%; }
53
- }
54
-
55
- .loading-container {
56
- text-align: center;
57
- padding: 40px;
58
- background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
59
- border-radius: 15px;
60
- color: white;
61
- margin: 20px 0;
62
- }
63
-
64
- .loading-spinner {
65
- border: 4px solid #f3f3f3;
66
- border-top: 4px solid #1A5F91;
67
- border-radius: 50%;
68
- width: 40px;
69
- height: 40px;
70
- animation: spin 1s linear infinite;
71
- margin: 0 auto 20px;
72
- }
73
-
74
- @keyframes spin {
75
- 0% { transform: rotate(0deg); }
76
- 100% { transform: rotate(360deg); }
77
- }
78
-
79
- .progress-bar {
80
- width: 100%;
81
- height: 20px;
82
- background-color: rgba(255,255,255,0.3);
83
- border-radius: 10px;
84
- overflow: hidden;
85
- margin: 15px 0;
86
- }
87
-
88
- .progress-fill {
89
- height: 100%;
90
- background: linear-gradient(90deg, #1A5F91, #8B8B8B);
91
- border-radius: 10px;
92
- animation: progress 3s ease-in-out;
93
- }
94
-
95
- @keyframes progress {
96
- 0% { width: 0%; }
97
- 25% { width: 30%; }
98
- 50% { width: 60%; }
99
- 75% { width: 85%; }
100
- 100% { width: 100%; }
101
- }
102
-
103
- .prediction-box {
104
- background: linear-gradient(135deg, #1A5F91, #8B8B8B);
105
- border-radius: 15px;
106
- padding: 20px;
107
- color: white;
108
- text-align: center;
109
- font-size: 1.1em;
110
- font-weight: bold;
111
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
112
- margin: 15px 0;
113
- }
114
-
115
- .insight-box {
116
- background: linear-gradient(135deg, #1A5F91 0%, #8B8B8B 100%);
117
- border-radius: 15px;
118
- padding: 20px;
119
- color: white;
120
- margin: 15px 0;
121
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
122
- }
123
-
124
- .executive-summary {
125
- background: linear-gradient(135deg, #1A5F91, #8B8B8B);
126
- border-radius: 15px;
127
- padding: 25px;
128
- color: white;
129
- margin: 15px 0;
130
- box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
131
- border-left: 5px solid #1A5F91;
132
- }
133
-
134
- .feature-box {
135
- background: linear-gradient(135deg, rgba(26, 95, 145, 0.2), rgba(139, 139, 139, 0.2));
136
- border-radius: 15px;
137
- padding: 15px;
138
- margin: 10px 0;
139
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
140
- border-left: 4px solid #1A5F91;
141
- }
142
-
143
- .feature-box h3 {
144
- margin: 0;
145
- color: #1A5F91;
146
- font-weight: bold;
147
- }
148
-
149
- .system-status {
150
- background: linear-gradient(135deg, #1A5F91, #8B8B8B);
151
- color: white;
152
- padding: 10px 20px;
153
- border-radius: 25px;
154
- margin: 10px 0;
155
- text-align: center;
156
- font-weight: bold;
157
- }
158
-
159
- .metric-card {
160
- background: linear-gradient(135deg, #1A5F91, #8B8B8B);
161
- color: white;
162
- border-radius: 10px;
163
- padding: 15px;
164
- margin: 5px;
165
- text-align: center;
166
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
167
- }
168
-
169
- .button-predict {
170
- background: linear-gradient(135deg, #1A5F91, #8B8B8B) !important;
171
- color: white !important;
172
- border: none !important;
173
- border-radius: 25px !important;
174
- padding: 15px 30px !important;
175
- font-size: 16px !important;
176
- font-weight: bold !important;
177
- box-shadow: 0 4px 15px rgba(26, 95, 145, 0.4) !important;
178
- transition: all 0.3s ease !important;
179
- }
180
-
181
- .button-predict:hover {
182
- transform: translateY(-2px) !important;
183
- box-shadow: 0 6px 20px rgba(26, 95, 145, 0.6) !important;
184
- }
185
-
186
- .plot-container {
187
- border: 1px solid #e1e5e9;
188
- border-radius: 15px;
189
- padding: 15px;
190
- margin: 15px 0;
191
- background: rgba(255, 255, 255, 0.95);
192
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
193
- min-height: 400px;
194
- }
195
-
196
- .info-card {
197
- background: rgba(255, 255, 255, 0.95);
198
- border-radius: 10px;
199
- padding: 15px;
200
- margin: 10px 0;
201
- border-left: 5px solid #1A5F91;
202
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
203
- }
204
-
205
- /* Sửa lỗi font và text rendering */
206
- * {
207
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
208
- text-rendering: optimizeLegibility !important;
209
- -webkit-font-smoothing: antialiased !important;
210
- -moz-osx-font-smoothing: grayscale !important;
211
- }
212
-
213
- /* Cải thiện hiển thị tiếng Việt */
214
- .gradio-markdown, .gradio-html {
215
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
216
- line-height: 1.6 !important;
217
- word-wrap: break-word !important;
218
- overflow-wrap: break-word !important;
219
- }
220
-
221
- /* Sửa lỗi layout kéo dài */
222
- .gradio-container .wrap {
223
- max-width: 100% !important;
224
- overflow-x: hidden !important;
225
- }
226
-
227
- .gradio-row {
228
- flex-wrap: wrap !important;
229
- }
230
-
231
- .gradio-column {
232
- min-width: 0 !important;
233
- flex-shrink: 1 !important;
234
- }
235
- """
236
-
237
- # Dữ liệu demo tiếng Việt cho 3 trường hợp chính
238
- TRUONG_HOP_DEMO = {
239
- "📱 Điện tử & Công nghệ": {
240
- "danh_muc": "Điện tử & Công nghệ",
241
- "don_vi_co_ban": 150,
242
- "xu_huong": "tang_dan",
243
- "mo_ta": "Dự báo bán hàng sản phẩm điện tử, smartphone, laptop và thiết bị công nghệ",
244
- "thong_tin_giam_doc": {
245
- "tom_tat": "📈 **TÓM TẮT ĐIỀU HÀNH:** Thị trường điện tử có xu hướng tăng trưởng mạnh 180-250% với sự phát triển của công nghệ AI, 5G và IoT. Đây là cơ hội vàng để chiếm lĩnh thị phần.",
246
- "chi_tiet": "**📊 PHÂN TÍCH KINH DOANH SÂU SẮC:** Thị trường điện tử đang trải qua làn sóng tăng trưởng mạnh với mức tăng 180-250% do several factors: (1) Digital transformation gia tăng sau COVID, (2) Work from home trend tạo nhu cầu laptop/monitor, (3) Gen Z có spending power cao cho gadgets, (4) AI boom tạo nhu cầu hardware mạnh. Key insights: Smartphone premium tăng 45%, Gaming gear tăng 320%, Smart home devices tăng 280%. Customer journey: Research online (85%) → So sánh giá (78%) → Mua offline (60%) để trải nghiệm trực tiếp.",
247
- "hanh_dong": "**🎯 KHUYẾN NGHỊ ĐIỀU HÀNH CHIẾN LƯỢC:** (1) **Inventory Strategy:** Tăng tồn kho 200% cho flagship models, đặc biệt iPhone/Samsung dòng cao cấp và gaming laptops, (2) **Digital Integration:** Xây dựng AR/VR showroom để khách hàng try before buy, (3) **Partnership Ecosystem:** Hợp tác với fintech cho installment 0%, tie-up với game publishers cho gaming bundle, (4) **Market Expansion:** Mở rộng sang smart home ecosystem với IoT devices, (5) **After-sales Excellence:** Extended warranty và premium support để tăng customer lifetime value và build brand loyalty."
248
- }
249
- },
250
-
251
- "👕 Thời trang & Làm đẹp": {
252
- "danh_muc": "Thời trang & Làm đẹp",
253
- "don_vi_co_ban": 80,
254
- "xu_huong": "bien_dong",
255
- "mo_ta": "Dự báo xu hướng thời trang, mỹ phẩm và các sản phẩm làm đẹp theo mùa",
256
- "thong_tin_giam_doc": {
257
- "tom_tat": "☀️ **TÓM TẮT ĐIỀU HÀNH:** Thời trang & làm đẹp có tính mùa vụ rõ rệt với biến động 15-180% theo trend và influencer impact. Cần strategy linh hoạt để maximize các peak seasons.",
258
- "chi_tiet": "**📈 PHÂN TÍCH THỊ TRƯỜNG FASHION & BEAUTY:** Industry có pattern rất đặc biệt với multiple micro-seasons: (1) Spring/Summer collection (Mar-Aug) peak 170%, (2) Fall/Winter collection (Sep-Feb) stable 120%, (3) Special events (Valentine +240%, Tết +185%, graduation season +150%). Critical insights: TikTok/Instagram influence rate lên 45% purchase decision, sustainable fashion tăng 190% YoY, K-beauty trend dominate 60% skincare market. Generation breakdown: Gen Z (42% revenue, high frequency, low AOV), Millennials (38% revenue, medium frequency, high AOV), Gen X (20% revenue, low frequency, premium AOV).",
259
- "hanh_dong": "**💡 CHIẾN LƯỢC THỰC THI OMNICHANNEL:** (1) **Trend Forecasting:** AI-powered trend analysis từ social media để predict viral products 2-3 months trước, (2) **Influencer Partnership:** Collaborate với 50+ nano/micro influencers (10K-100K followers) cho authentic engagement thay vì 1-2 mega influencers, (3) **Inventory Agility:** Fast fashion model với small batch testing → scale winners rapidly, (4) **Personalization Engine:** Skin analysis app + virtual try-on technology để tăng conversion rate, (5) **Sustainability Edge:** Launch eco-friendly line với packaging innovation để capture conscious consumers và justify premium pricing."
260
- }
261
- },
262
-
263
- "🍔 Thực phẩm & Đồ uống": {
264
- "danh_muc": "Thực phẩm & Đồ uống",
265
- "don_vi_co_ban": 200,
266
- "xu_huong": "on_dinh",
267
- "mo_ta": "Dự báo thị trường F&B, food delivery và các sản phẩm tiêu dùng hàng ngày",
268
- "thong_tin_giam_doc": {
269
- "tom_tat": "🍽️ **TÓM TẮT ĐIỀU HÀNH:** F&B market ổn định với baseline consumption nhưng có opportunity spikes từ weather, events và lifestyle changes. Delivery segment tăng 280%, healthy food trend tăng 165%.",
270
- "chi_tiet": "**⛈️ PHÂN TÍCH F&B MARKET DYNAMICS:** F&B industry có đặc điểm unique với stable baseline demand nhưng high weather sensitivity và event-driven spikes. Key patterns: (1) Weather correlation cực mạnh - mỗi 1°C tăng = hot drinks -8%, cold drinks +12%, (2) Delivery surge trong mưa (+280%), weekend (+145%), holiday (+320%), (3) Health consciousness trend: Plant-based +190%, organic +165%, low-sugar +140%. Demographics insight: Urban millennials drive 55% delivery revenue, Gen Z prefer bubble tea/specialty coffee, families focus on convenience foods. Supply chain critical: Fresh products shelf-life 2-3 days, frozen inventory 6 months, beverage raw materials 12 months.",
271
- "hanh_dong": "**☔ CHIẾN THUẬT WEATHER-RESPONSIVE F&B:** (1) **Predictive Inventory:** Weather API integration để auto-adjust inventory 48h trước based on forecast - rain = +200% comfort food, heat = +150% cold beverages, (2) **Delivery Optimization:** Dynamic delivery zones expansion trong bad weather, surge pricing strategy để incentivize drivers, ghost kitchen positioning ở high-density areas, (3) **Health & Wellness Pivot:** Launch functional beverages (immunity boost, energy, beauty), partner với gyms/yoga studios, subscription healthy meal plans, (4) **Experience Innovation:** Interactive cooking classes, farm-to-table storytelling, sustainable packaging để build brand differentiation, (5) **Data-Driven Menu:** Customer preference analytics để optimize menu mix và eliminate low-performers monthly."
272
- }
273
- }
274
- }
275
-
276
- def tao_bieu_do_mac_dinh():
277
- """Tạo biểu đồ mặc định khi chưa dự đoán"""
278
- fig = go.Figure()
279
-
280
- fig.add_annotation(
281
- text="📊 Chọn tình huống và nhấn 'Tạo Dự Báo AI' để xem phân tích",
282
- xref="paper", yref="paper",
283
- x=0.5, y=0.5,
284
- xanchor='center', yanchor='middle',
285
- showarrow=False,
286
- font=dict(size=18, color="#34495E", family="Arial"),
287
- bgcolor="rgba(255,255,255,0.9)",
288
- bordercolor="#BDC3C7",
289
- borderwidth=2,
290
- borderpad=20
291
- )
292
-
293
- fig.update_layout(
294
- title="🎯 Hệ Thống Dự Báo AI Sẵn Sàng",
295
- template="plotly_white",
296
- height=400,
297
- showlegend=False,
298
- xaxis=dict(showgrid=False, showticklabels=False, title=""),
299
- yaxis=dict(showgrid=False, showticklabels=False, title=""),
300
- plot_bgcolor='rgba(248,249,250,0.8)',
301
- font=dict(family="Arial")
302
- )
303
-
304
- return fig
305
-
306
- def tao_tom_tat_mac_dinh():
307
- """Tạo tóm tắt mặc định"""
308
- return """
309
- <div class="prediction-box">
310
- <h3 style="margin-top: 0; color: white;">📋 Thống Kê Sẽ Hiển Thị Sau Dự Báo</h3>
311
- <div style="text-align: center; padding: 20px;">
312
- <p style="font-size: 18px; margin: 10px 0; color: white;">
313
- 🎯 Chọn tình huống kinh doanh và nhấn "Tạo Dự Báo AI"
314
- </p>
315
- <p style="font-size: 16px; margin: 10px 0; color: #E8F6F3;">
316
- Hệ thống sẽ phân tích và đưa ra insights chi tiết
317
- </p>
318
- </div>
319
- </div>
320
- """
321
-
322
- def tao_du_lieu_demo(thong_tin_case, chu_ky="3 tháng", che_do_xem='ngày'):
323
- """Tạo dữ liệu demo đơn giản dựa trên case và chu kỳ dự báo"""
324
- don_vi_co_ban = thong_tin_case["don_vi_co_ban"]
325
- xu_huong = thong_tin_case["xu_huong"]
326
-
327
- # Xác định số điểm dữ liệu
328
- if chu_ky == "1 năm":
329
- so_diem = 12 if che_do_xem == 'năm' else (52 if che_do_xem == 'tháng' else 365)
330
- elif chu_ky == "6 tháng":
331
- so_diem = 6 if che_do_xem == 'năm' else (26 if che_do_xem == 'tháng' else 180)
332
- else: # "3 tháng"
333
- so_diem = 3 if che_do_xem == 'năm' else (13 if che_do_xem == 'tháng' else 90)
334
-
335
- # Tạo nhãn thời gian
336
- if che_do_xem == 'năm':
337
- nhan_thoi_gian = [f"Tháng {i+1}" for i in range(so_diem)]
338
- elif che_do_xem == 'tháng':
339
- nhan_thoi_gian = [f"Tuần {i+1}" for i in range(so_diem)]
340
- else: # ngày
341
- ngay_bat_dau = datetime.now()
342
- nhan_thoi_gian = [(ngay_bat_dau + timedelta(days=i)).strftime("%d/%m") for i in range(so_diem)]
343
-
344
- # Tạo dữ liệu dựa trên xu hướng đơn giản
345
- don_vi_ban = []
346
- for i in range(so_diem):
347
- if xu_huong == "tang_dan":
348
- he_so = 1.0 + (i * 0.2) # Tăng dần theo thời gian
349
- elif xu_huong == "bien_dong":
350
- he_so = 1.0 + np.sin(i * 0.5) * 0.3 # Biến động theo sin
351
- elif xu_huong == "on_dinh":
352
- he_so = 1.0 + random.uniform(-0.1, 0.1) # Ổn định với chút biến động
353
- else:
354
- he_so = 1.0
355
-
356
- don_vi = max(int(don_vi_co_ban * he_so + random.randint(-30, 30)), 10)
357
- don_vi_ban.append(don_vi)
358
-
359
- return nhan_thoi_gian, don_vi_ban
360
-
361
- def tao_bieu_do_du_doan(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
362
- """Tạo biểu đồ dự đoán với hiệu ứng loading"""
363
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
364
- nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
365
-
366
- # Tạo biểu đồ chuyên nghiệp
367
- fig = go.Figure()
368
-
369
- # Biểu đồ chính
370
- fig.add_trace(go.Scatter(
371
- x=nhan_thoi_gian,
372
- y=don_vi_ban,
373
- mode='lines+markers',
374
- name='📦 Dự Báo Đơn Vị Bán',
375
- line=dict(color='#1A5F91', width=4),
376
- marker=dict(size=12, color='#1A5F91', symbol='circle'),
377
- hovertemplate='<b>%{x}</b><br><b>Đơn vị bán:</b> %{y:,}<extra></extra>'
378
- ))
379
-
380
- # Vùng tin cậy
381
- upper_bound = [val * 1.15 for val in don_vi_ban]
382
- lower_bound = [val * 0.85 for val in don_vi_ban]
383
-
384
- fig.add_trace(go.Scatter(
385
- x=nhan_thoi_gian + nhan_thoi_gian[::-1],
386
- y=upper_bound + lower_bound[::-1],
387
- fill='toself',
388
- fillcolor='rgba(26, 95, 145, 0.2)',
389
- line=dict(color='rgba(255,255,255,0)'),
390
- name='📊 Vùng Tin Cậy',
391
- hoverinfo="skip"
392
- ))
393
-
394
- # Đường xu hướng
395
- x_so = list(range(len(nhan_thoi_gian)))
396
- z = np.polyfit(x_so, don_vi_ban, 1)
397
- duong_xu_huong = np.poly1d(z)(x_so)
398
-
399
- fig.add_trace(go.Scatter(
400
- x=nhan_thoi_gian,
401
- y=duong_xu_huong,
402
- mode='lines',
403
- name='📈 Xu Hướng',
404
- line=dict(color='#8B8B8B', width=3, dash='dash'),
405
- hovertemplate='<b>Xu hướng:</b> %{y:.0f}<extra></extra>'
406
- ))
407
-
408
- # Đánh dấu ngày đỉnh
409
- chi_so_dinh = [i for i, val in enumerate(don_vi_ban) if val == max(don_vi_ban)]
410
- if chi_so_dinh:
411
- chi_so = chi_so_dinh[0]
412
- fig.add_trace(go.Scatter(
413
- x=[nhan_thoi_gian[chi_so]],
414
- y=[don_vi_ban[chi_so]],
415
- mode='markers',
416
- name='🔥 Đỉnh Doanh Số',
417
- marker=dict(size=20, color='#F39C12', symbol='star'),
418
- hovertemplate='<b>Đỉnh cao:</b> %{x}<br><b>Đơn vị:</b> %{y:,}<extra></extra>'
419
- ))
420
-
421
- # Tiêu đề theo chế độ xem
422
- tieu_de_che_do = {
423
- 'ngày': 'Theo Ngày',
424
- 'tháng': 'Theo Tháng',
425
- 'năm': 'Theo Năm'
426
- }
427
-
428
- fig.update_layout(
429
- title=f"📊 Dự Báo Đơn Vị Bán - {tieu_de_che_do[che_do_xem]}: {ten_case} ({chu_ky})",
430
- xaxis_title="⏰ Thời Gian",
431
- yaxis_title="📦 Số Đơn Vị Bán",
432
- template="plotly_white",
433
- height=600,
434
- showlegend=True,
435
- hovermode='x unified',
436
- xaxis=dict(tickangle=45 if che_do_xem == 'ngày' else 0),
437
- font=dict(size=14, family="Arial"),
438
- plot_bgcolor='rgba(248,249,250,0.8)'
439
- )
440
-
441
- return fig
442
-
443
- def tao_thong_tin_tom_tat(ten_case, chu_ky="3 tháng", che_do_xem='ngày'):
444
- """Tạo thông tin tóm tắt dành cho giám đốc"""
445
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
446
- nhan_thoi_gian, don_vi_ban = tao_du_lieu_demo(thong_tin_case, chu_ky, che_do_xem)
447
-
448
- tong_don_vi = sum(don_vi_ban)
449
- trung_binh = tong_don_vi / len(don_vi_ban)
450
- ngay_dinh = max(don_vi_ban)
451
- ngay_thap = min(don_vi_ban)
452
- ty_le_tang_truong = ((don_vi_ban[-1] - don_vi_ban[0]) / don_vi_ban[0]) * 100
453
-
454
- # Tính toán theo chế độ xem
455
- don_vi_thoi_gian = {
456
- 'ngày': 'ngày',
457
- 'tháng': 'tuần',
458
- 'năm': 'tháng'
459
- }[che_do_xem]
460
-
461
- tom_tat_html = f"""
462
- <div class="prediction-box">
463
- <h3 style="margin-top: 0; color: white;">📋 Báo Cáo Dự Báo Điều Hành</h3>
464
- <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
465
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
466
- <h4 style="margin: 0; color: #E8F6F3;">📦 Tổng Đơn Vị</h4>
467
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{tong_don_vi:,}</p>
468
- </div>
469
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
470
- <h4 style="margin: 0; color: #E8F6F3;">📈 TB/{don_vi_thoi_gian.title()}</h4>
471
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{trung_binh:,.0f}</p>
472
- </div>
473
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
474
- <h4 style="margin: 0; color: #E8F6F3;">🔥 Đỉnh Cao</h4>
475
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold;">{ngay_dinh:,}</p>
476
- </div>
477
- <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px;">
478
- <h4 style="margin: 0; color: #E8F6F3;">📊 Tăng Trưởng</h4>
479
- <p style="font-size: 24px; margin: 5px 0; font-weight: bold; color: {'#2ECC71' if ty_le_tang_truong > 0 else '#E74C3C'};">
480
- {ty_le_tang_truong:+.1f}%
481
- </p>
482
- </div>
483
- </div>
484
- <div style="margin-top: 15px; text-align: center;">
485
- <p style="margin: 0; font-size: 16px; color: white;">📅 Chu Kỳ Dự Báo: <strong>{chu_ky}</strong></p>
486
- <p style="margin: 5px 0; font-size: 14px; opacity: 0.9; color: white;">Danh Mục: <strong>{thong_tin_case['danh_muc']}</strong></p>
487
- </div>
488
- </div>
489
- """
490
-
491
- return tom_tat_html
492
-
493
- def tao_bao_cao_giam_doc(ten_case):
494
- """Tạo báo cáo chi tiết dành cho giám đốc - trả về Markdown"""
495
- thong_tin_case = TRUONG_HOP_DEMO[ten_case]
496
- thong_tin_gd = thong_tin_case['thong_tin_giam_doc']
497
-
498
- bao_cao_markdown = f"""
499
- # 👔 BÁO CÁO ĐIỀU HÀNH
500
-
501
- ## 🎯 Tóm Tắt Điều Hành
502
-
503
- {thong_tin_gd['tom_tat']}
504
-
505
- ## 📊 Phân Tích Chi Tiết
506
-
507
- {thong_tin_gd['chi_tiet']}
508
-
509
- ## 🚀 Khuyến Nghị Hành Động
510
-
511
- {thong_tin_gd['hanh_dong']}
512
-
513
- ---
514
- *🤖 Phân tích được tạo bởi FoxAI Business Intelligence | ⚡ Cập nhật realtime*
515
- """
516
-
517
- return bao_cao_markdown
518
-
519
- def tao_loading_effect():
520
- """Tạo hiệu ứng loading để có cảm giác như production"""
521
- loading_html = """
522
- <div class="loading-container">
523
- <div class="loading-spinner"></div>
524
- <h3 style="color: white; margin: 0;">🤖 Đang Xử Lý Dự Báo AI...</h3>
525
- <div class="progress-bar">
526
- <div class="progress-fill"></div>
527
- </div>
528
- <p style="color: white; margin: 10px 0; opacity: 0.9;">
529
- ⚡ Phân tích dữ liệu • 🧠 Machine Learning • 📊 Tạo insights
530
- </p>
531
- </div>
532
- """
533
- return loading_html
534
-
535
- def xu_ly_du_doan_voi_loading(lua_chon_case, chu_ky, che_do_xem):
536
- """Xử lý dự đoán với hiệu ứng loading realistic"""
537
- if lua_chon_case is None:
538
- return tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh(), "# 👔 BÁO CÁO ĐIỀU HÀNH\n\n📊 **Chọn tình huống để xem phân tích**"
539
-
540
- try:
541
- # Giả lập thời gian xử lý
542
- time.sleep(1)
543
-
544
- # Tạo biểu đồ
545
- bieu_do = tao_bieu_do_du_doan(lua_chon_case, chu_ky, che_do_xem)
546
-
547
- # Tạo tóm tắt
548
- tom_tat = tao_thong_tin_tom_tat(lua_chon_case, chu_ky, che_do_xem)
549
-
550
- # Tạo báo cáo giám đốc (Markdown)
551
- bao_cao = tao_bao_cao_giam_doc(lua_chon_case)
552
-
553
- return bieu_do, tom_tat, bao_cao
554
-
555
- except Exception as e:
556
- loi = f"❌ Lỗi xử lý: {str(e)}"
557
- empty_fig = go.Figure().add_annotation(
558
- text=loi,
559
- xref="paper", yref="paper",
560
- x=0.5, y=0.5,
561
- showarrow=False,
562
- font=dict(size=16, color="red")
563
- )
564
- return empty_fig, loi, f"# ❌ Lỗi\n\n{loi}"
565
-
566
- def cap_nhat_thong_tin_case(lua_chon_case):
567
- """Cập nhật thông tin case khi chọn"""
568
- if lua_chon_case in TRUONG_HOP_DEMO:
569
- thong_tin = TRUONG_HOP_DEMO[lua_chon_case]
570
- return f"""
571
- <div class='info-card'>
572
- <h4>📋 Tình Huống: {lua_chon_case}</h4>
573
- <p><strong>Danh Mục:</strong> {thong_tin['danh_muc']}</p>
574
- <p><strong>Mô Tả:</strong> {thong_tin['mo_ta']}</p>
575
- </div>
576
- """
577
- return ""
578
-
579
- # Tạo ứng dụng Gradio
580
- def tao_ung_dung():
581
- """Tạo ứng dụng Gradio hoàn chỉnh bằng tiếng Việt"""
582
-
583
- with gr.Blocks(
584
- title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
585
- theme=gr.themes.Soft(),
586
- css=custom_css
587
- ) as demo:
588
-
589
- # Header tiếng Việt với logo FoxAI
590
- gr.HTML(f"""
591
- <div class="header-container">
592
- <div style="text-align: center; margin-bottom: 20px;">
593
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
594
- </div>
595
- <div class="header-title">
596
- 🇻🇳 HỆ THỐNG DỰ BÁO BÁN HÀNG AI 📊
597
- </div>
598
- <p style="font-size: 1.2em; color: #1A5F91; margin: 15px 0; font-weight: 600; line-height: 1.4;">
599
- Công nghệ AI tiên tiến từ <strong>FoxAI</strong> cho phân tích và dự báo kinh doanh
600
- </p>
601
- <div class="system-status">
602
- 🟢 Hệ thống hoạt động bình thường • 🚀 Độ chính xác 95.8% • ⚡ Realtime Analytics • Powered by FoxAI
603
- </div>
604
- </div>
605
- """)
606
-
607
- # Hướng dẫn sử dụng
608
- gr.HTML("""
609
- <div class='info-card'>
610
- <h3>🎯 Hướng Dẫn Sử Dụng Hệ Thống</h3>
611
- <p>Chọn tình huống kinh doanh, chu kỳ dự báo và chế độ xem để nhận được phân tích AI chi tiết với khuyến nghị điều hành.</p>
612
-
613
- <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
614
- <div>
615
- <h4>🎭 Tình Huống Có Sẵn:</h4>
616
- <ul>
617
- <li>📱 Điện tử & Công nghệ</li>
618
- <li>👕 Thời trang & Làm đẹp</li>
619
- <li>🍔 Thực phẩm & Đồ uống</li>
620
- </ul>
621
- </div>
622
-
623
- <div>
624
- <h4>📊 Chế Độ Phân Tích:</h4>
625
- <ul>
626
- <li>📅 <strong>3 Tháng:</strong> Dự báo ngắn hạn, chính xác cao</li>
627
- <li>📆 <strong>6 Tháng:</strong> Dự báo trung hạn, lập kế hoạch</li>
628
- <li>🗓️ <strong>1 Năm:</strong> Dự báo dài hạn, chiến lược</li>
629
- </ul>
630
- </div>
631
- </div>
632
- </div>
633
- """)
634
-
635
- with gr.Row():
636
- with gr.Column(scale=1):
637
- gr.HTML("<div class='feature-box'><h3>⚙️ Cài Đặt Phân Tích</h3></div>")
638
-
639
- lua_chon_dropdown = gr.Dropdown(
640
- choices=list(TRUONG_HOP_DEMO.keys()),
641
- value=list(TRUONG_HOP_DEMO.keys())[0],
642
- label="🎭 Chọn Tình Huống Kinh Doanh",
643
- info="Mỗi tình huống có đặc điểm và insight riêng biệt"
644
- )
645
-
646
- chu_ky_dropdown = gr.Dropdown(
647
- choices=[("📅 3 Tháng", "3 tháng"), ("📆 6 Tháng", "6 tháng"), ("🗓️ 1 Năm", "1 năm")],
648
- value="3 tháng",
649
- label="📊 Chu Kỳ Dự Báo",
650
- info="Chọn khoảng thời gian dự báo phù hợp với mục đích kinh doanh"
651
- )
652
-
653
- nut_du_bao = gr.Button(
654
- "🚀 Tạo Dự Báo AI",
655
- variant="primary",
656
- size="lg",
657
- elem_classes="button-predict"
658
- )
659
-
660
- # Hiển thị thông tin case
661
- hien_thi_thong_tin = gr.HTML()
662
-
663
- with gr.Row():
664
- with gr.Column():
665
- gr.HTML("<div class='feature-box'><h3>📈 Kết Quả Dự Báo</h3></div>")
666
-
667
- # Chế độ hiển thị được đặt gần biểu đồ
668
- che_do_xem = gr.Radio(
669
- choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
670
- value="ngày",
671
- label="📊 Chế Độ Hiển Thị Biểu Đồ",
672
- info="Thay đổi cách hiển thị dữ liệu trên biểu đồ"
673
- )
674
-
675
- bieu_do_du_bao = gr.Plot(
676
- label="Biểu Đồ Dự Báo Bán Hàng",
677
- elem_classes=["plot-container"]
678
- )
679
-
680
- with gr.Row():
681
- with gr.Column(scale=1):
682
- gr.HTML("<div class='feature-box'><h3>📊 Thống Kê Tổng Hợp</h3></div>")
683
- hien_thi_tom_tat = gr.HTML()
684
-
685
- with gr.Column(scale=1):
686
- gr.HTML("<div class='feature-box'><h3>👔 Báo Cáo Điều Hành</h3></div>")
687
- hien_thi_bao_cao = gr.Markdown()
688
-
689
- # Xử lý sự kiện
690
- lua_chon_dropdown.change(
691
- fn=cap_nhat_thong_tin_case,
692
- inputs=[lua_chon_dropdown],
693
- outputs=[hien_thi_thong_tin]
694
- )
695
-
696
- nut_du_bao.click(
697
- fn=xu_ly_du_doan_voi_loading,
698
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
699
- outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao],
700
- show_progress=True
701
- )
702
-
703
- # Cập nhật biểu đồ khi thay đổi chế độ hiển thị - chỉ khi đã có dự đo��n
704
- def cap_nhat_khi_doi_che_do(case, chu_ky, mode):
705
- try:
706
- if case and case != "":
707
- return [
708
- tao_bieu_do_du_doan(case, chu_ky, mode),
709
- tao_thong_tin_tom_tat(case, chu_ky, mode)
710
- ]
711
- else:
712
- return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
713
- except:
714
- return [tao_bieu_do_mac_dinh(), tao_tom_tat_mac_dinh()]
715
-
716
- che_do_xem.change(
717
- fn=cap_nhat_khi_doi_che_do,
718
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
719
- outputs=[bieu_do_du_bao, hien_thi_tom_tat]
720
- )
721
-
722
- # Tự động load case đầu tiên với biểu đồ mặc định
723
- demo.load(
724
- fn=lambda: [
725
- cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
726
- tao_bieu_do_mac_dinh(),
727
- tao_tom_tat_mac_dinh(),
728
- "# 👔 BÁO CÁO ĐIỀU HÀNH\n\n📊 **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**\n\nHệ thống sẽ tạo báo cáo điều hành với insights và khuyến nghị cụ thể."
729
- ],
730
- outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
731
- )
732
-
733
- # Footer thông tin hệ thống với branding FoxAI
734
- gr.HTML(f"""
735
- <div class='info-card' style="margin-top: 30px;">
736
- <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 20px;">
737
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
738
- <h3 style="color: #1A5F91; margin: 0;">💡 Thông Tin Hệ Thống FoxAI</h3>
739
- </div>
740
-
741
- <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin: 20px 0;">
742
- <div>
743
- <h4 style="color: #1A5F91;">🎯 Tính Năng Nổi Bật:</h4>
744
- <ul>
745
- <li><strong>AI Insights:</strong> Phân tích thông minh với khuyến nghị cụ thể</li>
746
- <li><strong>Multi-view:</strong> Xem theo ngày/tháng/năm linh hoạt</li>
747
- <li><strong>Executive Reports:</strong> Báo cáo chuyên nghiệp cho ban điều hành</li>
748
- <li><strong>Real-time:</strong> Cập nhật dữ liệu theo thời gian thực</li>
749
- </ul>
750
- </div>
751
-
752
- <div>
753
- <h4 style="color: #1A5F91;">📊 Chất Lượng Dự Báo:</h4>
754
- <ul>
755
- <li><strong>Độ Chính Xác:</strong> 95.8% trên 3 ngành hàng</li>
756
- <li><strong>Phạm Vi:</strong> Từ 3 tháng đến 1 năm</li>
757
- <li><strong>Cập Nhật:</strong> Real-time với market intelligence</li>
758
- <li><strong>Báo Cáo:</strong> Professional format cho C-level executives</li>
759
- </ul>
760
- </div>
761
- </div>
762
-
763
- <div style="text-align: center; margin: 20px 0; padding: 15px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 10px; border: 2px solid #1A5F91;">
764
- <p style="color: #1A5F91; font-weight: bold; margin: 0; font-size: 16px;">
765
- 🦊 <strong>Powered by FoxAI</strong> | 🇻🇳 Made in Vietnam | 🤖 Advanced AI | 📊 Enterprise Ready | ⚡ Real-time Analytics
766
- </p>
767
- <p style="color: #8B8B8B; margin: 5px 0 0 0; font-size: 14px;">
768
- YOUR TRUSTED PARTNER - FoxAI Technology Solutions
769
- </p>
770
- </div>
771
- </div>
772
- """)
773
-
774
- return demo
775
-
776
- # Chạy ứng dụng
777
- if __name__ == "__main__":
778
- demo = tao_ung_dung()
779
- demo.launch(
780
- share=True,
781
- server_name="0.0.0.0",
782
- server_port=7860,
783
- show_error=True
784
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app_tabs_final.py DELETED
@@ -1,275 +0,0 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import plotly.graph_objects as go
4
- import plotly.express as px
5
- import numpy as np
6
- import random
7
- import time
8
-
9
- # Import các hàm từ app.py gốc
10
- import sys
11
- import os
12
- sys.path.append(os.path.dirname(os.path.abspath(__file__)))
13
-
14
- from app import (
15
- TRUONG_HOP_DEMO, FOXAI_LOGO_URL, custom_css,
16
- tao_bao_cao_giam_doc, tao_du_lieu_demo, tao_bieu_do_du_doan,
17
- cap_nhat_thong_tin_case, xu_ly_du_doan_voi_loading, tao_thong_tin_tom_tat
18
- )
19
-
20
- def tao_tab_compliance():
21
- """Tạo tab Compliance & Age-Gate Radar"""
22
- with gr.Column():
23
- gr.HTML("""
24
- <div class='info-card' style="text-align: center; padding: 40px;">
25
- <div style="font-size: 4em; margin-bottom: 20px;">🧾</div>
26
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Compliance & Age‑Gate Radar</h2>
27
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
28
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
29
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
30
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
31
- <strong>Radar & Gauge tuân thủ chuẩn trưng bày/nhãn cảnh báo/age‑gate (18+)</strong>
32
- </p>
33
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
34
- <li>🎯 <strong>Radar Compliance:</strong> Theo dõi mức độ tuân thủ quy định trưng bày sản phẩm</li>
35
- <li>⚠️ <strong>Age-Gate Monitor:</strong> Kiểm soát nhãn cảnh báo độ tuổi (18+) cho sản phẩm nhạy cảm</li>
36
- <li>📊 <strong>Dashboard Quản Trị:</strong> Hệ thống gauge theo dõi rủi ro tuân thủ real-time</li>
37
- <li>🔍 <strong>Risk Assessment:</strong> Đánh giá và cảnh báo vi phạm quy định trưng bày</li>
38
- <li>📈 <strong>Compliance Score:</strong> Tính điểm tuân thủ tổng thể theo từng danh mục sản phẩm</li>
39
- </ul>
40
- </div>
41
-
42
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
43
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
44
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
45
- ⏳ <strong>Tính năng đang được phát triển</strong> - UI demo để minh họa câu chuyện quản trị rủi ro
46
- </p>
47
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
48
- Dự kiến hoàn thành: Q4 2024 • Beta testing: Q1 2025
49
- </p>
50
- </div>
51
- </div>
52
- </div>
53
- """)
54
-
55
- def tao_tab_route_optimizer():
56
- """Tạo tab Route-to-Market Optimizer"""
57
- with gr.Column():
58
- gr.HTML("""
59
- <div class='info-card' style="text-align: center; padding: 40px;">
60
- <div style="font-size: 4em; margin-bottom: 20px;">🚚</div>
61
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Route‑to‑Market Optimizer</h2>
62
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
63
- <h3 style="color: #475569; margin-bottom: 25px;">🎯 Mô Tả Tính Năng</h3>
64
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
65
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
66
- <strong>Scatter Pareto "số điểm ghé/tuyến" vs "doanh thu/km" – chọn tuyến "ngon – gọn – rẻ"</strong>
67
- </p>
68
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
69
- <li>📍 <strong>Route Analytics:</strong> Phân tích hiệu quả từng tuyến phân phối theo Pareto</li>
70
- <li>💰 <strong>Revenue per KM:</strong> Tính toán doanh thu/km để tối ưu lợi nhuận</li>
71
- <li>🎯 <strong>Stop Optimization:</strong> Tối ưu số điểm ghé/tuyến để giảm chi phí</li>
72
- <li>📊 <strong>Scatter Plot Analysis:</strong> Visualization ma trận "ngon-gọn-rẻ"</li>
73
- <li>🚚 <strong>Smart Routing:</strong> AI đề xuất tuyến đường tối ưu theo múi giờ</li>
74
- <li>⚡ <strong>Real-time Tracking:</strong> Theo dõi hiệu suất tuyến trực tiếp</li>
75
- </ul>
76
- </div>
77
-
78
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
79
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
80
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
81
- ⏳ <strong>Tính năng đang được phát triển</strong> - Mô hình giả lập cho demo
82
- </p>
83
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
84
- Đang thu thập dữ liệu GPS • Tích hợp API Maps • Alpha phase
85
- </p>
86
- </div>
87
- </div>
88
- </div>
89
- """)
90
-
91
- def tao_tab_material_predict():
92
- """Tạo tab Material Predict"""
93
- with gr.Column():
94
- gr.HTML("""
95
- <div class='info-card' style="text-align: center; padding: 40px;">
96
- <div style="font-size: 4em; margin-bottom: 20px;">📦</div>
97
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Material Predict</h2>
98
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
99
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
100
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
101
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
102
- <strong>Dự báo vật tư thông minh với AI-powered supply chain optimization</strong>
103
- </p>
104
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
105
- <li>📈 <strong>Demand Forecasting:</strong> Dự báo nhu cầu vật tư theo mùa vụ và xu hướng</li>
106
- <li>🏭 <strong>Inventory Optimization:</strong> Tối ưu mức tồn kho để giảm chi phí lưu trữ</li>
107
- <li>⚡ <strong>Auto-Reorder Points:</strong> Tự động đặt hàng khi đạt ngưỡng tối thiểu</li>
108
- <li>🔄 <strong>Supply Chain AI:</strong> Tích hợp với nhà cung cấp để dự báo leadtime</li>
109
- <li>💡 <strong>Cost Intelligence:</strong> Phân tích biến động giá nguyên liệu theo thời gian</li>
110
- <li>📊 <strong>Material Matrix:</strong> Ma trận ABC analysis cho ưu tiên vật tư quan trọng</li>
111
- <li>🎯 <strong>Waste Reduction:</strong> Giảm thiểu lãng phí bằng dự báo chính xác</li>
112
- </ul>
113
- </div>
114
-
115
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
116
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
117
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
118
- ⏳ <strong>Tính năng đang được phát triển</strong> - Module dự báo vật tư tiên tiến
119
- </p>
120
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
121
- Đang training ML models • Kết nối ERP systems • Pilot program
122
- </p>
123
- </div>
124
- </div>
125
- </div>
126
- """)
127
-
128
- def tao_tab_du_bao_chinh():
129
- """Tạo tab chính cho dự báo bán hàng"""
130
-
131
- with gr.Row():
132
- with gr.Column(scale=1):
133
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>⚙️ Cài Đặt</h3></div>")
134
-
135
- lua_chon_dropdown = gr.Dropdown(
136
- choices=list(TRUONG_HOP_DEMO.keys()),
137
- value=list(TRUONG_HOP_DEMO.keys())[0],
138
- label="🛍️ Chọn Sản Phẩm",
139
- info="Mỗi sản phẩm có insight riêng",
140
- elem_classes=["tech-border"]
141
- )
142
-
143
- chu_ky_dropdown = gr.Dropdown(
144
- choices=["3 tháng", "6 tháng", "1 năm"],
145
- value="6 tháng",
146
- label="📅 Chu Kỳ Dự Báo",
147
- info="Thời gian dự báo tương lai",
148
- elem_classes=["tech-border"]
149
- )
150
-
151
- nut_du_bao = gr.Button(
152
- "🚀 Tạo Dự Báo AI",
153
- variant="primary",
154
- size="lg",
155
- elem_classes=["btn-modern", "pulse-animation"]
156
- )
157
-
158
- hien_thi_thong_tin = gr.HTML(
159
- value=cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
160
- elem_classes=["floating", "glass-card"]
161
- )
162
-
163
- with gr.Column(scale=2):
164
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>��� Biểu Đồ Dự Báo</h3></div>")
165
- bieu_do_du_bao = gr.Plot(
166
- label="Dự báo xu hướng bán hàng",
167
- elem_classes=["chart-container"]
168
- )
169
-
170
- hien_thi_tom_tat = gr.HTML(
171
- value="🔍 Chọn sản phẩm và bấm 'Tạo Dự Báo AI' để xem phân tích",
172
- elem_classes=["summary-container", "floating"]
173
- )
174
-
175
- hien_thi_bao_cao = gr.HTML(
176
- value="",
177
- elem_classes=["report-container", "floating"]
178
- )
179
-
180
- # Event handlers
181
- lua_chon_dropdown.change(
182
- fn=cap_nhat_thong_tin_case,
183
- inputs=[lua_chon_dropdown],
184
- outputs=[hien_thi_thong_tin]
185
- )
186
-
187
- nut_du_bao.click(
188
- fn=xu_ly_du_doan_voi_loading,
189
- inputs=[lua_chon_dropdown, chu_ky_dropdown],
190
- outputs=[bieu_do_du_bao, hien_thi_tom_tat]
191
- )
192
-
193
- return lua_chon_dropdown, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, hien_thi_thong_tin
194
-
195
- def tao_ung_dung_voi_tabs():
196
- """Tạo ứng dụng Gradio với tabs"""
197
-
198
- with gr.Blocks(
199
- title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
200
- theme=gr.themes.Soft(),
201
- css=custom_css
202
- ) as demo:
203
-
204
- # Header
205
- gr.HTML(f"""
206
- <div class="header-container">
207
- <div style="text-align: center; margin-bottom: 20px;">
208
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
209
- </div>
210
- <div class="header-title">
211
- 🚀 HỆ THỐNG DỰ BÁO AI
212
- </div>
213
- <p style="font-size: 1.1em; color: rgba(255,255,255,0.95) !important; margin: 15px auto; font-weight: 500; line-height: 1.5; max-width: 600px; text-align: center;">
214
- Phân tích thông minh với công nghệ <strong style="color: white !important;">FoxAI</strong>
215
- </p>
216
- <div class="system-status">
217
- 🟢 Hoạt động • 95.8% độ chính xác • Powered by FoxAI
218
- </div>
219
- </div>
220
- """)
221
-
222
- # Tabs
223
- with gr.Tabs() as tabs:
224
- with gr.TabItem("📈 Dự Báo Bán Hàng", elem_id="main-tab"):
225
- components = tao_tab_du_bao_chinh()
226
-
227
- with gr.TabItem("🧾 Compliance & Age‑Gate Radar", elem_id="compliance-tab"):
228
- tao_tab_compliance()
229
-
230
- with gr.TabItem("🚚 Route‑to‑Market Optimizer", elem_id="route-tab"):
231
- tao_tab_route_optimizer()
232
-
233
- with gr.TabItem("📦 Material Predict", elem_id="material-tab"):
234
- tao_tab_material_predict()
235
-
236
- # Footer
237
- gr.HTML(f"""
238
- <div class='info-card' style="margin-top: 30px; text-align: center;">
239
- <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 25px;">
240
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
241
- <h3 style="color: #1A5F91; margin: 0;">💡 Hệ Thống FoxAI</h3>
242
- </div>
243
-
244
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 25px 0;">
245
- <div style="text-align: center; padding: 15px; background: rgba(26, 95, 145, 0.05); border-radius: 10px;">
246
- <div style="color: #334155; line-height: 1.8; font-weight: 500;">
247
- 🎯 Độ chính xác 95.8%<br/>
248
- 📅 Dự báo 3 tháng - 1 năm<br/>
249
- 🔄 Market intelligence<br/>
250
- 💼 Enterprise ready
251
- </div>
252
- </div>
253
- </div>
254
-
255
- <div style="text-align: center; margin: 25px 0; padding: 20px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 15px; border: 2px solid #1A5F91;">
256
- <p style="color: #1A5F91; font-weight: 700; margin: 0; font-size: 1.1em;">
257
- 🦊 <strong>Powered by FoxAI</strong> • 🇻🇳 Made in Vietnam • 🤖 Advanced AI
258
- </p>
259
- <p style="color: #334155; margin: 8px 0 0 0; font-size: 0.9em; font-weight: 500;">
260
- YOUR TRUSTED AI PARTNER
261
- </p>
262
- </div>
263
- </div>
264
- """)
265
-
266
- return demo
267
-
268
- if __name__ == "__main__":
269
- demo = tao_ung_dung_voi_tabs()
270
- demo.launch(
271
- share=True,
272
- server_name="0.0.0.0",
273
- server_port=7860,
274
- show_error=True
275
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app_with_tabs.py DELETED
@@ -1,336 +0,0 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import plotly.graph_objects as go
4
- import plotly.express as px
5
- import numpy as np
6
- import random
7
- import time
8
-
9
- # Import tất cả từ app.py gốc trừ phần Gradio interface
10
- from app import *
11
-
12
- def tao_tab_compliance():
13
- """Tạo tab Compliance & Age-Gate Radar"""
14
- gr.HTML("""
15
- <div class='info-card' style="text-align: center; padding: 40px;">
16
- <div style="font-size: 4em; margin-bottom: 20px;">🧾</div>
17
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Compliance & Age‑Gate Radar</h2>
18
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
19
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
20
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
21
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
22
- <strong>Radar & Gauge tuân thủ chuẩn trưng bày/nhãn cảnh báo/age‑gate (18+)</strong>
23
- </p>
24
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
25
- <li>🎯 <strong>Radar Compliance:</strong> Theo dõi mức độ tuân thủ quy định trưng bày sản phẩm</li>
26
- <li>⚠️ <strong>Age-Gate Monitor:</strong> Kiểm soát nhãn cảnh báo độ tuổi (18+) cho sản phẩm nhạy cảm</li>
27
- <li>📊 <strong>Dashboard Quản Trị:</strong> Hệ thống gauge theo dõi rủi ro tuân thủ real-time</li>
28
- <li>🔍 <strong>Risk Assessment:</strong> Đánh giá và cảnh báo vi phạm quy định trưng bày</li>
29
- <li>📈 <strong>Compliance Score:</strong> Tính điểm tuân thủ tổng thể theo từng danh mục sản phẩm</li>
30
- </ul>
31
- </div>
32
-
33
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
34
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
35
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
36
- ⏳ <strong>Tính năng đang được phát triển</strong> - UI demo để minh họa câu chuyện quản trị rủi ro
37
- </p>
38
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
39
- Dự kiến hoàn thành: Q4 2024 • Beta testing: Q1 2025
40
- </p>
41
- </div>
42
- </div>
43
- </div>
44
- """)
45
-
46
- def tao_tab_route_optimizer():
47
- """Tạo tab Route-to-Market Optimizer"""
48
- gr.HTML("""
49
- <div class='info-card' style="text-align: center; padding: 40px;">
50
- <div style="font-size: 4em; margin-bottom: 20px;">🚚</div>
51
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Route‑to‑Market Optimizer</h2>
52
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
53
- <h3 style="color: #475569; margin-bottom: 25px;">🎯 Mô Tả Tính Năng</h3>
54
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
55
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
56
- <strong>Scatter Pareto "số điểm ghé/tuyến" vs "doanh thu/km" – chọn tuyến "ngon – gọn – rẻ"</strong>
57
- </p>
58
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
59
- <li>📍 <strong>Route Analytics:</strong> Phân tích hiệu quả từng tuyến phân phối theo Pareto</li>
60
- <li>💰 <strong>Revenue per KM:</strong> Tính toán doanh thu/km để tối ưu lợi nhuận</li>
61
- <li>🎯 <strong>Stop Optimization:</strong> Tối ưu số điểm ghé/tuyến để giảm chi phí</li>
62
- <li>📊 <strong>Scatter Plot Analysis:</strong> Visualization ma trận "ngon-gọn-rẻ"</li>
63
- <li>🚚 <strong>Smart Routing:</strong> AI đề xuất tuyến đường tối ưu theo múi giờ</li>
64
- <li>⚡ <strong>Real-time Tracking:</strong> Theo dõi hiệu suất tuyến trực tiếp</li>
65
- </ul>
66
- </div>
67
-
68
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
69
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
70
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
71
- ⏳ <strong>Tính năng đang được phát triển</strong> - Mô hình giả lập cho demo
72
- </p>
73
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
74
- Đang thu thập dữ liệu GPS • Tích hợp API Maps • Alpha phase
75
- </p>
76
- </div>
77
- </div>
78
- </div>
79
- """)
80
-
81
- def tao_tab_material_predict():
82
- """Tạo tab Material Predict"""
83
- gr.HTML("""
84
- <div class='info-card' style="text-align: center; padding: 40px;">
85
- <div style="font-size: 4em; margin-bottom: 20px;">📦</div>
86
- <h2 style="color: #1A5F91; margin-bottom: 20px;">Material Predict</h2>
87
- <div style="max-width: 800px; margin: 0 auto; text-align: left;">
88
- <h3 style="color: #475569; margin-bottom: 25px;">📋 Mô Tả Tính Năng</h3>
89
- <div style="background: rgba(26, 95, 145, 0.05); padding: 25px; border-radius: 15px; margin-bottom: 30px;">
90
- <p style="font-size: 1.1em; line-height: 1.7; margin-bottom: 20px; color: #334155;">
91
- <strong>Dự báo vật tư thông minh với AI-powered supply chain optimization</strong>
92
- </p>
93
- <ul style="font-size: 1.05em; line-height: 1.8; color: #475569; padding-left: 25px;">
94
- <li>📈 <strong>Demand Forecasting:</strong> Dự báo nhu cầu vật tư theo mùa vụ và xu hướng</li>
95
- <li>🏭 <strong>Inventory Optimization:</strong> Tối ưu mức tồn kho để giảm chi phí lưu trữ</li>
96
- <li>⚡ <strong>Auto-Reorder Points:</strong> Tự động đặt hàng khi đạt ngưỡng tối thiểu</li>
97
- <li>🔄 <strong>Supply Chain AI:</strong> Tích hợp với nhà cung cấp để dự báo leadtime</li>
98
- <li>💡 <strong>Cost Intelligence:</strong> Phân tích biến động giá nguyên liệu theo thời gian</li>
99
- <li>📊 <strong>Material Matrix:</strong> Ma trận ABC analysis cho ưu tiên vật tư quan trọng</li>
100
- <li>🎯 <strong>Waste Reduction:</strong> Giảm thiểu lãng phí bằng dự báo chính xác</li>
101
- </ul>
102
- </div>
103
-
104
- <div style="background: linear-gradient(135deg, #FEF3C7, #FDE68A); padding: 25px; border-radius: 15px; border-left: 5px solid #F59E0B;">
105
- <h4 style="color: #92400E; margin-bottom: 15px;">🚧 Trạng Thái Phát Triển</h4>
106
- <p style="color: #78350F; font-size: 1.05em; font-weight: 600; margin: 0;">
107
- ⏳ <strong>Tính năng đang được phát triển</strong> - Module dự báo vật tư tiên tiến
108
- </p>
109
- <p style="color: #78350F; font-size: 0.95em; margin: 10px 0 0 0; font-style: italic;">
110
- Đang training ML models • Kết nối ERP systems • Pilot program
111
- </p>
112
- </div>
113
- </div>
114
- </div>
115
- """)
116
-
117
- def tao_tab_du_bao_chinh():
118
- """Tạo tab chính cho dự báo bán hàng"""
119
-
120
- with gr.Row():
121
- with gr.Column(scale=1):
122
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>⚙️ Cài Đặt</h3></div>")
123
-
124
- lua_chon_dropdown = gr.Dropdown(
125
- choices=list(TRUONG_HOP_DEMO.keys()),
126
- value=list(TRUONG_HOP_DEMO.keys())[0],
127
- label="🛍️ Chọn Sản Phẩm",
128
- info="Mỗi sản phẩm có insight riêng",
129
- elem_classes=["tech-border"]
130
- )
131
-
132
- chu_ky_dropdown = gr.Dropdown(
133
- choices=["3 tháng", "6 tháng", "1 năm"],
134
- value="6 tháng",
135
- label="📅 Chu Kỳ Dự Báo",
136
- info="Thời gian dự báo tương lai",
137
- elem_classes=["tech-border"]
138
- )
139
-
140
- nut_du_bao = gr.Button(
141
- "🚀 Tạo Dự Báo AI",
142
- variant="primary",
143
- size="lg",
144
- elem_classes=["btn-modern", "pulse-animation"]
145
- )
146
-
147
- hien_thi_thong_tin = gr.HTML(
148
- value=cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
149
- elem_classes=["floating", "glass-card"]
150
- )
151
-
152
- with gr.Row():
153
- with gr.Column():
154
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>📈 Kết Quả Dự Báo</h3></div>")
155
-
156
- che_do_xem = gr.Radio(
157
- choices=[("📅 Theo Ngày", "ngày"), ("📆 Theo Tuần", "tháng"), ("🗓️ Theo Tháng", "năm")],
158
- value="ngày",
159
- label="📊 Chế Độ Hiển Thị",
160
- info="Thay đổi cách hiển thị biểu đồ",
161
- elem_classes=["tech-border"]
162
- )
163
-
164
- bieu_do_du_bao = gr.Plot(
165
- label="Biểu Đồ Dự Báo Bán Hàng",
166
- elem_classes=["plot-container", "glass-card", "neon-border"],
167
- elem_id="chart-target"
168
- )
169
-
170
- loading_panel = gr.HTML(value="", elem_id="loading-panel")
171
-
172
- with gr.Row():
173
- with gr.Column(scale=1):
174
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>📊 Thống Kê</h3></div>")
175
- hien_thi_tom_tat = gr.HTML()
176
-
177
- with gr.Column(scale=1):
178
- gr.HTML("<div class='feature-box floating' style='text-align: center;'><h3>🎯 Chiến Lược AI</h3></div>")
179
-
180
- nut_streaming = gr.Button(
181
- "🤖 Tạo Chiến Lược AI (Streaming)",
182
- variant="secondary",
183
- size="sm",
184
- elem_classes=["btn-modern"],
185
- visible=False
186
- )
187
-
188
- hien_thi_bao_cao = gr.Markdown()
189
-
190
- # Event handlers
191
- def xu_ly_streaming(lua_chon_case):
192
- if lua_chon_case is None:
193
- return "# 🎯 CHIẾN LƯỢC ĐỀ XUẤT\n\n📊 **Chọn mặt hàng để tạo chiến lược**"
194
- try:
195
- for partial_text in tao_streaming_text(lua_chon_case):
196
- yield partial_text
197
- except Exception as e:
198
- yield f"# ❌ Lỗi\n\n{str(e)}"
199
-
200
- lua_chon_dropdown.change(
201
- fn=lambda case: [cap_nhat_thong_tin_case(case), gr.update(visible=case is not None)],
202
- inputs=[lua_chon_dropdown],
203
- outputs=[hien_thi_thong_tin, nut_streaming]
204
- )
205
-
206
- evt0 = nut_du_bao.click(
207
- fn=lambda: "",
208
- outputs=[loading_panel]
209
- )
210
-
211
- evt1 = evt0.then(
212
- fn=hien_loading_tung_buoc,
213
- outputs=[loading_panel],
214
- show_progress=False,
215
- )
216
-
217
- evt1.then(
218
- fn=tinh_toan_ket_qua,
219
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
220
- outputs=[bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, loading_panel],
221
- show_progress=False,
222
- )
223
-
224
- nut_streaming.click(
225
- fn=xu_ly_streaming,
226
- inputs=[lua_chon_dropdown],
227
- outputs=[hien_thi_bao_cao],
228
- show_progress=False
229
- )
230
-
231
- che_do_xem.change(
232
- fn=lambda case, chu_ky, mode: [
233
- tao_bieu_do_du_doan(case, chu_ky, mode) if case else tao_bieu_do_mac_dinh(),
234
- tao_thong_tin_tom_tat(case, chu_ky, mode) if case else tao_tom_tat_mac_dinh()
235
- ],
236
- inputs=[lua_chon_dropdown, chu_ky_dropdown, che_do_xem],
237
- outputs=[bieu_do_du_bao, hien_thi_tom_tat]
238
- )
239
-
240
- return (lua_chon_dropdown, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, hien_thi_thong_tin)
241
-
242
- def tao_ung_dung_voi_tabs():
243
- """Tạo ứng dụng Gradio với tabs"""
244
-
245
- with gr.Blocks(
246
- title="🚀 Hệ Thống Dự Báo Bán Hàng AI - FoxAI",
247
- theme=gr.themes.Soft(),
248
- css=custom_css
249
- ) as demo:
250
-
251
- # Header
252
- gr.HTML(f"""
253
- <div class="header-container">
254
- <div style="text-align: center; margin-bottom: 20px;">
255
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI Logo" class="foxai-logo"/>
256
- </div>
257
- <div class="header-title">
258
- 🚀 HỆ THỐNG DỰ BÁO AI
259
- </div>
260
- <p style="font-size: 1.1em; color: rgba(255,255,255,0.95) !important; margin: 15px auto; font-weight: 500; line-height: 1.5; max-width: 600px; text-align: center;">
261
- Phân tích thông minh với công nghệ <strong style="color: white !important;">FoxAI</strong>
262
- </p>
263
- <div class="system-status">
264
- 🟢 Hoạt động • 95.8% độ chính xác • Powered by FoxAI
265
- </div>
266
- </div>
267
- """)
268
-
269
- # Tabs
270
- with gr.Tabs() as tabs:
271
- with gr.TabItem("📈 Dự Báo Bán Hàng", elem_id="main-tab"):
272
- components = tao_tab_du_bao_chinh()
273
- lua_chon_dropdown, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao, hien_thi_thong_tin = components
274
-
275
- with gr.TabItem("🧾 Compliance & Age‑Gate Radar", elem_id="compliance-tab"):
276
- tao_tab_compliance()
277
-
278
- with gr.TabItem("🚚 Route‑to‑Market Optimizer", elem_id="route-tab"):
279
- tao_tab_route_optimizer()
280
-
281
- with gr.TabItem("📦 Material Predict", elem_id="material-tab"):
282
- tao_tab_material_predict()
283
-
284
- # Auto load cho tab chính
285
- demo.load(
286
- fn=lambda: [
287
- cap_nhat_thong_tin_case(list(TRUONG_HOP_DEMO.keys())[0]),
288
- tao_bieu_do_mac_dinh(),
289
- tao_tom_tat_mac_dinh(),
290
- """# 🎯 CHIẾN LƯỢC ĐỀ XUẤT
291
-
292
- ## 📊 **Sẵn Sàng Phân Tích**
293
-
294
- **Nhấn 'Tạo Dự Báo AI' để xem phân tích chi tiết**
295
-
296
- Hệ thống AI sẽ tạo chiến lược đề xuất với:
297
-
298
- • **Phân tích xu hướng** thị trường
299
- • **Insights chi tiết** từ dữ liệu
300
- • **Khuyến nghị cụ thể** để tối ưa doanh thu
301
- • **Roadmap hành động** rõ ràng
302
-
303
- *🤖 Powered by FoxAI Intelligence*"""
304
- ],
305
- outputs=[hien_thi_thong_tin, bieu_do_du_bao, hien_thi_tom_tat, hien_thi_bao_cao]
306
- )
307
-
308
- # Footer
309
- gr.HTML(f"""
310
- <div class='info-card' style="margin-top: 30px; text-align: center;">
311
- <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 25px;">
312
- <img src="{FOXAI_LOGO_URL}" alt="FoxAI" style="height: 40px; margin-right: 15px;"/>
313
- <h3 style="color: #1A5F91; margin: 0;">💡 Hệ Thống FoxAI</h3>
314
- </div>
315
-
316
- <div style="text-align: center; margin: 25px 0; padding: 20px; background: linear-gradient(135deg, rgba(26, 95, 145, 0.1), rgba(139, 139, 139, 0.1)); border-radius: 15px; border: 2px solid #1A5F91;">
317
- <p style="color: #1A5F91; font-weight: 700; margin: 0; font-size: 1.1em;">
318
- 🦊 <strong>Powered by FoxAI</strong> • 🇻🇳 Made in Vietnam • 🤖 Advanced AI
319
- </p>
320
- <p style="color: #334155; margin: 8px 0 0 0; font-size: 0.9em; font-weight: 500;">
321
- YOUR TRUSTED AI PARTNER
322
- </p>
323
- </div>
324
- </div>
325
- """)
326
-
327
- return demo
328
-
329
- if __name__ == "__main__":
330
- demo = tao_ung_dung_voi_tabs()
331
- demo.launch(
332
- share=True,
333
- server_name="0.0.0.0",
334
- server_port=7860,
335
- show_error=True
336
- )