Files
super_video/SKILL_ARCHITECTURE.md
T

12 KiB
Raw Blame History

📚 Skill 功能架构完整分析

🗂️ 文件结构(已清理)

src/views/skill/
├── index.vue                    # 主页面 - 技能树资源浏览器
├── resourceData.ts              # 数据层 - 资源数据管理
├── video.vue                    # 视频播放页面
└── components/
    ├── SkillTree.vue           # 技能树可视化组件
    ├── SearchTags.vue          # 搜索面包屑标签
    └── ResourceList.vue        # 资源列表展示

🎯 核心功能定位

技能树资源浏览系统 - 一个基于树形结构的学习资源导航和筛选平台


📊 数据架构

1. 数据层级结构

模块 (Module)
  └─ 标签 (Tag)
      └─ 子标签 (SubTag)
          └─ 资源 (Resource)

2. 数据实体

ResourceItem 接口

{
  id: string              // 资源唯一标识
  title: string           // 资源标题
  description?: string    // 资源描述
  moduleId: string        // 所属模块ID
  moduleName: string      // 所属模块名称
  tagId: string          // 所属标签ID
  tagName: string        // 所属标签名称
  subTagId?: string      // 所属子标签ID(可选)
  subTagName?: string    // 所属子标签名称(可选)
}

3. 数据统计

  • 4个模块:

    1. module-1: 新手导航 (5个资源)
    2. module-2: vlog发现与记录 (6个资源)
    3. module-3: 访谈聆听与对话 (3个资源)
    4. module-4: 电影创作与表达 (7个资源)
  • 8种标签类型:

    • 视觉素养 (橙色)
    • 摄影基础 (蓝色)
    • 剪映基础操作 (紫色)
    • 内容策划 (橙色)
    • 拍摄执行 (绿色)
    • 后期制作 (蓝色)
    • AI与版权伦理知识 (蓝色)
    • 思路提点与案例赏析 (蓝色)
  • 总资源数:21个学习资源

4. 工具函数

getAllResources() // 获取所有资源
getResourcesByModule(moduleId) // 按模块筛选
getResourcesByTag(moduleId, tagId) // 按标签筛选
getResourcesBySubTag(moduleId, tagId, subTagId) // 按子标签筛选
getAllModules() // 获取所有模块
getTagsByModule(moduleId) // 获取模块的标签
getSubTagsByTag(moduleId, tagId) // 获取标签的子标签
getTagResourceCount(moduleId, tagId) // 获取标签的资源数量

🎨 UI 布局

页面布局(1920x1080)

┌─────────────────────────────────────────────────────────────┐
│  [搜索框 + 面包屑]        [模块1][模块2][模块3][模块4]  [X] │
│                                                             │
│                                                             │
│  ┌──────────────┐                    ┌──────────────────┐  │
│  │              │                    │                  │  │
│  │   资源列表    │                    │     技能树        │  │
│  │   740x800    │                    │    860x820       │  │
│  │              │                    │                  │  │
│  │              │                    │   [标签节点...]   │  │
│  │  [资源卡片]   │                    │                  │  │
│  │  [资源卡片]   │                    │  技能树总览       │  │
│  └──────────────┘                    └──────────────────┘  │
└─────────────────────────────────────────────────────────────┘

组件定位

  1. 搜索框:左上角 (left-10, top-10, 547x84px)
  2. 模块图标:顶部居中 (left-55%, top-10, 4个141x150px)
  3. 资源列表:左下角 (left-10, bottom-20, 740x800px)
  4. 技能树:右下角 (right-0, bottom-20, 860x820px)
  5. 关闭按钮:右上角 (right-0, top-0)

🔄 交互逻辑流程

1. 状态管理

// 核心状态
selectedModuleId: string | null // 当前选中的模块
selectedTagId: string | null // 当前选中的标签
selectedSubTagId: string | null // 当前选中的子标签
expandedTags: Set<string> // 展开的标签集合
search: string // 搜索文本(待实现)

2. 用户交互流程

流程A:模块筛选

用户点击模块图标
  ↓
