teacher-select.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <view class="page">
  3. <!-- 导航栏 -->
  4. <!-- 提示 -->
  5. <view class="tip-banner">
  6. <text class="tip-icon">👩‍🏫</text>
  7. <text class="tip-text">选择一位规划师,将在方案生成后为您审核和定制计划</text>
  8. </view>
  9. <!-- 规划师列表 -->
  10. <view class="teacher-list" v-if="teachers.length > 0">
  11. <view
  12. v-for="t in teachers"
  13. :key="t.id"
  14. class="teacher-card"
  15. :class="{ active: selectedTeacherId === t.id }"
  16. @click="selectTeacher(t)"
  17. >
  18. <view class="teacher-avatar">{{ (t.name || '规划师').charAt(0) }}</view>
  19. <view class="teacher-info">
  20. <text class="teacher-name">{{ t.name || '规划师' }}</text>
  21. <text class="teacher-tag" v-if="t.isBound">✓ 已绑定家庭</text>
  22. </view>
  23. <view class="teacher-check" v-if="selectedTeacherId === t.id">✓</view>
  24. </view>
  25. </view>
  26. <!-- 空状态 -->
  27. <view class="empty-state" v-else>
  28. <text class="empty-icon">🔍</text>
  29. <text class="empty-text">暂无可用规划师</text>
  30. <text class="empty-hint">请联系管理员为您分配规划师</text>
  31. </view>
  32. <!-- 底部按钮 -->
  33. <view class="bottom-bar">
  34. <button class="btn-next" :disabled="!selectedTeacherId" @click="confirmSelection">
  35. {{ selectedTeacherId ? '确认选择' : '请选择规划师' }}
  36. </button>
  37. </view>
  38. </view>
  39. </template>
  40. <script>
  41. import { getAvailableTeachers } from '../../utils/api'
  42. export default {
  43. data() {
  44. return {
  45. teachers: [],
  46. selectedTeacherId: null,
  47. familyId: null,
  48. loading: false
  49. }
  50. },
  51. onLoad: function(options) {
  52. this.familyId = options.familyId ? parseInt(options.familyId) : null
  53. if (!this.familyId) {
  54. this.familyId = uni.getStorageSync('familyId') ? parseInt(uni.getStorageSync('familyId')) : null
  55. }
  56. if (!this.familyId) {
  57. uni.showToast({ title: '缺少家庭信息', icon: 'none' })
  58. setTimeout(() => uni.navigateBack(), 1000)
  59. return
  60. }
  61. this.loadTeachers()
  62. },
  63. methods: {
  64. async loadTeachers() {
  65. this.loading = true
  66. try {
  67. var self = this
  68. getAvailableTeachers({ familyId: this.familyId }).then(function(res) {
  69. self.loading = false
  70. if (res.code === 200) {
  71. self.teachers = res.data || []
  72. } else {
  73. uni.showToast({ title: res.message || '加载失败', icon: 'none' })
  74. }
  75. }).catch(function() {
  76. self.loading = false
  77. uni.showToast({ title: '加载失败,请重试', icon: 'none' })
  78. })
  79. } catch(e) {
  80. this.loading = false
  81. }
  82. },
  83. selectTeacher: function(t) {
  84. this.selectedTeacherId = t.id
  85. },
  86. confirmSelection: function() {
  87. if (!this.selectedTeacherId) return
  88. uni.setStorageSync('healthPlan_teacherId', this.selectedTeacherId)
  89. uni.navigateBack()
  90. },
  91. goBack: function() {
  92. uni.navigateBack()
  93. }
  94. }
  95. }
  96. </script>
  97. <style scoped>
  98. .page { min-height: 100vh; background: #F3F7FA; padding-bottom: 120rpx; }
  99. .nav-placeholder { width: 80rpx; }
  100. .tip-banner {
  101. display: flex; align-items: center; gap: 12rpx;
  102. margin: 24rpx 32rpx; padding: 20rpx 24rpx;
  103. background: #FEF3C7; border-radius: 16rpx;
  104. }
  105. .tip-icon { font-size: 36rpx; }
  106. .tip-text { font-size: 26rpx; color: #92400E; flex: 1; }
  107. .teacher-list { padding: 0 32rpx; }
  108. .teacher-card {
  109. display: flex; align-items: center; gap: 20rpx;
  110. background: #fff; border-radius: 16rpx; padding: 24rpx;
  111. margin-bottom: 16rpx; border: 2rpx solid #E5E7EB;
  112. }
  113. .teacher-card.active { border-color: #3B82F6; background: #EFF6FF; }
  114. .teacher-avatar {
  115. width: 80rpx; height: 80rpx; border-radius: 50%;
  116. background: linear-gradient(135deg, #3B82F6, #60A5FA);
  117. color: #fff; font-size: 32rpx; font-weight: bold;
  118. display: flex; align-items: center; justify-content: center;
  119. }
  120. .teacher-info { flex: 1; }
  121. .teacher-name { font-size: 30rpx; font-weight: bold; color: #333; display: block; }
  122. .teacher-tag { font-size: 22rpx; color: #10B981; margin-top: 4rpx; display: block; }
  123. .teacher-check { font-size: 36rpx; color: #3B82F6; font-weight: bold; }
  124. .empty-state { text-align: center; padding: 120rpx 40rpx; }
  125. .empty-icon { font-size: 80rpx; display: block; margin-bottom: 20rpx; }
  126. .empty-text { font-size: 30rpx; color: #666; display: block; }
  127. .empty-hint { font-size: 24rpx; color: #999; margin-top: 12rpx; display: block; }
  128. .bottom-bar {
  129. position: fixed; bottom: 0; left: 0; right: 0;
  130. padding: 24rpx 32rpx; background: #fff;
  131. border-top: 1rpx solid #E5E7EB;
  132. }
  133. .btn-next {
  134. width: 100%; height: 88rpx; line-height: 88rpx;
  135. background: linear-gradient(135deg, #3B82F6, #2563EB);
  136. color: #fff; font-size: 32rpx; font-weight: bold;
  137. border-radius: 44rpx; border: none;
  138. }
  139. .btn-next[disabled] { background: #CBD5E1; }
  140. </style>