mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-09-20 20:02:02 +08:00
💄 style(verify-code): 调整 APP 端验证码输入框的隐藏方案
- 将原生输入框移出可视区域,避免 Android 设备上原生光标与自绘数字冲突 - 为 xt__verify-code 增加 overflow 隐藏,输入内容与光标不再显示在验证码格上 ♻️ refactor(login): 移除 u-code 组件并自实现验证码倒计时 - 用 displayCodeTip 计算属性配合计时器替换 u-code,统一验证码按钮文案展示 - 新增 onBeforeUnmount 清理倒计时定时器,避免内存泄漏 - 重构 fetchCode 发送逻辑,简化校验与错误处理分支 - 更新获取验证码按钮样式为橙色渐变并调整文字颜色 ♻️ refactor(live): 为 APP 端补充直播服务占位实现 - 通过条件编译在 APP-PLUS 下提供 LiveChatService 与 LiveMqttService 空实现 - 避免 APP 端引入直播聊天与 MQTT 依赖,仅保留其他平台原有逻辑
This commit is contained in:
@@ -280,11 +280,21 @@ function codeFormat(val: string | undefined, isPassword: boolean): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #ifdef APP-PLUS */
|
/* #ifdef APP-PLUS */
|
||||||
/* APP 中让自绘验证码位于透明输入框上方;点击仍由 input-ground 触发聚焦。 */
|
/*
|
||||||
.xt__input {
|
* App 的原生 input 如果覆盖在验证码格上,部分 Android 设备会出现
|
||||||
z-index: 1;
|
* 原生光标/输入绘制层与自绘数字冲突。沿用 u-code-input 的隐藏输入方式,
|
||||||
}
|
* 将输入内容和原生光标移出可视区域,验证码格只负责展示响应式状态。
|
||||||
|
*/
|
||||||
|
.xt__verify-code {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xt__input {
|
||||||
|
left: -750rpx;
|
||||||
|
width: 1500rpx;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.xt__input-ground {
|
.xt__input-ground {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|||||||
@@ -41,13 +41,11 @@
|
|||||||
cursorColor="#D8D8D8"
|
cursorColor="#D8D8D8"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="fetch-btn">
|
<view class="fetch-btn" style="display: flex; align-items: center; justify-content: center; width: 370rpx; height: 80rpx; border-radius: 100rpx; background-color: #ff6a00">
|
||||||
<u-code change-text="验证码已发送(x)" end-text="重新获取验证码" unique-key="page-login"
|
<text @tap="fetchCode" style="color: #fff; font-size: 28rpx; line-height: 80rpx">
|
||||||
:seconds="seconds" @end="end" @start="start" ref="uCode" @change="codeChange">
|
{{ displayCodeTip }}
|
||||||
</u-code>
|
</text>
|
||||||
<span @tap="fetchCode" :style="{ color: codeColor }">
|
</view>
|
||||||
{{ tips }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -131,7 +129,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, computed, watch, nextTick, getCurrentInstance, onMounted } from 'vue'
|
import { ref, reactive, computed, watch, getCurrentInstance, onMounted, onBeforeUnmount } from 'vue'
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||||
import { useStore } from '@/store'
|
import { useStore } from '@/store'
|
||||||
import { openIdLogin, loginCallback, webConnect } from '@/api/connect.js'
|
import { openIdLogin, loginCallback, webConnect } from '@/api/connect.js'
|
||||||
@@ -166,8 +164,14 @@ const codeFlag = ref(true)
|
|||||||
const tips = ref('')
|
const tips = ref('')
|
||||||
const enableUserPwdBox = ref(false)
|
const enableUserPwdBox = ref(false)
|
||||||
const current = ref(0)
|
const current = ref(0)
|
||||||
const codeColor = ref('#999')
|
const isCodeCountingDown = ref(false)
|
||||||
const seconds = ref(60)
|
const seconds = 60
|
||||||
|
const remainingCodeSeconds = ref(60)
|
||||||
|
let codeCountdownTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
const displayCodeTip = computed(() => {
|
||||||
|
if (isCodeCountingDown.value) return `验证码已发送(${remainingCodeSeconds.value})`
|
||||||
|
return tips.value || '获取验证码'
|
||||||
|
})
|
||||||
const loginTitleWay = [
|
const loginTitleWay = [
|
||||||
{ title: '欢迎登录', desc: '登录后更精彩,美好生活即将开始' },
|
{ title: '欢迎登录', desc: '登录后更精彩,美好生活即将开始' },
|
||||||
{ title: '请输入验证码', desc: '已经发送验证码至' },
|
{ title: '请输入验证码', desc: '已经发送验证码至' },
|
||||||
@@ -192,7 +196,13 @@ const loginList = ref<LoginListItem[]>([
|
|||||||
const clientType = ref('')
|
const clientType = ref('')
|
||||||
|
|
||||||
const verification = ref<any>(null)
|
const verification = ref<any>(null)
|
||||||
const uCode = ref<any>(null)
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (codeCountdownTimer) {
|
||||||
|
clearInterval(codeCountdownTimer)
|
||||||
|
codeCountdownTimer = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 只要是app登录的全部清除内容
|
// 只要是app登录的全部清除内容
|
||||||
@@ -304,33 +314,31 @@ watch(flage, async (val) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首次发送时 uCode 尚未挂载;重新获取时才检查倒计时
|
const canSendCode = current.value === 0 || !isCodeCountingDown.value
|
||||||
const canSendCode = current.value === 0 || uCode.value?.canGetCode
|
|
||||||
if (!canSendCode) {
|
if (!canSendCode) {
|
||||||
proxy.$u.toast('请倒计时结束后再发送')
|
proxy.$u.toast('请倒计时结束后再发送')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.showLoading({})
|
uni.showLoading({})
|
||||||
const res = await sendMobile(mobile.value)
|
try {
|
||||||
if (store.state.isShowToast) {
|
const res = await sendMobile(mobile.value)
|
||||||
|
if (res.data.success) {
|
||||||
|
code.value = ''
|
||||||
|
current.value = 1
|
||||||
|
startCodeCountdown()
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message,
|
||||||
|
duration: 2000,
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
flage.value = false
|
||||||
|
verification.value?.getCode()
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
}
|
}
|
||||||
if (res.data.success) {
|
|
||||||
code.value = ''
|
|
||||||
current.value = 1
|
|
||||||
nextTick(() => {
|
|
||||||
uCode.value?.start()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: res.data.message,
|
|
||||||
duration: 2000,
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
flage.value = false
|
|
||||||
verification.value?.getCode()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
verification.value?.hide()
|
verification.value?.hide()
|
||||||
}
|
}
|
||||||
@@ -594,24 +602,29 @@ function navigateToPrivacy(val: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function start() {
|
function startCodeCountdown() {
|
||||||
codeColor.value = '#999'
|
if (codeCountdownTimer) clearInterval(codeCountdownTimer)
|
||||||
|
isCodeCountingDown.value = true
|
||||||
|
remainingCodeSeconds.value = seconds
|
||||||
|
tips.value = `验证码已发送(${seconds})`
|
||||||
|
codeCountdownTimer = setInterval(() => {
|
||||||
|
if (remainingCodeSeconds.value > 1) {
|
||||||
|
remainingCodeSeconds.value -= 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clearInterval(codeCountdownTimer!)
|
||||||
|
codeCountdownTimer = null
|
||||||
|
isCodeCountingDown.value = false
|
||||||
|
remainingCodeSeconds.value = 0
|
||||||
|
tips.value = '重新获取验证码'
|
||||||
|
codeFlag.value = true
|
||||||
|
}, 1000)
|
||||||
proxy.$u.toast('验证码已发送')
|
proxy.$u.toast('验证码已发送')
|
||||||
flage.value = false
|
flage.value = false
|
||||||
codeFlag.value = false
|
codeFlag.value = false
|
||||||
verification.value?.hide()
|
verification.value?.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
function codeChange(text: string) {
|
|
||||||
tips.value = text
|
|
||||||
}
|
|
||||||
|
|
||||||
function end() {
|
|
||||||
codeColor.value = lightColor.value
|
|
||||||
codeFlag.value = true
|
|
||||||
console.log(codeColor.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function passwordLogin() {
|
function passwordLogin() {
|
||||||
if (!enablePrivacy.value) {
|
if (!enablePrivacy.value) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -676,20 +689,6 @@ function fetchCode() {
|
|||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (tips.value == '重新获取验证码') {
|
|
||||||
uni.showLoading({ title: '加载中' })
|
|
||||||
if (!codeFlag.value) {
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
if (verification.value) {
|
|
||||||
verification.value.error()
|
|
||||||
}
|
|
||||||
clearInterval(timer)
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
if (store.state.isShowToast) {
|
|
||||||
uni.hideLoading()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flage.value) {
|
if (!flage.value) {
|
||||||
verification.value?.error()
|
verification.value?.error()
|
||||||
return false
|
return false
|
||||||
@@ -817,14 +816,18 @@ declare function miniProgramLogin(code: string | undefined): Promise<{ data: any
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fetch-btn {
|
.fetch-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 370rpx;
|
width: 370rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
line-height: 80rpx;
|
line-height: 80rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #f2f2f2;
|
background-color: #ff6a00;
|
||||||
|
background: linear-gradient(57.72deg, #ff8a19 18.14%, #ff5e00 98.44%);
|
||||||
border-radius: 100rpx;
|
border-radius: 100rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #999;
|
color: #fff;
|
||||||
|
|
||||||
margin: 71rpx auto 0 auto;
|
margin: 71rpx auto 0 auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -488,8 +488,34 @@ import {
|
|||||||
import config from '@/config/config'
|
import config from '@/config/config'
|
||||||
import { useStore } from '@/store'
|
import { useStore } from '@/store'
|
||||||
import { isLogin, navigateToLogin, unitPrice } from '@/utils/filters.js'
|
import { isLogin, navigateToLogin, unitPrice } from '@/utils/filters.js'
|
||||||
|
// #ifndef APP-PLUS
|
||||||
import { LiveChatService } from './utils/liveChat.js'
|
import { LiveChatService } from './utils/liveChat.js'
|
||||||
import { LiveMqttService } from './utils/liveMqtt.js'
|
import { LiveMqttService } from './utils/liveMqtt.js'
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
class LiveChatService {
|
||||||
|
userInfo: any = {}
|
||||||
|
constructor(_options: any = {}) {}
|
||||||
|
setGroupID(_id: string) {}
|
||||||
|
async initTencentIm(_viewLiveResult?: any) {}
|
||||||
|
cleanup() {}
|
||||||
|
}
|
||||||
|
class LiveMqttService {
|
||||||
|
userId: any = null
|
||||||
|
mqttClient: any = null
|
||||||
|
constructor(_liveId: any, userId: any) {
|
||||||
|
this.userId = userId
|
||||||
|
}
|
||||||
|
setMessageHandlers(_handlers: any) {}
|
||||||
|
isConnected() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
initMqtt() {}
|
||||||
|
cleanup() {
|
||||||
|
this.mqttClient = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
import { findRecommendPayload, parseRecommendMessageArray } from './utils/liveRecommend.js'
|
import { findRecommendPayload, parseRecommendMessageArray } from './utils/liveRecommend.js'
|
||||||
import { seedLiveSetting } from './utils/liveSetting.js'
|
import { seedLiveSetting } from './utils/liveSetting.js'
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
|
|||||||
Reference in New Issue
Block a user