handleModuleListItemClick(moduleId)
  ↓
如果已选中同一模块 → 取消选择(显示所有)
如果选中新模块 → 设置 selectedModuleId
  ↓
清空标签和子标签选择
  ↓
技能树只显示该模块的标签
资源列表只显示该模块的资源

流程B:标签筛选

用户点击技能树标签
  ↓
handleTagClick(moduleId, tagId)
  ↓
如果已选中同一标签:
  - 已展开 → 折叠并取消选择
  - 未展开 → 展开子标签
如果选中新标签:
  - 设置 selectedModuleId 和 selectedTagId
  - 如果有子标签 → 自动展开
  ↓
资源列表显示该标签的所有资源
搜索框显示面包屑:[模块] > [标签]

流程C:子标签筛选

用户点击子标签
  ↓
handleSubTagClick(moduleId, tagId, subTagId)
  ↓
如果已选中同一子标签 → 取消选择
如果选中新子标签 → 设置 selectedSubTagId
  ↓
资源列表显示该子标签的资源
搜索框显示面包屑:[模块] > [标签] > [子标签]

3. 计算属性逻辑

searchTags(面包屑)

根据选择状态生成面包屑数组:
- 选中模块 → 添加模块标签(蓝色)
- 选中标签 → 添加标签标签(橙色)
- 选中子标签 → 添加子标签标签(紫色)

filteredResources(资源过滤)

优先级:子标签 > 标签 > 模块 > 全部
1. 如果选中子标签 → 返回子标签的资源
2. 否则如果选中标签 → 返回标签的资源
3. 否则如果选中模块 → 返回模块的资源
4. 否则 → 返回所有资源

🌳 技能树组件详解

1. 核心功能

  • 标签去重:使用 displayedTags 计算属性,通过 moduleId-tagId 作为唯一键去重
  • 位置布局:14个预定义位置,形成树形分布
  • 颜色映射:根据标签名称返回不同颜色
  • 展开/折叠:有子标签的标签可以展开显示子标签列表
  • 数字徽章:显示每个标签下的资源数量

2. 标签位置分布

14个预定义位置(百分比定位):
顶部区域(树冠):
  - (8%, 35%)  - (12%, 55%)  - (18%, 72%)
中上区域:
  - (28%, 18%) - (32%, 82%)
中部区域:
  - (42%, 10%) - (45%, 28%)  - (48%, 68%)
中下区域:
  - (58%, 22%) - (62%, 78%)  - (68%, 85%)
底部区域(树干):
  - (75%, 15%) - (78%, 38%)  - (82%, 65%)

3. 标签样式

基础样式:
- 圆角矩形:rounded-xl
- 内边距:px-4 py-2
- 边框:border-2
- 尺寸:min-w-[140px] max-w-[200px]
- 阴影:shadow-lg

交互效果:
- hover:scale-105
- 选中:橙色背景 + 白色光圈

颜色映射:
- 后期制作:蓝色 (bg-blue-500/85)
- 拍摄执行:绿色 (bg-green-500/85)
- 内容策划:橙色 (bg-orange-500/85)
- 视觉素养:橙色 (bg-orange-500/85)
- 摄影基础:蓝色 (bg-blue-500/85)
- 剪映基础操作:紫色 (bg-purple-500/85)
- AI与版权伦理知识:蓝色 (bg-blue-500/85)
- 思路提点与案例赏析:蓝色 (bg-blue-500/85)

4. 子标签展开

父标签被点击且有子标签
  ↓
在父标签下方显示子标签列表
  ↓
子标签样式:
- 更小的尺寸 (px-3 py-1)
- 圆角矩形 (rounded-lg)
- 蓝色背景(未选中)/ 橙色背景(选中)
- 垂直排列 (space-y-1)

📋 资源列表组件

功能

  • 显示过滤后的资源列表
  • 滚动容器(overflow-y-auto)
  • 空状态提示

资源卡片样式

- 半透明蓝色背景:bg-blue-500/20
- 圆角:rounded
- 内边距:p-4
- hover效果:bg-blue-500/30
- 标题:text-2xl font-bold
- 描述:text-lg text-gray-300

