LockPage.vue 6.7 KB

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