JC321 commited on
Commit
2e50467
·
verified ·
1 Parent(s): 268a47a

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -60
app.py CHANGED
@@ -99,6 +99,39 @@ div[class*=" gradio-container-"] {
99
  text-align: left;
100
  width: 100%;
101
  box-sizing: border-box;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
103
 
104
  /* 悬停效果 */
@@ -107,9 +140,9 @@ div[class*=" gradio-container-"] {
107
  border-color: #d1d5db;
108
  }
109
 
110
- /* 选中效果 - 使用橙色渐变,更好看 */
111
  .company-list-container input[type="radio"]:checked + span {
112
- background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%) !important;
113
  color: white !important;
114
  font-weight: 600 !important;
115
  display: block;
@@ -128,7 +161,7 @@ div[class*=" gradio-container-"] {
128
  }
129
 
130
  label.selected {
131
- background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%) !important;
132
  color: white !important;
133
  }
134
 
@@ -210,13 +243,15 @@ label.selected {
210
  background: #f9fafb !important;
211
  }
212
 
213
- /* ✅ 缩小Easy Financial AI Assistant标题 */
214
  .chatbot > .wrap > .head h1,
215
  .chatbot > .wrap > .head h2,
216
  .chatbot > .wrap > .head h3 {
217
- font-size: 14px !important;
218
  margin: 0 !important;
219
- font-weight: 600 !important;
 
 
220
  }
221
 
222
  /* Tabs标签栏样式 */
@@ -700,7 +735,7 @@ def update_report_section(selected_company, report_data, stock_code):
700
  <div class="report-item-content">
701
  <span class="text-gray-800">{period}-{stock_code}-{source_form}</span>
702
  <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" class="text-blue-500" viewBox="0 0 20 20" fill="currentColor">
703
- <path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 10-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l-1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd" />
704
  </svg>
705
  </div>
706
  </div>
@@ -1172,35 +1207,6 @@ def build_income_table(table_data):
1172
  income_statement = table_data
1173
  yoy_rates = []
1174
 
1175
- # ✅ 转置表格:横轴显示Category,纵轴显示年份
1176
- # 原始数据格式: [["Category", "2024/FY", "2023/FY", "2022/FY"], ["Total", "100", "90", "80"], ...]
1177
- # 转置后格式: [["Year", "Total", "Net Income", ...], ["2024/FY", "100", "200", ...], ...]
1178
-
1179
- if len(income_statement) == 0:
1180
- return "<div>No data available</div>"
1181
-
1182
- # 提取原始表头和数据
1183
- original_headers = income_statement[0] # ["Category", "2024/FY", "2023/FY", "2022/FY"]
1184
- original_data = income_statement[1:] # 数据行
1185
-
1186
- # 构建转置后的表格
1187
- transposed_table = []
1188
-
1189
- # 新表头:第一列是"Year",其余是各个Category
1190
- new_header = ["Year"] + [row[0] for row in original_data]
1191
- transposed_table.append(new_header)
1192
-
1193
- # 新数据行:每一行对应一个年份
1194
- for col_idx in range(1, len(original_headers)):
1195
- year = original_headers[col_idx]
1196
- row_data = [year] # 第一列是年份
1197
- for data_row in original_data:
1198
- if col_idx < len(data_row):
1199
- row_data.append(data_row[col_idx])
1200
- else:
1201
- row_data.append("N/A")
1202
- transposed_table.append(row_data)
1203
-
1204
  # 创建一个映射,将年份列索引映射到增长率
1205
  yoy_map = {}
1206
  if len(yoy_rates) > 1 and len(yoy_rates[0]) > 1:
@@ -1216,10 +1222,10 @@ def build_income_table(table_data):
1216
  yoy_map[category][yoy_headers[j]] = rate
1217
 
1218
  table_rows = ""
 
1219
 
1220
- for i, row in enumerate(transposed_table):
1221
  if i == 0:
1222
- # 表头行
1223
  row_style = "background-color: #f5f5f5; font-weight: 500;"
1224
  else:
1225
  row_style = "background-color: #f9f9f9;"
@@ -1227,17 +1233,16 @@ def build_income_table(table_data):
1227
 
1228
  for j, cell in enumerate(row):
1229
  if j == 0:
1230
- # 第一列(Year列)左对齐,设置最大宽度
1231
- cells += f"<td style='padding: 8px; border: 1px solid #ddd; text-align: left; font-size: 13px; max-width: 100px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600;'>{cell}</td>"
1232
  else:
1233
- # 数据列居中对齐
1234
  # 添加增长率箭头(如果有的话)
1235
  growth = None
1236
- if i > 0 and j > 0: # 不是表头行,也不是第一列
1237
- year = row[0] # 当前行的年份
1238
- category = transposed_table[0][j] # 当前列的Category
1239
- if category in yoy_map and year in yoy_map[category]:
1240
- growth = yoy_map[category][year]
1241
 
1242
  if growth and growth != "N/A":
1243
  arrow = "▲" if growth.startswith("+") else "▼"
