feat: 技能树

This commit is contained in:
zhongyingmin committed 2025-12-31 01:08:21 +08:00
1 parent 6ab98c4764
commit b980f2993b
31 files changed
+861 -292

No files matched your search

+314
View File
@@ -0,0 +1,314 @@
// 资源数据结构定义 - 一维数组格式
export interface ResourceItem {
id: string
title: string
description?: string
// 用于检索的属性
moduleId: string
moduleName: string
tagId: string
tagName: string
subTagId?: string
subTagName?: string
// 资源数量(用于技能树显示)
resourceCount?: number
}
// 一维数组格式的资源数据
export const resourceData: ResourceItem[] = [
// 新手导航模块
{
id: 'res-1',
title: '九种构图法',
description: '学习九种基础构图技巧',
moduleId: 'module-1',
moduleName: '新手导航',
tagId: 'tag-1-1',
tagName: '视觉素养',
subTagId: 'subtag-1-1-1',
subTagName: '构图'
},
{
id: 'res-2',
title: '光线运用基础',
description: '掌握基础光线运用技巧',
moduleId: 'module-1',
moduleName: '新手导航',
tagId: 'tag-1-1',
tagName: '视觉素养',
subTagId: 'subtag-1-1-2',
subTagName: '光线'
},
{
id: 'res-3',
title: '运镜技巧入门',
description: '学习基础运镜方法',
moduleId: 'module-1',
moduleName: '新手导航',
tagId: 'tag-1-1',
tagName: '视觉素养',
subTagId: 'subtag-1-1-3',
subTagName: '运镜'
},
{
id: 'res-4',
title: '摄影基础教程',
description: '摄影基础知识讲解',
moduleId: 'module-1',
moduleName: '新手导航',
tagId: 'tag-1-2',
tagName: '摄影基础'
},
{
id: 'res-5',
title: '剪映入门',
description: '剪映基础操作教程',
moduleId: 'module-1',
moduleName: '新手导航',
tagId: 'tag-1-3',
tagName: '剪映基础操作'
},
// vlog发现与记录模块
{
id: 'res-6',
title: '设备准备指南',
description: 'vlog拍摄设备准备',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-1',
tagName: '内容策划',
subTagId: 'subtag-2-1-1',
subTagName: '设备准备'
},
{
id: 'res-7',
title: 'vlog脚本撰写',
description: '如何撰写vlog脚本',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-1',
tagName: '内容策划',
subTagId: 'subtag-2-1-2',
subTagName: '脚本制作'
},
{
id: 'res-8',
title: 'vlog构图技巧',
description: 'vlog拍摄构图方法',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-2',
tagName: '拍摄执行',
subTagId: 'subtag-2-2-1',
subTagName: '构图'
},
{
id: 'res-9',
title: 'vlog光线控制',
description: 'vlog拍摄光线运用',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-2',
tagName: '拍摄执行',
subTagId: 'subtag-2-2-2',
subTagName: '光线运用'
},
{
id: 'res-10',
title: 'vlog运镜方法',
description: 'vlog拍摄运镜技巧',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-2',
tagName: '拍摄执行',
subTagId: 'subtag-2-2-3',
subTagName: '运镜技巧'
},
{
id: 'res-11',
title: 'vlog后期剪辑',
description: 'vlog视频后期制作',
moduleId: 'module-2',
moduleName: 'vlog发现与记录',
tagId: 'tag-2-3',
tagName: '后期制作'
},
// 访谈聆听与对话模块
{
id: 'res-12',
title: '访谈选题方法',
description: '如何选择访谈主题',
moduleId: 'module-3',
moduleName: '访谈聆听与对话',
tagId: 'tag-3-1',
tagName: '内容策划',
subTagId: 'subtag-3-1-1',
subTagName: '选题与构思'
},
{
id: 'res-13',
title: '访谈脚本制作',
description: '访谈脚本撰写技巧',
moduleId: 'module-3',
moduleName: '访谈聆听与对话',
tagId: 'tag-3-1',
tagName: '内容策划',
subTagId: 'subtag-3-1-2',
subTagName: '脚本与分镜制作'
},
{
id: 'res-14',
title: '访谈拍摄技巧',
description: '访谈视频拍摄方法',
moduleId: 'module-3',
moduleName: '访谈聆听与对话',
tagId: 'tag-3-2',
tagName: '拍摄执行'
},
// 电影创作与表达模块
{
id: 'res-15',
title: '电影设备准备',
description: '电影拍摄设备清单',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-1',
tagName: '内容策划',
subTagId: 'subtag-4-1-1',
subTagName: '设备准备'
},
{
id: 'res-16',
title: '电影选题构思',
description: '电影创作选题方法',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-1',
tagName: '内容策划',
subTagId: 'subtag-4-1-2',
subTagName: '选题与构思'
},
{
id: 'res-17',
title: '电影脚本分镜',
description: '电影脚本和分镜制作',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-1',
tagName: '内容策划',
subTagId: 'subtag-4-1-3',
subTagName: '脚本与分镜制作'
},
{
id: 'res-18',
title: '电影拍摄执行',
description: '电影拍摄执行技巧',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-2',
tagName: '拍摄执行'
},
{
id: 'res-19',
title: '电影后期制作',
description: '电影后期剪辑与特效',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-3',
tagName: '后期制作'
},
{
id: 'res-20',
title: 'AI与版权伦理',
description: 'AI工具使用与版权规范',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-4',
tagName: 'AI与版权伦理知识'
},
{
id: 'res-21',
title: '创作思路与案例',
description: '电影创作思路和案例分析',
moduleId: 'module-4',
moduleName: '电影创作与表达',
tagId: 'tag-4-5',
tagName: '思路提点与案例赏析'
}
]
// 从一维数组获取所有资源
export function getAllResources(): ResourceItem[] {
return resourceData
}
// 根据模块ID获取资源
export function getResourcesByModule(moduleId: string): ResourceItem[] {
return resourceData.filter(resource => resource.moduleId === moduleId)
}
// 根据资源标签ID获取资源
export function getResourcesByTag(moduleId: string, tagId: string): ResourceItem[] {
return resourceData.filter(resource => resource.moduleId === moduleId && resource.tagId === tagId)
}
// 根据子标签ID获取资源
export function getResourcesBySubTag(
moduleId: string,
tagId: string,
subTagId: string
): ResourceItem[] {
return resourceData.filter(
resource =>
resource.moduleId === moduleId && resource.tagId === tagId && resource.subTagId === subTagId
)
}
// 获取所有模块
export function getAllModules(): Array<{ id: string; name: string }> {
const modules = new Map<string, string>()
resourceData.forEach(resource => {
if (!modules.has(resource.moduleId)) {
modules.set(resource.moduleId, resource.moduleName)
}
})
return Array.from(modules.entries()).map(([id, name]) => ({ id, name }))
}
// 获取模块下的所有标签
export function getTagsByModule(moduleId: string): Array<{ id: string; name: string }> {
const tags = new Map<string, string>()
resourceData
.filter(resource => resource.moduleId === moduleId)
.forEach(resource => {
if (!tags.has(resource.tagId)) {
tags.set(resource.tagId, resource.tagName)
}
})
return Array.from(tags.entries()).map(([id, name]) => ({ id, name }))
}
// 获取标签下的所有子标签
export function getSubTagsByTag(
moduleId: string,
tagId: string
): Array<{ id: string; name: string }> {
const subTags = new Map<string, string>()
resourceData
.filter(
resource => resource.moduleId === moduleId && resource.tagId === tagId && resource.subTagId
)
.forEach(resource => {
if (resource.subTagId && !subTags.has(resource.subTagId)) {
subTags.set(resource.subTagId, resource.subTagName || '')
}
})
return Array.from(subTags.entries()).map(([id, name]) => ({ id, name }))
}
// 获取标签的资源数量
export function getTagResourceCount(moduleId: string, tagId: string): number {
return resourceData.filter(resource => resource.moduleId === moduleId && resource.tagId === tagId)
.length
}