diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx
index 75ee49d6..d60868aa 100644
--- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx
@@ -357,10 +357,13 @@ test('keeps mobile rule selection focused and opens editing in a Semi bottom Sid
fireEvent.click(ruleItem);
const editor = await screen.findByRole('dialog', { name: '告警规则编辑' });
- expect(document.querySelector('.v2-alert-rule-editor-sidesheet')).toHaveClass('semi-sidesheet-bottom');
+ expect(document.querySelector('.v2-alert-rule-editor-sidesheet')).toHaveClass('semi-sidesheet-bottom', 'v2-workspace-editor-sidesheet');
expect(document.querySelector('.v2-alert-rule-editor-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(92dvh, 820px)' });
expect(within(editor).getByDisplayValue('测试超速规则')).toBeInTheDocument();
expect(within(editor).getByRole('button', { name: '保存规则' })).toBeInTheDocument();
+ expect(within(editor).getByRole('heading', { name: '触发条件' })).toBeInTheDocument();
+ expect(within(editor).getByRole('heading', { name: '恢复与提醒' })).toBeInTheDocument();
+ expect(within(editor).getByRole('heading', { name: '适用范围与说明' })).toBeInTheDocument();
expect(within(editor).queryByRole('region', { name: '告警规则模板' })).not.toBeInTheDocument();
expect(ruleItem).toHaveAttribute('aria-expanded', 'true');
@@ -397,6 +400,9 @@ test('creates auditable drafts from simple offline and hydrogen rule templates',
expect(view.container.querySelector('.v2-alert-rule-editor')).toHaveClass('semi-card');
expect(view.container.querySelector('.v2-alert-rule-list-heading')).toHaveClass('v2-workspace-panel-header');
expect(view.container.querySelector('.v2-alert-rule-editor-heading')).toHaveClass('v2-workspace-panel-header');
+ expect(screen.getByRole('heading', { name: '触发条件' }).closest('.v2-rule-form-section')).toBeInTheDocument();
+ expect(screen.getByRole('heading', { name: '恢复与提醒' }).closest('.v2-rule-form-section')).toBeInTheDocument();
+ expect(screen.getByRole('heading', { name: '适用范围与说明' }).closest('.v2-rule-form-section')).toBeInTheDocument();
expect(screen.getByRole('region', { name: '告警规则列表,可左右滚动选择' })).toHaveAttribute('tabindex', '0');
expect(ruleItem).toHaveClass('semi-button', 'v2-alert-rule-item');
await waitFor(() => expect(ruleItem).toHaveAttribute('aria-pressed', 'true'));
diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx
index ae852366..a7c7277c 100644
--- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx
@@ -1,7 +1,7 @@
import { IconAlarm, IconBell, IconChevronRight, IconClose, IconFilter, IconPlus, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
import { Button, Card, CardGroup, Collapse, Descriptions, Empty, Input, Radio, Select, SideSheet, Spin, Table, Tag, TextArea, Timeline, Typography } from '@douyinfe/semi-ui';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
-import { FormEvent, memo, useCallback, useEffect, useMemo, useState } from 'react';
+import { FormEvent, memo, useCallback, useEffect, useMemo, useState, type ReactNode } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import { api } from '../../api/client';
import type { AlertEvent, AlertQuery, AlertRule, AlertRuleInput, AlertStatus, MetricDefinition, Page } from '../../api/types';
@@ -17,6 +17,7 @@ import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
import { WorkspaceDetailSideSheet } from '../shared/WorkspaceDetailSideSheet';
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
+import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
import { detailTriggerRow } from '../shared/detailTriggerRow';
import { usePlatformSession } from '../auth/AuthGate';
import { canAdminister, canOperate } from '../auth/session';
@@ -369,6 +370,13 @@ function ruleDraft(rule: AlertRule): AlertRuleInput {
};
}
+function RuleFormSection({ id, title, description, children }: { id: string; title: string; description: string; children: ReactNode }) {
+ return ;
+}
+
function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: MetricDefinition[] }) {
const queryClient = useQueryClient();
const mobileLayout = useMobileLayout();
@@ -378,7 +386,6 @@ function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: Metri
useEffect(() => { if (!selectedID && rules[0]) { setSelectedID(rules[0].id); setDraft(ruleDraft(rules[0])); } }, [rules, selectedID]);
const save = useMutation({ mutationFn: api.saveAlertRuleV2, onSuccess: async (rule) => { setSelectedID(rule.id); setDraft(ruleDraft(rule)); await queryClient.invalidateQueries({ queryKey: ['alert-rules-v2'] }); } });
const toggle = useMutation({ mutationFn: (rule: AlertRule) => api.setAlertRuleEnabledV2(rule.id, { version: rule.version, enabled: !rule.enabled }), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ['alert-rules-v2'] }); } });
- useSideSheetA11y(mobileLayout && editorOpen, '.v2-alert-rule-editor-sidesheet', 'v2-alert-rule-editor', '告警规则编辑', '关闭告警规则编辑');
const mutationError = save.error ?? toggle.error;
const operators = draft.valueType === 'boolean' ? BOOLEAN_OPERATORS : NUMERIC_OPERATORS;
const availableMetrics = metrics.filter((metric) => metric.alertable && metric.valueType === draft.valueType);
@@ -417,7 +424,6 @@ function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: Metri
actions={toggleButton}
/> :
- {draft.version ? draft.enabled ? '已启用' : '已停用' : '新规则'}
{draft.version ? `v${draft.version} · 配置变更写入版本审计` : '保存后生成首个可审计版本'}
{toggleButton}
@@ -440,24 +446,30 @@ function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: Metri
;
})}
: null}
-
-
-
-
-
-
- {draft.operator === 'changed' ?
: draft.valueType === 'boolean' ?
:
}
- {draft.operator === 'between' || draft.operator === 'outside' ?
: null}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {draft.operator === 'changed' ? : draft.valueType === 'boolean' ? : }
+ {draft.operator === 'between' || draft.operator === 'outside' ? : null}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -492,17 +504,21 @@ function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: Metri
{!mobileLayout ? editor : null}
- {mobileLayout ?
{draft.version ? '编辑规则' : '新建规则'}{draft.name || '配置触发条件、范围与通知策略'} }
+ title={draft.version ? '编辑规则' : '新建规则'}
+ description={draft.name || '配置触发条件、范围与通知策略'}
+ badge={draft.version ? draft.enabled ? '已启用' : '已停用' : '新规则'}
+ badgeColor={draft.version ? draft.enabled ? 'green' : 'grey' : 'blue'}
onCancel={() => setEditorOpen(false)}
>
{editorOpen ? editor : null}
- : null}
+ : null}
;
}
diff --git a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx
index 8fa381a9..4ef8bf7e 100644
--- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx
@@ -282,7 +282,7 @@ test('renders only selectable Semi history cards on mobile', async () => {
await waitFor(() => expect(toolsButton).toHaveAttribute('aria-expanded', 'true'));
fireEvent.click(screen.getByRole('menuitem', { name: /导出任务/ }));
expect(await screen.findByRole('dialog', { name: '历史数据导出任务' })).toBeInTheDocument();
- expect(document.querySelector('.v2-history-export-sidesheet')).toHaveClass('semi-sidesheet-bottom');
+ expect(document.querySelector('.v2-history-export-sidesheet')).toHaveClass('semi-sidesheet-bottom', 'v2-workspace-task-sidesheet');
expect(document.querySelector('.v2-history-export-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(76dvh, 680px)' });
await waitFor(() => expect(mocks.historyExports).toHaveBeenCalledTimes(1));
expect(screen.getByText('暂无导出任务')).toBeInTheDocument();
@@ -388,6 +388,7 @@ test('shows only the authenticated customer export workspace with owner and scop
fireEvent.click(await screen.findByRole('button', { name: '查看导出任务' }));
expect(await screen.findByText(/customer-a · 1 辆/)).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: '历史数据导出任务' })).toBeInTheDocument();
+ expect(screen.getByRole('list', { name: '导出任务状态概览' })).toHaveTextContent('生成中0排队与执行可下载1已完成任务需处理0失败任务');
expect(screen.getByRole('button', { name: /创建导出/ })).toBeInTheDocument();
expect(mocks.historyExports).toHaveBeenCalled();
});
diff --git a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx
index 9dd3b85a..b1ff59f7 100644
--- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx
@@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { IconChevronRight, IconClose, IconDownload, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
-import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, SideSheet, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
+import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { api } from '../../api/client';
@@ -144,11 +144,22 @@ function ExportJobsPanel({ showHeader = true }: { showHeader?: boolean }) {
const jobs = query.data ?? [];
const statusLabel = (status: string) => status === 'queued' ? '排队中' : status === 'running' ? '执行中' : status === 'completed' ? '已完成' : '失败';
const statusColor = (status: string) => status === 'completed' ? 'green' : status === 'running' ? 'blue' : status === 'failed' ? 'red' : 'grey';
+ const activeJobs = jobs.filter((job) => job.status === 'queued' || job.status === 'running').length;
+ const completedJobs = jobs.filter((job) => job.status === 'completed').length;
+ const failedJobs = jobs.filter((job) => job.status === 'failed').length;
return {showHeader ? : null}
+ {query.isPending || query.isError || !jobs.length ? null :
+ 生成中{activeJobs}排队与执行
+ 可下载{completedJobs}已完成任务
+ 需处理{failedJobs}失败任务
+
}
{query.isPending ?
: query.isError ?
: !jobs.length ?
:
{jobs.slice(0, 6).map((job) => {job.name}} headerExtraContent={{statusLabel(job.status)}} headerLine bodyStyle={{ padding: 0 }}>
- {job.status === 'queued' ? '等待单并发执行' : job.status === 'running' ? `${job.processedRows.toLocaleString('zh-CN')} / ${job.totalRows.toLocaleString('zh-CN')} 行` : job.status === 'completed' ? `${job.rowCount.toLocaleString('zh-CN')} 行 · ${formatExportFileSize(job.fileSizeBytes)}` : job.error || '任务失败'}{job.ownerUsername || job.ownerName || '历史任务'} · {job.vehicleVins?.length ?? job.keywords.length} 辆{job.dateFrom && job.dateTo ? `${job.dateFrom.replace('T', ' ')} 至 ${job.dateTo.replace('T', ' ')}` : job.createdAt}
+
+ {job.status === 'queued' ? '等待单并发执行' : job.status === 'running' ? `${job.processedRows.toLocaleString('zh-CN')} / ${job.totalRows.toLocaleString('zh-CN')} 行` : job.status === 'completed' ? `${job.rowCount.toLocaleString('zh-CN')} 行 · ${formatExportFileSize(job.fileSizeBytes)}` : job.error || '任务失败'}
+ {job.ownerUsername || job.ownerName || '历史任务'} · {job.vehicleVins?.length ?? job.keywords.length} 辆{job.downloadUrl ? : null}
+ {job.dateFrom && job.dateTo ? `${job.dateFrom.replace('T', ' ')} 至 ${job.dateTo.replace('T', ' ')}` : job.createdAt}
+
{job.status === 'running' ? : null}
- {job.downloadUrl ? : null}
)}}
;
}
@@ -562,17 +573,21 @@ export default function HistoryPage() {
>
{mobileLayout && selectedRow ? : null}
- 导出任务查看生成进度与下载记录}
+ title="导出任务"
+ description="查看后台生成进度与可追溯下载记录"
+ badge="后台任务"
+ badgeColor="blue"
onCancel={() => setExportJobsOpen(false)}
>
{exportJobsOpen ? : null}
-
+
;
}
diff --git a/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts b/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts
index 32b74096..00ca67f5 100644
--- a/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts
+++ b/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts
@@ -142,7 +142,8 @@ describe('V2 production entry', () => {
expect(corePageSources.HistoryPage).toContain(' {
expect(corePageSources.AlertsPage).toContain('className="v2-alert-navigation v2-alert-command-bar"');
expect(corePageSources.AlertsPage).toContain(' | ');
diff --git a/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.test.tsx b/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.test.tsx
index b36d82f6..147e6285 100644
--- a/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.test.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.test.tsx
@@ -38,3 +38,35 @@ test('renders one accessible Semi configuration sheet with shared summary and ac
expect(onComplete).toHaveBeenCalledTimes(1);
expect(onCancel).toHaveBeenCalledTimes(1);
});
+
+test('exposes task and editor variants without changing the accessible dialog contract', () => {
+ const view = render(<>
+ undefined}
+ >
+ 任务内容
+
+ undefined}
+ >
+ 编辑内容
+
+ >);
+
+ expect(screen.getByRole('dialog', { name: '后台任务' }).closest('.semi-sidesheet')).toHaveClass('v2-workspace-task-sidesheet');
+ expect(screen.getByRole('dialog', { name: '策略编辑' }).closest('.semi-sidesheet')).toHaveClass('v2-workspace-editor-sidesheet');
+ expect(screen.getByText('任务内容')).toBeInTheDocument();
+ expect(screen.getByText('编辑内容')).toBeInTheDocument();
+ expect(view.baseElement).toHaveTextContent('查看生成进度');
+ expect(view.baseElement).toHaveTextContent('保存后生效');
+});
diff --git a/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.tsx b/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.tsx
index 30165ff4..340a5119 100644
--- a/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.tsx
+++ b/vehicle-data-platform/apps/web/src/v2/shared/WorkspaceSideSheet.tsx
@@ -21,7 +21,7 @@ export type WorkspaceSideSheetBadgeColor = 'blue' | 'green' | 'orange' | 'red' |
export type WorkspaceSideSheetProps = {
className?: string;
- variant?: 'config' | 'detail';
+ variant?: 'config' | 'detail' | 'task' | 'editor';
visible: boolean;
ariaLabel: string;
closeLabel?: string;
diff --git a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css
index b258dbbb..15e6d63e 100644
--- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css
+++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css
@@ -21068,3 +21068,330 @@
padding: 7px 8px;
}
}
+
+/*
+ * Shared task and editor SideSheets.
+ * Task sheets prioritise progress and traceable output; editor sheets preserve
+ * a stable title/status boundary while the form owns its save action.
+ */
+:is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet) .semi-sidesheet-inner {
+ overflow: hidden;
+ border-left: 1px solid #d9e3ef;
+ background: #f4f7fb;
+ box-shadow: -22px 0 64px rgba(24, 43, 68, .16);
+}
+
+:is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet) .semi-sidesheet-header {
+ min-height: 78px;
+ border-bottom: 1px solid #dfe7f0;
+ background:
+ radial-gradient(circle at 10% 0%, rgba(18, 104, 243, .075), transparent 36%),
+ linear-gradient(180deg, #fff 0%, #fbfcfe 100%);
+ padding: 13px 18px;
+}
+
+:is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet) .semi-sidesheet-title {
+ min-width: 0;
+}
+
+:is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet) .semi-sidesheet-close {
+ width: 36px;
+ height: 36px;
+ border-radius: 9px;
+}
+
+:is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet) .semi-sidesheet-body {
+ min-height: 0;
+ overflow: hidden;
+ background: #f4f7fb;
+ padding: 0;
+}
+
+.v2-workspace-task-sidesheet .v2-workspace-config-content {
+ padding: 12px;
+}
+
+.v2-workspace-editor-sidesheet .v2-workspace-config-content {
+ overflow: hidden;
+ padding: 0;
+}
+
+.v2-workspace-editor-sidesheet .v2-workspace-config-body,
+.v2-workspace-editor-sidesheet .v2-workspace-config-content {
+ width: 100%;
+}
+
+.v2-workspace-editor-sidesheet .v2-workspace-config-content > .semi-card {
+ width: 100%;
+ height: 100%;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+}
+
+.v2-history-export-sidesheet .v2-export-jobs.semi-card {
+ min-height: 100%;
+ border-color: #dce5ef;
+ border-radius: 12px;
+ box-shadow: 0 9px 28px rgba(31, 53, 80, .065);
+}
+
+.v2-export-job-overview {
+ display: grid;
+ min-height: 88px;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 1px;
+ border-bottom: 1px solid #e1e8f1;
+ background: #e1e8f1;
+}
+
+.v2-export-job-overview > span {
+ position: relative;
+ display: grid;
+ min-width: 0;
+ align-content: center;
+ gap: 3px;
+ background: #fff;
+ padding: 12px 13px;
+}
+
+.v2-export-job-overview > span::before {
+ position: absolute;
+ inset: 0 auto 0 0;
+ width: 2px;
+ background: transparent;
+ content: '';
+}
+
+.v2-export-job-overview > span.is-active::before { background: #1268f3; }
+.v2-export-job-overview > span.is-completed::before { background: #18a76f; }
+.v2-export-job-overview > span.is-failed::before { background: #e95a52; }
+
+.v2-export-job-overview small {
+ color: #7f8ea1;
+ font-size: 10px;
+ font-weight: 650;
+}
+
+.v2-export-job-overview strong {
+ color: #243950;
+ font-size: 21px;
+ font-weight: 760;
+ font-variant-numeric: tabular-nums;
+ line-height: 1.15;
+}
+
+.v2-export-job-overview > span.is-active strong { color: #1268f3; }
+.v2-export-job-overview > span.is-completed strong { color: #14865c; }
+.v2-export-job-overview > span.is-failed strong { color: #c8423b; }
+
+.v2-export-job-overview em {
+ overflow: hidden;
+ color: #98a3b2;
+ font-size: 8px;
+ font-style: normal;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.v2-history-export-sidesheet .v2-export-job-list {
+ max-height: none;
+ padding: 11px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-list > .semi-card-group {
+ gap: 9px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-card.semi-card {
+ border-radius: 10px;
+ box-shadow: 0 5px 16px rgba(30, 50, 74, .045);
+}
+
+.v2-history-export-sidesheet .v2-export-job-card > .semi-card-header {
+ min-height: 44px;
+ padding-inline: 12px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-name {
+ max-width: 310px;
+ color: #32475f;
+ font-size: 12px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-card > .semi-card-header .semi-tag {
+ min-height: 23px;
+ font-size: 9px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-card > .semi-card-body {
+ gap: 8px;
+ padding: 11px 12px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-summary {
+ gap: 5px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-summary > span {
+ display: flex;
+ min-width: 0;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-summary strong {
+ color: #354b63;
+ font-size: 12px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-summary small {
+ font-size: 9px;
+}
+
+.v2-history-export-sidesheet .v2-export-job-card .v2-export-download.semi-button {
+ min-width: 66px;
+ height: 30px;
+ flex: 0 0 auto;
+ justify-content: center;
+ border-radius: 7px;
+ background: #edf5ff;
+ font-size: 10px;
+}
+
+.v2-rule-form-sections {
+ display: grid;
+ gap: 12px;
+ background: #f5f7fa;
+ padding: 14px 15px 18px;
+}
+
+.v2-rule-form-section {
+ overflow: hidden;
+ border: 1px solid #dce5ef;
+ border-radius: 11px;
+ background: #fff;
+ box-shadow: 0 6px 20px rgba(31, 53, 80, .045);
+}
+
+.v2-rule-form-section > header {
+ min-height: 54px;
+ border-bottom: 1px solid #e5ebf2;
+ background: linear-gradient(180deg, #fff 0%, #fbfcfe 100%);
+ padding: 10px 13px;
+}
+
+.v2-rule-form-section > header > span {
+ display: grid;
+ gap: 3px;
+}
+
+.v2-rule-form-section > header h6.semi-typography {
+ margin: 0;
+ color: #2a4058;
+ font-size: 13px;
+ font-weight: 720;
+}
+
+.v2-rule-form-section > header small {
+ color: #8390a2;
+ font-size: 10px;
+ line-height: 1.45;
+}
+
+.v2-rule-form-section > .v2-rule-form-grid {
+ gap: 13px 15px;
+ padding: 14px;
+}
+
+@media (max-width: 680px) {
+ :is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet).semi-sidesheet-bottom .semi-sidesheet-inner {
+ width: 100% !important;
+ max-width: 100%;
+ border: 1px solid #d8e2ed;
+ border-bottom: 0;
+ border-radius: 18px 18px 0 0;
+ box-shadow: 0 -18px 48px rgba(23, 43, 68, .18);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+
+ :is(.v2-workspace-task-sidesheet, .v2-workspace-editor-sidesheet).semi-sidesheet-bottom .semi-sidesheet-header {
+ min-height: 70px;
+ padding: 10px 12px 10px 14px;
+ }
+
+ .v2-workspace-task-sidesheet .v2-workspace-config-content {
+ padding: 8px;
+ }
+
+ .v2-export-job-overview {
+ min-height: 72px;
+ }
+
+ .v2-export-job-overview > span {
+ gap: 2px;
+ padding: 9px 10px;
+ }
+
+ .v2-export-job-overview small {
+ font-size: 8px;
+ }
+
+ .v2-export-job-overview strong {
+ font-size: 17px;
+ }
+
+ .v2-export-job-overview em {
+ font-size: 7px;
+ }
+
+ .v2-history-export-sidesheet .v2-export-job-list {
+ padding: 8px;
+ }
+
+ .v2-history-export-sidesheet .v2-export-job-name {
+ max-width: 220px;
+ font-size: 11px;
+ }
+
+ .v2-history-export-sidesheet .v2-export-job-summary strong {
+ font-size: 11px;
+ }
+
+ .v2-history-export-sidesheet .v2-export-job-summary small {
+ font-size: 8px;
+ }
+
+ .v2-rule-form-sections {
+ gap: 9px;
+ padding: 9px 9px 14px;
+ }
+
+ .v2-rule-form-section {
+ border-radius: 10px;
+ }
+
+ .v2-rule-form-section > header {
+ min-height: 50px;
+ padding: 9px 11px;
+ }
+
+ .v2-rule-form-section > header h6.semi-typography {
+ font-size: 12px;
+ }
+
+ .v2-rule-form-section > header small {
+ font-size: 9px;
+ }
+
+ .v2-rule-form-section > .v2-rule-form-grid {
+ grid-template-columns: 1fr;
+ gap: 12px;
+ padding: 12px 11px 14px;
+ }
+
+ .v2-rule-form-section > .v2-rule-form-grid label.is-wide {
+ grid-column: auto;
+ }
+}
|---|