482 lines
12 KiB
Markdown
482 lines
12 KiB
Markdown
# 📚 Skill 功能架构完整分析
|
||
|
||
## 🗂️ 文件结构(已清理)
|
||
|
||
```
|
||
src/views/skill/
|
||
├── index.vue # 主页面 - 技能树资源浏览器
|
||
├── resourceData.ts # 数据层 - 资源数据管理
|
||
├── video.vue # 视频播放页面
|
||
└── components/
|
||
├── SkillTree.vue # 技能树可视化组件
|
||
├── SearchTags.vue # 搜索面包屑标签
|
||
└── ResourceList.vue # 资源列表展示
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 核心功能定位
|
||
|
||
**技能树资源浏览系统** - 一个基于树形结构的学习资源导航和筛选平台
|
||
|
||
---
|
||
|
||
## 📊 数据架构
|
||
|
||
### 1. 数据层级结构
|
||
|
||
```
|
||
模块 (Module)
|
||
└─ 标签 (Tag)
|
||
└─ 子标签 (SubTag)
|
||
└─ 资源 (Resource)
|
||
```
|
||
|
||
### 2. 数据实体
|
||
|
||
#### ResourceItem 接口
|
||
|
||
```typescript
|
||
{
|
||
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. 工具函数
|
||
|
||
```typescript
|
||
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. 状态管理
|
||
|
||
```typescript
|
||
// 核心状态
|
||
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(面包屑)
|
||
|
||
```typescript
|
||
根据选择状态生成面包屑数组:
|
||
- 选中模块 → 添加模块标签(蓝色)
|
||
- 选中标签 → 添加标签标签(橙色)
|
||
- 选中子标签 → 添加子标签标签(紫色)
|
||
```
|
||
|
||
#### filteredResources(资源过滤)
|
||
|
||
```typescript
|
||
优先级:子标签 > 标签 > 模块 > 全部
|
||
1. 如果选中子标签 → 返回子标签的资源
|
||
2. 否则如果选中标签 → 返回标签的资源
|
||
3. 否则如果选中模块 → 返回模块的资源
|
||
4. 否则 → 返回所有资源
|
||
```
|
||
|
||
---
|
||
|
||
## 🌳 技能树组件详解
|
||
|
||
### 1. 核心功能
|
||
|
||
- **标签去重**:使用 `displayedTags` 计算属性,通过 `moduleId-tagId` 作为唯一键去重
|
||
- **位置布局**:14个预定义位置,形成树形分布
|
||
- **颜色映射**:根据标签名称返回不同颜色
|
||
- **展开/折叠**:有子标签的标签可以展开显示子标签列表
|
||
- **数字徽章**:显示每个标签下的资源数量
|
||
|
||
### 2. 标签位置分布
|
||
|
||
```typescript
|
||
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. 标签样式
|
||
|
||
```css
|
||
基础样式:
|
||
- 圆角矩形: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)
|
||
- 空状态提示
|
||
|
||
### 资源卡片样式
|
||
|
||
```css
|
||
- 半透明蓝色背景:bg-blue-500/20
|
||
- 圆角:rounded
|
||
- 内边距:p-4
|
||
- hover效果:bg-blue-500/30
|
||
- 标题:text-2xl font-bold
|
||
- 描述:text-lg text-gray-300
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 搜索标签组件
|
||
|
||
### 功能
|
||
|
||
- 显示当前选择路径(面包屑导航)
|
||
- 不同类型不同颜色
|
||
|
||
### 标签样式
|
||
|
||
```css
|
||
- 圆角胶囊: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`
|
||
- 未接收路由参数
|
||
- 无法动态切换视频
|
||
|
||
### 建议改进
|
||
|
||
```typescript
|
||
// 应该接收资源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. 完善搜索功能
|
||
|
||
```typescript
|
||
// 在 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. 资源点击跳转
|
||
|
||
```typescript
|
||
// ResourceList.vue
|
||
const handleResourceClick = (resource: ResourceItem) => {
|
||
router.push({
|
||
name: 'SkillVideo',
|
||
params: { id: resource.id }
|
||
})
|
||
}
|
||
```
|
||
|
||
### 3. 动态视频播放
|
||
|
||
```typescript
|
||
// 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. 学习进度追踪
|
||
|
||
```typescript
|
||
// 添加到 ResourceItem
|
||
interface ResourceItem {
|
||
// ... 现有字段
|
||
completed?: boolean
|
||
progress?: number
|
||
lastViewedAt?: Date
|
||
}
|
||
```
|
||
|
||
### 5. 状态持久化
|
||
|
||
```typescript
|
||
// 使用 localStorage 或 Pinia
|
||
import { useLocalStorage } from '@vueuse/core'
|
||
|
||
const selectedModuleId = useLocalStorage('skill-module', null)
|
||
const selectedTagId = useLocalStorage('skill-tag', null)
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 数据扩展建议
|
||
|
||
### 1. 添加视频文件字段
|
||
|
||
```typescript
|
||
interface ResourceItem {
|
||
// ... 现有字段
|
||
videoFile?: string // 视频文件名
|
||
duration?: number // 视频时长(秒)
|
||
difficulty?: 'easy' | 'medium' | 'hard' // 难度
|
||
}
|
||
```
|
||
|
||
### 2. 添加标签元数据
|
||
|
||
```typescript
|
||
interface TagMeta {
|
||
id: string
|
||
name: string
|
||
color: string
|
||
icon?: string
|
||
description?: string
|
||
}
|
||
```
|
||
|
||
### 3. 添加模块元数据
|
||
|
||
```typescript
|
||
interface ModuleMeta {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
totalResources: number
|
||
completedResources: number
|
||
progress: number
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 总结
|
||
|
||
这是一个**结构清晰、功能完整的技能树资源浏览系统**,核心特点:
|
||
|
||
1. **数据驱动**:基于一维数组的资源数据,通过工具函数灵活查询
|
||
2. **层级筛选**:支持模块→标签→子标签的多层级筛选
|
||
3. **可视化导航**:技能树形式直观展示资源结构
|
||
4. **实时反馈**:点击即时更新,面包屑导航清晰
|
||
5. **代码整洁**:已清理冗余代码,结构简洁明了
|
||
|
||
主要改进方向是完善搜索、资源详情、视频播放和学习进度追踪功能。
|