HarmonyOS ArkTS 实战:实现一个校园奖助学金申请评审应用

项目效果

本文使用 HarmonyOS 和 ArkTS 实现一个校园奖助学金申请评审应用。

应用可以发布奖助学金项目,在线申请,提交材料,辅导员审核,学院评审,公示,并提供申请统计和结果查询等功能。

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

运行效果

校园奖助学金申请评审应用

功能介绍

本项目实现了以下功能:

  • 发布奖助学金项目
  • 设置金额和名额
  • 设置申请条件
  • 在线申请
  • 填写申请信息
  • 提交申请材料
  • 辅导员审核
  • 学院评审
  • 结果公示
  • 按状态筛选申请
  • 统计申请人数、通过人数
  • 申请进度查询

定义数据结构

首先定义申请记录和奖助学金项目的数据结构:

interface ReviewRecord {
  reviewer: string;
  role: string;
  action: string;
  time: string;
  comment: string;
}

interface Application {
  id: number;
  scholarshipId: number;
  applicantName: string;
  studentId: string;
  college: string;
  major: string;
  grade: string;
  gpa: number;
  reason: string;
  materials: string;
  status: string;
  applyTime: string;
  reviewRecords: ReviewRecord[];
  rejectReason: string;
}

interface Scholarship {
  id: number;
  name: string;
  type: string;
  amount: number;
  quota: number;
  deadline: string;
  requirement: string;
  description: string;
  status: string;
  applications: Application[];
  publishTime: string;
}

字段说明如下:

  • ReviewRecord:评审记录
    • reviewer:评审人
    • role:评审角色(辅导员/学院评审/学校)
    • action:操作(通过/驳回/公示)
    • time:评审时间
    • comment:评审意见
  • Application:申请记录
    • id:申请编号
    • scholarshipId:项目编号
    • applicantName:申请人
    • studentId:学号
    • college:学院
    • major:专业
    • grade:年级
    • gpa:绩点
    • reason:申请理由
    • materials:材料清单
    • status:状态(申请中/待审核/审核通过/审核不通过/已公示)
    • applyTime:申请时间
    • reviewRecords:评审记录
    • rejectReason:驳回原因
  • Scholarship:奖助学金项目
    • id:项目编号
    • name:项目名称
    • type:类型(奖学金/助学金/国家奖/社会奖)
    • amount:金额(元)
    • quota:名额
    • deadline:截止日期
    • requirement:申请条件
    • description:项目说明
    • status:状态(申请中/评审中/已公示/已结束)
    • applications:申请列表
    • publishTime:发布时间

初始化页面状态

使用 @State 保存输入内容、项目选择:

@State private nameText: string = '';
@State private studentIdText: string = '';
@State private collegeText: string = '';
@State private majorText: string = '';
@State private gradeText: string = '';
@State private gpaText: string = '';
@State private reasonText: string = '';
@State private materialsText: string = '';
@State private commentText: string = '';
@State private rejectReasonText: string = '';
@State private selectedScholarshipId: number = 0;
@State private filterStatus: string = '全部';
@State private currentUserId: string = '2023001';
@State private nextApplyId: number = 10;

准备一些初始项目数据:

