本篇开发职业性格测试模块,包括古代官场测试和现代职业测试

【完整案例】职业性格测试开发 教程结构图

图:【完整案例】职业性格测试开发 的关键流程与实现要点。

学习目标

  • ✅ 设计测试题目与选项
  • ✅ 实现答题流程与进度
  • ✅ 开发结果计算算法
  • ✅ 设计结果展示页面

预计学习时间

约 120 分钟


实战一:设计测试数据结构

第一步:定义题目接口

entry/src/main/ets/common/Types.ets 中添加测试相关类型:

// 测试题目接口
interface TestQuestion {
  id: number;
  question: string;
  options: TestOption[];
}

// 测试选项接口
interface TestOption {
  value: string;      // 选项值,用于计算结果
  text: string;       // 选项主文本
  subtext: string;    // 选项副文本(解释说明)
}

// 测试记录接口
interface TestRecord {
  testType: 'ancient' | 'modern';
  resultType: string;
  matchScore: number;
  timestamp: number;
}

原理解释

  • value 用于结果计算,如 MBTI 测试中的 E/I、S/N、T/F、J/P
  • subtext 提供选项的补充说明,帮助用户理解选项含义

第二步:设计古代官场测试题目

创建 10 道情景选择题,每题 4 个选项:

const ANCIENT_QUESTIONS: TestQuestion[] = [
  {
    id: 1,
    question: '假如初入官场,上司命你处理一件涉及权贵的棘手税务案件,你会如何应对?',
    options: [
      { value: 'A', text: '秉公执法,严查到底', subtext: '不畏强权,只求无愧于心' },
      { value: 'B', text: '圆滑处理,暗中请示', subtext: '两不得罪,以求自保' },
      { value: 'C', text: '请教官场前辈,依照旧例', subtext: '萧规曹随,稳妥为上' },
      { value: 'D', text: '称病推脱,避开是非', subtext: '明哲保身,不接烫手山芋' }
    ]
  },
  {
    id: 2,
    question: '朝廷派你去边疆赈灾,当地官员贪腐严重,你会如何处理?',
    options: [
      { value: 'A', text: '直接弹劾,上报朝廷', subtext: '铁面无私,为民请命' },
      { value: 'B', text: '先稳住局面,暗中收集证据', subtext: '谋定后动,步步为营' },
      { value: 'C', text: '与当地官员协商,各退一步', subtext: '以和为贵,共谋发展' },
      { value: 'D', text: '专注赈灾,不管闲事', subtext: '各司其职,完成使命' }
    ]
  },
  // ... 更多题目
];

第三步:设计现代职业测试题目(MBTI 风格)

const MODERN_QUESTIONS: TestQuestion[] = [
  {
    id: 1,
    question: '在团队会议中,你通常会?',
    options: [
      { value: 'E', text: '积极发言,分享想法', subtext: '喜欢在讨论中表达观点' },
      { value: 'I', text: '倾听为主,深思熟虑后发言', subtext: '更愿意先思考再表达' }
    ]
  },
  {
    id: 2,
    question: '面对一个新项目,你更倾向于?',
    options: [
      { value: 'S', text: '关注具体细节和实际操作', subtext: '脚踏实地,注重可行性' },
      { value: 'N', text: '思考整体愿景和创新可能', subtext: '着眼未来,追求突破' }
    ]
  },
  {
    id: 3,
    question: '做决策时,你更看重?',
    options: [
      { value: 'T', text: '逻辑分析和客观数据', subtext: '理性判断,追求效率' },
      { value: 'F', text: '团队感受和人际和谐', subtext: '重视关系,关注影响' }
    ]
  },
  {
    id: 4,
    question: '对于工作计划,你更喜欢?',
    options: [
      { value: 'J', text: '提前规划,按部就班', subtext: '有条不紊,掌控全局' },
      { value: 'P', text: '灵活应变,随机调整', subtext: '保持弹性,适应变化' }
    ]
  }
  // ... 共12道题,每个维度3道
];

预期效果:题目设计完成,古代测试 10 题,现代测试 12 题。

预期效果:题目设计完成,古代测试 10 题,现代测试 12 题。

案例效果:测试主页展示如下:

┌──────────────────────────────────────┐
│  ← 性格测试                         │
├──────────────────────────────────────┤
│                                      │
│    探索你的职业性格                   │
│                                      │
│  ┌══════════════════════════════┐   │
│  ║  🏛️  古代官场测试            ║   │
│  ║                              ║   │
│  ║  10道情景题,测测你在古代    ║   │
│  ║  官场中属于哪种类型          ║   │
│  ║                              ║   │
│  ║  上次结果: 谋臣智士  90分    ║   │
│  └══════════════════════════════┘   │
│                                      │
│  ┌══════════════════════════════┐   │
│  ║  💼  现代职业测试 (MBTI)     ║   │
│  ║                              ║   │
│  ║  12道选择题,发现你的        ║   │
│  ║  职业性格类型                ║   │
│  ║                              ║   │
│  ║  上次结果: INTJ 策略家  88分 ║   │
│  └══════════════════════════════┘   │
│                                      │
│  ── 测试历史 ──                     │
│  谋臣智士  90分  2024-01-15         │
│  INTJ      88分  2024-01-14         │
└──────────────────────────────────────┘

效果说明: - 两张测试入口卡片,分别对应古代和现代测试 - 卡片底部显示上次测试结果(如有) - 下方展示测试历史记录列表


实战二:实现答题页面

第一步:创建答题页面基础结构

@Component
struct AncientTestPage {
  @Consume('mainNavPathStack') mainNavPathStack: NavPathStack;
  @StorageLink('isDarkMode') isDarkMode: boolean = true;
  
  @State currentQuestion: number = 0;      // 当前题目索引
  @State selectedAnswer: string = '';       // 当前选中答案
  @State answers: string[] = [];            // 所有答案记录

  private questions: TestQuestion[] = ANCIENT_QUESTIONS;

  build() {
    NavDestination() {
      Stack() {
        // 背景
        Column()
          .width('100%')
          .height('100%')
          .backgroundColor(this.isDarkMode ? '#221210' : '#f8f6f5')

        Column() {
          // 顶部栏
          this.HeaderBar()
          // 进度条
          this.ProgressSection()
          // 题目和选项
          Scroll() {
            Column() {
              this.QuestionSection()
              this.OptionsSection()
            }
            .padding({ left: 20, right: 20, bottom: 100 })
          }
          .layoutWeight(1)
          .scrollBar(BarState.Off)
        }
        .width('100%')
        .height('100%')

        // 底部按钮
        this.BottomButton()
      }
    }
    .hideTitleBar(true)
  }
}

第二步:实现进度条组件

@Builder
ProgressSection() {
  Column({ space: 8 }) {
    Row() {
      Text(`QUESTION ${(this.currentQuestion + 1).toString().padStart(2, '0')}`)
        .fontSize(12)
        .fontWeight(FontWeight.Bold)
        .fontColor('#c41e3a')
        .letterSpacing(2)

      Blank()

      Text(`${this.currentQuestion + 1} / ${this.questions.length}`)
        .fontSize(12)
        .fontColor(this.isDarkMode ? 'rgba(255,255,255,0.4)' : '#9ca3af')
    }
    .width('100%')

    // 进度条
    Stack({ alignContent: Alignment.Start }) {
      // 背景
      Column()
        .width('100%')
        .height(6)
        .borderRadius(3)
        .backgroundColor(this.isDarkMode ? '#2d1f1d' : '#e5e7eb')

      // 进度
      Column()
        .width(`${((this.currentQuestion + 1) / this.questions.length) * 100}%`)
        .height(6)
        .borderRadius(3)
        .backgroundColor('#c41e3a')
        .shadow({ radius: 8, color: 'rgba(196, 30, 58, 0.5)', offsetY: 0 })
    }
    .width('100%')
  }
  .width('100%')
  .padding({ left: 20, right: 20, top: 16, bottom: 8 })
}

原理解释

  • 使用 Stack 叠加背景和进度条
  • 进度宽度通过百分比动态计算
  • shadow 添加发光效果增强视觉

第三步:实现选项组件

@Builder
OptionItem(option: TestOption) {
  Row({ space: 16 }) {
    // 单选指示器
    Column() {
      if (this.selectedAnswer === option.value) {
        Column()
          .width(12)
          .height(12)
          .borderRadius(6)
          .backgroundColor('#c41e3a')
      }
    }
    .width(24)
    .height(24)
    .borderRadius(12)
    .border({
      width: 2,
      color: this.selectedAnswer === option.value ? '#c41e3a' :
        (this.isDarkMode ? 'rgba(255,255,255,0.3)' : '#d1d5db')
    })
    .justifyContent(FlexAlign.Center)

    // 选项内容
    Column({ space: 4 }) {
      Text(option.text)
        .fontSize(15)
        .fontWeight(FontWeight.Medium)
        .fontColor(this.isDarkMode ? 'rgba(255,255,255,0.9)' : '#1e293b')

      Text(option.subtext)
        .fontSize(12)
        .fontColor(this.isDarkMode ? 'rgba(255,255,255,0.4)' : '#9ca3af')
    }
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Start)

    // 选中图标
    if (this.selectedAnswer === option.value) {
      Image($r('app.media.ic_check'))
        .width(20)
        .height(20)
        .fillColor('#c41e3a')
    }
  }
  .width('100%')
  .padding(16)
  .borderRadius(12)
  .backgroundColor(this.selectedAnswer === option.value ?
    'rgba(196, 30, 58, 0.1)' :
    (this.isDarkMode ? 'rgba(52, 28, 24, 0.5)' : Color.White))
  .border({
    width: 1,
    color: this.selectedAnswer === option.value ? '#c41e3a' :
      (this.isDarkMode ? 'rgba(255,255,255,0.1)' : '#e5e7eb')
  })
  .onClick(() => {
    this.selectedAnswer = option.value;
  })
}

第四步:实现答题流程控制

// 下一题或提交
goToNext() {
  // 保存当前答案
  this.answers[this.currentQuestion] = this.selectedAnswer;

  if (this.currentQuestion < this.questions.length - 1) {
    // 下一题
    this.currentQuestion++;
    // 恢复之前的答案(如果有)
    this.selectedAnswer = this.answers[this.currentQuestion] || '';
  } else {
    // 完成测试,跳转到结果页
    this.mainNavPathStack.pushPathByName('AncientTestResultPage', {
      answers: this.answers
    });
  }
}

// 底部按钮
@Builder
BottomButton() {
  Column() {
    Button() {
      Row({ space: 8 }) {
        Text(this.currentQuestion < this.questions.length - 1 ? '下一题' : '查看结果')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
        Image($r('app.media.ic_arrow_right'))
          .width(20)
          .height(20)
          .fillColor(Color.White)
      }
    }
    .width('100%')
    .height(52)
    .backgroundColor(this.selectedAnswer ? '#c41e3a' : 'rgba(196, 30, 58, 0.5)')
    .borderRadius(12)
    .enabled(this.selectedAnswer !== '')
    .onClick(() => this.goToNext())
  }
  .width('100%')
  .padding({ left: 16, right: 16, bottom: 32 })
  .position({ x: 0, y: '100%' })
  .translate({ y: -100 })
}

预期效果:点击选项选中,点击按钮进入下一题,最后一题显示"查看结果"。

预期效果:点击选项选中,点击按钮进入下一题,最后一题显示"查看结果"。

案例效果:答题页面展示如下:

┌──────────────────────────────────────┐
│  ← 古代官场测试                     │
├──────────────────────────────────────┤
│  QUESTION 03            3 / 10      │
│  ▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░  │ ← 红色进度条 + 发光效果
├──────────────────────────────────────┤
│                                      │
│  朝廷派你去边疆赈灾,当地官员        │
│  贪腐严重,你会如何处理?            │
│                                      │
│  ┌──────────────────────────────┐   │
│  │ ○  直接弹劾,上报朝廷       │   │
│  │    铁面无私,为民请命        │   │  ← 灰色副文本
│  └──────────────────────────────┘   │
│  ┌══════════════════════════════┐   │
│  ║ ◉  先稳住局面,暗中收集   ✓ ║   │  ← 选中: 红色边框
│  ║    谋定后动,步步为营        ║   │     红色圆点 + ✓
│  └══════════════════════════════┘   │
│  ┌──────────────────────────────┐   │
│  │ ○  与当地官员协商,各退一步 │   │
│  │    以和为贵,共谋发展        │   │
│  └──────────────────────────────┘   │
│  ┌──────────────────────────────┐   │
│  │ ○  专注赈灾,不管闲事       │   │
│  │    各司其职,完成使命        │   │
│  └──────────────────────────────┘   │
│                                      │
│  ┌══════════════════════════════┐   │
│  ║    下一题                 →  ║   │  ← 最后一题显示「查看结果」
│  └══════════════════════════════┘   │
└──────────────────────────────────────┘

效果说明: - 顶部 QUESTION 03 红色大写字母标识,右侧显示进度分数 - 进度条带阴影发光效果(shadow) - 选项卡片:未选为白底灰边框,选中为浅红底红边框 - 选中的单选圆点变红色实心,右侧出现红色 ✓ 图标 - 副文本(subtext)用小号灰色字体提供选项解释 - 未选择答案时底部按钮置灰不可点击


实战三:实现结果计算

第一步:古代官场结果计算

根据答案统计各类型得分:

// 结果类型定义
interface AncientResult {
  type: string;
  title: string;
  description: string;
  traits: string[];
  historicalFigure: string;
  matchScore: number;
}

// 计算古代官场测试结果
function calculateAncientResult(answers: string[]): AncientResult {
  // 统计各选项数量
  let countA = 0, countB = 0, countC = 0, countD = 0;
  
  answers.forEach(answer => {
    switch (answer) {
      case 'A': countA++; break;
      case 'B': countB++; break;
      case 'C': countC++; break;
      case 'D': countD++; break;
    }
  });

  // 根据最多的选项确定类型
  const maxCount = Math.max(countA, countB, countC, countD);
  
  if (countA === maxCount) {
    return {
      type: 'upright',
      title: '清官廉吏',
      description: '你刚正不阿,秉公执法,是百姓心中的青天大老爷。',
      traits: ['正直', '勇敢', '为民请命'],
      historicalFigure: '包拯',
      matchScore: 85 + Math.floor(Math.random() * 10)
    };
  } else if (countB === maxCount) {
    return {
      type: 'strategist',
      title: '谋臣智士',
      description: '你深谋远虑,善于权衡,是帝王身边的智囊。',
      traits: ['智慧', '谨慎', '善于谋划'],
      historicalFigure: '诸葛亮',
      matchScore: 80 + Math.floor(Math.random() * 15)
    };
  } else if (countC === maxCount) {
    return {
      type: 'diplomat',
      title: '圆滑老臣',
      description: '你八面玲珑,左右逢源,是官场中的不倒翁。',
      traits: ['圆滑', '人脉广', '善于协调'],
      historicalFigure: '和珅',
      matchScore: 75 + Math.floor(Math.random() * 15)
    };
  } else {
    return {
      type: 'hermit',
      title: '隐逸之士',
      description: '你淡泊名利,明哲保身,向往归隐田园。',
      traits: ['淡泊', '低调', '知足常乐'],
      historicalFigure: '陶渊明',
      matchScore: 70 + Math.floor(Math.random() * 20)
    };
  }
}

第二步:现代职业结果计算(MBTI 风格)

// MBTI 类型结果
interface MBTIResult {
  type: string;           // 如 'INTJ'
  title: string;          // 如 '策略家'
  careers: string[];      // 推荐职业
  strengths: string[];    // 优势
  matchScore: number;
}

// 计算 MBTI 类型
function calculateMBTIResult(answers: string[]): MBTIResult {
  // 统计各维度
  let E = 0, I = 0, S = 0, N = 0, T = 0, F = 0, J = 0, P = 0;
  
  answers.forEach(answer => {
    switch (answer) {
      case 'E': E++; break;
      case 'I': I++; break;
      case 'S': S++; break;
      case 'N': N++; break;
      case 'T': T++; break;
      case 'F': F++; break;
      case 'J': J++; break;
      case 'P': P++; break;
    }
  });

  // 组合 MBTI 类型
  const type = (E >= I ? 'E' : 'I') +
               (S >= N ? 'S' : 'N') +
               (T >= F ? 'T' : 'F') +
               (J >= P ? 'J' : 'P');

  // 根据类型返回结果
  return getMBTIDescription(type);
}

// MBTI 类型描述映射
function getMBTIDescription(type: string): MBTIResult {
  const descriptions: Record<string, MBTIResult> = {
    'INTJ': {
      type: 'INTJ',
      title: '策略家',
      careers: ['架构师', '数据分析师', '战略顾问'],
      strengths: ['战略思维', '独立自主', '追求卓越'],
      matchScore: 88
    },
    'ENFP': {
      type: 'ENFP',
      title: '探险家',
      careers: ['产品经理', '市场营销', '创意总监'],
      strengths: ['创造力', '热情洋溢', '善于沟通'],
      matchScore: 85
    }
    // ... 其他 16 种类型
  };
  
  return descriptions[type] || descriptions['INTJ'];
}

实战四:实现结果展示页

第一步:创建结果页面

@Component
struct AncientTestResultPage {
  @Consume('mainNavPathStack') mainNavPathStack: NavPathStack;
  @StorageLink('isDarkMode') isDarkMode: boolean = true;
  
  @State result: AncientResult | null = null;
  @State showAnimation: boolean = false;

  aboutToAppear() {
    // 获取答案并计算结果
    const params = this.mainNavPathStack.getParamByName('AncientTestResultPage');
    if (params && params.length > 0) {
      const answers = (params[0] as { answers: string[] }).answers;
      this.result = calculateAncientResult(answers);
      
      // 保存测试记录
      this.saveTestRecord();
      
      // 延迟显示动画
      setTimeout(() => {
        this.showAnimation = true;
      }, 100);
    }
  }

  saveTestRecord() {
    if (this.result) {
      const record: TestRecord = {
        testType: 'ancient',
        resultType: this.result.title,
        matchScore: this.result.matchScore,
        timestamp: Date.now()
      };
      saveTestRecord(record);
    }
  }

  build() {
    NavDestination() {
      Stack() {
        // 背景渐变
        Column()
          .width('100%')
          .height('100%')
          .linearGradient({
            direction: GradientDirection.Bottom,
            colors: [['#1a0a0a', 0], ['#3d1515', 0.5], ['#8b0000', 1]]
          })

        if (this.result) {
          Scroll() {
            Column({ space: 24 }) {
              // 结果卡片
              this.ResultCard()
              // 性格特点
              this.TraitsSection()
              // 历史名人对照
              this.HistoricalFigureSection()
              // 操作按钮
              this.ActionButtons()
            }
            .padding(20)
          }
          .layoutWeight(1)
        }
      }
    }
    .hideTitleBar(true)
  }
}

第二步:实现结果卡片动画

@Builder
ResultCard() {
  Column({ space: 16 }) {
    // 匹配度圆环
    Stack() {
      // 背景圆
      Circle()
        .width(120)
        .height(120)
        .fill(Color.Transparent)
        .stroke('rgba(255,255,255,0.2)')
        .strokeWidth(8)

      // 进度圆(动画)
      Circle()
        .width(120)
        .height(120)
        .fill(Color.Transparent)
        .stroke('#ffd700')
        .strokeWidth(8)
        .strokeDashArray([this.showAnimation ? (this.result!.matchScore / 100) * 377 : 0, 377])
        .animation({ duration: 1000, curve: Curve.EaseOut })

      // 分数文字
      Column({ space: 4 }) {
        Text(`${this.result!.matchScore}`)
          .fontSize(36)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ffd700')
        Text('匹配度')
          .fontSize(12)
          .fontColor('rgba(255,255,255,0.7)')
      }
    }

    // 结果类型
    Text(this.result!.title)
      .fontSize(32)
      .fontWeight(FontWeight.Bold)
      .fontColor(Color.White)
      .opacity(this.showAnimation ? 1 : 0)
      .animation({ duration: 500, delay: 300 })

    // 描述
    Text(this.result!.description)
      .fontSize(14)
      .fontColor('rgba(255,255,255,0.8)')
      .textAlign(TextAlign.Center)
      .lineHeight(22)
      .opacity(this.showAnimation ? 1 : 0)
      .animation({ duration: 500, delay: 500 })
  }
  .width('100%')
  .padding(24)
  .backgroundColor('rgba(255,255,255,0.1)')
  .borderRadius(20)
}

第三步:实现分享功能

@Builder
ActionButtons() {
  Column({ space: 12 }) {
    // 分享按钮
    Button() {
      Row({ space: 8 }) {
        Image($r('app.media.ic_share'))
          .width(20)
          .height(20)
          .fillColor(Color.White)
        Text('分享结果')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
      }
    }
    .width('100%')
    .height(52)
    .backgroundColor('#c41e3a')
    .borderRadius(12)
    .onClick(() => this.shareResult())

    // 重新测试
    Button('重新测试')
      .width('100%')
      .height(48)
      .backgroundColor('rgba(255,255,255,0.15)')
      .fontColor(Color.White)
      .borderRadius(12)
      .onClick(() => {
        this.mainNavPathStack.pop();
      })

    // 返回首页
    Button('返回首页')
      .width('100%')
      .height(48)
      .backgroundColor(Color.Transparent)
      .fontColor('rgba(255,255,255,0.7)')
      .onClick(() => {
        this.mainNavPathStack.clear();
      })
  }
  .width('100%')
  .padding({ top: 16 })
}

案例效果:结果页面展示如下(渐变深红背景):

┌──────────── 深红渐变背景 ────────────┐
│                                      │
│         ┌──────────────┐            │
│         │    ╭────╮    │            │
│         │    │ 90 │    │            │  ← 金色圆环动画
│         │    │匹配度│   │            │     从0到90动画填充
│         │    ╰────╯    │            │
│         │              │            │
│         │   谋臣智士    │            │  ← 白色大字,淡入动画
│         │              │            │
│         │ 你深谋远虑,善│            │
│         │ 于权衡,是帝王│            │  ← 渐显描述文字
│         │ 身边的智囊。  │            │
│         └──────────────┘            │
│        (半透明白色卡片背景)          │
│                                      │
│  ┌──────────────────────────────┐   │
│  │  性格特点                    │   │
│  │  ┌────┐ ┌────┐ ┌──────┐   │   │
│  │  │智慧│ │谨慎│ │善于谋划│   │   │
│  │  └────┘ └────┘ └──────┘   │   │
│  └──────────────────────────────┘   │
│                                      │
│  ┌──────────────────────────────┐   │
│  │  历史名人对照                │   │
│  │  你像:诸葛亮               │   │
│  └──────────────────────────────┘   │
│                                      │
│  ┌══════════════════════════════┐   │
│  ║  📤  分享结果                ║   │  ← 红色按钮
│  └══════════════════════════════┘   │
│  ┌──────────────────────────────┐   │
│  │       重新测试               │   │  ← 半透明白色按钮
│  └──────────────────────────────┘   │
│  │       返回首页               │   │  ← 透明按钮
└──────────────────────────────────────┘

效果说明: - 整体页面使用从深黑到暗红的渐变背景 - 匹配度圆环:背景为半透明白色圆环,进度为金色(#ffd700) - 圆环动画:页面打开后从 0% 动画填充到实际分数,持续1秒 - 结果标题(如「谋臣智士」)延迟 300ms 淡入 - 描述文字延迟 500ms 淡入,营造逐步揭晓效果 - 性格特点以胶囊标签展示 - 三个操作按钮层次分明:主要→次要→文字


完整代码汇总

测试主页 PersonalityTestPage.ets

@Component
struct PersonalityTestPage {
  @Consume('mainNavPathStack') mainNavPathStack: NavPathStack;
  @StorageLink('isDarkMode') isDarkMode: boolean = true;
  @State ancientRecord: TestRecord | null = null;
  @State modernRecord: TestRecord | null = null;

  aboutToAppear() {
    this.loadRecords();
  }

  loadRecords() {
    this.ancientRecord = getLatestTestRecord('ancient');
    this.modernRecord = getLatestTestRecord('modern');
  }

  build() {
    NavDestination() {
      Column() {
        this.HeaderBar()
        Scroll() {
          Column({ space: 24 }) {
            this.HeadlineSection()
            this.AncientTestCard()
            this.ModernTestCard()
            this.TestHistorySection()
          }
          .padding({ left: 16, right: 16, bottom: 32 })
        }
        .layoutWeight(1)
      }
    }
    .hideTitleBar(true)
  }

  @Builder
  AncientTestCard() {
    // 古代官场测试入口卡片
    Column() {
      // 图片 + 内容
    }
    .onClick(() => {
      this.mainNavPathStack.pushPathByName('AncientTestPage', null);
    })
  }

  @Builder
  ModernTestCard() {
    // 现代职业测试入口卡片
    Column() {
      // 图片 + 内容
    }
    .onClick(() => {
      this.mainNavPathStack.pushPathByName('ModernTestPage', null);
    })
  }
}

@Builder
export function PersonalityTestPageBuilder() {
  PersonalityTestPage()
}

本课小结

功能 实现方式
题目设计 情景选择题 + 选项说明
答题流程 状态管理 + 索引控制
结果计算 统计选项 + 类型映射
结果展示 动画效果 + 分享功能

课后练习

  1. 为测试结果添加历史名人头像展示
  2. 实现测试结果的图片生成与分享
  3. 添加测试历史记录的删除功能

下一课预告

第27课开发新年习俗专题,包括八朝年俗数据、列表展示、详情页面。


项目开源地址

https://gitcode.com/daleishen/gujinzhijian

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