- 她从不主动开口,点一下才冒气泡;比赛里不弹。台词 326 句(shared/mascot/lines.ts), 口吻照「小鲸鱼」角色卡,学校里舍掉英文、粗口,「用户」改叫「同学」 - 按情况换话:题目页分没写、没交、例子没对上/对上、答错、编译错误、运行出错、超时、 错很多次、做对、一次就对、终于对了、以前做过;首页、题目列表、提交、专题、自学、排名等各有一组 - 按钮真的去办:运行例子、我错在哪(切到结果里出错的那一段)、举手、输题号、随便来一道、 下一道、选题…… - 老师也看得到:有学生举手时任何页面先说这件事;首页、课堂任务、统计、题目页各有一组 - 页面用 useMascotGuide 告诉她现在的情况(shared/mascot/guide.ts),以后按学生行为调整也接在这一层 - 修:连点时像卡住了(快点时按压过渡来不及显示,改成每下播一遍压扁回弹); 一打开从左上角飞到右下角;去掉单击的摆动 设计稿与台词表:https://claude.ai/artifact/Qz2zPCfq2zCrqmxyms1UGx Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
15966ceb0d
commit
ef3c53c671
25 files changed
+860
-57
No files matched your search
@@ -6,6 +6,7 @@ import { useBreakpoints } from 'shared/composables/breakpoints'
|
||||
import { useAuthModalStore } from 'shared/store/authModal'
|
||||
import AdminLink from 'shared/components/AdminLink.vue'
|
||||
import { useUserStore } from 'shared/store/user'
|
||||
import { goAction, useMascotGuide } from 'shared/mascot/guide'
|
||||
import { COURSES, continueStep, doneCount, groupByProject, tutorialPath, tutorialState, splitProject, splitTitle, type TutorialType } from './utils'
|
||||
import TutorialRow from './components/TutorialRow.vue'
|
||||
import ProjectTile from './components/ProjectTile.vue'
|
||||
@@ -94,6 +95,14 @@ function doneIn(course: Course, ids: number[]) {
|
||||
return ids.filter((id) => tutorialState(course.progress[id]) === 'done').length
|
||||
}
|
||||
|
||||
// 看板娘:学过就带去「接着学」那一课,一课没学过就从当前页签那门课的第 1 课开始
|
||||
useMascotGuide(() => {
|
||||
if (!loaded.value || userStore.isTeacherOrAbove) return null
|
||||
const it = resume.value
|
||||
if (it) return { situation: 'learn.continue', n: it.step, actions: [goAction(router, '接着学', tutorialPath(it.course.type, it.step))] }
|
||||
return { situation: 'learn.fresh', actions: [goAction(router, '第 1 课', tutorialPath(tab.value, 1))] }
|
||||
})
|
||||
|
||||
watch(() => userStore.isAuthed, load)
|
||||
onMounted(load)
|
||||
</script>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useBackClose } from 'shared/composables/backClose'
|
||||
import { useBreakpoints } from 'shared/composables/breakpoints'
|
||||
import AdminLink from 'shared/components/AdminLink.vue'
|
||||
import { useUserStore } from 'shared/store/user'
|
||||
import { useMascotGuide, type MascotAction } from 'shared/mascot/guide'
|
||||
import { COURSES, doneCount, groupByProject, tutorialPath, tutorialState, splitTitle, type TutorialType } from './utils'
|
||||
import TutorialBody from './components/TutorialBody.vue'
|
||||
import TutorialEnd from './components/TutorialEnd.vue'
|
||||
@@ -233,6 +234,16 @@ function jump(id: string) {
|
||||
function jumpExercise(id: number) {
|
||||
jump(`exercise-${id}`)
|
||||
}
|
||||
|
||||
// 看板娘:练一练没做完就带去第一道没做对的;做完了(或这课没有练一练)就去下一课
|
||||
useMascotGuide(() => {
|
||||
if (!tutorial.value || userStore.isTeacherOrAbove) return null
|
||||
const to = next.value?.to
|
||||
const nextLesson: MascotAction[] = to ? [{ label: '下一课', run: () => router.push(to) }] : []
|
||||
const unsolved = firstUnsolved.value
|
||||
if (!unsolved) return { situation: 'tutorial.passed', actions: nextLesson }
|
||||
return { situation: 'tutorial', actions: [{ label: '练一练', run: () => jumpExercise(unsolved.id) }, ...nextLesson] }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in new issue
Block a user