feat: add loading animation

This commit is contained in:
JOJO 2025-11-25 23:46:30 +08:00
parent c246e31e8b
commit e8411affc1
2 changed files with 201 additions and 7 deletions

View File

@ -1,12 +1,39 @@
<template>
<AppShell :download-file="downloadFile" :download-folder="downloadFolder">
<div
v-if="!isConnected && messages.length === 0"
class="app-loading-state"
style="text-align: center; padding: 50px;"
>
<h2>正在连接服务器...</h2>
<p>如果长时间无响应请刷新页面</p>
<div v-if="!isConnected && messages.length === 0" class="app-loading-state">
<div class="loading-animation" aria-hidden="true">
<!-- From Uiverse.io by Nawsome -->
<div class="boxes">
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<div class="loading-copy">
<h2>加载中...</h2>
<p>正在连接服务器请稍候</p>
</div>
</div>
<template v-else>

View File

@ -548,3 +548,170 @@
border-left: 1px solid var(--claude-border);
padding: 0 0 0 0;
}
.app-loading-state {
min-height: calc(var(--app-viewport, 100vh) - 160px);
padding: 60px 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 28px;
text-align: center;
color: var(--claude-text);
}
.loading-animation {
display: flex;
align-items: center;
justify-content: center;
}
.loading-copy {
margin-top: 48px;
}
.loading-copy h2 {
margin: 0;
font-size: 24px;
font-weight: 600;
}
.loading-copy p {
margin: 6px 0 0;
color: var(--claude-text-secondary);
}
.boxes {
--size: 34px;
--duration: 900ms;
--box-primary: var(--claude-accent);
--box-secondary: var(--claude-accent-strong, #d07b4c);
--box-tertiary: #f8d7c0;
height: calc(var(--size) * 2);
width: calc(var(--size) * 3);
position: relative;
transform-style: preserve-3d;
transform-origin: 50% 50%;
margin-top: calc(var(--size) * -1.5);
transform: rotateX(60deg) rotateZ(45deg) rotateY(0deg) translateZ(0px);
}
.boxes .box {
width: var(--size);
height: var(--size);
top: 0;
left: 0;
position: absolute;
transform-style: preserve-3d;
}
.boxes .box:nth-child(1) {
transform: translate(100%, 0);
animation: box1 var(--duration) linear infinite;
}
.boxes .box:nth-child(2) {
transform: translate(0, 100%);
animation: box2 var(--duration) linear infinite;
}
.boxes .box:nth-child(3) {
transform: translate(100%, 100%);
animation: box3 var(--duration) linear infinite;
}
.boxes .box:nth-child(4) {
transform: translate(200%, 0);
animation: box4 var(--duration) linear infinite;
}
.boxes .box > div {
--background: var(--box-primary);
--top: auto;
--right: auto;
--bottom: auto;
--left: auto;
--translateZ: calc(var(--size) / 2);
--rotateY: 0deg;
--rotateX: 0deg;
position: absolute;
width: 100%;
height: 100%;
background: var(--background);
top: var(--top);
right: var(--right);
bottom: var(--bottom);
left: var(--left);
border-radius: 6px;
transform: rotateY(var(--rotateY)) rotateX(var(--rotateX)) translateZ(var(--translateZ));
}
.boxes .box > div:nth-child(1) {
--top: 0;
--left: 0;
}
.boxes .box > div:nth-child(2) {
--background: var(--box-secondary);
--right: 0;
--rotateY: 90deg;
}
.boxes .box > div:nth-child(3) {
--background: var(--box-tertiary);
--rotateX: -90deg;
}
.boxes .box > div:nth-child(4) {
--background: rgba(255, 255, 255, 0.95);
--top: 0;
--left: 0;
--translateZ: calc(var(--size) * 3 * -1);
}
@keyframes box1 {
0%, 50% {
transform: translate(100%, 0);
}
100% {
transform: translate(200%, 0);
}
}
@keyframes box2 {
0% {
transform: translate(0, 100%);
}
50% {
transform: translate(0, 0);
}
100% {
transform: translate(100%, 0);
}
}
@keyframes box3 {
0%, 50% {
transform: translate(100%, 100%);
}
100% {
transform: translate(0, 100%);
}
}
@keyframes box4 {
0% {
transform: translate(200%, 0);
}
50% {
transform: translate(200%, 100%);
}
100% {
transform: translate(100%, 100%);
}
}