优化个人中心与界面交互

This commit is contained in:
Cheng Zhou
2026-06-11 09:09:17 +08:00
parent 84e55af8fe
commit b7484c8e01
15 changed files with 572 additions and 141 deletions
+11 -2
View File
@@ -382,8 +382,17 @@ watch(
}
.legend-dot.active {
border-color: var(--ctms-primary);
box-shadow: 0 0 0 2px rgba(63, 93, 117, 0.18);
position: relative;
border: 3px solid #2f5f86;
box-shadow: 0 0 0 3px rgba(47, 95, 134, 0.14);
}
.legend-dot.active::after {
content: "";
position: absolute;
inset: 2px;
border-radius: inherit;
background: #2f5f86;
}
.legend-dot.pending {
@@ -100,7 +100,7 @@ const connectorClass = (status: StageStatus) => `connector-${status.toLowerCase(
align-items: flex-start;
gap: 8px;
overflow-x: auto;
padding-bottom: 4px;
padding: 10px 0 4px;
width: 100%;
min-width: 0;
}
@@ -125,7 +125,7 @@ const connectorClass = (status: StageStatus) => `connector-${status.toLowerCase(
height: 2px;
background-color: var(--ctms-border-color);
border-radius: 999px;
margin-top: 6px;
margin-top: 8px;
}
.stage-connector::after {
@@ -145,7 +145,9 @@ const connectorClass = (status: StageStatus) => `connector-${status.toLowerCase(
}
.connector-in_progress {
background: linear-gradient(90deg, var(--ctms-primary), rgba(63, 93, 117, 0.3));
height: 3px;
background: linear-gradient(90deg, #2f5f86 0%, rgba(47, 95, 134, 0.42) 68%, rgba(47, 95, 134, 0.14) 100%);
box-shadow: 0 2px 8px rgba(47, 95, 134, 0.18);
}
.connector-blocked {
@@ -158,8 +160,10 @@ const connectorClass = (status: StageStatus) => `connector-${status.toLowerCase(
}
.connector-in_progress::after {
border-top-color: var(--ctms-primary);
border-right-color: var(--ctms-primary);
width: 7px;
height: 7px;
border-top-color: #2f5f86;
border-right-color: #2f5f86;
}
.connector-blocked::after {
@@ -0,0 +1,32 @@
import { describe, expect, it } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const readStageNode = () => readFileSync(resolve(__dirname, "./StageNode.vue"), "utf8");
const readCenterProgressRow = () => readFileSync(resolve(__dirname, "./CenterProgressRow.vue"), "utf8");
const readProjectOverview = () => readFileSync(resolve(__dirname, "../ProjectOverview.vue"), "utf8");
describe("project overview stage progress styling", () => {
it("makes the in-progress stage visually distinct from pending stages", () => {
const source = readStageNode();
expect(source).toContain(".stage-in_progress .stage-dot");
expect(source).toContain("border: 3px solid #2f5f86");
expect(source).toContain(".stage-in_progress .stage-dot::after");
expect(source).toContain(".stage-in_progress .stage-dot::before");
expect(source).toContain("animation: progress-halo");
expect(source).toContain(".stage-in_progress .stage-label");
expect(source).toContain("font-weight: 800");
});
it("highlights the active connector and legend consistently", () => {
const rowSource = readCenterProgressRow();
const overviewSource = readProjectOverview();
expect(rowSource).toContain(".connector-in_progress");
expect(rowSource).toContain("height: 3px");
expect(rowSource).toContain("linear-gradient(90deg, #2f5f86");
expect(overviewSource).toContain(".legend-dot.active::after");
expect(overviewSource).toContain("background: #2f5f86");
});
});
@@ -44,11 +44,14 @@ const statusClass = computed(() => `stage-${props.status.toLowerCase()}`);
align-items: center;
gap: 5px;
min-width: 64px;
position: relative;
padding-top: 2px;
}
.stage-dot {
width: 14px;
height: 14px;
position: relative;
width: 15px;
height: 15px;
border-radius: 50%;
border: 2px solid var(--ctms-border-color);
background-color: #ffffff;
@@ -60,7 +63,7 @@ const statusClass = computed(() => `stage-${props.status.toLowerCase()}`);
color: var(--ctms-text-secondary);
text-align: center;
white-space: nowrap;
transition: color 0.2s ease;
transition: color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
.stage-date {
@@ -80,15 +83,55 @@ const statusClass = computed(() => `stage-${props.status.toLowerCase()}`);
}
.stage-in_progress .stage-dot {
border-color: var(--ctms-primary);
box-shadow: 0 0 0 3px rgba(63, 93, 117, 0.15);
width: 18px;
height: 18px;
border: 3px solid #2f5f86;
background-color: #ffffff;
animation: pulse-ring 2s ease-in-out infinite;
box-shadow:
0 0 0 4px rgba(47, 95, 134, 0.14),
0 6px 14px rgba(47, 95, 134, 0.22);
animation: progress-ring 1.8s ease-in-out infinite;
}
@keyframes pulse-ring {
0%, 100% { box-shadow: 0 0 0 3px rgba(63, 93, 117, 0.15); }
50% { box-shadow: 0 0 0 5px rgba(63, 93, 117, 0.08); }
.stage-in_progress .stage-dot::after {
content: "";
position: absolute;
inset: 3px;
border-radius: inherit;
background: #2f5f86;
}
.stage-in_progress .stage-dot::before {
content: "";
position: absolute;
inset: -8px;
border-radius: inherit;
border: 1px solid rgba(47, 95, 134, 0.24);
animation: progress-halo 1.8s ease-out infinite;
}
@keyframes progress-ring {
0%, 100% {
box-shadow:
0 0 0 4px rgba(47, 95, 134, 0.14),
0 6px 14px rgba(47, 95, 134, 0.22);
}
50% {
box-shadow:
0 0 0 6px rgba(47, 95, 134, 0.08),
0 8px 18px rgba(47, 95, 134, 0.26);
}
}
@keyframes progress-halo {
0% {
opacity: 0.65;
transform: scale(0.82);
}
100% {
opacity: 0;
transform: scale(1.25);
}
}
.stage-not_started .stage-dot {
@@ -108,8 +151,13 @@ const statusClass = computed(() => `stage-${props.status.toLowerCase()}`);
}
.stage-in_progress .stage-label {
color: var(--ctms-primary);
font-weight: 600;
margin-top: 1px;
padding: 2px 8px;
border-radius: 999px;
color: #244966;
background: rgba(47, 95, 134, 0.1);
box-shadow: inset 0 0 0 1px rgba(47, 95, 134, 0.14);
font-weight: 800;
}
.stage-blocked .stage-label {