partner-apply.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <template>
  2. <view class="partner-apply">
  3. <!-- 手机号和验证码区域 -->
  4. <u-form :model="form" ref="uForm" :rules="rules" :error-type="['toast']" :label-width="160">
  5. <view class="form-section">
  6. <u-form-item label="新手机号" prop="mobile">
  7. <u-input v-model="form.mobile" placeholder="获取手机号码" />
  8. <u-button slot="right" type="success" size="mini" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"plain>获取手机号</u-button>
  9. </u-form-item>
  10. <u-form-item label="验证码" prop="verifyCode">
  11. <u-input v-model="form.verifyCode" placeholder="请输入验证码" />
  12. <u-button slot="right" type="success" size="mini" @click="getCode" :disabled="counting" plain>
  13. {{ counting ? `${countdown}s后获取` : "获取验证码" }}
  14. </u-button>
  15. </u-form-item>
  16. </view>
  17. <!-- 基本信息区域 -->
  18. <view class="form-section">
  19. <u-form-item label="姓名" prop="name" required>
  20. <u-input v-model="form.name" placeholder="请输入真实姓名" />
  21. </u-form-item>
  22. <u-form-item label="地址选择" prop="address" required>
  23. <uni-data-picker
  24. v-model="selAddressCodes"
  25. :localdata="dataList"
  26. placeholder="请选择所在区县"
  27. popup-title="请选择所在区县"
  28. @change="cityChange"
  29. ></uni-data-picker>
  30. </u-form-item>
  31. <u-form-item label="学校" prop="school" required>
  32. <u-input v-model="form.school" placeholder="请输入学校" />
  33. </u-form-item>
  34. <u-form-item label="院系" prop="faculties" required>
  35. <u-input v-model="form.faculties" placeholder="请输入院系" />
  36. </u-form-item>
  37. <u-form-item label="专业" prop="specialty" required>
  38. <u-input v-model="form.specialty" placeholder="请输入专业" />
  39. </u-form-item>
  40. <u-form-item label="年级" prop="grade" required>
  41. <u-input v-model="form.grade" placeholder="请输入年级" />
  42. </u-form-item>
  43. </view>
  44. </u-form>
  45. <view class="agreement">
  46. <u-checkbox v-model="agreement" shape="circle">
  47. <text>我已阅读并同意</text>
  48. <text class="agreement-link" @click="goToAgreement">《书嗨用户协议》</text>
  49. </u-checkbox>
  50. </view>
  51. <view class="fixed-bottom">
  52. <u-button type="primary" color="#38C148" @click="submit">提交</u-button>
  53. </view>
  54. </view>
  55. </template>
  56. <script>
  57. export default {
  58. data() {
  59. return {
  60. form: {
  61. provinceId: "",
  62. cityId: "",
  63. districtId: "",
  64. name: "",
  65. school: "",
  66. faculties: "",
  67. specialty: "",
  68. grade: "",
  69. mobile: "",
  70. verifyCode: "",
  71. },
  72. agreement: false,
  73. counting: false,
  74. countdown: 60,
  75. rules: {
  76. name: [{ required: true, message: "请输入真实姓名" }],
  77. school: [{ required: true, message: "请输入学校" }],
  78. faculties: [{ required: true, message: "请输入院系" }],
  79. specialty: [{ required: true, message: "请输入专业" }],
  80. provinceId: [{ required: true, message: "请选择所在区县" }],
  81. grade: [{ required: true, message: "请输入年级" }],
  82. },
  83. // 省市区相关数据
  84. selAddressCodes: [],
  85. dataList: [],
  86. };
  87. },
  88. onLoad() {
  89. // 获取省市区数据
  90. this.getDistrictData();
  91. },
  92. methods: {
  93. // 获取省市区数据
  94. async getDistrictData() {
  95. try {
  96. const res = await uni.$u.http.get("/token/getAllDistrict");
  97. if (res.code == 200) {
  98. this.dataList = res.data;
  99. }
  100. } catch (error) {
  101. uni.$u.toast("获取地区数据失败");
  102. }
  103. },
  104. // 省市区选择回调
  105. cityChange(e) {
  106. let { value } = e.detail;
  107. if (!value.length) return;
  108. this.form.provinceId = value[0].value;
  109. this.form.cityId = value[1].value;
  110. this.form.districtId = value[2].value || "";
  111. },
  112. // 获取手机号
  113. async getPhoneNumber(e) {
  114. if (e.detail.errMsg !== "getPhoneNumber:ok") {
  115. return uni.$u.toast("获取手机号失败");
  116. }
  117. try {
  118. uni.showLoading({
  119. title: "手机号获取中",
  120. });
  121. // 调用后端接口解密手机号
  122. uni.$u.http
  123. .post("/token/user/wxMobileUpdate", {
  124. code: e.detail.code,
  125. })
  126. .then((res) => {
  127. if (res.code === 200) {
  128. // 更新手机号
  129. this.form.mobile = res.data.mobile;
  130. uni.showToast({
  131. title: "绑定成功",
  132. icon: "success",
  133. });
  134. } else {
  135. uni.$u.toast("手机号获取失败");
  136. }
  137. });
  138. } catch (error) {
  139. uni.$u.toast("手机号获取失败");
  140. } finally {
  141. uni.hideLoading();
  142. }
  143. },
  144. async getCode() {
  145. if (!this.form.mobile) {
  146. uni.$u.toast("请先获取手机号");
  147. return;
  148. }
  149. try {
  150. const res = await uni.$u.http.post("/token/applyPartner/getMobileCode", {
  151. mobile: this.form.mobile,
  152. });
  153. if (res.code === 200) {
  154. this.startCountdown();
  155. uni.$u.toast("验证码已发送");
  156. } else {
  157. uni.$u.toast(res.msg);
  158. }
  159. } catch (error) {
  160. uni.$u.toast("获取验证码失败");
  161. }
  162. },
  163. startCountdown() {
  164. this.counting = true;
  165. this.countdown = 60;
  166. const timer = setInterval(() => {
  167. this.countdown--;
  168. if (this.countdown <= 0) {
  169. clearInterval(timer);
  170. this.counting = false;
  171. }
  172. }, 1000);
  173. },
  174. goToAgreement() {
  175. uni.navigateTo({
  176. url: "/pages-home/pages/user-agreement",
  177. });
  178. },
  179. async submit() {
  180. if (!this.agreement) {
  181. uni.$u.toast("请先阅读并同意用户协议");
  182. return;
  183. }
  184. try {
  185. this.$refs.uForm.validate(async (valid) => {
  186. if (valid) {
  187. const res = await uni.$u.http.post("/token/applyPartner", this.form);
  188. if (res.code === 200) {
  189. uni.navigateTo({
  190. url: "/pages-mine/pages/partner/partner-status?status=pending",
  191. });
  192. } else {
  193. uni.$u.toast(res.msg);
  194. }
  195. }
  196. });
  197. } catch (error) {
  198. uni.$u.toast("提交失败");
  199. }
  200. },
  201. },
  202. };
  203. </script>
  204. <style lang="scss" scoped>
  205. .partner-apply {
  206. min-height: 100vh;
  207. background-color: #f5f5f5;
  208. padding: 20rpx;
  209. padding-bottom: 120rpx;
  210. .form-section {
  211. background-color: #fff;
  212. margin-bottom: 20rpx;
  213. padding: 0 30rpx;
  214. border-radius: 10rpx;
  215. :deep(.u-form-item) {
  216. .u-form-item--left {
  217. white-space: nowrap;
  218. }
  219. .u-button {
  220. margin-left: 20rpx;
  221. }
  222. }
  223. }
  224. .agreement {
  225. margin: 30rpx;
  226. display: flex;
  227. .agreement-link {
  228. color: #38c148;
  229. }
  230. }
  231. .fixed-bottom {
  232. position: fixed;
  233. left: 0;
  234. right: 0;
  235. bottom: 0;
  236. background-color: #fff;
  237. padding: 20rpx 30rpx;
  238. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  239. padding-bottom: 60rpx;
  240. .u-button {
  241. width: 100%;
  242. height: 80rpx;
  243. display: flex;
  244. align-items: center;
  245. justify-content: center;
  246. }
  247. }
  248. }
  249. </style>