form.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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="summary-box" v-if="salonTitle">
  7. <view class="summary-row">
  8. <text class="summary-label">活动主题</text>
  9. <text class="summary-value">{{ salonTheme }} - {{ salonTitle }}</text>
  10. </view>
  11. </view>
  12. <view class="form-item">
  13. <text class="form-label">姓名</text>
  14. <input class="form-input" v-model="form.name" placeholder="请输入真实姓名" />
  15. </view>
  16. <view class="form-item">
  17. <text class="form-label">手机号</text>
  18. <input class="form-input" v-model="form.phone" type="number" maxlength="11" placeholder="请输入手机号" />
  19. </view>
  20. <view class="form-item">
  21. <text class="form-label">邀请码(选填)</text>
  22. <input class="form-input" v-model="form.inviteCode" placeholder="邀请码(选填)" />
  23. </view>
  24. <button class="submit-btn" @click="handleSubmit" :loading="loading" :disabled="loading">提交报名</button>
  25. </view>
  26. </view>
  27. </template>
  28. <script>
  29. import { createSalonEnroll } from '@/utils/api.js'
  30. import { guardPage } from '@/utils/guard.js'
  31. export default {
  32. data() {
  33. return {
  34. form: {
  35. salonId: '',
  36. name: '',
  37. phone: '',
  38. inviteCode: ''
  39. },
  40. salonTheme: '',
  41. salonTitle: '',
  42. loading: false
  43. }
  44. },
  45. onLoad(options) {
  46. if (!guardPage()) return
  47. this.form.salonId = options && options.salonId ? options.salonId : ''
  48. this.salonTheme = options && options.theme ? decodeURIComponent(options.theme) : ''
  49. this.salonTitle = options && options.title ? decodeURIComponent(options.title) : ''
  50. this.form.name = options && options.name ? decodeURIComponent(options.name) : ''
  51. this.form.phone = options && options.phone ? decodeURIComponent(options.phone) : ''
  52. if (!this.form.salonId) {
  53. uni.showToast({ title: '参数错误', icon: 'none' })
  54. setTimeout(function() {
  55. uni.navigateBack({ delta: 1 })
  56. }, 1500)
  57. }
  58. },
  59. methods: {
  60. handleSubmit() {
  61. var name = (this.form.name || '').trim()
  62. var phone = (this.form.phone || '').trim()
  63. if (!name) {
  64. uni.showToast({ title: '请填写姓名', icon: 'none' })
  65. return
  66. }
  67. if (!/^1\d{10}$/.test(phone)) {
  68. uni.showToast({ title: '请填写正确的手机号', icon: 'none' })
  69. return
  70. }
  71. if (this.loading) return
  72. this.loading = true
  73. var self = this
  74. var payload = {
  75. salonId: self.form.salonId,
  76. name: name,
  77. phone: phone,
  78. inviteCode: (self.form.inviteCode || '').trim()
  79. }
  80. createSalonEnroll(payload).then(function(resp) {
  81. uni.showToast({ title: '报名成功', icon: 'success' })
  82. setTimeout(function() {
  83. var enrollmentId = resp.data && resp.data.id ? resp.data.id : ''
  84. if (enrollmentId) {
  85. uni.redirectTo({ url: '/pages/pay/index?enrollmentId=' + enrollmentId })
  86. } else {
  87. uni.redirectTo({ url: '/pages/salon/list' })
  88. }
  89. }, 1200)
  90. }).catch(function(err) {
  91. uni.showToast({ title: (err && err.message) || '报名失败', icon: 'none' })
  92. }).finally(function() {
  93. self.loading = false
  94. })
  95. }
  96. }
  97. }
  98. </script>
  99. <style scoped>
  100. .form-page { min-height: 100vh; background: #F5F5F5; padding: 32rpx; }
  101. .section-card { background: #FFF; border-radius: 16rpx; padding: 32rpx; }
  102. .section-title { display: block; font-size: 32rpx; font-weight: 700; color: #1E293B; margin-bottom: 8rpx; border-left: 8rpx solid #F97316; padding-left: 16rpx; }
  103. .card-desc { display: block; font-size: 26rpx; color: #64748B; margin-bottom: 32rpx; }
  104. .summary-box { background: #FFF7ED; border-radius: 8rpx; padding: 20rpx 24rpx; margin-bottom: 24rpx; border: 2rpx solid #FED7AA; }
  105. .summary-row { display: flex; align-items: center; margin-bottom: 8rpx; }
  106. .summary-row:last-child { margin-bottom: 0; }
  107. .summary-label { font-size: 24rpx; color: #64748B; width: 140rpx; flex-shrink: 0; }
  108. .summary-value { font-size: 26rpx; color: #1E293B; font-weight: 600; flex: 1; }
  109. .form-item { margin-bottom: 24rpx; }
  110. .form-label { display: block; font-size: 26rpx; color: #475569; font-weight: 500; margin-bottom: 12rpx; }
  111. .form-input { height: 72rpx; border: 2rpx solid #E2E8F0; border-radius: 8rpx; padding: 0 16rpx; font-size: 28rpx; color: #1E293B; background: #F8FAFC; }
  112. .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; }
  113. .submit-btn:active { opacity: 0.85; }
  114. </style>