乐于分享
好东西不私藏

性格测试小程序开发技术文档

性格测试小程序开发技术文档

📋 性格测试小程序开发技术文档

版本:v1.0.0   |   最后更新:2026-04-23   |   适用平台:微信小程序 (主) / H5 (辅)   |   预期工期:14 人/日

📑 目录

  1. 项目概述
  2. 技术架构
  3. 数据库设计
  4. 接口规范
  5. 核心算法逻辑
  6. 前端页面规范
  7. 合规与审核要点
  8. 测试用例
  9. 部署与监控
  10. 附录: 文案模板示例

1. 项目概述

1.1 产品定义

基于 MBTI 理论的趣味性格测试工具,用户完成 20-30 道选择题后获得人格类型报告,支持生成分享卡片。

  • 核心定位:
    社交娱乐 + 轻量裂变
  • 变现模式:
    激励视频广告 + 插屏广告
  • 用户价值:
    自我探索、社交货币、情绪共鸣

1.2 核心功能清单

模块
功能点
优先级
答题模块
题目展示、进度条、选项点击、上一题/下一题
P0
计分引擎
实时计算维度分数、生成最终类型
P0
结果页
展示类型、维度分析、简短描述、分享按钮
P0
分享裂变
生成包含用户头像/昵称的专属卡片、好友匹配度
P1
广告变现
激励视频解锁完整报告、Banner 广告
P1
用户系统
微信授权登录、答题历史记录
P2

1.3 非功能性指标

  • 首屏加载时间 < 1.8s (4G网络)
  • 答题页滑动帧率 ≥ 50fps
  • 并发支持 QPS ≥ 500 (答题接口)
  • 审核通过率目标 > 95%

2. 技术架构

2.1 技术选型

前端框架: uni-app (Vue3 + Vite + Pinia)

UI组件库: uView Plus / uni-ui后端服务: Node.js + Express (或 Python FastAPI)数据库: MySQL 8.0缓存: Redis 7.0对象存储: 腾讯云 COS部署: 微信云托管 (推荐) / 自建服务器

2.2 系统架构图

┌─────────────────┐     ┌─────────────────┐ │  微信小程序端    │────▶│   CDN + 网关     │ │  (uni-app)      │     │   (Nginx/LB)    │ └─────────────────┘     └────────┬────────┘                                  │ ┌─────────────────┐     ┌────────▼────────┐     ┌─────────────────┐ │   运营后台       │────▶│   业务 API 层    │────▶│   Redis 缓存    │ │   (Vue3 Admin)  │     │  (Node/Python)  │     │ (题目/会话/热度) │ └─────────────────┘     └────────┬────────┘     └─────────────────┘                                  │                         ┌────────▼────────┐                         │   MySQL 8.0      │                         │  (持久化存储)     │                         └────────┬────────┘                                  │                         ┌────────▼────────┐                         │   腾讯云 COS     │                         │ (海报背景/素材)  │                         └─────────────────┘

2.3 目录结构 (uni-app)

src/

├── pages/│   ├── index/               # 首页│   ├── quiz/                # 答题页│   ├── loading/             # 加载过渡页│   ├── result/              # 结果页│   └── match/               # 好友匹配页├── components/│   ├── QuestionCard.vue     # 题目卡片组件│   ├── ProgressBar.vue      # 进度条组件│   └── SharePoster.vue      # 海报绘制组件├── api/│   ├── quiz.js              # 答题接口封装│   └── user.js              # 用户接口封装├── stores/│   └── quizSession.js       # Pinia 答题会话状态├── utils/│   ├── request.js           # 请求拦截器│   ├── poster.js            # Canvas 绘制工具│   └── mbti.js              # 计分算法 (前端兜底)└── static/                  # 静态资源

3. 数据库设计

3.1 建表语句 (MySQL DDL)

题目表

CREATE TABLE questions (

id int unsigned NOT NULL AUTO_INCREMENT,  dimension enum('EI','SN','TF','JP') NOT NULL COMMENT '所属维度',  content varchar(500) NOT NULL COMMENT '题干',  option_a varchar(200) NOT NULL,  scorerulea json NOT NULL COMMENT '例: {"E": 1.0, "S": 0.5}',  option_b varchar(200) NOT NULL,  scoreruleb json NOT NULL,  order_index int DEFAULT 0,  status tinyint DEFAULT 1 COMMENT '1-启用 0-禁用',  createdat datetime DEFAULT CURRENTTIMESTAMP,   PRIMARY KEY (id),   KEY idx_dimension (dimension) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='题库表';

人格类型结果表

CREATE TABLE personality_types (

type_code char(4) PRIMARY KEY COMMENT '如 INFP',  type_name varchar(50) NOT NULL COMMENT '中文别名',  short_desc varchar(200) NOT NULL COMMENT '一句话概括',  fullreportjson json NOT NULL COMMENT '报告详细内容(分段落)',  bgimageurl varchar(255) COMMENT '分享卡片背景图',  match_tags json COMMENT '匹配关键词用于推荐',   PRIMARY KEY (type_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='16型人格模板';

答题会话表

CREATE TABLE result_sessions (

session_id varchar(64) PRIMARY KEY COMMENT 'UUID',  openid varchar(100) NOT NULL COMMENT '微信OpenID',  final_type char(4) NOT NULL,  dimension_scores json NOT NULL COMMENT '{"E":12,"I":8}',  share_count int DEFAULT 0,  ad_watched tinyint DEFAULT 0 COMMENT '是否看过广告',  createdat datetime DEFAULT CURRENTTIMESTAMP,   KEY idx_openid (openid),   KEY idxcreated (createdat) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='结果会话记录';

3.2 Redis 缓存键设计

键名
类型
TTL
说明
quiz:questions:active
String (JSON)
1h
全量启用题目数据
quiz:session:{sessionId}
Hash
30m
暂存分数: {E:5, I:3}
quiz:result:{typeCode}
String
12h
热门结果HTML片段
quiz:user:limit:{openid}
String
24h
防刷计数

4. 接口规范

4.1 通用响应格式

{

  "code": 0,           // 0-成功, 400-参数错误, 500-服务错误  "message": "success",  "data": {},  "timestamp": 1713868800}

4.2 接口示例

开始答题

POST /api/v1/quiz/start

Request: { "inviter_openid": "oXXXXX" }Response: { "code":0, "data":{ "sessionid":"...", "questions":[...], "totalcount":28 } }

提交单题答案

POST /api/v1/quiz/answer

Request: { "sessionid":"...", "questionid":5, "choice":"A" }Response: { "code":0, "data":{ "currentscores": {...}, "answeredcount":6 } }

完成答题

POST /api/v1/quiz/finish

Response: { "code":0, "data":{ "resultcode":"ENFP", "resultname":"快乐小狗·竞选者", ... } }

好友匹配度

POST /api/v1/quiz/match

Response: { "code":0, "data":{ "matchscore":88, "matchtext":"天生一对" } }

5. 核心算法逻辑

5.1 MBTI 计分算法 (Python 参考)

def calculatembti(answers, questionsmap):

    scores = {"E":0.0, "I":0.0, "S":0.0, "N":0.0, "T":0.0, "F":0.0, "J":0.0, "P":0.0}    for ans in answers:        rule = questionsmap[ans["qid"]][f"scorerule_{ans['choice'].lower()}"]        for dim, weight in rule.items():            scores[dim] += weight    result = ""    result += "E" if scores["E"] >= scores["I"] else "I"    result += "S" if scores["S"] >= scores["N"] else "N"    result += "T" if scores["T"] >= scores["F"] else "F"    result += "J" if scores["J"] >= scores["P"] else "P"    return {"typecode": result, "rawscores": scores}

5.2 好友匹配度算法 (JavaScript)

function calculateMatchScore(typeA, typeB, seed) {

    let baseScore = 0;    for (let i=0; i<4; i++) if(typeA[i]===typeB[i]) baseScore+=20;    // 特殊黄金组合加成    const goldenPairs = [["ENFP","INFJ"], ...];    if(goldenPairs.some(p=>(p[0]==typeA&&p[1]==typeB)||(p[0]==typeB&&p[1]==typeA))) baseScore+=15;    const hash = md5(seed).slice(0,4);    const offset = (parseInt(hash,16) % 21) - 8;    return Math.min(99, Math.max(60, baseScore + offset));}

5.3 Canvas 海报生成核心代码

export async function generateSharePoster(canvasId, userInfo, resultData) {

    const ctx = uni.createCanvasContext(canvasId);    // 绘制背景、头像、文字    ctx.draw(false, () => {        uni.canvasToTempFilePath({ canvasId, success: (res) => resolve(res.tempFilePath) });    });}

6. 前端页面规范

6.1 页面结构

路径
页面名称
核心组件
pages/index/index
首页
Swiper、Button
pages/quiz/quiz
答题页
QuestionCard、ProgressBar
pages/loading/loading
加载过渡页
Lottie动画
pages/result/result
结果页
SharePoster、AdUnit
pages/match/match
匹配页
Qrcode、MatchCard

6.2 Pinia Store 示例

export const useQuizStore = defineStore('quiz', {

    state: () => ({ sessionId: '', questions: [], answers: [], currentIndex: 0 }),    actions: {        async initSession(inviterId) { / ... / },        async submitAnswer(questionId, choice) { / ... / }    },    persist: { enabled: true }});

6.3 答题页滑动交互

<swiper :current="currentIndex" @change="onSwiperChange">

    <swiper-item v-for="q in questions">        <button @click="handleSelect('A')">{{ q.options[0].text }}</button>    </swiper-item></swiper>

7. 合规与审核要点

⚠️ 以下内容必须严格执行,否则微信审核将被驳回。

7.1 小程序类目选择

  • 必须选择:
    文娱 - 其他文娱 或 工具 - 信息查询
  • 严禁选择:
    医疗 - 健康资讯教育 - 教育信息服务

7.2 页面强制要求

位置
要求
首页标题
不得包含“专业测评”、“科学诊断”
结果页顶部
必须明确标注“测试结果仅供娱乐”
授权弹窗
必须提供“暂不授权”选项

7.3 广告合规

  • 激励视频必须明确告知“观看后解锁xxx”
  • 广告不得遮挡核心功能按钮
  • 答题过程中禁止弹出插屏广告

8. 测试用例

用例ID
场景
预期结果
TC-01
首次正常答题
完成28题后正确生成报告
TC-02
答题中途退出再进入
进度保留,显示“继续答题”
TC-03
网络断开时提交答案
提示异常,恢复后自动重试
TC-04
激励视频完整观看
回调后解锁完整报告
TC-05
分享海报生成
无白屏,图片清晰
TC-06
防刷校验
24小时内超过10次提示限制

9. 部署与监控

9.1 部署检查清单

  • ✅ MySQL 字符集为 utf8mb4
  • ✅ Redis 持久化配置 (AOF)
  • ✅ COS 存储桶公有读私有写
  • ✅ 小程序后台配置合法域名
  • ✅ 开启 Sentry 错误监控

9.2 关键埋点事件

事件名
触发时机
view_index
首页曝光
click_start
点击开始测试
quizquestionview
每道题曝光
quiz_complete
完成全部答题
resultshareclick
点击分享按钮
adwatchcomplete
激励视频看完

10. 附录:文案模板示例

10.1 16种人格结果简短描述

{

  "INFP": {    "type_name": "治愈者 · 调停者",    "short_desc": "你内心柔软,富有理想主义,是行走的诗人和灵魂画手。"  },  "ENFP": {    "type_name": "快乐小狗 · 竞选者",    "short_desc": "你热情洋溢,是人群中的小太阳,永远对世界保持好奇。"  }}

10.2 免责声明完整文案

本测试结果基于 MBTI 理论简化模型生成,旨在提供趣味性的自我探索体验。测试内容不具备临床诊断意义,不能替代专业心理咨询或职业规划建议。请以轻松心态看待结果,切勿作为人生重大决策的唯一依据。


📅 文档变更记录

日期
版本
修改内容
作者
2026-04-23
1.0.0
初始版本创建
[工程师姓名]

性格测试小程序开发文档 · 仅供内部开发使用。