mirror of
https://github.com/un-pany/v3-admin-vite.git
synced 2025-04-22 03:49:19 +08:00
feat: login-owl
This commit is contained in:
parent
975bfd24dc
commit
f4c6c0770c
BIN
src/assets/image/owl/arm-down-left.png
Normal file
BIN
src/assets/image/owl/arm-down-left.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/image/owl/arm-down-right.png
Normal file
BIN
src/assets/image/owl/arm-down-right.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/image/owl/arm-up-left.png
Normal file
BIN
src/assets/image/owl/arm-up-left.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/image/owl/arm-up-right.png
Normal file
BIN
src/assets/image/owl/arm-up-right.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/image/owl/eye.png
Normal file
BIN
src/assets/image/owl/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/image/owl/face.png
Normal file
BIN
src/assets/image/owl/face.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
24
src/composables/useInput.ts
Normal file
24
src/composables/useInput.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { ref } from "vue"
|
||||
|
||||
export function useInput() {
|
||||
const isFocus = ref<boolean>(false)
|
||||
/**
|
||||
* @desc:失去焦点
|
||||
* @return {*}
|
||||
*/
|
||||
const listenBlur = () => {
|
||||
isFocus.value = false
|
||||
}
|
||||
/**
|
||||
* @desc: 获取焦点
|
||||
* @return {*}
|
||||
*/
|
||||
const listenFocus = () => {
|
||||
isFocus.value = true
|
||||
}
|
||||
return {
|
||||
isFocus,
|
||||
listenBlur,
|
||||
listenFocus
|
||||
}
|
||||
}
|
@ -40,3 +40,30 @@
|
||||
// 文本内容溢出容器时,文本末尾显示省略号
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@mixin transition($timeSlot...) {
|
||||
-webkit-transition: $timeSlot;
|
||||
-moz-transition: $timeSlot;
|
||||
-o-transition: $timeSlot;
|
||||
-ms-transition: $timeSlot;
|
||||
transition: $timeSlot;
|
||||
}
|
||||
@mixin transform($translate) {
|
||||
-webkit-transform: $translate;
|
||||
-moz-transform: $translate;
|
||||
-o-transform: $translate;
|
||||
-ms-transform: $translate;
|
||||
transform: $translate;
|
||||
}
|
||||
|
||||
@mixin transformOrigin($origin) {
|
||||
-webkit-transform-origin: $origin;
|
||||
-moz-transform-origin: $origin;
|
||||
-o-transform-origin: $origin;
|
||||
-ms-transform-origin: $origin;
|
||||
transform-origin: $origin;
|
||||
}
|
||||
@mixin backgroundImage($url) {
|
||||
background-image: $url;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
110
src/views/login/components/Owl.vue
Normal file
110
src/views/login/components/Owl.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="owl" :class="props.closedEyes ? 'owl-password' : ''">
|
||||
<div class="eyes" />
|
||||
<div class="arm-up-right" />
|
||||
<div class="arm-up-left" />
|
||||
<div class="arm-down-left" />
|
||||
<div class="arm-down-right" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps<{
|
||||
closedEyes: boolean
|
||||
}>()
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@/styles/mixins.scss";
|
||||
.owl {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 120px;
|
||||
height: 95px;
|
||||
transform: translate(-50%, -322%);
|
||||
background-size: 116px 92px;
|
||||
// margin-left: -64px;
|
||||
cursor: pointer;
|
||||
@include backgroundImage(url("@/assets/image/owl/face.png"));
|
||||
|
||||
.eyes {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
@include transition(0.1s ease-out 0s);
|
||||
@include backgroundImage(url("@/assets/image/owl/eye.png"));
|
||||
}
|
||||
.arm-up-right {
|
||||
width: 51px;
|
||||
height: 41px;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 5px;
|
||||
z-index: 2;
|
||||
background-position: 0 25px;
|
||||
opacity: 0;
|
||||
@include transform(translateX(57px) scale(0.8));
|
||||
@include transformOrigin(0 40px);
|
||||
@include backgroundImage(url("@/assets/image/owl/arm-up-right.png"));
|
||||
@include transition(background-position 0.3s ease-out, transform 0.3s ease-out, opacity 0s linear 0.2s);
|
||||
}
|
||||
.arm-up-left {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: -3px;
|
||||
width: 52px;
|
||||
height: 41px;
|
||||
z-index: 2;
|
||||
background-position: 0 25px;
|
||||
opacity: 0;
|
||||
@include transform(translateX(-34px) scale(0.8));
|
||||
@include transformOrigin(0 40px);
|
||||
@include backgroundImage(url("@/assets/image/owl/arm-up-left.png"));
|
||||
@include transition(background-position 0.3s ease-out, transform 0.3s ease-out, opacity 0s linear 0.2s);
|
||||
}
|
||||
.arm-down-left {
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
left: -34px;
|
||||
width: 43px;
|
||||
height: 25px;
|
||||
z-index: 1;
|
||||
@include transition(0.3s ease-out);
|
||||
@include backgroundImage(url("@/assets/image/owl/arm-down-left.png"));
|
||||
}
|
||||
.arm-down-right {
|
||||
position: absolute;
|
||||
bottom: 1px;
|
||||
right: -40px;
|
||||
width: 43px;
|
||||
height: 26px;
|
||||
z-index: 1;
|
||||
|
||||
@include transition(0.3s ease-out);
|
||||
@include backgroundImage(url("@/assets/image/owl/arm-down-right.png"));
|
||||
}
|
||||
}
|
||||
.owl-password {
|
||||
.eyes {
|
||||
opacity: 1;
|
||||
@include transition(0.1s ease-out 0.2s);
|
||||
}
|
||||
.arm-up-right {
|
||||
background-position: 0 0;
|
||||
opacity: 1;
|
||||
@include transform(scale(1));
|
||||
@include transition(background-position 0.3s ease-out, transform 0.3s ease-out);
|
||||
}
|
||||
.arm-up-left {
|
||||
@include transform(scale(1));
|
||||
background-position: 0 0;
|
||||
opacity: 1;
|
||||
@include transition(background-position 0.3s ease-out, transform 0.3s ease-out);
|
||||
}
|
||||
.arm-down-left {
|
||||
@include transform(translateX(40px) scale(0) translateY(-10px));
|
||||
}
|
||||
.arm-down-right {
|
||||
@include transform(translateX(-32px) scale(0) translateY(-8px));
|
||||
}
|
||||
}
|
||||
</style>
|
@ -7,9 +7,13 @@ import { User, Lock, Key, Picture, Loading } from "@element-plus/icons-vue"
|
||||
import { getLoginCodeApi } from "@/api/login"
|
||||
import { type LoginRequestData } from "@/api/login/types/login"
|
||||
import ThemeSwitch from "@/components/ThemeSwitch/index.vue"
|
||||
import Owl from "@/views/login/components/Owl.vue"
|
||||
import { useInput } from "@/composables/useInput"
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const { isFocus, listenBlur, listenFocus } = useInput()
|
||||
|
||||
/** 登录表单元素的引用 */
|
||||
const loginFormRef = ref<FormInstance | null>(null)
|
||||
|
||||
@ -72,6 +76,7 @@ createCode()
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<ThemeSwitch class="theme-switch" />
|
||||
<Owl :closed-eyes="isFocus" />
|
||||
<div class="login-card">
|
||||
<div class="title">
|
||||
<img src="@/assets/layouts/logo-text-2.png" />
|
||||
@ -97,6 +102,8 @@ createCode()
|
||||
:prefix-icon="Lock"
|
||||
size="large"
|
||||
show-password
|
||||
@blur="listenBlur()"
|
||||
@focus="listenFocus()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
|
Loading…
x
Reference in New Issue
Block a user