在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、设计思路

延安精神学习应用采用"概述 → 核心内涵 → 圣地巡礼 → 经典故事 → 大事记"五段式信息架构。每个版块是一组结构化数据,页面用 Scroll + Column 纵向滚动承载全部内容。核心交互是"点击展开"——三组数据(内涵 / 圣地 / 故事)各自独立管理展开状态,互不干扰。

二、数据模型:三种实体 + 一个特色实体

interface SpiritItem { id: number; title: string; content: string; practice: string; }
interface PlaceItem  { id: number; name: string; desc: string; }
interface StoryItem  { id: number; title: string; content: string; }
interface TimeItem   { id: number; year: string; event: string; }

SpiritItem 多一个 practice(现实启示)字段——每个内涵都落到"今天该怎么做",这是思政学习应用的灵魂:历史精神要与当下生活挂钩。

核心内涵四条:

内涵 对应实践
坚定正确的政治方向 理想信念不动摇,听党话、跟党走
解放思想、实事求是 不唯书、不唯上、只唯实
全心全意为人民服务 人民至上,做群众贴心人
自力更生、艰苦奋斗 苦干实干,拒绝"躺平"

三、多组展开状态:三个 expandedId 独立管理

页面同时存在三组可展开列表(内涵、圣地、故事),若共用一个 expandedId,会出现"展开圣地时内涵全收起"的串扰。正确做法是每组一个独立状态

@State expandedCore: number = -1;   // 内涵展开
@State expandedPlace: number = -1;  // 圣地展开
@State expandedStory: number = -1;  // 故事展开

为了消除三个卡片的重复 onClick 逻辑,抽一个通用 toggle:

toggle(id: number, cur: number, set: (v: number) => void): void {
  set(cur === id ? -1 : id);
}

注意:ArkTS 不支持直接把 @State 字段按引用传递,所以 set 回调写法是 (v: number) => { this.expandedCore = v; }——用闭包捕获 this,绕开"按值传递"的限制。这是 ArkTS 状态管理的常见技巧。

调用方式:

.onClick(() => { this.toggle(item.id, this.expandedCore, (v: number) => { this.expandedCore = v; }); })

四、大事记时间轴:Row 三列布局

特色版块"延安十三年大事记"(1935→1948 共 9 条)用固定宽度时间列 + 节点列 + 内容列实现:

@Builder
timelineView() {
  Column() {
    ForEach(this.timeline, (t: TimeItem) => {
      Row() {
        Text(t.year)                              // 第一列:时间(固定 64 宽)
          .fontSize(12).fontWeight(FontWeight.Bold).fontColor('#92400E')
          .width(64).textAlign(TextAlign.Center)
        Column() { Text('●') }                    // 第二列:节点圆点
          .width(20).alignItems(HorizontalAlign.Center)
        Text(t.event)                             // 第三列:事件(弹性)
          .fontSize(13).fontColor('#4B5563')
          .layoutWeight(1).textAlign(TextAlign.Start)
      }
      .width('100%').alignItems(VerticalAlign.Top)
      .padding({ top: 8, bottom: 8 })
      .border({ width: { bottom: 1 }, color: '#FDE68A' })  // 行分隔线
    }, (t: TimeItem) => t.id.toString())
  }
  .width('100%').padding(14)
  .backgroundColor('#FFFBEB').borderRadius(14)
}

要点:

  • 固定宽度列width(64))+ 弹性列layoutWeight(1))组合,保证时间列对齐。
  • alignItems(VerticalAlign.Top) 让多行事件文本与时间列顶部对齐。
  • 分隔线用 border({ width: { bottom: 1 } }),比 Divider 更简洁。
  • 事件较长时, 节点在第二列水平居中,视觉上是标准时间轴。

五、主题色系统:同一架构三种配色

三个精神页面结构完全一致,仅靠主题色区分气质:

应用 主色 浅色底 语义
延安 #B45309 土黄 #FEF3C7 黄土高原、窑洞
井冈山 #047857 山绿 #ECFDF5 绿色革命摇篮
西柏坡 #1D4ED8 #EFF6FF 解放指挥所

配色集中在 sectionTitleoverviewCard、卡片边框等少数位置,改色只动常量——主题化是 UI 复用的最佳实践

六、技术要点总结

技术点 实现方式
多组展开 三个独立 expandedId 状态
通用 toggle 回调 set 闭包捕获 this
时间轴 固定宽列 + 弹性列 + 底部边框分隔
长页滚动 Scroll + Column + layoutWeight(1)
主题色 主色/浅底两套色值全页复用
数据驱动 加条目不改代码,改数组即改内容

"精神学习类"应用模板:概述 + 内涵 + 圣地 + 故事 + 特色版块,五段式信息架构可直接复用到任何革命精神、文化主题的学习应用。

Logo

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

更多推荐