Parcourir la source

发送验证码

Xiao_123 il y a 8 mois
Parent
commit
397663407c
13 fichiers modifiés avec 1792 ajouts et 188 suppressions
  1. 7 8
      api/auth.js
  2. 3 2
      api/user.js
  3. 0 134
      components/AuthModal/index.vue
  4. 9 1
      main.js
  5. 1461 18
      package-lock.json
  6. 2 1
      package.json
  7. 105 4
      pages/login/index.vue
  8. 45 0
      static/style/index.css
  9. 0 0
      static/style/index.min.css
  10. 49 0
      static/style/index.scss
  11. 0 20
      store/index.js
  12. 23 0
      store/modal.js
  13. 88 0
      utils/code.js

+ 7 - 8
api/auth.js

@@ -1,9 +1,10 @@
 import request from "@/utils/request"
 
 // 刷新令牌
-export const refreshToken = async (refreshToken) => {
-  return await request.post({
+export const refreshToken = (refreshToken) => {
+  return request({
     url: '/menduner/system/auth/refresh-token',
+    method: "POST",
     params: {
       refreshToken
     },
@@ -15,13 +16,11 @@ export const refreshToken = async (refreshToken) => {
 }
 
 // 发送手机验证码
-export const sendSmsCode = async (mobile, scene) => {
-  return await request.post({
+export const sendSmsCode = (data) => {
+  return request({
     url: '/menduner/system/auth/send-sms-code',
-    data: {
-      phone: mobile,
-      scene
-    },
+    method: "POST",
+    data,
     custom: {
       loadingMsg: '发送中',
       showSuccess: true,

+ 3 - 2
api/user.js

@@ -1,9 +1,10 @@
 import request from "@/utils/request"
 
 // 获取用户基本信息
-export const getUserInfo = async (params) => {
-  return await request.get({
+export const getUserInfo = (params) => {
+  return request({
     url: '/menduner/system/person/get',
+    method: 'GET',
     params,
     custom: {
       showLoading: false,

+ 0 - 134
components/AuthModal/index.vue

@@ -1,134 +0,0 @@
-<template>
-  <view>
-    <uni-popup ref="popup" background-color="#fff" type="bottom">
-      <view class="head-box ss-p-30">
-        <view class="ss-flex ss-m-b-20">
-          <view class="head-title head-title-line head-title-animation" :class="{ 'head-title-active': type === 'account' }" @tap="type = 'code'">短信登录</view>
-          <view class="head-title  ss-m-r-40" :class="{ 'head-title-active': type === 'code' }" @tap="type = 'account'">账号登录</view>
-        </view>
-        <view v-if="type === 'code'" class="head-subtitle">未注册的手机号,验证后自动注册账号</view>
-      </view>
-
-      <view class="ss-p-30 ss-m-b-60">
-        <!-- 短信验证码登录 -->
-        <uni-forms
-          v-if="type === 'code'"
-          ref="smsLoginRef"
-          v-model="state.sms"
-          :rules="state.smsRules"
-          validateTrigger="bind"
-          labelWidth="140"
-          labelAlign="center"
-        >
-          <uni-forms-item name="phone" label="手机号">
-            <uni-easyinput
-              placeholder="请输入手机号"
-              v-model="state.sms.phone"
-              :inputBorder="false"
-              type="number"
-            >
-              <template v-slot:right>
-                <button
-                  class="ss-reset-button code-btn code-btn-start"
-                  :disabled="state.isMobileEnd"
-                  :class="{ 'code-btn-end': state.isMobileEnd }"
-                  @tap="handleSendCode"
-                >
-                  <!-- {{ getSmsTimer('smsLogin') }} -->
-                </button>
-              </template>
-            </uni-easyinput>
-          </uni-forms-item>
-
-          <uni-forms-item name="code" label="验证码">
-            <uni-easyinput
-              placeholder="请输入验证码"
-              v-model="state.sms.code"
-              :inputBorder="false"
-              type="number"
-              maxlength="6"
-            >
-              <template v-slot:right>
-                <button class="ss-reset-button login-btn-start" @tap="smsLoginSubmit"> 登录 </button>
-              </template>
-            </uni-easyinput>
-          </uni-forms-item>
-        </uni-forms>
-        <!-- 账号密码登录 -->
-        <uni-forms
-          v-if="type === 'account'"
-          ref="accountLoginRef"
-          v-model="state.account"
-          :rules="state.rules"
-          validateTrigger="bind"
-          labelWidth="140"
-          labelAlign="center"
-        >
-          <uni-forms-item name="phone" label="账号">
-            <uni-easyinput placeholder="请输入账号" v-model="state.account.phone" :inputBorder="false"></uni-easyinput>
-          </uni-forms-item>
-
-          <uni-forms-item name="password" label="密码">
-            <uni-easyinput
-              type="password"
-              placeholder="请输入密码"
-              v-model="state.account.password"
-              :inputBorder="false"
-            >
-              <template v-slot:right>
-                <button class="ss-reset-button login-btn-start" @tap="accountLoginSubmit">登录</button>
-              </template>
-            </uni-easyinput>
-          </uni-forms-item>
-        </uni-forms>
-      </view>
-		</uni-popup>
-  </view>
-</template>
-
-<script setup>
-import { ref } from 'vue'
-import { mobile, password, code } from '@/utils/validate'
-// import { getSmsTimer } from '@/hooks/useModal'
-
-const popup = ref()
-const type = ref('code')
-const accountLoginRef = ref()
-const smsLoginRef = ref()
-const state = ref({
-  isMobileEnd: false, // 手机号输入完毕
-  codeText: '获取验证码',
-  sms: {
-    phone: '13229740092',
-    code: ''
-  },
-  account: {
-    phone: '13229740091',
-    password: 'Citu123'
-  },
-  rules: {
-    phone: mobile,
-    password,
-  },
-  smsRules: {
-    code,
-    phone: mobile
-  }
-})
-
-const open = () => {
-  popup.value.open()
-}
-
-const accountLoginSubmit = () => {}
-const smsLoginSubmit = () => {}
-
-defineExpose({
-  open,
-  popup
-})
-</script>
-
-<style scoped lang="scss">
-
-</style>

+ 9 - 1
main.js

@@ -8,7 +8,7 @@ Vue.config.productionTip = false
 App.mpType = 'app'
 
 const app = new Vue({
-    ...App
+  ...App
 })
 app.$mount()
 // #endif
@@ -16,8 +16,16 @@ app.$mount()
 // #ifdef VUE3
 import { createSSRApp } from 'vue'
 import App from './App.vue'
+import { createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
+const pinia = createPinia()
+pinia.use(piniaPluginPersistedstate)
+
 export function createApp() {
   const app = createSSRApp(App)
+
+  app.use(pinia)
+
   return {
     app
   }

Fichier diff supprimé car celui-ci est trop grand
+ 1461 - 18
package-lock.json


+ 2 - 1
package.json

@@ -4,6 +4,7 @@
     "lodash-es": "^4.17.21",
     "luch-request": "^3.1.1",
     "pinia": "^2.2.2",
-    "pinia-plugin-persist-uni": "^1.3.1"
+    "pinia-plugin-persist-uni": "^1.3.1",
+    "pinia-plugin-persistedstate": "^4.0.1"
   }
 }

+ 105 - 4
pages/login/index.vue

@@ -1,18 +1,119 @@
 <template>
-  <view>
+  <view class="ss-p-30 head-box">
     <view>欢迎来到门墩儿招聘</view>
-    <uni-segmented-control :current="current" :values="items" style-type="button" active-color="#00897B" @clickItem="onClickItem" />
+    <uni-segmented-control class="ss-m-t-60" :current="current" :values="items" style-type="text" active-color="#00897B" @clickItem="onClickItem" />
+    <view class="head-subtitle ss-m-t-10">未注册的手机号,验证后自动注册账号</view>
+
+    <view class="ss-m-t-30">
+      <!-- 短信验证码登录 -->
+      <uni-forms
+        v-if="current === 0"
+        ref="smsLoginRef"
+        v-model="state.sms"
+        :rules="state.smsRules"
+        validateTrigger="bind"
+        labelWidth="140"
+        labelAlign="center"
+      >
+        <uni-forms-item name="phone" label="手机号">
+          <uni-easyinput placeholder="请输入手机号" v-model="state.sms.phone" :inputBorder="false" type="number">
+            <template v-slot:right>
+              <button class="login-code" :disabled="state.isMobileEnd" :class="{ 'code-btn-end': state.isMobileEnd }" @tap="handleCode">
+                {{ getSmsTimer('smsLogin') }}
+              </button>
+            </template>
+          </uni-easyinput>
+        </uni-forms-item>
+
+        <uni-forms-item name="code" label="验证码">
+          <uni-easyinput placeholder="请输入验证码" v-model="state.sms.code" :inputBorder="false" type="number" maxlength="6"></uni-easyinput>
+        </uni-forms-item>
+      </uni-forms>
+
+      <!-- 账号密码登录 -->
+      <uni-forms
+        v-else
+        ref="accountLoginRef"
+        v-model="state.account"
+        :rules="state.rules"
+        validateTrigger="bind"
+        labelWidth="140"
+        labelAlign="center"
+      >
+        <uni-forms-item name="phone" label="账号">
+          <uni-easyinput placeholder="请输入账号" v-model="state.account.phone" :inputBorder="false"></uni-easyinput>
+        </uni-forms-item>
+
+        <uni-forms-item name="password" label="密码">
+          <uni-easyinput type="password" placeholder="请输入密码" v-model="state.account.password" :inputBorder="false"></uni-easyinput>
+        </uni-forms-item>
+      </uni-forms>
+
+      <button class="send-button" @tap="smsLoginSubmit"> 登录/注册 </button>
+    </view>
   </view>
 </template>
 
 <script setup>
 import { ref } from 'vue'
+import { mobile, password, code } from '@/utils/validate'
+import { getSmsCode, getSmsTimer } from '@/utils/code'
+
 const items = ['短信登录', '账号登录']
 const current = ref(0)
+const accountLoginRef = ref()
+const smsLoginRef = ref()
+const state = ref({
+  isMobileEnd: false, // 手机号输入完毕
+  codeText: '获取验证码',
+  sms: {
+    phone: '13229740092',
+    code: ''
+  },
+  account: {
+    phone: '13229740091',
+    password: 'Citu123'
+  },
+  rules: {
+    phone: mobile,
+    password,
+  },
+  smsRules: {
+    code,
+    phone: mobile
+  }
+})
+
+const onClickItem = (e) => {
+  current.value = e.currentIndex
+}
 
-const onClickItem = (e) => {}
+// 获取验证码
+const handleCode = () => {
+  if (!state.value.sms.phone) {
+    uni.showToast({
+      title: '请输入手机号',
+      icon: 'none',
+      duration: 2000
+    })
+    return
+  }
+  getSmsCode('smsLogin', state.value.sms.phone)
+}
+
+const smsLoginSubmit = () => {}
 </script>
 
 <style scoped lang="scss">
-
+.login-code {
+  width: 73px;
+  min-width: 73px;
+  color: var(--v-primary-base);
+  text-align: center; 
+  font-size: 12px; 
+  cursor: pointer;
+  border: 1px dashed var(--v-primary-base);
+  border-radius: 26px;
+  padding: 0;
+}
 </style>

+ 45 - 0
static/style/index.css

@@ -8965,3 +8965,48 @@
   font-weight: 500;
   color: #fff;
 }
+
+.recomm-button {
+  width: 85%;
+  height: 44px;
+  line-height: 44px;
+  margin: 20px auto;
+  background-color: #00897B !important;
+}
+
+.second-button {
+  width: 50vw;
+  height: 44px;
+  margin: 15px;
+  background-color: #00897B !important;
+}
+
+.second-button:first-child {
+  margin: 15px 0 15px 15px;
+}
+
+.bottom-sticky {
+  display: flex;
+  width: 100vw;
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  background-image: linear-gradient(rgba(255, 255, 255, 0.8), white);
+}
+
+.send-button {
+  width: 90vw;
+  height: 44px;
+  line-height: 44px;
+  margin: 20px auto;
+  background-color: #00897B !important;
+  color: #fff;
+}
+
+.disabled-button {
+  width: 85%;
+  height: 44px;
+  line-height: 44px;
+  margin: 20px auto;
+  background-color: grey !important;
+}

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
static/style/index.min.css


+ 49 - 0
static/style/index.scss

@@ -347,4 +347,53 @@
   font-size: 26rpx;
   font-weight: 500;
   color: #fff;
+}
+
+//页面底部单个按钮
+.recomm-button {
+  width: 85%;
+  height: 44px;
+  line-height: 44px;
+  margin: 20px auto;
+  background-color: #00897B !important;
+  // border-radius: 25px;
+}
+//页面底部两个按钮
+.second-button {
+  width: 50vw;
+  height: 44px;
+  margin: 15px;
+  background-color: #00897B !important;
+  // border-radius: 25px;
+}
+.second-button:first-child {
+	margin: 15px 0 15px 15px;
+}
+//底部按钮公用定位
+.bottom-sticky{
+  display: flex;
+  width:100vw;
+  position: fixed;
+  bottom:0;
+  left: 0;
+  background-image:linear-gradient(rgba(255,255,255,0.8),white);
+}
+// 主要页面大按钮用这个
+.send-button {
+	width: 90vw;
+	height:44px;
+	line-height: 44px;
+	margin:20px auto;
+	background-color: #00897B !important;
+	// border-radius: 25px;
+	color: #fff;
+}
+//禁用按钮
+.disabled-button {
+	width: 85%;
+  height: 44px;
+  line-height: 44px;
+  margin: 20px auto;
+  background-color: grey !important;
+  // border-radius: 25px;
 }

+ 0 - 20
store/index.js

@@ -1,20 +0,0 @@
-import { createPinia } from 'pinia';
-import piniaPersist from 'pinia-plugin-persist-uni';
-
-// 自动注入所有pinia模块
-const files = import.meta.glob('./*.js', { eager: true });
-const modules = {};
-Object.keys(files).forEach((key) => {
-  modules[key.replace(/(.*\/)*([^.]+).*/gi, '$2')] = files[key].default;
-});
-
-export const setupPinia = (app) => {
-  const pinia = createPinia();
-  pinia.use(piniaPersist);
-
-  app.use(pinia);
-};
-
-export default (name) => {
-  return modules[name]();
-};

+ 23 - 0
store/modal.js

@@ -0,0 +1,23 @@
+import { defineStore } from 'pinia';
+
+export const modalStore = defineStore({
+  id: 'modal',
+  state: () => ({
+    lastTimer: {
+      // 短信验证码计时器,为了防止刷新请求做了持久化
+      smsLogin: 0,
+      changeMobile: 0,
+      resetPassword: 0,
+      changePassword: 0,
+    }
+  }),
+  persist: {
+    enabled: true,
+    strategies: [
+      {
+        key: 'modal-store',
+        paths: ['lastTimer', 'advHistory'],
+      },
+    ],
+  },
+});

+ 88 - 0
utils/code.js

@@ -0,0 +1,88 @@
+import { ref } from 'vue'
+import { sendSmsCode } from '@/api/auth'
+import { modalStore } from '@/store/modal'
+import dayjs from 'dayjs';
+import test from '@/utils/test'
+
+const modal = modalStore()
+// 发送验证码
+export const getSmsCode = (event, mobile) => {
+  const lastSendTimer = modal.lastTimer[event];
+  if (typeof lastSendTimer === 'undefined') {
+    uni.showToast({
+      title: '短信发送事件错误'
+    })
+    return;
+  }
+
+  const duration = dayjs().unix() - lastSendTimer;
+  const canSend = duration >= 60;
+  if (!canSend) {
+    uni.showToast({
+      title: '请稍后再试'
+    })
+    return;
+  }
+  // 只有 mobile 非空时才校验。因为部分场景(修改密码),不需要输入手机
+  if (mobile && !test.mobile(mobile)) {
+    uni.showToast({
+      title: '手机号码格式不正确'
+    })
+    return;
+  }
+
+  // 发送验证码 + 更新上次发送验证码时间
+  let scene = -1;
+  switch (event) {
+    case 'resetPassword':
+      scene = 4;
+      break;
+    case 'changePassword':
+      scene = 3;
+      break;
+    case 'changeMobile':
+      scene = 2;
+      break;
+    case 'smsLogin':
+      scene = 30; // 对接门墩短信登录
+      break;
+  }
+  sendSmsCode({ phone: mobile, scene }).then((res) => {
+    if (res.code === 0) {
+      uni.showToast({
+        title: '发送成功,请注意查收',
+        icon: 'success',
+        duration: 2000
+      })
+      modal.$patch((state) => {
+        state.lastTimer[event] = dayjs().unix();
+      })
+    }
+  })
+}
+
+// 验证码倒计时
+export const getSmsTimer = (event) => {
+  const lastSendTimer = modal.lastTimer[event]
+
+  if (typeof lastSendTimer === 'undefined') {
+    uni.showToast({
+      title: '短信发送事件错误'
+    })
+    return
+  }
+
+  const duration = ref(dayjs().unix() - lastSendTimer - 60)
+  const canSend = duration.value >= 0
+
+  if (canSend) {
+    return '获取验证码'
+  }
+
+  if (!canSend) {
+    setTimeout(() => {
+      duration.value++;
+    }, 1000);
+    return -duration.value.toString() + ' 秒'
+  }
+}

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff