木邻有你前端代码仓库
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.

356 lines
8.0 KiB

10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months 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="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. sex: '',
  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.sex = 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.sex) {
  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.sex = this.formData.sex === '男' ? 0 : 1
  214. // 提交表单数据
  215. // delete this.formData.age
  216. this.$emit('submit', this.formData)
  217. // 重置表单
  218. this.resetForm()
  219. // 关闭弹窗
  220. this.handleClose()
  221. },
  222. resetForm() {
  223. this.formData = {
  224. name: '',
  225. sex: '',
  226. age: '',
  227. phone: '',
  228. area: '',
  229. address: ''
  230. }
  231. },
  232. open() {
  233. this.$refs.popup.open()
  234. },
  235. close() {
  236. this.$refs.popup.close()
  237. }
  238. },
  239. expose: ['open', 'close']
  240. }
  241. </script>
  242. <style lang="scss" scoped>
  243. .signup-form {
  244. max-height: 1000rpx;
  245. display: flex;
  246. flex-direction: column;
  247. background: #ffffff;
  248. .form-header {
  249. padding: 40rpx 30rpx 20rpx;
  250. text-align: center;
  251. border-bottom: 1rpx solid #f0f0f0;
  252. .form-title {
  253. font-size: 36rpx;
  254. font-weight: bold;
  255. color: #333333;
  256. }
  257. }
  258. .form-content {
  259. flex: 1;
  260. padding: 30rpx;
  261. overflow-y: auto;
  262. .form-item {
  263. margin-bottom: 30rpx;
  264. &:last-child {
  265. margin-bottom: 0;
  266. }
  267. .input-container {
  268. background: #f3f7f8;
  269. border-radius: 16rpx;
  270. padding: 24rpx 30rpx;
  271. display: flex;
  272. align-items: center;
  273. .input-label {
  274. font-size: 28rpx;
  275. color: #333333;
  276. margin-right: 20rpx;
  277. min-width: 120rpx;
  278. &.required::before {
  279. content: '*';
  280. color: #ff4757;
  281. margin-right: 4rpx;
  282. }
  283. }
  284. .picker-input {
  285. flex: 1;
  286. display: flex;
  287. align-items: center;
  288. justify-content: space-between;
  289. .picker-text {
  290. font-size: 28rpx;
  291. color: #333333;
  292. &.placeholder {
  293. color: #999999;
  294. }
  295. }
  296. }
  297. }
  298. }
  299. }
  300. .form-footer {
  301. padding: 30rpx;
  302. border-top: 1rpx solid #f0f0f0;
  303. }
  304. }
  305. </style>