| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <template>
- <view class="mbt-page">
- <view class="mbt-header">
- <text class="mbt-progress-text">{{ currentIndex + 1 }} / {{ questions.length }}</text>
- </view>
- <view class="mbt-progress-bar">
- <view class="mbt-progress-fill" :style="{ width: progress + '%', background: '#6366F1' }"></view>
- </view>
- <view class="mbt-loading" v-if="loading">
- <text>加载题库...</text>
- </view>
- <template v-else>
- <view class="mbt-card">
- <text class="mbt-dim-tag" :style="{ background: currentDimColor }">{{ currentDimName }}</text>
- <text class="mbt-q-text">{{ currentQuestion.questionText }}</text>
- <view class="mbt-opts">
- <view class="mbt-opt" :class="{ 'mbt-opt-sel': answer === 'A' }" @click="selectAnswer('A')">
- <text class="mbt-opt-label">{{ currentQuestion.optionA }}</text>
- <view class="mbt-opt-radio" :class="{ on: answer === 'A' }"></view>
- </view>
- <view class="mbt-opt" :class="{ 'mbt-opt-sel': answer === 'B' }" @click="selectAnswer('B')">
- <text class="mbt-opt-label">{{ currentQuestion.optionB }}</text>
- <view class="mbt-opt-radio" :class="{ on: answer === 'B' }"></view>
- </view>
- </view>
- </view>
- <view class="mbt-footer">
- <button class="mbt-btn mbt-btn-prev" :disabled="currentIndex === 0" @click="prev">上一题</button>
- <button class="mbt-btn mbt-btn-next" :disabled="!answer" @click="next">{{ currentIndex === questions.length - 1 ? '提交' : '下一题' }}</button>
- </view>
- </template>
- </view>
- </template>
- <script>
- import { getMbtiQuestions, submitMbti } from '@/utils/api'
- export default {
- data() {
- return {
- loading: true,
- questions: [],
- answers: {},
- currentIndex: 0,
- memberId: 0
- }
- },
- computed: {
- currentQuestion() { return this.questions[this.currentIndex] || {} },
- currentDimName() {
- var map = { E: '外向/内向', I: '外向/内向', S: '实感/直觉', N: '实感/直觉', T: '思考/情感', F: '思考/情感', J: '判断/知觉', P: '判断/知觉' }
- return map[this.currentQuestion.dimension] || ''
- },
- currentDimColor() {
- var map = { E: '#6366F1', I: '#6366F1', S: '#10B981', N: '#10B981', T: '#FF6B9D', F: '#FF6B9D', J: '#F59E0B', P: '#F59E0B' }
- return map[this.currentQuestion.dimension] || '#6366F1'
- },
- progress() { return this.questions.length > 0 ? Math.round((this.currentIndex + 1) / this.questions.length * 100) : 0 },
- answer() { return this.answers[this.currentQuestion.id] || '' }
- },
- onLoad(options) {
- this.memberId = options.memberId ? parseInt(options.memberId) : 0
- this.loadQuestions()
- },
- methods: {
- loadQuestions() {
- var self = this
- getMbtiQuestions().then(function(res) {
- if (res.code === 200 && res.data) self.questions = res.data
- self.loading = false
- }).catch(function() { self.loading = false })
- },
- selectAnswer(val) { this.answers[this.currentQuestion.id] = val },
- prev() { if (this.currentIndex > 0) this.currentIndex-- },
- next() {
- if (!this.answer) return
- if (this.currentIndex < this.questions.length - 1) {
- this.currentIndex++
- } else {
- this.submit()
- }
- },
- submit() {
- var self = this
- var answers = []
- var ids = Object.keys(this.answers)
- for (var i = 0; i < ids.length; i++) {
- answers.push({ questionId: parseInt(ids[i]), answer: this.answers[ids[i]] })
- }
- uni.showLoading({ title: '计算中...', mask: true })
- submitMbti({ familyMemberId: this.memberId, answers: answers }).then(function(res) {
- uni.hideLoading()
- if (res.code === 200) {
- uni.navigateTo({ url: '/pages/family/mbti-result?id=' + res.data.id })
- } else {
- uni.showToast({ title: res.message || '提交失败', icon: 'none' })
- }
- }).catch(function() {
- uni.hideLoading()
- uni.showToast({ title: '网络异常', icon: 'none' })
- })
- }
- }
- }
- </script>
- <style scoped>
- .mbt-page { min-height: 100vh; background: #F5FAFE; padding-bottom: 180rpx }
- .mbt-header { padding: 20rpx 30rpx; text-align: right }
- .mbt-progress-text { font-size: 24rpx; color: #999 }
- .mbt-progress-bar { height: 6rpx; background: #E0E7FF; margin: 0 30rpx; border-radius: 3rpx; overflow: hidden }
- .mbt-progress-fill { height: 100%; transition: width .3s }
- .mbt-loading { display: flex; justify-content: center; padding: 100rpx 0 }
- .mbt-card { background: #fff; margin: 20rpx 30rpx; border-radius: 24rpx; padding: 30rpx 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.05) }
- .mbt-dim-tag { display: inline-block; font-size: 22rpx; color: #fff; padding: 4rpx 16rpx; border-radius: 16rpx; margin-bottom: 16rpx }
- .mbt-q-text { font-size: 30rpx; font-weight: 500; color: #333; line-height: 1.5; margin-bottom: 24rpx }
- .mbt-opts { display: flex; flex-direction: column; gap: 16rpx }
- .mbt-opt { flex: 1; padding: 24rpx; border: 2rpx solid #F0F0F0; border-radius: 16rpx; display: flex; align-items: center; justify-content: space-between; transition: border-color .2s, background .2s }
- .mbt-opt-sel { border-color: #6366F1; background: #F0F4FF }
- .mbt-opt-label { font-size: 26rpx; color: #333; line-height: 1.4 }
- .mbt-opt-radio { width: 24rpx; height: 24rpx; border: 2rpx solid #D1D5DB; border-radius: 50%; flex-shrink: 0 }
- .mbt-opt-radio.on { background: #6366F1; border-color: #6366F1 }
- .mbt-footer { position: fixed; bottom: 0; left: 0; right: 0; padding: 20rpx 30rpx; background: #fff; border-top: 1rpx solid #F0F0F0; display: flex; gap: 20rpx; box-sizing: border-box }
- .mbt-btn { flex: 1; height: 88rpx; line-height: 88rpx; font-size: 30rpx; border-radius: 44rpx; border: none; text-align: center }
- .mbt-btn-prev { background: #fff; color: #6366F1; border: 2rpx solid #6366F1 }
- .mbt-btn-next { background: linear-gradient(135deg, #6366F1, #818CF8); color: #fff; font-weight: 600 }
- </style>
|