diff --git a/eslint.config.ts b/eslint.config.ts index 082a3ee..87a1bbb 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -5,7 +5,10 @@ import { defineConfig } from 'eslint/config' import { fileURLToPath } from 'node:url' // 直接使用 tsconfig 的绝对路径,避免中文路径在 URL/路径互转时被编码导致读取失败 -const tsconfigEslintPath = fileURLToPath(new URL('./tsconfig.eslint.json', import.meta.url)) +const tsconfigRootDir = fileURLToPath(new URL('.', import.meta.url)) +const tsconfigEslintPath = fileURLToPath( + new URL('./tsconfig.eslint.json', import.meta.url), +) export default defineConfig([ // 全局忽略:自身配置文件、产物、第三方静态资源等不参与 lint @@ -18,24 +21,25 @@ export default defineConfig([ 'public/**', 'vite.config.*', 'postcss.config.*', - 'tailwind.config.*' - ] + 'tailwind.config.*', + ], }, { files: ['**/*.{js,mjs,cjs,ts,mts,cts,tsx,vue}'], - languageOptions: { globals: globals.browser } + languageOptions: { globals: globals.browser }, }, tseslint.configs.recommended, { languageOptions: { parserOptions: { // 让 typescript-eslint 使用专用 tsconfig(显式 include .vue) - project: [tsconfigEslintPath] - } + project: [tsconfigEslintPath], + tsconfigRootDir, + }, }, rules: { - '@typescript-eslint/no-explicit-any': 'off' - } + '@typescript-eslint/no-explicit-any': 'off', + }, }, pluginVue.configs['flat/essential'], { @@ -44,22 +48,28 @@ export default defineConfig([ parserOptions: { parser: { ts: tseslint.parser, - tsx: tseslint.parser + tsx: tseslint.parser, }, project: [tsconfigEslintPath], + tsconfigRootDir, extraFileExtensions: ['.vue'], ecmaFeatures: { - jsx: true - } - } + jsx: true, + }, + }, }, rules: { 'vue/multi-word-component-names': 'off', 'vue/no-undef-components': [ 'error', { - ignorePatterns: ['router-view', 'router-link', 'RouterView', 'RouterLink'] - } + ignorePatterns: [ + 'router-view', + 'router-link', + 'RouterView', + 'RouterLink', + ], + }, ], '@typescript-eslint/no-unused-vars': 'warn', '@typescript-eslint/no-explicit-any': 'off', // 完全禁用 any 检查 @@ -71,7 +81,7 @@ export default defineConfig([ '@typescript-eslint/no-unsafe-argument': 'off', '@typescript-eslint/no-empty-object-type': 'off', // 允许空接口 '@typescript-eslint/no-unused-expressions': 'warn', // 改为警告而非错误 - 'no-unused-expressions': 'off' - } - } + 'no-unused-expressions': 'off', + }, + }, ]) diff --git a/src/App.vue b/src/App.vue index dca5bc4..3a3f434 100644 --- a/src/App.vue +++ b/src/App.vue @@ -15,6 +15,11 @@
请横屏观看,以获得最佳体验
+ + @@ -27,8 +32,10 @@ import { useInterviewStore, useBasicElementsStore, } from '@/stores' -import { onMounted } from 'vue' +import { onMounted, ref } from 'vue' import { syncAllCompletedYibanLessons } from '@/utils/yibanLessonProgress' +import { initializeStorageBackend } from '@/utils/yiban' +import LoadingOverlay from '@/components/Loading/LoadingOverlay.vue' // 使用等比例缩放hook const { scaleStyle } = useScale() @@ -38,6 +45,9 @@ const filmStore = useFilmStore() const interviewStore = useInterviewStore() const basicElementsStore = useBasicElementsStore() +// 易班数据读取期间的全屏 loading +const bootstrapLoading = ref(true) + onMounted(async () => { const params = new URLSearchParams(window.location.search) const courseId = params.get('courseid') @@ -50,12 +60,18 @@ onMounted(async () => { }) } - await Promise.allSettled([ - vlogStore.loadVlogStore(), - filmStore.loadFilmStore(), - interviewStore.loadInterviewStore(), - basicElementsStore.loadBasicElementsStore(), - ]) + try { + await initializeStorageBackend() + + await Promise.allSettled([ + vlogStore.loadVlogStore(), + filmStore.loadFilmStore(), + interviewStore.loadInterviewStore(), + basicElementsStore.loadBasicElementsStore(), + ]) + } finally { + bootstrapLoading.value = false + } await syncAllCompletedYibanLessons() }) diff --git a/src/assets/images/components/medal/vlog徽章-弹.png b/src/assets/images/components/medal/vlog徽章-弹.png new file mode 100644 index 0000000..6b8ca10 Binary files /dev/null and b/src/assets/images/components/medal/vlog徽章-弹.png differ diff --git a/src/assets/images/components/medal/关闭.png b/src/assets/images/components/medal/关闭.png new file mode 100644 index 0000000..d9d7d9d Binary files /dev/null and b/src/assets/images/components/medal/关闭.png differ diff --git a/src/assets/images/components/medal/半透明背景.png b/src/assets/images/components/medal/半透明背景.png new file mode 100644 index 0000000..4437321 Binary files /dev/null and b/src/assets/images/components/medal/半透明背景.png differ diff --git a/src/assets/images/components/medal/恭喜获得vlog模块徽章.png b/src/assets/images/components/medal/恭喜获得vlog模块徽章.png new file mode 100644 index 0000000..b5f5086 Binary files /dev/null and b/src/assets/images/components/medal/恭喜获得vlog模块徽章.png differ diff --git a/src/assets/images/components/medal/恭喜获得新手导航模块徽章.png b/src/assets/images/components/medal/恭喜获得新手导航模块徽章.png new file mode 100644 index 0000000..e0e231a Binary files /dev/null and b/src/assets/images/components/medal/恭喜获得新手导航模块徽章.png differ diff --git a/src/assets/images/components/medal/恭喜获得电影模块徽章.png b/src/assets/images/components/medal/恭喜获得电影模块徽章.png new file mode 100644 index 0000000..834ab81 Binary files /dev/null and b/src/assets/images/components/medal/恭喜获得电影模块徽章.png differ diff --git a/src/assets/images/components/medal/恭喜获得访谈模块徽章.png b/src/assets/images/components/medal/恭喜获得访谈模块徽章.png new file mode 100644 index 0000000..24b1d67 Binary files /dev/null and b/src/assets/images/components/medal/恭喜获得访谈模块徽章.png differ diff --git a/src/assets/images/components/medal/恭喜获得通关证书.png b/src/assets/images/components/medal/恭喜获得通关证书.png new file mode 100644 index 0000000..3f178a8 Binary files /dev/null and b/src/assets/images/components/medal/恭喜获得通关证书.png differ diff --git a/src/assets/images/components/medal/收集后可在【我的进度】中查看.png b/src/assets/images/components/medal/收集后可在【我的进度】中查看.png new file mode 100644 index 0000000..7e35889 Binary files /dev/null and b/src/assets/images/components/medal/收集后可在【我的进度】中查看.png differ diff --git a/src/assets/images/components/medal/新手导航徽章-弹.png b/src/assets/images/components/medal/新手导航徽章-弹.png new file mode 100644 index 0000000..72a833e Binary files /dev/null and b/src/assets/images/components/medal/新手导航徽章-弹.png differ diff --git a/src/assets/images/components/medal/电影徽章-弹.png b/src/assets/images/components/medal/电影徽章-弹.png new file mode 100644 index 0000000..47f806f Binary files /dev/null and b/src/assets/images/components/medal/电影徽章-弹.png differ diff --git a/src/assets/images/components/medal/立即查看.png b/src/assets/images/components/medal/立即查看.png new file mode 100644 index 0000000..91da445 Binary files /dev/null and b/src/assets/images/components/medal/立即查看.png differ diff --git a/src/assets/images/components/medal/访谈徽章-弹.png b/src/assets/images/components/medal/访谈徽章-弹.png new file mode 100644 index 0000000..f034173 Binary files /dev/null and b/src/assets/images/components/medal/访谈徽章-弹.png differ diff --git a/src/assets/images/components/medal/证书详情.png b/src/assets/images/components/medal/证书详情.png new file mode 100644 index 0000000..bd491ce Binary files /dev/null and b/src/assets/images/components/medal/证书详情.png differ diff --git a/src/assets/images/components/medal/通关证书-弹.png b/src/assets/images/components/medal/通关证书-弹.png new file mode 100644 index 0000000..2f856cd Binary files /dev/null and b/src/assets/images/components/medal/通关证书-弹.png differ diff --git a/src/assets/images/cover/Vlogmk_dtgpyzp_batch.jpg b/src/assets/images/cover/Vlogmk_dtgpyzp_batch.jpg index 97041de..75f27d3 100644 Binary files a/src/assets/images/cover/Vlogmk_dtgpyzp_batch.jpg and b/src/assets/images/cover/Vlogmk_dtgpyzp_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_jcjbyy_batch.jpg b/src/assets/images/cover/Vlogmk_jcjbyy_batch.jpg index 4d961af..aab1e30 100644 Binary files a/src/assets/images/cover/Vlogmk_jcjbyy_batch.jpg and b/src/assets/images/cover/Vlogmk_jcjbyy_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_jdjbch_batch.jpg b/src/assets/images/cover/Vlogmk_jdjbch_batch.jpg index 9cb1668..10a42a8 100644 Binary files a/src/assets/images/cover/Vlogmk_jdjbch_batch.jpg and b/src/assets/images/cover/Vlogmk_jdjbch_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_jjjz_batch.jpg b/src/assets/images/cover/Vlogmk_jjjz_batch.jpg index a8f84f8..2b93262 100644 Binary files a/src/assets/images/cover/Vlogmk_jjjz_batch.jpg and b/src/assets/images/cover/Vlogmk_jjjz_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_jjqd_batch.jpg b/src/assets/images/cover/Vlogmk_jjqd_batch.jpg index b7297df..faae1b1 100644 Binary files a/src/assets/images/cover/Vlogmk_jjqd_batch.jpg and b/src/assets/images/cover/Vlogmk_jjqd_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_jtyy_batch.jpg b/src/assets/images/cover/Vlogmk_jtyy_batch.jpg index 1838335..8cd6e17 100644 Binary files a/src/assets/images/cover/Vlogmk_jtyy_batch.jpg and b/src/assets/images/cover/Vlogmk_jtyy_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_kcjl_batch.jpg b/src/assets/images/cover/Vlogmk_kcjl_batch.jpg index c7478be..3a30ec3 100644 Binary files a/src/assets/images/cover/Vlogmk_kcjl_batch.jpg and b/src/assets/images/cover/Vlogmk_kcjl_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_scdrjjpj_batch.jpg b/src/assets/images/cover/Vlogmk_scdrjjpj_batch.jpg index d4131a5..e568332 100644 Binary files a/src/assets/images/cover/Vlogmk_scdrjjpj_batch.jpg and b/src/assets/images/cover/Vlogmk_scdrjjpj_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_syyzc_batch.jpg b/src/assets/images/cover/Vlogmk_syyzc_batch.jpg index 31da037..f07d545 100644 Binary files a/src/assets/images/cover/Vlogmk_syyzc_batch.jpg and b/src/assets/images/cover/Vlogmk_syyzc_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_tjbjyy_batch.jpg b/src/assets/images/cover/Vlogmk_tjbjyy_batch.jpg index b7b3997..87b5b75 100644 Binary files a/src/assets/images/cover/Vlogmk_tjbjyy_batch.jpg and b/src/assets/images/cover/Vlogmk_tjbjyy_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_tsybz_batch.jpg b/src/assets/images/cover/Vlogmk_tsybz_batch.jpg index eada33f..5ace4a1 100644 Binary files a/src/assets/images/cover/Vlogmk_tsybz_batch.jpg and b/src/assets/images/cover/Vlogmk_tsybz_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_yhpp_batch.jpg b/src/assets/images/cover/Vlogmk_yhpp_batch.jpg index ed7c055..ef92f75 100644 Binary files a/src/assets/images/cover/Vlogmk_yhpp_batch.jpg and b/src/assets/images/cover/Vlogmk_yhpp_batch.jpg differ diff --git a/src/assets/images/cover/Vlogmk_ystyycbbdgd_batch.jpg b/src/assets/images/cover/Vlogmk_ystyycbbdgd_batch.jpg index 064cb8c..01a7a30 100644 Binary files a/src/assets/images/cover/Vlogmk_ystyycbbdgd_batch.jpg and b/src/assets/images/cover/Vlogmk_ystyycbbdgd_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_czsjx_batch.jpg b/src/assets/images/cover/dygmk_czsjx_batch.jpg index 55a5bd8..b4e5ba1 100644 Binary files a/src/assets/images/cover/dygmk_czsjx_batch.jpg and b/src/assets/images/cover/dygmk_czsjx_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_fjt_batch.jpg b/src/assets/images/cover/dygmk_fjt_batch.jpg index e6ad965..460724b 100644 Binary files a/src/assets/images/cover/dygmk_fjt_batch.jpg and b/src/assets/images/cover/dygmk_fjt_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_gljj_batch.jpg b/src/assets/images/cover/dygmk_gljj_batch.jpg new file mode 100644 index 0000000..b19bf41 Binary files /dev/null and b/src/assets/images/cover/dygmk_gljj_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_gx_batch.jpg b/src/assets/images/cover/dygmk_gx_batch.jpg index f4c99a3..d7a77a0 100644 Binary files a/src/assets/images/cover/dygmk_gx_batch.jpg and b/src/assets/images/cover/dygmk_gx_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_hgydjt_batch.jpg b/src/assets/images/cover/dygmk_hgydjt_batch.jpg index 2e3c98b..c493203 100644 Binary files a/src/assets/images/cover/dygmk_hgydjt_batch.jpg and b/src/assets/images/cover/dygmk_hgydjt_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_jjcnlks_batch.jpg b/src/assets/images/cover/dygmk_jjcnlks_batch.jpg index bf2b532..f25e00c 100644 Binary files a/src/assets/images/cover/dygmk_jjcnlks_batch.jpg and b/src/assets/images/cover/dygmk_jjcnlks_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_jzxjj_batch.jpg b/src/assets/images/cover/dygmk_jzxjj_batch.jpg new file mode 100644 index 0000000..04a2851 Binary files /dev/null and b/src/assets/images/cover/dygmk_jzxjj_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_kq_batch.jpg b/src/assets/images/cover/dygmk_kq_batch.jpg new file mode 100644 index 0000000..7b0b569 Binary files /dev/null and b/src/assets/images/cover/dygmk_kq_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_lj_batch.jpg b/src/assets/images/cover/dygmk_lj_batch.jpg index 0f3e023..1eb1af1 100644 Binary files a/src/assets/images/cover/dygmk_lj_batch.jpg and b/src/assets/images/cover/dygmk_lj_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_lxjj_batch.jpg b/src/assets/images/cover/dygmk_lxjj_batch.jpg new file mode 100644 index 0000000..4708330 Binary files /dev/null and b/src/assets/images/cover/dygmk_lxjj_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_mmps_batch.jpg b/src/assets/images/cover/dygmk_mmps_batch.jpg index e79ca1d..8661310 100644 Binary files a/src/assets/images/cover/dygmk_mmps_batch.jpg and b/src/assets/images/cover/dygmk_mmps_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_tqs_batch.jpg b/src/assets/images/cover/dygmk_tqs_batch.jpg index 0319bdf..d29c192 100644 Binary files a/src/assets/images/cover/dygmk_tqs_batch.jpg and b/src/assets/images/cover/dygmk_tqs_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_txjt_batch.jpg b/src/assets/images/cover/dygmk_txjt_batch.jpg index 71767c1..75de9a7 100644 Binary files a/src/assets/images/cover/dygmk_txjt_batch.jpg and b/src/assets/images/cover/dygmk_txjt_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_xs_batch.jpg b/src/assets/images/cover/dygmk_xs_batch.jpg index 76ad871..6ba592d 100644 Binary files a/src/assets/images/cover/dygmk_xs_batch.jpg and b/src/assets/images/cover/dygmk_xs_batch.jpg differ diff --git a/src/assets/images/cover/dygmk_zf_batch.jpg b/src/assets/images/cover/dygmk_zf_batch.jpg index a9a92ce..a6ae620 100644 Binary files a/src/assets/images/cover/dygmk_zf_batch.jpg and b/src/assets/images/cover/dygmk_zf_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_bpjtynx_batch.jpg b/src/assets/images/cover/ftmk_bpjtynx_batch.jpg index cbacbfd..a65a906 100644 Binary files a/src/assets/images/cover/ftmk_bpjtynx_batch.jpg and b/src/assets/images/cover/ftmk_bpjtynx_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_jlcutyy_batch.jpg b/src/assets/images/cover/ftmk_jlcutyy_batch.jpg index 7b044d8..f86e183 100644 Binary files a/src/assets/images/cover/ftmk_jlcutyy_batch.jpg and b/src/assets/images/cover/ftmk_jlcutyy_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_jtzjlj_batch.jpg b/src/assets/images/cover/ftmk_jtzjlj_batch.jpg index cb51bfe..91d073a 100644 Binary files a/src/assets/images/cover/ftmk_jtzjlj_batch.jpg and b/src/assets/images/cover/ftmk_jtzjlj_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_jwsz_batch.jpg b/src/assets/images/cover/ftmk_jwsz_batch.jpg index 5758e7a..8418a74 100644 Binary files a/src/assets/images/cover/ftmk_jwsz_batch.jpg and b/src/assets/images/cover/ftmk_jwsz_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_jzjjjq_batch.jpg b/src/assets/images/cover/ftmk_jzjjjq_batch.jpg index a41aa97..c3e29db 100644 Binary files a/src/assets/images/cover/ftmk_jzjjjq_batch.jpg and b/src/assets/images/cover/ftmk_jzjjjq_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_sczmp_batch.jpg b/src/assets/images/cover/ftmk_sczmp_batch.jpg index 1ea52ff..ed01e2a 100644 Binary files a/src/assets/images/cover/ftmk_sczmp_batch.jpg and b/src/assets/images/cover/ftmk_sczmp_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_shjjlc_batch.jpg b/src/assets/images/cover/ftmk_shjjlc_batch.jpg index eb0c01b..f857a4e 100644 Binary files a/src/assets/images/cover/ftmk_shjjlc_batch.jpg and b/src/assets/images/cover/ftmk_shjjlc_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_sytbysl_batch.jpg b/src/assets/images/cover/ftmk_sytbysl_batch.jpg index 6b35d06..c5a4ebb 100644 Binary files a/src/assets/images/cover/ftmk_sytbysl_batch.jpg and b/src/assets/images/cover/ftmk_sytbysl_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_txjtdzy_batch.jpg b/src/assets/images/cover/ftmk_txjtdzy_batch.jpg index c41d0f9..9f01823 100644 Binary files a/src/assets/images/cover/ftmk_txjtdzy_batch.jpg and b/src/assets/images/cover/ftmk_txjtdzy_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_ydjtdzy_batch.jpg b/src/assets/images/cover/ftmk_ydjtdzy_batch.jpg index 125f76c..6c38a60 100644 Binary files a/src/assets/images/cover/ftmk_ydjtdzy_batch.jpg and b/src/assets/images/cover/ftmk_ydjtdzy_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_yx_batch.jpg b/src/assets/images/cover/ftmk_yx_batch.jpg index 284689a..7adefba 100644 Binary files a/src/assets/images/cover/ftmk_yx_batch.jpg and b/src/assets/images/cover/ftmk_yx_batch.jpg differ diff --git a/src/assets/images/cover/ftmk_zxyz_batch.jpg b/src/assets/images/cover/ftmk_zxyz_batch.jpg index aef6a3c..c2a8581 100644 Binary files a/src/assets/images/cover/ftmk_zxyz_batch.jpg and b/src/assets/images/cover/ftmk_zxyz_batch.jpg differ diff --git a/src/assets/images/cover/jiaoben.jpg b/src/assets/images/cover/jiaoben.jpg index c85d6d1..508ee71 100644 Binary files a/src/assets/images/cover/jiaoben.jpg and b/src/assets/images/cover/jiaoben.jpg differ diff --git a/src/assets/images/cover/start.jpg b/src/assets/images/cover/start.jpg new file mode 100644 index 0000000..c0f1998 Binary files /dev/null and b/src/assets/images/cover/start.jpg differ diff --git a/src/assets/images/cover/xinshou_guangdejichurenzhi.jpg b/src/assets/images/cover/xinshou_guangdejichurenzhi.jpg index 26e1bcb..70f8656 100644 Binary files a/src/assets/images/cover/xinshou_guangdejichurenzhi.jpg and b/src/assets/images/cover/xinshou_guangdejichurenzhi.jpg differ diff --git a/src/assets/images/cover/xinshou_guangdesidashuxing.jpg b/src/assets/images/cover/xinshou_guangdesidashuxing.jpg index 168af3a..c74d0ec 100644 Binary files a/src/assets/images/cover/xinshou_guangdesidashuxing.jpg and b/src/assets/images/cover/xinshou_guangdesidashuxing.jpg differ diff --git a/src/assets/images/cover/xinshou_shenqideweijusheying.jpg b/src/assets/images/cover/xinshou_shenqideweijusheying.jpg index 8f85f80..3049306 100644 Binary files a/src/assets/images/cover/xinshou_shenqideweijusheying.jpg and b/src/assets/images/cover/xinshou_shenqideweijusheying.jpg differ diff --git a/src/assets/images/cover/xinshou_shoujishexiangtoujieshao.jpg b/src/assets/images/cover/xinshou_shoujishexiangtoujieshao.jpg index e22ff8d..71c8644 100644 Binary files a/src/assets/images/cover/xinshou_shoujishexiangtoujieshao.jpg and b/src/assets/images/cover/xinshou_shoujishexiangtoujieshao.jpg differ diff --git a/src/assets/images/cover/xinshou_yunjingdejibenfangshi.jpg b/src/assets/images/cover/xinshou_yunjingdejibenfangshi.jpg index d3dbd5c..6815704 100644 Binary files a/src/assets/images/cover/xinshou_yunjingdejibenfangshi.jpg and b/src/assets/images/cover/xinshou_yunjingdejibenfangshi.jpg differ diff --git a/src/assets/images/cover/xinshou_zhengquedeshoujipaishe.jpg b/src/assets/images/cover/xinshou_zhengquedeshoujipaishe.jpg index b686d38..abee406 100644 Binary files a/src/assets/images/cover/xinshou_zhengquedeshoujipaishe.jpg and b/src/assets/images/cover/xinshou_zhengquedeshoujipaishe.jpg differ diff --git a/src/assets/images/cover/xsdh_csjyzybjmhgn_batch.jpg b/src/assets/images/cover/xsdh_csjyzybjmhgn_batch.jpg index c41c40a..e718beb 100644 Binary files a/src/assets/images/cover/xsdh_csjyzybjmhgn_batch.jpg and b/src/assets/images/cover/xsdh_csjyzybjmhgn_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_djmldyjsy_batch.jpg b/src/assets/images/cover/xsdh_djmldyjsy_batch.jpg index d62f92a..d0ad97f 100644 Binary files a/src/assets/images/cover/xsdh_djmldyjsy_batch.jpg and b/src/assets/images/cover/xsdh_djmldyjsy_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_gjzgnyfxj_batch.jpg b/src/assets/images/cover/xsdh_gjzgnyfxj_batch.jpg index 1ac9447..af3fbe0 100644 Binary files a/src/assets/images/cover/xsdh_gjzgnyfxj_batch.jpg and b/src/assets/images/cover/xsdh_gjzgnyfxj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_hhmsgnyfxj_batch.jpg b/src/assets/images/cover/xsdh_hhmsgnyfxj_batch.jpg index 11caab9..4c8af3f 100644 Binary files a/src/assets/images/cover/xsdh_hhmsgnyfxj_batch.jpg and b/src/assets/images/cover/xsdh_hhmsgnyfxj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_jbgnjs_batch.jpg b/src/assets/images/cover/xsdh_jbgnjs_batch.jpg index 3fbe492..dfefe15 100644 Binary files a/src/assets/images/cover/xsdh_jbgnjs_batch.jpg and b/src/assets/images/cover/xsdh_jbgnjs_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_jzgtf_batch.jpg b/src/assets/images/cover/xsdh_jzgtf_batch.jpg index 8dcd425..4125abd 100644 Binary files a/src/assets/images/cover/xsdh_jzgtf_batch.jpg and b/src/assets/images/cover/xsdh_jzgtf_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_mbgnyfxj_batch.jpg b/src/assets/images/cover/xsdh_mbgnyfxj_batch.jpg index 18cfe6a..bf26137 100644 Binary files a/src/assets/images/cover/xsdh_mbgnyfxj_batch.jpg and b/src/assets/images/cover/xsdh_mbgnyfxj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_psdhjsj_batch.jpg b/src/assets/images/cover/xsdh_psdhjsj_batch.jpg index 16d048e..3b86fb5 100644 Binary files a/src/assets/images/cover/xsdh_psdhjsj_batch.jpg and b/src/assets/images/cover/xsdh_psdhjsj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_qxbsgnyfxj_batch.jpg b/src/assets/images/cover/xsdh_qxbsgnyfxj_batch.jpg index 77410c3..7be64a7 100644 Binary files a/src/assets/images/cover/xsdh_qxbsgnyfxj_batch.jpg and b/src/assets/images/cover/xsdh_qxbsgnyfxj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_rhghmts_batch.jpg b/src/assets/images/cover/xsdh_rhghmts_batch.jpg index 7f2ffb7..15dfc9d 100644 Binary files a/src/assets/images/cover/xsdh_rhghmts_batch.jpg and b/src/assets/images/cover/xsdh_rhghmts_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_rhgspksszm_batch.jpg b/src/assets/images/cover/xsdh_rhgspksszm_batch.jpg index 0c84250..b5f6b51 100644 Binary files a/src/assets/images/cover/xsdh_rhgspksszm_batch.jpg and b/src/assets/images/cover/xsdh_rhgspksszm_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_rhxzgt_batch.jpg b/src/assets/images/cover/xsdh_rhxzgt_batch.jpg index 5d03495..1e0b47b 100644 Binary files a/src/assets/images/cover/xsdh_rhxzgt_batch.jpg and b/src/assets/images/cover/xsdh_rhxzgt_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_sjmdz_batch.jpg b/src/assets/images/cover/xsdh_sjmdz_batch.jpg index 4d2acea..9d73a88 100644 Binary files a/src/assets/images/cover/xsdh_sjmdz_batch.jpg and b/src/assets/images/cover/xsdh_sjmdz_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_sjxdyfxj_batch.jpg b/src/assets/images/cover/xsdh_sjxdyfxj_batch.jpg index 6cbb291..3c56b01 100644 Binary files a/src/assets/images/cover/xsdh_sjxdyfxj_batch.jpg and b/src/assets/images/cover/xsdh_sjxdyfxj_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_ypdgnyyhcl_batch.jpg b/src/assets/images/cover/xsdh_ypdgnyyhcl_batch.jpg index ba1a3b1..a15f240 100644 Binary files a/src/assets/images/cover/xsdh_ypdgnyyhcl_batch.jpg and b/src/assets/images/cover/xsdh_ypdgnyyhcl_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_yssy_batch.jpg b/src/assets/images/cover/xsdh_yssy_batch.jpg index a8802fd..5857782 100644 Binary files a/src/assets/images/cover/xsdh_yssy_batch.jpg and b/src/assets/images/cover/xsdh_yssy_batch.jpg differ diff --git a/src/assets/images/cover/xsdh_zctxtzgnxj_batch.jpg b/src/assets/images/cover/xsdh_zctxtzgnxj_batch.jpg index 25fdea1..ad06542 100644 Binary files a/src/assets/images/cover/xsdh_zctxtzgnxj_batch.jpg and b/src/assets/images/cover/xsdh_zctxtzgnxj_batch.jpg differ diff --git a/src/assets/images/film/任务取景框背景.png b/src/assets/images/film/任务取景框背景.png index 26bd3d4..b92cdb7 100644 Binary files a/src/assets/images/film/任务取景框背景.png and b/src/assets/images/film/任务取景框背景.png differ diff --git a/src/assets/images/film/分镜制作-拍摄分镜.png b/src/assets/images/film/分镜制作-拍摄分镜.png index f9afef7..e7126e8 100644 Binary files a/src/assets/images/film/分镜制作-拍摄分镜.png and b/src/assets/images/film/分镜制作-拍摄分镜.png differ diff --git a/src/assets/images/film/脚本编写-拍摄脚本.png b/src/assets/images/film/脚本编写-拍摄脚本.png index bd46fbe..85e0676 100644 Binary files a/src/assets/images/film/脚本编写-拍摄脚本.png and b/src/assets/images/film/脚本编写-拍摄脚本.png differ diff --git a/src/assets/images/home/action/学习进度入口.png b/src/assets/images/home/action/学习进度入口.png index b59e125..1f6e169 100644 Binary files a/src/assets/images/home/action/学习进度入口.png and b/src/assets/images/home/action/学习进度入口.png differ diff --git a/src/assets/images/home/action/首页锁.png b/src/assets/images/home/action/首页锁.png new file mode 100644 index 0000000..c5214ad Binary files /dev/null and b/src/assets/images/home/action/首页锁.png differ diff --git a/src/assets/images/home/stuy/vlog-亮.png b/src/assets/images/home/stuy/vlog-亮.png new file mode 100644 index 0000000..09f4125 Binary files /dev/null and b/src/assets/images/home/stuy/vlog-亮.png differ diff --git a/src/assets/images/home/stuy/vlog-灰.png b/src/assets/images/home/stuy/vlog-灰.png new file mode 100644 index 0000000..540f946 Binary files /dev/null and b/src/assets/images/home/stuy/vlog-灰.png differ diff --git a/src/assets/images/home/stuy/学习进度底图.png b/src/assets/images/home/stuy/学习进度底图.png index 9b9fcbf..74ff2fc 100644 Binary files a/src/assets/images/home/stuy/学习进度底图.png and b/src/assets/images/home/stuy/学习进度底图.png differ diff --git a/src/assets/images/home/stuy/学习进度底图_.png b/src/assets/images/home/stuy/学习进度底图_.png deleted file mode 100644 index b518f4e..0000000 Binary files a/src/assets/images/home/stuy/学习进度底图_.png and /dev/null differ diff --git a/src/assets/images/home/stuy/新手导航-亮.png b/src/assets/images/home/stuy/新手导航-亮.png new file mode 100644 index 0000000..578c270 Binary files /dev/null and b/src/assets/images/home/stuy/新手导航-亮.png differ diff --git a/src/assets/images/home/stuy/新手导航-灰.png b/src/assets/images/home/stuy/新手导航-灰.png new file mode 100644 index 0000000..12892ab Binary files /dev/null and b/src/assets/images/home/stuy/新手导航-灰.png differ diff --git a/src/assets/images/home/stuy/电影-亮.png b/src/assets/images/home/stuy/电影-亮.png new file mode 100644 index 0000000..4e9829e Binary files /dev/null and b/src/assets/images/home/stuy/电影-亮.png differ diff --git a/src/assets/images/home/stuy/电影-灰.png b/src/assets/images/home/stuy/电影-灰.png new file mode 100644 index 0000000..c0b6a01 Binary files /dev/null and b/src/assets/images/home/stuy/电影-灰.png differ diff --git a/src/assets/images/home/stuy/访谈-亮.png b/src/assets/images/home/stuy/访谈-亮.png new file mode 100644 index 0000000..ce8a500 Binary files /dev/null and b/src/assets/images/home/stuy/访谈-亮.png differ diff --git a/src/assets/images/home/stuy/访谈-灰.png b/src/assets/images/home/stuy/访谈-灰.png new file mode 100644 index 0000000..0fda47c Binary files /dev/null and b/src/assets/images/home/stuy/访谈-灰.png differ diff --git a/src/assets/images/home/stuy/通关证书-已获取.png b/src/assets/images/home/stuy/通关证书-已获取.png new file mode 100644 index 0000000..5684487 Binary files /dev/null and b/src/assets/images/home/stuy/通关证书-已获取.png differ diff --git a/src/assets/images/home/stuy/通关证书-暂未获取.png b/src/assets/images/home/stuy/通关证书-暂未获取.png new file mode 100644 index 0000000..7e5fe61 Binary files /dev/null and b/src/assets/images/home/stuy/通关证书-暂未获取.png differ diff --git a/src/assets/images/interview/img/育人故事配音.png b/src/assets/images/interview/img/育人故事配音.png index 427e421..0a98ca6 100644 Binary files a/src/assets/images/interview/img/育人故事配音.png and b/src/assets/images/interview/img/育人故事配音.png differ diff --git a/src/assets/images/interview/work/任务取景框背景.png b/src/assets/images/interview/work/任务取景框背景.png index 40fd018..3153f7c 100644 Binary files a/src/assets/images/interview/work/任务取景框背景.png and b/src/assets/images/interview/work/任务取景框背景.png differ diff --git a/src/assets/images/skill/icon/ai技术应用.png b/src/assets/images/skill/icon/ai技术应用.png index 47ca6ac..e4ed4db 100644 Binary files a/src/assets/images/skill/icon/ai技术应用.png and b/src/assets/images/skill/icon/ai技术应用.png differ diff --git a/src/assets/images/skill/icon/光线.png b/src/assets/images/skill/icon/光线.png index f9c4d69..7e09407 100644 Binary files a/src/assets/images/skill/icon/光线.png and b/src/assets/images/skill/icon/光线.png differ diff --git a/src/assets/images/skill/icon/光线运用.png b/src/assets/images/skill/icon/光线运用.png index f5d6026..b973167 100644 Binary files a/src/assets/images/skill/icon/光线运用.png and b/src/assets/images/skill/icon/光线运用.png differ diff --git a/src/assets/images/skill/icon/剪辑技巧.png b/src/assets/images/skill/icon/剪辑技巧.png index c293608..2d22035 100644 Binary files a/src/assets/images/skill/icon/剪辑技巧.png and b/src/assets/images/skill/icon/剪辑技巧.png differ diff --git a/src/assets/images/skill/icon/包装.png b/src/assets/images/skill/icon/包装.png index bc495e2..8f4041b 100644 Binary files a/src/assets/images/skill/icon/包装.png and b/src/assets/images/skill/icon/包装.png differ diff --git a/src/assets/images/skill/icon/思路提点.png b/src/assets/images/skill/icon/思路提点.png index 30bb71d..c2eedd6 100644 Binary files a/src/assets/images/skill/icon/思路提点.png and b/src/assets/images/skill/icon/思路提点.png differ diff --git a/src/assets/images/skill/icon/拍摄技巧.png b/src/assets/images/skill/icon/拍摄技巧.png index e4b12d4..a95d665 100644 Binary files a/src/assets/images/skill/icon/拍摄技巧.png and b/src/assets/images/skill/icon/拍摄技巧.png differ diff --git a/src/assets/images/skill/icon/景别.png b/src/assets/images/skill/icon/景别.png index 23806f4..bff6573 100644 Binary files a/src/assets/images/skill/icon/景别.png and b/src/assets/images/skill/icon/景别.png differ diff --git a/src/assets/images/skill/icon/构图.png b/src/assets/images/skill/icon/构图.png index d753f9c..ee1d8d2 100644 Binary files a/src/assets/images/skill/icon/构图.png and b/src/assets/images/skill/icon/构图.png differ diff --git a/src/assets/images/skill/icon/案例合集.png b/src/assets/images/skill/icon/案例合集.png index 5504c3c..31f9c32 100644 Binary files a/src/assets/images/skill/icon/案例合集.png and b/src/assets/images/skill/icon/案例合集.png differ diff --git a/src/assets/images/skill/icon/版权意识.png b/src/assets/images/skill/icon/版权意识.png index 3182f07..f89c335 100644 Binary files a/src/assets/images/skill/icon/版权意识.png and b/src/assets/images/skill/icon/版权意识.png differ diff --git a/src/assets/images/skill/icon/画面构图.png b/src/assets/images/skill/icon/画面构图.png index 0290ddf..49820ce 100644 Binary files a/src/assets/images/skill/icon/画面构图.png and b/src/assets/images/skill/icon/画面构图.png differ diff --git a/src/assets/images/skill/icon/素材管理.png b/src/assets/images/skill/icon/素材管理.png index 22443e9..36646ee 100644 Binary files a/src/assets/images/skill/icon/素材管理.png and b/src/assets/images/skill/icon/素材管理.png differ diff --git a/src/assets/images/skill/icon/脚本与分镜制作.png b/src/assets/images/skill/icon/脚本与分镜制作.png index 08dee9b..957f755 100644 Binary files a/src/assets/images/skill/icon/脚本与分镜制作.png and b/src/assets/images/skill/icon/脚本与分镜制作.png differ diff --git a/src/assets/images/skill/icon/蒙太奇剪辑.png b/src/assets/images/skill/icon/蒙太奇剪辑.png index 8a26be4..3f679e2 100644 Binary files a/src/assets/images/skill/icon/蒙太奇剪辑.png and b/src/assets/images/skill/icon/蒙太奇剪辑.png differ diff --git a/src/assets/images/skill/icon/设备准备.png b/src/assets/images/skill/icon/设备准备.png index 088319e..7391c6e 100644 Binary files a/src/assets/images/skill/icon/设备准备.png and b/src/assets/images/skill/icon/设备准备.png differ diff --git a/src/assets/images/skill/icon/调色.png b/src/assets/images/skill/icon/调色.png index 863662e..bc306fa 100644 Binary files a/src/assets/images/skill/icon/调色.png and b/src/assets/images/skill/icon/调色.png differ diff --git a/src/assets/images/skill/icon/运镜.png b/src/assets/images/skill/icon/运镜.png index 8fe6cc9..8cb788d 100644 Binary files a/src/assets/images/skill/icon/运镜.png and b/src/assets/images/skill/icon/运镜.png differ diff --git a/src/assets/images/skill/icon/运镜技巧.png b/src/assets/images/skill/icon/运镜技巧.png index bc21f01..4c877c7 100644 Binary files a/src/assets/images/skill/icon/运镜技巧.png and b/src/assets/images/skill/icon/运镜技巧.png differ diff --git a/src/assets/images/skill/icon/选题与构思.png b/src/assets/images/skill/icon/选题与构思.png index 475ab5e..ce7f695 100644 Binary files a/src/assets/images/skill/icon/选题与构思.png and b/src/assets/images/skill/icon/选题与构思.png differ diff --git a/src/assets/images/skill/icon/音效.png b/src/assets/images/skill/icon/音效.png index da76458..c19528a 100644 Binary files a/src/assets/images/skill/icon/音效.png and b/src/assets/images/skill/icon/音效.png differ diff --git a/src/assets/images/work/bg.png b/src/assets/images/work/bg.png index 9d6894f..3ca013c 100644 Binary files a/src/assets/images/work/bg.png and b/src/assets/images/work/bg.png differ diff --git a/src/assets/images/work/未选中_带三角.png b/src/assets/images/work/未选中_带三角.png index be10b2f..9c78c51 100644 Binary files a/src/assets/images/work/未选中_带三角.png and b/src/assets/images/work/未选中_带三角.png differ diff --git a/src/components/AnchoredProgressBar/AnchoredProgressBar.vue b/src/components/AnchoredProgressBar/AnchoredProgressBar.vue deleted file mode 100644 index b3476cf..0000000 --- a/src/components/AnchoredProgressBar/AnchoredProgressBar.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - diff --git a/src/components/DownloadButton.vue b/src/components/DownloadButton.vue new file mode 100644 index 0000000..49299f5 --- /dev/null +++ b/src/components/DownloadButton.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/components/ProgressBar/ProgressBar.vue b/src/components/ProgressBar/ProgressBar.vue index a07cc62..45bc647 100644 --- a/src/components/ProgressBar/ProgressBar.vue +++ b/src/components/ProgressBar/ProgressBar.vue @@ -183,7 +183,7 @@ const emit = defineEmits() // 步骤:1=前期准备, 2=中期拍摄, 3=后期剪辑, 4=实战操作台 // 当 completedStep >= 3(即完成第3步)时,解锁右侧完成按钮 const canComplete = computed(() => props.completedStep >= 3) -const isPracticeCompleted = computed(() => props.completedStep >= 4) +const isPracticeCompleted = computed(() => props.completedStep >= 5) const completeButtonImage = computed(() => { if (!canComplete.value) return IMAGE_PATHS.PROGRESS_BAR.COMPLETE_BUTTON_DISABLED diff --git a/src/components/QuestionQuiz/QuestionQuiz.vue b/src/components/QuestionQuiz/QuestionQuiz.vue index 7365b96..5b89b5a 100644 --- a/src/components/QuestionQuiz/QuestionQuiz.vue +++ b/src/components/QuestionQuiz/QuestionQuiz.vue @@ -36,9 +36,30 @@ const emit = defineEmits<{ const currentIndex = ref(0) const selectedOptionId = ref(null) // 单选题选中的选项 const selectedOptionIds = ref([]) // 多选题选中的选项数组 +const wrongAnswerCount = ref(0) // 当前题答错次数 +const showWrongFeedback = ref(false) // 是否显示答错提示 const showErrorExplanation = ref(false) // 是否显示错误解析 const showCorrectFeedback = ref(false) +const VIDEO_EXTENSIONS = [ + '.mp4', + '.mov', + '.avi', + '.webm', + '.mkv', + '.flv', + '.wmv', +] +const IMAGE_EXTENSIONS = [ + '.png', + '.jpg', + '.jpeg', + '.gif', + '.webp', + '.svg', + '.bmp', +] + const total = computed(() => props.questions.length) const currentQuestion = computed(() => props.questions[currentIndex.value]) const hasMedia = computed(() => !!currentQuestion.value?.mediaSrc) @@ -66,37 +87,96 @@ const hasMoreThanFourOptions = computed(() => { watch(currentIndex, () => { selectedOptionId.value = null selectedOptionIds.value = [] + wrongAnswerCount.value = 0 + showWrongFeedback.value = false showErrorExplanation.value = false showCorrectFeedback.value = false }) // 通过文件后缀判断媒体类型 +const getFileExtension = (src: string): string => { + const cleanSrc = src.split('?')[0].split('#')[0].toLowerCase() + const dotIndex = cleanSrc.lastIndexOf('.') + return dotIndex > -1 ? cleanSrc.slice(dotIndex) : '' +} + const isVideo = (src: string): boolean => { - const videoExtensions = [ - '.mp4', - '.mov', - '.avi', - '.webm', - '.mkv', - '.flv', - '.wmv', - ] - const lowerSrc = src.toLowerCase() - return videoExtensions.some((ext) => lowerSrc.endsWith(ext)) + return VIDEO_EXTENSIONS.includes(getFileExtension(src)) } const isImage = (src: string): boolean => { - const imageExtensions = [ - '.png', - '.jpg', - '.jpeg', - '.gif', - '.webp', - '.svg', - '.bmp', - ] - const lowerSrc = src.toLowerCase() - return imageExtensions.some((ext) => lowerSrc.endsWith(ext)) + return IMAGE_EXTENSIONS.includes(getFileExtension(src)) +} + +const isOptionSelected = (optionId: string) => { + return isMultiple.value + ? selectedOptionIds.value.includes(optionId) + : selectedOptionId.value === optionId +} + +const isCorrectOption = (optionId: string) => { + const q = currentQuestion.value + if (!q) return false + + return isMultiple.value + ? (q.correctOptionIds?.includes(optionId) ?? false) + : optionId === q.correctOptionId +} + +const getOptionClass = (optionId: string) => { + const selected = isOptionSelected(optionId) + const correct = isCorrectOption(optionId) + + if (showErrorExplanation.value) { + if (selected && correct) { + return 'border-emerald-400 bg-emerald-500/30 shadow-lg shadow-emerald-500/30' + } + + if (correct) { + return 'border-emerald-400 bg-emerald-500/20 shadow-lg shadow-emerald-500/20' + } + + if (selected && !correct) { + return 'border-red-400 bg-red-500/20 shadow-lg shadow-red-500/20' + } + + return 'border-white/15 bg-white/5 hover:bg-white/10 hover:border-white/25' + } + + if (showWrongFeedback.value && selected) { + return 'border-red-400 bg-red-500/20 shadow-lg shadow-red-500/20' + } + + if (selected) { + return 'border-emerald-400 bg-emerald-500/20 shadow-lg shadow-emerald-500/20' + } + + return 'border-white/15 bg-white/5 hover:bg-white/10 hover:border-white/25' +} + +const hasSelectedAnswer = () => { + return isMultiple.value + ? selectedOptionIds.value.length > 0 + : !!selectedOptionId.value +} + +const isCurrentAnswerCorrect = () => { + const q = currentQuestion.value + if (!q) return false + + if (isMultiple.value) { + const correctIds = q.correctOptionIds || [] + const selectedIds = selectedOptionIds.value + + if (correctIds.length === 0) return false + if (selectedIds.length !== correctIds.length) return false + + const correctSet = new Set(correctIds) + return selectedIds.every((id) => correctSet.has(id)) + } + + const isGuideQuestion = q.correctOptionId === '' // 引导题判断 + return isGuideQuestion || selectedOptionId.value === q.correctOptionId } const handleOptionClick = (optionId: string) => { @@ -114,73 +194,41 @@ const handleOptionClick = (optionId: string) => { // 单选题:直接选中 selectedOptionId.value = optionId } - // 选择新选项时隐藏错误解析 + // 选择新选项时隐藏错误提示和解析 + showWrongFeedback.value = false showErrorExplanation.value = false showCorrectFeedback.value = false } -// 交互规则:选对进入下一步,选错显示解析;最后一题选对触发 complete 事件 -// 如果 correctOptionId 为空字符串,表示引导题,任意选择都可进入下一题 -const handleSubmit = async () => { - const q = currentQuestion.value - - if (showCorrectFeedback.value) return - - if (isMultiple.value) { - // 多选题:必须选择至少一个选项 - if (selectedOptionIds.value.length === 0) return - - // 多选题:必须选择所有正确答案,且不能选择错误答案 - const correctIds = q.correctOptionIds || [] - const selectedSet = new Set(selectedOptionIds.value) - const correctSet = new Set(correctIds) - - // 检查是否选择了所有正确答案 - const hasAllCorrect = correctIds.every((id) => selectedSet.has(id)) - // 检查是否只选择了正确答案(没有选择错误答案) - const onlyCorrect = selectedOptionIds.value.every((id) => - correctSet.has(id), - ) - - const isCorrect = - hasAllCorrect && - onlyCorrect && - selectedOptionIds.value.length === correctIds.length - - if (!isCorrect) { - // 答错时显示解析 - showErrorExplanation.value = true - return - } - } else { - // 单选题 - if (!selectedOptionId.value) return - - const isGuideQuestion = q.correctOptionId === '' // 引导题判断 - const isCorrect = - isGuideQuestion || selectedOptionId.value === q.correctOptionId - - if (!isCorrect) { - // 答错时显示解析 - showErrorExplanation.value = true - return - } - } - - // 答对时重置错误解析状态 +const goNextQuestion = async () => { + showWrongFeedback.value = false showErrorExplanation.value = false showCorrectFeedback.value = true await new Promise((resolve) => setTimeout(resolve, 800)) if (currentIndex.value < total.value - 1) { currentIndex.value += 1 - selectedOptionId.value = null - selectedOptionIds.value = [] } else { showCorrectFeedback.value = false emit('complete') } } + +// 交互规则:选对进入下一步,选错显示解析;最后一题选对触发 complete 事件 +// 如果 correctOptionId 为空字符串,表示引导题,任意选择都可进入下一题 +const handleSubmit = async () => { + if (showCorrectFeedback.value) return + if (!hasSelectedAnswer()) return + + if (!isCurrentAnswerCorrect()) { + wrongAnswerCount.value += 1 + showWrongFeedback.value = true + showErrorExplanation.value = wrongAnswerCount.value >= 3 + return + } + + await goNextQuestion() +} diff --git a/src/views/film/midterm-shooting/shooting/filmingLocation-a/useViewfinderA.ts b/src/views/film/midterm-shooting/shooting/filmingLocation-a/useViewfinderA.ts index b3d184e..e97533d 100644 --- a/src/views/film/midterm-shooting/shooting/filmingLocation-a/useViewfinderA.ts +++ b/src/views/film/midterm-shooting/shooting/filmingLocation-a/useViewfinderA.ts @@ -12,7 +12,7 @@ export function useViewfinderA() { // 缩放级别 (保留用于点击按钮) const zoomLevels = [3, 2, 1] - const currentZoom = ref(1) + const currentZoom = ref(2) const isCapturing = ref(false) // 拍照闪光效果 // 拖拽相关状态 @@ -44,8 +44,14 @@ export function useViewfinderA() { const maxOffsetY = (scaledHeight - containerHeight) / 2 // 限制偏移量 - currentOffsetX.value = Math.max(-maxOffsetX, Math.min(maxOffsetX, currentOffsetX.value)) - currentOffsetY.value = Math.max(-maxOffsetY, Math.min(maxOffsetY, currentOffsetY.value)) + currentOffsetX.value = Math.max( + -maxOffsetX, + Math.min(maxOffsetX, currentOffsetX.value), + ) + currentOffsetY.value = Math.max( + -maxOffsetY, + Math.min(maxOffsetY, currentOffsetY.value), + ) } // 设置缩放级别 @@ -144,6 +150,6 @@ export function useViewfinderA() { onDrag, endDrag, handleWheel, - getTransform + getTransform, } } diff --git a/src/views/film/practice/index.vue b/src/views/film/practice/index.vue index f6a3b4b..4e9dc45 100644 --- a/src/views/film/practice/index.vue +++ b/src/views/film/practice/index.vue @@ -111,6 +111,7 @@ interface WorkItem { title: string stars: number path: string + watchKey: string description: string } @@ -121,6 +122,7 @@ const worksList = ref([ title: '学生案例', stars: 4, path: '/video/film/practice/film_anli1.mp4', + watchKey: 'film-practice-case-1', description: '27084 施颖雯 杨可馨 胡悦莹 陆佳慧 雷鑫丽', }, ]) @@ -375,7 +377,7 @@ onUnmounted(() => { diff --git a/src/views/film/practice/video/index.vue b/src/views/film/practice/video/index.vue index 042d859..115d610 100644 --- a/src/views/film/practice/video/index.vue +++ b/src/views/film/practice/video/index.vue @@ -1,5 +1,5 @@ @@ -510,35 +358,18 @@ onActivated(() => { :steps="homeGuideSteps" position-offset-y="82%" @close="handleHomeGuideComplete" - @step-change="handleGuideStepChange" - /> - - @@ -555,21 +386,33 @@ onActivated(() => { > -
- +
+
+ + {{ totalStudyPercent }}% + +
-
- {{ totalStudyPercent }}% -
+ +
- -
-
-
- -
- - - -
-
- -
-