@@ -1251,7 +1256,7 @@ def build_income_table(table_data):
1251
  table_rows += f"<tr style='{row_style}'>{cells}</tr>"
1252
 
1253
  html = f"""
1254
- <div style="min-width: 400px;max-width: 600px;height: auto !important;border: 1px solid #e5e7eb; border-radius: 12px; padding: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.08); font-family: 'Segoe UI', sans-serif; background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);">
1255
  <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 18px; padding-bottom: 12px; border-bottom: 2px solid #e5e7eb;">
1256
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1257
  <path d="M12 2L15.09 8.26L19 9.07L16 14L16 19L12 19L8 14L8 9.07L4.91 8.26L8 2L12 2Z" fill="#3b82f6"/>
@@ -1322,18 +1327,18 @@ def create_metrics_dashboard():
1322
  prev_close_val = company_info.get("previous_close", "N/A")
1323
 
1324
  html = f"""
1325
- <div style="width: 250px; height: 300px !important; border: 1px solid #e5e7eb; border-radius: 12px; padding: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.08); font-family: 'Segoe UI', sans-serif; background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);">
1326
- <div style="font-size: 17px; color: #374151; font-weight: 600; margin-bottom: 4px;">{company_name}</div>
1327
- <div style="font-size: 13px; color: #6b7280; margin-bottom: 12px;">NYSE:{symbol}</div>
1328
- <div style="display: flex; align-items: center; gap: 10px; margin: 12px 0; padding: 12px; background: #f9fafb; border-radius: 8px;">
1329
- <div style="font-size: 34px; font-weight: bold; color: #111827;">{price}</div>
1330
- <div style="font-size: 15px;">{change_html}</div>
1331
  </div>
1332
- <div style="margin-top: 16px; display: grid; grid-template-columns: auto 1fr; gap: 10px; padding: 12px; background: white; border-radius: 8px; border: 1px solid #e5e7eb;">
1333
- <div style="font-size: 14px; color: #6b7280;">Open</div><div style="font-size: 14px; font-weight: 600; text-align: right; color: #111827;">{open_val}</div>
1334
- <div style="font-size: 14px; color: #6b7280;">High</div><div style="font-size: 14px; font-weight: 600; text-align: right; color: #111827;">{high_val}</div>
1335
- <div style="font-size: 14px; color: #6b7280;">Low</div><div style="font-size: 14px; font-weight: 600; text-align: right; color: #111827;">{low_val}</div>
1336
- <div style="font-size: 14px; color: #6b7280;">Prev Close</div><div style="font-size: 14px; font-weight: 600; text-align: right; color: #111827;">{prev_close_val}</div>
1337
  </div>
1338
  </div>
1339
  """
@@ -1541,9 +1546,9 @@ def update_metrics_dashboard(company_name):
1541
  </div>
1542
  """
1543
  # <div style="font-size: 14px; color: #555;">Vol</div><div style="font-size: 14px; font-weight: 500; text-align: center;">{volume_display}</div>
1544
-
1545
  return html
1546
-
1547
  except Exception as e:
1548
  print(f"Error building stock card: {e}")
1549
  return '<div style="width:250px; padding:16px; color:red;">Error loading stock data</div>'
 
99
  text-align: left;
100
  width: 100%;
101
  box-sizing: border-box;
102
+ position: relative;
103
+ padding-right: 2rem;
104
+ }
105
+
106
+ /* ✅ 为每个公司选项添加删除按钮 */
107
+ .company-list-container label::after {
108
+ content: '×';
109
+ position: absolute;
110
+ right: 8px;
111
+ top: 50%;
112
+ transform: translateY(-50%);
113
+ width: 18px;
114
+ height: 18px;
115
+ border-radius: 50%;
116
+ background: #d1d5db;
117
+ color: white;
118
+ font-size: 14px;
119
+ font-weight: bold;
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ opacity: 0;
124
+ transition: opacity 0.2s;
125
+ cursor: pointer;
126
+ line-height: 1;
127
+ }
128
+
129
+ .company-list-container label:hover::after {
130
+ opacity: 1;
131
+ }
132
+
133
+ .company-list-container label::after:hover {
134
+ background: #9ca3af;
135
  }
136
 
137
  /* 悬停效果 */
 
140
  border-color: #d1d5db;
141
  }
142
 
143
+ /* 选中效果 - 使用蓝色 */
144
  .company-list-container input[type="radio"]:checked + span {
145
+ background: #3b82f6 !important;
146
  color: white !important;
147
  font-weight: 600 !important;
148
  display: block;
 
161
  }
162
 
163
  label.selected {
164
+ background: #3b82f6 !important;
165
  color: white !important;
166
  }
167
 
 
243
  background: #f9fafb !important;
244
  }
245
 
246
+ /* ✅ 缩小Easy Financial AI Assistant标题 - 更精致 */
247
  .chatbot > .wrap > .head h1,
248
  .chatbot > .wrap > .head h2,
