index.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <div class="vab-lock">
  3. <vab-icon icon="lock-line" @click="handleLock" />
  4. <el-collapse-transition>
  5. <div v-show="lock" class="vab-screen-lock">
  6. <div
  7. class="vab-screen-lock-background"
  8. :style="{
  9. background: `fixed url(${background}) center`,
  10. backgroundSize: '100% 100%',
  11. filter: 'blur(10px)',
  12. transform: 'scale(1.05)',
  13. }"
  14. ></div>
  15. <div class="vab-screen-lock-content">
  16. <div class="vab-screen-lock-content-title">
  17. <el-avatar :size="180" :src="avatar" />
  18. <vab-icon icon="lock-line" />
  19. {{ title }} {{ translate('屏幕已锁定') }}
  20. </div>
  21. <div class="vab-screen-lock-content-form">
  22. <el-form ref="formRef" :model="form" :rules="rules" @submit.prevent>
  23. <el-form-item label="" :label-width="0" prop="password">
  24. <el-input v-model="form.password" v-focus autocomplete="off" :placeholder="translate('请输入密码123456')" type="password">
  25. <template #suffix>
  26. <el-button native-type="submit" type="primary" @click="handleUnLock">
  27. <vab-icon icon="lock-line" />
  28. <span>{{ translate('解锁') }}</span>
  29. </el-button>
  30. </template>
  31. </el-input>
  32. </el-form-item>
  33. </el-form>
  34. </div>
  35. <span @click="randomBackground">{{ translate('切换壁纸') }}</span>
  36. </div>
  37. </div>
  38. </el-collapse-transition>
  39. </div>
  40. </template>
  41. <script lang="ts" setup>
  42. import { translate } from '/@/i18n'
  43. import { useSettingsStore } from '/@/store/modules/settings'
  44. import { useUserStore } from '/@/store/modules/user'
  45. defineOptions({
  46. name: 'VabLock',
  47. })
  48. const userStore = useUserStore()
  49. const { avatar } = storeToRefs(userStore)
  50. const settingsStore = useSettingsStore()
  51. const { lock, title } = storeToRefs(settingsStore)
  52. const { handleLock: _handleLock, handleUnLock: _handleUnLock } = settingsStore
  53. const url = 'https://gcore.jsdelivr.net/gh/chuzhixin/image/vab-image-lock/'
  54. const background = ref(`${url}${Math.round(Math.random() * 31)}.jpg`)
  55. const randomBackground = () => {
  56. background.value = `${url}${Math.round(Math.random() * 31)}.jpg`
  57. }
  58. const validatePass = (rule: any, value: string, callback: any) => {
  59. if (value === '' || value !== '123456') {
  60. callback(new Error('请输入正确的密码'))
  61. } else {
  62. callback()
  63. }
  64. }
  65. const formRef = ref()
  66. const form = ref({
  67. password: '123456',
  68. })
  69. const rules = {
  70. password: [{ validator: validatePass, trigger: 'blur' }],
  71. }
  72. const handleUnLock = () => {
  73. formRef.value.validate(async (valid: boolean) => {
  74. if (valid) {
  75. setTimeout(async () => {
  76. await _handleUnLock()
  77. }, 500)
  78. }
  79. })
  80. }
  81. const handleLock = () => {
  82. _handleLock()
  83. }
  84. </script>
  85. <style lang="scss" scoped>
  86. .vab-screen-lock {
  87. position: fixed;
  88. top: 0;
  89. right: 0;
  90. bottom: 0;
  91. left: 0;
  92. z-index: var(--el-z-index);
  93. display: flex;
  94. flex-wrap: wrap;
  95. align-items: center;
  96. justify-content: center;
  97. font-weight: bold;
  98. background: var(--el-mask-color);
  99. backdrop-filter: blur(10px);
  100. opacity: var(--opacity-value);
  101. &-background {
  102. position: absolute;
  103. top: 0;
  104. right: 0;
  105. bottom: 0;
  106. left: 0;
  107. z-index: calc(var(--el-z-index) - 1);
  108. }
  109. &-content {
  110. z-index: var(--el-z-index);
  111. width: 400px;
  112. padding: 40px 55px 40px 55px;
  113. color: var(--el-color-grey);
  114. text-align: center;
  115. background: var(--el-mask-color);
  116. backdrop-filter: blur(10px);
  117. border-radius: 15px;
  118. > span {
  119. font-size: var(--el-font-size-small);
  120. cursor: pointer;
  121. }
  122. &-title {
  123. line-height: 50px;
  124. color: var(--el-color-grey);
  125. text-align: center;
  126. :deep() {
  127. .el-avatar {
  128. width: 150px;
  129. height: 150px;
  130. img {
  131. padding: 30px;
  132. cursor: pointer;
  133. }
  134. }
  135. .ri-lock-line {
  136. display: block;
  137. margin: auto !important;
  138. font-size: 30px;
  139. color: var(--el-color-grey) !important;
  140. }
  141. }
  142. }
  143. &-form {
  144. :deep() {
  145. .el-input {
  146. position: relative;
  147. width: 100%;
  148. height: 40px;
  149. line-height: 40px;
  150. .el-input__wrapper {
  151. padding-right: 0;
  152. border: 1px solid var(--el-color-primary);
  153. box-shadow: none;
  154. .el-input__suffix {
  155. .el-button {
  156. position: absolute;
  157. right: -1px;
  158. height: 40px;
  159. margin-left: 0 !important;
  160. line-height: 40px;
  161. border-top-left-radius: 0;
  162. border-bottom-left-radius: 0;
  163. .ri-lock-line {
  164. margin-left: 0 !important;
  165. }
  166. }
  167. .el-input__validateIcon {
  168. display: none;
  169. }
  170. }
  171. }
  172. }
  173. }
  174. }
  175. }
  176. @media (max-width: 576px) {
  177. .vab-screen-lock-content {
  178. width: 100% !important;
  179. margin: 5vw;
  180. }
  181. }
  182. }
  183. </style>