partner-apply.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. mobile: [{ required: true, message: "请输入手机号" }],
  79. verifyCode: [{ required: true, message: "请输入验证码" }],
  80. name: [{ required: true, message: "请输入真实姓名" }],
  81. school: [{ required: true, message: "请输入学校" }],
  82. faculties: [{ required: true, message: "请输入院系" }],
  83. specialty: [{ required: true, message: "请输入专业" }],
  84. provinceId: [{ required: true, message: "请选择所在区县" }],
  85. grade: [{ required: true, message: "请输入年级" }],
  86. },
  87. // 省市区相关数据
  88. selAddressCodes: [],
  89. dataList: [],
  90. };
  91. },
  92. onLoad() {
  93. // 获取省市区数据
  94. this.getDistrictData();
  95. },
  96. // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  97. onReady() {
  98. this.$refs.uForm?.setRules(this.rules);
  99. },
  100. methods: {
  101. // 获取省市区数据
  102. async getDistrictData() {
  103. try {
  104. const res = await uni.$u.http.get("/token/getAllDistrict");
  105. if (res.code == 200) {
  106. this.dataList = res.data;
  107. }
  108. } catch (error) {
  109. uni.$u.toast("获取地区数据失败");
  110. }
  111. },
  112. // 省市区选择回调
  113. cityChange(e) {
  114. let { value } = e.detail;
  115. if (!value.length) return;
  116. this.form.provinceId = value[0].value;
  117. this.form.cityId = value[1].value;
  118. this.form.districtId = value[2].value || "";
  119. },
  120. //支付宝获取手机号
  121. onGetAuthorize(e) {
  122. my.getPhoneNumber({
  123. success: (res) => {
  124. this.getPhoneNumberApi(res.response, 'alipay')
  125. },
  126. fail: (err) => {
  127. console.log('获取手机号失败', err);
  128. }
  129. })
  130. },
  131. handleAuthError(e) {
  132. console.log(e, 'handleAuthError')
  133. },
  134. // 获取手机号
  135. async getPhoneNumber(e) {
  136. if (e.detail.errMsg !== "getPhoneNumber:ok") {
  137. return uni.$u.toast("获取手机号失败");
  138. }
  139. try {
  140. uni.showLoading({
  141. title: "手机号获取中",
  142. });
  143. // 调用后端接口解密手机号
  144. this.getPhoneNumberApi(e.detail.code)
  145. } catch (error) {
  146. uni.$u.toast("手机号获取失败");
  147. } finally {
  148. uni.hideLoading();
  149. }
  150. },
  151. // 获取手机号
  152. getPhoneNumberApi(code, type = 'wechat') {
  153. let params = type === 'wechat' ? { code } : code
  154. // 调用后端接口解密手机号
  155. uni.$u.http.post('/token/user/wxMobileUpdate', params).then(res => {
  156. if (res.code === 200) {
  157. this.form.mobile = res.data.mobile;
  158. uni.showToast({
  159. title: "手机号绑定成功",
  160. icon: "success",
  161. });
  162. } else {
  163. uni.$u.toast(res.msg);
  164. }
  165. })
  166. },
  167. async getCode() {
  168. if (!this.form.mobile) {
  169. uni.$u.toast("请先获取手机号");
  170. return;
  171. }
  172. try {
  173. const res = await uni.$u.http.post("/token/applyPartner/getMobileCode", {
  174. mobile: this.form.mobile,
  175. });
  176. if (res.code === 200) {
  177. this.startCountdown();
  178. uni.$u.toast("验证码已发送");
  179. } else {
  180. uni.$u.toast(res.msg);
  181. }
  182. } catch (error) {
  183. uni.$u.toast("获取验证码失败");
  184. }
  185. },
  186. startCountdown() {
  187. this.counting = true;
  188. this.countdown = 60;
  189. const timer = setInterval(() => {
  190. this.countdown--;
  191. if (this.countdown <= 0) {
  192. clearInterval(timer);
  193. this.counting = false;
  194. }
  195. }, 1000);
  196. },
  197. goToAgreement() {
  198. uni.navigateTo({
  199. url: "/pages-home/pages/user-agreement",
  200. });
  201. },
  202. async submit() {
  203. if (!this.agreement) {
  204. uni.$u.toast("请先阅读并同意用户协议");
  205. return;
  206. }
  207. try {
  208. this.$refs.uForm.validate(async (valid) => {
  209. if (valid) {
  210. const res = await uni.$u.http.post("/token/applyPartner", this.form);
  211. if (res.code === 200) {
  212. uni.navigateTo({
  213. url: "/pages-mine/pages/partner/partner-status?status=pending",
  214. });
  215. } else {
  216. uni.$u.toast(res.msg);
  217. }
  218. }
  219. });
  220. } catch (error) {
  221. uni.$u.toast("提交失败");
  222. }
  223. },
  224. },
  225. };
  226. </script>
  227. <style lang="scss" scoped>
  228. .partner-apply {
  229. min-height: 100vh;
  230. background-color: #f5f5f5;
  231. padding: 20rpx;
  232. padding-bottom: 120rpx;
  233. .form-section {
  234. background-color: #fff;
  235. margin-bottom: 20rpx;
  236. padding: 0 30rpx;
  237. border-radius: 10rpx;
  238. :deep(.u-form-item) {
  239. .u-form-item--left {
  240. white-space: nowrap;
  241. }
  242. .u-button {
  243. margin-left: 20rpx;
  244. }
  245. }
  246. }
  247. .agreement {
  248. margin: 30rpx;
  249. display: flex;
  250. .agreement-link {
  251. color: #38c148;
  252. }
  253. }
  254. .phone-btn {
  255. color: #19be6b;
  256. border: 1px solid #71d5a1;
  257. background-color: #dbf1e1;
  258. font-size: 12px;
  259. padding: 0 20rpx;
  260. height: 52rpx;
  261. line-height: 52rpx;
  262. border-radius: 2rpx;
  263. &::after{
  264. border: none;
  265. }
  266. }
  267. .fixed-bottom {
  268. position: fixed;
  269. left: 0;
  270. right: 0;
  271. bottom: 0;
  272. background-color: #fff;
  273. padding: 20rpx 30rpx;
  274. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  275. padding-bottom: 60rpx;
  276. .u-button {
  277. width: 100%;
  278. height: 80rpx;
  279. display: flex;
  280. align-items: center;
  281. justify-content: center;
  282. }
  283. }
  284. }
  285. </style>