鸿蒙NEXT开发-学生管理系统小案例(基于最新api12稳定版)

注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下

如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识

专栏地址: https://blog.csdn.net/qq_56760790/category_12794123.html

目录

[1. 基本介绍](#1. 基本介绍)

[2. 案例设计图](#2. 案例设计图)

[2.1 app应用](#2.1 app应用)

[2.2 登录页](#2.2 登录页)

[2.3 首页](#2.3 首页)

[2.4 添加/编辑页面](#2.4 添加/编辑页面)

[3. 项目结构](#3. 项目结构)

[4. 案例实现源码](#4. 案例实现源码)

[4.1 首先创建一个工程,然后将一些图片资源放在资源下面](#4.1 首先创建一个工程,然后将一些图片资源放在资源下面)

[2. 将AppScope下面的信息修改](#2. 将AppScope下面的信息修改)

[3. 修改module.json5文件](#3. 修改module.json5文件)

[4. 创建models目录,创建Student.ets文件](#4. 创建models目录,创建Student.ets文件)

[5. 创建conponents目录,,然后新增如下两个组件](#5. 创建conponents目录,,然后新增如下两个组件)

[6. 创建params目录,新增PageRouterParam.ets文件](#6. 创建params目录,新增PageRouterParam.ets文件)

[7. 创建utils目录,新增RdbUtil.ets文件](#7. 创建utils目录,新增RdbUtil.ets文件)

[8. 在pages目录下面新增三个页面](#8. 在pages目录下面新增三个页面)

[9. 修改EntryAbility.ets文件](#9. 修改EntryAbility.ets文件)

[4. 学习地址](#4. 学习地址)


1. 基本介绍

本案例涉及到多个鸿蒙相关技术知识点:

1、布局

2、配置文件

3、组件的封装和使用

4、路由的使用

5、应用数据持久化-关系型数据库的使用

鸿蒙学习交流

qq群号:767465523

2. 案例设计图

2.1 app应用

2.2 登录页

2.3 首页

2.4 添加/编辑页面

3. 项目结构

4. 案例实现源码

注意源码地址:

study_manage: 基于鸿蒙NEXT API12稳定版实现的一款学生管理系统项目案例。本案例涉及到多个鸿蒙相关技术知识点:1、布局2、配置文件3、组件的封装和使用4、路由的使用5、应用数据持久化-关系型数据库的使用

4.1 首先创建一个工程,然后将一些图片资源放在资源下面

icon.png

login.png

login_background.png

system.png

title.png

4.2 将AppScope下面的信息修改

4.3 修改module.json5文件

4.4 创建models目录,创建Student.ets文件

/**
 * 学生信息
 */
export default interface  Student {
  /**
   * 学生id
   */
  id: number
  /**
   * 学生名称
   */
  username: string
  /**
   * 年龄
   */
  age: number
  /**
   * 爱好
   */
  like: string
}

4.5 创建conponents目录,,然后新增如下两个组件

/**
 * 学生列表组件
 */
import Student from '../models/Student'
import { promptAction, router } from '@kit.ArkUI'
import PageRouterParam from '../params/PageRouterParam'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'


@Component
  export default struct StudentListComponent {
    @Link
    studentList: Student[]

    // 删除数据
    remove(id: number) {
      RdbUtil.deleteById(id)
        .then((param) => {
          console.log('remove student data success:' + param)
          promptAction.showToast({
            message: '删除数据成功'
          })
          router.replaceUrl({ url: 'pages/Index' })
        }).catch((err: BusinessError) => {
          console.log('remove student data fail:' + err)
          promptAction.showToast({
            message: '删除数据失败'
          })
        })
    }

    build() {
      Column() {
        // 数据标题
        Row() {
          Text('编号')
            .TextStyle()
          Text('姓名')
            .TextStyle()
          Text('年龄')
            .TextStyle()
          Text('爱好')
            .TextStyle()
          Text('操作')
            .TextStyle()
            .width('25%')

        }
        .width('100%')
          .height(50)
          .justifyContent(FlexAlign.SpaceAround)
          .margin({ left: 20 })

        // 学生数据
        List({ space: 20 }) {
          ForEach(this.studentList, (item: Student) => {
            ListItem() {
              Row() {
                Text(item.id.toString())
                  .TextStyle()
                Text(item.username)
                  .TextStyle()
                Text(item.age.toString())
                  .TextStyle()
                Text(item.like)
                  .TextStyle()

                Text('编辑')
                  .TextStyle()
                  .fontColor(Color.Blue)
                  .onClick(() => {
                    router.pushUrl({
                      url: 'pages/Register',
                      params: new PageRouterParam('欢迎来到编辑学生界面', '确认修改', item.id)
                    })
                  })

                Text('删除')
                  .TextStyle()
                  .fontColor(Color.Red)
                  .margin({ right: 10 })
                  .onClick(() => {
                    // 删除弹窗
                    AlertDialog.show(
                      {
                        title: '删除学生信息', // 标题
                        message: '是否需要删除所选学生信息?', // 内容
                        autoCancel: false, // 点击遮障层时,是否关闭弹窗。
                        alignment: DialogAlignment.Bottom, // 弹窗在竖直方向的对齐方式
                        offset: { dx: 0, dy: -20 }, // 弹窗相对alignment位置的偏移量
                        primaryButton: {
                          value: '取消',
                          action: () => {
                            console.info('Callback when the first button is clicked');
                          }
                        },
                        secondaryButton: {
                          value: '删除',
                          fontColor: '#D94838',
                          action: () => {
                            // 删除学生信息
                            this.remove(item.id)

                          }
                          },
                      cancel: () => { // 点击遮障层关闭dialog时的回调
                        console.info('Closed callbacks');
                      }
                    }
                  )

                })
            }
            .width('100%')
            .height(50)
            .justifyContent(FlexAlign.SpaceAround)
            .margin({ left: 20 })
            .backgroundColor(Color.White)
            .borderRadius(20)

          }
        }, (item: Student) => item.id.toString())
      }
    }.height('500')
  }
}

@Extend(Text)
function TextStyle() {
  .lineHeight(20)
  .fontWeight(400)
  .fontSize(15)
}

4.6 创建params目录,新增PageRouterParam.ets文件

/**
 * 页面路由参数
 */
export default class PageRouterParam {
  registerName: string = ''
  buttonName: string = ''
  studentId: number = 0

  constructor(registerName: string, buttonName: string, studentId: number) {
    this.registerName = registerName
    this.buttonName = buttonName
    this.studentId = studentId
  }
}

4.7 创建utils目录,新增RdbUtil.ets文件

import relationalStore from '@ohos.data.relationalStore';
import Student from '../models/Student';
import { BusinessError } from '@ohos.base';

/**
 * 关系型数据库工具类
 */
export default class RdbUtil {
  /**
   * 数据库对象
   */
  private static rdbStore: relationalStore.RdbStore;

  static setStore(store: relationalStore.RdbStore) {
    RdbUtil.rdbStore = store;
  }

  static getStore(): relationalStore.RdbStore {
    return RdbUtil.rdbStore;
  }

  /**
   * 执行sql
   * @param sql
   * @returns
   */
  static executeSql(sql: string): Promise<void> {
    return RdbUtil.getStore().executeSql(sql);
  }

  /**
   * 插入数据
   * @param tableName
   * @param data
   * @returns
   */
  static insert(tableName: string, data: relationalStore.ValuesBucket): Promise<number> {
    return RdbUtil.getStore().insert(tableName, data);
  }

  /**
   * 查询数据
   * @returns
   */
  static queryAll(): Promise<Array<Student>> {
    let predicates = new relationalStore.RdbPredicates('STUDENT');
    return new Promise<Array<Student>>((resolve, reject) => {
      RdbUtil.getStore().query(predicates).then((result) => {
        let students = new Array<Student>();
        while (result.goToNextRow()) {
          students.push({
            id: result.getLong(0),
            username: result.getString(1),
            age: result.getLong(2),
            like: result.getString(3)
          });
        }
        resolve(students);
      }).catch((error: BusinessError) => {
        reject(error)
      })
    })
  }

  /**
   * 删除
   * @param id
   * @returns
   */
  static deleteById(id: number) {
    let predicates = new relationalStore.RdbPredicates('STUDENT');
    predicates.equalTo('ID', id)
    return RdbUtil.getStore().delete(predicates);
  }

  /**
   * 更新
   * @param id
   * @param data
   * @returns
   */
  static updateById(id: number, data: relationalStore.ValuesBucket) {
    let predicates = new relationalStore.RdbPredicates('STUDENT');
    predicates.equalTo('ID', id)
    return RdbUtil.getStore().update(data, predicates);
  }
}

4.8 在pages目录下面新增三个页面

import StudentListComponent from '../components/StudentListComponent'
import Student from '../models/Student'
import { promptAction, router } from '@kit.ArkUI'
import PageRouterParam from '../params/PageRouterParam'
import TitleComponent from '../components/TitileComponent'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'

@Entry
  @Component
  struct Index {
    // 学生数组数据
    @State studentList: Student[] = []

    /**
    * 查询数据
    */
    onPageShow() {
      // 从关系型数据库中获取
      this.studentList = []
      RdbUtil.queryAll()
        .then((students: Array<Student>) => {
          this.studentList = students
          promptAction.showToast({ message: '获取学生信息成功' })
        }).catch((error: BusinessError) => {
          promptAction.showToast({
            message: ' 获取学生信息失败 '
          })
        })
    }

    build() {
      Column() {

        // 标题组件
        TitleComponent()

        Row() {
          // 学生数据
          Text('学生数据')
            .TextIndexStyle()

          // 添加
          Text('添加')
            .fontColor(Color.Blue)
            .TextIndexStyle()
            .onClick(() => {
              router.pushUrl({ url: 'pages/Register', params: new PageRouterParam('欢迎来到添加学生界面', '注册', 0) })
            })
        }.width('80%')
          .height(40)
          .justifyContent(FlexAlign.SpaceBetween)

        // 学生成绩展示
        StudentListComponent({ studentList: this.studentList })

      }
      .height('100%')
        .width('100%')
        .backgroundImage($r('app.media.login_background'))
        .backgroundImageSize({ width: '100%', height: '100%' })
    }
  }

@Extend(Text)
  function TextIndexStyle() {
    .lineHeight(20)
      .fontWeight(400)
      .fontSize(15)
  }

import { promptAction, router } from '@kit.ArkUI';

@Entry
  @Component
  struct Login {
    @State account: string = 'admin';
    @State password: string = '123456';

    /**
   * 登录
   */
    login() {
      // 校验账号密码是否符合要求
      if (this.account === 'admin' || this.password === '123456') {
        promptAction.showToast({ message: '登录成功' })
        router.pushUrl({
          url: 'pages/Index'
        })
      } else {
        promptAction.showToast({ message: '登录失败' })
        router.pushUrl({
          url: 'pages/login'
        })
      }

    }

    build() {
      Column() {
        Column() {
          // 登录图片
          Image($r('app.media.login'))
            .width(100)
            .height(100)
            .margin({ top: 200 })

          // 学生管理系统
          Text('学生管理系统')
            .padding(20)
            .fontSize(20)
            .fontWeight(600)

          // 输入账号密码
          TextInput({ text: this.account, placeholder: '请输入账号' })
            .TextInputLoginStyle()
            .onChange((value) => {
              this.account = value
            })


          // 请输入密码
          TextInput({ text: this.password, placeholder: '请输入密码' })
            .TextInputLoginStyle()
            .type(InputType.Password)
            .onChange((value) => {
              this.password = value

            })

          // 登录
          Button('登录', { stateEffect: true })
            .fontColor(Color.White)
            .width(300)
            .height(40)
            .type(ButtonType.Normal)
            .onClick(() => {
              this.login()
            })


        }
      }
      .height('100%')
        .width('100%')
        .backgroundImage($r('app.media.login_background'))
        .backgroundImageSize({ width: '100%', height: '100%' })
    }
  }

@Extend(TextInput)
  function TextInputLoginStyle() {
    .placeholderFont({ size: 15 })
      .width(300)
      .height(40)
      .margin({ bottom: 10 })
      .borderRadius(0)
  }

import { promptAction, router } from '@kit.ArkUI'
import TitleComponent from '../components/TitileComponent'
import PageRouterParam from '../params/PageRouterParam'
import { relationalStore } from '@kit.ArkData'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'

@Entry
  @Component
  struct Register {
    @State username: string = ''
    @State age: number = 0
    @State like: string = ''
    @State registerName: string = '欢迎来到添加学生界面'
    @State buttonName: string = '注册'
    @State studentId: number = 0

    aboutToAppear() {
      // 获取路由参数
      const param = router.getParams() as PageRouterParam
      this.registerName = param.registerName
      this.buttonName = param.buttonName
      this.studentId = param.studentId
    }

    register() {
      // 校验参数
      if (!this.username || !this.age || !this.like) {
        promptAction.showToast({
          message: this.buttonName + '失败,请填写学生信息'
        })
        return
      }
      if (this.studentId === 0) {
        // 注册
        const valueBucket: relationalStore.ValuesBucket = {
          'USERNAME': this.username,
          'AGE': this.age,
          'LIKE': this.like
        };
        RdbUtil.insert('STUDENT', valueBucket)
          .then((data) => {
            console.log('insert data success:' + JSON.stringify(data))
            promptAction.showToast({
              message: '注册成功'
            })
          }).catch((error: BusinessError) => {
            console.log('insert data fail:' + error)
            promptAction.showToast({
              message: '注册失败 '
            })
          })
      } else {
        // 修改
        const valueBucket: relationalStore.ValuesBucket = {
          'USERNAME': this.username,
          'AGE': this.age,
          'LIKE': this.like
        };
        RdbUtil.updateById(this.studentId, valueBucket)
          .then((data) => {
            console.log('update student success:' + JSON.stringify(data))
            promptAction.showToast({
              message: '修改成功'
            })
          }).catch((err: BusinessError) => {
            console.log('update student fail:' + err)
            promptAction.showToast({
              message: ' 修改失败 '
            })
          })
      }
      // 跳转到首页
      router.replaceUrl({ url: 'pages/Index' })
    }

    build() {
      Column() {
        // 欢迎页面
        TitleComponent({ name: this.registerName })

        // 注册功能
        TextInput({ placeholder: '请输入学生名称' })
          .TextInputRegisterStyle()
          .onChange((value) => {
            this.username = value
          })

        TextInput({ placeholder: '请输入学生年龄' })
          .TextInputRegisterStyle()
          .onChange((value) => {
            this.age = Number(value)
          })

        TextInput({ placeholder: '请输入学生爱好' })
          .TextInputRegisterStyle()
          .onChange((value) => {
            this.like = value
          })

        Button(this.buttonName)
          .width(300)
          .type(ButtonType.Normal)
          .stateEffect(true)
          .onClick(() => {
            // 注册或者修改
            this.register()
          })


      }
      .height('100%')
        .width('100%')
        .backgroundImage($r('app.media.login_background'))
    .backgroundImageSize({ width: '100%', height: '100%' })
  }
}

@Extend(TextInput)
function TextInputRegisterStyle() {
  .placeholderFont({ size: 15 })
  .width(300)
  .height(40)
  .margin({ bottom: 10 })
  .borderRadius(0)
}

4.9 修改EntryAbility.ets文件

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { promptAction, window } from '@kit.ArkUI';
import { relationalStore } from '@kit.ArkData';
import RdbUtil from '../utils/RdbUtil';
import { BusinessError } from '@kit.BasicServicesKit';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    // 创建数据库
    const STORE_CONFIG: relationalStore.StoreConfig = {
      name: 'study_manage.db', // 数据库文件名
      securityLevel: relationalStore.SecurityLevel.S3, // 数据库安全级别
      encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
      customDir: 'customDir/subCustomDir', // 可选参数,数据库自定义路径。数据库将在如下的目录结构中被创建:context.databaseDir + '/rdb/' + customDir,其中context.databaseDir是应用沙箱对应的路径,'/rdb/'表示创建的是关系型数据库,customDir表示自定义的路径。当此参数不填时,默认在本应用沙箱目录下创建RdbStore实例。
      isReadOnly: false // 可选参数,指定数据库是否以只读方式打开。该参数默认为false,表示数据库可读可写。该参数为true时,只允许从数据库读取数据,不允许对数据库进行写操作,否则会返回错误码801。
    };
    relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {
      if (err) {
        console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
        return;
      }
      console.info(`Succeeded in getting RdbStore.`);
      //保存store, 方便后面我们对数据库的操作
      RdbUtil.setStore(store)
      // 创建学生表
      const SQL_CREATE_TABLE =
        'CREATE TABLE IF NOT EXISTS STUDENT (ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT NOT NULL, AGE INTEGER,LIKE TEXT NOT NULL)'; // 建表Sql语句
      RdbUtil.executeSql(SQL_CREATE_TABLE)
        .then(() => {
          console.log('success create table')
        }).catch((err: BusinessError) => {
          console.log('fail create table')
        })

    })

    windowStage.loadContent('pages/Login', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

5. 学习地址

全网首发鸿蒙NEXT星河版零基础入门到实战,2024年最新版,企业级开发!视频陆续更新中!_哔哩哔哩_bilibili

相关推荐
新手小白勇闯新世界17 分钟前
论文阅读-用于图像识别的深度残差学习
论文阅读·人工智能·深度学习·学习·计算机视觉
麻衣带我去上学26 分钟前
Spring源码学习(五):Spring AOP
java·学习·spring
Mephisto.java1 小时前
【大数据学习 | kafka】producer之拦截器,序列化器与分区器
大数据·学习·kafka
HarmonyOS_SDK2 小时前
【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit
harmonyos
爱做ppt的阿伟3 小时前
11.5学习swing
学习
Python大数据分析@3 小时前
学习python中的pandas有没有好的教程推荐?
python·学习·pandas
Forever_Hopeful4 小时前
华为 HarmonyOS NEXT 原生应用开发: 动画的基础使用(属性、显示、专场)动画
华为·harmonyos
青椒大仙KI114 小时前
24/11/5 算法笔记adagrad 自适应学习率
笔记·学习·算法
青瓷看世界4 小时前
华为HarmonyOS打造开放、合规的广告生态 - 开屏广告
华为·harmonyos·广告投放
霍格沃兹测试开发学社测试人社区5 小时前
软件测试学习笔记丨Vue学习笔记-基本介绍
软件测试·vue.js·笔记·测试开发·学习