HarmonyOS ArkTS 实战:实现一个校园宿舍管理与查寝应用

HarmonyOS ArkTS 实战:实现一个校园宿舍管理与查寝应用

项目效果

本文使用 HarmonyOS 和 ArkTS 实现一个校园宿舍管理与查寝应用。

应用可以管理宿舍成员信息,进行查寝签到,记录晚归情况,进行卫生评分,并提供宿舍报修、水电费查询和查寝统计等功能。

项目使用 DevEco Studio 开发,适配 API 23 及以上版本。

运行效果

功能介绍

本项目实现了以下功能:

  • 宿舍成员管理
  • 查寝签到
  • 晚归登记
  • 卫生检查评分
  • 宿舍报修
  • 水电费查询
  • 请假外宿登记
  • 查寝记录查看
  • 卫生排名统计
  • 晚归次数统计
  • 宿舍公告

定义数据结构

首先定义宿舍成员和查寝记录的数据结构:

typescript 复制代码
interface DormMember {
  id: number;
  studentId: string;
  name: string;
  bedNumber: string;
  major: string;
  phone: string;
  isRoomLeader: boolean;
}

interface CheckRecord {
  id: number;
  date: string;
  time: string;
  type: string;
  status: string;
  lateReason: string;
  score: number;
  remark: string;
}

interface Dormitory {
  id: number;
  building: string;
  roomNumber: string;
  floor: number;
  members: DormMember[];
  checkRecords: CheckRecord[];
  hygieneScore: number;
  notice: string;
}

字段说明如下:

  • DormMember:宿舍成员
    • id:成员编号
    • studentId:学号
    • name:姓名
    • bedNumber:床位号
    • major:专业
    • phone:电话
    • isRoomLeader:是否宿舍长
  • CheckRecord:查寝记录
    • id:记录编号
    • date:日期
    • time:时间
    • type:类型(查寝/卫生检查/晚归)
    • status:状态(在寝/晚归/不在/请假)
    • lateReason:晚归原因
    • score:卫生评分
    • remark:备注
  • Dormitory:宿舍
    • id:宿舍编号
    • building:楼栋
    • roomNumber:房间号
    • floor:楼层
    • members:成员列表
    • checkRecords:查寝记录
    • hygieneScore:卫生评分
    • notice:宿舍公告

初始化页面状态

使用 @State 保存签到信息、评分:

typescript 复制代码
@State private lateReasonText: string = '';
@State private remarkText: string = '';
@State private hygieneScore: number = 90;
@State private selectedStatus: string = '在寝';
@State private nextRecordId: number = 10;

准备一些初始宿舍数据:

typescript 复制代码
@State private dormitories: Dormitory[] = [
  {
    id: 1,
    building: '12号楼',
    roomNumber: '302',
    floor: 3,
    hygieneScore: 92,
    notice: '本周四下午卫生检查,请大家整理好内务',
    members: [
      { id: 1, studentId: '2023001', name: '张三', bedNumber: '1号床', major: '计算机科学与技术', phone: '138****1234', isRoomLeader: true },
      { id: 2, studentId: '2023002', name: '李四', bedNumber: '2号床', major: '计算机科学与技术', phone: '139****2345', isRoomLeader: false },
      { id: 3, studentId: '2023003', name: '王五', bedNumber: '3号床', major: '软件工程', phone: '137****3456', isRoomLeader: false },
      { id: 4, studentId: '2023004', name: '赵六', bedNumber: '4号床', major: '软件工程', phone: '136****4567', isRoomLeader: false }
    ],
    checkRecords: [
      { id: 1, date: '2026-07-17', time: '22:30', type: '查寝', status: '在寝', lateReason: '', score: 0, remark: '全员在寝' },
      { id: 2, date: '2026-07-16', time: '22:45', type: '查寝', status: '晚归', lateReason: '实验室做项目', score: 0, remark: '李四晚归15分钟' },
      { id: 3, date: '2026-07-15', time: '15:00', type: '卫生检查', status: '', lateReason: '', score: 92, remark: '整体整洁,桌面需整理' }
    ]
  }
];

查寝签到

宿舍长进行查寝签到:

typescript 复制代码
private submitCheck(dormId: number): void {
  const now = new Date();
  const date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
  const time = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.dormitories = this.dormitories.map((dorm: Dormitory) => {
    if (dorm.id === dormId) {
      const record: CheckRecord = {
        id: this.nextRecordId,
        date,
        time,
        type: '查寝',
        status: this.selectedStatus,
        lateReason: this.lateReasonText,
        score: 0,
        remark: this.remarkText
      };
      this.nextRecordId += 1;

      return {
        ...dorm,
        checkRecords: [record, ...dorm.checkRecords]
      };
    }
    return dorm;
  });

  this.lateReasonText = '';
  this.remarkText = '';
  this.selectedStatus = '在寝';
}

