You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

687 lines
43 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实验报告 · AI 编程辅助与成绩分析实训</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'toge-primary': '#4F46E5',
'toge-secondary': '#7C3AED',
'toge-accent': '#06B6D4',
'toge-success': '#10B981',
'toge-warning': '#F59E0B',
'toge-danger': '#EF4444',
'toge-light': '#F3F4F6',
'toge-dark': '#1F2937',
},
fontFamily: {
'sans': ['Inter', 'Noto Sans SC', 'sans-serif'],
}
}
}
}
</script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- 使用更可靠的Font Awesome CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/vs2015.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
body {
font-family: 'Inter', 'Noto Sans SC', sans-serif;
}
.glass-card {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.score-circle {
background: conic-gradient(#4F46E5 0deg, #4F46E5 var(--percentage), #E5E7EB var(--percentage));
}
.tab-active {
border-bottom: 2px solid #4F46E5;
color: #4F46E5;
}
.code-block {
background-color: #1E1E1E;
color: #D4D4D4;
font-family: 'Consolas', 'Monaco', monospace;
}
#repo-preview-body pre {
margin: 0;
background: transparent;
}
#repo-preview-body code.hljs {
background: transparent !important;
padding: 0;
}
/* Markdown对话与提问卡片 + Hook 详情弹窗 */
.question-tab-md,
.hook-modal-md {
font-size: 0.875rem;
line-height: 1.65;
color: #334155;
word-break: break-word;
}
.question-tab-md > :first-child,
.hook-modal-md > :first-child {
margin-top: 0;
}
.question-tab-md > :last-child,
.hook-modal-md > :last-child {
margin-bottom: 0;
}
.question-tab-md h1, .hook-modal-md h1 { font-size: 1.25rem; font-weight: 600; margin: 0.75em 0 0.35em; }
.question-tab-md h2, .hook-modal-md h2 { font-size: 1.1rem; font-weight: 600; margin: 0.65em 0 0.3em; }
.question-tab-md h3, .hook-modal-md h3 { font-size: 1rem; font-weight: 600; margin: 0.55em 0 0.25em; }
.question-tab-md h4, .hook-modal-md h4 { font-size: 0.95rem; font-weight: 600; margin: 0.5em 0 0.2em; }
.question-tab-md p, .hook-modal-md p { margin: 0.4em 0; }
.question-tab-md ul, .question-tab-md ol,
.hook-modal-md ul, .hook-modal-md ol { margin: 0.4em 0; padding-left: 1.35rem; }
.question-tab-md li, .hook-modal-md li { margin: 0.15em 0; }
.question-tab-md blockquote, .hook-modal-md blockquote {
margin: 0.5em 0;
padding-left: 0.85rem;
border-left: 3px solid #c7d2fe;
color: #475569;
}
.question-tab-md pre, .hook-modal-md pre {
margin: 0.5em 0;
padding: 0.65rem 0.85rem;
border-radius: 0.5rem;
overflow-x: auto;
background: #1e293b;
color: #e2e8f0;
font-size: 0.8125rem;
}
.question-tab-md pre code, .hook-modal-md pre code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
background: transparent !important;
padding: 0;
font-size: inherit;
color: inherit;
}
.question-tab-md :not(pre) > code, .hook-modal-md :not(pre) > code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.8125em;
background: #f1f5f9;
padding: 0.1em 0.35em;
border-radius: 0.25rem;
color: #0f172a;
}
.question-tab-md a, .hook-modal-md a { color: #4f46e5; text-decoration: underline; text-underline-offset: 2px; }
.question-tab-md a:hover, .hook-modal-md a:hover { color: #4338ca; }
.question-tab-md table, .hook-modal-md table {
width: 100%;
border-collapse: collapse;
margin: 0.5em 0;
font-size: 0.8125rem;
}
.question-tab-md th, .question-tab-md td,
.hook-modal-md th, .hook-modal-md td {
border: 1px solid #e2e8f0;
padding: 0.35rem 0.5rem;
text-align: left;
}
.question-tab-md th, .hook-modal-md th { background: #f8fafc; font-weight: 600; }
.question-tab-md hr, .hook-modal-md hr { margin: 0.75em 0; border: 0; border-top: 1px solid #e2e8f0; }
.question-tab-md img, .hook-modal-md img { max-width: 100%; height: auto; border-radius: 0.375rem; }
.highlight-line {
background-color: rgba(255, 255, 0, 0.1);
}
.ai-message {
position: relative;
overflow: hidden;
}
.ai-message::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(to bottom, #4F46E5, #7C3AED);
}
.progress-bar {
transition: width 1s ease-in-out;
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.pulse-dot {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes hook-modal-in {
from { opacity: 0; transform: scale(0.96) translateY(8px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
.hook-modal-panel-animate {
animation: hook-modal-in 0.22s ease-out;
}
/* 确保图标显示 */
.fa, .fas, .far, .fal, .fad, .fab {
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen">
<!-- Header -->
<header class="bg-white shadow-sm sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-toge-primary to-toge-secondary flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
</div>
<div>
<h1 class="text-xl font-bold text-gray-900">头歌实践教学平台</h1>
<p class="text-xs text-gray-500">Cursor智能编程环境</p>
</div>
</div>
<div class="flex items-center space-x-4">
<div class="hidden md:flex items-center space-x-2 text-sm text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span id="report-date">加载中…</span>
</div>
<button class="flex items-center space-x-2 bg-toge-primary hover:bg-indigo-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-all shadow-sm hover:shadow">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
<span>导出报告</span>
</button>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div id="report-banner" class="mb-4 hidden rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900"></div>
<!-- Student Info & Experiment Title -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 mb-6 fade-in">
<div class="flex flex-col md:flex-row md:items-center md:justify-between">
<div class="flex items-center space-x-4 mb-4 md:mb-0">
<div class="relative">
<img id="student-avatar" src="https://picsum.photos/seed/student456/80/80.jpg" alt="学生头像" class="w-16 h-16 rounded-full object-cover border-2 border-toge-primary">
<div class="absolute -bottom-1 -right-1 w-5 h-5 bg-toge-success rounded-full border-2 border-white"></div>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-900" id="student-name">学员</h2>
<p class="text-sm text-gray-600" id="student-meta">正在拉取仓库并读取 chat_logs推断身份与实训上下文…</p>
</div>
</div>
<div class="flex items-center space-x-3">
<span class="px-3 py-1 bg-toge-light rounded-full text-sm text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline-block mr-1 text-toge-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span id="tag-course">大模型与智能编程实践</span>
</span>
<span class="px-3 py-1 bg-toge-light rounded-full text-sm text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline-block mr-1 text-toge-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
<span id="tag-exp">实训成绩分析脚本AI 辅助)</span>
</span>
</div>
</div>
</div>
<!-- Stats Overview -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
<!-- Score Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 fade-in" style="animation-delay: 0.1s">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-medium text-gray-600">实训对齐度</h3>
<div class="w-8 h-8 rounded-full bg-toge-light flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-toge-warning" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
</svg>
</div>
</div>
<div class="flex items-center justify-center">
<div class="relative w-28 h-28">
<div class="absolute inset-0 rounded-full score-circle" id="score-ring" style="--percentage: 0deg;"></div>
<div class="absolute inset-2 rounded-full bg-white flex items-center justify-center flex-col">
<span class="text-3xl font-bold text-toge-primary" id="stat-lab-progress"></span>
<span class="text-xs text-gray-500">/ 100</span>
</div>
</div>
</div>
<div class="mt-4 text-center">
<span id="align-label-badge" class="px-3 py-1 bg-green-100 text-green-800 text-xs rounded-full">良好</span>
</div>
</div>
<!-- Time Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 fade-in" style="animation-delay: 0.2s">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-medium text-gray-600">TOKENS消耗量</h3>
<div class="w-8 h-8 rounded-full bg-toge-light flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-toge-accent" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
</div>
<div class="flex items-center justify-center h-28">
<div class="text-center">
<div class="flex items-baseline justify-center">
<span class="text-3xl font-bold text-toge-accent" id="stat-hook-count">0</span>
<span id="stat-hook-unit" class="text-lg font-medium text-gray-700 ml-1">TOKENS</span>
</div>
<div class="mt-3 flex items-center justify-center text-sm text-gray-600 px-1 text-center" id="stat-token-hint">
TOKENS消耗明细加载中…
</div>
</div>
</div>
</div>
<!-- Questions Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 fade-in" style="animation-delay: 0.3s">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-medium text-gray-600">用户提问摘录</h3>
<div class="w-8 h-8 rounded-full bg-toge-light flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-toge-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
</div>
<div class="flex items-center justify-center h-28">
<div class="text-center">
<div class="flex items-baseline justify-center">
<span class="text-3xl font-bold text-toge-secondary" id="stat-question-count">0</span>
<span class="text-lg font-medium text-gray-700 ml-1"></span>
</div>
<div class="mt-3 flex items-center justify-center space-x-2" id="stat-question-badges">
<span class="px-2 py-1 bg-gray-100 text-gray-800 text-xs rounded-full">加载中</span>
</div>
</div>
</div>
</div>
<!-- Code Quality Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 fade-in" style="animation-delay: 0.4s">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-medium text-gray-600">对话覆盖度</h3>
<div class="w-8 h-8 rounded-full bg-toge-light flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-toge-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
</div>
</div>
<div class="flex items-center justify-center h-28">
<div class="w-full">
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-gray-600" id="stat-coverage-a-label">会话数</span>
<span class="text-sm font-medium text-toge-primary" id="stat-coverage-a">0</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2 mb-3">
<div class="bg-toge-primary h-2 rounded-full progress-bar" id="stat-coverage-a-bar" style="width: 0%"></div>
</div>
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-gray-600" id="stat-coverage-b-label">最近模型</span>
<span class="text-sm font-medium text-toge-secondary truncate max-w-[8rem]" id="stat-coverage-b"></span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-toge-secondary h-2 rounded-full progress-bar" id="stat-coverage-b-bar" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Tabs Navigation -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-6 overflow-hidden">
<div class="border-b border-gray-100">
<nav class="flex -mb-px">
<button id="tab-questions" class="tab-active px-6 py-4 text-sm font-medium flex items-center space-x-2" onclick="switchTab('questions')">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>对话与提问</span>
</button>
<button id="tab-answers" class="px-6 py-4 text-sm font-medium text-gray-500 hover:text-gray-700 flex items-center space-x-2" onclick="switchTab('answers')">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" />
</svg>
<span>实训步骤 / 评测对齐</span>
</button>
<button id="tab-code" class="px-6 py-4 text-sm font-medium text-gray-500 hover:text-gray-700 flex items-center space-x-2" onclick="switchTab('code')">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<span>作业文件</span>
</button>
<button id="tab-evaluation" class="px-6 py-4 text-sm font-medium text-gray-500 hover:text-gray-700 flex items-center space-x-2" onclick="switchTab('evaluation')">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span>作业评价</span>
<span class="px-1.5 py-0.5 bg-toge-primary text-white text-xs rounded-full">AI</span>
</button>
</nav>
</div>
<!-- Tab Content: Questions -->
<div id="content-questions" class="p-6">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900" id="questions-section-title">从钩子捕获的提问与上下文(需结合仓库核验)</h3>
<div class="flex items-center space-x-2">
<select class="bg-white border border-gray-200 rounded-lg text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-toge-primary focus:border-transparent">
<option>全部问题</option>
<option>已解决</option>
<option>未解决</option>
</select>
<select class="bg-white border border-gray-200 rounded-lg text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-toge-primary focus:border-transparent">
<option>按时间排序</option>
<option>按类型排序</option>
</select>
</div>
</div>
<div class="space-y-4" id="dynamic-questions">
<div class="border border-dashed border-gray-200 rounded-xl p-6 text-center text-sm text-gray-500">
正在加载对话与提问分析chat_logs + 大模型整理)…
</div>
</div>
<div class="mt-6 flex items-center justify-between">
<div class="text-sm text-gray-500" id="questions-pager-hint">
共 0 条(去重后展示)
</div>
<div id="questions-footer-hint" class="flex items-center space-x-2 text-xs text-gray-400">
数据来自本机/实验环境中的 Cursor 钩子导出
</div>
</div>
</div>
<!-- Tab Content: Answers -->
<div id="content-answers" class="p-6 hidden">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900" id="rubric-section-title">实训步骤与头歌评测项对齐</h3>
<div class="flex items-center space-x-2">
<select class="bg-white border border-gray-200 rounded-lg text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-toge-primary focus:border-transparent">
<option>全部题目</option>
<option>选择题</option>
<option>编程题</option>
<option>填空题</option>
</select>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">环节</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">对应实训要求</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" id="rubric-col-status">仓库 / 日志</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">与头歌评测关系</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200" id="dynamic-rubric-body">
<tr>
<td class="px-6 py-4 text-sm text-gray-500" colspan="4">加载中…</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-6 text-sm text-gray-500" id="rubric-footer-hint">
推断规则:在钩子捕获的用户提问与 AI 回复文本中匹配关键词(如 read_csv、mean、matplotlib 等),仅供参考。
</div>
</div>
<!-- Tab Content: Assignment Files -->
<div id="content-code" class="p-6 hidden">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900" id="assignment-section-title">学员仓库文件</h3>
<div class="flex items-center space-x-2">
<select class="bg-white border border-gray-200 rounded-lg text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-toge-primary focus:border-transparent">
<option>全部文件</option>
<option>代码文件</option>
<option>文档文件</option>
<option>其他文件</option>
</select>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- File List由 report-ui.js 填充) -->
<div class="lg:col-span-1 space-y-3" id="dynamic-file-list">
<div class="text-sm text-gray-500 border border-dashed rounded-xl p-4">加载交付物清单…</div>
</div>
<!-- File Preview -->
<div class="lg:col-span-2">
<div class="bg-white border border-gray-200 rounded-xl overflow-hidden">
<div class="bg-gray-800 px-4 py-3 flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
<span class="text-gray-400 text-sm ml-2" id="preview-filename">AI 回复摘录</span>
</div>
<div class="flex items-center space-x-2">
<button class="text-gray-400 hover:text-white text-sm">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline-block mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
复制
</button>
<button class="text-gray-400 hover:text-white text-sm">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline-block mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
</svg>
全屏
</button>
</div>
</div>
<div id="repo-preview-body" class="code-block p-4 text-sm overflow-x-auto min-h-[12rem]">
<pre id="repo-text-preview-wrap" class="m-0 min-h-[10rem]"><code id="dynamic-code-snippet" class="hljs block w-full whitespace-pre-wrap text-[13px] leading-relaxed">点击左侧仓库中的文件可在此预览内容。</code></pre>
<img id="repo-preview-image" class="hidden max-h-[28rem] mx-auto rounded border border-gray-600 mt-2" alt="图片预览" />
</div>
</div>
<div class="mt-4 bg-white border border-gray-200 rounded-xl p-4" id="snippet-meta-card">
<h4 class="font-medium text-gray-900 mb-2" id="snippet-meta-heading">文件信息</h4>
<p class="text-sm text-gray-600" id="snippet-meta-text">加载中…</p>
</div>
</div>
</div>
</div>
<!-- Tab Content: Assignment Evaluation -->
<div id="content-evaluation" class="p-6 hidden">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900 flex items-center">
作业评价
<span class="ml-2 px-2 py-1 bg-toge-primary text-white text-xs rounded-full">AI</span>
</h3>
<div class="flex items-center space-x-2">
<span class="text-sm text-gray-500" id="eval-generated-at">生成时间: —</span>
<button type="button" id="btn-refresh-report" class="flex items-center space-x-1 text-toge-primary hover:text-indigo-700 text-sm font-medium">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
<span>重新拉取并生成</span>
</button>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Overall Evaluation -->
<div class="lg:col-span-2 space-y-6">
<div class="bg-gradient-to-r from-toge-primary to-toge-secondary rounded-xl p-6 text-white">
<div class="flex items-start space-x-4">
<div class="w-12 h-12 rounded-full bg-white/20 flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div>
<h3 class="text-lg font-semibold mb-2">总体评价</h3>
<p class="text-white/90 whitespace-pre-wrap leading-relaxed" id="eval-overall-text">
正在拉取学员仓库并结合对话日志生成总体评价(含完成度、待改进点与提问技巧等)…
</p>
</div>
</div>
</div>
<div class="bg-white border border-gray-200 rounded-xl p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">能力评估(映射实训能力)</h3>
<p class="text-xs text-gray-500 mb-3 leading-relaxed" id="ability-section-hint">维度定义见 <code class="text-gray-700">config/evaluation-dimensions.yaml</code>;加载后将结合本任务要求、仓库扫描、实训步骤对齐与提问摘录给出核验说明与分值。</p>
<div class="space-y-4" id="eval-ability-container"></div>
</div>
<div class="bg-white border border-gray-200 rounded-xl p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">问题分析与建议(对照头歌评测项)</h3>
<p class="text-xs text-gray-500 mb-3">对照交付物与评测步骤;快速模式为规则摘要,整页大模型模式为深度分析。</p>
<div class="space-y-4" id="dynamic-eval-issues">
<p class="text-sm text-gray-500">加载中…</p>
</div>
</div>
</div>
<!-- Learning Suggestions -->
<div class="space-y-6">
<div class="bg-white border border-gray-200 rounded-xl p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">学习建议(结合本实训)</h3>
<p class="text-xs text-gray-500 mb-3 leading-relaxed" id="learning-section-hint">依据任务说明、远程仓库代码与数据扫描、实训步骤对齐表及对话日志生成;加载完成后将显示具体说明。</p>
<div class="space-y-3" id="dynamic-learning-list"></div>
</div>
<div class="bg-white border border-gray-200 rounded-xl p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">推荐学习资源</h3>
<p class="text-xs text-gray-500 mb-2" id="resources-source-hint">默认链接若已运行大模型评价lab-eval-ai.json此处由模型推荐覆盖。</p>
<div class="space-y-3" id="dynamic-resources">
<div class="text-sm text-gray-400 border border-dashed rounded-lg p-3">加载中…</div>
</div>
</div>
<div class="bg-white border border-gray-200 rounded-xl p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">班级排名</h3>
<div class="flex items-center justify-center">
<div class="text-center">
<div class="text-4xl font-bold text-toge-primary" id="class-rank-place"></div>
<div class="text-sm text-gray-500 mt-1" id="class-rank-line2">需教务数据</div>
<div class="mt-3 flex items-center justify-center text-sm text-gray-600 px-2" id="class-rank-note">
可由 lab-eval-ai.json 的 class_rank 填充;无数据时为占位。
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- Hook 对话详情弹窗(由 report-ui.js 打开,正文为 innerHTML 结构化渲染) -->
<div id="question-chat-modal" class="fixed inset-0 z-[100] hidden items-center justify-center p-3 sm:p-5" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="question-chat-modal-title">
<div id="question-chat-modal-backdrop" class="absolute inset-0 bg-slate-900/55 backdrop-blur-sm cursor-pointer" tabindex="-1"></div>
<div id="question-chat-modal-panel" class="hook-modal-panel-animate relative z-[101] flex w-full max-w-3xl max-h-[min(92vh,880px)] flex-col overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-900/10">
<div class="shrink-0 bg-gradient-to-r from-indigo-600 via-violet-600 to-indigo-700 px-5 py-4 text-white">
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div class="min-w-0 flex-1">
<p class="text-[11px] font-medium uppercase tracking-wider text-indigo-200/90">钩子捕获 · 会话时间线</p>
<h2 id="question-chat-modal-title" class="mt-1 text-lg font-semibold tracking-tight">对话详情</h2>
<p class="mt-2 break-all font-mono text-xs leading-relaxed text-indigo-100/95" id="question-chat-modal-conv-id" title="">会话 ID</p>
</div>
<div class="flex shrink-0 flex-wrap items-center gap-2">
<button type="button" id="question-chat-modal-copy" class="rounded-lg bg-white/15 px-3 py-2 text-xs font-medium text-white ring-1 ring-white/25 transition hover:bg-white/25">复制全文</button>
<button type="button" id="question-chat-modal-close" class="rounded-lg bg-white/10 px-3 py-2 text-xs font-medium text-white ring-1 ring-white/20 transition hover:bg-white/20">关闭</button>
</div>
</div>
</div>
<div id="question-chat-modal-body" class="min-h-[14rem] flex-1 overflow-y-auto bg-gradient-to-b from-slate-50 to-white px-4 py-5 sm:px-6"></div>
<p class="shrink-0 border-t border-slate-100 bg-slate-50/80 px-4 py-3 text-center text-[11px] leading-relaxed text-slate-500 sm:px-6">数据来自本服务读取的 chat_logs用户侧摘录与模型回复可与仓库交付物对照核验。</p>
</div>
</div>
<!-- Footer -->
<footer class="bg-white border-t border-gray-200 mt-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="flex flex-col md:flex-row md:items-center md:justify-between">
<div class="flex items-center space-x-2 mb-4 md:mb-0">
<div class="w-8 h-8 rounded-lg bg-gradient-to-r from-toge-primary to-toge-secondary flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
</div>
<span class="text-sm font-medium text-gray-700">头歌实践教学平台</span>
</div>
<div class="flex items-center space-x-4 text-sm text-gray-500">
<a href="#" class="hover:text-gray-700">帮助中心</a>
<a href="#" class="hover:text-gray-700">隐私政策</a>
<a href="#" class="hover:text-gray-700">联系我们</a>
<span>© 2026 头歌实践教学平台</span>
</div>
</div>
</div>
</footer>
<script>
// Tab switching functionality
function switchTab(tabName) {
// Hide all content sections
document.querySelectorAll('[id^="content-"]').forEach(content => {
content.classList.add('hidden');
});
// Remove active class from all tabs
document.querySelectorAll('[id^="tab-"]').forEach(tab => {
tab.classList.remove('tab-active');
tab.classList.add('text-gray-500', 'hover:text-gray-700');
});
// Show selected content section
document.getElementById(`content-${tabName}`).classList.remove('hidden');
// Add active class to selected tab
const selectedTab = document.getElementById(`tab-${tabName}`);
selectedTab.classList.add('tab-active');
selectedTab.classList.remove('text-gray-500', 'hover:text-gray-700');
}
// Initialize progress bars animation
document.addEventListener('DOMContentLoaded', function() {
setTimeout(() => {
document.querySelectorAll('.progress-bar').forEach(bar => {
const width = bar.style.width;
bar.style.width = '0';
setTimeout(() => {
bar.style.width = width;
}, 100);
});
}, 500);
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/11.1.1/marked.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="/report-ui.js" defer></script>
</body>
</html>