国外MOSE官网
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.

353 lines
8.0 KiB

4 days ago
4 days 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.gender }">{{ formData.gender || '请选择' }}</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="chooseLocation">
  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. </view>
  107. </template>
  108. <script>
  109. export default {
  110. name: 'SignUpForm',
  111. data() {
  112. return {
  113. show: false,
  114. formData: {
  115. name: '',
  116. gender: '',
  117. age: '',
  118. phone: '',
  119. area: '',
  120. address: ''
  121. },
  122. genderOptions: [['男', '女']],
  123. inputStyle: {
  124. backgroundColor: 'transparent',
  125. fontSize: '28rpx'
  126. },
  127. buttonStyle: {
  128. width: '100%',
  129. height: '88rpx',
  130. borderRadius: '44rpx'
  131. }
  132. }
  133. },
  134. methods: {
  135. handleClose() {
  136. this.$emit('close')
  137. this.$refs.popup.close()
  138. },
  139. showGenderPicker() {
  140. this.$refs.genderPicker.open()
  141. },
  142. chooseLocation() {
  143. uni.chooseLocation({
  144. success: (res) => {
  145. console.log('位置名称:' + res.name)
  146. console.log('详细地址:' + res.address)
  147. console.log('纬度:' + res.latitude)
  148. console.log('经度:' + res.longitude)
  149. // 设置选中的地址
  150. this.formData.area = res.address || res.name
  151. // 如果详细地址为空,也可以自动填充
  152. if (!this.formData.address && res.name) {
  153. this.formData.address = res.name
  154. }
  155. },
  156. fail: (err) => {
  157. console.log('选择位置失败:', err)
  158. uni.showToast({
  159. title: '获取位置失败',
  160. icon: 'none'
  161. })
  162. }
  163. })
  164. },
  165. onGenderConfirm(value) {
  166. this.formData.gender = value.value[0]
  167. },
  168. onGenderCancel() {
  169. // 性别选择器取消时的处理
  170. },
  171. validateForm() {
  172. if (!this.formData.name.trim()) {
  173. uni.showToast({
  174. title: '请输入姓名',
  175. icon: 'none'
  176. })
  177. return false
  178. }
  179. if (!this.formData.gender) {
  180. uni.showToast({
  181. title: '请选择性别',
  182. icon: 'none'
  183. })
  184. return false
  185. }
  186. if (!this.formData.age.trim()) {
  187. uni.showToast({
  188. title: '请输入年龄',
  189. icon: 'none'
  190. })
  191. return false
  192. }
  193. if (!this.formData.phone.trim()) {
  194. uni.showToast({
  195. title: '请输入手机号',
  196. icon: 'none'
  197. })
  198. return false
  199. }
  200. if (!/^1[3-9]\d{9}$/.test(this.formData.phone)) {
  201. uni.showToast({
  202. title: '请输入正确的手机号',
  203. icon: 'none'
  204. })
  205. return false
  206. }
  207. return true
  208. },
  209. submitForm() {
  210. if (!this.validateForm()) {
  211. return
  212. }
  213. this.formData.gender = this.formData.gender === '男' ? 0 : 1
  214. // 提交表单数据
  215. this.$emit('submit', this.formData)
  216. // 重置表单
  217. this.resetForm()
  218. // 关闭弹窗
  219. this.handleClose()
  220. },
  221. resetForm() {
  222. this.formData = {
  223. name: '',
  224. gender: '',
  225. age: '',
  226. phone: '',
  227. area: '',
  228. address: ''
  229. }
  230. },
  231. open() {
  232. this.$refs.popup.open()
  233. },
  234. close() {
  235. this.$refs.popup.close()
  236. }
  237. },
  238. expose: ['open', 'close']
  239. }
  240. </script>
  241. <style lang="scss" scoped>
  242. .signup-form {
  243. max-height: 1000rpx;
  244. display: flex;
  245. flex-direction: column;
  246. background: #ffffff;
  247. .form-header {
  248. padding: 40rpx 30rpx 20rpx;
  249. text-align: center;
  250. border-bottom: 1rpx solid #f0f0f0;
  251. .form-title {
  252. font-size: 36rpx;
  253. font-weight: bold;
  254. color: #333333;
  255. }
  256. }
  257. .form-content {
  258. flex: 1;
  259. padding: 30rpx;
  260. overflow-y: auto;
  261. .form-item {
  262. margin-bottom: 30rpx;
  263. &:last-child {
  264. margin-bottom: 0;
  265. }
  266. .input-container {
  267. background: #f3f7f8;
  268. border-radius: 16rpx;
  269. padding: 24rpx 30rpx;
  270. display: flex;
  271. align-items: center;
  272. .input-label {
  273. font-size: 28rpx;
  274. color: #333333;
  275. margin-right: 20rpx;
  276. min-width: 120rpx;
  277. &.required::before {
  278. content: '*';
  279. color: #ff4757;
  280. margin-right: 4rpx;
  281. }
  282. }
  283. .picker-input {
  284. flex: 1;
  285. display: flex;
  286. align-items: center;
  287. justify-content: space-between;
  288. .picker-text {
  289. font-size: 28rpx;
  290. color: #333333;
  291. &.placeholder {
  292. color: #999999;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. }
  299. .form-footer {
  300. padding: 30rpx;
  301. border-top: 1rpx solid #f0f0f0;
  302. }
  303. }
  304. </style>