卫生检查评分

typescript 复制代码
private submitHygieneCheck(dormId: number): void {
  const now = new Date();
  const date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
  const time = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.dormitories = this.dormitories.map((dorm: Dormitory) => {
    if (dorm.id === dormId) {
      const record: CheckRecord = {
        id: this.nextRecordId,
        date,
        time,
        type: '卫生检查',
        status: '',
        lateReason: '',
        score: this.hygieneScore,
        remark: this.remarkText
      };
      this.nextRecordId += 1;

      return {
        ...dorm,
        hygieneScore: this.hygieneScore,
        checkRecords: [record, ...dorm.checkRecords]
      };
    }
    return dorm;
  });

  this.remarkText = '';
}

请假外宿登记

typescript 复制代码
private submitLeave(dormId: number, reason: string): void {
  const now = new Date();
  const date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
  const time = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.dormitories = this.dormitories.map((dorm: Dormitory) => {
    if (dorm.id === dormId) {
      const record: CheckRecord = {
        id: this.nextRecordId,
        date,
        time,
        type: '请假',
        status: '请假',
        lateReason: reason,
        score: 0,
        remark: '已报备辅导员'
      };
      this.nextRecordId += 1;

      return {
        ...dorm,
        checkRecords: [record, ...dorm.checkRecords]
      };
    }
    return dorm;
  });
}

统计数据

typescript 复制代码
private getLateCount(dorm: Dormitory): number {
  return dorm.checkRecords.filter(r => r.status === '晚归').length;
}

private getPresentCount(dorm: Dormitory): number {
  return dorm.checkRecords.filter(r => r.status === '在寝').length;
}

private getAverageScore(dorm: Dormitory): number {
  const scores = dorm.checkRecords.filter(r => r.type === '卫生检查').map(r => r.score);
  if (scores.length === 0) return 0;
  return Math.round(scores.reduce((a, b) => a + b, 0) / scores.length);
}

private getLeaveCount(dorm: Dormitory): number {
  return dorm.checkRecords.filter(r => r.status === '请假').length;
}

顶部统计区域展示本月查寝、在寝率、晚归次数、卫生评分:

typescript 复制代码
this.StatCard(
  '本月查寝',
  `${dorm.checkRecords.filter(r => r.type === '查寝').length}次`,
  '#15803D',
  '#DCFCE7'
);
this.StatCard(
  '在寝率',
  `${Math.round(this.getPresentCount(dorm) / (this.getPresentCount(dorm) + this.getLateCount(dorm) + this.getLeaveCount(dorm)) * 100)}%`,
  '#059669',
  '#ECFDF5'
);
this.StatCard(
  '晚归次数',
  `${this.getLateCount(dorm)}次`,
  '#DC2626',
  '#FEF2F2'
);
this.StatCard(
  '卫生评分',
  `${dorm.hygieneScore}分`,
  '#F59E0B',
  '#FFFBEB'
);

设置状态颜色

typescript 复制代码
private getStatusColor(status: string): ResourceColor {
  if (status === '在寝') return '#059669';
  if (status === '晚归') return '#DC2626';
  if (status === '请假') return '#F59E0B';
  return '#6B7280';
}

private getStatusBgColor(status: string): ResourceColor {
  if (status === '在寝') return '#DCFCE7';
  if (status === '晚归') return '#FEE2E2';
  if (status === '请假') return '#FEF3C7';
  return '#F3F4F6';
}

private getScoreColor(score: number): ResourceColor {
  if (score >= 90) return '#059669';
  if (score >= 80) return '#F59E0B';
  return '#DC2626';
}
  • 绿色:在寝/优秀
  • 红色:晚归/不合格
  • 橙色:请假/良好
  • 灰色:其他
  • 深绿色系:页面主题色

状态选择按钮封装

typescript 复制代码
@Builder
StatusButton(text: string) {
  Button(text)
    .height(36)
    .padding({ left: 16, right: 16 })
    .fontSize(13)
    .fontColor(this.selectedStatus === text ? Color.White : '#344054')
    .backgroundColor(
      this.selectedStatus === text ? '#15803D' : '#F3F4F6'
    )
    .borderRadius(18)
    .onClick(() => {
      this.selectedStatus = text;
    });
}

宿舍成员网格展示

