form.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <view class="form-page">
  3. <view class="section-card">
  4. <text class="section-title">报名信息</text>
  5. <text class="card-desc">请填写您的联系方式与准备情况</text>
  6. <view class="form-item">
  7. <text class="form-label">姓名</text>
  8. <input class="form-input" v-model="form.name" placeholder="请输入真实姓名" />
  9. </view>
  10. <view class="form-item">
  11. <text class="form-label">手机号</text>
  12. <input class="form-input" v-model="form.phone" type="number" maxlength="11" placeholder="请输入手机号" />
  13. </view>
  14. <view class="form-item switch-item">
  15. <text class="form-label">是否携带笔记本</text>
  16. <switch :checked="form.bringLaptop === 1" color="#F97316" @change="onLaptopChange" />
  17. </view>
  18. <view class="form-item">
  19. <text class="form-label">已备数据</text>
  20. <view class="check-group">
  21. <view class="check-item" @click="toggleData('wealth')">
  22. <text class="check-square" :class="{ checked: dataReadyList.indexOf('wealth') > -1 }">✓</text>
  23. <text class="check-text">券商持仓</text>
  24. </view>
  25. <view class="check-item" @click="toggleData('health')">
  26. <text class="check-square" :class="{ checked: dataReadyList.indexOf('health') > -1 }">✓</text>
  27. <text class="check-text">体检/血压报告</text>
  28. </view>
  29. <view class="check-item" @click="toggleData('growth')">
  30. <text class="check-square" :class="{ checked: dataReadyList.indexOf('growth') > -1 }">✓</text>
  31. <text class="check-text">孩子成绩/日程</text>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="form-item">
  36. <text class="form-label">最想解决的问题</text>
  37. <textarea class="form-textarea" v-model="form.topProblems" placeholder="如:如何用AI管理家庭资产、孩子学习计划…" />
  38. </view>
  39. <view class="form-item" v-if="form.inviteCode">
  40. <text class="form-label">邀请码</text>
  41. <input class="form-input" v-model="form.inviteCode" disabled placeholder="微信好友邀请码" />
  42. </view>
  43. <button class="submit-btn" @click="handleSubmit" :loading="loading" :disabled="loading">提交报名</button>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. import { createEnrollment } from '@/utils/api.js'
  49. export default {
  50. data() {
  51. return {
  52. form: {
  53. classId: '',
  54. name: '',
  55. phone: '',
  56. bringLaptop: 0,
  57. dataReady: '',
  58. topProblems: '',
  59. inviteCode: ''
  60. },
  61. dataReadyList: [],
  62. loading: false
  63. }
  64. },
  65. onLoad(options) {
  66. this.form.classId = options && options.classId ? options.classId : ''
  67. this.form.inviteCode = options && options.inviteCode ? decodeURIComponent(options.inviteCode) : ''
  68. this.form.name = options && options.name ? decodeURIComponent(options.name) : ''
  69. this.form.phone = options && options.phone ? decodeURIComponent(options.phone) : ''
  70. if (!this.form.classId) {
  71. uni.showToast({ title: '请先选择班次', icon: 'none' })
  72. setTimeout(function() {
  73. uni.navigateBack({ delta: 1 })
  74. }, 1500)
  75. }
  76. },
  77. methods: {
  78. onLaptopChange(e) {
  79. this.form.bringLaptop = e.detail.value ? 1 : 0
  80. },
  81. toggleData(key) {
  82. var idx = this.dataReadyList.indexOf(key)
  83. if (idx > -1) {
  84. this.dataReadyList.splice(idx, 1)
  85. } else {
  86. this.dataReadyList.push(key)
  87. }
  88. this.form.dataReady = this.dataReadyList.join(',')
  89. },
  90. handleSubmit() {
  91. var name = (this.form.name || '').trim()
  92. var phone = (this.form.phone || '').trim()
  93. if (!name) {
  94. uni.showToast({ title: '请填写姓名', icon: 'none' })
  95. return
  96. }
  97. if (!/^1\d{10}$/.test(phone)) {
  98. uni.showToast({ title: '请填写正确的手机号', icon: 'none' })
  99. return
  100. }
  101. if (this.loading) return
  102. this.loading = true
  103. var self = this
  104. var payload = {
  105. classId: self.form.classId,
  106. name: name,
  107. phone: phone,
  108. bringLaptop: self.form.bringLaptop,
  109. dataReady: self.form.dataReady,
  110. topProblems: (self.form.topProblems || '').trim(),
  111. inviteCode: self.form.inviteCode
  112. }
  113. createEnrollment(payload).then(function(resp) {
  114. uni.showToast({ title: '报名成功', icon: 'success' })
  115. setTimeout(function() {
  116. uni.redirectTo({ url: '/pages/enroll/list' })
  117. }, 1200)
  118. }).catch(function(err) {
  119. uni.showToast({ title: (err && err.message) || '报名失败', icon: 'none' })
  120. }).finally(function() {
  121. self.loading = false
  122. })
  123. }
  124. }
  125. }
  126. </script>
  127. <style scoped>
  128. .form-page { min-height: 100vh; background: #F5F5F5; padding: 32rpx; }
  129. .section-card { background: #FFF; border-radius: 16rpx; padding: 32rpx; }
  130. .section-title { display: block; font-size: 32rpx; font-weight: 700; color: #1E293B; margin-bottom: 8rpx; border-left: 8rpx solid #F97316; padding-left: 16rpx; }
  131. .card-desc { display: block; font-size: 26rpx; color: #64748B; margin-bottom: 32rpx; }
  132. .form-item { margin-bottom: 24rpx; }
  133. .form-label { display: block; font-size: 26rpx; color: #475569; font-weight: 500; margin-bottom: 12rpx; }
  134. .form-input { height: 72rpx; border: 2rpx solid #E2E8F0; border-radius: 8rpx; padding: 0 16rpx; font-size: 28rpx; color: #1E293B; background: #F8FAFC; }
  135. .form-textarea { width: 100%; height: 160rpx; border: 2rpx solid #E2E8F0; border-radius: 8rpx; padding: 16rpx; font-size: 28rpx; color: #1E293B; background: #F8FAFC; box-sizing: border-box; }
  136. .check-group { display: flex; flex-wrap: wrap; }
  137. .check-item { display: flex; align-items: center; width: 50%; margin-bottom: 16rpx; }
  138. .check-square { width: 36rpx; height: 36rpx; border: 2rpx solid #CBD5E1; border-radius: 6rpx; display: flex; align-items: center; justify-content: center; font-size: 24rpx; color: #FFF; margin-right: 12rpx; flex-shrink: 0; }
  139. .check-square.checked { background: #F97316; border-color: #F97316; }
  140. .check-text { font-size: 26rpx; color: #1E293B; }
  141. .switch-item { display: flex; align-items: center; justify-content: space-between; }
  142. .switch-item .form-label { margin-bottom: 0; }
  143. .submit-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: #F97316; color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; margin-top: 24rpx; }
  144. .submit-btn:active { opacity: 0.85; }
  145. </style>