Deploy / deploy (push) Canceled after 0s
- 后台课堂任务 admin/lesson → admin/task(/admin/task),和前台 oj/task 对上 - 后台首页 admin/setting/home.vue → admin/home/,设置 → admin/config/ - 卡点分析、年度趋势从 admin/problem 搬到 admin/analytics(/admin/analytics/stuck|trend),和菜单的「学情分析」、后端 analytics.ts 对上 - 首页 dashboard.vue / TeacherHome.vue → student.vue / teacher.vue;自学首页 home.vue → index.vue,看一课 index.vue → tutorial.vue - lesson 只表示课堂上的一节:自学那边改叫 tutorial(oj/learn/lesson.ts → utils.ts、isLessonDone → isTutorialDone、Lesson*.vue → Tutorial*.vue、自学情况的 lessons 字段 → tutorials) - 旧地址不留跳转 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
1.4 KiB
Vue
60 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import type { TutorialState, ProjectGroup } from '../utils'
|
|
|
|
/**
|
|
* 一门课的进度条:一课一小段,按项目分组隔开。绿 = 学完,橙 = 在学,灰 = 没开始,
|
|
* 当前这课描一圈。
|
|
*/
|
|
defineProps<{
|
|
groups: ProjectGroup[]
|
|
stateOf: (id: number) => TutorialState
|
|
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.tutorials[0]!.id" class="group" :style="{ gap: `${gap ?? 3}px` }">
|
|
<span
|
|
v-for="tutorial in group.tutorials"
|
|
:key="tutorial.id"
|
|
class="cell"
|
|
:class="[stateOf(tutorial.id), { current: tutorial.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>
|