使用 Grid 展示宿舍成员:

typescript 复制代码
Grid() {
  ForEach(
    dorm.members,
    (member: DormMember) => {
      GridItem() {
        Column() {
          Circle()
            .width(48)
            .height(48)
            .fill('#15803D20')
            .overlay(
              Text(member.name.charAt(0))
                .fontSize(18)
                .fontColor('#15803D')
            )
          Text(member.name)
            .fontSize(13)
            .fontWeight(FontWeight.Medium)
            .margin({ top: 8 })
          Text(member.bedNumber)
            .fontSize(11)
            .fontColor('#6B7280')
            .margin({ top: 2 })
          if (member.isRoomLeader) {
            Text('宿舍长')
              .fontSize(10)
              .fontColor('#15803D')
              .backgroundColor('#DCFCE7')
              .padding({ left: 6, right: 6, top: 2, bottom: 2 })
              .borderRadius(4)
              .margin({ top: 4 })
          }
        }
        .width('100%')
        .padding(12)
        .backgroundColor(Color.White)
        .borderRadius(12)
      }
    },
    (member: DormMember) => member.id.toString()
  )
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsGap(12)
.columnsGap(12)
.width('100%')

页面设计说明

应用使用深绿色作为主题色,体现宿舍、生活、整洁的氛围。

页面主要分为以下区域:

  1. 顶部宿舍信息
  2. 查寝数据统计
  3. 宿舍公告
  4. 成员网格展示
  5. 查寝签到表单
  6. 卫生评分
  7. 查寝记录列表

页面采用浅灰色背景和白色卡片。床位使用4列网格展示,查寝状态使用不同颜色标签,卫生评分使用星级展示,查寝记录使用时间倒序排列,宿舍长使用特殊标记。

SDK 配置

本项目使用 HarmonyOS API 24,满足 API 23 及以上要求:

json5 复制代码
{
  "name": "default",
  "compatibleSdkVersion": "6.1.1(24)",
  "runtimeOS": "HarmonyOS",
  "targetSdkVersion": "6.1.1(24)",
  "compileSdkVersion": "6.1.1(24)"
}

entry 模块中的运行系统也要保持一致:

json5 复制代码
{
  "apiType": "stageMode",
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    }
  ]
}

运行项目

使用 DevEco Studio 打开项目,然后找到:

复制代码
entry/src/main/ets/pages/Index.ets

等待项目同步完成,点击右侧的 Preview 按钮即可查看应用效果。

项目总结

本文使用 HarmonyOS 和 ArkTS 实现了一个校园宿舍管理与查寝应用。

项目实现了成员管理、查寝签到、晚归登记、卫生评分、请假登记、查寝记录、统计排名等功能。

通过这个项目可以掌握:

  • ArkTS 接口定义和嵌套数据结构
  • @State 状态管理
  • 查寝签到流程
  • Grid 网格布局展示成员
  • ListForEach 列表渲染
  • 评分和统计计算
  • 自定义 @Builder 组件
  • HarmonyOS 宿舍管理类应用布局

后续还可以加入人脸识别查寝、自动定位签到、水电费缴纳、宿舍报修、调宿申请、文明宿舍评选、访客登记和宿舍评比等功能。

相关推荐
listening7775 小时前
HarmonyOS ArkTS 实战:实现一个校园打印复印预约应用
华为·harmonyos
绝世番茄6 小时前
鸿蒙原生 ArkTS 布局之道:Grid 替代多层嵌套布局深度解析
华为·harmonyos·鸿蒙
●VON6 小时前
鸿蒙 PC Markdown 编辑器可靠性设计:未保存内容的崩溃恢复闭环
华为·中间件·编辑器·harmonyos·鸿蒙
●VON6 小时前
鸿蒙 PC Markdown 编辑器导出架构:安全 HTML 与系统 PDF
华为·架构·编辑器·harmonyos·鸿蒙
信仰8747 小时前
HCIA-华为数通基础理论与实践08
网络·笔记·华为
不羁的木木7 小时前
HarmonyOS技术精讲-Connectivity Kit(短距通信服务):初识统一短距通信框架
华为·wpf·harmonyos
爸爸6197 小时前
UIAbility 生命周期在日记 App 中的实践
后端·华为·harmonyos·鸿蒙系统
tyqtyq2215 小时前
旅行打包清单 App — HarmonyOS AI 应用开发技术博客
人工智能·学习·华为·生活·harmonyos
HONG````15 小时前
Lazy Import 动态加载:减少 HarmonyOS 应用冷启动时间
harmonyos