SarahXia0405 commited on
Commit
471bb76
·
verified ·
1 Parent(s): fda6da3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -77
app.py CHANGED
@@ -186,49 +186,18 @@ Currently: English & 简体中文.
186
  CUSTOM_CSS = """
187
  /* --- Login Page --- */
188
  .login-container {
189
- max-width: 500px !important;
190
- margin: 100px auto !important;
191
- padding: 40px !important;
192
- background: #ffffff;
193
- border: 1px solid #e5e7eb;
194
- border-radius: 12px;
195
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
196
- text-align: center;
197
- }
198
- .login-btn {
199
- background-color: #8B1A1A !important;
200
- color: white !important;
201
- font-weight: bold !important;
202
- margin-top: 20px !important;
203
  }
 
204
 
205
  /* --- Main Header --- */
206
- .header-container {
207
- padding: 10px 20px;
208
- background-color: #ffffff;
209
- border-bottom: 2px solid #f3f4f6;
210
- margin-bottom: 15px;
211
- display: flex;
212
- align-items: center;
213
- }
214
 
215
- /* 伪装成 Link 的 Button (Log Out) */
216
- .link-btn {
217
- background: transparent !important;
218
- border: none !important;
219
- box-shadow: none !important;
220
- color: #000 !important;
221
- text-decoration: underline;
222
- font-weight: bold !important;
223
- font-size: 12px !important;
224
- padding: 0 5px !important;
225
- min-width: auto !important;
226
- }
227
- .link-btn:hover {
228
- color: #cc0000 !important;
229
- }
230
-
231
- /* User Guide 样式 */
232
  .main-user-guide { border: none !important; background: transparent !important; box-shadow: none !important; }
233
  .main-user-guide > .label-wrap { border: none !important; background: transparent !important; padding: 10px 0 !important; }
234
  .main-user-guide > .label-wrap span { font-size: 1.3rem !important; font-weight: 800 !important; color: #111827 !important; }
@@ -238,17 +207,26 @@ CUSTOM_CSS = """
238
  .clean-accordion > .label-wrap span { font-size: 0.9rem !important; font-weight: 500 !important; color: #374151 !important; }
239
  .clean-accordion > .label-wrap:hover { background-color: #f9fafb !important; }
240
 
241
- /* Action 按钮 & Tooltip */
242
  .action-btn { font-weight: bold !important; font-size: 0.9rem !important; position: relative; overflow: visible !important; }
243
  .action-btn:hover::before { content: "See User Guide for details"; position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background-color: #333; color: #fff; padding: 5px 10px; border-radius: 5px; font-size: 12px; white-space: nowrap; z-index: 1000; pointer-events: none; opacity: 0; animation: fadeIn 0.2s forwards; }
244
  .action-btn:hover::after { content: ""; position: absolute; bottom: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: #333 transparent transparent transparent; opacity: 0; animation: fadeIn 0.2s forwards; }
245
 
 
246
  .html-tooltip { border-bottom: 1px dashed #999; cursor: help; position: relative; }
247
  .html-tooltip:hover::before { content: attr(data-tooltip); position: absolute; bottom: 120%; left: 0; background-color: #333; color: #fff; padding: 5px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 100; pointer-events: none; }
248
-
249
- /* Memory Line Box */
250
  .memory-line-box { border: 1px solid #e5e7eb; padding: 12px; border-radius: 8px; background-color: #f9fafb; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
251
 
 
 
 
 
 
 
 
 
 
 
252
  @keyframes fadeIn { to { opacity: 1; } }
253
  """
254
 
@@ -269,7 +247,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
269
  # ================== Layer 1: Login View ==================
270
  with gr.Group(visible=True) as login_view:
271
  with gr.Column(elem_classes="login-container"):
272
- # Logo Area
273
  gr.HTML(
274
  f"""
275
  <div style="display:flex; justify-content:center; gap:20px; margin-bottom:20px;">
@@ -280,20 +257,16 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
280
  <p style="color: #666; margin-bottom: 30px;">Your Personalized AI Tutor</p>
281
  """
282
  )
283
-
284
  login_name = gr.Textbox(label="Student Name", placeholder="Enter your full name", autofocus=True)
285
  login_id = gr.Textbox(label="Student ID / Email", placeholder="Enter your student ID or email")
286
-
287
  login_btn = gr.Button("Enter Class", elem_classes="login-btn", size="lg")
288
-
289
- login_msg = gr.Markdown(visible=False) # 错误提示占位
290
 
291
  # ================== Layer 2: Main App View ==================
292
  with gr.Group(visible=False) as main_view:
293
 
294
- # --- Custom Header (Using Row for Alignment) ---
295
  with gr.Row(elem_classes="header-container"):
296
- # Left: Mascot & Title
297
  with gr.Column(scale=1):
298
  gr.HTML(
299
  f"""
@@ -312,9 +285,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
312
  """
313
  )
314
 
315
- # Right: Hanbridge Logo + Student Info + Logout
316
  with gr.Column(scale=1):
317
- # 顶部放 Logo,居右
318
  gr.HTML(
319
  f"""
320
  <div style="display:flex; justify-content:flex-end; margin-bottom: 5px;">
@@ -322,18 +293,14 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
322
  </div>
323
  """
324
  )
325
- # 下面放 Info 和 Logout 按钮,使用 Row 紧凑排列
326
  with gr.Row():
327
- # 这里放一个空的 Column 把内容挤到右边
328
  with gr.Column(scale=1): pass
329
-
330
- # 真正的内容在右边
331
  with gr.Column(scale=0, min_width=300):
332
  with gr.Row(elem_classes="no-gap"):
333
  student_info_disp = gr.Markdown(value="", elem_id="student-info")
334
  logout_btn = gr.Button("Log Out", elem_classes="link-btn")
335
 
336
- # --- Main Layout (Sidebar + Center + Right) ---
337
  with gr.Row():
338
 
339
  # === Left Sidebar ===
@@ -378,25 +345,28 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
378
  # === Center Main ===
379
  with gr.Column(scale=3):
380
 
381
- # Upload & Memory Line
382
  with gr.Row():
383
- # [Left] Upload
384
- with gr.Column(scale=2):
385
- with gr.Row():
386
- with gr.Column(scale=3):
387
- # 调大高度 height=160
388
- syllabus_file = gr.File(
389
- file_types=[".docx", ".pdf", ".pptx"],
390
- file_count="single",
391
- height=160,
392
- label="Upload file (.docx/.pdf/.pptx)"
393
- )
394
- with gr.Column(scale=1):
395
- doc_type = gr.Dropdown(choices=DOC_TYPES, value="Syllabus", label="", container=False)
396
- docs_btn = gr.Button("📂 Loaded Docs", size="sm", variant="secondary")
397
 
398
- # [Right] Memory Line
399
- with gr.Column(scale=1):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  with gr.Group(elem_classes="memory-line-box"):
401
  gr.HTML(
402
  f"""
@@ -439,7 +409,9 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
439
  summary_btn = gr.Button("Summarization", size="sm", elem_classes="action-btn")
440
 
441
  gr.Markdown("### Results")
442
- result_display = gr.Textbox(label="Generated Content", lines=15, placeholder="Results...", show_label=False)
 
 
443
 
444
  # ================== Logic & Events ==================
445
 
@@ -447,7 +419,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
447
  if not name.strip() or not id_val.strip():
448
  return {login_msg: gr.update(value="❌ Please enter both Name and ID", visible=True)}
449
 
450
- # 登录成功:更新Header信息,隐藏登录页,显示主页
451
  welcome_text = f"🎓 **{name}** ({id_val})"
452
  return {
453
  login_view: gr.update(visible=False),
@@ -459,7 +430,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
459
  }
460
 
461
  def perform_logout():
462
- # 登出:清空输入,隐藏主页,显示登录页
463
  return {
464
  login_view: gr.update(visible=True),
465
  main_view: gr.update(visible=False),
@@ -479,7 +449,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
479
  outputs=[login_view, main_view, login_name, login_id, student_info_disp]
480
  )
481
 
482
- # Existing Main App Logic
483
  def update_course_and_rag(file, doc_type_val):
484
  topics = extract_course_topics_from_file(file, doc_type_val)
485
  rag_chunks = build_rag_chunks_from_file(file, doc_type_val)
 
186
  CUSTOM_CSS = """
187
  /* --- Login Page --- */
188
  .login-container {
189
+ max-width: 500px !important; margin: 100px auto !important; padding: 40px !important;
190
+ background: #ffffff; border: 1px solid #e5e7eb; border-radius: 12px;
191
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); text-align: center;
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
+ .login-btn { background-color: #8B1A1A !important; color: white !important; font-weight: bold !important; margin-top: 20px !important; }
194
 
195
  /* --- Main Header --- */
196
+ .header-container { padding: 10px 20px; background-color: #ffffff; border-bottom: 2px solid #f3f4f6; margin-bottom: 15px; display: flex; align-items: center; }
197
+ .link-btn { background: transparent !important; border: none !important; box-shadow: none !important; color: #000 !important; text-decoration: underline; font-weight: bold !important; font-size: 12px !important; padding: 0 5px !important; min-width: auto !important; }
198
+ .link-btn:hover { color: #cc0000 !important; }
 
 
 
 
 
199
 
200
+ /* User Guide */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  .main-user-guide { border: none !important; background: transparent !important; box-shadow: none !important; }
202
  .main-user-guide > .label-wrap { border: none !important; background: transparent !important; padding: 10px 0 !important; }
203
  .main-user-guide > .label-wrap span { font-size: 1.3rem !important; font-weight: 800 !important; color: #111827 !important; }
 
207
  .clean-accordion > .label-wrap span { font-size: 0.9rem !important; font-weight: 500 !important; color: #374151 !important; }
208
  .clean-accordion > .label-wrap:hover { background-color: #f9fafb !important; }
209
 
210
+ /* Action Buttons */
211
  .action-btn { font-weight: bold !important; font-size: 0.9rem !important; position: relative; overflow: visible !important; }
212
  .action-btn:hover::before { content: "See User Guide for details"; position: absolute; bottom: 110%; left: 50%; transform: translateX(-50%); background-color: #333; color: #fff; padding: 5px 10px; border-radius: 5px; font-size: 12px; white-space: nowrap; z-index: 1000; pointer-events: none; opacity: 0; animation: fadeIn 0.2s forwards; }
213
  .action-btn:hover::after { content: ""; position: absolute; bottom: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: #333 transparent transparent transparent; opacity: 0; animation: fadeIn 0.2s forwards; }
214
 
215
+ /* Tooltips & Memory Line */
216
  .html-tooltip { border-bottom: 1px dashed #999; cursor: help; position: relative; }
217
  .html-tooltip:hover::before { content: attr(data-tooltip); position: absolute; bottom: 120%; left: 0; background-color: #333; color: #fff; padding: 5px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 100; pointer-events: none; }
 
 
218
  .memory-line-box { border: 1px solid #e5e7eb; padding: 12px; border-radius: 8px; background-color: #f9fafb; height: 100%; display: flex; flex-direction: column; justify-content: space-between; }
219
 
220
+ /* Results Box Style (For Markdown) */
221
+ .result-box {
222
+ border: 1px solid #e5e7eb;
223
+ background: #ffffff;
224
+ padding: 10px;
225
+ border-radius: 8px;
226
+ height: 100%;
227
+ }
228
+ .result-box .prose { font-size: 0.9rem; }
229
+
230
  @keyframes fadeIn { to { opacity: 1; } }
231
  """
232
 
 
247
  # ================== Layer 1: Login View ==================
248
  with gr.Group(visible=True) as login_view:
249
  with gr.Column(elem_classes="login-container"):
 
250
  gr.HTML(
251
  f"""
252
  <div style="display:flex; justify-content:center; gap:20px; margin-bottom:20px;">
 
257
  <p style="color: #666; margin-bottom: 30px;">Your Personalized AI Tutor</p>
258
  """
259
  )
 
260
  login_name = gr.Textbox(label="Student Name", placeholder="Enter your full name", autofocus=True)
261
  login_id = gr.Textbox(label="Student ID / Email", placeholder="Enter your student ID or email")
 
262
  login_btn = gr.Button("Enter Class", elem_classes="login-btn", size="lg")
263
+ login_msg = gr.Markdown(visible=False)
 
264
 
265
  # ================== Layer 2: Main App View ==================
266
  with gr.Group(visible=False) as main_view:
267
 
268
+ # --- Custom Header ---
269
  with gr.Row(elem_classes="header-container"):
 
270
  with gr.Column(scale=1):
271
  gr.HTML(
272
  f"""
 
285
  """
286
  )
287
 
 
288
  with gr.Column(scale=1):
 
289
  gr.HTML(
290
  f"""
291
  <div style="display:flex; justify-content:flex-end; margin-bottom: 5px;">
 
293
  </div>
294
  """
295
  )
 
296
  with gr.Row():
 
297
  with gr.Column(scale=1): pass
 
 
298
  with gr.Column(scale=0, min_width=300):
299
  with gr.Row(elem_classes="no-gap"):
300
  student_info_disp = gr.Markdown(value="", elem_id="student-info")
301
  logout_btn = gr.Button("Log Out", elem_classes="link-btn")
302
 
303
+ # --- Main Layout ---
304
  with gr.Row():
305
 
306
  # === Left Sidebar ===
 
345
  # === Center Main ===
346
  with gr.Column(scale=3):
347
 
348
+ # --- Top Control Row: Upload | Controls | Memory Line ---
349
  with gr.Row():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
 
351
+ # Col 1: Upload File (最左)
352
+ with gr.Column(scale=2):
353
+ syllabus_file = gr.File(
354
+ file_types=[".docx", ".pdf", ".pptx"],
355
+ file_count="single",
356
+ height=160,
357
+ label="Upload file (.docx/.pdf/.pptx)"
358
+ )
359
+
360
+ # Col 2: Controls (中间 - Dropdown & Docs Button)
361
+ with gr.Column(scale=1):
362
+ # 垂直排列
363
+ doc_type = gr.Dropdown(choices=DOC_TYPES, value="Syllabus", label="File type", container=True)
364
+ # 增加一点间距
365
+ gr.HTML("<div style='height:5px'></div>")
366
+ docs_btn = gr.Button("📂 Loaded Docs", size="sm", variant="secondary")
367
+
368
+ # Col 3: Memory Line (最右)
369
+ with gr.Column(scale=2):
370
  with gr.Group(elem_classes="memory-line-box"):
371
  gr.HTML(
372
  f"""
 
409
  summary_btn = gr.Button("Summarization", size="sm", elem_classes="action-btn")
410
 
411
  gr.Markdown("### Results")
412
+ # 【修改点】:改用 Markdown 组件来显示格式化文本,外面包裹一个 Group 模拟 Box 样式
413
+ with gr.Group(elem_classes="result-box"):
414
+ result_display = gr.Markdown(value="Results will appear here...", label="Generated Content")
415
 
416
  # ================== Logic & Events ==================
417
 
 
419
  if not name.strip() or not id_val.strip():
420
  return {login_msg: gr.update(value="❌ Please enter both Name and ID", visible=True)}
421
 
 
422
  welcome_text = f"🎓 **{name}** ({id_val})"
423
  return {
424
  login_view: gr.update(visible=False),
 
430
  }
431
 
432
  def perform_logout():
 
433
  return {
434
  login_view: gr.update(visible=True),
435
  main_view: gr.update(visible=False),
 
449
  outputs=[login_view, main_view, login_name, login_id, student_info_disp]
450
  )
451
 
 
452
  def update_course_and_rag(file, doc_type_val):
453
  topics = extract_course_topics_from_file(file, doc_type_val)
454
  rag_chunks = build_rag_chunks_from_file(file, doc_type_val)