Redesign login page with feature carousel

This commit is contained in:
2026-06-30 18:47:53 +08:00
parent 05f0c62d15
commit 157d8133f9
6 changed files with 526 additions and 59 deletions
+174 -12
View File
@@ -4125,30 +4125,49 @@ input[type="checkbox"] {
.login-page-wrapper { .login-page-wrapper {
min-height: 100vh; min-height: 100vh;
background: radial-gradient(circle at 12% 10%, rgba(37, 99, 235, 0.15) 0%, transparent 42%), background:
radial-gradient(circle at 90% 0%, rgba(14, 165, 233, 0.14) 0%, transparent 45%), linear-gradient(135deg, rgba(15, 23, 42, 0.04), rgba(37, 99, 235, 0.07)),
linear-gradient(180deg, #f8fafc 0%, #e8eefc 100%); linear-gradient(180deg, #f8fafc 0%, #e8eefc 100%);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 24px; padding: 28px;
}
.login-shell {
width: min(1180px, 100%);
min-height: min(720px, calc(100vh - 56px));
display: grid;
grid-template-columns: minmax(340px, 420px) minmax(0, 1fr);
background: #ffffff;
border: 1px solid #dbe4f3;
border-radius: 18px;
box-shadow: 0 18px 38px rgba(15, 23, 42, 0.14);
overflow: hidden;
} }
.login-card { .login-card {
width: min(420px, 94vw); width: 100%;
background: #ffffff; background: #ffffff;
border: 1px solid #dbe4f3; border-right: 1px solid #dbe4f3;
border-radius: 16px; padding: 34px;
box-shadow: 0 24px 52px rgba(15, 23, 42, 0.16);
padding: 24px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 14px; justify-content: center;
gap: 16px;
}
.login-card--checking {
width: min(420px, 94vw);
border: 1px solid #dbe4f3;
border-radius: 14px;
box-shadow: var(--shadow-panel);
} }
.login-card h2 { .login-card h2 {
margin: 0; margin: 0;
font-size: 1.4em; font-size: 1.55em;
line-height: 1.25;
color: var(--color-text-primary); color: var(--color-text-primary);
} }
@@ -4166,7 +4185,7 @@ input[type="checkbox"] {
color: var(--color-accent-strong); color: var(--color-accent-strong);
font-weight: 700; font-weight: 700;
font-size: 0.75em; font-size: 0.75em;
letter-spacing: 0.4px; letter-spacing: 0;
padding: 4px 10px; padding: 4px 10px;
} }
@@ -4196,7 +4215,7 @@ input[type="checkbox"] {
.login-card input, .login-card input,
.login-card select { .login-card select {
width: 100%; width: 100%;
padding: 10px 12px; padding: 11px 12px;
border: 1px solid #cbd5e1; border: 1px solid #cbd5e1;
border-radius: 8px; border-radius: 8px;
font-size: 0.95em; font-size: 0.95em;
@@ -4240,6 +4259,149 @@ input[type="checkbox"] {
color: #1e3a8a; color: #1e3a8a;
} }
.login-submit-btn {
min-height: 42px;
border-radius: 8px;
font-weight: 700;
}
.login-visual-panel {
min-width: 0;
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
gap: 18px;
padding: 34px;
background: #f8fafc;
}
.login-slide-copy {
max-width: 680px;
}
.login-slide-copy span {
color: var(--color-accent-strong);
font-size: 0.82em;
font-weight: 700;
}
.login-slide-copy h3 {
margin: 8px 0 8px;
color: var(--color-text-primary);
font-size: 1.55em;
line-height: 1.25;
}
.login-slide-copy p {
margin: 0;
color: var(--color-text-secondary);
line-height: 1.58;
}
.login-slide-frame {
position: relative;
min-height: 0;
border: 1px solid #cbd5e1;
border-radius: 12px;
overflow: hidden;
background: #0f172a;
}
.login-slide-image {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transform: scale(1.018);
transition: opacity 0.45s ease, transform 0.7s ease;
}
.login-slide-image.active {
opacity: 1;
transform: scale(1);
}
.login-slide-dots {
display: flex;
justify-content: center;
gap: 8px;
}
.login-slide-dots button {
width: 30px;
height: 8px;
border: 1px solid #93a4bd;
border-radius: 999px;
background: #e2e8f0;
padding: 0;
cursor: pointer;
}
.login-slide-dots button.active {
width: 42px;
border-color: var(--color-accent);
background: var(--color-accent);
}
@media (max-width: 920px) {
.login-page-wrapper {
align-items: flex-start;
overflow-y: auto;
}
.login-shell {
min-height: auto;
grid-template-columns: 1fr;
}
.login-card {
border-right: none;
border-bottom: 1px solid #dbe4f3;
padding: 24px;
}
.login-visual-panel {
min-height: 420px;
padding: 24px;
}
}
@media (max-width: 560px) {
.login-page-wrapper {
padding: 12px;
}
.login-shell {
border-radius: 12px;
}
.login-card,
.login-visual-panel {
padding: 18px;
}
.login-card h2,
.login-slide-copy h3 {
font-size: 1.28em;
}
.login-visual-panel {
min-height: 360px;
}
}
@media (prefers-reduced-motion: reduce) {
.login-slide-image {
transition: opacity 0.15s ease;
transform: none;
}
.login-slide-image.active {
transform: none;
}
}
.user-role-chip { .user-role-chip {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
+1 -1
View File
@@ -2095,7 +2095,7 @@ function App() {
if (!authChecked) { if (!authChecked) {
return ( return (
<div className="login-page-wrapper"> <div className="login-page-wrapper">
<div className="login-card"> <div className="login-card login-card--checking">
<h2>正在检查登录状态...</h2> <h2>正在检查登录状态...</h2>
<p>请稍候系统正在验证会话</p> <p>请稍候系统正在验证会话</p>
</div> </div>
+65 -4
View File
@@ -1,5 +1,26 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import apiClient from './api/client'; import apiClient from './api/client';
import clusterDeliveryUrl from './assets/login/cluster-delivery.svg';
import processingArchitectureUrl from './assets/login/processing-architecture.svg';
import systemOverviewUrl from './assets/login/system-overview.svg';
const loginSlides = [
{
title: '统一管理雷达数据生产流程',
description: '覆盖源数据入库、精密轨道匹配、生产编排、成果目录和地图分析,形成可审计的工程闭环。',
image: systemOverviewUrl,
},
{
title: '面向 D-InSAR / SBAS 的处理链路',
description: '扫描与解析先行,生产任务进入队列,运行结果和失败归因统一登记,便于复查和补跑。',
image: processingArchitectureUrl,
},
{
title: '支持集群生产与成果交付',
description: '主服务器负责资产、权限和审计,生产节点承担受控处理服务,结果回传后进入交付申请与下载流程。',
image: clusterDeliveryUrl,
},
];
const LoginPage = ({ onLoginSuccess }) => { const LoginPage = ({ onLoginSuccess }) => {
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
@@ -7,6 +28,7 @@ const LoginPage = ({ onLoginSuccess }) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [licenseStatus, setLicenseStatus] = useState(null); const [licenseStatus, setLicenseStatus] = useState(null);
const [activeSlide, setActiveSlide] = useState(0);
useEffect(() => { useEffect(() => {
const checkLicense = async () => { const checkLicense = async () => {
@@ -20,6 +42,13 @@ const LoginPage = ({ onLoginSuccess }) => {
checkLicense(); checkLicense();
}, []); }, []);
useEffect(() => {
const timer = window.setInterval(() => {
setActiveSlide((current) => (current + 1) % loginSlides.length);
}, 5200);
return () => window.clearInterval(timer);
}, []);
const handleSubmit = async (event) => { const handleSubmit = async (event) => {
event.preventDefault(); event.preventDefault();
setLoading(true); setLoading(true);
@@ -48,10 +77,11 @@ const LoginPage = ({ onLoginSuccess }) => {
return ( return (
<div className="login-page-wrapper"> <div className="login-page-wrapper">
<div className="login-card"> <div className="login-shell">
<section className="login-card" aria-label="系统登录">
<div className="login-card-header"> <div className="login-card-header">
<div className="login-brand-tag">InSAR</div> <div className="login-brand-tag">InSAR Production</div>
<h2>管理系统登录</h2> <h2>雷达数据生产管理系统</h2>
<p className="login-subtitle">内网受控访问请使用管理员分配的账号登录</p> <p className="login-subtitle">内网受控访问请使用管理员分配的账号登录</p>
</div> </div>
@@ -84,7 +114,7 @@ const LoginPage = ({ onLoginSuccess }) => {
required required
/> />
</label> </label>
<button type="submit" className="primary-btn" disabled={loading}> <button type="submit" className="primary-btn login-submit-btn" disabled={loading}>
{loading ? '登录中...' : '登录'} {loading ? '登录中...' : '登录'}
</button> </button>
</form> </form>
@@ -99,6 +129,37 @@ const LoginPage = ({ onLoginSuccess }) => {
<strong>提示</strong> <strong>提示</strong>
<span>首次部署请确认已在 `.env` 配置管理员账号与密码</span> <span>首次部署请确认已在 `.env` 配置管理员账号与密码</span>
</div> </div>
</section>
<section className="login-visual-panel" aria-label="系统能力介绍">
<div className="login-slide-copy">
<span>系统能力</span>
<h3>{loginSlides[activeSlide].title}</h3>
<p>{loginSlides[activeSlide].description}</p>
</div>
<div className="login-slide-frame">
{loginSlides.map((slide, index) => (
<img
key={slide.title}
src={slide.image}
alt={slide.title}
className={`login-slide-image ${index === activeSlide ? 'active' : ''}`}
aria-hidden={index !== activeSlide}
/>
))}
</div>
<div className="login-slide-dots" aria-label="切换系统介绍图">
{loginSlides.map((slide, index) => (
<button
key={slide.title}
type="button"
className={index === activeSlide ? 'active' : ''}
aria-label={`查看${slide.title}`}
onClick={() => setActiveSlide(index)}
/>
))}
</div>
</section>
</div> </div>
</div> </div>
); );
@@ -0,0 +1,78 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-labelledby="title desc">
<title id="title">Cluster and Result Delivery Architecture</title>
<desc id="desc">A cluster processing and result delivery architecture for radar data production.</desc>
<defs>
<linearGradient id="bg3" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#111827"/>
<stop offset="0.48" stop-color="#123b61"/>
<stop offset="1" stop-color="#14532d"/>
</linearGradient>
<filter id="shadow3" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="18" stdDeviation="20" flood-color="#020617" flood-opacity="0.3"/>
</filter>
</defs>
<rect width="1440" height="900" fill="url(#bg3)"/>
<g opacity="0.2" stroke="#d1fae5" stroke-width="1.5" fill="none">
<path d="M100 190h1240M100 360h1240M100 530h1240M100 700h1240"/>
<path d="M230 90v720M430 90v720M630 90v720M830 90v720M1030 90v720M1230 90v720"/>
</g>
<g transform="translate(130 104)" filter="url(#shadow3)" font-family="Segoe UI, Arial, sans-serif">
<rect width="1180" height="692" rx="22" fill="#f8fafc"/>
<text x="54" y="76" font-size="32" font-weight="700" fill="#0f172a">集群生产与成果交付</text>
<text x="54" y="110" font-size="18" fill="#475569">主服务器统一管理任务,子服务器只承担受控生产服务,成果回传后进入交付流程。</text>
<g transform="translate(70 172)">
<rect width="280" height="370" rx="18" fill="#e0f2fe" stroke="#7dd3fc"/>
<text x="34" y="52" font-size="25" font-weight="700" fill="#0f172a">主服务器</text>
<text x="34" y="88" font-size="17" fill="#475569">资产、任务、用户、审计</text>
<g transform="translate(34 132)" fill="#0f172a">
<rect width="212" height="42" rx="8" fill="#ffffff" stroke="#bfdbfe"/>
<text x="18" y="27" font-size="16">任务队列</text>
<rect y="62" width="212" height="42" rx="8" fill="#ffffff" stroke="#bfdbfe"/>
<text x="18" y="89" font-size="16">成果目录</text>
<rect y="124" width="212" height="42" rx="8" fill="#ffffff" stroke="#bfdbfe"/>
<text x="18" y="151" font-size="16">用户权限</text>
</g>
</g>
<g transform="translate(460 172)">
<rect width="280" height="370" rx="18" fill="#ecfdf5" stroke="#86efac"/>
<text x="34" y="52" font-size="25" font-weight="700" fill="#0f172a">生产节点</text>
<text x="34" y="88" font-size="17" fill="#475569">LandSAR / Gamma 执行</text>
<g transform="translate(34 132)">
<rect width="92" height="92" rx="14" fill="#10b981"/>
<text x="26" y="54" font-size="18" font-weight="700" fill="#ffffff">1.6</text>
<rect x="120" width="92" height="92" rx="14" fill="#059669"/>
<text x="146" y="54" font-size="18" font-weight="700" fill="#ffffff">GPU</text>
<rect y="120" width="212" height="46" rx="10" fill="#ffffff" stroke="#bbf7d0"/>
<text x="18" y="149" font-size="16" fill="#166534">受控 Worker 服务</text>
</g>
</g>
<g transform="translate(850 172)">
<rect width="260" height="370" rx="18" fill="#fef3c7" stroke="#fcd34d"/>
<text x="34" y="52" font-size="25" font-weight="700" fill="#0f172a">成果交付</text>
<text x="34" y="88" font-size="17" fill="#475569">申请、打包、下载</text>
<g transform="translate(34 132)">
<path d="M0 0h180l44 48v118H0z" fill="#ffffff" stroke="#fde68a"/>
<path d="M180 0v48h44" fill="#fde68a"/>
<text x="22" y="68" font-size="18" font-weight="700" fill="#92400e">交付包</text>
<text x="22" y="105" font-size="15" fill="#78350f">D-InSAR / SBAS</text>
<text x="22" y="132" font-size="15" fill="#78350f">LT-1 / GF3 正射</text>
</g>
</g>
<g fill="none" stroke="#2563eb" stroke-width="6" stroke-linecap="round" stroke-linejoin="round">
<path d="M368 322h70"/>
<path d="M758 322h70"/>
<path d="M438 358h-70"/>
<path d="M828 358h-70"/>
</g>
<g fill="#2563eb">
<path d="M438 322l-14-10v20z"/>
<path d="M828 322l-14-10v20z"/>
<path d="M368 358l14-10v20z"/>
<path d="M758 358l14-10v20z"/>
</g>
<g transform="translate(70 584)">
<rect width="1040" height="56" rx="12" fill="#0f172a"/>
<text x="28" y="36" font-size="18" fill="#dbeafe">最小化子服务器代码暴露:仅部署受控执行服务、运行环境和任务数据目录;业务资产与权限仍由主服务器统一管理。</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,85 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-labelledby="title desc">
<title id="title">Production Pipeline Architecture</title>
<desc id="desc">A pipeline diagram for SAR data parsing, precise orbit matching, D-InSAR and SBAS production, and catalog registration.</desc>
<defs>
<linearGradient id="bg2" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#082f49"/>
<stop offset="0.48" stop-color="#0f3b5f"/>
<stop offset="1" stop-color="#164e63"/>
</linearGradient>
<filter id="shadow2" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="16" stdDeviation="18" flood-color="#020617" flood-opacity="0.24"/>
</filter>
</defs>
<rect width="1440" height="900" fill="url(#bg2)"/>
<g opacity="0.18" fill="none" stroke="#bae6fd" stroke-width="2">
<path d="M132 170C345 72 525 75 672 178s335 103 564-4"/>
<path d="M80 700c203-126 385-132 545-18s378 113 735-3"/>
</g>
<g transform="translate(140 110)" filter="url(#shadow2)">
<rect width="1160" height="680" rx="20" fill="#f8fafc"/>
<text x="48" y="72" font-family="Segoe UI, Arial, sans-serif" font-size="32" font-weight="700" fill="#0f172a">生产处理链路</text>
<text x="48" y="106" font-family="Segoe UI, Arial, sans-serif" font-size="18" fill="#475569">增量扫描优先,解析与预览异步,生产结果统一登记到成果目录。</text>
<g transform="translate(64 170)" font-family="Segoe UI, Arial, sans-serif">
<g>
<rect width="184" height="122" rx="14" fill="#dbeafe" stroke="#93c5fd"/>
<text x="24" y="44" font-size="23" font-weight="700" fill="#0f172a">源数据扫描</text>
<text x="24" y="80" font-size="16" fill="#475569">增量过滤</text>
</g>
<g transform="translate(240 0)">
<rect width="184" height="122" rx="14" fill="#e0f2fe" stroke="#7dd3fc"/>
<text x="24" y="44" font-size="23" font-weight="700" fill="#0f172a">元数据解析</text>
<text x="24" y="80" font-size="16" fill="#475569">XML / TAR / ZIP</text>
</g>
<g transform="translate(480 0)">
<rect width="184" height="122" rx="14" fill="#dcfce7" stroke="#86efac"/>
<text x="24" y="44" font-size="23" font-weight="700" fill="#0f172a">精轨匹配</text>
<text x="24" y="80" font-size="16" fill="#475569">自动补链</text>
</g>
<g transform="translate(720 0)">
<rect width="184" height="122" rx="14" fill="#fef3c7" stroke="#fcd34d"/>
<text x="24" y="44" font-size="23" font-weight="700" fill="#0f172a">生产编排</text>
<text x="24" y="80" font-size="16" fill="#475569">队列 / Worker</text>
</g>
<g transform="translate(960 0)">
<rect width="132" height="122" rx="14" fill="#fee2e2" stroke="#fca5a5"/>
<text x="24" y="44" font-size="23" font-weight="700" fill="#0f172a">成果</text>
<text x="24" y="80" font-size="16" fill="#475569">登记交付</text>
</g>
<g fill="none" stroke="#2563eb" stroke-width="5" stroke-linecap="round">
<path d="M192 61h38"/>
<path d="M432 61h38"/>
<path d="M672 61h38"/>
<path d="M912 61h38"/>
</g>
</g>
<g transform="translate(64 380)" font-family="Segoe UI, Arial, sans-serif">
<rect width="500" height="190" rx="16" fill="#0f172a"/>
<text x="30" y="48" font-size="24" font-weight="700" fill="#f8fafc">D-InSAR / SBAS 生产</text>
<text x="30" y="84" font-size="17" fill="#cbd5e1">LandSAR、Gamma、SARscape 按任务类型接入</text>
<g transform="translate(30 120)">
<rect width="112" height="36" rx="18" fill="#2563eb"/>
<text x="24" y="24" font-size="15" fill="#ffffff">配对</text>
<rect x="130" width="112" height="36" rx="18" fill="#0ea5e9"/>
<text x="154" y="24" font-size="15" fill="#ffffff">处理</text>
<rect x="260" width="112" height="36" rx="18" fill="#10b981"/>
<text x="284" y="24" font-size="15" fill="#ffffff">登记</text>
</g>
<rect x="600" width="492" height="190" rx="16" fill="#eef2ff"/>
<text x="630" y="48" font-size="24" font-weight="700" fill="#0f172a">可审计运行记录</text>
<text x="630" y="84" font-size="17" fill="#475569">成功、部分成功、失败原因与日志明细独立记录</text>
<g fill="#2563eb">
<circle cx="648" cy="132" r="8"/>
<circle cx="648" cy="164" r="8"/>
<circle cx="846" cy="132" r="8"/>
<circle cx="846" cy="164" r="8"/>
</g>
<g font-size="16" fill="#334155">
<text x="668" y="137">任务批次</text>
<text x="668" y="169">失败归因</text>
<text x="866" y="137">成果目录</text>
<text x="866" y="169">交付申请</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

@@ -0,0 +1,81 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-labelledby="title desc">
<title id="title">Radar Data Production System Overview</title>
<desc id="desc">An engineering-style system overview with satellite acquisition, asset catalog, processing, result management, and map analysis.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#0f172a"/>
<stop offset="0.55" stop-color="#14345f"/>
<stop offset="1" stop-color="#0b4f63"/>
</linearGradient>
<linearGradient id="panel" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#f8fafc" stop-opacity="0.96"/>
<stop offset="1" stop-color="#e0f2fe" stop-opacity="0.86"/>
</linearGradient>
<filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="18" stdDeviation="22" flood-color="#020617" flood-opacity="0.28"/>
</filter>
</defs>
<rect width="1440" height="900" fill="url(#bg)"/>
<g opacity="0.28" stroke="#93c5fd" stroke-width="1">
<path d="M0 150H1440M0 300H1440M0 450H1440M0 600H1440M0 750H1440"/>
<path d="M160 0V900M320 0V900M480 0V900M640 0V900M800 0V900M960 0V900M1120 0V900M1280 0V900"/>
</g>
<g opacity="0.5" fill="none" stroke="#67e8f9" stroke-width="2">
<circle cx="1070" cy="270" r="150"/>
<circle cx="1070" cy="270" r="226"/>
<path d="M845 276c70-48 139-70 211-65 93 6 168 62 226 152"/>
</g>
<g transform="translate(150 120)" filter="url(#softShadow)">
<rect width="1140" height="660" rx="18" fill="#f8fafc" opacity="0.96"/>
<rect x="28" y="28" width="1084" height="74" rx="12" fill="#e2e8f0"/>
<text x="56" y="75" font-family="Segoe UI, Arial, sans-serif" font-size="30" font-weight="700" fill="#0f172a">雷达数据生产管理系统</text>
<text x="720" y="73" font-family="Segoe UI, Arial, sans-serif" font-size="18" fill="#475569">数据接入 · 生产编排 · 成果管理 · 地图分析</text>
<g transform="translate(56 146)">
<rect width="212" height="110" rx="12" fill="url(#panel)" stroke="#93c5fd"/>
<text x="24" y="42" font-family="Segoe UI, Arial, sans-serif" font-size="24" font-weight="700" fill="#0f172a">源数据接入</text>
<text x="24" y="75" font-family="Segoe UI, Arial, sans-serif" font-size="17" fill="#475569">LT-1 / Sentinel-1 / GF3</text>
<path d="M168 35l22 13-22 13z" fill="#2563eb"/>
</g>
<g transform="translate(332 146)">
<rect width="212" height="110" rx="12" fill="url(#panel)" stroke="#93c5fd"/>
<text x="24" y="42" font-family="Segoe UI, Arial, sans-serif" font-size="24" font-weight="700" fill="#0f172a">资产台账</text>
<text x="24" y="75" font-family="Segoe UI, Arial, sans-serif" font-size="17" fill="#475569">解析、精轨匹配、缓存</text>
<rect x="154" y="30" width="34" height="50" rx="6" fill="#0ea5e9"/>
<rect x="164" y="22" width="34" height="50" rx="6" fill="#2563eb" opacity="0.75"/>
</g>
<g transform="translate(608 146)">
<rect width="212" height="110" rx="12" fill="url(#panel)" stroke="#93c5fd"/>
<text x="24" y="42" font-family="Segoe UI, Arial, sans-serif" font-size="24" font-weight="700" fill="#0f172a">生产工作台</text>
<text x="24" y="75" font-family="Segoe UI, Arial, sans-serif" font-size="17" fill="#475569">D-InSAR / SBAS / 正射</text>
<circle cx="174" cy="56" r="28" fill="#10b981"/>
<path d="M162 55l10 10 20-24" fill="none" stroke="#f8fafc" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<g transform="translate(884 146)">
<rect width="212" height="110" rx="12" fill="url(#panel)" stroke="#93c5fd"/>
<text x="24" y="42" font-family="Segoe UI, Arial, sans-serif" font-size="24" font-weight="700" fill="#0f172a">成果目录</text>
<text x="24" y="75" font-family="Segoe UI, Arial, sans-serif" font-size="17" fill="#475569">登记、提取、交付包</text>
<path d="M156 36h42v44h-42z" fill="#f59e0b"/>
<path d="M156 36l20 18 22-18" fill="none" stroke="#fff7ed" stroke-width="5"/>
</g>
<g fill="none" stroke="#2563eb" stroke-width="5" stroke-linecap="round">
<path d="M276 201h42"/>
<path d="M552 201h42"/>
<path d="M828 201h42"/>
</g>
<g transform="translate(56 326)">
<rect width="1040" height="244" rx="16" fill="#0f172a"/>
<path d="M30 186c110-82 222-102 336-60 95 36 155 111 240 115 132 6 195-150 329-144 45 2 79 21 105 48v99H30z" fill="#0ea5e9" opacity="0.22"/>
<path d="M30 171c112-74 220-88 324-42 100 44 159 121 254 117 129-5 181-143 314-132 49 4 88 25 118 58" fill="none" stroke="#38bdf8" stroke-width="4"/>
<g transform="translate(46 36)">
<text font-family="Segoe UI, Arial, sans-serif" font-size="26" font-weight="700" fill="#f8fafc">统一生产态势</text>
<text y="42" font-family="Segoe UI, Arial, sans-serif" font-size="17" fill="#cbd5e1">任务、Worker、成果、日志形成可追溯闭环</text>
</g>
<g font-family="Segoe UI, Arial, sans-serif" font-size="18" fill="#e0f2fe">
<text x="60" y="194">扫描入库</text>
<text x="304" y="130">配对规划</text>
<text x="548" y="214">集群生产</text>
<text x="792" y="122">成果发布</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB