| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896 |
- <template>
- <view class="mbti-page">
- <!-- 自定义顶部导航栏 -->
- <view class="custom-nav">
- <view class="nav-left" @click="goBack">
- <text class="back-icon">←</text>
- </view>
- <view class="nav-title">MBTI人格测试</view>
- <view class="nav-right"></view>
- </view>
- <!-- 测试说明页面 -->
- <view v-if="currentStep === 'intro'" class="intro-section">
- <view class="intro-header">
- <view class="mbti-logo">🧩</view>
- <view class="intro-title">MBTI人格类型测试</view>
- <view class="intro-subtitle">发现真实的自己,了解你的人格类型</view>
- </view>
- <view class="intro-content">
- <view class="feature-list">
- <view class="feature-item">
- <view class="feature-icon">🎯</view>
- <view class="feature-text">
- <text class="feature-title">科学准确</text>
- <text class="feature-desc">基于心理学理论的专业测评</text>
- </view>
- </view>
- <view class="feature-item">
- <view class="feature-icon">⏱️</view>
- <view class="feature-text">
- <text class="feature-title">快速便捷</text>
- <text class="feature-desc">仅需5-10分钟完成测试</text>
- </view>
- </view>
- <view class="feature-item">
- <view class="feature-icon">📊</view>
- <view class="feature-text">
- <text class="feature-title">详细报告</text>
- <text class="feature-desc">获得专业的人格分析报告</text>
- </view>
- </view>
- </view>
- <view class="test-info">
- <view class="info-item">
- <text class="info-label">测试题数:</text>
- <text class="info-value">{{ totalQuestions }}道题</text>
- </view>
- <view class="info-item">
- <text class="info-label">测试时间:</text>
- <text class="info-value">约5-10分钟</text>
- </view>
- <view class="info-item">
- <text class="info-label">测试人数:</text>
- <text class="info-value">已有{{ testCount }}人测试</text>
- </view>
- </view>
- <view class="start-btn" @click="startTest">
- <text class="btn-text">开始测试</text>
- </view>
- <view class="tips">
- <text class="tips-text">💡 请根据真实想法作答,无标准答案</text>
- </view>
- </view>
- </view>
- <!-- 测试进行页面 -->
- <view v-if="currentStep === 'testing'" class="testing-section">
- <!-- 进度条 -->
- <view class="progress-bar">
- <view class="progress-bg">
- <view class="progress-fill" :style="{width: progressPercent + '%'}"></view>
- </view>
- <view class="progress-text">{{ currentQuestion }}/{{ totalQuestions }}</view>
- </view>
- <!-- 题目内容 -->
- <view class="question-card">
- <view class="question-number">第{{ currentQuestion }}题</view>
- <view class="question-text">{{ currentQuestionData.question }}</view>
-
- <!-- 选择题选项 -->
- <view v-if="currentQuestionData.type === 'choice'" class="options-list">
- <view
- v-for="(option, index) in currentQuestionData.options"
- :key="index"
- class="option-item"
- :class="{'selected': selectedAnswer === index}"
- @click="selectAnswer(index)"
- >
- <view class="option-marker">{{ String.fromCharCode(65 + index) }}</view>
- <view class="option-text">{{ option.text }}</view>
- </view>
- </view>
- <!-- 量表题选项 -->
- <view v-if="currentQuestionData.type === 'scale'" class="scale-options">
- <view class="scale-labels">
- <text class="scale-label">非常不同意</text>
- <text class="scale-label">非常同意</text>
- </view>
- <view class="scale-buttons">
- <view
- v-for="(score, index) in [1,2,3,4,5]"
- :key="index"
- class="scale-btn"
- :class="{'selected': selectedAnswer === score}"
- @click="selectAnswer(score)"
- >
- {{ score }}
- </view>
- </view>
- </view>
- </view>
- <!-- 操作按钮 -->
- <view class="action-buttons">
- <view class="btn-secondary" @click="previousQuestion" v-if="currentQuestion > 1">
- 上一题
- </view>
- <view class="btn-primary" @click="nextQuestion" :class="{'disabled': selectedAnswer === null}">
- {{ currentQuestion === totalQuestions ? '完成测试' : '下一题' }}
- </view>
- </view>
- </view>
- <!-- 结果页面 -->
- <view v-if="currentStep === 'result'" class="result-section">
- <view class="result-header">
- <view class="result-type">{{ mbtiResult.type }}</view>
- <view class="result-name">{{ mbtiResult.name }}</view>
- <view class="result-desc">{{ mbtiResult.description }}</view>
- </view>
- <view class="result-details">
- <!-- 四个维度分析 -->
- <view class="dimensions">
- <view class="dimension-item" v-for="(dim, index) in mbtiResult.dimensions" :key="index">
- <view class="dim-header">
- <text class="dim-name">{{ dim.name }}</text>
- <text class="dim-percent">{{ dim.percent }}%</text>
- </view>
- <view class="dim-bar">
- <view class="dim-fill" :style="{width: dim.percent + '%', background: dim.color}"></view>
- </view>
- <view class="dim-desc">{{ dim.description }}</view>
- </view>
- </view>
- <!-- 性格特点 -->
- <view class="traits-section">
- <view class="section-title">💎 性格特点</view>
- <view class="traits-list">
- <text class="trait-item" v-for="(trait, index) in mbtiResult.traits" :key="index">
- {{ trait }}
- </text>
- </view>
- </view>
- <!-- 适合职业 -->
- <view class="careers-section">
- <view class="section-title">💼 适合职业</view>
- <view class="careers-list">
- <text class="career-item" v-for="(career, index) in mbtiResult.careers" :key="index">
- {{ career }}
- </text>
- </view>
- </view>
- <!-- 恋爱风格 -->
- <view class="love-section">
- <view class="section-title">💕 恋爱风格</view>
- <view class="love-content">{{ mbtiResult.loveStyle }}</view>
- </view>
- <!-- 匹配类型 -->
- <view class="compatibility-section">
- <view class="section-title">🔗 最佳配对</view>
- <view class="compatibility-types">
- <text class="compat-type" v-for="(type, index) in mbtiResult.compatibility" :key="index">
- {{ type }}
- </text>
- </view>
- </view>
- </view>
- <view class="result-actions">
- <view class="btn-secondary" @click="retakeTest">重新测试</view>
- <view class="btn-primary" @click="shareResult">分享结果</view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import { MBTI_QUESTIONS, MBTI_TYPES, calculateMBTI } from '@/utils/mbti.js'
- export default {
- data() {
- return {
- currentStep: 'intro', // intro, testing, result
- currentQuestion: 1,
- totalQuestions: 0,
- selectedAnswer: null,
- answers: [],
- testCount: 15678,
- mbtiResult: null
- }
- },
- computed: {
- progressPercent() {
- return Math.round((this.currentQuestion / this.totalQuestions) * 100)
- },
-
- currentQuestionData() {
- return MBTI_QUESTIONS[this.currentQuestion - 1] || {}
- }
- },
- onLoad() {
- this.initData()
- },
- methods: {
- // 初始化数据
- initData() {
- this.totalQuestions = MBTI_QUESTIONS.length
- this.answers = new Array(this.totalQuestions).fill(null)
- },
- // 返回上一页
- goBack() {
- if (this.currentStep === 'testing' && this.currentQuestion > 1) {
- // 测试中显示确认弹窗
- uni.showModal({
- title: '提示',
- content: '测试还未完成,确定要退出吗?',
- success: (res) => {
- if (res.confirm) {
- uni.navigateBack()
- }
- }
- })
- } else {
- uni.navigateBack()
- }
- },
- // 开始测试
- startTest() {
- this.currentStep = 'testing'
- this.currentQuestion = 1
- this.selectedAnswer = this.answers[0]
- },
- // 选择答案
- selectAnswer(answer) {
- this.selectedAnswer = answer
- this.answers[this.currentQuestion - 1] = answer
- },
- // 下一题
- nextQuestion() {
- if (this.selectedAnswer === null) {
- uni.showToast({
- title: '请选择一个选项',
- icon: 'none'
- })
- return
- }
- // 保存当前答案
- this.answers[this.currentQuestion - 1] = this.selectedAnswer
- if (this.currentQuestion === this.totalQuestions) {
- // 完成测试,计算结果
- this.calculateResult()
- } else {
- // 下一题
- this.currentQuestion++
- this.selectedAnswer = this.answers[this.currentQuestion - 1]
- }
- },
- // 上一题
- previousQuestion() {
- if (this.currentQuestion > 1) {
- this.currentQuestion--
- this.selectedAnswer = this.answers[this.currentQuestion - 1]
- }
- },
- // 计算测试结果
- calculateResult() {
- try {
- const mbtiType = calculateMBTI(this.answers)
- this.mbtiResult = MBTI_TYPES[mbtiType]
- this.currentStep = 'result'
-
- // 统计测试完成
- this.testCount++
- } catch (error) {
- console.error('计算MBTI结果失败:', error)
- uni.showToast({
- title: '计算结果失败',
- icon: 'error'
- })
- }
- },
- // 重新测试
- retakeTest() {
- this.currentStep = 'intro'
- this.currentQuestion = 1
- this.selectedAnswer = null
- this.answers = new Array(this.totalQuestions).fill(null)
- this.mbtiResult = null
- },
- // 分享结果
- shareResult() {
- uni.showActionSheet({
- itemList: ['保存图片', '分享给朋友', '复制结果'],
- success: (res) => {
- switch (res.tapIndex) {
- case 0:
- this.saveResultImage()
- break
- case 1:
- this.shareToFriend()
- break
- case 2:
- this.copyResult()
- break
- }
- }
- })
- },
- // 保存结果图片
- saveResultImage() {
- uni.showToast({
- title: '功能开发中',
- icon: 'none'
- })
- },
- // 分享给朋友
- shareToFriend() {
- uni.showToast({
- title: '功能开发中',
- icon: 'none'
- })
- },
- // 复制结果
- copyResult() {
- const resultText = `我的MBTI人格类型是:${this.mbtiResult.type} - ${this.mbtiResult.name}\n${this.mbtiResult.description}`
-
- uni.setClipboardData({
- data: resultText,
- success: () => {
- uni.showToast({
- title: '已复制到剪贴板',
- icon: 'success'
- })
- }
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .mbti-page {
- min-height: 100vh;
- background: linear-gradient(180deg, #F8F9FA 0%, #FFFFFF 100%);
- }
- /* 自定义导航栏 */
- .custom-nav {
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- height: 88rpx;
- padding: 0 30rpx;
- background-color: #FFFFFF;
- border-bottom: 1rpx solid #F0F0F0;
- .nav-left {
- width: 80rpx;
- .back-icon {
- font-size: 40rpx;
- color: #333333;
- }
- }
- .nav-title {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- font-size: 34rpx;
- font-weight: 600;
- color: #333333;
- }
- .nav-right {
- width: 80rpx;
- }
- }
- /* 介绍页面 */
- .intro-section {
- padding: 40rpx 30rpx;
- }
- .intro-header {
- text-align: center;
- margin-bottom: 60rpx;
- .mbti-logo {
- font-size: 120rpx;
- margin-bottom: 30rpx;
- }
- .intro-title {
- font-size: 48rpx;
- font-weight: bold;
- color: #333333;
- margin-bottom: 15rpx;
- }
- .intro-subtitle {
- font-size: 28rpx;
- color: #666666;
- line-height: 1.6;
- }
- }
- .intro-content {
- .feature-list {
- margin-bottom: 50rpx;
- .feature-item {
- display: flex;
- align-items: center;
- background-color: #FFFFFF;
- border-radius: 20rpx;
- padding: 30rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
- .feature-icon {
- font-size: 50rpx;
- margin-right: 25rpx;
- }
- .feature-text {
- flex: 1;
- .feature-title {
- display: block;
- font-size: 32rpx;
- font-weight: 600;
- color: #333333;
- margin-bottom: 8rpx;
- }
- .feature-desc {
- font-size: 26rpx;
- color: #666666;
- }
- }
- }
- }
- .test-info {
- background-color: #FFFFFF;
- border-radius: 20rpx;
- padding: 30rpx;
- margin-bottom: 40rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
- .info-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20rpx;
- &:last-child {
- margin-bottom: 0;
- }
- .info-label {
- font-size: 28rpx;
- color: #666666;
- }
- .info-value {
- font-size: 28rpx;
- font-weight: 600;
- color: #333333;
- }
- }
- }
- .start-btn {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border-radius: 50rpx;
- height: 100rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 30rpx;
- box-shadow: 0 8rpx 20rpx rgba(102, 126, 234, 0.3);
- transition: transform 0.2s;
- &:active {
- transform: scale(0.98);
- }
- .btn-text {
- font-size: 32rpx;
- font-weight: 600;
- color: #FFFFFF;
- }
- }
- .tips {
- text-align: center;
- .tips-text {
- font-size: 24rpx;
- color: #999999;
- }
- }
- }
- /* 测试进行页面 */
- .testing-section {
- padding: 30rpx;
- }
- .progress-bar {
- background-color: #FFFFFF;
- border-radius: 15rpx;
- padding: 25rpx;
- margin-bottom: 30rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
- .progress-bg {
- height: 12rpx;
- background-color: #F0F0F0;
- border-radius: 6rpx;
- overflow: hidden;
- margin-bottom: 15rpx;
- .progress-fill {
- height: 100%;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border-radius: 6rpx;
- transition: width 0.3s ease;
- }
- }
- .progress-text {
- text-align: center;
- font-size: 26rpx;
- color: #666666;
- }
- }
- .question-card {
- background-color: #FFFFFF;
- border-radius: 20rpx;
- padding: 40rpx;
- margin-bottom: 30rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
- .question-number {
- font-size: 24rpx;
- color: #999999;
- margin-bottom: 15rpx;
- }
- .question-text {
- font-size: 32rpx;
- color: #333333;
- line-height: 1.6;
- margin-bottom: 40rpx;
- font-weight: 500;
- }
- }
- .options-list {
- .option-item {
- display: flex;
- align-items: center;
- background-color: #F8F9FA;
- border-radius: 15rpx;
- padding: 25rpx;
- margin-bottom: 15rpx;
- transition: all 0.2s;
- &.selected {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: #FFFFFF;
- }
- &:last-child {
- margin-bottom: 0;
- }
- .option-marker {
- width: 50rpx;
- height: 50rpx;
- border-radius: 50%;
- background-color: rgba(255, 255, 255, 0.2);
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 20rpx;
- font-weight: 600;
- }
- .option-text {
- flex: 1;
- font-size: 28rpx;
- line-height: 1.5;
- }
- }
- }
- .scale-options {
- .scale-labels {
- display: flex;
- justify-content: space-between;
- margin-bottom: 30rpx;
- .scale-label {
- font-size: 24rpx;
- color: #666666;
- }
- }
- .scale-buttons {
- display: flex;
- justify-content: space-between;
- .scale-btn {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
- background-color: #F0F0F0;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 28rpx;
- font-weight: 600;
- color: #666666;
- transition: all 0.2s;
- &.selected {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: #FFFFFF;
- }
- }
- }
- }
- .action-buttons {
- display: flex;
- gap: 20rpx;
- .btn-secondary,
- .btn-primary {
- flex: 1;
- height: 80rpx;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 30rpx;
- font-weight: 600;
- transition: all 0.2s;
- &:active {
- transform: scale(0.98);
- }
- }
- .btn-secondary {
- background-color: #F8F9FA;
- color: #666666;
- border: 2rpx solid #E9ECEF;
- }
- .btn-primary {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: #FFFFFF;
- box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
- &.disabled {
- background: #CCCCCC;
- box-shadow: none;
- pointer-events: none;
- }
- }
- }
- /* 结果页面 */
- .result-section {
- padding: 30rpx;
- }
- .result-header {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border-radius: 20rpx;
- padding: 40rpx;
- text-align: center;
- color: #FFFFFF;
- margin-bottom: 30rpx;
- box-shadow: 0 8rpx 20rpx rgba(102, 126, 234, 0.3);
- .result-type {
- font-size: 60rpx;
- font-weight: bold;
- margin-bottom: 15rpx;
- }
- .result-name {
- font-size: 36rpx;
- font-weight: 600;
- margin-bottom: 20rpx;
- }
- .result-desc {
- font-size: 26rpx;
- line-height: 1.6;
- opacity: 0.9;
- }
- }
- .result-details {
- background-color: #FFFFFF;
- border-radius: 20rpx;
- padding: 30rpx;
- margin-bottom: 30rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
- .section-title {
- font-size: 32rpx;
- font-weight: 600;
- color: #333333;
- margin-bottom: 25rpx;
- }
- }
- .dimensions {
- margin-bottom: 40rpx;
- .dimension-item {
- margin-bottom: 30rpx;
- &:last-child {
- margin-bottom: 0;
- }
- .dim-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 10rpx;
- .dim-name {
- font-size: 28rpx;
- color: #333333;
- }
- .dim-percent {
- font-size: 28rpx;
- font-weight: 600;
- color: #667eea;
- }
- }
- .dim-bar {
- height: 12rpx;
- background-color: #F0F0F0;
- border-radius: 6rpx;
- overflow: hidden;
- margin-bottom: 10rpx;
- .dim-fill {
- height: 100%;
- border-radius: 6rpx;
- transition: width 0.6s ease;
- }
- }
- .dim-desc {
- font-size: 24rpx;
- color: #666666;
- line-height: 1.4;
- }
- }
- }
- .traits-section,
- .careers-section {
- margin-bottom: 40rpx;
- .traits-list,
- .careers-list {
- display: flex;
- flex-wrap: wrap;
- gap: 10rpx;
- .trait-item,
- .career-item {
- padding: 10rpx 20rpx;
- background-color: #F8F9FA;
- border-radius: 20rpx;
- font-size: 24rpx;
- color: #333333;
- }
- }
- }
- .love-section {
- margin-bottom: 40rpx;
- .love-content {
- font-size: 28rpx;
- color: #333333;
- line-height: 1.6;
- }
- }
- .compatibility-section {
- .compatibility-types {
- display: flex;
- flex-wrap: wrap;
- gap: 15rpx;
- .compat-type {
- padding: 15rpx 25rpx;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: #FFFFFF;
- border-radius: 25rpx;
- font-size: 26rpx;
- font-weight: 600;
- }
- }
- }
- .result-actions {
- display: flex;
- gap: 20rpx;
- .btn-secondary,
- .btn-primary {
- flex: 1;
- height: 80rpx;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 30rpx;
- font-weight: 600;
- transition: all 0.2s;
- &:active {
- transform: scale(0.98);
- }
- }
- .btn-secondary {
- background-color: #F8F9FA;
- color: #666666;
- border: 2rpx solid #E9ECEF;
- }
- .btn-primary {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: #FFFFFF;
- box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
- }
- }
- </style>
|