
鸿蒙编程学习助手应用开发指南 原创
鸿蒙编程学习助手应用开发指南
一、系统架构设计
基于HarmonyOS的分布式能力和AI技术,我们设计了一套交互式编程学习系统,主要功能包括:
代码练习:提供交互式编程练习环境
智能指导:AI分析代码并提供实时反馈
多设备协同:跨设备同步学习进度和代码
课程管理:组织编程课程和学习路径
成就系统:激励用户完成学习目标
!https://example.com/harmony-code-learning-arch.png
二、核心代码实现
代码执行服务
// CodeExecutionService.ets
import codeRunner from ‘@ohos.codeRunner’;
class CodeExecutionService {
private static instance: CodeExecutionService;
private runner: codeRunner.CodeRunner;
private constructor() {
this.runner = codeRunner.createRunner();
public static getInstance(): CodeExecutionService {
if (!CodeExecutionService.instance) {
CodeExecutionService.instance = new CodeExecutionService();
return CodeExecutionService.instance;
public async executeCode(code: string, language: string): Promise<ExecutionResult> {
return new Promise((resolve, reject) => {
this.runner.run(
code,
language,
timeout: 5000
},
(err, result) => {
if (err) {
reject(err);
else {
resolve(this.processResult(result));
}
);
});
private processResult(rawData: any): ExecutionResult {
return {
output: rawData.output || '',
errors: rawData.errors || [],
warnings: rawData.warnings || [],
executionTime: rawData.executionTime || 0,
memoryUsage: rawData.memoryUsage || 0,
success: rawData.success || false
};
public async checkCodeStyle(code: string, language: string): Promise<CodeStyleReport> {
return new Promise((resolve, reject) => {
this.runner.analyze(
code,
language,
checks: ['style', 'complexity']
},
(err, report) => {
if (err) {
reject(err);
else {
resolve(this.processStyleReport(report));
}
);
});
private processStyleReport(rawData: any): CodeStyleReport {
return {
issues: rawData.issues || [],
complexity: rawData.complexity || 0,
readability: rawData.readability || 0,
styleScore: rawData.styleScore || 0
};
}
export const codeExecutionService = CodeExecutionService.getInstance();
学习进度服务
// LearningProgressService.ets
import distributedData from ‘@ohos.data.distributedData’;
class LearningProgressService {
private static instance: LearningProgressService;
private kvManager: distributedData.KVManager;
private kvStore: distributedData.KVStore;
private constructor() {
this.initKVStore();
private async initKVStore(): Promise<void> {
const config = {
bundleName: 'com.example.codeLearning',
userInfo: { userId: 'currentUser' }
};
this.kvManager = distributedData.createKVManager(config);
this.kvStore = await this.kvManager.getKVStore('learning_progress', {
createIfMissing: true
});
this.kvStore.on('dataChange', (data) => {
this.handleRemoteUpdate(data);
});
public static getInstance(): LearningProgressService {
if (!LearningProgressService.instance) {
LearningProgressService.instance = new LearningProgressService();
return LearningProgressService.instance;
public async saveProgress(progress: LearningProgress): Promise<void> {
await this.kvStore.put(progress_${progress.courseId}, JSON.stringify(progress));
public async getProgress(courseId: string): Promise<LearningProgress | null> {
const value = await this.kvStore.get(progress_${courseId});
return value ? JSON.parse(value) : null;
public async getCompletedLessons(courseId: string): Promise<string[]> {
const progress = await this.getProgress(courseId);
return progress?.completedLessons || [];
public async completeLesson(courseId: string, lessonId: string): Promise<void> {
const progress = await this.getProgress(courseId) || {
courseId,
completedLessons: [],
lastAccessed: Date.now()
};
if (!progress.completedLessons.includes(lessonId)) {
progress.completedLessons.push(lessonId);
progress.lastAccessed = Date.now();
await this.saveProgress(progress);
}
public async syncProgressToDevice(deviceId: string): Promise<void> {
const entries = await this.kvStore.getEntries(‘progress_’);
const ability = await featureAbility.startAbility({
bundleName: ‘com.example.codeLearning’,
abilityName: ‘ProgressSyncAbility’,
deviceId
});
await ability.call({
method: 'receiveProgressData',
parameters: [Array.from(entries)]
});
private handleRemoteUpdate(data: distributedData.ChangeInfo): void {
if (data.deviceId === deviceInfo.deviceId) return;
const key = data.key as string;
if (key.startsWith('progress_')) {
const progress = JSON.parse(data.value);
EventBus.emit('progressUpdated', progress);
}
export const progressService = LearningProgressService.getInstance();
AI代码分析服务
// CodeAnalysisService.ets
import http from ‘@ohos.net.http’;
class CodeAnalysisService {
private static instance: CodeAnalysisService;
private httpClient: http.HttpRequest;
private apiKey = ‘YOUR_CODE_ANALYSIS_API_KEY’;
private constructor() {
this.httpClient = http.createHttp();
public static getInstance(): CodeAnalysisService {
if (!CodeAnalysisService.instance) {
CodeAnalysisService.instance = new CodeAnalysisService();
return CodeAnalysisService.instance;
public async analyzeCode(code: string, language: string): Promise<CodeAnalysis> {
return new Promise((resolve, reject) => {
this.httpClient.request(
'https://code-analysis-api.example.com/analyze',
method: ‘POST’,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify({
code,
language,
api_key: this.apiKey
})
},
(err, data) => {
if (err) {
reject(err);
else {
const result = JSON.parse(data.result);
resolve(this.processAnalysisResult(result));
}
);
});
private processAnalysisResult(rawData: any): CodeAnalysis {
return {
qualityScore: rawData.qualityScore || 0,
issues: rawData.issues?.map((issue: any) => ({
type: issue.type,
message: issue.message,
line: issue.line,
column: issue.column,
severity: issue.severity,
suggestion: issue.suggestion
})) || [],
complexity: rawData.complexity || 0,
maintainability: rawData.maintainability || 0,
bestPractices: rawData.bestPractices || []
};
public async explainCode(code: string, language: string): Promise<CodeExplanation> {
return new Promise((resolve, reject) => {
this.httpClient.request(
'https://code-analysis-api.example.com/explain',
method: ‘POST’,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify({
code,
language,
api_key: this.apiKey
})
},
(err, data) => {
if (err) {
reject(err);
else {
const result = JSON.parse(data.result);
resolve(this.processExplanationResult(result));
}
);
});
private processExplanationResult(rawData: any): CodeExplanation {
return {
overview: rawData.overview || '',
lineByLine: rawData.lineByLine || [],
keyConcepts: rawData.keyConcepts || [],
relatedTopics: rawData.relatedTopics || []
};
public async suggestImprovement(code: string, language: string): Promise<CodeImprovement> {
return new Promise((resolve, reject) => {
this.httpClient.request(
'https://code-analysis-api.example.com/improve',
method: ‘POST’,
header: { 'Content-Type': 'application/json' },
extraData: JSON.stringify({
code,
language,
api_key: this.apiKey
})
},
(err, data) => {
if (err) {
reject(err);
else {
const result = JSON.parse(data.result);
resolve(this.processImprovementResult(result));
}
);
});
private processImprovementResult(rawData: any): CodeImprovement {
return {
improvedCode: rawData.improvedCode || '',
changes: rawData.changes || [],
benefits: rawData.benefits || [],
beforeMetrics: rawData.beforeMetrics || {},
afterMetrics: rawData.afterMetrics || {}
};
}
export const codeAnalysisService = CodeAnalysisService.getInstance();
三、主界面实现
代码练习界面
// CodePracticeView.ets
@Component
struct CodePracticeView {
@State currentLesson: Lesson | null = null;
@State userCode: string = ‘’;
@State executionResult: ExecutionResult | null = null;
@State analysisResult: CodeAnalysis | null = null;
@State isRunning: boolean = false;
@State isAnalyzing: boolean = false;
aboutToAppear() {
this.loadLesson();
build() {
Column() {
if (!this.currentLesson) {
LoadingProgress()
.width(50)
.height(50)
.margin({ top: 32 })
else {
// 课程标题和描述
Text(this.currentLesson.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(this.currentLesson.description)
.fontSize(16)
.margin({ top: 8 })
// 代码编辑器
CodeEditor({
code: this.userCode,
language: this.currentLesson.language,
onCodeChange: (code) => this.userCode = code
})
.height(300)
.margin({ top: 16 })
// 操作按钮
Row() {
Button('运行代码')
.onClick(() => this.runCode())
.enabled(!this.isRunning)
.margin({ right: 8 })
Button('代码分析')
.onClick(() => this.analyzeCode())
.enabled(!this.isAnalyzing)
.margin({ top: 16 })
// 执行结果
if (this.executionResult) {
ExecutionResultView({ result: this.executionResult })
.margin({ top: 16 })
// 分析结果
if (this.analysisResult) {
CodeAnalysisView({ analysis: this.analysisResult })
.margin({ top: 16 })
// 完成课程按钮
if (this.isLessonComplete()) {
Button('完成课程')
.onClick(() => this.completeLesson())
.margin({ top: 16 })
}
.padding(16)
private async loadLesson(): Promise<void> {
const lessonId = router.getParams()?.lessonId;
if (lessonId) {
this.currentLesson = await courseService.getLesson(lessonId);
this.userCode = this.currentLesson?.initialCode || '';
}
private async runCode(): Promise<void> {
if (!this.currentLesson || !this.userCode) return;
this.isRunning = true;
try {
this.executionResult = await codeExecutionService.executeCode(
this.userCode,
this.currentLesson.language
);
finally {
this.isRunning = false;
}
private async analyzeCode(): Promise<void> {
if (!this.currentLesson || !this.userCode) return;
this.isAnalyzing = true;
try {
this.analysisResult = await codeAnalysisService.analyzeCode(
this.userCode,
this.currentLesson.language
);
finally {
this.isAnalyzing = false;
}
private isLessonComplete(): boolean {
if (!this.currentLesson || !this.executionResult) return false;
// 检查是否满足课程完成条件
return this.currentLesson.successCondition.type === 'output'
this.executionResult.output.includes(this.currentLesson.successCondition.value)
this.executionResult.success;
private async completeLesson(): Promise<void> {
if (!this.currentLesson) return;
await progressService.completeLesson(
this.currentLesson.courseId,
this.currentLesson.id
);
router.back();
}
@Component
struct CodeEditor {
@State code: string;
private language: string;
private onCodeChange: (code: string) => void;
build() {
// 简化实现,实际应使用代码编辑器组件
TextArea({ text: this.code })
.onChange((value: string) => this.onCodeChange(value))
.fontSize(14)
.fontFamily(‘monospace’)
}
@Component
struct ExecutionResultView {
private result: ExecutionResult;
build() {
Column() {
Text(this.result.success ? ‘执行成功’ : ‘执行失败’)
.fontSize(18)
.fontColor(this.result.success ? ‘#4CAF50’ : ‘#F44336’)
if (this.result.output) {
Text('输出:')
.fontSize(16)
.margin({ top: 8 })
Text(this.result.output)
.fontSize(14)
.fontFamily('monospace')
.backgroundColor('#F5F5F5')
.padding(8)
if (this.result.errors.length > 0) {
Text('错误:')
.fontSize(16)
.margin({ top: 8 })
ForEach(this.result.errors, (error) => {
Text(error)
.fontSize(14)
.fontColor('#F44336')
.fontFamily('monospace')
.margin({ top: 4 })
})
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)
}
@Component
struct CodeAnalysisView {
private analysis: CodeAnalysis;
build() {
Column() {
Text(代码质量评分: ${this.analysis.qualityScore.toFixed(1)}/10)
.fontSize(18)
.fontColor(this.getScoreColor(this.analysis.qualityScore))
Row() {
Text(复杂度: ${this.analysis.complexity.toFixed(1)})
.fontSize(14)
.margin({ right: 16 })
Text(可维护性: ${this.analysis.maintainability.toFixed(1)})
.fontSize(14)
.margin({ top: 8 })
if (this.analysis.issues.length > 0) {
Text('发现问题:')
.fontSize(16)
.margin({ top: 16 })
ForEach(this.analysis.issues, (issue) => {
Column() {
Row() {
Text({issue.line}:{issue.column})
.fontSize(12)
.fontColor('#666666')
Text(issue.type)
.fontSize(12)
.fontColor(this.getSeverityColor(issue.severity))
.margin({ left: 8 })
Text(issue.message)
.fontSize(14)
.margin({ top: 4 })
if (issue.suggestion) {
Text(建议: ${issue.suggestion})
.fontSize(12)
.fontColor('#4CAF50')
.margin({ top: 4 })
}
.padding(8)
.margin({ top: 8 })
.backgroundColor('#FAFAFA')
.borderRadius(4)
})
if (this.analysis.bestPractices.length > 0) {
Text('最佳实践:')
.fontSize(16)
.margin({ top: 16 })
ForEach(this.analysis.bestPractices, (practice) => {
Text(• ${practice})
.fontSize(14)
.margin({ top: 4 })
})
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)
private getScoreColor(score: number): string {
if (score >= 8) return '#4CAF50';
if (score >= 5) return '#FFC107';
return '#F44336';
private getSeverityColor(severity: string): string {
const colors: Record<string, string> = {
critical: '#F44336',
high: '#FF5722',
medium: '#FF9800',
low: '#2196F3',
info: '#607D8B'
};
return colors[severity.toLowerCase()] || '#000000';
}
课程列表界面
// CourseListView.ets
@Component
struct CourseListView {
@State courses: Course[] = [];
@State searchQuery: string = ‘’;
aboutToAppear() {
this.loadCourses();
build() {
Column() {
Text('编程课程')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 16 })
// 搜索框
TextInput({ placeholder: '搜索课程...' })
.onChange((value: string) => this.searchQuery = value)
.margin({ top: 16 })
if (this.courses.length === 0) {
Text('加载中...')
.fontSize(16)
.margin({ top: 32 })
else {
List({ space: 10 }) {
ForEach(this.filteredCourses, (course) => {
ListItem() {
CourseItem({ course })
})
.layoutWeight(1)
}
.padding(16)
private async loadCourses(): Promise<void> {
this.courses = await courseService.getAllCourses();
private get filteredCourses(): Course[] {
if (!this.searchQuery) return this.courses;
const query = this.searchQuery.toLowerCase();
return this.courses.filter(course =>
course.title.toLowerCase().includes(query) |
course.description.toLowerCase().includes(query)
|
course.tags.some(tag => tag.toLowerCase().includes(query))
);
}
@Component
struct CourseItem {
private course: Course;
@State progress: number = 0;
aboutToAppear() {
this.loadProgress();
build() {
Row() {
Image(this.course.image || 'resources/default_course.png')
.width(80)
.height(80)
.borderRadius(8)
.margin({ right: 12 })
Column() {
Text(this.course.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(this.course.description)
.fontSize(14)
.maxLines(2)
.margin({ top: 4 })
Row() {
ForEach(this.course.tags.slice(0, 3), (tag) => {
Text(tag)
.fontSize(12)
.padding(4)
.backgroundColor('#E3F2FD')
.borderRadius(4)
.margin({ right: 4 })
})
.margin({ top: 8 })
if (this.progress > 0) {
Progress({
value: this.progress,
total: 100,
type: ProgressType.PROGRESS_TYPE_LINEAR
})
.width('100%')
.margin({ top: 8 })
Text(${Math.round(this.progress)}% 已完成)
.fontSize(12)
.fontColor('#666666')
.margin({ top: 4 })
}
.layoutWeight(1)
.padding(12)
.onClick(() => {
router.push({ url: pages/course?courseId=${this.course.id} });
})
private async loadProgress(): Promise<void> {
const progress = await progressService.getProgress(this.course.id);
if (progress) {
const totalLessons = await courseService.getLessonCount(this.course.id);
this.progress = (progress.completedLessons.length / totalLessons) * 100;
}
课程详情界面
// CourseDetailView.ets
@Component
struct CourseDetailView {
@State course: Course | null = null;
@State lessons: Lesson[] = [];
@State progress: LearningProgress | null = null;
aboutToAppear() {
this.loadCourse();
EventBus.on(‘progressUpdated’, () => this.loadProgress());
build() {
Column() {
if (!this.course) {
LoadingProgress()
.width(50)
.height(50)
.margin({ top: 32 })
else {
// 课程封面和标题
Image(this.course.image || 'resources/default_course.png')
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
Text(this.course.title)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 16 })
Text(this.course.description)
.fontSize(16)
.margin({ top: 8 })
// 课程标签
Row() {
ForEach(this.course.tags, (tag) => {
Text(tag)
.fontSize(12)
.padding(6)
.backgroundColor('#E3F2FD')
.borderRadius(12)
.margin({ right: 8 })
})
.margin({ top: 16 })
// 课程进度
if (this.progress) {
Row() {
Text('学习进度:')
.fontSize(16)
Text({this.progress.completedLessons.length}/{this.lessons.length}课)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ left: 8 })
.margin({ top: 16 })
Progress({
value: (this.progress.completedLessons.length / this.lessons.length) * 100,
total: 100,
type: ProgressType.PROGRESS_TYPE_LINEAR
})
.width('100%')
.margin({ top: 8 })
// 课程章节
Text('课程内容')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 24 })
if (this.lessons.length === 0) {
Text('暂无课程内容')
.fontSize(16)
.margin({ top: 32 })
else {
List({ space: 10 }) {
ForEach(this.lessons, (lesson) => {
ListItem() {
LessonItem({
lesson,
isCompleted: this.progress?.completedLessons.includes(lesson.id) || false
})
})
.layoutWeight(1)
}
.padding(16)
private async loadCourse(): Promise<void> {
const courseId = router.getParams()?.courseId;
if (courseId) {
this.course = await courseService.getCourse(courseId);
this.lessons = await courseService.getLessons(courseId);
this.loadProgress();
}
private async loadProgress(): Promise<void> {
if (!this.course) return;
this.progress = await progressService.getProgress(this.course.id);
}
@Component
struct LessonItem {
private lesson: Lesson;
private isCompleted: boolean;
build() {
Row() {
Column() {
Text(this.lesson.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(this.isCompleted ? ‘#4CAF50’ : ‘#000000’)
Text(this.lesson.description)
.fontSize(14)
.maxLines(2)
.margin({ top: 4 })
.layoutWeight(1)
if (this.isCompleted) {
Image('resources/checkmark.png')
.width(24)
.height(24)
}
.padding(12)
.onClick(() => {
router.push({ url: pages/lesson?lessonId=${this.lesson.id} });
})
}
四、高级功能实现
多设备学习同步
// LearningSyncService.ets
import deviceManager from ‘@ohos.distributedHardware.deviceManager’;
class LearningSyncService {
private static instance: LearningSyncService;
private constructor() {}
public static getInstance(): LearningSyncService {
if (!LearningSyncService.instance) {
LearningSyncService.instance = new LearningSyncService();
return LearningSyncService.instance;
public async syncAllProgressToDevice(deviceId: string): Promise<void> {
const progressData = await progressService.getAllProgress();
const ability = await featureAbility.startAbility({
bundleName: 'com.example.codeLearning',
abilityName: 'ProgressSyncAbility',
deviceId
});
await ability.call({
method: 'receiveAllProgress',
parameters: [progressData]
});
public async syncCourseProgressToDevice(deviceId: string, courseId: string): Promise<void> {
const progress = await progressService.getProgress(courseId);
if (!progress) return;
const ability = await featureAbility.startAbility({
bundleName: 'com.example.codeLearning',
abilityName: 'CourseProgressAbility',
deviceId
});
await ability.call({
method: 'receiveCourseProgress',
parameters: [progress]
});
public async syncCodeToDevice(deviceId: string, code: CodeSnippet): Promise<void> {
const ability = await featureAbility.startAbility({
bundleName: 'com.example.codeLearning',
abilityName: 'CodeSyncAbility',
deviceId
});
await ability.call({
method: 'receiveCodeSnippet',
parameters: [code]
});
public async requestProgressFromDevice(deviceId: string): Promise<LearningProgress[]> {
const ability = await featureAbility.startAbility({
bundleName: 'com.example.codeLearning',
abilityName: 'ProgressRequestAbility',
deviceId
});
const result = await ability.call({
method: 'getAllProgress',
parameters: []
});
return JSON.parse(result);
}
export const learningSyncService = LearningSyncService.getInstance();
智能代码推荐
// CodeRecommendationService.ets
class CodeRecommendationService {
private static instance: CodeRecommendationService;
private constructor() {}
public static getInstance(): CodeRecommendationService {
if (!CodeRecommendationService.instance) {
CodeRecommendationService.instance = new CodeRecommendationService();
return CodeRecommendationService.instance;
public async recommendCode(lesson: Lesson, userCode: string): Promise<CodeRecommendation[]> {
const analysis = await codeAnalysisService.analyzeCode(userCode, lesson.language);
const recommendations: CodeRecommendation[] = [];
// 根据常见问题推荐
analysis.issues.forEach(issue => {
recommendations.push({
type: 'fix',
description: issue.message,
code: issue.suggestion || '',
priority: this.getIssuePriority(issue.severity)
});
});
// 根据最佳实践推荐
lesson.bestPractices.forEach(practice => {
if (!userCode.includes(practice.pattern)) {
recommendations.push({
type: 'improvement',
description: practice.description,
code: practice.example,
priority: 'medium'
});
});
// 根据课程目标推荐
if (lesson.successCondition.type === 'pattern' &&
!userCode.includes(lesson.successCondition.value)) {
recommendations.push({
type: 'hint',
description: '尝试使用课程要求的模式',
code: lesson.successHint || '',
priority: 'high'
});
return recommendations.sort(this.sortRecommendations);
private getIssuePriority(severity: string): string {
const priorityMap: Record<string, string> = {
critical: 'high',
high: 'high',
medium: 'medium',
low: 'low',
info: 'low'
};
return priorityMap[severity] || 'medium';
private sortRecommendations(a: CodeRecommendation, b: CodeRecommendation): number {
const priorityOrder: Record<string, number> = {
high: 3,
medium: 2,
low: 1
};
return (priorityOrder[b.priority] |0) - (priorityOrder[a.priority]
| 0);
public async generateChallenge(language: string, level: number): Promise<CodeChallenge> {
const challenges: Record<string, CodeChallenge[]> = {
'javascript': [
id: ‘js-challenge-1’,
title: '数组去重',
description: '编写一个函数,去除数组中的重复元素',
difficulty: 'easy',
starterCode: 'function unique(arr) {\n // 你的代码\n}',
testCases: [
input: ‘[1,2,2,3]’, output: ‘[1,2,3]’ },
input: ‘[“a”,“b”,“a”]’, output: ‘[“a”,“b”]’ }
},
id: ‘js-challenge-2’,
title: '深拷贝对象',
description: '实现一个对象的深拷贝函数',
difficulty: 'medium',
starterCode: 'function deepClone(obj) {\n // 你的代码\n}',
testCases: [
input: ‘{a:1,b:{c:2}}’, output: ‘{“a”:1,“b”:{“c”:2}}’ }
}
],
'python': [
id: ‘py-challenge-1’,
title: '斐波那契数列',
description: '生成斐波那契数列的前n项',
difficulty: 'easy',
starterCode: 'def fibonacci(n):\n # 你的代码',
testCases: [
input: ‘5’, output: ‘[0,1,1,2,3]’ },
input: ‘8’, output: ‘[0,1,1,2,3,5,8,13]’ }
}
};
const langChallenges = challenges[language] || [];
return langChallenges[level % langChallenges.length];
}
export const recommendationService = CodeRecommendationService.getInstance();
成就系统服务
// AchievementService.ets
import preferences from ‘@ohos.data.preferences’;
class AchievementService {
private static instance: AchievementService;
private constructor() {}
public static getInstance(): AchievementService {
if (!AchievementService.instance) {
AchievementService.instance = new AchievementService();
return AchievementService.instance;
public async checkAchievements(progress: LearningProgress): Promise<Achievement[]> {
const allAchievements = await this.getAllAchievements();
const unlocked = await this.getUnlockedAchievements();
const newAchievements: Achievement[] = [];
// 检查课程完成成就
const course = await courseService.getCourse(progress.courseId);
if (progress.completedLessons.length === course.totalLessons) {
const achievementId = complete_course_${course.id};
if (!unlocked.some(a => a.id === achievementId)) {
const achievement = {
id: achievementId,
name: 完成课程: ${course.title},
description: 完成所有${course.title}课程的学习,
icon: 'course_complete.png',
points: 100,
unlockedAt: Date.now()
};
newAchievements.push(achievement);
}
// 检查连续学习成就
const streak = await this.checkLearningStreak();
if (streak >= 7 && !unlocked.some(a => a.id === '7_day_streak')) {
newAchievements.push({
id: '7_day_streak',
name: '7天学习达人',
description: '连续7天学习编程',
icon: 'streak_7.png',
points: 50,
unlockedAt: Date.now()
});
// 保存新成就
if (newAchievements.length > 0) {
await this.unlockAchievements(newAchievements);
return newAchievements;
public async getUnlockedAchievements(): Promise<Achievement[]> {
const prefs = await preferences.getPreferences('achievements');
const value = await prefs.get('unlocked', '[]');
return JSON.parse(value);
public async getAllAchievements(): Promise<Achievement[]> {
// 简化实现,实际应从服务器获取
return [
id: ‘first_lesson’,
name: '第一课',
description: '完成第一个编程课程',
icon: 'first_lesson.png',
points: 10
},
id: ‘fast_learner’,
name: '快速学习者',
description: '在一天内完成3个课程',
icon: 'fast_learner.png',
points: 30
},
id: ‘code_master’,
name: '代码大师',
description: '完成所有基础课程',
icon: 'code_master.png',
points: 100
];
private async unlockAchievements(achievements: Achievement[]): Promise<void> {
const unlocked = await this.getUnlockedAchievements();
const newUnlocked = [...unlocked, ...achievements];
const prefs = await preferences.getPreferences('achievements');
await prefs.put('unlocked', JSON.stringify(newUnlocked));
await prefs.flush();
// 通知成就解锁
achievements.forEach(achievement => {
EventBus.emit('achievementUnlocked', achievement);
});
private async checkLearningStreak(): Promise<number> {
const prefs = await preferences.getPreferences('learning_stats');
const lastDate = await prefs.get('last_learning_date', '');
const currentStreak = await prefs.get('current_streak', 0);
const today = new Date().toISOString().split('T')[0];
if (lastDate === today) return currentStreak;
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const yesterdayStr = yesterday.toISOString().split('T')[0];
if (lastDate === yesterdayStr) {
const newStreak = currentStreak + 1;
await prefs.put('current_streak', newStreak);
await prefs.put('last_learning_date', today);
await prefs.flush();
return newStreak;
else {
await prefs.put('current_streak', 1);
await prefs.put('last_learning_date', today);
await prefs.flush();
return 1;
}
export const achievementService = AchievementService.getInstance();
五、总结
本编程学习助手应用实现了以下核心价值:
交互学习:提供实时反馈的编程练习环境
智能指导:AI分析代码并提供改进建议
多设备同步:跨设备无缝切换学习进度
结构化课程:系统化的编程学习路径
成就激励:通过成就系统保持学习动力
扩展方向:
增加更多编程语言支持
开发社交学习功能
集成在线编程竞赛
增加AR/VR编程学习体验
注意事项:
需要网络连接以使用AI分析功能
代码执行有安全限制
多设备协同需保持网络连接
首次使用建议完成引导教程
部分高级功能可能需要订阅服务
