提交 | 用户 | 时间
|
820397
|
1 |
<script lang="ts" setup> |
H |
2 |
import { resetRouter } from '@/router' |
|
3 |
import { deleteUserCache } from '@/hooks/web/useCache' |
|
4 |
import { useLockStore } from '@/store/modules/lock' |
|
5 |
import { useNow } from '@/hooks/web/useNow' |
|
6 |
import { useDesign } from '@/hooks/web/useDesign' |
|
7 |
import { useTagsViewStore } from '@/store/modules/tagsView' |
|
8 |
import { useUserStore } from '@/store/modules/user' |
|
9 |
import avatarImg from '@/assets/imgs/avatar.gif' |
|
10 |
|
|
11 |
const tagsViewStore = useTagsViewStore() |
|
12 |
|
|
13 |
const { replace } = useRouter() |
|
14 |
|
|
15 |
const userStore = useUserStore() |
|
16 |
|
|
17 |
const password = ref('') |
|
18 |
const loading = ref(false) |
|
19 |
const errMsg = ref(false) |
|
20 |
const showDate = ref(true) |
|
21 |
|
|
22 |
const { getPrefixCls } = useDesign() |
|
23 |
const prefixCls = getPrefixCls('lock-page') |
|
24 |
|
3e359e
|
25 |
const avatar = computed(() => userStore.user.avatar || avatarImg) |
820397
|
26 |
const userName = computed(() => userStore.user.nickname ?? 'Admin') |
H |
27 |
|
|
28 |
const lockStore = useLockStore() |
|
29 |
|
|
30 |
const { hour, month, minute, meridiem, year, day, week } = useNow(true) |
|
31 |
|
|
32 |
const { t } = useI18n() |
|
33 |
|
|
34 |
// 解锁 |
|
35 |
async function unLock() { |
|
36 |
if (!password.value) { |
|
37 |
return |
|
38 |
} |
|
39 |
let pwd = password.value |
|
40 |
try { |
|
41 |
loading.value = true |
|
42 |
const res = await lockStore.unLock(pwd) |
|
43 |
errMsg.value = !res |
|
44 |
} finally { |
|
45 |
loading.value = false |
|
46 |
} |
|
47 |
} |
|
48 |
|
|
49 |
// 返回登录 |
|
50 |
async function goLogin() { |
|
51 |
await userStore.loginOut().catch(() => {}) |
|
52 |
// 登出后清理 |
|
53 |
deleteUserCache() // 清空用户缓存 |
|
54 |
tagsViewStore.delAllViews() |
|
55 |
// resetRouter() // 重置静态路由表 |
|
56 |
lockStore.resetLockInfo() |
|
57 |
replace('/login') |
|
58 |
} |
|
59 |
|
|
60 |
function handleShowForm(show = false) { |
|
61 |
showDate.value = show |
|
62 |
} |
|
63 |
</script> |
|
64 |
|
|
65 |
<template> |
|
66 |
<div |
|
67 |
:class="prefixCls" |
|
68 |
class="fixed inset-0 flex h-screen w-screen bg-black items-center justify-center" |
|
69 |
> |
|
70 |
<div |
|
71 |
:class="`${prefixCls}__unlock`" |
|
72 |
class="absolute top-0 left-1/2 flex pt-5 h-16 items-center justify-center sm:text-md xl:text-xl text-white flex-col cursor-pointer transform translate-x-1/2" |
|
73 |
@click="handleShowForm(false)" |
|
74 |
v-show="showDate" |
|
75 |
> |
|
76 |
<Icon icon="ep:lock" /> |
|
77 |
<span>{{ t('lock.unlock') }}</span> |
|
78 |
</div> |
|
79 |
|
|
80 |
<div class="flex w-screen h-screen justify-center items-center"> |
|
81 |
<div :class="`${prefixCls}__hour`" class="relative mr-5 md:mr-20 w-2/5 h-2/5 md:h-4/5"> |
|
82 |
<span>{{ hour }}</span> |
|
83 |
<span class="meridiem absolute left-5 top-5 text-md xl:text-xl" v-show="showDate"> |
|
84 |
{{ meridiem }} |
|
85 |
</span> |
|
86 |
</div> |
|
87 |
<div :class="`${prefixCls}__minute w-2/5 h-2/5 md:h-4/5 `"> |
|
88 |
<span> {{ minute }}</span> |
|
89 |
</div> |
|
90 |
</div> |
|
91 |
<transition name="fade-slide"> |
|
92 |
<div :class="`${prefixCls}-entry`" v-show="!showDate"> |
|
93 |
<div :class="`${prefixCls}-entry-content`"> |
|
94 |
<div class="flex flex-col items-center"> |
|
95 |
<img :src="avatar" alt="" class="w-70px h-70px rounded-[50%]" /> |
|
96 |
<span class="text-14px my-10px text-[var(--logo-title-text-color)]"> |
|
97 |
{{ userName }} |
|
98 |
</span> |
|
99 |
</div> |
|
100 |
<ElInput |
|
101 |
type="password" |
|
102 |
:placeholder="t('lock.placeholder')" |
|
103 |
class="enter-x" |
|
104 |
v-model="password" |
|
105 |
/> |
|
106 |
<span :class="`text-14px ${prefixCls}-entry__err-msg enter-x`" v-if="errMsg"> |
|
107 |
{{ t('lock.message') }} |
|
108 |
</span> |
|
109 |
<div :class="`${prefixCls}-entry__footer enter-x`"> |
|
110 |
<ElButton |
|
111 |
type="primary" |
|
112 |
size="small" |
|
113 |
class="mt-2 mr-2 enter-x" |
|
114 |
link |
|
115 |
:disabled="loading" |
|
116 |
@click="handleShowForm(true)" |
|
117 |
> |
|
118 |
{{ t('common.back') }} |
|
119 |
</ElButton> |
|
120 |
<ElButton |
|
121 |
type="primary" |
|
122 |
size="small" |
|
123 |
class="mt-2 mr-2 enter-x" |
|
124 |
link |
|
125 |
:disabled="loading" |
|
126 |
@click="goLogin" |
|
127 |
> |
|
128 |
{{ t('lock.backToLogin') }} |
|
129 |
</ElButton> |
|
130 |
<ElButton |
|
131 |
type="primary" |
|
132 |
class="mt-2" |
|
133 |
size="small" |
|
134 |
link |
|
135 |
@click="unLock()" |
|
136 |
:disabled="loading" |
|
137 |
> |
|
138 |
{{ t('lock.entrySystem') }} |
|
139 |
</ElButton> |
|
140 |
</div> |
|
141 |
</div> |
|
142 |
</div> |
|
143 |
</transition> |
|
144 |
|
|
145 |
<div class="absolute bottom-5 w-full text-gray-300 xl:text-xl 2xl:text-3xl text-center enter-y"> |
|
146 |
<div class="text-5xl mb-4 enter-x" v-show="!showDate"> |
|
147 |
{{ hour }}:{{ minute }} <span class="text-3xl">{{ meridiem }}</span> |
|
148 |
</div> |
|
149 |
<div class="text-2xl">{{ year }}/{{ month }}/{{ day }} {{ week }}</div> |
|
150 |
</div> |
|
151 |
</div> |
|
152 |
</template> |
|
153 |
|
|
154 |
<style lang="scss" scoped> |
|
155 |
$prefix-cls: '#{$namespace}-lock-page'; |
|
156 |
|
|
157 |
// Small screen / tablet |
|
158 |
$screen-sm: 576px; |
|
159 |
|
|
160 |
// Medium screen / desktop |
|
161 |
$screen-md: 768px; |
|
162 |
|
|
163 |
// Large screen / wide desktop |
|
164 |
$screen-lg: 992px; |
|
165 |
|
|
166 |
// Extra large screen / full hd |
|
167 |
$screen-xl: 1200px; |
|
168 |
|
|
169 |
// Extra extra large screen / large desktop |
|
170 |
$screen-2xl: 1600px; |
|
171 |
|
|
172 |
$error-color: #ed6f6f; |
|
173 |
|
|
174 |
.#{$prefix-cls} { |
|
175 |
z-index: 3000; |
|
176 |
|
|
177 |
&__unlock { |
|
178 |
transform: translate(-50%, 0); |
|
179 |
} |
|
180 |
|
|
181 |
&__hour, |
|
182 |
&__minute { |
|
183 |
display: flex; |
|
184 |
font-weight: 700; |
|
185 |
color: #bababa; |
|
186 |
background-color: #141313; |
|
187 |
border-radius: 30px; |
|
188 |
justify-content: center; |
|
189 |
align-items: center; |
|
190 |
|
|
191 |
@media screen and (max-width: $screen-md) { |
|
192 |
span:not(.meridiem) { |
|
193 |
font-size: 160px; |
|
194 |
} |
|
195 |
} |
|
196 |
|
|
197 |
@media screen and (min-width: $screen-md) { |
|
198 |
span:not(.meridiem) { |
|
199 |
font-size: 160px; |
|
200 |
} |
|
201 |
} |
|
202 |
|
|
203 |
@media screen and (max-width: $screen-sm) { |
|
204 |
span:not(.meridiem) { |
|
205 |
font-size: 90px; |
|
206 |
} |
|
207 |
} |
|
208 |
@media screen and (min-width: $screen-lg) { |
|
209 |
span:not(.meridiem) { |
|
210 |
font-size: 220px; |
|
211 |
} |
|
212 |
} |
|
213 |
|
|
214 |
@media screen and (min-width: $screen-xl) { |
|
215 |
span:not(.meridiem) { |
|
216 |
font-size: 260px; |
|
217 |
} |
|
218 |
} |
|
219 |
@media screen and (min-width: $screen-2xl) { |
|
220 |
span:not(.meridiem) { |
|
221 |
font-size: 320px; |
|
222 |
} |
|
223 |
} |
|
224 |
} |
|
225 |
|
|
226 |
&-entry { |
|
227 |
position: absolute; |
|
228 |
top: 0; |
|
229 |
left: 0; |
|
230 |
display: flex; |
|
231 |
width: 100%; |
|
232 |
height: 100%; |
|
233 |
background-color: rgba(0, 0, 0, 0.5); |
|
234 |
backdrop-filter: blur(8px); |
|
235 |
justify-content: center; |
|
236 |
align-items: center; |
|
237 |
|
|
238 |
&-content { |
|
239 |
width: 260px; |
|
240 |
} |
|
241 |
|
|
242 |
&__header { |
|
243 |
text-align: center; |
|
244 |
|
|
245 |
&-img { |
|
246 |
width: 70px; |
|
247 |
margin: 0 auto; |
|
248 |
border-radius: 50%; |
|
249 |
} |
|
250 |
|
|
251 |
&-name { |
|
252 |
margin-top: 5px; |
|
253 |
font-weight: 500; |
|
254 |
color: #bababa; |
|
255 |
} |
|
256 |
} |
|
257 |
|
|
258 |
&__err-msg { |
|
259 |
display: inline-block; |
|
260 |
margin-top: 10px; |
|
261 |
color: $error-color; |
|
262 |
} |
|
263 |
|
|
264 |
&__footer { |
|
265 |
display: flex; |
|
266 |
justify-content: space-between; |
|
267 |
} |
|
268 |
} |
|
269 |
} |
|
270 |
</style> |