- 新手导航 -

-

- 点击节点即可开始学习 -

-
- - -
- - - - - - - - - - - - - -
-
- -
- {{ node.num }} - -
- - -
- -
- {{ node.label }} -
-
- - - -
-
-
- -
-
- - - -
-
-
-
-
-
-
-
-
-
+
- + diff --git a/src/views/home/components/ModuleMedalPopup/ModuleMedalPopup.vue b/src/views/home/components/ModuleMedalPopup/ModuleMedalPopup.vue new file mode 100644 index 0000000..37b5250 --- /dev/null +++ b/src/views/home/components/ModuleMedalPopup/ModuleMedalPopup.vue @@ -0,0 +1,232 @@ + + + + + diff --git a/src/views/home/components/ModuleMedalPopup/index.ts b/src/views/home/components/ModuleMedalPopup/index.ts new file mode 100644 index 0000000..b65826b --- /dev/null +++ b/src/views/home/components/ModuleMedalPopup/index.ts @@ -0,0 +1,3 @@ +export { default as ModuleMedalPopup } from './ModuleMedalPopup.vue' +export * from './useModuleMedalPopup' +export * from './moduleMedalConfig' diff --git a/src/views/home/components/ModuleMedalPopup/moduleMedalConfig.ts b/src/views/home/components/ModuleMedalPopup/moduleMedalConfig.ts new file mode 100644 index 0000000..fad2c06 --- /dev/null +++ b/src/views/home/components/ModuleMedalPopup/moduleMedalConfig.ts @@ -0,0 +1,27 @@ +export type MedalModuleKey = 'basic' | 'vlog' | 'interview' | 'film' + +export const moduleMedalConfig = { + basic: { + label: '新手导航', + titleImage: 'components/medal/恭喜获得新手导航模块徽章', + medalImage: 'components/medal/新手导航徽章-弹', + }, + vlog: { + label: 'Vlog', + titleImage: 'components/medal/恭喜获得vlog模块徽章', + medalImage: 'components/medal/vlog徽章-弹', + }, + interview: { + label: '访谈', + titleImage: 'components/medal/恭喜获得访谈模块徽章', + medalImage: 'components/medal/访谈徽章-弹', + }, + film: { + label: '电影', + titleImage: 'components/medal/恭喜获得电影模块徽章', + medalImage: 'components/medal/电影徽章-弹', + }, +} satisfies Record< + MedalModuleKey, + { label: string; titleImage: string; medalImage: string } +> diff --git a/src/views/home/components/ModuleMedalPopup/useModuleMedalPopup.ts b/src/views/home/components/ModuleMedalPopup/useModuleMedalPopup.ts new file mode 100644 index 0000000..7ab7c22 --- /dev/null +++ b/src/views/home/components/ModuleMedalPopup/useModuleMedalPopup.ts @@ -0,0 +1,49 @@ +import { computed, ref } from 'vue' +import { + useBasicElementsStore, + useFilmStore, + useInterviewStore, + useVlogStore, +} from '@/stores' +import type { MedalModuleKey } from './moduleMedalConfig' + +// 复用各模块 store 的 guideShown 记录徽章是否已展示: +// 它已随易班 userDefine 持久化,并在各 store reset 时清空。 +const MEDAL_SHOWN_KEY = 'module-medal-popup' + +// 当前展示的徽章 key(运行时 UI 状态,跨页面共享,无需持久化) +const activeMedalKey = ref(null) + +export const useModuleMedalPopup = () => { + const storeMap = { + basic: useBasicElementsStore(), + vlog: useVlogStore(), + interview: useInterviewStore(), + film: useFilmStore(), + } + + const visible = computed(() => activeMedalKey.value !== null) + + const isMedalShown = (key: MedalModuleKey) => + storeMap[key].guideShown[MEDAL_SHOWN_KEY] === true + + const showMedalIfNeeded = (key: MedalModuleKey) => { + if (isMedalShown(key)) return + activeMedalKey.value = key + } + + const closeMedal = () => { + const key = activeMedalKey.value + if (key) { + storeMap[key].markGuideShown(MEDAL_SHOWN_KEY) + } + activeMedalKey.value = null + } + + return { + activeMedalKey, + visible, + showMedalIfNeeded, + closeMedal, + } +} diff --git a/src/views/home/components/NewbieNavigation/NewbieNavigation.vue b/src/views/home/components/NewbieNavigation/NewbieNavigation.vue new file mode 100644 index 0000000..02c2d52 --- /dev/null +++ b/src/views/home/components/NewbieNavigation/NewbieNavigation.vue @@ -0,0 +1,379 @@ + + + + + diff --git a/src/views/home/components/NewbieNavigation/index.ts b/src/views/home/components/NewbieNavigation/index.ts new file mode 100644 index 0000000..4e671d6 --- /dev/null +++ b/src/views/home/components/NewbieNavigation/index.ts @@ -0,0 +1,2 @@ +export { default as NewbieNavigation } from './NewbieNavigation.vue' +export * from './navigationNodes' diff --git a/src/views/home/components/NewbieNavigation/navigationNodes.ts b/src/views/home/components/NewbieNavigation/navigationNodes.ts new file mode 100644 index 0000000..1c6899d --- /dev/null +++ b/src/views/home/components/NewbieNavigation/navigationNodes.ts @@ -0,0 +1,92 @@ +import type { RouteRecordName } from 'vue-router' +import { + basicElementsFoundationVideoKeys, + basicElementsShootingVideoKeys, + basicElementsEditingVideoKeys, +} from '@/config/moduleStepMap' + +export type GuideChildNode = { + id: number + label: string + icon: string + routeName: RouteRecordName + videoKeys: readonly string[] +} + +export type GuideNode = { + id: number + num: string + label: string + x: number + y: number + hasChildren: boolean + routeName?: RouteRecordName + children?: GuideChildNode[] + videoKeys: readonly string[] +} + +const compositionVideoKeys = basicElementsFoundationVideoKeys.filter((key) => + key.startsWith('basic-composition:'), +) +const lightVideoKeys = basicElementsFoundationVideoKeys.filter((key) => + key.startsWith('basic-light:'), +) +const cameraMovementVideoKeys = basicElementsFoundationVideoKeys.filter((key) => + key.startsWith('basic-camera-movement:'), +) + +// 新手导航节点配置 +export const navigationNodes: GuideNode[] = [ + { + id: 1, + num: '1', + label: '三大基础要素', + x: 20, + y: 30, + hasChildren: true, + videoKeys: basicElementsFoundationVideoKeys, + children: [ + { + id: 1, + label: '构图', + icon: 'home/action/新手导航构图', + routeName: 'Composition', + videoKeys: compositionVideoKeys, + }, + { + id: 2, + label: '光', + icon: 'home/action/新手导航光', + routeName: 'Light', + videoKeys: lightVideoKeys, + }, + { + id: 3, + label: '运镜', + icon: 'home/action/新手导航运镜', + routeName: 'CameraMovement', + videoKeys: cameraMovementVideoKeys, + }, + ], + }, + { + id: 2, + num: '2', + label: '基础拍摄技巧', + x: 50, + y: 60, + hasChildren: false, + routeName: 'BasicShootingSkills', + videoKeys: basicElementsShootingVideoKeys, + }, + { + id: 3, + num: '3', + label: '短视频剪辑技巧', + x: 80, + y: 30, + hasChildren: false, + routeName: 'ShortVideoEditingSkills', + videoKeys: basicElementsEditingVideoKeys, + }, +] diff --git a/src/views/home/components/StudyProgressPopup.vue b/src/views/home/components/StudyProgressPopup.vue deleted file mode 100644 index 30b5ec0..0000000 --- a/src/views/home/components/StudyProgressPopup.vue +++ /dev/null @@ -1,347 +0,0 @@ - - - diff --git a/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/AnchoredProgressBar.vue b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/AnchoredProgressBar.vue new file mode 100644 index 0000000..6c0b62e --- /dev/null +++ b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/AnchoredProgressBar.vue @@ -0,0 +1,131 @@ + + + diff --git a/src/components/AnchoredProgressBar/computeSegmentLayout.ts b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/computeSegmentLayout.ts similarity index 100% rename from src/components/AnchoredProgressBar/computeSegmentLayout.ts rename to src/views/home/components/StudyProgressPopup/AnchoredProgressBar/computeSegmentLayout.ts diff --git a/src/components/AnchoredProgressBar/index.ts b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/index.ts similarity index 100% rename from src/components/AnchoredProgressBar/index.ts rename to src/views/home/components/StudyProgressPopup/AnchoredProgressBar/index.ts diff --git a/src/components/AnchoredProgressBar/types.ts b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/types.ts similarity index 65% rename from src/components/AnchoredProgressBar/types.ts rename to src/views/home/components/StudyProgressPopup/AnchoredProgressBar/types.ts index 623bacf..4185b88 100644 --- a/src/components/AnchoredProgressBar/types.ts +++ b/src/views/home/components/StudyProgressPopup/AnchoredProgressBar/types.ts @@ -17,9 +17,20 @@ export type AnchoredProgressBarProps = { progress: number min?: number max?: number + width?: number + height?: number + dividerWidth?: number + dividerHeight?: number segments?: ProgressSegment[] trackClass?: string fillClass?: string segmentClass?: string showDividers?: boolean + markerSrc?: string + markerSize?: number + markerTop?: number + showPercent?: boolean + percentTop?: number + percentClass?: string + percentTextShadow?: string } diff --git a/src/views/home/components/StudyProgressPopup/CertificateDetailPopup.vue b/src/views/home/components/StudyProgressPopup/CertificateDetailPopup.vue new file mode 100644 index 0000000..f3249b4 --- /dev/null +++ b/src/views/home/components/StudyProgressPopup/CertificateDetailPopup.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/src/views/home/components/StudyProgressPopup/StudyProgressPopup.vue b/src/views/home/components/StudyProgressPopup/StudyProgressPopup.vue new file mode 100644 index 0000000..2d17eea --- /dev/null +++ b/src/views/home/components/StudyProgressPopup/StudyProgressPopup.vue @@ -0,0 +1,440 @@ + + + diff --git a/src/views/home/components/StudyProgressPopup/index.ts b/src/views/home/components/StudyProgressPopup/index.ts new file mode 100644 index 0000000..81fa646 --- /dev/null +++ b/src/views/home/components/StudyProgressPopup/index.ts @@ -0,0 +1 @@ +export { default as StudyProgressPopup } from './StudyProgressPopup.vue' diff --git a/src/views/home/components/studyProgressConfig.ts b/src/views/home/components/StudyProgressPopup/studyProgressConfig.ts similarity index 95% rename from src/views/home/components/studyProgressConfig.ts rename to src/views/home/components/StudyProgressPopup/studyProgressConfig.ts index c75f617..90e9a2b 100644 --- a/src/views/home/components/studyProgressConfig.ts +++ b/src/views/home/components/StudyProgressPopup/studyProgressConfig.ts @@ -1,4 +1,4 @@ -import type { ProgressSegment } from '@/components' +import type { ProgressSegment } from './AnchoredProgressBar' export type StudyProgressModuleKey = 'basic' | 'vlog' | 'interview' | 'film' diff --git a/src/views/home/components/studyProgressUtils.ts b/src/views/home/components/studyProgressUtils.ts deleted file mode 100644 index 6cad638..0000000 --- a/src/views/home/components/studyProgressUtils.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { - getBasicElementsProgress, - getOverallStudyProgress, - getProductionModuleProgress, - type ProductionModuleKey, -} from '@/config/studyProgress' diff --git a/src/views/home/index.tsx b/src/views/home/index.tsx index 94e4eb7..402d923 100644 --- a/src/views/home/index.tsx +++ b/src/views/home/index.tsx @@ -6,7 +6,12 @@ import { IMAGE_PATHS, } from '@/utils' import { ImgButton } from '@/components/Button' -import { CourseGuidePopup, CourseFrameworkPopup, GuideSteps, Video } from '@/components' +import { + CourseGuidePopup, + CourseFrameworkPopup, + GuideSteps, + Video, +} from '@/components' import Loading from './components/Loading.vue' import { useScale } from '@/composables/useScale' import { useBasicElementsStore } from '@/stores/modules/basic-elements' @@ -19,7 +24,7 @@ const CourseFrameGuide = () => ( src={getStaticImage(IMAGE_PATHS.BUTTONS.COURSE_FRAME)} alt="" /> - 查看课程结构,快速了解每个模块的学习内容。 + 查看课程整体结构,快速了解每个模块的学习内容。 ) @@ -30,7 +35,7 @@ const OperateGuide = () => ( src={getStaticImage(IMAGE_PATHS.BUTTONS.OPERATE_GUIDE)} alt="" /> - 包含课程介绍和操作指南,点击即可查看! + 包含课程介绍和操作指引,点击即可查看! ) @@ -90,12 +95,20 @@ export default defineComponent({ const { scale, offsetX, offsetY } = useScale() // 首次进入的视频播放序列 - const introVideos = computed(() => [getPublicPath('video/start.mp4')]) + const introVideos = computed(() => [ + getPublicPath('video/start.mp4'), + getPublicPath('video/guide.mp4'), + ]) const introVideoIndex = ref(0) const showIntroVideo = ref(isFirstVisit) const currentIntroSrc = computed( () => introVideos.value[introVideoIndex.value] ?? '', ) + const currentIntroPoster = computed(() => + introVideoIndex.value === 0 + ? (getStaticImage('cover/start.jpg') as string) + : '', + ) if (isFirstVisit) { basicElementsStore.markGuideShown(guideKey) @@ -114,6 +127,10 @@ export default defineComponent({ } } + const handleSkipIntro = () => { + showIntroVideo.value = false + } + // Loading 加载状态 const showLoading = ref(isFirstVisit) const loadingProgress = ref(0) @@ -187,7 +204,7 @@ export default defineComponent({ style={{ backgroundImage: getBackgroundImage(IMAGE_PATHS.HOME_BG) }} /> -
+
-
)} diff --git a/src/views/interview/after-editing/editing.vue b/src/views/interview/after-editing/editing.vue index 9033757..6dc235b 100644 --- a/src/views/interview/after-editing/editing.vue +++ b/src/views/interview/after-editing/editing.vue @@ -171,13 +171,13 @@ onBeforeRouteLeave((to) => { @click="handleClose" />
diff --git a/src/views/interview/midterm-shooting/on-site/index.vue b/src/views/interview/midterm-shooting/on-site/index.vue index 8940363..fdcfe29 100644 --- a/src/views/interview/midterm-shooting/on-site/index.vue +++ b/src/views/interview/midterm-shooting/on-site/index.vue @@ -207,13 +207,13 @@ onBeforeRouteLeave((to) => { @click="back" /> + + 当前查看:{{ currentFilterText }} + + + 共 {{ filteredResources.length }} 个资源 + + + @@ -597,12 +609,12 @@ const handleGuideSkip = () => {