Commit f8552a6a authored by drigle's avatar drigle

style: unify process group tabs and refine card spacing

parent 6f8a35a9
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
} }
.process-page__topbar { .process-page__topbar {
display: flex; display: flex;
align-items: flex-start; align-items: center;
gap: 16px; gap: 16px;
min-width: 0; min-width: 0;
} }
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
top: 0; top: 0;
z-index: 10; z-index: 10;
isolation: isolate; isolation: isolate;
background: var(--rc-bg-canvas); background: var(--surface);
padding: 16px 20px;
border-radius: 20px;
} }
.process-page__tabs { .process-page__tabs {
flex: 1 1 auto; flex: 1 1 auto;
...@@ -35,28 +37,32 @@ ...@@ -35,28 +37,32 @@
.process-page__tabs .tabs__list { .process-page__tabs .tabs__list {
width: max-content; width: max-content;
min-width: max-content; min-width: max-content;
padding: 0; padding: 4px;
gap: 10px; gap: 12px;
background: transparent;
} }
.process-page__tabs .tabs__tab { .process-page__tabs .tabs__tab {
flex: 0 0 auto; flex: 0 0 auto;
} }
.process-page__tabs .tabs__list-container, .process-page__tabs .tabs__list-container,
.process-page__tabs .tabs__list-container__scroller { .process-page__tabs .tabs__list-container__scroller {
padding-bottom: 2px; background: transparent;
scroll-padding-left: 2px; border-radius: 0;
scroll-padding-inline: 4px;
} }
.process-group-tab { .process-group-tab {
position: relative; position: relative;
width: 180px; width: 184px;
min-width: 180px; min-width: 184px;
min-height: 74px; height: auto;
min-height: 92px;
align-self: stretch;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
white-space: normal; white-space: normal;
text-align: start; text-align: start;
border: 1px solid var(--separator); border: 1px solid var(--separator);
border-radius: 10px; border-radius: 14px;
background: var(--surface); background: var(--surface);
box-shadow: 0 1px 2px rgb(0 0 0 / 0.03); box-shadow: 0 1px 2px rgb(0 0 0 / 0.03);
transition: transition:
...@@ -67,17 +73,20 @@ ...@@ -67,17 +73,20 @@
.process-group-tab[aria-selected="true"], .process-group-tab[aria-selected="true"],
.process-group-tab[data-selected="true"] { .process-group-tab[data-selected="true"] {
border-color: color-mix(in oklab, var(--accent) 58%, var(--separator)); border-color: color-mix(in oklab, var(--accent) 58%, var(--separator));
background: color-mix(in oklab, var(--accent) 7%, var(--surface)); background: var(--surface);
box-shadow: 0 1px 2px rgb(0 0 0 / 0.04); box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 10%, transparent);
} }
.process-group-tab:hover:not([aria-selected="true"], [data-selected="true"]) { .process-group-tab:hover:not([aria-selected="true"], [data-selected="true"]) {
border-color: color-mix(in oklab, var(--accent) 28%, var(--separator)); border-color: color-mix(in oklab, var(--accent) 28%, var(--separator));
background: color-mix(in oklab, var(--accent) 3%, var(--surface)); background: var(--surface);
box-shadow: 0 2px 6px rgb(0 0 0 / 0.06);
opacity: 1;
} }
.process-group-tab:active:not([aria-selected="true"], [data-selected="true"]) { .process-group-tab:active:not([aria-selected="true"], [data-selected="true"]) {
background: color-mix(in oklab, var(--accent) 5%, var(--surface)); background: color-mix(in oklab, var(--accent) 5%, var(--surface));
} }
.process-group-tab:focus-visible { .process-group-tab:focus-visible,
.process-group-tab[data-focus-visible="true"] {
outline: 2px solid color-mix(in oklab, var(--accent) 72%, var(--separator)); outline: 2px solid color-mix(in oklab, var(--accent) 72%, var(--separator));
outline-offset: 2px; outline-offset: 2px;
} }
...@@ -88,9 +97,10 @@ ...@@ -88,9 +97,10 @@
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
min-height: 70px; min-height: 90px;
padding: 12px 14px; height: 100%;
gap: 10px; padding: 14px 16px;
gap: 12px;
} }
.process-group-tab__title { .process-group-tab__title {
display: block; display: block;
...@@ -111,7 +121,7 @@ ...@@ -111,7 +121,7 @@
} }
.process-group-tab__meta strong { .process-group-tab__meta strong {
color: var(--foreground); color: var(--foreground);
font-size: 22px; font-size: 24px;
font-weight: 600; font-weight: 600;
line-height: 1; line-height: 1;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
...@@ -121,8 +131,14 @@ ...@@ -121,8 +131,14 @@
color: color-mix(in oklab, var(--accent) 72%, var(--foreground)); color: color-mix(in oklab, var(--accent) 72%, var(--foreground));
} }
.process-group-tab .tabs__indicator { .process-group-tab .tabs__indicator {
top: auto;
bottom: 0;
inset-inline-start: 16px;
width: calc(100% - 32px);
height: 3px; height: 3px;
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
background: var(--accent);
box-shadow: none;
} }
.process-editor > .react-flow { .process-editor > .react-flow {
flex: 1; flex: 1;
...@@ -150,8 +166,13 @@ ...@@ -150,8 +166,13 @@
@media (max-width: 760px) { @media (max-width: 760px) {
.process-page__topbar { .process-page__topbar {
flex-direction: column; flex-direction: column;
align-items: stretch;
gap: 12px; gap: 12px;
} }
.process-page__topbar--sticky {
padding: 12px;
border-radius: 16px;
}
.process-page__header { .process-page__header {
order: -1; order: -1;
justify-content: flex-start; justify-content: flex-start;
...@@ -171,3 +192,10 @@ ...@@ -171,3 +192,10 @@
overflow-x: auto; overflow-x: auto;
} }
} }
@media (prefers-reduced-motion: reduce) {
.process-group-tab,
.process-group-tab .tabs__indicator {
transition: none;
}
}
...@@ -823,6 +823,18 @@ export function StatisticCard({ statistic, style }) { ...@@ -823,6 +823,18 @@ export function StatisticCard({ statistic, style }) {
</KPI> </KPI>
); );
} }
export function ProcessGroupTabLabel({ title, count }) {
return (
<span className="process-group-tab__content">
<span className="process-group-tab__title" title={title}>{title}</span>
<span className="process-group-tab__meta">
<strong>{count}</strong>
<span>个流程</span>
</span>
</span>
);
}
export function PageContainer({ export function PageContainer({
children, children,
tabList = [], tabList = [],
......
...@@ -10,6 +10,7 @@ import useQuery from "@/utils/useQuery.js"; ...@@ -10,6 +10,7 @@ import useQuery from "@/utils/useQuery.js";
import { import {
ModalForm, ModalForm,
PageContainer, PageContainer,
ProcessGroupTabLabel,
ProCard, ProCard,
ProForm, ProForm,
ProFormSelect, ProFormSelect,
...@@ -116,8 +117,14 @@ const ProcessFlowGraphContent = () => { ...@@ -116,8 +117,14 @@ const ProcessFlowGraphContent = () => {
const tabList = useMemo(() => { const tabList = useMemo(() => {
return groupList?.map((record) => { return groupList?.map((record) => {
return { return {
label: `${record.title}(${record.metadata.process_list?.length || 0})`, label: (
<ProcessGroupTabLabel
title={record.title}
count={record.metadata?.process_list?.length || 0}
/>
),
key: record.name, key: record.name,
className: "process-group-tab",
}; };
}); });
}, [groupList]); }, [groupList]);
...@@ -308,6 +315,7 @@ const ProcessFlowGraphContent = () => { ...@@ -308,6 +315,7 @@ const ProcessFlowGraphContent = () => {
return ( return (
<PageContainer <PageContainer
className="process-page--group-list"
fixedHeader fixedHeader
tabList={tabList} tabList={tabList}
tabProps={{ tabProps={{
......
...@@ -19,6 +19,7 @@ import { ...@@ -19,6 +19,7 @@ import {
import { import {
ModalForm, ModalForm,
PageContainer, PageContainer,
ProcessGroupTabLabel,
ProForm, ProForm,
ProFormSelect, ProFormSelect,
ProFormText, ProFormText,
...@@ -129,15 +130,10 @@ export default function ProcessList() { ...@@ -129,15 +130,10 @@ export default function ProcessList() {
return groupList?.map((record) => { return groupList?.map((record) => {
return { return {
label: ( label: (
<span className="process-group-tab__content"> <ProcessGroupTabLabel
<span className="process-group-tab__title" title={record.title}> title={record.title}
{record.title} count={record.metadata?.process_list?.length || 0}
</span> />
<span className="process-group-tab__meta">
<strong>{record.metadata.process_list?.length || 0}</strong>
<span>个流程</span>
</span>
</span>
), ),
key: record.name, key: record.name,
className: "process-group-tab", className: "process-group-tab",
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
## 流程列表 ## 流程列表
1. 查询配置指定的 `process_flow_group`(旧查询参数保留 `page=0,page_size=100`)。 1. 查询配置指定的 `process_flow_group`(旧查询参数保留 `page=0,page_size=100`)。
2. 使用 URL `tab` 或第一分组加载详情;分组卡显示名称及流程数量。 2. 使用 URL `tab` 或第一分组加载详情;分组卡显示名称及流程数量。流程管理和流程面板共用 `ProcessGroupTabLabel` 与 HeroUI Tabs 卡片样式:白色卡面、透明 tabs 容器、细边框、圆角及轻阴影;选中时使用主题色边框、标题及底部短线标识,不使用灰色背景。顶部白色容器使用 20px 圆角、左右 20px / 上下 16px 内边距,避免分组卡片及添加按钮贴边;小屏使用 16px 圆角与 12px 内边距。分组较多时横向滚动,小屏操作栏换行,支持键盘切换及焦点提示。
3. 页面向下滚动时,分组卡片与“添加分组”操作栏固定在主内容滚动区顶部,确保切换分组和新增入口持续可见;列表内容从其下方滚动,不遮挡顶部应用导航。 3. 页面向下滚动时,分组卡片与“添加分组”操作栏固定在主内容滚动区顶部,确保切换分组和新增入口持续可见;列表内容从其下方滚动,不遮挡顶部应用导航。
4. 列表展示流程标题、备注、父流程;标题和父流程链接打开详情。 4. 列表展示流程标题、备注、父流程;标题和父流程链接打开详情。
5. 标题关键字在当前分组中筛选,按 `created_at` 倒序排列。保留分页、每页条数和列显示设置。 5. 标题关键字在当前分组中筛选,按 `created_at` 倒序排列。保留分页、每页条数和列显示设置。
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
## 视图面板 ## 视图面板
1. 加载相同分组与分组详情。 1. 加载相同分组与分组详情;顶部与流程管理使用相同的分组名称、流程数量卡片和吸顶间距,切换仍使用 URL `tab`,加载失败仍显示错误及重试入口。
2. `parseGraph` 从 `process_list` 建立 process 节点,根据 `metadata.source` 建立父子连线。 2. `parseGraph` 从 `process_list` 建立 process 节点,根据 `metadata.source` 建立父子连线。
3. Dagre 保留旧 LR 自动布局及节点尺寸;提供缩放、适配视图、MiniMap。 3. Dagre 保留旧 LR 自动布局及节点尺寸;提供缩放、适配视图、MiniMap。
4. 禁止拖动、手工连接和键盘删除;点击标题打开流程详情。 4. 禁止拖动、手工连接和键盘删除;点击标题打开流程详情。
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment