Files
education/frontend/node_modules/.cache/vue-loader/43b8c08925c572e7f4027b7b4917b56b.json
T

1 line
18 KiB
JSON

{"remainingRequest":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\lock.vue?vue&type=style&index=0&id=0d7b86c5&scoped=true&lang=css","dependencies":[{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\lock.vue","mtime":1787567871616},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\css-loader\\dist\\cjs.js","mtime":1787309792478},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":1787309794547},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\postcss-loader\\src\\index.js","mtime":1787309793084},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js","mtime":1787309793790}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg0KLmxvY2stY29udGFpbmVyIHsNCiAgcG9zaXRpb246IGZpeGVkOw0KICBpbnNldDogMDsNCiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzBmMGMyOSwgIzMwMmI2MywgIzI0MjQzZSk7DQogIGRpc3BsYXk6IGZsZXg7DQogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47DQogIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICB6LWluZGV4OiA5OTk5Ow0KICBmb250LWZhbWlseTogJ1BpbmdGYW5nIFNDJywgJ01pY3Jvc29mdCBZYUhlaScsIHNhbnMtc2VyaWY7DQogIG92ZXJmbG93OiBoaWRkZW47DQp9DQoNCi5wYXJ0aWNsZS1iZyB7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgaW5zZXQ6IDA7DQogIHotaW5kZXg6IDA7DQp9DQoNCi5sb2NrLXRpbWUgew0KICBwb3NpdGlvbjogcmVsYXRpdmU7DQogIHotaW5kZXg6IDE7DQogIGZvbnQtc2l6ZTogNzJweDsNCiAgZm9udC13ZWlnaHQ6IDIwMDsNCiAgY29sb3I6ICNmZmY7DQogIGxldHRlci1zcGFjaW5nOiA0cHg7DQogIHRleHQtc2hhZG93OiAwIDAgNDBweCByZ2JhKDI1NSwyNTUsMjU1LDAuMyk7DQogIG1hcmdpbi1ib3R0b206IDhweDsNCiAgZm9udC12YXJpYW50LW51bWVyaWM6IHRhYnVsYXItbnVtczsNCn0NCg0KLmxvY2stZGF0ZSB7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgei1pbmRleDogMTsNCiAgZm9udC1zaXplOiAxNXB4Ow0KICBjb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwwLjYpOw0KICBtYXJnaW4tYm90dG9tOiA0OHB4Ow0KICBsZXR0ZXItc3BhY2luZzogMnB4Ow0KfQ0KDQoubG9jay1jYXJkIHsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICB6LWluZGV4OiAxOw0KICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDgpOw0KICBiYWNrZHJvcC1maWx0ZXI6IGJsdXIoMjBweCk7DQogIC13ZWJraXQtYmFja2Ryb3AtZmlsdGVyOiBibHVyKDIwcHgpOw0KICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMTUpOw0KICBib3JkZXItcmFkaXVzOiAyNHB4Ow0KICBwYWRkaW5nOiA0MHB4IDQ4cHg7DQogIHdpZHRoOiAzNjBweDsNCiAgZGlzcGxheTogZmxleDsNCiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgYm94LXNoYWRvdzogMCAyNXB4IDYwcHggcmdiYSgwLDAsMCwwLjQpOw0KfQ0KDQouYXZhdGFyLXdyYXAgew0KICBwb3NpdGlvbjogcmVsYXRpdmU7DQogIG1hcmdpbi1ib3R0b206IDE2cHg7DQp9DQoNCi5sb2NrLWF2YXRhciB7DQogIHdpZHRoOiA4MHB4Ow0KICBoZWlnaHQ6IDgwcHg7DQogIGJvcmRlci1yYWRpdXM6IDUwJTsNCiAgYm9yZGVyOiAzcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwwLjMpOw0KICBvYmplY3QtZml0OiBjb3ZlcjsNCiAgZGlzcGxheTogYmxvY2s7DQp9DQoNCi5sb2NrLWljb24gew0KICBwb3NpdGlvbjogYWJzb2x1dGU7DQogIGJvdHRvbTogLTRweDsNCiAgcmlnaHQ6IC00cHg7DQogIGJhY2tncm91bmQ6IHJnYmEoMjU1LDI1NSwyNTUsMC4xNSk7DQogIGJvcmRlci1yYWRpdXM6IDUwJTsNCiAgd2lkdGg6IDI2cHg7DQogIGhlaWdodDogMjZweDsNCiAgZGlzcGxheTogZmxleDsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogIGZvbnQtc2l6ZTogMTNweDsNCiAgYmFja2Ryb3AtZmlsdGVyOiBibHVyKDhweCk7DQp9DQoNCi5sb2NrLXVzZXJuYW1lIHsNCiAgY29sb3I6ICNmZmY7DQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgbWFyZ2luLWJvdHRvbTogNnB4Ow0KICBsZXR0ZXItc3BhY2luZzogMXB4Ow0KfQ0KDQoubG9jay1oaW50IHsNCiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsMC41KTsNCiAgZm9udC1zaXplOiAxM3B4Ow0KICBtYXJnaW4tYm90dG9tOiAyOHB4Ow0KfQ0KDQouaW5wdXQtd3JhcCB7DQogIHdpZHRoOiAxMDAlOw0KICBkaXNwbGF5OiBmbGV4Ow0KICBhbGlnbi1pdGVtczogY2VudGVyOw0KICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuMSk7DQogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjU1LDI1NSwyNTUsMC4yKTsNCiAgYm9yZGVyLXJhZGl1czogNTBweDsNCiAgcGFkZGluZzogNHB4IDRweCA0cHggMjBweDsNCiAgdHJhbnNpdGlvbjogYm9yZGVyLWNvbG9yIDAuM3M7DQp9DQoNCi5pbnB1dC13cmFwOmZvY3VzLXdpdGhpbiB7DQogIGJvcmRlci1jb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwwLjYpOw0KICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuMTMpOw0KfQ0KDQouaW5wdXQtd3JhcC5zaGFrZSB7DQogIGFuaW1hdGlvbjogc2hha2UgMC41cyBlYXNlOw0KfQ0KDQpAa2V5ZnJhbWVzIHNoYWtlIHsNCiAgMCUsIDEwMCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoMCk7IH0NCiAgMjAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC04cHgpOyB9DQogIDQwJSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCg4cHgpOyB9DQogIDYwJSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNnB4KTsgfQ0KICA4MCUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoNnB4KTsgfQ0KfQ0KDQoubG9jay1pbnB1dCB7DQogIGZsZXg6IDE7DQogIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50Ow0KICBib3JkZXI6IG5vbmU7DQogIG91dGxpbmU6IG5vbmU7DQogIGNvbG9yOiAjZmZmOw0KICBmb250LXNpemU6IDE1cHg7DQogIHBhZGRpbmc6IDEwcHggMDsNCn0NCg0KLmxvY2staW5wdXQ6OnBsYWNlaG9sZGVyIHsNCiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsMC4zNSk7DQp9DQoNCi51bmxvY2stYnRuIHsNCiAgd2lkdGg6IDQycHg7DQogIGhlaWdodDogNDJweDsNCiAgYm9yZGVyLXJhZGl1czogNTAlOw0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjNjY3ZWVhLCAjNzY0YmEyKTsNCiAgYm9yZGVyOiBub25lOw0KICBjb2xvcjogI2ZmZjsNCiAgZm9udC1zaXplOiAxOHB4Ow0KICBjdXJzb3I6IHBvaW50ZXI7DQogIHRyYW5zaXRpb246IHRyYW5zZm9ybSAwLjJzLCBvcGFjaXR5IDAuMnM7DQogIGRpc3BsYXk6IGZsZXg7DQogIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICBmbGV4LXNocmluazogMDsNCn0NCg0KLnVubG9jay1idG46aG92ZXI6bm90KDpkaXNhYmxlZCkgew0KICB0cmFuc2Zvcm06IHNjYWxlKDEuMDgpOw0KfQ0KDQoudW5sb2NrLWJ0bjpkaXNhYmxlZCB7DQogIG9wYWNpdHk6IDAuNjsNCiAgY3Vyc29yOiBub3QtYWxsb3dlZDsNCn0NCg0KLmxvYWRpbmctZG90IHsNCiAgZm9udC1zaXplOiAxM3B4Ow0KICBsZXR0ZXItc3BhY2luZzogMXB4Ow0KfQ0KDQouZXJyb3ItbXNnIHsNCiAgbWFyZ2luLXRvcDogMTRweDsNCiAgY29sb3I6ICNmZjc2NzU7DQogIGZvbnQtc2l6ZTogMTNweDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBhbmltYXRpb246IGZhZGVJbiAwLjNzIGVhc2U7DQp9DQoNCkBrZXlmcmFtZXMgZmFkZUluIHsNCiAgZnJvbSB7IG9wYWNpdHk6IDA7IHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNHB4KTsgfQ0KICB0byAgIHsgb3BhY2l0eTogMTsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDApOyB9DQp9DQoNCi5sb2NrLWZvb3RlciB7DQogIG1hcmdpbi10b3A6IDI0cHg7DQp9DQoNCi5sb2NrLWZvb3RlciBhIHsNCiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsMC40KTsNCiAgZm9udC1zaXplOiAxM3B4Ow0KICB0ZXh0LWRlY29yYXRpb246IG5vbmU7DQogIHRyYW5zaXRpb246IGNvbG9yIDAuMnM7DQp9DQoNCi5sb2NrLWZvb3RlciBhOmhvdmVyIHsNCiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsMC44KTsNCn0NCg=="},{"version":3,"sources":["lock.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA","file":"lock.vue","sourceRoot":"src/views","sourcesContent":["<template>\r\n <div class=\"lock-container\">\r\n <!-- 动态粒子背景 -->\r\n <canvas ref=\"particleCanvas\" class=\"particle-bg\"></canvas>\r\n\r\n <!-- 时钟 -->\r\n <div class=\"lock-time\">{{ currentTime }}</div>\r\n <div class=\"lock-date\">{{ currentDate }}</div>\r\n\r\n <!-- 锁屏卡片 -->\r\n <div class=\"lock-card\">\r\n <div class=\"avatar-wrap\">\r\n <img :src=\"avatar\" class=\"lock-avatar\" @error=\"onAvatarError\" />\r\n <div class=\"lock-icon\">🔒</div>\r\n </div>\r\n <div class=\"lock-username\">{{ nickName }}</div>\r\n <div class=\"lock-hint\">系统已锁定,请输入密码解锁</div>\r\n\r\n <div class=\"input-wrap\" :class=\"{ shake: isShaking }\">\r\n <input ref=\"passwordInput\" v-model=\"password\" type=\"password\" placeholder=\"请输入登录密码\" class=\"lock-input\" @keydown.enter=\"handleUnlock\" autocomplete=\"off\" />\r\n <button class=\"unlock-btn\" @click=\"handleUnlock\" :disabled=\"loading\">\r\n <span v-if=\"!loading\">→</span>\r\n <span v-else class=\"loading-dot\">···</span>\r\n </button>\r\n </div>\r\n\r\n <div v-if=\"errorMsg\" class=\"error-msg\">{{ errorMsg }}</div>\r\n\r\n <div class=\"lock-footer\">\r\n <a href=\"/login\" @click.prevent=\"goLogin\">退出重新登录</a>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport { mapGetters } from 'vuex'\r\nimport { unlockScreen } from '@/api/login'\r\nimport defAva from '@/assets/images/profile.jpg'\r\n\r\nexport default {\r\n name: 'LockScreen',\r\n data() {\r\n return {\r\n password: '',\r\n loading: false,\r\n errorMsg: '',\r\n isShaking: false,\r\n currentTime: '',\r\n currentDate: '',\r\n timer: null,\r\n animationId: null,\r\n particles: []\r\n }\r\n },\r\n computed: {\r\n ...mapGetters(['avatar', 'nickName'])\r\n },\r\n mounted() {\r\n this.startClock()\r\n this.initParticles()\r\n this.$nextTick(() => {\r\n this.$refs.passwordInput && this.$refs.passwordInput.focus()\r\n })\r\n },\r\n beforeDestroy() {\r\n clearInterval(this.timer)\r\n cancelAnimationFrame(this.animationId)\r\n },\r\n methods: {\r\n onAvatarError(e) {\r\n e.target.src = defAva\r\n },\r\n startClock() {\r\n const update = () => {\r\n const now = new Date()\r\n const h = String(now.getHours()).padStart(2, '0')\r\n const m = String(now.getMinutes()).padStart(2, '0')\r\n const s = String(now.getSeconds()).padStart(2, '0')\r\n this.currentTime = `${h}:${m}:${s}`\r\n const days = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']\r\n this.currentDate = `${now.getFullYear()}年${now.getMonth()+1}月${now.getDate()}日 ${days[now.getDay()]}`\r\n }\r\n update()\r\n this.timer = setInterval(update, 1000)\r\n },\r\n async handleUnlock() {\r\n if (!this.password) {\r\n this.showError('请输入密码')\r\n return\r\n }\r\n this.loading = true\r\n this.errorMsg = ''\r\n try {\r\n await unlockScreen(this.password)\r\n const lockPath = this.$store.getters.lockPath // 取锁屏前的路径\r\n await this.$store.dispatch('lock/unlockScreen')\r\n this.$router.replace(lockPath)\r\n } catch (err) {\r\n const msg = err.message || err.toString()\r\n this.showError(msg)\r\n this.password = ''\r\n this.$refs.passwordInput && this.$refs.passwordInput.focus()\r\n } finally {\r\n this.loading = false\r\n }\r\n },\r\n showError(msg) {\r\n this.errorMsg = msg\r\n this.isShaking = true\r\n setTimeout(() => { this.isShaking = false }, 600)\r\n },\r\n goLogin() {\r\n this.$store.dispatch('lock/unlockScreen')\r\n this.$store.dispatch('LogOut').then(() => {\r\n this.$router.push('/login')\r\n })\r\n },\r\n // 粒子背景\r\n initParticles() {\r\n const canvas = this.$refs.particleCanvas\r\n if (!canvas) return\r\n const ctx = canvas.getContext('2d')\r\n const resize = () => {\r\n canvas.width = window.innerWidth\r\n canvas.height = window.innerHeight\r\n }\r\n resize()\r\n window.addEventListener('resize', resize)\r\n const count = 80\r\n for (let i = 0; i < count; i++) {\r\n this.particles.push({\r\n x: Math.random() * canvas.width,\r\n y: Math.random() * canvas.height,\r\n r: Math.random() * 2 + 1,\r\n dx: (Math.random() - 0.5) * 0.6,\r\n dy: (Math.random() - 0.5) * 0.6,\r\n alpha: Math.random() * 0.5 + 0.2\r\n })\r\n }\r\n const draw = () => {\r\n ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n this.particles.forEach(p => {\r\n ctx.beginPath()\r\n ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2)\r\n ctx.fillStyle = `rgba(255,255,255,${p.alpha})`\r\n ctx.fill()\r\n p.x += p.dx\r\n p.y += p.dy\r\n if (p.x < 0 || p.x > canvas.width) p.dx *= -1\r\n if (p.y < 0 || p.y > canvas.height) p.dy *= -1\r\n })\r\n // 连线\r\n for (let i = 0; i < this.particles.length; i++) {\r\n for (let j = i + 1; j < this.particles.length; j++) {\r\n const a = this.particles[i], b = this.particles[j]\r\n const dist = Math.hypot(a.x - b.x, a.y - b.y)\r\n if (dist < 120) {\r\n ctx.beginPath()\r\n ctx.moveTo(a.x, a.y)\r\n ctx.lineTo(b.x, b.y)\r\n ctx.strokeStyle = `rgba(255,255,255,${0.15 * (1 - dist / 120)})`\r\n ctx.lineWidth = 0.5\r\n ctx.stroke()\r\n }\r\n }\r\n }\r\n this.animationId = requestAnimationFrame(draw)\r\n }\r\n draw()\r\n }\r\n }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.lock-container {\r\n position: fixed;\r\n inset: 0;\r\n background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 9999;\r\n font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;\r\n overflow: hidden;\r\n}\r\n\r\n.particle-bg {\r\n position: absolute;\r\n inset: 0;\r\n z-index: 0;\r\n}\r\n\r\n.lock-time {\r\n position: relative;\r\n z-index: 1;\r\n font-size: 72px;\r\n font-weight: 200;\r\n color: #fff;\r\n letter-spacing: 4px;\r\n text-shadow: 0 0 40px rgba(255,255,255,0.3);\r\n margin-bottom: 8px;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n\r\n.lock-date {\r\n position: relative;\r\n z-index: 1;\r\n font-size: 15px;\r\n color: rgba(255,255,255,0.6);\r\n margin-bottom: 48px;\r\n letter-spacing: 2px;\r\n}\r\n\r\n.lock-card {\r\n position: relative;\r\n z-index: 1;\r\n background: rgba(255, 255, 255, 0.08);\r\n backdrop-filter: blur(20px);\r\n -webkit-backdrop-filter: blur(20px);\r\n border: 1px solid rgba(255, 255, 255, 0.15);\r\n border-radius: 24px;\r\n padding: 40px 48px;\r\n width: 360px;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n box-shadow: 0 25px 60px rgba(0,0,0,0.4);\r\n}\r\n\r\n.avatar-wrap {\r\n position: relative;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.lock-avatar {\r\n width: 80px;\r\n height: 80px;\r\n border-radius: 50%;\r\n border: 3px solid rgba(255,255,255,0.3);\r\n object-fit: cover;\r\n display: block;\r\n}\r\n\r\n.lock-icon {\r\n position: absolute;\r\n bottom: -4px;\r\n right: -4px;\r\n background: rgba(255,255,255,0.15);\r\n border-radius: 50%;\r\n width: 26px;\r\n height: 26px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 13px;\r\n backdrop-filter: blur(8px);\r\n}\r\n\r\n.lock-username {\r\n color: #fff;\r\n font-size: 18px;\r\n font-weight: 600;\r\n margin-bottom: 6px;\r\n letter-spacing: 1px;\r\n}\r\n\r\n.lock-hint {\r\n color: rgba(255,255,255,0.5);\r\n font-size: 13px;\r\n margin-bottom: 28px;\r\n}\r\n\r\n.input-wrap {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n background: rgba(255,255,255,0.1);\r\n border: 1px solid rgba(255,255,255,0.2);\r\n border-radius: 50px;\r\n padding: 4px 4px 4px 20px;\r\n transition: border-color 0.3s;\r\n}\r\n\r\n.input-wrap:focus-within {\r\n border-color: rgba(255,255,255,0.6);\r\n background: rgba(255,255,255,0.13);\r\n}\r\n\r\n.input-wrap.shake {\r\n animation: shake 0.5s ease;\r\n}\r\n\r\n@keyframes shake {\r\n 0%, 100% { transform: translateX(0); }\r\n 20% { transform: translateX(-8px); }\r\n 40% { transform: translateX(8px); }\r\n 60% { transform: translateX(-6px); }\r\n 80% { transform: translateX(6px); }\r\n}\r\n\r\n.lock-input {\r\n flex: 1;\r\n background: transparent;\r\n border: none;\r\n outline: none;\r\n color: #fff;\r\n font-size: 15px;\r\n padding: 10px 0;\r\n}\r\n\r\n.lock-input::placeholder {\r\n color: rgba(255,255,255,0.35);\r\n}\r\n\r\n.unlock-btn {\r\n width: 42px;\r\n height: 42px;\r\n border-radius: 50%;\r\n background: linear-gradient(135deg, #667eea, #764ba2);\r\n border: none;\r\n color: #fff;\r\n font-size: 18px;\r\n cursor: pointer;\r\n transition: transform 0.2s, opacity 0.2s;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n}\r\n\r\n.unlock-btn:hover:not(:disabled) {\r\n transform: scale(1.08);\r\n}\r\n\r\n.unlock-btn:disabled {\r\n opacity: 0.6;\r\n cursor: not-allowed;\r\n}\r\n\r\n.loading-dot {\r\n font-size: 13px;\r\n letter-spacing: 1px;\r\n}\r\n\r\n.error-msg {\r\n margin-top: 14px;\r\n color: #ff7675;\r\n font-size: 13px;\r\n text-align: center;\r\n animation: fadeIn 0.3s ease;\r\n}\r\n\r\n@keyframes fadeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.lock-footer {\r\n margin-top: 24px;\r\n}\r\n\r\n.lock-footer a {\r\n color: rgba(255,255,255,0.4);\r\n font-size: 13px;\r\n text-decoration: none;\r\n transition: color 0.2s;\r\n}\r\n\r\n.lock-footer a:hover {\r\n color: rgba(255,255,255,0.8);\r\n}\r\n</style>\r\n"]}]}