feat(自学): 自学重做——首页课程地图、读一课按项目分目录、代码块就地运行、学完给题做
Deploy / deploy (push) Canceled after 0s

- 顶栏「自学」进新的自学首页 /learn:接着学(按服务端记录,不再串到上一个学生)+ 按项目分组的课程地图
- 读一课:左边目录按项目折叠,正文加宽,右边本课大纲带练一练标记;去掉了不能运行的示例代码栏
- 正文里的代码块能改能运行,报错用题目页那套中文解释;读输入的代码出输入框
- 课末:练一练做到几道 → 学完了 → 老师挑的几道题(必会标出来)→ 下一课
- 练一练统一成绿色提交、结果一行字;手机版目录从底部弹出
- 后台:教程列表按项目分组拖动排序,编辑页左写右看、练一练插到光标处、挑相关题;
  自学情况改成方块格 + 还没打开过的名单

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-12 09:40:34 +08:00
1 parent 11194543a3
commit 845e41c060
43 files changed
+4675 -1294

No files matched your search

@@ -0,0 +1,64 @@
<script setup lang="ts">
import type { LessonState, ProjectGroup } from "../lesson"
/**
* 一门课的进度条:一课一小段,按项目分组隔开。绿 = 学完,橙 = 在学,灰 = 没开始,
* 当前这课描一圈。
*/
defineProps<{
groups: ProjectGroup[]
stateOf: (id: number) => LessonState
current?: number
/** 每段的宽、高 */
width?: number
height?: number
gap?: number
groupGap?: number
}>()
</script>
<template>
<div class="seg" :style="{ gap: `${groupGap ?? 10}px` }" aria-hidden="true">
<div
v-for="group in groups"
:key="group.lessons[0]!.id"
class="group"
:style="{ gap: `${gap ?? 3}px` }"
>
<span
v-for="lesson in group.lessons"
:key="lesson.id"
class="cell"
:class="[stateOf(lesson.id), { current: lesson.id === current }]"
:style="{
width: `${width ?? 20}px`,
height: `${height ?? 6}px`,
borderRadius: `${(height ?? 6) / 2}px`,
}"
/>
</div>
</div>
</template>
<style scoped>
.seg,
.group {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.cell {
flex-shrink: 0;
background: var(--learn-todo);
}
.cell.done {
background: var(--learn-green);
}
.cell.started {
background: var(--learn-orange);
}
.cell.current {
outline: 2px solid var(--learn-green-text);
outline-offset: 1px;
}
</style>