Files
vueadmin/src/layouts/other/404.vue
T
2026-01-14 14:49:08 +08:00

402 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goHome = () => {
router.push('/')
}
const goBack = () => {
router.back()
}
</script>
<template>
<div class="not-found">
<div class="content-wrapper">
<div class="error-code">404</div>
<div class="error-text">
<h1>页面未找到</h1>
<p>抱歉您访问的页面不存在或已被移除</p>
</div>
<div class="error-illustration">
<div class="planet"></div>
<div class="star star-1"></div>
<div class="star star-2"></div>
<div class="star star-3"></div>
<div class="rocket">
<div class="rocket-body"></div>
<div class="rocket-window"></div>
<div class="rocket-flame"></div>
</div>
</div>
<div class="action-buttons">
<button class="btn btn-primary" @click="goHome">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
返回首页
</button>
<button class="btn btn-secondary" @click="goBack">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 12H5M12 19l-7-7 7-7"></path>
</svg>
返回上一页
</button>
</div>
</div>
</div>
</template>
<style scoped>
.not-found {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0c1929 0%, #1a237e 50%, #0d47a1 100%);
padding: 20px;
position: relative;
overflow: hidden;
}
/* 星空背景 */
.not-found::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(2px 2px at 20px 30px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(2px 2px at 40px 70px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(1px 1px at 90px 40px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(2px 2px at 160px 120px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(1px 1px at 230px 80px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(2px 2px at 300px 150px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(1px 1px at 370px 200px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(2px 2px at 450px 50px, #ffffff, rgba(0, 0, 0, 0)),
radial-gradient(1px 1px at 520px 180px, #ffffff, rgba(0, 0, 0, 0));
background-size: 550px 250px;
animation: stars 50s linear infinite;
opacity: 0.3;
}
@keyframes stars {
0% {
background-position: 0 0;
}
100% {
background-position: 550px 250px;
}
}
.content-wrapper {
text-align: center;
position: relative;
z-index: 1;
max-width: 600px;
animation: fadeIn 0.8s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.error-code {
font-size: 180px;
font-weight: 900;
background: linear-gradient(135deg, #00d4ff 0%, #7c4dff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1;
margin-bottom: 20px;
position: relative;
animation: float 3s ease-in-out infinite;
text-shadow: 0 0 60px rgba(0, 212, 255, 0.5);
}
@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
.error-text {
margin-bottom: 40px;
}
.error-text h1 {
font-size: 36px;
font-weight: 700;
color: white;
margin: 0 0 12px;
letter-spacing: 1px;
}
.error-text p {
font-size: 16px;
color: rgba(255, 255, 255, 0.7);
margin: 0;
}
.error-illustration {
position: relative;
width: 200px;
height: 200px;
margin: 0 auto 40px;
}
.planet {
width: 120px;
height: 120px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow:
0 0 60px rgba(102, 126, 234, 0.6),
inset -10px -10px 20px rgba(0, 0, 0, 0.2);
animation: rotatePlanet 20s linear infinite;
}
.planet::before {
content: '';
position: absolute;
width: 160px;
height: 20px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotateX(75deg);
}
.planet::after {
content: '';
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.2);
top: 20%;
left: 30%;
}
@keyframes rotatePlanet {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
.star {
position: absolute;
background: white;
border-radius: 50%;
animation: twinkle 2s ease-in-out infinite;
}
.star-1 {
width: 6px;
height: 6px;
top: 20%;
right: 10%;
animation-delay: 0s;
}
.star-2 {
width: 4px;
height: 4px;
top: 60%;
left: 5%;
animation-delay: 0.5s;
}
.star-3 {
width: 5px;
height: 5px;
bottom: 10%;
right: 20%;
animation-delay: 1s;
}
@keyframes twinkle {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.3;
transform: scale(0.8);
}
}
.rocket {
position: absolute;
top: 30%;
right: 0;
animation: flyRocket 2s ease-in-out infinite;
}
.rocket-body {
width: 20px;
height: 40px;
background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
position: relative;
}
.rocket-window {
width: 10px;
height: 10px;
background: white;
border-radius: 50%;
position: absolute;
top: 12px;
left: 50%;
transform: translateX(-50%);
box-shadow: inset -2px -2px 4px rgba(0, 0, 0, 0.2);
}
.rocket-flame {
width: 12px;
height: 20px;
background: linear-gradient(to bottom, #feca57, #ff6b6b, transparent);
position: absolute;
bottom: -18px;
left: 50%;
transform: translateX(-50%);
border-radius: 50% 50% 20% 20%;
animation: flame 0.3s ease-in-out infinite alternate;
}
@keyframes flame {
0% {
height: 20px;
opacity: 1;
}
100% {
height: 30px;
opacity: 0.8;
}
}
@keyframes flyRocket {
0%,
100% {
transform: translateY(0) rotate(-15deg);
}
50% {
transform: translateY(-15px) rotate(-10deg);
}
}
.action-buttons {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: flex;
align-items: center;
gap: 8px;
padding: 14px 28px;
border: none;
border-radius: 12px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
letter-spacing: 0.5px;
}
.btn svg {
flex-shrink: 0;
}
.btn-primary {
background: linear-gradient(135deg, #00d4ff 0%, #7c4dff 100%);
color: white;
box-shadow: 0 4px 15px rgba(0, 212, 255, 0.4);
}
.btn-primary:hover {
transform: translateY(-3px);
box-shadow: 0 6px 25px rgba(0, 212, 255, 0.6);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: white;
border: 2px solid rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10px);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.5);
transform: translateY(-3px);
}
@media (max-width: 768px) {
.error-code {
font-size: 120px;
}
.error-text h1 {
font-size: 28px;
}
.error-text p {
font-size: 14px;
}
.error-illustration {
width: 150px;
height: 150px;
}
.action-buttons {
flex-direction: column;
}
.btn {
width: 100%;
justify-content: center;
}
}
</style>