|
|
<!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>
|