HarmonyOS ArkTS 实战:实现一个校园助学贷款申请与还款应用

项目效果

本文使用 HarmonyOS 和 ArkTS 实现一个校园助学贷款申请与还款应用。

应用可以在线申请贷款,查看审批进度,贷款合同查看,在线还款,并提供还款计划、逾期提醒、贷款计算器、政策咨询等完整功能。

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

运行效果

校园助学贷款申请与还款应用

功能介绍

  • 贷款产品介绍
  • 在线申请贷款
  • 材料上传
  • 审批进度查询
  • 贷款合同查看
  • 还款计划
  • 在线还款
  • 逾期提醒
  • 贷款计算器
  • 政策咨询
  • 历史贷款记录
  • 征信说明

定义数据结构

interface LoanApplication {
  id: number;
  type: string;
  amount: number;
  year: number;
  reason: string;
  applyTime: string;
  status: string; // 草稿/待审核/审核中/已通过/已拒绝/已放款
  progress: number;
}

interface RepaymentPlan {
  id: number;
  loanId: number;
  period: number;
  dueDate: string;
  amount: number;
  principal: number;
  interest: number;
  status: string; // 待还款/已还款/逾期
}

初始化页面状态

@State private tabIndex: number = 0;
@State private totalLoan: number = 32000;
@State private totalRepaid: number = 8000;
@State private nextDueAmount: number = 1200;
@State private nextDueDate: string = '2026-09-20';

@State private applications: LoanApplication[] = [
  { id: 1, type: '生源地助学贷款', amount: 16000, year: 2024, reason: '学费和住宿费', applyTime: '2024-08-15', status: '已放款', progress: 100 },
  { id: 2, type: '校园地助学贷款', amount: 16000, year: 2025, reason: '学费和住宿费', applyTime: '2025-08-20', status: '已放款', progress: 100 },
];

@State private plans: RepaymentPlan[] = [
  { id: 1, loanId: 1, period: 1, dueDate: '2026-09-20', amount: 1200, principal: 1000, interest: 200, status: '待还款' },
  { id: 2, loanId: 1, period: 2, dueDate: '2027-09-20', amount: 1200, principal: 1000, interest: 200, status: '待还款' },
];

@State private nextId: number = 10;

申请贷款

private applyLoan(type: string, amount: number, year: number, reason: string): void {
  const app: LoanApplication = {
    id: this.nextId, type, amount, year, reason,
    applyTime: new Date().toLocaleDateString(), status: '待审核', progress: 20
  };
  this.applications = [app, ...this.applications];
  this.nextId += 1;
}

还款

private repay(planId: number): void {
  const plan = this.plans.find(p => p.id === planId);
  if (!plan) return;
  
  this.plans = this.plans.map(p => p.id === planId ? { ...p, status: '已还款' } : p);
  this.totalRepaid += plan.amount;
}

计算月供

private calculateMonthlyPayment(principal: number, annualRate: number, years: number): number {
  const monthlyRate = annualRate / 12;
  const n = years * 12;
  return principal * monthlyRate * Math.pow(1 + monthlyRate, n) / (Math.pow(1 + monthlyRate, n) - 1);
}

申请卡片组件

@Builder
ApplicationCard(app: LoanApplication) {
  Column({ space: 8 }) {
    Row() {
      Text(app.type)
        .fontSize(16)
        .fontWeight(FontWeight.Medium)
        .fontColor('#450A0A')
      Blank()
      Text(app.status)
        .fontSize(12)
        .fontColor(app.status === '已放款' ? '#059669' : '#F59E0B')
        .padding({ left: 8, right: 8, top: 4, bottom: 4 })
        .backgroundColor(app.status === '已放款' ? '#D1FAE5' : '#FEF3C7')
        .borderRadius(10)
    }
    .width('100%')
    
    Text(`金额:¥${app.amount} | ${app.year}学年`)
      .fontSize(13)
      .fontColor('#7F1D1D')
    
    Progress({ value: app.progress, total: 100, type: ProgressType.Linear })
      .width('100%')
      .color('#DC2626')
      .backgroundColor('#FEE2E2')
  }
  .width('100%')
  .padding(16)
  .backgroundColor('#FEF2F2')
  .borderRadius(12)
}

页面布局

build() {
  Column() {
    // 顶部贷款概览
    Column({ space: 12 }) {
      Text('我的助学贷款')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.White)
      Row({ space: 20 }) {
        Column() {
          Text(`¥${this.totalLoan}`)
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
            .fontColor(Color.White)
          Text('贷款总额')
            .fontSize(12)
            .fontColor('#FECACA')
        }
        Column() {
          Text(`¥${this.totalRepaid}`)
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
            .fontColor(Color.White)
          Text('已还金额')
            .fontSize(12)
            .fontColor('#FECACA')
        }
        Column() {
          Text(`¥${this.nextDueAmount}`)
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
            .fontColor('#FBBF24')
          Text('下期应还')
            .fontSize(12)
            .fontColor('#FECACA')
        }
      }
      .width('100%')
    }
    .width('100%')
    .padding(20)
    .backgroundColor('#450A0A')
    
    // Tab
    Row({ space: 20 }) {
      Text('我的申请')
        .fontSize(16)
        .fontWeight(this.tabIndex === 0 ? FontWeight.Bold : FontWeight.Normal)
        .fontColor(this.tabIndex === 0 ? '#450A0A' : '#94A3B8')
        .onClick(() => this.tabIndex = 0)
      Text('还款计划')
        .fontSize(16)
        .fontWeight(this.tabIndex === 1 ? FontWeight.Bold : FontWeight.Normal)
        .fontColor(this.tabIndex === 1 ? '#450A0A' : '#94A3B8')
        .onClick(() => this.tabIndex = 1)
    }
    .width('100%')
    .padding({ left: 20, right: 20, top: 20 })
    
    if (this.tabIndex === 0) {
      List({ space: 12 }) {
        ForEach(this.applications, (a: LoanApplication) => {
          ListItem() { this.ApplicationCard(a) }
        })
      }
      .width('100%')
      .padding(20)
      .layoutWeight(1)
      
      Button('+ 新申请')
        .width('90%')
        .height(48)
        .fontSize(16)
        .backgroundColor('#450A0A')
        .borderRadius(24)
        .margin({ bottom: 20 })
        .onClick(() => this.applyLoan('校园地助学贷款', 16000, 2026, '学费住宿费'))
    } else {
      List({ space: 12 }) {
        ForEach(this.plans, (p: RepaymentPlan) => {
          ListItem() {
            Row() {
              Column({ space: 4 }) {
                Text(`${p.period}`)
                  .fontSize(15)
                  .fontWeight(FontWeight.Medium)
                Text(`到期:${p.dueDate}`)
                  .fontSize(12)
                  .fontColor('#7F1D1D')
                Text(`本金¥${p.principal} + 利息¥${p.interest}`)
                  .fontSize(12)
                  .fontColor('#94A3B8')
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1)
              
              Column({ space: 4 }) {
                Text(`¥${p.amount}`)
                  .fontSize(18)
                  .fontWeight(FontWeight.Bold)
                  .fontColor('#DC2626')
                if (p.status === '待还款') {
                  Button('还款')
                    .fontSize(12)
                    .height(32)
                    .backgroundColor('#DC2626')
                    .onClick(() => this.repay(p.id))
                } else {
                  Text('已还款')
                    .fontSize(12)
                    .fontColor('#059669')
                }
              }
            }
            .width('100%')
            .padding(16)
            .backgroundColor('#FEF2F2')
            .borderRadius(12)
          }
        })
      }
      .width('100%')
      .padding(20)
      .layoutWeight(1)
    }
  }
  .width('100%')
  .height('100%')
  .backgroundColor(Color.White)
}

页面设计说明

主题色采用red-950#450A0A,深红色体现金融贷款的严谨、正式。顶部深色区域展示贷款概览,进度条显示审批进度,还款计划清晰列出每期金额。

SDK配置

API 24,compatibleSdkVersion: “6.1.1(24)”

运行项目

将代码复制到 entry/src/main/ets/pages/Index.ets 即可运行。

项目总结

实现了贷款申请、审批进度、还款计划、在线还款、贷款计算等功能。掌握了进度条组件、金融计算、状态流转、深色顶部设计等。后续可加入材料上传、合同电子签、自动扣款、征信查询、政策问答、毕业确认等功能。

Logo

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

更多推荐