🔍 搜索标签组件

功能

  • 显示当前选择路径(面包屑导航)
  • 不同类型不同颜色

标签样式

- 圆角胶囊:rounded-full
- 边框:border border-white/80
- 内边距:px-3 py-1
- 颜色映射:
  - 模块:蓝色 (bg-blue-500/80)
  - 标签:橙色 (bg-orange-500/80)
  - 子标签:紫色 (bg-purple-500/80)

🎬 视频播放页面

功能

  • 播放学习视频
  • 全屏视频播放器
  • 返回按钮

当前问题

  • 硬编码视频路径:/video/xinshou_jiuzhonggoutufa.mp4
  • 未接收路由参数
  • 无法动态切换视频

建议改进

// 应该接收资源ID参数
const route = useRoute()
const resourceId = route.params.id

// 根据资源ID获取视频路径
const videoSrc = getVideoByResourceId(resourceId)

🚀 功能特点

✅ 已实现

  1. 多层级筛选:模块 → 标签 → 子标签
  2. 可视化导航:技能树形式展示
  3. 实时过滤:点击即时更新资源列表
  4. 面包屑导航:清晰显示当前位置
  5. 标签去重:避免重复显示
  6. 展开/折叠:子标签动态显示
  7. 资源计数:显示每个标签的资源数量
  8. 响应式交互:hover、选中等视觉反馈

⚠️ 待完善

  1. 搜索功能:文本搜索未实现
  2. 资源详情:点击资源卡片无响应
  3. 视频播放:未与资源数据关联
  4. 学习进度:无进度追踪
  5. 数据持久化:刷新后状态丢失

💡 优化建议

1. 完善搜索功能

// 在 filteredResources 中添加文本搜索
const filteredResources = computed(() => {
  let resources = /* 现有筛选逻辑 */

  // 添加文本搜索
  if (search.value.trim()) {
    resources = resources.filter(r =>
      r.title.includes(search.value) ||
      r.description?.includes(search.value)
    )
  }

  return resources
})

2. 资源点击跳转

// ResourceList.vue
const handleResourceClick = (resource: ResourceItem) => {
  router.push({
    name: 'SkillVideo',
    params: { id: resource.id }
  })
}

3. 动态视频播放

// video.vue
const route = useRoute()
const resourceId = route.params.id as string
const resource = getAllResources().find(r => r.id === resourceId)
const videoSrc = `/video/${resource?.videoFile || 'default.mp4'}`

4. 学习进度追踪

// 添加到 ResourceItem
interface ResourceItem {
  // ... 现有字段
  completed?: boolean
  progress?: number
  lastViewedAt?: Date
}

5. 状态持久化

// 使用 localStorage 或 Pinia
import { useLocalStorage } from '@vueuse/core'

const selectedModuleId = useLocalStorage('skill-module', null)
const selectedTagId = useLocalStorage('skill-tag', null)

📈 数据扩展建议

1. 添加视频文件字段

interface ResourceItem {
  // ... 现有字段
  videoFile?: string // 视频文件名
  duration?: number // 视频时长(秒)
  difficulty?: 'easy' | 'medium' | 'hard' // 难度
}

2. 添加标签元数据

interface TagMeta {
  id: string
  name: string
  color: string
  icon?: string
  description?: string
}

3. 添加模块元数据

interface ModuleMeta {
  id: string
  name: string
  description: string
  totalResources: number
  completedResources: number
  progress: number
}

🎯 总结

这是一个结构清晰、功能完整的技能树资源浏览系统,核心特点:

  1. 数据驱动:基于一维数组的资源数据,通过工具函数灵活查询
  2. 层级筛选:支持模块→标签→子标签的多层级筛选
  3. 可视化导航:技能树形式直观展示资源结构
  4. 实时反馈:点击即时更新,面包屑导航清晰
  5. 代码整洁:已清理冗余代码,结构简洁明了

主要改进方向是完善搜索、资源详情、视频播放和学习进度追踪功能。