diff --git a/.tmp.modal.print-config.json b/.tmp.modal.print-config.json
new file mode 100644
index 0000000..b845737
Binary files /dev/null and b/.tmp.modal.print-config.json differ
diff --git a/STEP_NAVIGATION_REDESIGN.md b/STEP_NAVIGATION_REDESIGN.md
deleted file mode 100644
index 0519ecb..0000000
--- a/STEP_NAVIGATION_REDESIGN.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/eslint.config.ts b/eslint.config.ts
index 4fb5b97..b539dfd 100644
--- a/eslint.config.ts
+++ b/eslint.config.ts
@@ -13,13 +13,16 @@ export default defineConfig([
rules: {
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
- '@typescript-eslint/no-explicit-any': 'warn',
+ '@typescript-eslint/no-explicit-any': 'off', // 完全禁用 any 检查
// 关闭所有需要类型信息的规则
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
- '@typescript-eslint/no-unsafe-argument': 'off'
+ '@typescript-eslint/no-unsafe-argument': 'off',
+ '@typescript-eslint/no-empty-object-type': 'off', // 允许空接口
+ '@typescript-eslint/no-unused-expressions': 'warn', // 改为警告而非错误
+ 'no-unused-expressions': 'off'
}
}
])
diff --git a/src/assets/images/afterditing/color/卡片-日落增色.png b/src/assets/images/afterditing/color/卡片-日落增色.png
new file mode 100644
index 0000000..80a0199
Binary files /dev/null and b/src/assets/images/afterditing/color/卡片-日落增色.png differ
diff --git a/src/assets/images/afterditing/color/卡片-智能调色.png b/src/assets/images/afterditing/color/卡片-智能调色.png
index fb6b998..6d94ad9 100644
Binary files a/src/assets/images/afterditing/color/卡片-智能调色.png and b/src/assets/images/afterditing/color/卡片-智能调色.png differ
diff --git a/src/assets/images/afterditing/color/卡片-落日火烧云.png b/src/assets/images/afterditing/color/卡片-落日火烧云.png
new file mode 100644
index 0000000..70ca195
Binary files /dev/null and b/src/assets/images/afterditing/color/卡片-落日火烧云.png differ
diff --git a/src/assets/images/afterditing/color/原图.png b/src/assets/images/afterditing/color/原图.png
index 54ca147..ba64a09 100644
Binary files a/src/assets/images/afterditing/color/原图.png and b/src/assets/images/afterditing/color/原图.png differ
diff --git a/src/assets/images/afterditing/color/日落增色.png b/src/assets/images/afterditing/color/日落增色.png
new file mode 100644
index 0000000..c675394
Binary files /dev/null and b/src/assets/images/afterditing/color/日落增色.png differ
diff --git a/src/assets/images/afterditing/color/智能调色.png b/src/assets/images/afterditing/color/智能调色.png
index e857c99..e5f2535 100644
Binary files a/src/assets/images/afterditing/color/智能调色.png and b/src/assets/images/afterditing/color/智能调色.png differ
diff --git a/src/assets/images/afterditing/color/落日火烧云.png b/src/assets/images/afterditing/color/落日火烧云.png
new file mode 100644
index 0000000..7093bcc
Binary files /dev/null and b/src/assets/images/afterditing/color/落日火烧云.png differ
diff --git a/src/assets/images/equipment/内容-安卓小米.png b/src/assets/images/equipment/内容-安卓小米.png
index 7d27721..b542753 100644
Binary files a/src/assets/images/equipment/内容-安卓小米.png and b/src/assets/images/equipment/内容-安卓小米.png differ
diff --git a/src/assets/images/equipment/内容-苹果.png b/src/assets/images/equipment/内容-苹果.png
index 3c055f2..8444bef 100644
Binary files a/src/assets/images/equipment/内容-苹果.png and b/src/assets/images/equipment/内容-苹果.png differ
diff --git a/src/assets/images/home/guide/action-btn.png b/src/assets/images/home/guide/action-btn.png
index 4f619d3..bc2bd8e 100644
Binary files a/src/assets/images/home/guide/action-btn.png and b/src/assets/images/home/guide/action-btn.png differ
diff --git a/src/assets/images/home/guide/bg.png b/src/assets/images/home/guide/bg.png
index ec7b3a2..271e4bc 100644
Binary files a/src/assets/images/home/guide/bg.png and b/src/assets/images/home/guide/bg.png differ
diff --git a/src/assets/images/home/guide/cz-btn.png b/src/assets/images/home/guide/cz-btn.png
index a91f40b..b10c8af 100644
Binary files a/src/assets/images/home/guide/cz-btn.png and b/src/assets/images/home/guide/cz-btn.png differ
diff --git a/src/assets/images/home/guide/kc-btn.png b/src/assets/images/home/guide/kc-btn.png
index cd57231..d4e2a39 100644
Binary files a/src/assets/images/home/guide/kc-btn.png and b/src/assets/images/home/guide/kc-btn.png differ
diff --git a/src/assets/images/shooting/对角线构图1.png b/src/assets/images/shooting/对角线构图1.png
new file mode 100644
index 0000000..a894c39
Binary files /dev/null and b/src/assets/images/shooting/对角线构图1.png differ
diff --git a/src/assets/images/shooting/对角线构图2.png b/src/assets/images/shooting/对角线构图2.png
new file mode 100644
index 0000000..187022f
Binary files /dev/null and b/src/assets/images/shooting/对角线构图2.png differ
diff --git a/src/assets/images/shooting/居中构图1.png b/src/assets/images/shooting/居中构图1.png
new file mode 100644
index 0000000..fe535a4
Binary files /dev/null and b/src/assets/images/shooting/居中构图1.png differ
diff --git a/src/assets/images/shooting/居中构图2.png b/src/assets/images/shooting/居中构图2.png
new file mode 100644
index 0000000..1f9635b
Binary files /dev/null and b/src/assets/images/shooting/居中构图2.png differ
diff --git a/src/assets/images/shooting/示意图-对角线.png b/src/assets/images/shooting/示意图-对角线.png
new file mode 100644
index 0000000..7221a79
Binary files /dev/null and b/src/assets/images/shooting/示意图-对角线.png differ
diff --git a/src/assets/images/shooting/示意图-居中.png b/src/assets/images/shooting/示意图-居中.png
new file mode 100644
index 0000000..0797db3
Binary files /dev/null and b/src/assets/images/shooting/示意图-居中.png differ
diff --git a/src/assets/images/work/专业剖析小屏.png b/src/assets/images/work/专业剖析小屏.png
new file mode 100644
index 0000000..162be95
Binary files /dev/null and b/src/assets/images/work/专业剖析小屏.png differ
diff --git a/src/components/KnowledgeCard/KnowledgeCard.vue b/src/components/KnowledgeCard/KnowledgeCard.vue
new file mode 100644
index 0000000..c317513
--- /dev/null
+++ b/src/components/KnowledgeCard/KnowledgeCard.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+ {{ props.title }}
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+ {{ props.desc }}
+
+
+
+
+
+
+
+
diff --git a/src/components/Video/Video.vue b/src/components/Video/Video.vue
new file mode 100644
index 0000000..730e6ad
--- /dev/null
+++ b/src/components/Video/Video.vue
@@ -0,0 +1,486 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ fmt(currentTime) }}
+
+
+
+
{{ fmt(duration) }}
+
+
+ 🔊
+ handleVolume(Number((e.target as HTMLInputElement).value))"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Video/index.ts b/src/components/Video/index.ts
new file mode 100644
index 0000000..218cfb5
--- /dev/null
+++ b/src/components/Video/index.ts
@@ -0,0 +1,2 @@
+export { default as Video } from './Video.vue'
+export type {} from './Video.vue'
diff --git a/src/components/index.ts b/src/components/index.ts
index 9b069e7..ccbbfb6 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -22,3 +22,6 @@ export * from './Modal'
// 遮罩层组件
export * from './Overlay'
+
+// 视频组件
+export * from './Video'
diff --git a/src/views/afterditing/color.vue b/src/views/afterditing/color.vue
index 64418d0..92a991a 100644
--- a/src/views/afterditing/color.vue
+++ b/src/views/afterditing/color.vue
@@ -20,15 +20,15 @@ const colorBarList = ref([
},
{
id: 2,
- name: '滤镜-冬日物语',
- image: getStaticImage('afterditing/color/冬日物语.jpg'),
- Screenshot: getStaticImage('afterditing/color/卡片-冬日物语.png')
+ name: '滤镜-日落增色',
+ image: getStaticImage('afterditing/color/日落增色.png'),
+ Screenshot: getStaticImage('afterditing/color/卡片-日落增色.png')
},
{
id: 3,
- name: '滤镜-日落电影',
- image: getStaticImage('afterditing/color/落日余晖.jpg'),
- Screenshot: getStaticImage('afterditing/color/卡片-落日余晖.png')
+ name: '滤镜-落日火烧云',
+ image: getStaticImage('afterditing/color/落日火烧云.png'),
+ Screenshot: getStaticImage('afterditing/color/卡片-落日火烧云.png')
}
])
diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index 23f7012..f02e18a 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -12,15 +12,15 @@ import { ImgButton } from '@/components/Button'
>
-
+
-
+
-
diff --git a/src/views/midterm-shooting/equipment/index.vue b/src/views/midterm-shooting/equipment/index.vue
index 36d82b0..4ef0c5d 100644
--- a/src/views/midterm-shooting/equipment/index.vue
+++ b/src/views/midterm-shooting/equipment/index.vue
@@ -237,7 +237,7 @@ const currentHighlight = computed(() =>
stepIndex.value === 0 ? '.img-switch-item--vlog' : '.work-border'
)
-
diff --git a/src/views/skill/components/IconLayer.vue b/src/views/skill/components/IconLayer.vue
new file mode 100644
index 0000000..a29b484
--- /dev/null
+++ b/src/views/skill/components/IconLayer.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
diff --git a/src/views/skill/components/ModuleSwitcher.vue b/src/views/skill/components/ModuleSwitcher.vue
new file mode 100644
index 0000000..872704a
--- /dev/null
+++ b/src/views/skill/components/ModuleSwitcher.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+ {{ props.moduleName }}
+
+
+
+
diff --git a/src/views/skill/index.vue b/src/views/skill/index.vue
index 80f3c42..5f8d635 100644
--- a/src/views/skill/index.vue
+++ b/src/views/skill/index.vue
@@ -1,239 +1,155 @@
@@ -244,101 +160,24 @@ setTimeout(() => {
:style="{ backgroundImage: getBackgroundImage('skill/技能树背景') }"
>
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
+
{
}"
>
-
-
- {{ selectedCategory || currentModule.name }}
-
-
{{
- !status
- ? '当前尚未收集任何知识点,快去学习收集知识点吧'
- : selectedCategory
- ? `当前${selectedCategory}模块已全部解锁`
- : '当前已全部解锁'
+ !status ? '当前尚未收集任何知识点,快去学习收集知识点吧' : '当前已全部解锁'
}}
@@ -383,6 +213,17 @@ setTimeout(() => {
@step-change="handleStepChange"
position-offset-y="85%"
/>
+
+
+
diff --git a/src/views/skill/useSkillState.ts b/src/views/skill/useSkillState.ts
new file mode 100644
index 0000000..d4bef74
--- /dev/null
+++ b/src/views/skill/useSkillState.ts
@@ -0,0 +1,214 @@
+import { ref, computed } from 'vue'
+
+// 分类配置
+interface CategoryConfig {
+ icons: string[]
+ positions: { top: string; left: string }[]
+}
+
+// 模块配置
+interface ModuleConfig {
+ name: string
+ value: number
+ categories: Record
+}
+
+// 知识卡片按钮数据结构(与 shooting/index.vue 对齐)
+export type KnowledgeBtn = {
+ key: string
+ name: string
+ btnImage: string
+ images: string[]
+ desc: string
+}
+
+export function useSkillState() {
+ // 模块/分类/图标层级状态(仅保留必要业务状态)
+ const selectedModule = ref(1)
+ const selectedCategory = ref('')
+ const showSubIcons = ref(false)
+ const selectedPrimaryIcon = ref(null)
+
+ const moduleList = ref([
+ {
+ name: '技能树-新手启航',
+ value: 1,
+ categories: {
+ 拍摄基础: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 内容策划: {
+ icons: ['skill/画面构图未选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 拍摄执行: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 后期制作: {
+ icons: ['skill/画面构图未选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 版权伦理意识: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ }
+ }
+ },
+ {
+ name: '技能树-vlog',
+ value: 2,
+ categories: {
+ 拍摄基础: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 内容策划: {
+ icons: ['skill/画面构图未选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 拍摄执行: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 后期制作: {
+ icons: ['skill/画面构图未选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ },
+ 版权伦理意识: {
+ icons: ['skill/画面构图未选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
+ positions: [
+ { top: '36%', left: '23%' },
+ { top: '15%', left: '34%' },
+ { top: '20%', left: '45%' },
+ { top: '28%', left: '58%' }
+ ]
+ }
+ }
+ }
+ ])
+
+ const currentModule = computed(() => {
+ return moduleList.value.find(item => item.value === selectedModule.value) || moduleList.value[0]
+ })
+
+ const nextModule = () => {
+ if (selectedModule.value === moduleList.value.length) {
+ selectedModule.value = 1
+ } else {
+ selectedModule.value++
+ }
+ }
+
+ const prevModule = () => {
+ if (selectedModule.value === 1) {
+ selectedModule.value = moduleList.value.length
+ } else {
+ selectedModule.value--
+ }
+ }
+
+ const handleCategoryClick = (categoryName: string) => {
+ selectedCategory.value = categoryName
+ showSubIcons.value = false
+ selectedPrimaryIcon.value = null
+ }
+
+ const currentCategoryConfig = computed(() => {
+ if (!selectedCategory.value) return null
+ return currentModule.value.categories[selectedCategory.value] || null
+ })
+
+ const displayedIcons = computed(() => {
+ const cfg = currentCategoryConfig.value
+ if (!cfg) return [] as string[]
+ if (showSubIcons.value && selectedPrimaryIcon.value) {
+ return ['skill/画面构图选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图']
+ }
+ return cfg.icons
+ })
+
+ type IconAction =
+ | { type: 'navigate'; payload: { name: string } }
+ | { type: 'expand' }
+ | { type: 'openKnowledge'; payload: { name: '三分法构图' | '居中构图' | '对角线构图' } }
+ | null
+
+ const getIconAction = (icon: string): IconAction => {
+ if (icon === 'skill/画面构图未选中' && selectedCategory.value === '拍摄执行') {
+ if (selectedModule.value === 1) return { type: 'navigate', payload: { name: 'SkillVdieo' } }
+ if (selectedModule.value === 2) return { type: 'expand' }
+ }
+ if (showSubIcons.value && selectedModule.value === 2 && selectedCategory.value === '拍摄执行') {
+ const map: Record = {
+ 'skill/三分法构图': '三分法构图',
+ 'skill/居中构图': '居中构图',
+ 'skill/对角线构图': '对角线构图'
+ }
+ if (icon in map) return { type: 'openKnowledge', payload: { name: map[icon] } }
+ }
+ return null
+ }
+
+ return {
+ // module switcher
+ currentModule,
+ nextModule,
+ prevModule,
+ // category & icons
+ selectedCategory,
+ handleCategoryClick,
+ currentCategoryConfig,
+ displayedIcons,
+ selectedModule,
+ showSubIcons,
+ selectedPrimaryIcon,
+ getIconAction
+ }
+}
diff --git a/src/views/test-step-navigation.vue b/src/views/test-step-navigation.vue
deleted file mode 100644
index 0519ecb..0000000
--- a/src/views/test-step-navigation.vue
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/views/vlog/video/index.vue b/src/views/vlog/video/index.vue
index 7c67b46..c78b4d0 100644
--- a/src/views/vlog/video/index.vue
+++ b/src/views/vlog/video/index.vue
@@ -3,6 +3,7 @@ import { computed, nextTick, onMounted, ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import ImgButton from '@/components/Button/ImgButton.vue'
import { GuideSteps, StepNavigation } from '@/components/Guide'
+import { Video } from '@/components'
import { getStaticImage, IMAGE_PATHS } from '@/utils'
import second from '/video/Vlog模块_任务取景框_专业剖析_基础景别运用.mp4'
import third from '/video/Vlog模块_任务取景框_专业剖析_画面构图.mp4'
@@ -13,7 +14,8 @@ import six from '/video/Vlog模块_任务取景框_专业剖析_素材导入、
const router = useRouter()
const route = useRoute()
-const videoRef = ref()
+// 受控播放开关(用于切换到下一个视频时自动播放)
+const playing = ref(false)
const status = ref(false)
//引导步骤
@@ -68,6 +70,11 @@ const currentVideoIndex = ref(0)
//按顺序播放
const currentVideo = computed(() => videoList[currentVideoIndex.value])
+const resolvedSrc = computed(() => {
+ if (key.value === 'case') return '/video/案例赏析-美食小确幸:桂花酒酿小圆子.mp4'
+ if (key.value === 'profession') return currentVideo.value
+ return ''
+})
const handleVideoChange = () => {
if (currentVideoIndex.value < videoList.length - 1) {
currentVideoIndex.value++
@@ -83,10 +90,8 @@ const handleVideoChange = () => {
return
}
nextTick(() => {
- if (!videoRef.value) return
- videoRef.value.muted = false
- videoRef.value.volume = 1
- videoRef.value.play()
+ // 使用受控播放来触发下一个视频自动播放
+ playing.value = true
})
}
@@ -97,16 +102,12 @@ const handleClose = () => {
const image = computed(() => route.query.image as string)
const key = computed(() => route.query.key as string)
-const handleClick = () => {
- if (!videoRef.value) return
- videoRef.value.muted = false
- videoRef.value.volume = 1
-}
+const handleClick = () => {}
-const handlePlay = () => {
- if (!videoRef.value) return
- videoRef.value.muted = false
- videoRef.value.volume = 1
+const handlePlay = () => {}
+
+const onEnded = () => {
+ if (key.value === 'profession') handleVideoChange()
}
const handleComplete = () => {
@@ -132,10 +133,7 @@ const handleStepClick = (index: number) => {
currentVideoIndex.value = index
currentNavigationStep.value = index
nextTick(() => {
- if (!videoRef.value) return
- videoRef.value.muted = false
- videoRef.value.volume = 1
- videoRef.value.play()
+ playing.value = true
})
}
@@ -152,12 +150,14 @@ onMounted(() => {
-
-
+
+
+
+