diff --git a/web/src/assets/styles/components/top-bar.css b/web/src/assets/styles/components/top-bar.css index 4527bde..95d1321 100644 --- a/web/src/assets/styles/components/top-bar.css +++ b/web/src/assets/styles/components/top-bar.css @@ -881,6 +881,176 @@ line-height: 1.5; } +.help-wrap { + position: relative; + display: inline-flex; +} + +.help-wrap.is-open .help-btn { + border: 1px solid var(--theme-primary-light-5); + background: var(--theme-primary-light-9); + color: var(--theme-primary-active); +} + +.help-btn { + border: 1px solid transparent; + border-radius: 4px; + transition: + border-color 180ms var(--ease), + background 180ms var(--ease), + color 180ms var(--ease); +} + +.help-panel-enter-active, +.help-panel-leave-active { + transition: + opacity 220ms var(--ease), + transform 220ms var(--ease); +} + +.help-panel-enter-from, +.help-panel-leave-to { + opacity: 0; + transform: translateY(-6px); +} + +@media (prefers-reduced-motion: reduce) { + .help-panel-enter-active, + .help-panel-leave-active { + transition-duration: 1ms; + } + + .help-panel-enter-from, + .help-panel-leave-to { + transform: none; + } +} + +.help-popover { + position: absolute; + top: calc(100% + 8px); + right: 0; + z-index: 60; + width: min(300px, calc(100vw - 32px)); + overflow: hidden; + border: 1px solid #d7e0ea; + border-radius: 4px; + background: #fff; + box-shadow: 0 16px 40px rgba(15, 23, 42, 0.12); +} + +.help-popover::before { + content: ""; + display: block; + height: 3px; + background: linear-gradient( + 90deg, + var(--theme-primary-active) 0%, + var(--theme-primary-light-3, #7eb3d4) 100% + ); +} + +.help-head { + display: flex; + align-items: center; + gap: 10px; + padding: 12px 14px; + border-bottom: 1px solid #edf2f7; + background: #fafbfd; +} + +.help-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; +} + +.help-head-copy { + min-width: 0; + flex: 1 1 auto; + display: grid; + gap: 2px; +} + +.help-head-copy strong { + color: #0f172a; + font-size: 13px; + font-weight: 800; +} + +.help-head-copy small { + color: #64748b; + font-size: 12px; + font-weight: 600; +} + +.help-close-btn { + width: 28px; + height: 28px; + flex: 0 0 auto; + display: inline-grid; + place-items: center; + border: 0; + border-radius: 4px; + background: transparent; + color: #64748b; + font-size: 18px; + transition: + background 160ms var(--ease), + color 160ms var(--ease); +} + +.help-close-btn:hover { + background: #eef2f7; + color: #0f172a; +} + +.help-meta { + margin: 0; + padding: 10px 14px 12px; + display: grid; + gap: 8px; +} + +.help-meta-row { + display: grid; + grid-template-columns: 72px minmax(0, 1fr); + gap: 8px; + align-items: start; +} + +.help-meta-row--block { + grid-template-columns: 1fr; + gap: 4px; +} + +.help-meta-row dt { + color: #64748b; + font-size: 12px; + font-weight: 700; +} + +.help-meta-row dd { + margin: 0; + color: #0f172a; + font-size: 13px; + font-weight: 650; + line-height: 1.45; +} + +.help-meta-row--block dd { + color: #475569; + font-size: 12px; + font-weight: 600; +} + .company-switcher { max-width: min(220px, 28vw); height: 38px; diff --git a/web/src/assets/styles/views/travel-request-detail-view.css b/web/src/assets/styles/views/travel-request-detail-view.css index 66c08eb..f4d6f75 100644 --- a/web/src/assets/styles/views/travel-request-detail-view.css +++ b/web/src/assets/styles/views/travel-request-detail-view.css @@ -936,25 +936,33 @@ .detail-expense-table .col-action { width: 9%; } .expense-time { - position: relative; + min-width: 0; } -.expense-time.has-major-risk { - padding-left: 30px; +.expense-time-content { + display: grid; + grid-template-columns: 18px minmax(0, 1fr); + align-items: center; + gap: 6px; + min-width: 0; +} + +.expense-time-value { + min-width: 0; +} + +.expense-risk-indicator, +.expense-risk-indicator-placeholder { + width: 18px; + height: 18px; } .expense-risk-indicator { - position: absolute; - left: 8px; - top: 50%; - width: 18px; - height: 18px; padding: 0; border: 0; background: transparent; display: inline-grid; place-items: center; - transform: translateY(-50%); color: #dc2626; font-size: 18px; line-height: 1; diff --git a/web/src/components/charts/RiskDailyTrendChart.vue b/web/src/components/charts/RiskDailyTrendChart.vue index daad379..9ae0162 100644 --- a/web/src/components/charts/RiskDailyTrendChart.vue +++ b/web/src/components/charts/RiskDailyTrendChart.vue @@ -32,6 +32,12 @@ const totals = computed(() => props.rows.map((item) => Number(item.total || 0))) const highValues = computed(() => props.rows.map((item) => Number(item.highOrAbove || 0))) const maxValue = computed(() => Math.max(...totals.value, ...highValues.value, 1)) const axisMax = computed(() => Math.max(5, Math.ceil(maxValue.value * 1.2))) +const barWidth = computed(() => { + if (labels.value.length >= 12) return 9 + if (labels.value.length >= 8) return 11 + return 14 +}) +const bottomGridSize = computed(() => (labels.value.some((label) => String(label).includes('~')) ? 38 : 28)) const ariaLabel = computed(() => props.rows.map((item) => ( @@ -47,7 +53,7 @@ const chartOptions = computed(() => ({ grid: { top: 34, right: 16, - bottom: 24, + bottom: bottomGridSize.value, left: 28, containLabel: true }, @@ -86,7 +92,10 @@ const chartOptions = computed(() => ({ axisLabel: { color: '#64748b', fontSize: 11, - fontWeight: 700 + fontWeight: 700, + interval: 0, + lineHeight: 14, + formatter: (value) => String(value || '').replace('~', '\n~') } }, yAxis: { @@ -106,7 +115,8 @@ const chartOptions = computed(() => ({ name: '风险观察', type: 'bar', data: totals.value, - barWidth: 14, + barWidth: barWidth.value, + barMaxWidth: 14, itemStyle: { color: themeColors.value.chartPrimary, borderRadius: [4, 4, 0, 0] diff --git a/web/src/components/layout/TopBar.vue b/web/src/components/layout/TopBar.vue index fc7e913..e9ddd46 100644 --- a/web/src/components/layout/TopBar.vue +++ b/web/src/components/layout/TopBar.vue @@ -123,14 +123,14 @@