register.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <view class="content">
  3. <uni-nav-bar :fixed="true" shadow left-icon="left" title="技师注册" :statusBar="true" @clickLeft="handleToBack" />
  4. <view class="logo_wrap">
  5. <image src="/static/logo.png" class="logo" />
  6. </view>
  7. <view class="form_row">
  8. <view class="form_input_wrap">
  9. <image src="/static/login/phone.png" class="form_input_prefix" mode="aspectFill" />
  10. <input class="form_input" placeholder="请输入手机号" v-model="loginData.mobile" />
  11. </view>
  12. </view>
  13. <view class="form_row">
  14. <view class="form_input_wrap">
  15. <image src="/static/login/verify.png" class="form_input_prefix" mode="aspectFill" />
  16. <input class="form_input" type="number" :maxlength="6" placeholder="请输入验证码" v-model="loginData.code" style="width: 330upx" />
  17. <view
  18. style="width: 160upx; font-size: 28upx; font-weight: 400; color: #07d69e; display: flex; justify-content: flex-end; align-items: center"
  19. @tap="getVerificationCode"
  20. >
  21. {{ countdown > 0 ? countdown : '获取验证码' }}
  22. </view>
  23. </view>
  24. </view>
  25. <view class="form_row">
  26. <view class="form_input_wrap">
  27. <image src="/static/login/password.png" class="form_input_prefix" mode="aspectFill" />
  28. <input class="form_input" placeholder="请输入密码" :password="isPassword" v-model="loginData.password" />
  29. <image src="/static/login/hidden.png" class="form_input_suffix" mode="aspectFill" @click="onChangePassword" v-if="isPassword" />
  30. <image src="/static/login/show.png" class="form_input_suffix" mode="aspectFill" @click="onChangePassword" v-else />
  31. </view>
  32. </view>
  33. <view class="form_row">
  34. <view class="form_input_wrap">
  35. <image src="/static/login/invite.png" class="form_input_prefix" mode="aspectFill" />
  36. <input class="form_input" type="number" :maxlength="10" placeholder="请输入邀请码(可不填)" v-model="loginData.referral" />
  37. </view>
  38. </view>
  39. <view class="form_row">
  40. <view class="form_link" @tap="handleToForgot">忘记密码</view>
  41. <view class="form_link" @tap="handleToLogin">登录</view>
  42. </view>
  43. <view style="height: 100px"></view>
  44. <view class="agreement">
  45. <image src="/static/common/radio_selected.png" class="agreement_radio" @tap="handleAgreement" v-if="isAgreement"></image>
  46. <image src="/static/common/radio_unselect.png" class="agreement_radio" @tap="handleAgreement" v-else></image>
  47. <text @tap="handleAgreement">已阅读并同意</text>
  48. <text class="link_text" @tap="handleToServiceHtml">《用户协议》</text>
  49. <text class="link_text" @tap="handleToPravicyHtml">《隐私政策》</text>
  50. </view>
  51. <button type="primary" class="form_submit_btn" :loading="loading" @click="handleRegister">注册</button>
  52. <uni-popup ref="alertDialog" type="dialog">
  53. <uni-popup-dialog type="info" cancelText="取消" confirmText="已阅读并同意" title="服务协议及隐私保护" @confirm="dialogConfirm" @close="dialogClose">
  54. <view>
  55. 为了保障您的合法权益,请阅读本平台以下协议
  56. <text style="color: #07d69e" @tap="handleToServiceHtml">《用户协议》</text>
  57. <text style="color: #07d69e" @tap="handleToPravicyHtml">《隐私政策》</text>
  58. </view>
  59. </uni-popup-dialog>
  60. </uni-popup>
  61. </view>
  62. </template>
  63. <script setup>
  64. import { ref, reactive } from 'vue';
  65. import { onLoad, onShow } from '@dcloudio/uni-app';
  66. import request from '/common/request.js';
  67. const statusBarHeight = ref();
  68. const countdown = ref(0);
  69. const loading = ref(false);
  70. const loginData = reactive({
  71. mobile: '',
  72. password: '',
  73. code: '',
  74. referral: '',
  75. type: 2 // 客户
  76. });
  77. const isPassword = ref(true);
  78. const isAgreement = ref(false);
  79. const alertDialog = ref();
  80. onLoad((option) => {
  81. loginData.referral = option?.invite || '';
  82. statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight;
  83. const _countdownTime = uni.getStorageSync('countdownVerificationCode');
  84. if (_countdownTime) {
  85. const _countdown = 60 - parseInt((new Date() - _countdownTime) / 1000);
  86. if (_countdown > 0) countdown.value = _countdown;
  87. }
  88. });
  89. onShow((option) => {});
  90. const handleToBack = () => {
  91. const canNavBack = getCurrentPages();
  92. if (canNavBack && canNavBack.length > 1) uni.navigateBack();
  93. else history.back();
  94. };
  95. const showToast = (title) => {
  96. uni.showToast({ title, duration: 2000, icon: 'none' });
  97. };
  98. const verifyFormData = () => {
  99. let message = '';
  100. if (loginData.mobile == '') message = '请填写手机号';
  101. else if (loginData.password == '') message = '请填写密码';
  102. else if (loginData.code == '') message = '请填写验证码';
  103. return message;
  104. };
  105. const onChangePassword = () => {
  106. isPassword.value = !isPassword.value;
  107. };
  108. const handleToLogin = () => {
  109. uni.redirectTo({
  110. url: '/pages/account/login'
  111. });
  112. };
  113. const handleToForgot = () => {
  114. uni.redirectTo({
  115. url: '/pages/account/forgot'
  116. });
  117. };
  118. //跳转到用户协议
  119. const handleToServiceHtml = () => {
  120. uni.navigateTo({
  121. url: '/pages/account/help?id=24'
  122. });
  123. };
  124. //跳转到隐私政策
  125. const handleToPravicyHtml = () => {
  126. uni.navigateTo({
  127. url: '/pages/account/help?id=23'
  128. });
  129. };
  130. const handleAgreement = () => {
  131. isAgreement.value = !isAgreement.value;
  132. };
  133. const dialogConfirm = () => {
  134. isAgreement.value = true;
  135. handleRegister();
  136. };
  137. const dialogClose = () => {};
  138. const dialogToggle = () => {
  139. alertDialog.value.open();
  140. };
  141. const handleRegister = async () => {
  142. let message = verifyFormData();
  143. if (message) {
  144. showToast(message);
  145. return;
  146. }
  147. if (!isAgreement.value) {
  148. dialogToggle();
  149. return;
  150. }
  151. uni.showLoading();
  152. request({
  153. url: '/api/regPost',
  154. method: 'POST',
  155. data: { ...loginData },
  156. success: async (res) => {
  157. console.log('用户注册', res);
  158. uni.hideLoading();
  159. showToast(res.data?.msg || '注册成功');
  160. if (res.data.code == 1) {
  161. uni.setStorageSync('token', res.data?.data?.token);
  162. uni.setStorageSync('id', res.data?.data?.id);
  163. setTimeout(function () {
  164. uni.switchTab({
  165. url: '/pages/index/index'
  166. });
  167. }, 2000);
  168. }
  169. },
  170. fail: () => {},
  171. complete: () => {}
  172. });
  173. };
  174. const getVerificationCode = () => {
  175. if (countdown.value) return;
  176. if (!loginData.mobile) {
  177. uni.showToast({
  178. title: '请输入手机号',
  179. duration: 2000,
  180. icon: 'none'
  181. });
  182. return;
  183. }
  184. countdown.value = 60;
  185. uni.setStorageSync({
  186. key: 'countdownVerificationCode',
  187. data: new Date()
  188. });
  189. let countdownTimer = setInterval(function () {
  190. if (countdown.value > 0) countdown.value -= 1;
  191. else {
  192. countdown.value = 0;
  193. uni.removeStorageSync('countdownVerificationCode');
  194. clearInterval(countdownTimer);
  195. }
  196. }, 1000);
  197. uni.showLoading({
  198. content: '加载中',
  199. mask: true
  200. });
  201. request({
  202. url: '/api/getVerificationCode',
  203. method: 'POST',
  204. data: {
  205. mobile: loginData.mobile,
  206. status: 2,
  207. type: 1
  208. },
  209. success: (res) => {
  210. uni.hideLoading();
  211. console.log('获取验证码', res);
  212. const message = res.data?.msg || '验证码已发送';
  213. uni.showToast({
  214. title: message,
  215. duration: 2000,
  216. icon: 'none'
  217. });
  218. },
  219. fail: () => {
  220. countdown.value = 0;
  221. uni.removeStorageSync('countdownVerificationCode');
  222. clearInterval(countdownTimer);
  223. uni.hideLoading();
  224. },
  225. complete: () => {}
  226. });
  227. };
  228. const handleWechartLogin = () => {
  229. uni.login({
  230. provider: 'weixin',
  231. success: function (loginRes) {
  232. console.log(loginRes.code);
  233. // 获取用户信息
  234. uni.getUserInfo({
  235. provider: 'weixin',
  236. success: function (infoRes) {
  237. console.log('用户昵称为:' + infoRes.userInfo.nickName);
  238. /* uni.showToast({
  239. title:JSON.stringify(infoRes),
  240. duration: 5000,
  241. icon: 'none'
  242. });*/
  243. uni.showLoading({
  244. content: '加载中',
  245. mask: true
  246. });
  247. request({
  248. url: '/api/wxlogin/wxLogin',
  249. method: 'POST',
  250. data: {
  251. openid: infoRes.userInfo.openId,
  252. avatar: infoRes.userInfo.avatarUrl,
  253. type: 2,
  254. nickname: infoRes.userInfo.nickName
  255. },
  256. success: (res) => {
  257. console.log(res);
  258. if (res.data.code == 1) {
  259. if (res.data.data.token) {
  260. uni.setStorage({
  261. key: 'token',
  262. data: res.data.data.token,
  263. success: function () {}
  264. });
  265. uni.setStorage({
  266. key: 'id',
  267. data: res.data.data.id,
  268. success: function () {}
  269. });
  270. uni.$emit('sxdd', {
  271. msg: '页面更新'
  272. });
  273. // uni.navigateBack();
  274. setTimeout(function () {
  275. uni.switchTab({
  276. url: '/pages/index/index'
  277. });
  278. }, 1000);
  279. } else {
  280. uni.navigateTo({
  281. url: '/pages/bangding/bangding?id=' + res.data.data.id
  282. });
  283. }
  284. } else {
  285. uni.showToast({
  286. title: res.data.msg,
  287. duration: 2000,
  288. icon: 'none'
  289. });
  290. }
  291. },
  292. fail: () => {},
  293. complete: () => {
  294. setTimeout(function () {
  295. uni.hideLoading();
  296. }, 2000);
  297. }
  298. });
  299. }
  300. });
  301. }
  302. });
  303. };
  304. </script>
  305. <style lang="scss" scoped>
  306. .content {
  307. width: 750upx;
  308. margin: 0 auto;
  309. background: #f9f9f9;
  310. position: relative;
  311. .logo_wrap {
  312. padding: 69upx 0;
  313. .logo {
  314. width: 160upx;
  315. height: 160upx;
  316. display: block;
  317. margin: 0 auto;
  318. border-radius: 40upx;
  319. }
  320. }
  321. .form_row {
  322. display: flex;
  323. justify-content: space-between;
  324. padding: 0 60upx;
  325. .form_input_wrap {
  326. width: 630upx;
  327. height: 80upx;
  328. background: #ffffff;
  329. border: 1upx solid #07d69e;
  330. border-radius: 40upx;
  331. margin: 0 auto 30upx;
  332. display: flex;
  333. padding: 18upx 35upx 22upx;
  334. .form_input_prefix {
  335. width: 40upx;
  336. height: 40upx;
  337. }
  338. .form_input {
  339. width: 430upx;
  340. height: 42upx;
  341. font-size: 28upx;
  342. font-weight: 400;
  343. color: #999999;
  344. line-height: 40upx;
  345. margin: 0 20upx;
  346. }
  347. .form_input_suffix {
  348. width: 40upx;
  349. height: 40upx;
  350. }
  351. }
  352. .form_link {
  353. font-size: 26upx;
  354. font-weight: 400;
  355. color: #07d69e;
  356. margin: 0 22upx;
  357. }
  358. }
  359. .form_submit_btn {
  360. width: 630upx;
  361. height: 80upx;
  362. background: linear-gradient(90deg, #37ecba 0%, #72afd3 100%);
  363. border-radius: 40upx;
  364. margin: 10upx auto;
  365. font-size: 32upx;
  366. font-weight: bold;
  367. color: #ffffff;
  368. }
  369. .agreement {
  370. font-size: 24upx;
  371. color: #666;
  372. display: flex;
  373. align-items: center;
  374. justify-content: center;
  375. margin: 62upx 0;
  376. .agreement_radio {
  377. width: 28upx;
  378. height: 28upx;
  379. margin: 0 10upx;
  380. }
  381. .link_text {
  382. color: #07d69e;
  383. }
  384. }
  385. }
  386. :deep(.uni-modal) {
  387. .uni-modal__bd {
  388. padding: 30upx;
  389. }
  390. .uni-modal__ft {
  391. .uni-modal__btn_primary {
  392. color: #07d69e !important;
  393. }
  394. .uni-modal__btn_default {
  395. color: #999 !important;
  396. }
  397. }
  398. }
  399. </style>