木邻有你前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
7.6 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view>
  3. <uv-popup
  4. ref="popup"
  5. mode="bottom"
  6. border-radius="20"
  7. @close="handleClose"
  8. >
  9. <view class="signup-form">
  10. <!-- 表单标题 -->
  11. <view class="form-header">
  12. <text class="form-title">我要报名</text>
  13. </view>
  14. <!-- 表单内容 -->
  15. <view class="form-content">
  16. <!-- 姓名 -->
  17. <view class="form-item">
  18. <view class="input-container">
  19. <text class="input-label required">姓名</text>
  20. <uv-input
  21. v-model="formData.name"
  22. placeholder="请输入您的姓名"
  23. border="none"
  24. :custom-style="inputStyle"
  25. ></uv-input>
  26. </view>
  27. </view>
  28. <!-- 性别 -->
  29. <view class="form-item">
  30. <view class="input-container" @click="showGenderPicker">
  31. <text class="input-label required">性别</text>
  32. <view class="picker-input">
  33. <text class="picker-text" :class="{ placeholder: !formData.sex }">{{ formData.sex || '请选择' }}</text>
  34. <uv-icon name="arrow-right" size="14" color="#999"></uv-icon>
  35. </view>
  36. </view>
  37. </view>
  38. <!-- 年龄 -->
  39. <view class="form-item">
  40. <view class="input-container">
  41. <text class="input-label required">年龄</text>
  42. <uv-input
  43. v-model="formData.age"
  44. placeholder="请输入您的年龄"
  45. type="number"
  46. border="none"
  47. :custom-style="inputStyle"
  48. ></uv-input>
  49. </view>
  50. </view>
  51. <!-- 手机号 -->
  52. <view class="form-item">
  53. <view class="input-container">
  54. <text class="input-label required">手机号</text>
  55. <uv-input
  56. v-model="formData.phone"
  57. placeholder="请输入您的手机号"
  58. type="number"
  59. border="none"
  60. :custom-style="inputStyle"
  61. ></uv-input>
  62. </view>
  63. </view>
  64. <!-- 所在地区 -->
  65. <view class="form-item">
  66. <view class="input-container" @click="openAreaPicker">
  67. <text class="input-label">所在宿集区</text>
  68. <view class="picker-input">
  69. <text class="picker-text" :class="{ placeholder: !formData.area }">{{ formData.area || '请选择宿集区' }}</text>
  70. <uv-icon name="arrow-right" size="14" color="#999"></uv-icon>
  71. </view>
  72. </view>
  73. </view>
  74. <!-- 详细地址 -->
  75. <view class="form-item">
  76. <view class="input-container">
  77. <text class="input-label">详细地址</text>
  78. <uv-input
  79. v-model="formData.address"
  80. placeholder="请输入详细地址"
  81. border="none"
  82. :custom-style="inputStyle"
  83. ></uv-input>
  84. </view>
  85. </view>
  86. </view>
  87. <!-- 提交按钮 -->
  88. <view class="form-footer">
  89. <uv-button
  90. type="primary"
  91. text="提交报名"
  92. :custom-style="buttonStyle"
  93. @click="submitForm"
  94. ></uv-button>
  95. </view>
  96. </view>
  97. </uv-popup>
  98. <!-- 性别选择器 -->
  99. <uv-picker
  100. ref="genderPicker"
  101. :columns="genderOptions"
  102. @confirm="onGenderConfirm"
  103. @cancel="onGenderCancel"
  104. @close="onGenderCancel"
  105. ></uv-picker>
  106. <uv-picker ref="areaPicker" :columns="columns" @confirm="onAreaConfirm"></uv-picker>
  107. </view>
  108. </template>
  109. <script>
  110. export default {
  111. name: 'SignUpForm',
  112. data() {
  113. return {
  114. show: false,
  115. formData: {
  116. name: '',
  117. sex: '',
  118. age: '',
  119. phone: '',
  120. area: '',
  121. address: ''
  122. },
  123. genderOptions: [['男', '女']],
  124. inputStyle: {
  125. backgroundColor: 'transparent',
  126. fontSize: '28rpx'
  127. },
  128. buttonStyle: {
  129. width: '100%',
  130. height: '88rpx',
  131. borderRadius: '44rpx'
  132. }
  133. }
  134. },
  135. computed:{
  136. columns(){
  137. return [[...this.$store.state.areaList.map(item => item.title)]]
  138. }
  139. },
  140. methods: {
  141. handleClose() {
  142. this.$emit('close')
  143. this.$refs.popup.close()
  144. },
  145. showGenderPicker() {
  146. this.$refs.genderPicker.open()
  147. },
  148. openAreaPicker() {
  149. // 打开选择器
  150. this.$refs.areaPicker.open()
  151. },
  152. onGenderConfirm(value) {
  153. this.formData.sex = value.value[0]
  154. },
  155. onAreaConfirm(value) {
  156. this.formData.area = value.value[0]
  157. },
  158. validateForm() {
  159. if (!this.formData.name.trim()) {
  160. uni.showToast({
  161. title: '请输入姓名',
  162. icon: 'none'
  163. })
  164. return false
  165. }
  166. if (!this.formData.sex) {
  167. uni.showToast({
  168. title: '请选择性别',
  169. icon: 'none'
  170. })
  171. return false
  172. }
  173. if (!this.formData.age.trim()) {
  174. uni.showToast({
  175. title: '请输入年龄',
  176. icon: 'none'
  177. })
  178. return false
  179. }
  180. if (!this.formData.phone.trim()) {
  181. uni.showToast({
  182. title: '请输入手机号',
  183. icon: 'none'
  184. })
  185. return false
  186. }
  187. if (!/^1[3-9]\d{9}$/.test(this.formData.phone)) {
  188. uni.showToast({
  189. title: '请输入正确的手机号',
  190. icon: 'none'
  191. })
  192. return false
  193. }
  194. return true
  195. },
  196. submitForm() {
  197. if (!this.validateForm()) {
  198. return
  199. }
  200. this.formData.sex = this.formData.sex === '男' ? 0 : 1
  201. // 提交表单数据
  202. // delete this.formData.age
  203. this.$emit('submit', this.formData)
  204. // 重置表单
  205. this.resetForm()
  206. // 关闭弹窗
  207. this.handleClose()
  208. },
  209. resetForm() {
  210. this.formData = {
  211. name: '',
  212. sex: '',
  213. age: '',
  214. phone: '',
  215. area: '',
  216. address: ''
  217. }
  218. },
  219. open() {
  220. this.$refs.popup.open()
  221. },
  222. close() {
  223. this.$refs.popup.close()
  224. }
  225. },
  226. expose: ['open', 'close']
  227. }
  228. </script>
  229. <style lang="scss" scoped>
  230. .signup-form {
  231. max-height: 1000rpx;
  232. display: flex;
  233. flex-direction: column;
  234. background: #ffffff;
  235. .form-header {
  236. padding: 40rpx 30rpx 20rpx;
  237. text-align: center;
  238. border-bottom: 1rpx solid #f0f0f0;
  239. .form-title {
  240. font-size: 36rpx;
  241. font-weight: bold;
  242. color: #333333;
  243. }
  244. }
  245. .form-content {
  246. flex: 1;
  247. padding: 30rpx;
  248. overflow-y: auto;
  249. .form-item {
  250. margin-bottom: 30rpx;
  251. &:last-child {
  252. margin-bottom: 0;
  253. }
  254. .input-container {
  255. background: #f3f7f8;
  256. border-radius: 16rpx;
  257. padding: 24rpx 30rpx;
  258. display: flex;
  259. align-items: center;
  260. .input-label {
  261. font-size: 28rpx;
  262. color: #333333;
  263. margin-right: 20rpx;
  264. min-width: 120rpx;
  265. &.required::before {
  266. content: '*';
  267. color: #ff4757;
  268. margin-right: 4rpx;
  269. }
  270. }
  271. .picker-input {
  272. flex: 1;
  273. display: flex;
  274. align-items: center;
  275. justify-content: space-between;
  276. .picker-text {
  277. font-size: 28rpx;
  278. color: #333333;
  279. &.placeholder {
  280. color: #999999;
  281. }
  282. }
  283. }
  284. }
  285. }
  286. }
  287. .form-footer {
  288. padding: 30rpx;
  289. border-top: 1rpx solid #f0f0f0;
  290. }
  291. }
  292. </style>