鸿蒙原生应用 ArkUI 声明式实战:志愿服务我的页等级经验条与成就墙组合技

App 17「志愿服务」我的 Tab(ProfileTab),是个人中心页。整页用渐变用户卡片(小明同学 + Lv.4 + 距 Lv.5 还需 120 经验 + 74% 经验条)+ 4 栏彩色统计(历史订单 28/进行中 3/满意度 98%/连续天数 15)+ 本周使用条形图(20 次/周六高亮)+ 6 徽章成就墙(4 解锁 2 未解锁)+ 5 项菜单(我的收藏带 NEW 角标)+ About。本篇基于 17-volunteer/entry/src/main/ets/pages/ProfileTab.ets(约 226 行)逐段拆解,附 4 张实机截图。

一、整体结构:6 个 @Builder 的红色个人中心

ProfileTab 的结构与 App 13 我的页完全同源(甚至0 个 @State)——"渐变用户卡 + 4 栏统计 + 周图 + 成就墙 + 菜单列表 + About":

build() {
  Column() {
    Scroll() {
      Column({ space: 0 }) {
        this.UserCard()
        this.StatRow()
        this.WeekChartCard()
        this.AchievementWall()
        this.MenuList()
        this.About()
      }
      .width('100%').padding({ bottom: D.pad + this.safeBottom + 20 })
    }
    .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
  }
  .width('100%').height('100%').backgroundColor(C.bg)
}

6 个块顺序:UserCard(身份)→ StatRow(数据)→ WeekChartCard(行为图)→ AchievementWall(成就)→ MenuList(资产)→ About(关于)。

space: 0 让 UserCard 和 StatRow 紧贴——UserCard 渐变 + StatRow 卡片 + margin({ top: -28 }) 让 StatRow "上浮"到 UserCard 底部,形成"卡片叠在用户卡上"的悬浮效果(Material Design 的 elevation)。

与 App 13 我的页完全同源——6 块顺序、布局、负边距悬浮完全一致。唯一差异:主题色(紫→红)+ 文案(音乐→志愿)。

志愿服务我的页首屏 · 红色渐变用户卡+Lv.4+74%经验条+签到/数据报告+4栏统计

项目源码开源:https://gitee.com/codenestFlow/HarmonyOSHub

配图

二、UserCard:渐变 + Lv.4 + 经验条 + 签到

UserCard 是整页的"个人门面"——Stack 双层头像/等级徽章 + 姓名/认证/Slogan + 经验条 + 签到/数据报告双按钮:

@Builder
UserCard() {
  Column({ space: 12 }) {
    Row({ space: 14 }) {
      Stack({ alignContent: Alignment.BottomEnd }) {
        Row() { Text('👤').fontSize(34) }
          .width(60).height(60).backgroundColor('rgba(255,255,255,0.35)').borderRadius(D.rLg).justifyContent(FlexAlign.Center)
          .border({ width: 2, color: 'rgba(255,255,255,0.7)' })
        Row() { Text('Lv.4').fontSize(9).fontColor('#FFFFFF').fontWeight(FontWeight.Bold) }
          .padding({ left: 5, right: 5, top: 1, bottom: 1 })
          .backgroundColor(C.warn).borderRadius(4).border({ width: 1.5, color: '#FFFFFF' })
      }
      Column({ space: 5 }) {
        Row({ space: 8 }) {
          Text('小明同学').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
          Text('认证').fontSize(9).fontColor('#FFFFFF')
            .backgroundColor('rgba(255,255,255,0.3)').padding({ left: 5, right: 5, top: 1, bottom: 1 }).borderRadius(3)
        }
        Text('活跃用户 · 已使用 28 天').fontSize(11).fontColor('rgba(255,255,255,0.85)')
        Row({ space: 4 }) {
          Text('距 Lv.5 还需').fontSize(9).fontColor('rgba(255,255,255,0.7)')
          Text('120').fontSize(11).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)
          Text('经验').fontSize(9).fontColor('rgba(255,255,255,0.7)')
        }
        Stack({ alignContent: Alignment.Start }) {
          Column().width('100%').height(4).backgroundColor('rgba(255,255,255,0.25)').borderRadius(2)
          Column().width('74%').height(4).backgroundColor('#FFFFFF').borderRadius(2)
        }.width(140)
      }.alignItems(HorizontalAlign.Start).layoutWeight(1)
    }.width('100%').padding({ left: D.pad, right: D.pad, top: this.safeTop + 30, bottom: 16 })

    Row() {
      Row({ space: 5 }) {
        Text('🎁').fontSize(11)
        Text('每日签到').fontSize(11).fontColor('#FFFFFF')
      }
      .padding({ left: 12, right: 12, top: 6, bottom: 6 })
      .backgroundColor('rgba(255,255,255,0.2)').borderRadius(D.rSm)
      .onClick(() => { promptAction.showToast({ message: '签到成功 +5 经验' }); })
      Blank()
      Row({ space: 5 }) {
        Text('📊').fontSize(11)
        Text('数据报告').fontSize(11).fontColor('#FFFFFF')
      }
      .padding({ left: 12, right: 12, top: 6, bottom: 6 })
      .backgroundColor('rgba(255,255,255,0.2)').borderRadius(D.rSm)
      .onClick(() => { promptAction.showToast({ message: '数据报告' }); })
    }.width('100%').padding({ left: D.pad, right: D.pad, bottom: 14 })
  }
  .width('100%').linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })
}

