fix: 优化顶部导航栏布局与工作台摘要展示并清理旧票据数据
This commit is contained in:
@@ -73,9 +73,9 @@
|
||||
.insight-metric-row,
|
||||
.insight-profile-card {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
grid-template-columns: 18px minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
min-height: 0;
|
||||
padding: 7px 9px;
|
||||
border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.12);
|
||||
@@ -102,6 +102,15 @@
|
||||
rgba(var(--theme-primary-rgb, 58, 124, 165), 0.04);
|
||||
}
|
||||
|
||||
.insight-metric-icon,
|
||||
.insight-profile-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--workbench-muted);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.insight-metric-label,
|
||||
.insight-profile-label {
|
||||
min-width: 0;
|
||||
@@ -136,19 +145,21 @@
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.insight-metric-row--amount .insight-metric-icon,
|
||||
.insight-metric-row--amount .insight-metric-value {
|
||||
color: var(--workbench-primary-active);
|
||||
}
|
||||
|
||||
.insight-metric-row--warning .insight-metric-icon,
|
||||
.insight-metric-row--warning .insight-metric-value {
|
||||
color: var(--warning);
|
||||
}
|
||||
|
||||
.insight-metric-row--info .insight-metric-icon,
|
||||
.insight-metric-row--info .insight-metric-value {
|
||||
color: var(--workbench-chart-blue);
|
||||
}
|
||||
|
||||
.insight-profile-icon,
|
||||
.insight-profile-hint {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -505,12 +505,19 @@
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.progress-identity,
|
||||
.progress-result {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.progress-identity strong,
|
||||
.progress-result strong {
|
||||
margin-bottom: 2px;
|
||||
|
||||
overflow: hidden;
|
||||
color: var(--workbench-ink);
|
||||
font-size: 13px;
|
||||
font-weight: 850;
|
||||
font-weight: bold;
|
||||
line-height: 1.25;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -573,24 +580,29 @@
|
||||
}
|
||||
|
||||
.progress-status--warning {
|
||||
background: var(--warning-soft);
|
||||
color: var(--warning);
|
||||
background: var(--warning-soft, #fff7ed);
|
||||
color: var(--warning, #ea580c);
|
||||
}
|
||||
|
||||
.progress-status--success {
|
||||
background: var(--workbench-primary-soft);
|
||||
color: var(--workbench-primary-active);
|
||||
background: var(--workbench-primary-soft, #eaf4fa);
|
||||
color: var(--workbench-primary-active, #255b7d);
|
||||
}
|
||||
|
||||
.progress-status--muted {
|
||||
background: var(--info-soft);
|
||||
color: var(--workbench-muted);
|
||||
background: var(--info-soft, #f1f5f9);
|
||||
color: var(--workbench-muted, #64748b);
|
||||
}
|
||||
|
||||
.progress-status--danger {
|
||||
background: var(--danger-soft, #fef2f2);
|
||||
color: var(--danger, #dc2626);
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(78px, 0.42fr) minmax(132px, 0.74fr) minmax(84px, 0.42fr) minmax(260px, 1.28fr) minmax(92px, auto);
|
||||
grid-template-columns: minmax(118px, 0.58fr) minmax(132px, 0.74fr) minmax(84px, 0.42fr) minmax(260px, 1.28fr) minmax(92px, auto);
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
@@ -638,6 +650,54 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.progress-time-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.expense-type-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.expense-type-icon--blue {
|
||||
background: color-mix(in srgb, var(--workbench-primary, #3a7ca5) 12%, #ffffff);
|
||||
color: var(--workbench-primary, #3a7ca5);
|
||||
}
|
||||
|
||||
.expense-type-icon--amber {
|
||||
background: color-mix(in srgb, var(--workbench-chart-amber, #b58b4c) 12%, #ffffff);
|
||||
color: var(--workbench-chart-amber, #b58b4c);
|
||||
}
|
||||
|
||||
.expense-type-icon--emerald {
|
||||
background: color-mix(in srgb, #10b981 12%, #ffffff);
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.expense-type-icon--violet {
|
||||
background: color-mix(in srgb, #8b5cf6 12%, #ffffff);
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.expense-type-icon--cyan {
|
||||
background: color-mix(in srgb, #06b6d4 12%, #ffffff);
|
||||
color: #06b6d4;
|
||||
}
|
||||
|
||||
.expense-type-icon--muted {
|
||||
background: var(--info-soft, #f1f5f9);
|
||||
color: var(--workbench-muted, #64748b);
|
||||
}
|
||||
|
||||
.progress-time,
|
||||
.progress-identity,
|
||||
.progress-type,
|
||||
@@ -649,6 +709,7 @@
|
||||
|
||||
.progress-time {
|
||||
color: var(--workbench-muted);
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.progress-time time {
|
||||
@@ -669,6 +730,16 @@
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.progress-time .time-capsule {
|
||||
margin-top: 4px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 999px;
|
||||
background: var(--danger-soft, #fef2f2);
|
||||
color: var(--danger, #dc2626);
|
||||
font-weight: 850;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.progress-result {
|
||||
justify-items: end;
|
||||
}
|
||||
|
||||
@@ -408,115 +408,168 @@
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.notification-wrap.is-open .notification-btn {
|
||||
border: 1px solid var(--theme-primary-light-5);
|
||||
background: var(--theme-primary-light-9);
|
||||
color: var(--theme-primary-active);
|
||||
}
|
||||
|
||||
.notification-btn {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 180ms var(--ease),
|
||||
background 180ms var(--ease),
|
||||
color 180ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 0;
|
||||
min-width: 15px;
|
||||
height: 15px;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 999px;
|
||||
background: #ef4444;
|
||||
border-radius: 4px;
|
||||
background: #dc2626;
|
||||
color: #fff;
|
||||
font-size: 9px;
|
||||
font-weight: 850;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
box-shadow: 0 5px 10px rgba(239, 68, 68, .22);
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.notification-panel-enter-active,
|
||||
.notification-panel-leave-active {
|
||||
transition:
|
||||
opacity 220ms var(--ease),
|
||||
transform 220ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-panel-enter-from,
|
||||
.notification-panel-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-6px);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.notification-panel-enter-active,
|
||||
.notification-panel-leave-active {
|
||||
transition-duration: 1ms;
|
||||
}
|
||||
|
||||
.notification-panel-enter-from,
|
||||
.notification-panel-leave-to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-popover {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
right: -8px;
|
||||
top: calc(100% + 8px);
|
||||
right: 0;
|
||||
z-index: 60;
|
||||
width: min(392px, calc(100vw - 32px));
|
||||
width: min(380px, calc(100vw - 32px));
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid #e5edf5;
|
||||
grid-template-rows: auto auto minmax(0, 1fr);
|
||||
gap: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid #d7e0ea;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
box-shadow:
|
||||
0 18px 46px rgba(15, 23, 42, 0.14),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.92);
|
||||
box-shadow: 0 16px 40px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
.notification-popover::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 18px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-top: 1px solid #e5edf5;
|
||||
border-left: 1px solid #e5edf5;
|
||||
background: #fff;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.notification-head,
|
||||
.notification-tabs {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: block;
|
||||
height: 3px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--theme-primary-active) 0%,
|
||||
var(--theme-primary-light-3, #7eb3d4) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.notification-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding-bottom: 10px;
|
||||
gap: 12px;
|
||||
padding: 12px 14px 10px;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
background: #fafbfd;
|
||||
}
|
||||
|
||||
.notification-head-brand {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.notification-head-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex: 0 0 auto;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 1px solid var(--theme-primary-light-6);
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: var(--theme-primary-active);
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.notification-head-copy {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.notification-head strong {
|
||||
color: #0f172a;
|
||||
font-size: 15px;
|
||||
font-weight: 850;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.notification-head small {
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 650;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notification-head-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 4px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.notification-clear-btn {
|
||||
height: 26px;
|
||||
padding: 0 9px;
|
||||
border: 1px solid #dbe4ee;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: #475569;
|
||||
background: transparent;
|
||||
color: var(--theme-primary-active);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
font-weight: 750;
|
||||
white-space: nowrap;
|
||||
transition:
|
||||
background 160ms var(--ease),
|
||||
color 160ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-clear-btn:hover:not(:disabled) {
|
||||
border-color: var(--theme-primary-light-5);
|
||||
background: var(--theme-primary-light-9);
|
||||
color: var(--theme-primary-active);
|
||||
}
|
||||
|
||||
.notification-clear-btn:disabled {
|
||||
@@ -525,111 +578,92 @@
|
||||
}
|
||||
|
||||
.notification-close-btn {
|
||||
position: relative;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
border: 1px solid transparent;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.notification-close-btn span,
|
||||
.notification-close-btn span::before,
|
||||
.notification-close-btn span::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.notification-close-btn span {
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.notification-close-btn span::before,
|
||||
.notification-close-btn span::after {
|
||||
content: "";
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 12px;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
background: currentColor;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.notification-close-btn span::before {
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.notification-close-btn span::after {
|
||||
transform: translate(-50%, -50%) rotate(-45deg);
|
||||
font-size: 18px;
|
||||
transition:
|
||||
background 160ms var(--ease),
|
||||
color 160ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-close-btn:hover {
|
||||
border-color: #e2e8f0;
|
||||
background: #f8fafc;
|
||||
background: #eef2f7;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.notification-tabs {
|
||||
gap: 6px;
|
||||
padding: 3px;
|
||||
border: 1px solid #edf2f7;
|
||||
border-radius: 4px;
|
||||
background: #f8fafc;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
padding: 0 14px;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.notification-tabs button {
|
||||
position: relative;
|
||||
flex: 1 1 0;
|
||||
height: 30px;
|
||||
height: 38px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
border-radius: 3px;
|
||||
border: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
font-size: 13px;
|
||||
font-weight: 750;
|
||||
transition:
|
||||
color 180ms var(--ease),
|
||||
border-color 180ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-tabs button em {
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 6px;
|
||||
border-radius: 999px;
|
||||
background: #e2e8f0;
|
||||
border-radius: 4px;
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
font-style: normal;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
transition:
|
||||
background 180ms var(--ease),
|
||||
color 180ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-tabs button.active {
|
||||
background: #fff;
|
||||
color: var(--theme-primary-active);
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
|
||||
border-bottom-color: var(--theme-primary-active);
|
||||
}
|
||||
|
||||
.notification-tabs button.active em {
|
||||
background: var(--theme-primary-light-8);
|
||||
background: var(--theme-primary-light-9);
|
||||
color: var(--theme-primary-active);
|
||||
}
|
||||
|
||||
.notification-list {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
max-height: 244px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 280px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-right: 2px;
|
||||
padding: 6px 0;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #cbd5e1 transparent;
|
||||
scrollbar-color: #cbd5e1 #f8fafc;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar {
|
||||
@@ -637,45 +671,56 @@
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar-thumb {
|
||||
border-radius: 999px;
|
||||
border-radius: 4px;
|
||||
background: #cbd5e1;
|
||||
}
|
||||
|
||||
.notification-row {
|
||||
display: grid;
|
||||
grid-template-columns: 34px minmax(0, 1fr) 16px;
|
||||
align-items: start;
|
||||
grid-template-columns: 36px minmax(0, 1fr) 14px;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-height: 72px;
|
||||
padding: 10px;
|
||||
border: 1px solid #edf2f7;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
min-height: 0;
|
||||
padding: 10px 14px;
|
||||
border: 0;
|
||||
border-left: 3px solid transparent;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
transition:
|
||||
border-color 160ms var(--ease),
|
||||
background 160ms var(--ease),
|
||||
box-shadow 160ms var(--ease);
|
||||
background 180ms var(--ease),
|
||||
border-color 180ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-row + .notification-row {
|
||||
border-top: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.notification-row.unread {
|
||||
border-left-color: var(--theme-primary-active);
|
||||
background: linear-gradient(90deg, var(--theme-primary-light-9) 0%, #fff 42%);
|
||||
}
|
||||
|
||||
.notification-row:hover {
|
||||
border-color: var(--theme-primary-light-5);
|
||||
background: #f8fbff;
|
||||
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.08);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.notification-row.unread:hover {
|
||||
background: linear-gradient(90deg, var(--theme-primary-light-8) 0%, #f8fafc 48%);
|
||||
}
|
||||
|
||||
.notification-type-icon {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 1px solid var(--theme-primary-light-6);
|
||||
border-radius: 4px;
|
||||
background: var(--theme-primary-light-9);
|
||||
background: #fff;
|
||||
color: var(--theme-primary-active);
|
||||
font-size: 18px;
|
||||
}
|
||||
@@ -707,7 +752,7 @@
|
||||
.notification-copy {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.notification-copy strong,
|
||||
@@ -728,7 +773,7 @@
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 850;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.notification-title-line b {
|
||||
@@ -738,17 +783,19 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 6px;
|
||||
border-radius: 999px;
|
||||
background: #ef4444;
|
||||
padding: 0 5px;
|
||||
border-radius: 4px;
|
||||
background: #dc2626;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.notification-copy small {
|
||||
color: #475569;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.notification-meta {
|
||||
@@ -764,25 +811,54 @@
|
||||
color: #94a3b8;
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notification-row > .mdi {
|
||||
align-self: center;
|
||||
color: #94a3b8;
|
||||
font-size: 16px;
|
||||
.notification-row-arrow {
|
||||
color: #cbd5e1;
|
||||
font-size: 18px;
|
||||
transition: color 160ms var(--ease), transform 160ms var(--ease);
|
||||
}
|
||||
|
||||
.notification-row:hover .notification-row-arrow {
|
||||
color: var(--theme-primary-active);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.notification-empty {
|
||||
min-height: 112px;
|
||||
min-height: 148px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
gap: 8px;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
justify-items: center;
|
||||
gap: 6px;
|
||||
padding: 24px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.notification-empty .mdi {
|
||||
font-size: 24px;
|
||||
.notification-empty-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-bottom: 4px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 4px;
|
||||
background: #f8fafc;
|
||||
color: #94a3b8;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.notification-empty strong {
|
||||
color: #334155;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.notification-empty > span:last-child {
|
||||
max-width: 220px;
|
||||
color: #94a3b8;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.company-switcher {
|
||||
|
||||
@@ -291,6 +291,7 @@
|
||||
.receipt-all-field-grid {
|
||||
max-height: clamp(360px, 60vh, 640px);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 10px;
|
||||
padding-right: 4px;
|
||||
overflow-y: auto;
|
||||
@@ -666,6 +667,7 @@
|
||||
}
|
||||
|
||||
.receipt-static-grid,
|
||||
.receipt-all-field-grid,
|
||||
.receipt-data-list.association {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@@ -205,18 +205,23 @@
|
||||
:class="{ 'has-long-duration-divider': item.hasLongDurationDivider }"
|
||||
@click="openWorkbenchTarget(item)"
|
||||
>
|
||||
<span class="progress-time">
|
||||
<time :datetime="item.updatedAt || ''">{{ item.displayTime }}</time>
|
||||
<small>更新</small>
|
||||
<span class="progress-time-wrapper">
|
||||
<span class="expense-type-icon" :class="`expense-type-icon--${item.expenseTypeTone}`">
|
||||
<i :class="item.expenseTypeIcon"></i>
|
||||
</span>
|
||||
<span class="progress-time">
|
||||
<time :datetime="item.updatedAt || ''">{{ item.displayTime }}</time>
|
||||
<small v-if="item.showTimeCapsule" class="time-capsule">更新时间</small>
|
||||
<small v-if="item.showUpdateText">更新</small>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="progress-identity">
|
||||
<strong>{{ item.id }}</strong>
|
||||
<small>{{ item.title }}</small>
|
||||
<strong>{{ item.title }}</strong>
|
||||
<small>{{ item.id }}</small>
|
||||
</span>
|
||||
|
||||
<span class="progress-type" :title="item.expenseTypeLabel || '其他费用'">
|
||||
<small>费用类型</small>
|
||||
<strong>{{ item.expenseTypeLabel || '其他费用' }}</strong>
|
||||
</span>
|
||||
|
||||
@@ -237,8 +242,8 @@
|
||||
</span>
|
||||
|
||||
<span class="progress-result">
|
||||
<span class="progress-status" :class="`progress-status--${item.statusTone}`">{{ item.status }}</span>
|
||||
<strong>{{ item.amount }}</strong>
|
||||
<span class="progress-status" :class="`progress-status--${item.statusTone}`">{{ item.status }}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -268,6 +273,9 @@
|
||||
class="insight-metric-row"
|
||||
:class="`insight-metric-row--${item.tone}`"
|
||||
>
|
||||
<span class="insight-metric-icon" aria-hidden="true">
|
||||
<i :class="item.icon"></i>
|
||||
</span>
|
||||
<span class="insight-metric-label">{{ item.label }}</span>
|
||||
<strong class="insight-metric-value">
|
||||
{{ item.value }}<small v-if="item.unit">{{ item.unit }}</small>
|
||||
@@ -478,6 +486,15 @@ const currentUserProfileKey = computed(() => {
|
||||
user.employee_no
|
||||
].map((item) => String(item || '').trim()).filter(Boolean).join('|')
|
||||
})
|
||||
function resolveExpenseTypeStyle(label) {
|
||||
if (label === '差旅交通') return { icon: 'mdi mdi-airplane', tone: 'blue' }
|
||||
if (label === '业务招待') return { icon: 'mdi mdi-silverware-fork-knife', tone: 'amber' }
|
||||
if (label === '办公采购') return { icon: 'mdi mdi-cart-outline', tone: 'emerald' }
|
||||
if (label === '培训会议') return { icon: 'mdi mdi-projector', tone: 'violet' }
|
||||
if (label === '市场活动') return { icon: 'mdi mdi-bullhorn-outline', tone: 'cyan' }
|
||||
return { icon: 'mdi mdi-receipt-text-outline', tone: 'muted' }
|
||||
}
|
||||
|
||||
const visibleProgressItems = computed(() => {
|
||||
const rows = Array.isArray(props.workbenchSummary.progressItems)
|
||||
? props.workbenchSummary.progressItems
|
||||
@@ -488,10 +505,18 @@ const visibleProgressItems = computed(() => {
|
||||
isLongDuration: isLongDurationProgress(item?.updatedAt)
|
||||
}))
|
||||
|
||||
return progressRows.map((item, index) => ({
|
||||
...item,
|
||||
hasLongDurationDivider: item.isLongDuration && !progressRows[index - 1]?.isLongDuration
|
||||
}))
|
||||
return progressRows.map((item, index) => {
|
||||
const isCompleted = item.statusTone === 'muted';
|
||||
const expenseStyle = resolveExpenseTypeStyle(item.expenseTypeLabel);
|
||||
return {
|
||||
...item,
|
||||
expenseTypeIcon: expenseStyle.icon,
|
||||
expenseTypeTone: expenseStyle.tone,
|
||||
showTimeCapsule: !item.isLongDuration,
|
||||
showUpdateText: item.isLongDuration && !isCompleted,
|
||||
hasLongDurationDivider: item.isLongDuration && !progressRows[index - 1]?.isLongDuration
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const LONG_DURATION_DAYS = 10
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -196,42 +196,48 @@ export function buildExpenseStatItems(summary = {}) {
|
||||
label: '本月报销笔数',
|
||||
value: summary.monthlyCount ?? 0,
|
||||
unit: '笔',
|
||||
tone: 'primary'
|
||||
tone: 'primary',
|
||||
icon: 'mdi mdi-text-box-check-outline'
|
||||
},
|
||||
{
|
||||
key: 'monthly-amount',
|
||||
label: '本月报销金额',
|
||||
value: summary.monthlyAmountLabel || '¥0',
|
||||
unit: '',
|
||||
tone: 'amount'
|
||||
tone: 'amount',
|
||||
icon: 'mdi mdi-cash-multiple'
|
||||
},
|
||||
{
|
||||
key: 'total-count',
|
||||
label: '累计报销笔数',
|
||||
value: summary.totalCount ?? 0,
|
||||
unit: '笔',
|
||||
tone: 'muted'
|
||||
tone: 'muted',
|
||||
icon: 'mdi mdi-clipboard-text-outline'
|
||||
},
|
||||
{
|
||||
key: 'total-amount',
|
||||
label: '累计报销金额',
|
||||
value: summary.totalAmountLabel || '¥0',
|
||||
unit: '',
|
||||
tone: 'amount'
|
||||
tone: 'amount',
|
||||
icon: 'mdi mdi-bank-outline'
|
||||
},
|
||||
{
|
||||
key: 'in-review',
|
||||
label: '审批中单据',
|
||||
value: summary.inReviewCount ?? 0,
|
||||
unit: '笔',
|
||||
tone: 'warning'
|
||||
tone: 'warning',
|
||||
icon: 'mdi mdi-timer-sand'
|
||||
},
|
||||
{
|
||||
key: 'pending-payment',
|
||||
label: '待付款单据',
|
||||
value: summary.pendingPaymentCount ?? 0,
|
||||
unit: '笔',
|
||||
tone: 'info'
|
||||
tone: 'info',
|
||||
icon: 'mdi mdi-credit-card-outline'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -194,10 +194,11 @@ function buildTodoItems(ownedRequests) {
|
||||
.sort((left, right) => normalizeText(right.due).localeCompare(normalizeText(left.due)))
|
||||
}
|
||||
|
||||
function resolveProgressStatusTone(approvalKey) {
|
||||
if (approvalKey === 'completed') return 'muted'
|
||||
if (approvalKey === 'pending_payment') return 'warning'
|
||||
if (approvalKey === 'supplement' || approvalKey === 'rejected') return 'danger'
|
||||
function resolveProgressStatusTone(approvalKey, statusText = '') {
|
||||
const status = String(statusText || '').trim()
|
||||
if (approvalKey === 'completed' || /完成|结束|通过/i.test(status)) return 'muted'
|
||||
if (approvalKey === 'pending_payment' || /付款|支付/i.test(status)) return 'warning'
|
||||
if (approvalKey === 'supplement' || approvalKey === 'rejected' || /退回|驳回|修改/i.test(status)) return 'danger'
|
||||
return 'success'
|
||||
}
|
||||
|
||||
@@ -243,14 +244,15 @@ function buildProgressItems(ownedRequests) {
|
||||
const currentStep = steps.find((step) => step.current)
|
||||
const title = normalizeText(request?.title || request?.note || request?.sceneLabel) || '费用单据'
|
||||
|
||||
const status = normalizeText(request?.approvalStatus || currentStep?.label) || '处理中'
|
||||
return {
|
||||
id: requestId,
|
||||
requestId,
|
||||
title,
|
||||
expenseTypeLabel: resolveExpenseCategory(request),
|
||||
amount: formatCurrency(request?.amount),
|
||||
status: normalizeText(request?.approvalStatus || currentStep?.label) || '处理中',
|
||||
statusTone: resolveProgressStatusTone(normalizeText(request?.approvalKey)),
|
||||
status,
|
||||
statusTone: resolveProgressStatusTone(normalizeText(request?.approvalKey), status),
|
||||
updatedAt: normalizeText(request?.updatedAt || request?.submittedAt || request?.createdAt),
|
||||
steps,
|
||||
target: resolveRequestTarget(request),
|
||||
@@ -391,12 +393,14 @@ function buildExpenseProcessingRows(ownedRequests) {
|
||||
const latestAt = dates[dates.length - 1] || toDate(request?.updatedAt || request?.submittedAt || request?.createdAt)
|
||||
const stepCount = Array.isArray(request?.progressSteps) ? request.progressSteps.length : 0
|
||||
|
||||
const status = normalizeText(request?.approvalStatus || request?.status) || '处理中'
|
||||
|
||||
return {
|
||||
id: requestId || title,
|
||||
requestId,
|
||||
title,
|
||||
status: normalizeText(request?.approvalStatus || request?.status) || '处理中',
|
||||
statusTone: resolveProgressStatusTone(normalizeText(request?.approvalKey)),
|
||||
status,
|
||||
statusTone: resolveProgressStatusTone(normalizeText(request?.approvalKey), status),
|
||||
startedAt: startedAt ? formatDateTimeLabel(startedAt) : '暂无开始时间',
|
||||
updatedAt: latestAt ? formatDateTimeLabel(latestAt) : '暂无更新时间',
|
||||
durationLabel: startedAt && latestAt ? formatDurationLabel(latestAt.getTime() - startedAt.getTime()) : '暂无耗时',
|
||||
|
||||
@@ -127,6 +127,7 @@ function testReceiptFolderDetailLayoutAdjustments() {
|
||||
assert.match(receiptStyles, /\.receipt-association-panel/)
|
||||
assert.match(receiptStyles, /\.receipt-preview-box[\s\S]*height: clamp\(380px, 56vh, 640px\)/)
|
||||
assert.match(receiptStyles, /\.receipt-all-field-grid/)
|
||||
assert.match(receiptStyles, /\.receipt-all-field-grid[\s\S]*grid-template-columns: repeat\(auto-fit, minmax\(260px, 1fr\)\)/)
|
||||
assert.match(receiptStyles, /\.receipt-edit-log-list/)
|
||||
assert.doesNotMatch(receiptStyles, /\.receipt-detail-toolbar/)
|
||||
assert.doesNotMatch(receiptStyles, /\.receipt-side-stack/)
|
||||
|
||||
Reference in New Issue
Block a user