index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <!-- 短信登录 - smsLogin -->
  2. <template>
  3. <view class="register-container">
  4. <!-- 标题栏 -->
  5. <view class="head-box ss-m-b-60">
  6. <view class="ss-flex ss-m-b-20">
  7. <view class="head-title head-title-line head-title-animation">短信登录</view>
  8. </view>
  9. <view class="head-subtitle">未注册的手机号,验证后自动注册账号</view>
  10. </view>
  11. <!-- 表单项 -->
  12. <uni-forms ref="smsLoginRef" v-model="state.model" :rules="state.rules" validateTrigger="bind" labelWidth="140"
  13. labelAlign="center" class="form-box">
  14. <uni-forms-item name="mobile" label="手机号">
  15. <uni-easyinput placeholder="请输入手机号" v-model="state.model.mobile" :inputBorder="false" type="number">
  16. <template v-slot:right>
  17. <button class="ss-reset-button code-btn" :disabled="state.isMobileEnd"
  18. :class="{ 'code-btn-disabled': state.isMobileEnd }" @tap="getSmsCode('smsLogin', state.model.mobile)">
  19. {{ getSmsTimer('smsLogin') }}
  20. </button>
  21. </template>
  22. </uni-easyinput>
  23. </uni-forms-item>
  24. <uni-forms-item name="code" label="验证码">
  25. <uni-easyinput placeholder="请输入验证码" v-model="state.model.code" :inputBorder="false" type="number" maxlength="4">
  26. <template v-slot:right>
  27. <button class="ss-reset-button login-btn" @tap="smsLoginSubmit">注册</button>
  28. </template>
  29. </uni-easyinput>
  30. </uni-forms-item>
  31. </uni-forms>
  32. <!-- 用户协议的勾选 -->
  33. <view class="agreement-box ss-flex ss-row-center" :class="{ shake: currentProtocol }">
  34. <label class="radio ss-flex ss-col-center" @tap="onChange">
  35. <radio :checked="state.protocol" color="#d10019" style="transform: scale(0.8)" @tap.stop="onChange" />
  36. <view class="agreement-text ss-flex ss-col-center ss-m-l-8">
  37. 我已阅读并遵守
  38. <view class="tcp-text" @tap.stop="onProtocol('用户协议')"> 《用户协议》 </view>
  39. <view class="agreement-text">与</view>
  40. <view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> 《隐私协议》 </view>
  41. </view>
  42. </label>
  43. </view>
  44. </view>
  45. </template>
  46. <script setup>
  47. import { ref, reactive, unref } from 'vue';
  48. import sheep from '@/sheep';
  49. import { code, mobile } from '@/sheep/validate/form';
  50. import { showAuthModal, closeAuthModal, getSmsCode, getSmsTimer } from '@/sheep/hooks/useModal';
  51. import AuthUtil from '@/sheep/api/member/auth';
  52. const smsLoginRef = ref(null);
  53. const currentProtocol = ref(false);
  54. const emits = defineEmits(['onConfirm']);
  55. const props = defineProps({
  56. agreeStatus: {
  57. type: Boolean,
  58. default: false,
  59. },
  60. });
  61. // 数据
  62. const state = reactive({
  63. isMobileEnd: false, // 手机号输入完毕
  64. codeText: '获取验证码',
  65. protocol: false, // 协议勾选状态
  66. model: {
  67. mobile: '', // 手机号
  68. code: '', // 验证码
  69. userNo: "1024",
  70. },
  71. rules: {
  72. code,
  73. mobile,
  74. },
  75. });
  76. // 勾选协议
  77. function onChange() {
  78. state.protocol = !state.protocol;
  79. }
  80. // 查看协议
  81. function onProtocol(title) {
  82. sheep.$router.go('/pages/public/richtext', {
  83. title,
  84. });
  85. }
  86. // 短信登录
  87. async function smsLoginSubmit() {
  88. // 参数校验
  89. const validate = await unref(smsLoginRef)
  90. .validate()
  91. .catch((error) => {
  92. console.log('error: ', error);
  93. });
  94. if (!validate) {
  95. return;
  96. }
  97. if (!state.protocol) {
  98. currentProtocol.value = true;
  99. setTimeout(() => {
  100. currentProtocol.value = false;
  101. }, 1000);
  102. sheep.$helper.toast('请勾选同意');
  103. return;
  104. }
  105. // 提交数据
  106. const { code } = await AuthUtil.register(state.model);
  107. if (code === 0) {
  108. sheep.$router.go('/pages/index/index')
  109. closeAuthModal();
  110. }
  111. }
  112. </script>
  113. <style lang="scss" scoped>
  114. .register-container {
  115. padding: 40rpx;
  116. min-height: 100vh;
  117. background: #f8f8f8;
  118. }
  119. .head-box {
  120. margin-top: 60rpx;
  121. .head-title {
  122. font-size: 48rpx;
  123. font-weight: bold;
  124. color: #333;
  125. margin-bottom: 20rpx;
  126. position: relative;
  127. &::after {
  128. content: '';
  129. position: absolute;
  130. left: 0;
  131. bottom: -10rpx;
  132. width: 60rpx;
  133. height: 6rpx;
  134. background: #d10019;
  135. border-radius: 3rpx;
  136. }
  137. }
  138. .head-subtitle {
  139. font-size: 28rpx;
  140. color: #999;
  141. margin-top: 30rpx;
  142. }
  143. }
  144. .form-box {
  145. margin-top: 80rpx;
  146. padding: 40rpx;
  147. background: #fff;
  148. border-radius: 20rpx;
  149. box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.05);
  150. :deep(.uni-forms-item) {
  151. margin-bottom: 40rpx;
  152. }
  153. :deep(.uni-forms-item__label) {
  154. font-size: 28rpx;
  155. color: #666;
  156. }
  157. :deep(.uni-easyinput__content) {
  158. background: #f8f8f8;
  159. border-radius: 10rpx;
  160. padding: 10rpx 20rpx;
  161. }
  162. }
  163. .code-btn {
  164. width: 180rpx;
  165. height: 70rpx;
  166. line-height: 70rpx;
  167. border: 1rpx solid #d10019;
  168. color: #d10019;
  169. border-radius: 35rpx;
  170. font-size: 26rpx;
  171. text-align: center;
  172. &.code-btn-disabled {
  173. background: #ccc;
  174. }
  175. }
  176. .login-btn {
  177. width: 180rpx;
  178. height: 70rpx;
  179. line-height: 70rpx;
  180. background: linear-gradient(90deg, #d10019, rgba(209, 0, 25, 0.6));
  181. border-radius: 35rpx;
  182. font-size: 28rpx;
  183. color: #fff;
  184. text-align: center;
  185. box-shadow: 0 10rpx 20rpx rgba(209, 0, 25, 0.2);
  186. }
  187. .shake {
  188. animation: shake 0.05s linear 4 alternate;
  189. }
  190. @keyframes shake {
  191. from {
  192. transform: translateX(-10rpx);
  193. }
  194. to {
  195. transform: translateX(10rpx);
  196. }
  197. }
  198. .agreement-box {
  199. margin-top: 40rpx;
  200. }
  201. .tcp-text {
  202. color: #d10019;
  203. }
  204. .agreement-text {
  205. color: #999;
  206. }
  207. </style>