partner-apply.vue 10.0 KB

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