mbti-entry.vue 4.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. <template>
  2. <view class="mbe-page">
  3. <view class="mbe-loading" v-if="loading">
  4. <text class="mbe-loading-text">加载成员...</text>
  5. </view>
  6. <template v-else>
  7. <view class="mbe-hero">
  8. <text class="mbe-hero-title">MBTI 人格测评</text>
  9. <text class="mbe-hero-desc">标准版 30 题 · 发现你的天赋型 · 获得专属育儿建议</text>
  10. </view>
  11. <view class="mbe-section">
  12. <text class="mbe-section-title">选择测评对象</text>
  13. <view class="mbe-member-list">
  14. <view class="mbe-member-item" :class="{ active: selectedMemberId === m.id }" v-for="m in members" :key="m.id" @click="selectMember(m)">
  15. <image class="mbe-member-avatar" :src="m.avatar || '/static/avatar-default.png'" mode="aspectFill"></image>
  16. <view class="mbe-member-info">
  17. <text class="mbe-member-name">{{ m.nickname }}</text>
  18. <text class="mbe-member-role" :class="'role-' + m.effectiveRole">{{ m.roleLabel }}</text>
  19. </view>
  20. <view class="mbe-member-check" v-if="selectedMemberId === m.id">✓</view>
  21. </view>
  22. </view>
  23. </view>
  24. <view class="mbe-footer">
  25. <button class="mbe-btn mbe-btn-primary" :disabled="!selectedMemberId || startLoading" @click="start">
  26. {{ startLoading ? '加载中...' : '开始测评(约 8 分钟)' }}
  27. </button>
  28. <text class="mbe-tip">测评结果:4 字母类型 · 4 维雷达 · 专属画像 · 五维联动建议</text>
  29. </view>
  30. </template>
  31. </view>
  32. </template>
  33. <script>
  34. import { getFamilyMemberList } from '@/utils/api'
  35. export default {
  36. data() {
  37. return {
  38. loading: true,
  39. members: [],
  40. selectedMemberId: null,
  41. startLoading: false
  42. }
  43. },
  44. onLoad() {
  45. this.loadMembers()
  46. },
  47. methods: {
  48. loadMembers() {
  49. var self = this
  50. getFamilyMemberList({ visibleOnly: true }).then(function(res) {
  51. if (res.code === 200 && res.data && res.data.length > 0) {
  52. self.members = res.data
  53. var own = null
  54. for (var i = 0; i < self.members.length; i++) {
  55. if (self.members[i].isSelf) { own = self.members[i]; break }
  56. }
  57. self.selectedMemberId = own ? own.id : (self.members.length > 0 ? self.members[0].id : null)
  58. }
  59. self.loading = false
  60. }).catch(function() { self.loading = false })
  61. },
  62. selectMember(m) { this.selectedMemberId = m.id },
  63. start() {
  64. if (!this.selectedMemberId || this.startLoading) return
  65. this.startLoading = true
  66. uni.navigateTo({ url: '/pages/family/mbti-test?memberId=' + this.selectedMemberId })
  67. }
  68. }
  69. }
  70. </script>
  71. <style scoped>
  72. .mbe-page { min-height: 100vh; background: #F5FAFE; padding: 24rpx 30rpx 120rpx; box-sizing: border-box }
  73. .mbe-loading { display: flex; justify-content: center; align-items: center; height: 50vh }
  74. .mbe-loading-text { font-size: 28rpx; color: #999 }
  75. .mbe-hero { text-align: center; padding: 40rpx 0 10rpx }
  76. .mbe-hero-title { font-size: 36rpx; font-weight: 600; color: #333; display: block; margin-bottom: 8rpx }
  77. .mbe-hero-desc { font-size: 24rpx; color: #999; display: block }
  78. .mbe-section { background: #fff; border-radius: 24rpx; padding: 24rpx; margin-bottom: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.05) }
  79. .mbe-section-title { font-size: 28rpx; font-weight: 600; color: #333; margin-bottom: 20rpx; display: block }
  80. .mbe-member-list { display: flex; overflow-x: auto; gap: 20rpx; padding-bottom: 10rpx }
  81. .mbe-member-item { flex: 0 0 140rpx; display: flex; flex-direction: column; align-items: center; border: 4rpx solid transparent; border-radius: 20rpx; padding: 16rpx 10rpx; transition: border-color .2s }
  82. .mbe-member-item.active { border-color: #6366F1 }
  83. .mbe-member-avatar { width: 80rpx; height: 80rpx; border-radius: 50%; margin-bottom: 12rpx }
  84. .mbe-member-name { font-size: 26rpx; font-weight: 500; color: #333; text-align: center; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
  85. .mbe-member-role { font-size: 20rpx; padding: 2rpx 10rpx; border-radius: 10rpx; display: inline-block }
  86. .role-parent { background: #FFF7ED; color: #E65100 }
  87. .role-child { background: #E8F5E9; color: #2E7D32 }
  88. .role-teacher { background: #E0E7FF; color: #3730A3 }
  89. .mbe-member-check { margin-top: 8rpx; font-size: 24rpx; color: #6366F1 }
  90. .mbe-footer { position: fixed; bottom: 0; left: 0; right: 0; padding: 20rpx 30rpx; background: #fff; border-top: 1rpx solid #F0F0F0; box-sizing: border-box }
  91. .mbe-btn { width: 100%; height: 88rpx; line-height: 88rpx; font-size: 30rpx; border-radius: 44rpx; border: none; text-align: center }
  92. .mbe-btn-primary { background: linear-gradient(135deg, #6366F1, #818CF8); color: #fff; font-weight: 600 }
  93. .mbe-tip { display: block; text-align: center; margin-top: 16rpx; font-size: 22rpx; color: #999 }
  94. </style>