5 changed files with 4 additions and 241 deletions
@ -1,172 +0,0 @@ |
|||
<template> |
|||
<div v-if="modelValue" class="logout-container"> |
|||
<div class="dialog-wrapper"> |
|||
<p class="out-icon" @click="close"> |
|||
<img src="./chahao.svg" class="close-icon" /> |
|||
</p> |
|||
<input id="pwd" v-model="state.pwd" class="commons" placeholder="请输入密码" type="password" /> |
|||
<p v-if="state.error" class="err-tips">密码错误</p> |
|||
<ul class="num-items"> |
|||
<li v-for="item of state.num" :key="item" class="num-item" @click="handleClick(item)"> |
|||
{{ item }} |
|||
</li> |
|||
<li class="num-item deletes" @click="deletes"> |
|||
<img alt="" src="./chahao.svg" /> |
|||
</li> |
|||
</ul> |
|||
<button class="close-browser commons" @click="closeBrowser">退出程序</button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { watch, reactive, computed } from 'vue' |
|||
|
|||
defineProps({ |
|||
modelValue: Boolean |
|||
}) |
|||
|
|||
const emits = defineEmits(['bingo', 'close', 'update:modelValue']) |
|||
|
|||
const state = reactive({ |
|||
pwd: '', |
|||
error: false, |
|||
num: [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] |
|||
}) |
|||
|
|||
const MAX_LEN = 6 |
|||
|
|||
//生成密码 |
|||
const generatePwd = computed(() => { |
|||
const date = new Date() |
|||
return `${date.getDate().toString().padStart(2, '0')}${date.getDay().toString().padStart(2, '0')}${(date.getMonth() + 1) |
|||
.toString() |
|||
.padStart(2, '0')}` |
|||
}) |
|||
|
|||
function closeBrowser() { |
|||
if (state.pwd === generatePwd.value) { |
|||
emits('bingo') |
|||
} |
|||
} |
|||
function close() { |
|||
emits('update:modelValue', false) |
|||
} |
|||
|
|||
function deletes() { |
|||
state.pwd = state.pwd.substring(0, state.pwd.length - 1) |
|||
} |
|||
|
|||
function handleClick(item: number) { |
|||
if (state.pwd.length >= MAX_LEN) { |
|||
return |
|||
} |
|||
state.pwd += item |
|||
} |
|||
|
|||
watch( |
|||
() => state.pwd, |
|||
newVal => { |
|||
state.error = newVal.length === MAX_LEN && newVal !== generatePwd.value |
|||
} |
|||
) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.logout-container { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
z-index: 9999; |
|||
background-color: rgb(0 0 0 / 30%); |
|||
backdrop-filter: blur(20px); |
|||
animation-duration: 0.3s; |
|||
|
|||
.dialog-wrapper { |
|||
position: fixed; |
|||
top: 50%; |
|||
left: 50%; |
|||
display: flex; |
|||
align-items: center; |
|||
width: 780px; |
|||
padding: 90px 0; |
|||
background-color: #fff; |
|||
border-radius: 20px; |
|||
transform: translate3d(-50%, -50%, 0); |
|||
flex-direction: column; |
|||
align-content: flex-start; |
|||
.out-icon { |
|||
position: absolute; |
|||
top: 20px; |
|||
right: 25px; |
|||
.close-icon { |
|||
width: 50px; |
|||
} |
|||
} |
|||
.err-tips { |
|||
position: absolute; |
|||
top: 166px; |
|||
left: 172px; |
|||
font-size: 14px; |
|||
color: #c03127; |
|||
font-weight: bolder; |
|||
} |
|||
.commons { |
|||
width: 500px; |
|||
height: 60px; |
|||
border: none; |
|||
border-radius: 60px; |
|||
outline: none; |
|||
} |
|||
|
|||
#pwd { |
|||
padding-left: 30px; |
|||
margin-bottom: 45px; |
|||
font-size: 16px; |
|||
box-shadow: 0 5px 9px 0 rgb(90 90 90 / 20%); |
|||
} |
|||
|
|||
.num-items { |
|||
display: grid; |
|||
grid-template-columns: repeat(3, 62px); |
|||
grid-template-rows: repeat(3, 62px); |
|||
gap: 45px 80px; |
|||
width: 350px; |
|||
margin: 0 auto; |
|||
margin-bottom: 45px; |
|||
|
|||
.num-item { |
|||
font-size: 30px; |
|||
text-align: center; |
|||
color: black; |
|||
border-radius: 50%; |
|||
line-height: 62px; |
|||
&.deletes { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
&:hover { |
|||
color: #fff; |
|||
background-color: #aca8b3; |
|||
} |
|||
&:nth-child(10) { |
|||
grid-column-start: 2; |
|||
} |
|||
img { |
|||
width: 40px; |
|||
height: 40px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.close-browser { |
|||
font-size: 22px; |
|||
color: #fff; |
|||
background-color: #aca8b3; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
|
Before Width: | Height: | Size: 797 B |
@ -1,50 +0,0 @@ |
|||
import { ref, nextTick, watch } from 'vue' |
|||
|
|||
export const useLogout = () => { |
|||
const logout = ref(false) |
|||
const clickedNumberTotal = ref(0) |
|||
const timer = ref() |
|||
const MAX_NUMBER = 10 |
|||
const DELAY_TIME = 10000 |
|||
const SAFE_COORDINATES = 200 |
|||
|
|||
function resetClickNumber() { |
|||
clickedNumberTotal.value = 0 |
|||
} |
|||
|
|||
function setLogout(flag: boolean) { |
|||
logout.value = flag |
|||
} |
|||
|
|||
//点击商场logo 达到最大次数显示退出框
|
|||
function addTotalClick(e: TouchEvent) { |
|||
try { |
|||
const { clientX, clientY } = e.changedTouches[0] |
|||
const _clientX = parseInt(String(clientX), 10) |
|||
const _clientY = parseInt(String(clientY), 10) |
|||
if (_clientX >= 0 && _clientX <= SAFE_COORDINATES && _clientY >= 0 && _clientY <= SAFE_COORDINATES) { |
|||
clickedNumberTotal.value++ |
|||
} |
|||
nextTick(() => { |
|||
if (clickedNumberTotal.value >= MAX_NUMBER) { |
|||
logout.value = true |
|||
resetClickNumber() |
|||
} |
|||
}) |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
} |
|||
|
|||
watch(clickedNumberTotal, newVal => { |
|||
clearTimeout(timer.value) |
|||
timer.value = setTimeout(() => { |
|||
if (newVal !== 0) { |
|||
clearTimeout(timer.value) |
|||
resetClickNumber() |
|||
} |
|||
}, DELAY_TIME) |
|||
}) |
|||
|
|||
return { resetClickNumber, addTotalClick, setLogout, logout } |
|||
} |
|||
Loading…
Reference in new issue