diff --git a/vehicle-data-platform/apps/web/src/styles/global.css b/vehicle-data-platform/apps/web/src/styles/global.css
index 6b9ce4b2..33afb693 100644
--- a/vehicle-data-platform/apps/web/src/styles/global.css
+++ b/vehicle-data-platform/apps/web/src/styles/global.css
@@ -389,6 +389,10 @@ body {
flex-wrap: wrap;
}
+.vp-mobile-service-dock {
+ display: none;
+}
+
.vp-topbar-time-window {
display: inline-flex;
align-items: center;
@@ -12528,9 +12532,82 @@ button.vp-realtime-command-item:focus-visible {
.vp-topbar {
position: relative;
grid-template-columns: minmax(0, 1fr);
+ gap: 8px;
padding: 12px;
}
+ .vp-mobile-service-dock {
+ display: grid;
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+ gap: 6px;
+ padding: 8px;
+ border: 1px solid rgba(22, 100, 255, 0.16);
+ border-radius: 8px;
+ background: #ffffff;
+ box-shadow: 0 10px 26px rgba(15, 23, 42, 0.06);
+ }
+
+ .vp-mobile-service-dock button {
+ min-width: 0;
+ min-height: 34px;
+ border: 1px solid rgba(22, 100, 255, 0.14);
+ border-radius: 7px;
+ background: #f8fafc;
+ color: var(--vp-text);
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 1;
+ cursor: pointer;
+ }
+
+ .vp-mobile-service-dock button:focus-visible,
+ .vp-mobile-service-dock button:hover {
+ border-color: rgba(22, 100, 255, 0.42);
+ background: rgba(22, 100, 255, 0.08);
+ color: var(--vp-primary);
+ outline: none;
+ }
+
+ .vp-topbar-context {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr);
+ gap: 8px;
+ overflow: visible;
+ }
+
+ .vp-service-delivery-strip,
+ .vp-topbar-quick-actions {
+ display: none;
+ }
+
+ .vp-topbar-time-window {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr);
+ gap: 6px;
+ }
+
+ .vp-topbar-time-window-copy {
+ width: auto;
+ }
+
+ .vp-topbar-time-window-copy span {
+ max-width: none;
+ }
+
+ .vp-topbar-time-window-presets,
+ .vp-topbar-time-window label {
+ flex-wrap: wrap;
+ }
+
+ .vp-topbar-time-window label {
+ height: auto;
+ min-height: 28px;
+ }
+
+ .vp-topbar-time-window input {
+ width: min(100%, 132px);
+ }
+
.vp-evidence-grid,
.vp-action-grid,
.vp-fleet-monitor .semi-card-body,
diff --git a/vehicle-data-platform/apps/web/src/test/App.test.tsx b/vehicle-data-platform/apps/web/src/test/App.test.tsx
index 2ed2a49c..a08af8a2 100644
--- a/vehicle-data-platform/apps/web/src/test/App.test.tsx
+++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx
@@ -96,6 +96,26 @@ test('topbar frames customer work as a vehicle service delivery strip', () => {
expect(screen.getByRole('button', { name: '车辆服务交付条 告警' })).toBeInTheDocument();
});
+test('topbar exposes a mobile vehicle service shortcut dock', () => {
+ vi.spyOn(globalThis, 'fetch').mockImplementation(async () => ({
+ ok: true,
+ json: async () => ({
+ data: { items: [], total: 0, limit: 20, offset: 0, linkHealth: [], runtime: { requestTimeoutMs: 5000 } },
+ traceId: 'trace-test',
+ timestamp: 1783094400000
+ })
+ }) as Response);
+
+ render(
);
+
+ expect(screen.getByRole('navigation', { name: '移动端车辆服务快捷入口' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 地图' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 轨迹' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 统计' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 导出' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 告警' })).toBeInTheDocument();
+});
+
test('exposes AMap operations shortcuts when map key is configured', async () => {
window.__LINGNIU_APP_CONFIG__ = { amapWebJsKey: 'amap-web-key' };
vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {