index.vue 5.6 KB

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