249
  .chatbot > .wrap > .head h3 {
250
+ font-size: 13px !important;
251
  margin: 0 !important;
252
+ font-weight: 500 !important;
253
+ color: #6b7280 !important;
254
+ letter-spacing: 0.3px !important;
255
  }
256
 
257
  /* Tabs标签栏样式 */
 
735
  <div class="report-item-content">
736
  <span class="text-gray-800">{period}-{stock_code}-{source_form}</span>
737
  <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" class="text-blue-500" viewBox="0 0 20 20" fill="currentColor">
738
+ <path fill-rule="evenodd" d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 10-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l-1.5-1.5a2 2 0 11-2.828-2.828l3-3z" clip-rule="evenodd" />
739
  </svg>
740
  </div>
741
  </div>
 
1207
  income_statement = table_data
1208
  yoy_rates = []
1209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1210
  # 创建一个映射,将年份列索引映射到增长率
1211
  yoy_map = {}
1212
  if len(yoy_rates) > 1 and len(yoy_rates[0]) > 1:
 
1222
  yoy_map[category][yoy_headers[j]] = rate
1223
 
1224
  table_rows = ""
1225
+ header_row = income_statement[0]
1226
 
1227
+ for i, row in enumerate(income_statement):
1228
  if i == 0:
 
1229
  row_style = "background-color: #f5f5f5; font-weight: 500;"
1230
  else:
1231
  row_style = "background-color: #f9f9f9;"
 
1233
 
1234
  for j, cell in enumerate(row):
1235
  if j == 0:
1236
+ # Category列设置最大宽度,避免过宽
1237
+ cells += f"<td style='padding: 8px; border: 1px solid #ddd; text-align: left; font-size: 13px; max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;'>{cell}</td>"
1238
  else:
 
1239
  # 添加增长率箭头(如果有的话)
1240
  growth = None
1241
+ category = row[0]
1242
+ if i > 0 and category in yoy_map and j > 0 and j < len(header_row):
1243
+ year_header = header_row[j]
1244
+ if year_header in yoy_map[category]:
1245
+ growth = yoy_map[category][year_header]
1246
 
1247
  if growth and growth != "N/A":
1248
  arrow = "▲" if growth.startswith("+") else "▼"
 
1256
  table_rows += f"<tr style='{row_style}'>{cells}</tr>"
1257
 
1258
  html = f"""
1259
+ <div style="min-width: 400px;max-width: 600px;height: 300px !important;border: 1px solid #e5e7eb; border-radius: 12px; padding: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.08); font-family: 'Segoe UI', sans-serif; background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);">
1260
  <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 18px; padding-bottom: 12px; border-bottom: 2px solid #e5e7eb;">
1261
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1262
  <path d="M12 2L15.09 8.26L19 9.07L16 14L16 19L12 19L8 14L8 9.07L4.91 8.26L8 2L12 2Z" fill="#3b82f6"/>
 
1327
  prev_close_val = company_info.get("previous_close", "N/A")
1328
 
1329
  html = f"""
1330
+ <div style="width: 250px; height: 300px !important; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px; box-shadow: 0 4px 6px rgba(0,0,0,0.08); font-family: 'Segoe UI', sans-serif; background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%); display: flex; flex-direction: column;">
1331
+ <div style="font-size: 15px; color: #374151; font-weight: 600; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{company_name}</div>
1332
+ <div style="font-size: 12px; color: #6b7280; margin-bottom: 10px;">NYSE:{symbol}</div>
1333
+ <div style="display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; padding: 10px; background: #f9fafb; border-radius: 8px; flex-wrap: wrap;">
1334
+ <div style="font-size: 28px; font-weight: bold; color: #111827;">{price}</div>
1335
+ <div style="font-size: 13px;">{change_html}</div>
1336
  </div>
1337
+ <div style="flex: 1; display: grid; grid-template-columns: auto 1fr; gap: 6px 8px; padding: 10px; background: white; border-radius: 8px; border: 1px solid #e5e7eb; font-size: 12px; align-content: start;">
1338
+ <div style="color: #6b7280;">Open</div><div style="font-weight: 600; text-align: right; color: #111827; white-space: nowrap;">{open_val}</div>
1339
+ <div style="color: #6b7280;">High</div><div style="font-weight: 600; text-align: right; color: #111827; white-space: nowrap;">{high_val}</div>
1340
+ <div style="color: #6b7280;">Low</div><div style="font-weight: 600; text-align: right; color: #111827; white-space: nowrap;">{low_val}</div>
1341
+ <div style="color: #6b7280;">Prev Close</div><div style="font-weight: 600; text-align: right; color: #111827; white-space: nowrap;">{prev_close_val}</div>
1342
  </div>
1343
  </div>
1344
  """
 
1546
  </div>
1547
  """
1548
  # <div style="font-size: 14px; color: #555;">Vol</div><div style="font-size: 14px; font-weight: 500; text-align: center;">{volume_display}</div>
1549
+
1550
  return html
1551
+
1552
  except Exception as e:
1553
  print(f"Error building stock card: {e}")
1554
  return '<div style="width:250px; padding:16px; color:red;">Error loading stock data</div>'