LockPage.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <div
  3. :class="prefixCls"
  4. class="fixed inset-0 flex h-screen w-screen bg-black items-center justify-center"
  5. >
  6. <div
  7. :class="`${prefixCls}__unlock`"
  8. 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"
  9. @click="handleShowForm(false)"
  10. v-show="showDate"
  11. >
  12. <LockOutlined />
  13. <span>{{ t('sys.lock.unlock') }}</span>
  14. </div>
  15. <div class="flex w-screen h-screen justify-center items-center">
  16. <div :class="`${prefixCls}__hour`" class="relative mr-5 md:mr-20 w-2/5 h-2/5 md:h-4/5">
  17. <span>{{ hour }}</span>
  18. <span class="meridiem absolute left-5 top-5 text-md xl:text-xl" v-show="showDate">
  19. {{ meridiem }}
  20. </span>
  21. </div>
  22. <div :class="`${prefixCls}__minute w-2/5 h-2/5 md:h-4/5 `">
  23. <span> {{ minute }}</span>
  24. </div>
  25. </div>
  26. <transition name="fade-slide">
  27. <div :class="`${prefixCls}-entry`" v-show="!showDate">
  28. <div :class="`${prefixCls}-entry-content`">
  29. <div :class="`${prefixCls}-entry__header enter-x`">
  30. <img :src="headerImg" :class="`${prefixCls}-entry__header-img`" />
  31. <p :class="`${prefixCls}-entry__header-name`">
  32. {{ nickname }}
  33. </p>
  34. </div>
  35. <InputPassword
  36. :placeholder="t('sys.lock.placeholder')"
  37. class="enter-x"
  38. v-model:value="password"
  39. />
  40. <span :class="`${prefixCls}-entry__err-msg enter-x`" v-if="errMsgRef">
  41. {{ t('sys.lock.alert') }}
  42. </span>
  43. <div :class="`${prefixCls}-entry__footer enter-x`">
  44. <a-button
  45. type="link"
  46. size="small"
  47. class="mt-2 mr-2 enter-x"
  48. :disabled="loadingRef"
  49. @click="handleShowForm(true)"
  50. >
  51. {{ t('common.back') }}
  52. </a-button>
  53. <a-button
  54. type="link"
  55. size="small"
  56. class="mt-2 mr-2 enter-x"
  57. :disabled="loadingRef"
  58. @click="goLogin"
  59. >
  60. {{ t('sys.lock.backToLogin') }}
  61. </a-button>
  62. <a-button class="mt-2" type="link" size="small" @click="unLock()" :loading="loadingRef">
  63. {{ t('sys.lock.entry') }}
  64. </a-button>
  65. </div>
  66. </div>
  67. </div>
  68. </transition>
  69. <div class="absolute bottom-5 w-full text-gray-300 xl:text-xl 2xl:text-3xl text-center enter-y">
  70. <div class="text-5xl mb-4 enter-x" v-show="!showDate">
  71. {{ hour }}:{{ minute }} <span class="text-3xl">{{ meridiem }}</span>
  72. </div>
  73. <div class="text-2xl"> {{ year }}/{{ month }}/{{ day }} {{ week }} </div>
  74. </div>
  75. </div>
  76. </template>
  77. <script lang="ts">
  78. import { defineComponent, ref, computed } from 'vue';
  79. import { Input } from 'ant-design-vue';
  80. import { userStore } from '/@/store/modules/user';
  81. import { lockStore } from '/@/store/modules/lock';
  82. import { useI18n } from '/@/hooks/web/useI18n';
  83. import { useNow } from './useNow';
  84. import { useDesign } from '/@/hooks/web/useDesign';
  85. import { LockOutlined } from '@ant-design/icons-vue';
  86. import headerImg from '/@/assets/images/header.jpg';
  87. export default defineComponent({
  88. name: 'LockPage',
  89. components: { LockOutlined, InputPassword: Input.Password },
  90. setup() {
  91. const passwordRef = ref('');
  92. const loadingRef = ref(false);
  93. const errMsgRef = ref(false);
  94. const showDate = ref(true);
  95. const { prefixCls } = useDesign('lock-page');
  96. const { ...state } = useNow(true);
  97. const { t } = useI18n();
  98. const nickname = computed(() => {
  99. const { nickname } = userStore.getUserInfoState || {};
  100. return nickname;
  101. });
  102. /**
  103. * @description: unLock
  104. */
  105. async function unLock() {
  106. if (!passwordRef.value) {
  107. return;
  108. }
  109. let password = passwordRef.value;
  110. try {
  111. loadingRef.value = true;
  112. const res = await lockStore.unLockAction({ password });
  113. errMsgRef.value = !res;
  114. } finally {
  115. loadingRef.value = false;
  116. }
  117. }
  118. function goLogin() {
  119. userStore.logout(true);
  120. lockStore.resetLockInfo();
  121. }
  122. function handleShowForm(show = false) {
  123. showDate.value = show;
  124. }
  125. return {
  126. goLogin,
  127. nickname,
  128. unLock,
  129. errMsgRef,
  130. loadingRef,
  131. t,
  132. prefixCls,
  133. showDate,
  134. password: passwordRef,
  135. handleShowForm,
  136. headerImg,
  137. ...state,
  138. };
  139. },
  140. });
  141. </script>
  142. <style lang="less" scoped>
  143. @prefix-cls: ~'@{namespace}-lock-page';
  144. .@{prefix-cls} {
  145. z-index: @lock-page-z-index;
  146. &__unlock {
  147. transform: translate(-50%, 0);
  148. }
  149. &__hour,
  150. &__minute {
  151. display: flex;
  152. font-weight: 700;
  153. color: #bababa;
  154. background: #141313;
  155. border-radius: 30px;
  156. justify-content: center;
  157. align-items: center;
  158. @media screen and (max-width: @screen-md) {
  159. span:not(.meridiem) {
  160. font-size: 160px;
  161. }
  162. }
  163. @media screen and (min-width: @screen-md) {
  164. span:not(.meridiem) {
  165. font-size: 160px;
  166. }
  167. }
  168. @media screen and (max-width: @screen-sm) {
  169. span:not(.meridiem) {
  170. font-size: 90px;
  171. }
  172. }
  173. @media screen and (min-width: @screen-lg) {
  174. span:not(.meridiem) {
  175. font-size: 220px;
  176. }
  177. }
  178. @media screen and (min-width: @screen-xl) {
  179. span:not(.meridiem) {
  180. font-size: 260px;
  181. }
  182. }
  183. @media screen and (min-width: @screen-2xl) {
  184. span:not(.meridiem) {
  185. font-size: 320px;
  186. }
  187. }
  188. }
  189. &-entry {
  190. position: absolute;
  191. top: 0;
  192. left: 0;
  193. display: flex;
  194. width: 100%;
  195. height: 100%;
  196. background: rgba(0, 0, 0, 0.5);
  197. backdrop-filter: blur(8px);
  198. justify-content: center;
  199. align-items: center;
  200. &-content {
  201. width: 260px;
  202. }
  203. &__header {
  204. text-align: center;
  205. &-img {
  206. width: 70px;
  207. margin: 0 auto;
  208. border-radius: 50%;
  209. }
  210. &-name {
  211. margin-top: 5px;
  212. font-weight: 500;
  213. color: #bababa;
  214. }
  215. }
  216. &__err-msg {
  217. display: inline-block;
  218. margin-top: 10px;
  219. color: @error-color;
  220. }
  221. &__footer {
  222. display: flex;
  223. justify-content: space-between;
  224. }
  225. }
  226. }
  227. </style>