第24篇:学习中心 - 课程体系设计
📚 本篇导读
学习中心是农业应用的重要功能模块,为用户提供系统化的农业知识学习平台。本篇教程将实现一个完整的课程体系,包括课程分类、课程列表、搜索功能等,帮助用户从新手到专家逐步提升种植技能。
本篇将实现:
- 📖 课程分类体系(入门、进阶、专业)
- 📚 课程列表展示(卡片式布局)
- 🔍 课程搜索功能(关键词搜索)
- 📊 学习统计展示(总数、完成数、进行中)
- 🎨 双模式适配(家庭园艺/专业农业)
🎯 学习目标
完成本篇教程后,你将掌握:
- 如何设计课程数据模型
- 如何实现课程分类和筛选
- 如何展示课程列表
- 如何实现搜索功能
- 学习进度的管理方式
一、课程体系架构
1.1 课程分类设计
学习中心
├── 家庭园艺模式
│ ├── 入门基础(新手必学)
│ │ ├── 家庭园艺入门指南
│ │ ├── 认识土壤与培养土
│ │ └── 浇水与施肥基础
│ │
│ ├── 日常养护(日常管理)
│ │ ├── 四季养护要点
│ │ ├── 修剪与造型技巧
│ │ └── 繁殖与扦插方法
│ │
│ ├── 病虫防治(问题解决)
│ │ ├── 常见病虫害识别
│ │ ├── 生态防治方法
│ │ └── 药剂使用指南
│ │
│ └── 进阶技巧(高级技能)
│ ├── 阳台菜园打造
│ ├── 多肉组合盆栽
│ └── 水培与无土栽培
│
└── 专业农业模式
├── 作物种植(核心技术)
│ ├── 小麦种植技术
│ ├── 水稻栽培管理
│ └── 蔬菜大棚技术
│
├── 植保技术(病虫害防治)
│ ├── 病虫害综合防治
│ ├── 农药安全使用
│ └── 生物防治技术
│
├── 农机操作(机械化)
│ ├── 拖拉机操作规范
│ ├── 收割机使用技巧
│ └── 农机维护保养
│
└── 市场营销(经营管理)
├── 农产品销售渠道
├── 品牌建设与推广
└── 电商运营实战
1.2 课程难度分级
| 难度等级 | 适用人群 | 特点 |
|---|---|---|
| 入门级 | 零基础新手 | 基础概念、简单操作、图文并茂 |
| 进阶级 | 有一定经验 | 深入技巧、实战案例、问题解决 |
| 专业级 | 专业从业者 | 系统理论、高级技术、行业标准 |
1.3 课程内容结构
课程
├── 基本信息
│ ├── 课程ID
│ ├── 课程标题
│ ├── 课程分类
│ ├── 难度等级
│ ├── 课程时长
│ └── 课程封面
│
├── 详细信息
│ ├── 课程描述
│ ├── 讲师信息
│ ├── 课程标签
│ └── 适用模式
│
├── 课程内容
│ ├── 课时列表
│ │ ├── 课时标题
│ │ ├── 课时时长
│ │ ├── 课时内容
│ │ └── 完成状态
│ └── 课程资料
│
└── 学习数据
├── 学习进度
├── 完成状态
├── 报名时间
└── 完成时间
二、数据模型设计
2.1 课程数据模型
文件位置 :entry/src/main/ets/models/KnowledgeModels.ets
typescript
/**
* 课程难度枚举
*/
export enum CourseDifficulty {
BEGINNER = 'beginner', // 入门
INTERMEDIATE = 'intermediate', // 进阶
ADVANCED = 'advanced' // 专业
}
/**
* 课程基本信息
*/
export interface Course {
id: string; // 课程ID
title: string; // 课程标题
category: string; // 课程分类
duration: string; // 课程时长
difficulty: CourseDifficulty; // 难度等级
cover: string; // 封面图标
progress: number; // 学习进度 0-100
isCompleted: boolean; // 是否完成
mode: AppMode; // 适用模式
}
/**
* 课程详细信息
*/
export interface CourseDetail extends Course {
description: string; // 课程描述
instructor: string; // 讲师姓名
tags: string[]; // 课程标签
lessons: CourseLesson[]; // 课时列表
}
/**
* 课时信息
*/
export interface CourseLesson {
id: string; // 课时ID
title: string; // 课时标题
duration: string; // 课时时长
content: string; // 课时内容
isCompleted: boolean; // 是否完成
isCurrent: boolean; // 是否当前学习
}
/**
* 学习统计
*/
export interface CourseStats {
total: number; // 总课程数
completed: number; // 已完成数
inProgress: number; // 学习中数
}
模型说明:
Course:课程基本信息,用于列表展示CourseDetail:课程详细信息,包含课时列表CourseLesson:课时信息,课程的最小学习单元CourseStats:学习统计数据
2.2 课程进度数据
typescript
/**
* 课程进度数据结构
*/
interface CourseProgress {
courseId: string; // 课程ID
progress: number; // 进度百分比 0-100
isCompleted: boolean; // 是否完成
completedDate?: number; // 完成时间
enrolledDate?: number; // 报名时间
completedLessons: string[]; // 已完成的课时ID列表
currentLessonId?: string; // 当前正在学习的课时ID
}
三、KnowledgeService 课程服务
3.1 服务类设计
文件位置 :entry/src/main/ets/services/KnowledgeService.ets
typescript
import { AppMode } from '../models/CommonModels';
import { Course, CourseDetail, CourseDifficulty, CourseLesson, CourseStats } from '../models/KnowledgeModels';
import { StorageUtil } from '../utils/StorageUtil';
class KnowledgeService {
// 课程数据存储
private courses: CourseDetail[] = [];
// 进度是否已加载
private isProgressLoaded: boolean = false;
constructor() {
// 初始化静态课程内容
this.initStaticContent();
// 加载学习进度
this.loadProgress();
}
/**
* 初始化静态课程内容
*/
private initStaticContent() {
// 家庭园艺课程
this.courses.push({
id: 'hg_1',
title: '家庭园艺入门指南(上)------新手上路',
category: '入门基础',
duration: '45分钟',
difficulty: CourseDifficulty.BEGINNER,
cover: '🌱',
progress: 0,
isCompleted: false,
mode: AppMode.HOME_GARDENING,
description: '本课程将带你了解家庭园艺的基础知识,从环境评估到工具准备,帮助新手避开常见的坑,轻松开启种植之旅。',
instructor: '林园艺',
tags: ['新手', '基础', '工具', '环境'],
lessons: [
{
id: 'l_1_1',
title: '什么是家庭园艺?',
duration: '5分钟',
isCompleted: false,
isCurrent: true,
content: '家庭园艺是指在室内、阳台、屋顶或庭院等家庭空间内,进行植物栽培和装饰的活动...'
},
{
id: 'l_1_2',
title: '评估你的种植环境(光照、通风)',
duration: '10分钟',
isCompleted: false,
isCurrent: false,
content: '并不是所有植物都适合你的家。在买花之前,最重要的第一步是评估环境...'
}
// ... 更多课时
]
});
// 专业农业课程
this.courses.push({
id: 'pa_1',
title: '小麦种植技术全流程',
category: '作物种植',
duration: '90分钟',
difficulty: CourseDifficulty.INTERMEDIATE,
cover: '🌾',
progress: 0,
isCompleted: false,
mode: AppMode.PROFESSIONAL_AGRICULTURE,
description: '系统讲解小麦从播种到收获的全流程技术要点,包括品种选择、田间管理、病虫害防治等。',
instructor: '张农技',
tags: ['小麦', '粮食作物', '田间管理'],
lessons: [
{
id: 'l_pa_1_1',
title: '小麦品种选择与种子处理',
duration: '15分钟',
isCompleted: false,
isCurrent: true,
content: '选择适合当地气候的小麦品种是成功的第一步...'
}
// ... 更多课时
]
});
}
/**
* 获取课程列表
*/
public getCourses(mode: AppMode): Course[] {
return this.courses
.filter(course => course.mode === mode)
.map(course => ({
id: course.id,
title: course.title,
category: course.category,
duration: course.duration,
difficulty: course.difficulty,
cover: course.cover,
progress: course.progress,
isCompleted: course.isCompleted,
mode: course.mode
}));
}
/**
* 根据ID获取课程详情
*/
public getCourseById(courseId: string): CourseDetail | null {
return this.courses.find(c => c.id === courseId) || null;
}
/**
* 搜索课程
*/
public searchCourses(keyword: string, mode: AppMode): Course[] {
const lowerKeyword = keyword.toLowerCase();
return this.courses
.filter(course =>
course.mode === mode &&
(course.title.toLowerCase().includes(lowerKeyword) ||
course.description.toLowerCase().includes(lowerKeyword) ||
course.tags?.some(tag => tag.toLowerCase().includes(lowerKeyword)))
)
.map(course => ({
id: course.id,
title: course.title,
category: course.category,
duration: course.duration,
difficulty: course.difficulty,
cover: course.cover,
progress: course.progress,
isCompleted: course.isCompleted,
mode: course.mode
}));
}
/**
* 获取课程统计
*/
public getCourseStats(mode: AppMode): CourseStats {
const modeCourses = this.courses.filter(c => c.mode === mode);
return {
total: modeCourses.length,
completed: modeCourses.filter(c => c.isCompleted).length,
inProgress: modeCourses.filter(c => c.progress > 0 && !c.isCompleted).length
};
}
/**
* 加载学习进度
*/
private async loadProgress(): Promise<void> {
if (this.isProgressLoaded) return;
try {
const progressData = await StorageUtil.getObject<CourseProgress[]>('course_progress', []);
// 将进度数据应用到课程
progressData.forEach(progress => {
const course = this.courses.find(c => c.id === progress.courseId);
if (course) {
course.progress = progress.progress;
course.isCompleted = progress.isCompleted;
course.enrolledDate = progress.enrolledDate;
course.completedDate = progress.completedDate;
// 更新课时完成状态
course.lessons.forEach(lesson => {
lesson.isCompleted = progress.completedLessons.includes(lesson.id);
lesson.isCurrent = lesson.id === progress.currentLessonId;
});
}
});
this.isProgressLoaded = true;
console.info('[KnowledgeService] Progress loaded successfully');
} catch (error) {
console.error('[KnowledgeService] Failed to load progress:', error);
}
}
/**
* 保存学习进度
*/
public async saveProgress(courseId: string, progress: CourseProgress): Promise<void> {
try {
const progressData = await StorageUtil.getObject<CourseProgress[]>('course_progress', []);
// 更新或添加进度
const index = progressData.findIndex(p => p.courseId === courseId);
if (index >= 0) {
progressData[index] = progress;
} else {
progressData.push(progress);
}
await StorageUtil.saveObject('course_progress', progressData);
// 同步更新内存中的课程数据
const course = this.courses.find(c => c.id === courseId);
if (course) {
course.progress = progress.progress;
course.isCompleted = progress.isCompleted;
}
console.info('[KnowledgeService] Progress saved for course:', courseId);
} catch (error) {
console.error('[KnowledgeService] Failed to save progress:', error);
}
}
}
// 导出单例
export const knowledgeService = new KnowledgeService();
服务功能说明:
- 课程管理:初始化、获取、搜索课程
- 进度管理:加载、保存学习进度
- 统计功能:计算学习统计数据
- 数据持久化:使用 StorageUtil 存储进度
四、学习中心页面实现
4.1 页面结构设计
文件位置 :entry/src/main/ets/pages/Learning/LearningCenterPage.ets
typescript
import { router } from '@kit.ArkUI';
import { StorageUtil } from '../../utils/StorageUtil';
import { AppMode } from '../../models/CommonModels';
import { Course, CourseStats } from '../../models/KnowledgeModels';
import { knowledgeService } from '../../services/KnowledgeService';
@Entry
@ComponentV2
export struct LearningCenterPage {
@Local userMode: AppMode = AppMode.HOME_GARDENING;
@Local selectedCategory: string = '全部';
@Local courses: Course[] = [];
@Local searchKeyword: string = '';
@Local isSearching: boolean = false;
@Local courseStats: CourseStats = { total: 0, completed: 0, inProgress: 0 };
async aboutToAppear(): Promise<void> {
// 获取用户模式
const mode = await StorageUtil.getString('user_mode', AppMode.HOME_GARDENING);
this.userMode = mode as AppMode;
this.loadCourses();
}
onPageShow(): void {
// 页面显示时重新加载课程(刷新进度)
this.loadCourses();
}
build() {
Column() {
this.buildHeader()
if (!this.isSearching) {
this.buildBanner()
this.buildCategoryTabs()
}
this.buildCourseList()
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.background'))
}
}
4.2 顶部导航栏
typescript
@Builder
buildHeader() {
Row() {
if (this.isSearching) {
// 搜索模式
Search({ value: this.searchKeyword, placeholder: '搜索课程、知识点...' })
.layoutWeight(1)
.searchButton('搜索')
.onSubmit((value: string) => {
this.searchKeyword = value;
this.performSearch();
})
.onChange((value: string) => {
this.searchKeyword = value;
if (value === '') {
this.performSearch();
}
})
.margin({ right: 8 })
Text('取消')
.fontColor(this.userMode === AppMode.HOME_GARDENING ?
$r('app.color.primary_home_gardening') : $r('app.color.primary_professional'))
.onClick(() => {
this.isSearching = false;
this.searchKeyword = '';
this.loadCourses();
})
} else {
// 正常模式
Text(' ')
.width(60)
Text('学习中心')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Button({ type: ButtonType.Circle }) {
Text('🔍')
.fontSize(20)
}
.backgroundColor(Color.Transparent)
.width(40)
.height(40)
.onClick(() => {
this.isSearching = true;
})
}
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.alignItems(VerticalAlign.Center)
}
功能说明:
- 正常模式:显示标题和搜索按钮
- 搜索模式:显示搜索框和取消按钮
- 支持实时搜索和搜索提交
4.3 Banner 横幅
typescript
@Builder
buildBanner() {
Column() {
Text(this.userMode === AppMode.HOME_GARDENING ? '🌱 家庭种植课程' : '🌾 专业农业培训')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
Text(this.userMode === AppMode.HOME_GARDENING ?
'从新手到专家,一步步学习' : '提升专业技能,科学高效种植')
.fontSize(14)
.fontColor(Color.White)
.opacity(0.9)
.margin({ top: 8 })
// 学习统计
Row({ space: 24 }) {
Column({ space: 4 }) {
Text(`${this.courseStats.total}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
Text('总课程')
.fontSize(12)
.fontColor(Color.White)
.opacity(0.8)
}
Column({ space: 4 }) {
Text(`${this.courseStats.completed}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
Text('已完成')
.fontSize(12)
.fontColor(Color.White)
.opacity(0.8)
}
Column({ space: 4 }) {
Text(`${this.courseStats.inProgress}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
Text('学习中')
.fontSize(12)
.fontColor(Color.White)
.opacity(0.8)
}
}
.margin({ top: 16 })
}
.width('100%')
.padding(20)
.linearGradient({
angle: 135,
colors: this.userMode === AppMode.HOME_GARDENING ?
[[0x52C41A, 0.0], [0x389E0D, 1.0]] :
[[0x1890FF, 0.0], [0x096DD9, 1.0]]
})
.borderRadius(12)
.margin({ left: 16, right: 16, top: 16, bottom: 16 })
}
Banner 功能:
- 显示模式标题和描述
- 展示学习统计数据
- 使用渐变背景区分模式
4.4 分类标签
typescript
@Builder
buildCategoryTabs() {
Scroll() {
Row({ space: 8 }) {
this.buildCategoryTab('全部')
if (this.userMode === AppMode.HOME_GARDENING) {
this.buildCategoryTab('入门基础')
this.buildCategoryTab('日常养护')
this.buildCategoryTab('病虫防治')
this.buildCategoryTab('进阶技巧')
} else {
this.buildCategoryTab('作物种植')
this.buildCategoryTab('植保技术')
this.buildCategoryTab('农机操作')
this.buildCategoryTab('市场营销')
}
}
.padding({ left: 16, right: 16 })
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.height(48)
}
@Builder
buildCategoryTab(category: string) {
Text(category)
.fontSize(14)
.fontColor(this.selectedCategory === category ?
Color.White : $r('app.color.text_primary'))
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.backgroundColor(this.selectedCategory === category ?
(this.userMode === AppMode.HOME_GARDENING ?
$r('app.color.primary_home_gardening') : $r('app.color.primary_professional')) :
$r('app.color.card_background'))
.borderRadius(16)
.onClick(() => {
this.selectedCategory = category;
})
}
分类功能:
- 横向滚动的分类标签
- 选中状态高亮显示
- 根据模式显示不同分类
4.5 课程列表
typescript
@Builder
buildCourseList() {
Scroll() {
Column({ space: 12 }) {
if (this.courses.length === 0) {
this.buildEmptyState()
} else {
ForEach(this.getFilteredCourses(), (course: Course) => {
this.buildCourseCard(course)
})
}
}
.padding(16)
}
.layoutWeight(1)
.scrollBar(BarState.Auto)
}
@Builder
buildEmptyState() {
Column() {
Text('🍃')
.fontSize(48)
.margin({ bottom: 16 })
Text('暂无相关课程')
.fontSize(16)
.fontColor($r('app.color.text_secondary'))
}
.width('100%')
.height(300)
.justifyContent(FlexAlign.Center)
}
4.6 课程卡片
typescript
@Builder
buildCourseCard(course: Course) {
Row() {
// 课程封面
Text(course.cover)
.fontSize(48)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
.backgroundColor($r('app.color.background'))
.borderRadius(8)
// 课程信息
Column({ space: 6 }) {
Text(course.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Row({ space: 8 }) {
Text(course.category)
.fontSize(12)
.fontColor($r('app.color.text_tertiary'))
Text('·')
.fontSize(12)
.fontColor($r('app.color.text_tertiary'))
Text(course.duration)
.fontSize(12)
.fontColor($r('app.color.text_tertiary'))
Text('·')
.fontSize(12)
.fontColor($r('app.color.text_tertiary'))
Text(course.difficulty)
.fontSize(12)
.fontColor(this.getDifficultyColor(course.difficulty))
}
// 学习进度
if (course.progress > 0) {
Row() {
Progress({ value: course.progress, total: 100, type: ProgressType.Linear })
.width(120)
.height(4)
.color(this.userMode === AppMode.HOME_GARDENING ?
$r('app.color.primary_home_gardening') : $r('app.color.primary_professional'))
Text(`${course.progress}%`)
.fontSize(12)
.fontColor($r('app.color.text_tertiary'))
.margin({ left: 8 })
}
}
// 完成标记
if (course.isCompleted) {
Row({ space: 4 }) {
Text('✓')
.fontSize(12)
.fontColor('#52C41A')
Text('已完成')
.fontSize(12)
.fontColor('#52C41A')
}
}
}
.layoutWeight(1)
.margin({ left: 12 })
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding(12)
.backgroundColor($r('app.color.card_background'))
.borderRadius(12)
.shadow({ radius: 4, color: $r('app.color.shadow_light'), offsetY: 2 })
.onClick(() => {
router.pushUrl({
url: 'pages/Learning/CourseDetailPage',
params: { courseId: course.id }
});
})
}
/**
* 获取难度颜色
*/
private getDifficultyColor(difficulty: string): string {
const colors: Record<string, string> = {
'入门': '#52C41A',
'中级': '#FA8C16',
'高级': '#F5222D',
'专家': '#722ED1'
};
return colors[difficulty] || '#52C41A';
}
卡片功能:
- 显示课程封面、标题、分类、时长、难度
- 显示学习进度条
- 显示完成状态
- 点击跳转到课程详情
五、数据加载与筛选
5.1 加载课程数据
typescript
/**
* 加载课程列表
*/
private loadCourses(): void {
this.courses = knowledgeService.getCourses(this.userMode);
this.courseStats = knowledgeService.getCourseStats(this.userMode);
console.info('[LearningCenterPage] Courses loaded:', this.courses.length);
}
5.2 搜索功能
typescript
/**
* 执行搜索
*/
private performSearch(): void {
if (this.searchKeyword.trim() === '') {
this.loadCourses();
} else {
this.courses = knowledgeService.searchCourses(this.searchKeyword, this.userMode);
}
}
5.3 分类筛选
typescript
/**
* 获取筛选后的课程
*/
private getFilteredCourses(): Course[] {
if (this.isSearching) {
return this.courses;
}
if (this.selectedCategory === '全部') {
return this.courses;
}
return this.courses.filter(c => c.category === this.selectedCategory);
}
六、实操练习
练习1:添加课程收藏功能
任务:实现课程收藏功能,用户可以收藏感兴趣的课程
提示:
- 在课程卡片上添加收藏按钮
- 使用 StorageUtil 存储收藏列表
- 添加"我的收藏"筛选项
参考代码:
typescript
/**
* 切换收藏状态
*/
private async toggleFavorite(courseId: string): Promise<void> {
const favorites = await StorageUtil.getObject<string[]>('favorite_courses', []);
const index = favorites.indexOf(courseId);
if (index > -1) {
favorites.splice(index, 1);
promptAction.showToast({ message: '已取消收藏' });
} else {
favorites.push(courseId);
promptAction.showToast({ message: '已添加收藏' });
}
await StorageUtil.saveObject('favorite_courses', favorites);
}
练习2:添加课程排序功能
任务:支持按不同维度排序课程列表
提示:
- 添加排序选择器(最新、最热、难度)
- 实现排序逻辑
- 保存用户排序偏好
参考代码:
typescript
/**
* 排序课程
*/
private sortCourses(courses: Course[], sortBy: string): Course[] {
switch (sortBy) {
case '最新':
return courses.sort((a, b) => b.id.localeCompare(a.id));
case '最热':
// 可以根据学习人数排序(需要添加字段)
return courses;
case '难度':
const difficultyOrder = { '入门': 1, '中级': 2, '高级': 3, '专家': 4 };
return courses.sort((a, b) =>
difficultyOrder[a.difficulty] - difficultyOrder[b.difficulty]
);
default:
return courses;
}
}
练习3:添加学习提醒功能
任务:提醒用户继续未完成的课程
提示:
- 检测有进度但未完成的课程
- 在页面顶部显示提醒卡片
- 点击直接跳转到课程
七、常见问题
问题1:课程进度不同步
原因:
- 进度数据未正确保存
- 页面未刷新进度数据
解决方案:
typescript
// 在 onPageShow 中重新加载课程
onPageShow(): void {
console.info('[LearningCenterPage] onPageShow - Reloading courses');
this.loadCourses();
}
// 确保进度保存成功
public async saveProgress(courseId: string, progress: CourseProgress): Promise<void> {
try {
const progressData = await StorageUtil.getObject<CourseProgress[]>('course_progress', []);
const index = progressData.findIndex(p => p.courseId === courseId);
if (index >= 0) {
progressData[index] = progress;
} else {
progressData.push(progress);
}
await StorageUtil.saveObject('course_progress', progressData);
console.info('[KnowledgeService] Progress saved successfully');
} catch (error) {
console.error('[KnowledgeService] Failed to save progress:', error);
throw error;
}
}
问题2:搜索结果不准确
原因:
- 搜索关键词处理不当
- 搜索范围不够全面
解决方案:
typescript
/**
* 改进的搜索功能
*/
public searchCourses(keyword: string, mode: AppMode): Course[] {
// 去除首尾空格并转小写
const lowerKeyword = keyword.trim().toLowerCase();
if (!lowerKeyword) {
return this.getCourses(mode);
}
return this.courses
.filter(course => {
if (course.mode !== mode) return false;
// 搜索标题
if (course.title.toLowerCase().includes(lowerKeyword)) return true;
// 搜索描述
if (course.description.toLowerCase().includes(lowerKeyword)) return true;
// 搜索标签
if (course.tags?.some(tag => tag.toLowerCase().includes(lowerKeyword))) return true;
// 搜索分类
if (course.category.toLowerCase().includes(lowerKeyword)) return true;
// 搜索讲师
if (course.instructor.toLowerCase().includes(lowerKeyword)) return true;
return false;
})
.map(course => ({
id: course.id,
title: course.title,
category: course.category,
duration: course.duration,
difficulty: course.difficulty,
cover: course.cover,
progress: course.progress,
isCompleted: course.isCompleted,
mode: course.mode
}));
}
问题3:课程数据加载慢
原因:
- 课程数据量大
- 每次都重新加载
解决方案:
typescript
class KnowledgeService {
private courses: CourseDetail[] = [];
private isInitialized: boolean = false;
private initPromise: Promise<void> | null = null;
/**
* 延迟初始化
*/
private async ensureInitialized(): Promise<void> {
if (this.isInitialized) return;
if (this.initPromise) {
return this.initPromise;
}
this.initPromise = (async () => {
this.initStaticContent();
await this.loadProgress();
this.isInitialized = true;
console.info('[KnowledgeService] Initialization completed');
})();
return this.initPromise;
}
/**
* 获取课程列表(确保已初始化)
*/
public async getCourses(mode: AppMode): Promise<Course[]> {
await this.ensureInitialized();
return this.courses
.filter(course => course.mode === mode)
.map(course => ({
id: course.id,
title: course.title,
category: course.category,
duration: course.duration,
difficulty: course.difficulty,
cover: course.cover,
progress: course.progress,
isCompleted: course.isCompleted,
mode: course.mode
}));
}
}
八、功能扩展建议
1. 课程推荐系统
功能描述:
- 基于学习历史推荐相关课程
- 推荐同类型热门课程
- 推荐适合当前水平的课程
实现思路:
typescript
/**
* 获取推荐课程
*/
public getRecommendedCourses(userId: string, mode: AppMode): Course[] {
const userCourses = this.getUserCompletedCourses(userId);
const recommendations: Course[] = [];
// 1. 推荐同分类的课程
userCourses.forEach(course => {
const sameCategoryCourses = this.courses.filter(c =>
c.mode === mode &&
c.category === course.category &&
c.id !== course.id &&
!userCourses.some(uc => uc.id === c.id)
);
recommendations.push(...sameCategoryCourses);
});
// 2. 推荐进阶课程
const userLevel = this.getUserLevel(userCourses);
const nextLevelCourses = this.courses.filter(c =>
c.mode === mode &&
this.getDifficultyLevel(c.difficulty) === userLevel + 1
);
recommendations.push(...nextLevelCourses);
// 去重并限制数量
return Array.from(new Set(recommendations)).slice(0, 5);
}
2. 学习路径规划
功能描述:
- 为用户规划学习路径
- 显示前置课程要求
- 推荐学习顺序
实现思路:
typescript
/**
* 学习路径接口
*/
interface LearningPath {
id: string;
name: string;
description: string;
courses: string[]; // 课程ID列表(按顺序)
estimatedDuration: string;
}
/**
* 获取学习路径
*/
public getLearningPaths(mode: AppMode): LearningPath[] {
if (mode === AppMode.HOME_GARDENING) {
return [
{
id: 'path_beginner',
name: '新手入门路径',
description: '从零开始学习家庭园艺',
courses: ['hg_1', 'hg_2', 'hg_3'],
estimatedDuration: '3小时'
},
{
id: 'path_advanced',
name: '进阶提升路径',
description: '掌握高级种植技巧',
courses: ['hg_4', 'hg_5', 'hg_6'],
estimatedDuration: '5小时'
}
];
} else {
return [
{
id: 'path_crop',
name: '作物种植专业路径',
description: '系统学习作物种植技术',
courses: ['pa_1', 'pa_2', 'pa_3'],
estimatedDuration: '8小时'
}
];
}
}
3. 学习笔记功能
功能描述:
- 在学习过程中记录笔记
- 标记重点内容
- 导出学习笔记
4. 学习社区功能
功能描述:
- 课程评论和讨论
- 学习心得分享
- 问题求助和解答
九、本篇总结
9.1 核心知识点
本篇教程完整实现了学习中心的课程体系,涵盖以下核心内容:
-
课程体系设计
- 分类体系规划
- 难度等级划分
- 课程内容结构
-
数据模型设计
- Course 课程模型
- CourseLesson 课时模型
- CourseProgress 进度模型
-
服务层实现
- KnowledgeService 课程服务
- 课程管理功能
- 进度管理功能
- 搜索和筛选功能
-
UI组件开发
- 课程列表展示
- 分类标签筛选
- 搜索功能
- 学习统计展示
-
双模式适配
- 家庭园艺模式
- 专业农业模式
- 动态内容切换
9.2 技术要点
- ✅ 数据持久化:使用 StorageUtil 存储学习进度
- ✅ 状态管理:@Local 装饰器管理页面状态
- ✅ 列表渲染:ForEach 高效渲染课程列表
- ✅ 搜索功能:实时搜索和关键词匹配
- ✅ 分类筛选:多维度筛选课程
- ✅ 进度展示:Progress 组件显示学习进度
9.3 实际应用价值
学习中心系统解决了以下实际问题:
- 系统化学习:提供结构化的学习内容
- 个性化推荐:根据用户水平推荐课程
- 进度跟踪:记录和展示学习进度
- 知识检索:快速查找所需知识
- 技能提升:帮助用户逐步提升种植技能
9.4 下一篇预告
第25篇:学习中心 - 课程详情与学习
下一篇将实现课程详情和学习功能,包括:
- 📖 课程详情页面设计
- 📚 课时列表展示
- ▶️ 课时学习页面
- ✅ 学习进度更新
- 📝 学习笔记功能
附录:完整代码文件清单
模型层
entry/src/main/ets/models/KnowledgeModels.ets- 课程数据模型
服务层
entry/src/main/ets/services/KnowledgeService.ets- 课程服务
页面层
entry/src/main/ets/pages/Learning/LearningCenterPage.ets- 学习中心页面