@State private scholarships: Scholarship[] = [
  {
    id: 1,
    name: '国家奖学金',
    type: '国家奖',
    amount: 8000,
    quota: 5,
    deadline: '2026-09-30',
    requirement: '绩点3.8以上,无挂科',
    description: '奖励特别优秀的全日制本专科学生',
    status: '申请中',
    publishTime: '2026-07-01',
    applications: [
      {
        id: 1,
        scholarshipId: 1,
        applicantName: '王同学',
        studentId: '2023001',
        college: '计算机学院',
        major: '计算机科学与技术',
        grade: '大三',
        gpa: 3.9,
        reason: '学习成绩优异,专业排名第一',
        materials: '成绩单、获奖证书',
        status: '待审核',
        applyTime: '2026-07-15',
        reviewRecords: [],
        rejectReason: ''
      }
    ]
  },
  {
    id: 2,
    name: '国家励志奖学金',
    type: '国家奖',
    amount: 5000,
    quota: 20,
    deadline: '2026-10-15',
    requirement: '家庭经济困难,绩点3.5以上',
    description: '奖励资助品学兼优的家庭经济困难学生',
    status: '申请中',
    publishTime: '2026-07-05',
    applications: []
  },
  {
    id: 3,
    name: '校级一等奖学金',
    type: '奖学金',
    amount: 2000,
    quota: 50,
    deadline: '2026-09-15',
    requirement: '绩点3.7以上',
    description: '奖励学习成绩优秀的学生',
    status: '已公示',
    publishTime: '2026-06-01',
    applications: [
      {
        id: 2,
        scholarshipId: 3,
        applicantName: '李同学',
        studentId: '2022005',
        college: '文学院',
        major: '汉语言文学',
        grade: '大四',
        gpa: 3.85,
        reason: '专业排名前5%,发表论文1篇',
        materials: '成绩单、论文发表证明',
        status: '已公示',
        applyTime: '2026-06-10',
        reviewRecords: [
          {
            reviewer: '张老师',
            role: '辅导员',
            action: '通过',
            time: '2026-06-15',
            comment: '情况属实,同意推荐'
          },
          {
            reviewer: '学院评审组',
            role: '学院评审',
            action: '公示',
            time: '2026-06-25',
            comment: '评审通过,予以公示'
          }
        ],
        rejectReason: ''
      }
    ]
  }
];

提交申请

学生提交奖助学金申请:

private submitApplication(): void {
  const name = this.nameText.trim();
  const studentId = this.studentIdText.trim();
  const college = this.collegeText.trim();
  const major = this.majorText.trim();
  const grade = this.gradeText.trim();
  const gpa = parseFloat(this.gpaText);
  const reason = this.reasonText.trim();
  const materials = this.materialsText.trim();

  if (name.length === 0 || studentId.length === 0 || isNaN(gpa) || reason.length === 0) {
    return;
  }

  this.scholarships = this.scholarships.map((s: Scholarship) => {
    if (s.id === this.selectedScholarshipId && s.status === '申请中') {
      const alreadyApplied = s.applications.some(a => a.studentId === studentId);
      if (alreadyApplied) return s;

      const newApply: Application = {
        id: this.nextApplyId,
        scholarshipId: s.id,
        applicantName: name,
        studentId,
        college,
        major,
        grade,
        gpa,
        reason,
        materials,
        status: '待审核',
        applyTime: new Date().toISOString().split('T')[0],
        reviewRecords: [],
        rejectReason: ''
      };
      this.nextApplyId += 1;

      return {
        id: s.id,
        name: s.name,
        type: s.type,
        amount: s.amount,
        quota: s.quota,
        deadline: s.deadline,
        requirement: s.requirement,
        description: s.description,
        status: s.status,
        publishTime: s.publishTime,
        applications: [...s.applications, newApply]
      };
    }
    return s;
  });

  this.nameText = '';
  this.studentIdText = '';
  this.collegeText = '';
  this.majorText = '';
  this.gradeText = '';
  this.gpaText = '';
  this.reasonText = '';
  this.materialsText = '';
}

审核通过和驳回

辅导员审核申请:

private approveApplication(scholarshipId: number, applyId: number): void {
  const comment = this.commentText.trim();
  const now = new Date();
  const time = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.scholarships = this.scholarships.map((s: Scholarship) => {
    if (s.id === scholarshipId) {
      const updatedApps = s.applications.map((a: Application) => {
        if (a.id === applyId && a.status === '待审核') {
          const newRecord: ReviewRecord = {
            reviewer: '张辅导员',
            role: '辅导员',
            action: '通过',
            time,
            comment: comment || '同意推荐'
          };

          return {
            id: a.id,
            scholarshipId: a.scholarshipId,
            applicantName: a.applicantName,
            studentId: a.studentId,
            college: a.college,
            major: a.major,
            grade: a.grade,
            gpa: a.gpa,
            reason: a.reason,
            materials: a.materials,
            status: '审核通过',
            applyTime: a.applyTime,
            reviewRecords: [...a.reviewRecords, newRecord],
            rejectReason: ''
          };
        }
        return a;
      });

      return {
        id: s.id,
        name: s.name,
        type: s.type,
        amount: s.amount,
        quota: s.quota,
        deadline: s.deadline,
        requirement: s.requirement,
        description: s.description,
        status: s.status,
        publishTime: s.publishTime,
        applications: updatedApps
      };
    }
    return s;
  });

  this.commentText = '';
}

private rejectApplication(scholarshipId: number, applyId: number): void {
  const rejectReason = this.rejectReasonText.trim();
  if (rejectReason.length === 0) return;

  const now = new Date();
  const time = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.scholarships = this.scholarships.map((s: Scholarship) => {
    if (s.id === scholarshipId) {
      const updatedApps = s.applications.map((a: Application) => {
        if (a.id === applyId && a.status === '待审核') {
          const newRecord: ReviewRecord = {
            reviewer: '张辅导员',
            role: '辅导员',
            action: '驳回',
            time,
            comment: rejectReason
          };

          return {
            id: a.id,
            scholarshipId: a.scholarshipId,
            applicantName: a.applicantName,
            studentId: a.studentId,
            college: a.college,
            major: a.major,
            grade: a.grade,
            gpa: a.gpa,
            reason: a.reason,
            materials: a.materials,
            status: '审核不通过',
            applyTime: a.applyTime,
            reviewRecords: [...a.reviewRecords, newRecord],
            rejectReason
          };
        }
        return a;
      });

      return {
        id: s.id,
        name: s.name,
        type: s.type,
        amount: s.amount,
        quota: s.quota,
        deadline: s.deadline,
        requirement: s.requirement,
        description: s.description,
        status: s.status,
        publishTime: s.publishTime,
        applications: updatedApps
      };
    }
    return s;
  });

  this.rejectReasonText = '';
}

公示通过申请

学院评审后公示:

private publishApplication(scholarshipId: number, applyId: number): void {
  const now = new Date();
  const time = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;

  this.scholarships = this.scholarships.map((s: Scholarship) => {
    if (s.id === scholarshipId) {
      const updatedApps = s.applications.map((a: Application) => {
        if (a.id === applyId && a.status === '审核通过') {
          const newRecord: ReviewRecord = {
            reviewer: '学院评审组',
            role: '学院评审',
            action: '公示',
            time,
            comment: '评审通过,予以公示'
          };

          return {
            id: a.id,
            scholarshipId: a.scholarshipId,
            applicantName: a.applicantName,
            studentId: a.studentId,
            college: a.college,
            major: a.major,
            grade: a.grade,
            gpa: a.gpa,
            reason: a.reason,
            materials: a.materials,
            status: '已公示',
            applyTime: a.applyTime,
            reviewRecords: [...a.reviewRecords, newRecord],
            rejectReason: ''
          };
        }
        return a;
      });

      return {
        id: s.id,
        name: s.name,
        type: s.type,
        amount: s.amount,
        quota: s.quota,
        deadline: s.deadline,
        requirement: s.requirement,
        description: s.description,
        status: '已公示',
        publishTime: s.publishTime,
        applications: updatedApps
      };
    }
    return s;
  });
}

筛选申请

private getAllApplications(): Application[] {
  let allApps: Application[] = [];
  this.scholarships.forEach(s => {
    s.applications.forEach(a => {
      if (this.filterStatus === '全部' || a.status === this.filterStatus) {
        allApps.push({...a, scholarshipName: s.name});
      }
    });
  });
  return allApps;
}

项目类型按钮封装:

@Builder
TypeButton(text: string) {
  Button(text)
    .height(32)
    .padding({ left: 14, right: 14 })
    .fontSize(12)
    .fontColor(Color.White)
    .backgroundColor('#CA8A04')
    .borderRadius(16);
}

统计数据

private getOpenCount(): number {
  return this.scholarships.filter(s => s.status === '申请中').length;
}

private getTotalApplications(): number {
  return this.scholarships.reduce((sum, s) => sum + s.applications.length, 0);
}

private getApprovedCount(): number {
  let count = 0;
  this.scholarships.forEach(s => {
    s.applications.forEach(a => {
      if (a.status === '已公示' || a.status === '审核通过') count++;
    });
  });
  return count;
}

private getTotalAmount(): number {
  let total = 0;
  this.scholarships.forEach(s => {
    s.applications.forEach(a => {
      if (a.status === '已公示') total += s.amount;
    });
  });
  return total;
}

顶部统计区域展示进行中项目、总申请数、通过人数、总金额:

this.StatCard(
  '进行中',
  `${this.getOpenCount()}`,
  '#CA8A04',
  '#FEFCE8'
);
this.StatCard(
  '总申请',
  `${this.getTotalApplications()}`,
  '#2563EB',
  '#EFF6FF'
);
this.StatCard(
  '通过',
  `${this.getApprovedCount()}`,
  '#059669',
  '#ECFDF5'
);
this.StatCard(
  '总金额',
  `¥${this.getTotalAmount()}`,
  '#DC2626',
  '#FEF2F2'
);

设置状态颜色

private getStatusColor(status: string): ResourceColor {
  if (status === '待审核') return '#D97706';
  if (status === '审核通过') return '#2563EB';
  if (status === '已公示') return '#059669';
  if (status === '审核不通过') return '#DC2626';
  return '#6B7280';
}

private getStatusBgColor(status: string): ResourceColor {
  if (status === '待审核') return '#FEF3C7';
  if (status === '审核通过') return '#DBEAFE';
  if (status === '已公示') return '#DCFCE7';
  if (status === '审核不通过') return '#FEE2E2';
  return '#F3F4F6';
}
  • 橙色:待审核
  • 蓝色:审核通过
  • 绿色:已公示
  • 红色:审核不通过
  • 灰色:已结束
  • 金色:页面主题色

页面设计说明

应用使用金色作为主题色,体现荣誉、奖励、正式的感觉。

页面主要分为以下区域:

  1. 顶部标题
  2. 数据统计区域
  3. 奖助学金项目列表
  4. 申请入口
  5. 申请状态筛选
  6. 我的申请列表
  7. 评审流程时间线
  8. 审核弹窗

页面采用浅灰色背景和白色卡片。金额使用大号金色字体突出显示,项目类型使用金色标签,评审流程使用时间线展示,公示状态使用绿色徽章。

SDK 配置

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

{
  "name": "default",
  "compatibleSdkVersion": "6.1.1(24)",
  "runtimeOS": "HarmonyOS",
  "targetSdkVersion": "6.1.1(24)",
  "compileSdkVersion": "6.1.1(24)"
}

运行项目

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

entry/src/main/ets/pages/Index.ets

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

项目总结

本文使用 HarmonyOS 和 ArkTS 实现了一个校园奖助学金申请评审应用。

项目实现了项目发布、在线申请、材料提交、辅导员审核、学院评审、结果公示、状态筛选、申请统计等功能。

通过这个项目可以掌握:

  • ArkTS 接口定义和多层嵌套数据结构
  • @State 状态管理
  • 多级评审流程
  • 时间线组件布局
  • ListForEach 列表渲染
  • 金额统计计算
  • 自定义 @Builder 组件
  • HarmonyOS 办公政务类应用布局

后续还可以加入材料上传、绩点自动核验、班级排名公示、异议申诉、奖金发放记录、证书生成、历年获奖查询和消息通知等功能。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