【2026最新】鸿蒙NEXT培训班管理系统实战:从零搭建完整项目架构
本文详细介绍了基于鸿蒙NEXT开发培训班管理系统的完整流程。首先进行需求分析,明确了学员管理、课程管理等核心功能模块。然后采用分层架构设计,规划了清晰的目录结构,包括UI层、ViewModel层、Service层和Data层。接着指导开发环境搭建,包括DevEco Studio安装配置和项目初始化。最后实现了基础框架代码,包含数据模型定义、数据库帮助类、工具类和首页实现等核心功能。文章还总结了开发
引言
想用鸿蒙NEXT开发一个完整的培训班管理系统,却不知道从何下手?项目结构混乱、模块划分不清晰、代码难以维护?别担心,本文将手把手带你从零搭建一个高内聚低耦合的鸿蒙NEXT项目架构,涵盖需求分析、架构设计、目录规划、环境搭建和基础框架实现,让你的培训班管理系统开发事半功倍!
一、需求分析
1.1 业务背景
培训班管理系统是一个典型的教育类应用,主要用于管理培训机构的日常运营,包括学员管理、课程管理、报名管理、考勤管理等核心功能。
1.2 功能需求
核心功能模块
|
模块 |
功能点 |
优先级 |
|---|---|---|
|
学员管理 |
学员信息录入、查询、修改、删除 |
P0 |
|
课程管理 |
课程信息维护、课程表展示 |
P0 |
|
报名管理 |
学员报名、退费、课程选择 |
P0 |
|
考勤管理 |
签到签退、考勤统计 |
P1 |
|
数据统计 |
学员统计、课程统计、收入统计 |
P1 |
用户角色
-
管理员:系统管理、数据统计、权限管理
-
教师:课程管理、考勤管理、学员查看
-
学员:课程查看、报名、个人信息管理
1.3 界面原型
┌─────────────────────────────────────┐
│ 首页 (TabBar) │
├─────────────────────────────────────┤
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ 学员 │ │ 课程 │ │ 报名 │ │ 我的 │ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────┘
二、架构设计
2.1 整体架构
采用分层架构设计,将应用分为以下层次:
┌─────────────────────────────────────┐
│ UI层 (ArkUI) │
├─────────────────────────────────────┤
│ ViewModel层 │
├─────────────────────────────────────┤
│ Service层 │
├─────────────────────────────────────┤
│ Data层 │
└─────────────────────────────────────┘
2.2 技术选型
|
技术领域 |
技术方案 |
说明 |
|---|---|---|
|
UI框架 |
ArkUI |
鸿蒙原生UI框架 |
|
状态管理 |
@State/@Prop/@Link |
组件状态管理 |
|
数据持久化 |
Preferences + RDB |
轻量级+关系型数据库 |
|
网络请求 |
@ohos.net.http |
系统HTTP API |
|
路由管理 |
Navigation + NavRouter |
页面导航 |
2.3 模块划分
TrainingManagement/
├── entry/ # 主模块
│ ├── src/main/ets/
│ │ ├── pages/ # 页面
│ │ ├── components/ # 公共组件
│ │ ├── viewmodel/ # 视图模型
│ │ ├── service/ # 业务服务
│ │ ├── model/ # 数据模型
│ │ ├── common/ # 公共工具
│ │ └── resources/ # 资源文件
│ └── src/main/resources/ # 系统资源
└── features/ # 功能模块
├── student/ # 学员模块
├── course/ # 课程模块
├── enrollment/ # 报名模块
└── attendance/ # 考勤模块
三、目录结构规划
3.1 完整目录结构
entry/src/main/ets/
├── pages/
│ ├── Index.ets # 首页
│ ├── StudentList.ets # 学员列表页
│ ├── StudentDetail.ets # 学员详情页
│ ├── CourseList.ets # 课程列表页
│ ├── CourseDetail.ets # 课程详情页
│ ├── EnrollmentPage.ets # 报名页面
│ └── MyPage.ets # 个人中心
├── components/
│ ├── common/
│ │ ├── TitleBar.ets # 标题栏
│ │ ├── SearchBar.ets # 搜索栏
│ │ ├── EmptyView.ets # 空状态视图
│ │ └── LoadingView.ets # 加载视图
│ ├── student/
│ │ ├── StudentCard.ets # 学员卡片
│ │ └── StudentForm.ets # 学员表单
│ └── course/
│ ├── CourseCard.ets # 课程卡片
│ └── CourseSchedule.ets # 课程表
├── viewmodel/
│ ├── StudentViewModel.ets # 学员视图模型
│ ├── CourseViewModel.ets # 课程视图模型
│ └── EnrollmentViewModel.ets # 报名视图模型
├── service/
│ ├── StudentService.ets # 学员服务
│ ├── CourseService.ets # 课程服务
│ └── EnrollmentService.ets # 报名服务
├── model/
│ ├── Student.ets # 学员模型
│ ├── Course.ets # 课程模型
│ └── Enrollment.ets # 报名模型
├── common/
│ ├── Constants.ets # 常量定义
│ ├── Utils.ets # 工具类
│ └── DatabaseHelper.ets # 数据库帮助类
└── resources/
├── base/element/ # 元素资源
├── base/media/ # 媒体资源
└── base/profile/ # 配置文件
3.2 模块职责说明
|
目录 |
职责 |
说明 |
|---|---|---|
|
pages |
页面层 |
负责UI展示和用户交互 |
|
components |
组件层 |
可复用的UI组件 |
|
viewmodel |
视图模型层 |
管理页面状态和业务逻辑 |
|
service |
服务层 |
处理业务逻辑和数据操作 |
|
model |
模型层 |
定义数据结构 |
|
common |
公共层 |
工具类和常量定义 |
四、开发环境搭建
4.1 DevEco Studio安装
-
下载DevEco Studio
-
访问华为开发者联盟官网
-
下载最新版本DevEco Studio 5.0+
-
-
安装配置
系统要求: - Windows 10/11 64位 - 内存:16GB以上 - 硬盘:100GB以上可用空间 -
SDK配置
-
打开DevEco Studio
-
进入Settings → HarmonyOS SDK
-
下载API 12及以上版本
-
4.2 项目创建
-
创建新项目
-
打开DevEco Studio
-
选择"Create HarmonyOS Project"
-
选择"Empty Ability"模板
-
配置项目信息:
-
Project Name: TrainingManagement
-
Bundle Name: com.example.training
-
Compile SDK: API 12
-
Model: Stage
-
-
-
项目初始化
# 项目结构生成后,检查以下文件 - entry/src/main/ets/entryability/EntryAbility.ets - entry/src/main/ets/pages/Index.ets - entry/src/main/module.json5
4.3 开发工具配置
-
代码风格配置
// .eslintrc.json { "extends": "@typescript-eslint/recommended", "rules": { "indent": ["error", 2], "quotes": ["error", "single"], "semi": ["error", "always"] } } -
Git配置
# 初始化Git仓库 git init git add . git commit -m "初始化鸿蒙培训班管理系统项目"
五、基础框架代码实现
5.1 数据模型定义
// model/Student.ets
export interface Student {
id: string;
name: string;
phone: string;
email: string;
gender: number; // 0: 未知, 1: 男, 2: 女
birthday: string;
address: string;
avatar: string;
createTime: string;
updateTime: string;
}
// model/Course.ets
export interface Course {
id: string;
name: string;
description: string;
teacher: string;
price: number;
duration: number; // 课时
maxStudents: number;
currentStudents: number;
startTime: string;
endTime: string;
status: number; // 0: 未开始, 1: 进行中, 2: 已结束
createTime: string;
updateTime: string;
}
// model/Enrollment.ets
export interface Enrollment {
id: string;
studentId: string;
courseId: string;
enrollTime: string;
status: number; // 0: 已报名, 1: 已上课, 2: 已退费
remark: string;
createTime: string;
updateTime: string;
}
5.2 数据库帮助类
// common/DatabaseHelper.ets
import rdb from '@ohos.data.relationalStore';
const DB_NAME = 'training_management.db';
const DB_VERSION = 1;
export class DatabaseHelper {
private static instance: DatabaseHelper;
private rdbStore: rdb.RdbStore | null = null;
private constructor() {}
static getInstance(): DatabaseHelper {
if (!DatabaseHelper.instance) {
DatabaseHelper.instance = new DatabaseHelper();
}
return DatabaseHelper.instance;
}
async init(context: Context): Promise<void> {
const config: rdb.StoreConfig = {
name: DB_NAME,
securityLevel: rdb.SecurityLevel.S1
};
this.rdbStore = await rdb.getRdbStore(context, config, DB_VERSION);
await this.createTables();
}
private async createTables(): Promise<void> {
const createStudentTable = `
CREATE TABLE IF NOT EXISTS student (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
phone TEXT,
email TEXT,
gender INTEGER DEFAULT 0,
birthday TEXT,
address TEXT,
avatar TEXT,
create_time TEXT,
update_time TEXT
)
`;
const createCourseTable = `
CREATE TABLE IF NOT EXISTS course (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
teacher TEXT,
price REAL,
duration INTEGER,
max_students INTEGER,
current_students INTEGER DEFAULT 0,
start_time TEXT,
end_time TEXT,
status INTEGER DEFAULT 0,
create_time TEXT,
update_time TEXT
)
`;
const createEnrollmentTable = `
CREATE TABLE IF NOT EXISTS enrollment (
id TEXT PRIMARY KEY,
student_id TEXT NOT NULL,
course_id TEXT NOT NULL,
enroll_time TEXT,
status INTEGER DEFAULT 0,
remark TEXT,
create_time TEXT,
update_time TEXT,
FOREIGN KEY (student_id) REFERENCES student(id),
FOREIGN KEY (course_id) REFERENCES course(id)
)
`;
await this.rdbStore?.executeSql(createStudentTable);
await this.rdbStore?.executeSql(createCourseTable);
await this.rdbStore?.executeSql(createEnrollmentTable);
}
getRdbStore(): rdb.RdbStore | null {
return this.rdbStore;
}
}
5.3 工具类
// common/Utils.ets
export class Utils {
/**
* 生成唯一ID
*/
static generateId(): string {
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
/**
* 格式化日期
*/
static formatDate(date: Date, format: string = 'YYYY-MM-DD HH:mm:ss'): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
/**
* 验证手机号
*/
static isValidPhone(phone: string): boolean {
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phone);
}
/**
* 验证邮箱
*/
static isValidEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
/**
* 显示提示信息
*/
static showToast(message: string): void {
// 使用系统Toast API
console.info(message);
}
}
5.4 常量定义
// common/Constants.ets
export class Constants {
// 数据库版本
static readonly DB_VERSION = 1;
// 性别常量
static readonly GENDER_UNKNOWN = 0;
static readonly GENDER_MALE = 1;
static readonly GENDER_FEMALE = 2;
// 课程状态
static readonly COURSE_STATUS_NOT_STARTED = 0;
static readonly COURSE_STATUS_IN_PROGRESS = 1;
static readonly COURSE_STATUS_ENDED = 2;
// 报名状态
static readonly ENROLLMENT_STATUS_ENROLLED = 0;
static readonly ENROLLMENT_STATUS_ATTENDED = 1;
static readonly ENROLLMENT_STATUS_REFUNDED = 2;
// 页面路由
static readonly PAGE_INDEX = 'pages/Index';
static readonly PAGE_STUDENT_LIST = 'pages/StudentList';
static readonly PAGE_STUDENT_DETAIL = 'pages/StudentDetail';
static readonly PAGE_COURSE_LIST = 'pages/CourseList';
static readonly PAGE_COURSE_DETAIL = 'pages/CourseDetail';
static readonly PAGE_ENROLLMENT = 'pages/EnrollmentPage';
static readonly PAGE_MY = 'pages/MyPage';
}
5.5 首页实现
// pages/Index.ets
import { Constants } from '../common/Constants';
@Entry
@Component
struct Index {
@State currentIndex: number = 0;
private tabItems: TabBarItem[] = [
{ title: '学员', icon: $r('app.media.ic_student') },
{ title: '课程', icon: $r('app.media.ic_course') },
{ title: '报名', icon: $r('app.media.ic_enrollment') },
{ title: '我的', icon: $r('app.media.ic_my') }
];
build() {
Column() {
// 标题栏
TitleBar({ title: '培训班管理系统' })
// 内容区域
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
StudentList()
}
.tabBar(this.TabBarItem(0))
TabContent() {
CourseList()
}
.tabBar(this.TabBarItem(1))
TabContent() {
EnrollmentPage()
}
.tabBar(this.TabBarItem(2))
TabContent() {
MyPage()
}
.tabBar(this.TabBarItem(3))
}
.onChange((index: number) => {
this.currentIndex = index;
})
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
@Builder
TabBarItem(index: number) {
Column() {
Image(this.tabItems[index].icon)
.width(24)
.height(24)
.fillColor(this.currentIndex === index ? '#007DFF' : '#999999')
Text(this.tabItems[index].title)
.fontSize(12)
.fontColor(this.currentIndex === index ? '#007DFF' : '#999999')
.margin({ top: 4 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
interface TabBarItem {
title: string;
icon: Resource;
}
5.6 标题栏组件
// components/common/TitleBar.ets
@Component
export struct TitleBar {
@Prop title: string = '';
@Prop showBack: boolean = false;
backCallback: () => void = () => {};
build() {
Row() {
// 返回按钮
if (this.showBack) {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.onClick(() => {
this.backCallback();
})
}
// 标题
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.layoutWeight(1)
.textAlign(TextAlign.Center)
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor('#FFFFFF')
}
}
六、踩坑记录
6.1 数据库初始化问题
问题:数据库初始化时,表创建失败。
原因:SQL语句中的外键约束导致创建失败。
解决方案:
// 先创建主表,再创建外键表
await this.rdbStore?.executeSql(createStudentTable);
await this.rdbStore?.executeSql(createCourseTable);
await this.rdbStore?.executeSql(createEnrollmentTable);
6.2 资源引用问题
问题:图片资源无法加载。
原因:资源路径配置错误。
解决方案:
// 确保资源文件放在正确的目录
entry/src/main/resources/base/media/
6.3 组件通信问题
问题:父子组件数据不同步。
原因:@Prop装饰器是单向数据流。
解决方案:
// 使用@Link实现双向数据绑定
@Link isRefresh: boolean;
七、总结与预告
本文要点回顾
-
需求分析:明确了培训班管理系统的功能需求和用户角色
-
架构设计:采用分层架构,分离UI、业务逻辑和数据层
-
目录规划:按照功能模块划分,提高代码可维护性
-
环境搭建:详细介绍了DevEco Studio的安装和配置
-
基础框架:实现了数据模型、数据库、工具类等基础代码
下期预告
下期我们将深入讲解UI界面篇,包括:
-
学员列表页面实现
-
课程详情页面设计
-
报名页面交互优化
-
响应式布局适配
互动引导
如果本文对你有帮助,请点赞、收藏、关注!有任何问题欢迎在评论区留言,我会及时回复。
系列文章导航:
-
第1篇:项目架构篇(本文)
-
第2篇:UI界面篇
-
第3篇:状态管理篇
-
第4篇:数据持久化篇
-
第5篇:性能优化篇
更多推荐



所有评论(0)