| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <template>
- <LoginLayout>
- <!-- 背景 -->
- <template #background>
- <div class="login-bg"></div>
- <!-- 漂浮闪烁点 -->
- <div class="spark-layer" aria-hidden="true">
- <span v-for="d in dots" :key="d.id" class="spark" :style="dotStyle(d)" />
- </div>
- </template>
- <template #main>
- <BottomDock mode="ellipse" :auto-hide="false" :custom-class="['dock-style']" :auto-rotate="true"></BottomDock>
- </template>
- </LoginLayout>
- </template>
- <script>
- import LoginLayout from "@/layouts/LoginLayout.vue";
- import BottomDock from "@/components/ui/BottomDock.vue";
- export default {
- name: "MainPage",
- components: {
- LoginLayout,
- BottomDock
- },
- created() {
- },
- data() {
- return {
- // 亮点
- dots: [],
- };
- },
- mounted() {
- this.updateScale();
- window.addEventListener("resize", this.updateScale, { passive: true });
- this.initDots();
- },
- beforeDestroy() {
- window.removeEventListener("resize", this.updateScale);
- },
- methods: {
- updateScale() {
- const w = window.innerWidth || this.baseW;
- const h = window.innerHeight || this.baseH;
- // 取 min 保证不裁切(大屏常见)
- this.scale = Math.min(w / this.baseW, h / this.baseH);
- // 写到 css 变量,方便 calc(var(--s) * xxxpx)
- this.$el && this.$el.style.setProperty("--s", this.scale.toFixed(6));
- },
- // ---------- 闪烁点 ----------
- initDots() {
- const count = 50;
- const arr = [];
- for (let i = 0; i < count; i++) {
- arr.push({
- id: i,
- x: 18 + Math.random() * 64, // 百分比布局,适配任意屏幕
- y: 22 + Math.random() * 56,
- r: 1.2 + Math.random() * 2.8, // 半径
- a: 0.45 + Math.random() * 0.55,
- d: Math.random() * 2.8, // delay
- t: 1.8 + Math.random() * 2.6, // duration
- });
- }
- this.dots = arr;
- },
- dotStyle(d) {
- return {
- left: d.x + "%",
- top: d.y + "%",
- width: `${d.r * 4}px`,
- height: `${d.r * 4}px`,
- opacity: d.a,
- animationDelay: `${d.d}s`,
- animationDuration: `${d.t}s`,
- };
- },
- }
- }
- </script>
- <style scoped>
- .dock-style {
- left: 0;
- bottom: unset !important;
- height: 100%;
- margin: auto 0;
- border-radius: calc(var(--s) * 1.125rem);
- background: linear-gradient(180deg, rgba(10, 35, 70, .18), rgba(0, 0, 0, .08));
- box-shadow: 0 0 calc(var(--s) * 1.625rem) rgba(0, 140, 255, .08) inset;
- backdrop-filter: blur(.125rem);
- }
- .dock-style ::v-deep .right-arrow {
- margin-left: 100px;
- }
- .dock-style ::v-deep .left-arrow {
- margin-right: 100px;
- }
- .main-page {
- position: relative;
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- --s: 1;
- color: #d9efff;
- user-select: none;
- }
- .login-bg {
- background: url('@/assets/images/main-background.png') no-repeat center/cover;
- width: 100%;
- height: 100%;
- filter: saturate(1.05) contrast(1.03);
- }
- /* 闪烁亮点 */
- .spark-layer {
- position: absolute;
- inset: 0;
- z-index: 4;
- pointer-events: none;
- width: 100%;
- height: 100%;
- }
- .spark {
- position: absolute;
- border-radius: 999px;
- background: radial-gradient(circle, rgba(140, 235, 255, .95), rgba(140, 235, 255, 0) 70%);
- animation-name: twinkle;
- animation-timing-function: ease-in-out;
- animation-iteration-count: infinite;
- }
- @keyframes twinkle {
- 0% {
- transform: translateZ(0) scale(.7);
- opacity: .22;
- }
- 50% {
- transform: translateZ(0) scale(1.25);
- opacity: .9;
- }
- 100% {
- transform: translateZ(0) scale(.7);
- opacity: .22;
- }
- }
- </style>
|