|
|
@@ -54,8 +54,60 @@
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
+ <template v-if="showSmsLogin">
|
|
|
+ <view class="login-card-head">
|
|
|
+ <text class="login-card-title">验证码登录</text>
|
|
|
+ </view>
|
|
|
+ <view class="login-form">
|
|
|
+ <view class="login-field">
|
|
|
+ <text class="login-label">手机号</text>
|
|
|
+ <input
|
|
|
+ @focus="mobile=''"
|
|
|
+ v-model="mobile"
|
|
|
+ class="login-input"
|
|
|
+ placeholder="请输入手机号"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ <view class="login-field login-field--last" style="display: flex; align-items: center; justify-content: space-between;">
|
|
|
+ <view style="flex: 1; margin-right: 20upx;">
|
|
|
+ <text class="login-label">验证码</text>
|
|
|
+ <input
|
|
|
+ @focus="smsCode=''"
|
|
|
+ v-model="smsCode"
|
|
|
+ class="login-input"
|
|
|
+ placeholder="请输入验证码"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ <button
|
|
|
+ class="admin-button-com middle blue"
|
|
|
+ :disabled="smsCountdown > 0"
|
|
|
+ @click="getSmsCode"
|
|
|
+ style="margin-top: 40upx; font-size: 26upx; height: 70upx; line-height: 70upx; padding: 0 20upx; min-width: 180upx;"
|
|
|
+ >
|
|
|
+ {{ smsCountdown > 0 ? smsCountdown + 's' : '获取验证码' }}
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ <button class="login-btn login-btn--primary" @click="smsLoginFun">登录</button>
|
|
|
+ </view>
|
|
|
+ <view class="login-agreement">
|
|
|
+ <checkbox-group @change="agreeItem">
|
|
|
+ <label class="login-agreement-label">
|
|
|
+ <checkbox value="1" class="login-checkbox" :checked="agree == 1" />
|
|
|
+ <text class="login-agreement-text">
|
|
|
+ 我已阅读并同意
|
|
|
+ <text class="login-agreement-link" @click.stop="goToService">《服务协议》</text>
|
|
|
+ 和
|
|
|
+ <text class="login-agreement-link" @click.stop="goToPrivacy">《隐私政策》</text>
|
|
|
+ </text>
|
|
|
+ </label>
|
|
|
+ </checkbox-group>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+
|
|
|
<!-- #ifdef MP-WEIXIN -->
|
|
|
- <view v-if="showAccountLogin == false" class="login-quick">
|
|
|
+ <view v-if="showAccountLogin == false && showSmsLogin == false" class="login-quick">
|
|
|
<view class="login-card-head">
|
|
|
<text class="login-card-title">手机号快捷登录</text>
|
|
|
</view>
|
|
|
@@ -75,7 +127,7 @@
|
|
|
<!-- #endif -->
|
|
|
|
|
|
<!-- #ifdef APP-PLUS -->
|
|
|
- <view v-if="showAccountLogin == false" class="login-quick">
|
|
|
+ <view v-if="showAccountLogin == false && showSmsLogin == false" class="login-quick">
|
|
|
<view class="login-card-head">
|
|
|
<text class="login-card-title">本机号码快捷登录</text>
|
|
|
</view>
|
|
|
@@ -100,27 +152,63 @@
|
|
|
<!-- #endif -->
|
|
|
|
|
|
<view class="login-footer-links">
|
|
|
+ <!-- 如果当前不是账号密码登录,显示切换到账号密码登录的链接 -->
|
|
|
<text
|
|
|
v-if="showAccountLogin == false"
|
|
|
class="login-footer-link"
|
|
|
@click="useAccount()"
|
|
|
>使用账号密码登录</text>
|
|
|
+ <!-- 如果当前是账号密码登录,显示切换到快捷登录的链接 -->
|
|
|
+ <text
|
|
|
+ v-else
|
|
|
+ class="login-footer-link"
|
|
|
+ @click="useMoibleAccount()"
|
|
|
+ >使用快捷登录</text>
|
|
|
+
|
|
|
+ <text class="login-footer-divider">|</text>
|
|
|
+
|
|
|
+ <!-- 如果当前不是短信登录,显示切换到短信登录的链接 -->
|
|
|
+ <text
|
|
|
+ v-if="showSmsLogin == false"
|
|
|
+ class="login-footer-link"
|
|
|
+ @click="useSms()"
|
|
|
+ >使用短信登录</text>
|
|
|
+ <!-- 如果当前是短信登录,显示切换到快捷登录的链接 -->
|
|
|
<text
|
|
|
v-else
|
|
|
class="login-footer-link"
|
|
|
@click="useMoibleAccount()"
|
|
|
- >使用手机号登录</text>
|
|
|
+ >使用快捷登录</text>
|
|
|
+
|
|
|
<text class="login-footer-divider">|</text>
|
|
|
<text class="login-footer-link login-footer-link--register" @click="register">注册账号</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+
|
|
|
+ <!-- #ifdef APP-PLUS -->
|
|
|
+ <web-view
|
|
|
+ v-if="showAppCaptcha"
|
|
|
+ :src="'/hybrid/html/captcha.html?sceneId=' + captchaSceneId"
|
|
|
+ @message="onAppCaptchaMessage"
|
|
|
+ style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 99999;"
|
|
|
+ ></web-view>
|
|
|
+ <!-- #endif -->
|
|
|
+
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
+ <aliyun-captcha
|
|
|
+ v-if="showWxCaptcha"
|
|
|
+ :sceneId="captchaSceneId"
|
|
|
+ @success="onWxCaptchaSuccess"
|
|
|
+ @fail="onWxCaptchaFail"
|
|
|
+ ></aliyun-captcha>
|
|
|
+ <!-- #endif -->
|
|
|
</view>
|
|
|
</template>
|
|
|
<script>
|
|
|
import { mapActions } from "vuex";
|
|
|
import { getShopInfo} from "@/utils/auth";
|
|
|
-import {appLogin} from '@/api/common'
|
|
|
+import {appLogin, sendLoginSms, smsLogin} from '@/api/common'
|
|
|
import { getDictionaries,postWxCode } from '@/api/mini'
|
|
|
import { phoneLogin,wxMobileLogin } from "@/api/auth";
|
|
|
|
|
|
@@ -135,6 +223,13 @@ export default {
|
|
|
hasMobileNet:false,
|
|
|
agree:0,
|
|
|
showAccountLogin:false,
|
|
|
+ showSmsLogin:false,
|
|
|
+ showAppCaptcha: false,
|
|
|
+ showWxCaptcha: false,
|
|
|
+ captchaSceneId: 'YOUR_SCENE_ID', // 阿里云控制台申请的场景ID
|
|
|
+ smsCode:'',
|
|
|
+ smsCountdown: 0,
|
|
|
+ smsTimer: null,
|
|
|
statusBarHeight: 0
|
|
|
}
|
|
|
},
|
|
|
@@ -142,6 +237,7 @@ export default {
|
|
|
},
|
|
|
onLoad(){
|
|
|
this.setStatusBarHeight()
|
|
|
+ this.initSmsCountdown()
|
|
|
let that = this
|
|
|
uni.getNetworkType({
|
|
|
success: function (res) {
|
|
|
@@ -175,6 +271,9 @@ export default {
|
|
|
},
|
|
|
onUnload(){
|
|
|
uni.offNetworkStatusChange(this.dealLogin)
|
|
|
+ if (this.smsTimer) {
|
|
|
+ clearInterval(this.smsTimer)
|
|
|
+ }
|
|
|
},
|
|
|
methods: {
|
|
|
...mapActions(['setUserShopAll']),
|
|
|
@@ -194,14 +293,165 @@ export default {
|
|
|
},
|
|
|
useMoibleAccount(){
|
|
|
this.showAccountLogin = false
|
|
|
+ this.showSmsLogin = false
|
|
|
this.agree = 0
|
|
|
this.$forceUpdate()
|
|
|
},
|
|
|
useAccount(){
|
|
|
this.showAccountLogin = true
|
|
|
+ this.showSmsLogin = false
|
|
|
this.agree = 0
|
|
|
this.$forceUpdate()
|
|
|
},
|
|
|
+ useSms(){
|
|
|
+ this.showAccountLogin = false
|
|
|
+ this.showSmsLogin = true
|
|
|
+ this.agree = 0
|
|
|
+ this.$forceUpdate()
|
|
|
+ },
|
|
|
+ // 从 storage 恢复短信倒计时,防止刷新或重新打开页面绕过限制
|
|
|
+ initSmsCountdown() {
|
|
|
+ const lastSent = uni.getStorageSync('last_sms_sent_time_login')
|
|
|
+ if (lastSent) {
|
|
|
+ const passed = Math.floor((Date.now() - lastSent) / 1000)
|
|
|
+ if (passed < 60) {
|
|
|
+ this.startCountdown(60 - passed)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 启动短信倒计时定时器
|
|
|
+ startCountdown(seconds) {
|
|
|
+ this.smsCountdown = seconds
|
|
|
+ if (this.smsTimer) {
|
|
|
+ clearInterval(this.smsTimer)
|
|
|
+ }
|
|
|
+ this.smsTimer = setInterval(() => {
|
|
|
+ this.smsCountdown--
|
|
|
+ if (this.smsCountdown <= 0) {
|
|
|
+ clearInterval(this.smsTimer)
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
+ },
|
|
|
+ // 获取短信验证码(先触发人机验证)
|
|
|
+ getSmsCode() {
|
|
|
+ let mobile = this.mobile
|
|
|
+ if (this.$util.isEmpty(mobile)) {
|
|
|
+ this.$msg('请输入手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.$util.checkMobile(mobile) == false) {
|
|
|
+ this.$msg('请输入正确手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 触发人机验证
|
|
|
+ this.triggerCaptcha()
|
|
|
+ },
|
|
|
+ // 唤起人机验证组件
|
|
|
+ triggerCaptcha() {
|
|
|
+ // #ifdef APP-PLUS
|
|
|
+ this.showAppCaptcha = true
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ this.showWxCaptcha = true
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // #ifndef APP-PLUS || MP-WEIXIN
|
|
|
+ // 其他平台(如H5或调试环境)若未集成,可直接调用发送接口
|
|
|
+ this.sendSmsWithCaptcha('')
|
|
|
+ // #endif
|
|
|
+ },
|
|
|
+ // 携带人机验证凭证请求发送短信
|
|
|
+ sendSmsWithCaptcha(captchaVerifyParam) {
|
|
|
+ let that = this
|
|
|
+ let mobile = this.mobile
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ sendLoginSms({
|
|
|
+ mobile: mobile,
|
|
|
+ captchaVerifyParam: captchaVerifyParam
|
|
|
+ }).then(res => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (res.code == 1) {
|
|
|
+ this.$msg('验证码已发送')
|
|
|
+ uni.setStorageSync('last_sms_sent_time_login', Date.now())
|
|
|
+ this.startCountdown(60)
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // App 端 WebView 消息监听
|
|
|
+ onAppCaptchaMessage(e) {
|
|
|
+ const data = e.detail.data[0]
|
|
|
+ if (data && data.action === 'captcha_success') {
|
|
|
+ this.showAppCaptcha = false
|
|
|
+ this.sendSmsWithCaptcha(data.captchaVerifyParam)
|
|
|
+ } else if (data && data.action === 'captcha_cancel') {
|
|
|
+ this.showAppCaptcha = false
|
|
|
+ this.$msg('验证已取消')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 微信小程序端人机验证成功
|
|
|
+ onWxCaptchaSuccess(e) {
|
|
|
+ this.showWxCaptcha = false
|
|
|
+ const param = e.detail || e
|
|
|
+ this.sendSmsWithCaptcha(param)
|
|
|
+ },
|
|
|
+ // 微信小程序端人机验证失败
|
|
|
+ onWxCaptchaFail(e) {
|
|
|
+ this.showWxCaptcha = false
|
|
|
+ this.$msg('验证失败,请重试')
|
|
|
+ },
|
|
|
+ // 短信验证码登录提交
|
|
|
+ smsLoginFun() {
|
|
|
+ let that = this
|
|
|
+ let mobile = this.mobile
|
|
|
+ let code = this.smsCode
|
|
|
+ if (this.$util.isEmpty(mobile)) {
|
|
|
+ this.$msg('请输入手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.$util.checkMobile(mobile) == false) {
|
|
|
+ this.$msg('请输入正确手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.$util.isEmpty(code)) {
|
|
|
+ this.$msg('请输入验证码')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ this.checkAgreement(function() {
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ smsLogin({ mobile: mobile, code: code, deviceId: uni.getStorageSync('deviceId') }).then(subRes => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (subRes.code == 1) {
|
|
|
+ if (that.$util.isEmpty(subRes)) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ uni.setStorageSync('token', subRes.data.token)
|
|
|
+ uni.setStorageSync('shopId', subRes.data.admin.currentGhsShopId)
|
|
|
+ getDictionaries({ token: subRes.data.token }).then(res => {
|
|
|
+ if (that.$util.isEmpty(res)) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ that.$store.commit('setDictionariesInfo', { ...res.data.dict, ...res.data })
|
|
|
+ that.$store.commit('setMyShopInfo', { ...res.data.shop, ...res.data })
|
|
|
+ })
|
|
|
+ that.$store.commit('setLoginInfo', { ...subRes.data.admin, ...subRes.data })
|
|
|
+ getShopInfo(true).then(res => { uni.setNavigationBarTitle({ title: res.name }) })
|
|
|
+ that.setUserShopAll()
|
|
|
+ uni.navigateBack()
|
|
|
+
|
|
|
+ // #ifdef APP-PLUS
|
|
|
+ that.$util.afterAppLoginSuccess({ auto: 0 })
|
|
|
+ // #endif
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
goToService(){
|
|
|
this.$util.pageTo({ url: "/admin/home/register"})
|
|
|
},
|