2.1 Stack 头像 + Lv.4 徽章

Stack({ alignContent: Alignment.BottomEnd }) {
  Row() { Text('👤').fontSize(34) }
    .width(60).height(60).backgroundColor('rgba(255,255,255,0.35)').borderRadius(D.rLg).justifyContent(FlexAlign.Center)
    .border({ width: 2, color: 'rgba(255,255,255,0.7)' })
  Row() { Text('Lv.4').fontSize(9).fontColor('#FFFFFF').fontWeight(FontWeight.Bold) }
    .padding({ left: 5, right: 5, top: 1, bottom: 1 })
    .backgroundColor(C.warn).borderRadius(4).border({ width: 1.5, color: '#FFFFFF' })
}

Stack({ alignContent: Alignment.BottomEnd }) 让 Lv.4 标签"贴"在头像右下角:

  • 底层:60×60 头像块(半透明白 + 2vp 白色描边) + 👤 emoji
  • 上层:Lv.4 标签,C.warn 橙色底 + 白字 + 1.5vp 白边

注意 Lv.4 徽章是橙色(C.warn)而不是主色红(C.primary——等级徽章用警示色形成"显著标记"(在红色背景的渐变上,橙色比红色更"跳")。

60×60 圆角 20——半透明白(rgba(255,255,255,0.35))+ 2vp 白色描边(rgba(255,255,255,0.7))——在红色渐变上若隐若现。

2.2 姓名 + 认证 + Slogan

  • 姓名:"小明同学" 18sp 加粗白字
  • 认证:"认证" 小胶囊(半透明白底 + 白字)
  • Slogan:"活跃用户 · 已使用 28 天"(11sp 白字 85% 透明)

"小明同学"是系列虚拟角色名(App 13 我的页也是这个名字)——同一套 demo 用了统一的虚拟用户"小明"。真实项目里每个 App 有自己的用户。

2.3 经验值 + 进度条(双通道)

Row({ space: 4 }) {
  Text('距 Lv.5 还需').fontSize(9).fontColor('rgba(255,255,255,0.7)')
  Text('120').fontSize(11).fontColor('#FFFFFF').fontWeight(FontWeight.Bold)
  Text('经验').fontSize(9).fontColor('rgba(255,255,255,0.7)')
}
Stack({ alignContent: Alignment.Start }) {
  Column().width('100%').height(4).backgroundColor('rgba(255,255,255,0.25)').borderRadius(2)
  Column().width('74%').height(4).backgroundColor('#FFFFFF').borderRadius(2)
}.width(140)

"距 Lv.5 还需 120 经验" + "74% 进度条"——双通道表示"成长进度"。

进度条 = 背景(25% 透明白)+ 前景(100% 白、74% 宽)——白色进度条在红色渐变上高对比width(140) 限制最大宽度 140vp。

74% 暗示"还差 26% 升级"——**"具体数字(120 经验)+ 抽象百分比(74%)"**双通道,让用户既知道"还差多少"也看到"走了多远"。

2.4 签到/数据报告双按钮

Row() {
  Row({ space: 5 }) {
    Text('🎁').fontSize(11)
    Text('每日签到').fontSize(11).fontColor('#FFFFFF')
  }
  .padding({ left: 12, right: 12, top: 6, bottom: 6 })
  .backgroundColor('rgba(255,255,255,0.2)').borderRadius(D.rSm)
  .onClick(() => { promptAction.showToast({ message: '签到成功 +5 经验' }); })
  Blank()
  Row({ space: 5 }) {
    Text('📊').fontSize(11)
    Text('数据报告').fontSize(11).fontColor('#FFFFFF')
  }
  .padding({ left: 12, right: 12, top: 6, bottom: 6 })
  .backgroundColor('rgba(255,255,255,0.2)').borderRadius(D.rSm)
  .onClick(() => { promptAction.showToast({ message: '数据报告' }); })
}.width('100%').padding({ left: D.pad, right: D.pad, bottom: 14 })

两个"伪按钮"(背景 + 文字 + emoji)——rgba(255,255,255,0.2) 半透明白底在红色渐变上。中间 Blank() 撑开。

签到点击弹 Toast "签到成功 +5 经验"——注意没有 @State checked(与 App 14/15/16 不同,App 13/17 的签到只弹 Toast 不改状态)。"伪签到"——demo 简化版,不实现真正的签到状态翻转。

2.5 红色 135° 渐变

.width('100%').linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })

#EF4444 → #F87171 135° 渐变——左上鲜红、右下浅红,营造"光从左上洒下"的视觉。App 13 是紫色 8B5CF6 → A78BFA,App 17 是红色 EF4444 → F87171——同一套 135° 渐变结构换主题色

三、StatRow:4 栏统计 + 悬浮效果

StatRow 是 4 个统计数字(历史订单 28/进行中 3/满意度 98%/连续天数 15):

@Builder
StatRow() {
  Row() {
    ForEach(this.stats, (s: StatItem, idx: number) => {
      Column({ space: 3 }) {
        Text(s.value).fontSize(18).fontWeight(FontWeight.Bold).fontColor(s.color)
        Text(s.label).fontSize(10).fontColor(C.textDim)
      }.layoutWeight(1)
      if (idx < this.stats.length - 1) { Divider().vertical(true).height(32).color(C.stroke) }
    }, (s: StatItem) => s.label)
  }
  .width('92%').height(76).backgroundColor(C.card).borderRadius(D.rMd)
  .border({ width: 1, color: C.stroke })
  .justifyContent(FlexAlign.SpaceAround).alignItems(VerticalAlign.Center).margin({ top: -28 })
}

4 色映射

  • 历史订单 28C.primary 红色(聚合)
  • 进行中 3C.accent 浅红(进行中)
  • 满意度 98%C.ok 绿色(成功)
  • 连续天数 15C.warn 橙色(坚持天数)

**margin({ top: -28 }) 负边距让 StatRow "上浮"到 UserCard 底部——视觉上"叠在用户卡上"。width('92%') 比父容器窄 8%,左右各留 4%——"缩进卡片"**让 StatRow 显得嵌在 UserCard 下。

Divider().vertical(true).height(32) 竖向分隔线——每两个数字之间用 1vp 浅灰竖线分隔。if (idx < this.stats.length - 1) 防止最后一条也有分隔线。

alignItems(VerticalAlign.Center) 让 4 个数字在 76vp 高度内垂直居中。

四、WeekChartCard:本周使用条形图(周六高亮)

WeekChartCard 与首页同构(7 天条形图),汇总改为"20 次":

@Builder
WeekChartCard() {
  Column({ space: 12 }) {
    Row() {
      Text('📈 本周使用').fontSize(15).fontWeight(FontWeight.Bold).fontColor(C.text)
      Blank()
      Text('20 次').fontSize(13).fontWeight(FontWeight.Bold).fontColor(C.primary)
    }.width('100%')

    Row({ space: 4 }) {
      ForEach(this.weekBars, (b: WeekBar, idx: number) => {
        Column({ space: 6 }) {
          Column()
            .width(18)
            .height(Math.max(6, b.value / 5 * 80))
            .borderRadius(4)
            .linearGradient({
              angle: 180,
              colors: idx === 5 ? [[C.primary, 0.0], [C.accent, 1.0]] : [[C.primarySoft, 0.0], [C.primary, 1.0]]
            })
          Text(b.day).fontSize(10).fontColor(idx === 5 ? C.primary : C.textDim)
            .fontWeight(idx === 5 ? FontWeight.Bold : FontWeight.Normal)
        }.layoutWeight(1).alignItems(HorizontalAlign.Center)
      }, (b: WeekBar) => b.day)
    }.width('100%')
  }
  .width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd)
  .border({ width: 1, color: C.stroke })
  .margin({ top: 14, left: D.pad, right: D.pad })
}

数据:2/3/1/4/3/5/2——周六(idx=5)value=5 最高周三(idx=2)value=1 最低

b.value / 5 * 80 归一化(最大值 5 → 80vp)——让最高柱顶到 80vp 上限。

"周六高亮"是写死的idx === 5),与首页 App 13 同款(首页 selectedBar = 4 是动态的,本页是写死的)——"动态 vs 静态高亮"的两种实现

汇总"20 次":2+3+1+4+3+5+2 = 20——汇总严格等于各柱之和(App 14 +385 严格自洽、App 16 -3,700 不一致,App 17 同样严格自洽)。

五、AchievementWall:6 徽章成就墙(4 解锁)

AchievementWall 是 6 个徽章的横向 Row(一行 6 个):

@Builder
AchievementWall() {
  Column({ space: 12 }) {
    Row() {
      Text('🏅 成就徽章').fontSize(15).fontWeight(FontWeight.Bold).fontColor(C.text)
      Blank()
      Text(`${this.achievements.filter(a => a.unlocked).length}/${this.achievements.length}`).fontSize(11).fontColor(C.primary)
    }.width('100%')

    Row() {
      ForEach(this.achievements, (item: Achievement) => {
        Column({ space: 6 }) {
          Row() { Text(item.icon).fontSize(24) }
            .width(48).height(48).borderRadius(D.rMd).justifyContent(FlexAlign.Center)
            .backgroundColor(item.unlocked ? C.primarySoft : C.cardSoft)
            .opacity(item.unlocked ? 1 : 0.4)
          Text(item.title).fontSize(9).fontColor(item.unlocked ? C.text : C.textDim)
          Text(item.desc).fontSize(7).fontColor(C.textDim).maxLines(1)
        }.layoutWeight(1)
      }, (item: Achievement) => item.title)
    }.width('100%')
  }
  .width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd)
  .border({ width: 1, color: C.stroke })
  .margin({ top: 14, left: D.pad, right: D.pad })
}

6 个公益徽章

  • 🎯 初次使用(解锁)— 第一次下单
  • 🔥 活跃用户(解锁)— 使用 7 天
  • ⭐ 好评达人(解锁)— 5 星好评 10 次
  • 💰 省钱能手(解锁)— 节省 100 元
  • 👑 资深用户(未解锁)— 使用 100 天
  • 💎 完美用户(未解锁)— 满意度 100%

注意"省钱能手"——志愿服务没有"省钱"概念,但徽章是通用的("节省 100 元"可能是"为公益节省成本 100 元")。"徽章名 = 业务语义"的弱关联——App 13 我的页也用同样的 6 个徽章。这是"模板换肤"的副作用:徽章文案没换,但页面主题已换。真实项目应让徽章名跟随业务调整(如"志愿时长 100 小时"取代"省钱 100 元")。

解锁/未解锁三件套(背景/透明度/文字):

.backgroundColor(item.unlocked ? C.primarySoft : C.cardSoft)
.opacity(item.unlocked ? 1 : 0.4)
  • 解锁:浅红背景 + 100% 不透明 + 深色文字
  • 未解:浅灰背景 + 40% 透明("灰蒙感")+ 灰色文字

opacity: 0.4 关键——比单纯换背景色更直接传达"未解锁"。

4/6 动态计算(用 .filter().length)——this.achievements.filter(a => a.unlocked).length 实时算出已解锁数。"动态 vs 硬编码":App 13 我的页同款用了动态计算,App 14/15 用了硬编码(之前文章也指出了这是 App 14/15 的"回退")。App 17 用动态计算更好

六、MenuList:5 项菜单 + NEW 角标

MenuList 是 5 个菜单项(历史订单/消费统计/提醒设置/我的收藏/设置)的纵向列表:

@Builder
MenuList() {
  Column() {
    ForEach(this.menus, (m: MenuItem, idx: number) => {
      Column() {
        Row({ space: 12 }) {
          Row() { Text(m.emoji).fontSize(20) }
            .width(36).height(36).backgroundColor(C.cardSoft).borderRadius(D.rSm).justifyContent(FlexAlign.Center)
          Column({ space: 2 }) {
            Text(m.title).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text)
            Text(m.desc).fontSize(11).fontColor(C.textDim)
          }.alignItems(HorizontalAlign.Start).layoutWeight(1)
          if (m.badge.length > 0) {
            Text(m.badge).fontSize(9).fontColor('#FFFFFF')
              .backgroundColor(m.badge === 'NEW' ? C.ok : C.danger)
              .padding({ left: 5, right: 5, top: 1, bottom: 1 }).borderRadius(D.rSm)
          }
          Text('›').fontSize(22).fontColor(C.textDim)
        }
        .width('100%').padding(14)
        .onClick(() => { promptAction.showToast({ message: m.title }); })
        if (idx < this.menus.length - 1) { Divider().color(C.stroke).margin({ left: 58 }) }
      }
    }, (m: MenuItem) => m.title)
  }
  .width('100%').backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
  .margin({ top: 14, left: D.pad, right: D.pad }).clip(true)
}

5 项菜单

  • 📦 历史订单 — 查看所有历史记录
  • 📊 消费统计 — 月度数据分析
  • 🔔 提醒设置 — 订单状态通知
  • ⭐ 我的收藏 — 常用列表(NEW 角标
  • ⚙️ 设置 — 账号与隐私

"NEW" 角标

if (m.badge.length > 0) {
  Text(m.badge).fontSize(9).fontColor('#FFFFFF')
    .backgroundColor(m.badge === 'NEW' ? C.ok : C.danger)
    .padding({ left: 5, right: 5, top: 1, bottom: 1 }).borderRadius(D.rSm)
}
  • NEW → C.ok 绿色(清新新功能)
  • 数字 → C.danger 红色(待办提醒)

if (m.badge.length > 0) 条件渲染——空字符串 '' 视为"无角标"。

Divider().color(C.stroke).margin({ left: 58 }) ——分隔线不贯穿全宽(从图标右侧开始),iOS 风格。if (idx < this.menus.length - 1) 防止最后一条也加分隔线(用 idx 判断比 m.id < length 可靠)。

.clip(true):整张菜单卡的圆角对内部 Divider 也生效——父容器圆角 + 子内容裁剪的标准做法。

七、About:版本号

@Builder
About() {
  Column({ space: 4 }) {
    Text('Version 1.0.0').fontSize(12).fontColor(C.textDim)
    Text('HarmonyOS 6.0+ · ArkTS · API 23').fontSize(10).fontColor(C.textDim)
  }
  .width('100%').padding({ top: 24, bottom: 10 }).alignItems(HorizontalAlign.Center)
}

Version 1.0.0 + HarmonyOS 6.0+ · ArkTS · API 23 底部版本信息,10-12sp 灰色居中。padding({ top: 24 }) 让 About 与上方 MenuList 拉开 24vp 间距。

注意 About 只有 2 行(与 App 14/15/16 的 3 行不同,少了"版权 © 2024")——这是 App 13 我的页的简化版

志愿服务我的页中段 · 4栏统计+本周使用条形图(周六高亮)+6徽章成就墙+5项菜单

八、@State 数量 = 0(与 App 13 同款)

ProfileTab 0 个 @State——所有数据 private 不可变。与 App 14/15/16 的 1 个 checked 不同——App 17 完全没有交互(签到只弹 Toast 不改状态)。

4 个 Tab 的 @State 分布

页面@State 数量类型
首页2可交互
活动5表单
记录1筛选
我的0纯展示

"@State 0"与 App 13 同款"个人中心纯展示"——App 13 也是 0 个,App 14/15/16 是 1 个。"0 @State 个人中心"是 App 13/17 这类"模板复刻"的副作用——签到交互被简化。

"@State 数量 = 交互点数"规律:0 = 纯展示、1 = 简单筛选/签到、5 = 表单。模板复刻的 0 @State 版本是合理的简化——读者想看更完整的签到交互可以参考 App 14/15/16。

志愿服务我的页底部 · 完整菜单+About版本信息+底部Tab栏

九、个人中心的"红色"调性

App 17 整个个人中心用红色(#EF4444)主导——

  • UserCard 渐变:红→浅红,传达"公益热情"
  • StatRow 数字:历史订单红、进行中浅红
  • WeekChartCard 柱子:红色渐变(与首页同款)
  • AchievementWall 已解锁徽章:浅红背景
  • MenuList 图标块:浅灰(C.cardSoft)保持简洁

"红色" 调性贯穿:UserCard(最显眼)→ StatRow(数字)→ 周图(行为)→ 成就(已解锁)→ 菜单(资产)。5 个层次都用红色用户从任何一个模块都感受到"志愿红"的品牌

与 App 14/15/16 的"个人中心"对比

App主题用户等级签到状态
13 音乐紫 #8B5CF6小明Lv.40 @State
14 运动绿 #16A34A张运动Lv.5+101 @State
15 环保绿 #22C55E李环保Lv.6+51 @State
16 商城玫红 #F43F5E王积分Lv.7+201 @State
17 志愿红 #EF4444小明Lv.40 @State

App 17 与 App 13 完全一致(小明/Lv.4/伪签到/0 @State)——再次印证"模板复刻"对比 App 14/15/16 的渐进(Lv.5→6→7、签到 +10→5→20、1 @State),App 17 退回了最简化版本。

十、总结:本系列"个人中心"模板的 5 次复用

回顾系列 5 个"个人中心"(App 13/14/15/16/17),6 个 @Builder 块完全同源(UserCard/StatRow/WeekChartCard/AchievementWall/MenuList/About):

维度App 13App 14App 15App 16App 17
主题色绿绿玫红
用户小明张运动李环保王积分小明
等级Lv.4Lv.5Lv.6Lv.7Lv.4
经验74%64%62%57%74%
签到+10+5+20
统计通用运动环保商城通用
成就6 通用6 运动6 环保6 商城6 通用
菜单56665
@State01110

5 次复用展示了 ArkUI "个人中心"模板的极致稳定性——**"6 个 @Builder + 1 个 Scroll 容器"**承载了任意主题/业务/数据。

真实项目套用建议

  1. 复制任意一个 App 的 ProfileTab 源码
  2. 改 Theme.ets 的 3 个颜色(primary/accent/primarySoft)
  3. 改 4 个数据数组(stats/weekBars/achievements/menus)+ 3 个标量值(用户名/经验/等级)
  4. 改 Slogan 文案
  5. 改 README 的 App 名/bundleName

5 步换肤 = 5 分钟生成一个全新个人中心——这是 ArkUI 模板设计的最高境界。

志愿服务我的页中下部 · 6徽章成就墙完整(4解锁2未解锁)+5项菜单完整

十一、徽章的"业务语义"重写(与 App 13 不同的建议)

App 17 复用了 App 13 的 6 个徽章("省钱能手""完美用户"等),但这些徽章与志愿服务的业务语义不匹配——志愿者不"省钱"、不"消费"。

真实项目应重写徽章

App 13 徽章App 17 应改为
🎯 初次使用🤝 初次参加
🔥 活跃用户🔥 活跃志愿者
⭐ 好评达人⭐ 服务明星
💰 省钱能手💯 服务100h(时长)
👑 资深用户👑 资深志愿者
💎 完美用户💎 公益大使

"徽章名 = 业务成就"——徽章应该让志愿者一眼读懂"我达成了一个什么成就",而不是"省钱 100 元"这种电商逻辑。

"模板复刻"不是"完全照抄"——数据/文案要跟随业务调整,否则会出现"省钱能手"出现在志愿 App 这种违和感。真实项目套用模板时必改业务字段(用户名/徽章名/统计项/菜单/周图数据)。

改进建议

  1. 复制 App 13 我的页源码
  2. 改 Theme.ets 3 个颜色(primary/accent/primarySoft)
  3. 改 4 个数据数组 + 3 个标量值(注意:徽章名要符合新业务)
  4. 改 Slogan 文案(小红帽/小志愿者/小公益人)
  5. 改 About 版本号(Version 1.0.0 → 新版本)

5 步换肤 + 业务适配 = 5 分钟生成新应用

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