feat: 编辑器交互优化——圆形返回键、名称块居中、面板按钮悬停动画、删除移至右上角

- 返回键改圆形按钮:悬停变蓝+箭头左移动画,面包屑仅留「编辑流程」
- 流程名称块保持工具栏绝对居中
- 保存/运行按钮悬停动画(弹性缩放/上浮光晕);撤销重做保持静态
- 节点复制/删除移至属性面板右上角,删除悬停红色更醒目
This commit is contained in:
yu 2026-10-29 16:28:25 +08:00
parent 543d5d1564
commit 0694bd45d3
3 changed files with 102 additions and 26 deletions

View File

@ -185,10 +185,9 @@ export function EditorPage({ catalog, onToast, onBack }: EditorPageProps) {
<section className="panel canvas-panel" aria-label="流程画布">
<div className="canvas-toolbar">
<div className="editor-breadcrumb">
<button type="button" className="back-link" onClick={onBack}>
<ArrowLeft className="icon" /> 任务中心
<button type="button" className="back-btn" onClick={onBack} title="返回任务中心" aria-label="返回任务中心">
<ArrowLeft className="icon" />
</button>
<span className="breadcrumb-sep">/</span>
<span className="breadcrumb-current">编辑流程</span>
</div>
@ -223,7 +222,7 @@ export function EditorPage({ catalog, onToast, onBack }: EditorPageProps) {
<button type="button" className="icon-btn" title="重做 (Ctrl+Y)" onClick={redo} disabled={!canRedo}>
<Redo2 className="icon" />
</button>
<button type="button" className="icon-btn" title="保存 (Ctrl+S)" onClick={() => void save({ interactive: true })} disabled={saving}>
<button type="button" className="icon-btn save-btn" title="保存 (Ctrl+S)" onClick={() => void save({ interactive: true })} disabled={saving}>
{saving ? <Loader2 className="icon spin" /> : <Save className="icon" />}
</button>
{running ? (

View File

@ -130,6 +130,14 @@ export function Properties({ catalog, onToast }: PropertiesProps) {
<strong className="props-title">{node.label || component.name}</strong>
<span className="props-id">{component.id}</span>
</div>
<div className="props-head-actions">
<button type="button" className="icon-btn head-action" title="复制节点" onClick={() => duplicateNode(node.id)}>
<Copy className="icon" />
</button>
<button type="button" className="icon-btn head-action head-action-danger" title="删除节点" onClick={() => removeNode(node.id)}>
<Trash2 className="icon" />
</button>
</div>
</div>
<div className="tabs" role="tablist">
@ -174,14 +182,6 @@ export function Properties({ catalog, onToast }: PropertiesProps) {
<div className="props-foot">
<span>{component.implemented ? "已接入执行器" : "待接入执行器"}</span>
<div style={{ display: "flex", gap: 4 }}>
<button type="button" className="icon-btn" title="复制节点" onClick={() => duplicateNode(node.id)}>
<Copy className="icon" />
</button>
<button type="button" className="icon-btn" title="删除节点" onClick={() => removeNode(node.id)}>
<Trash2 className="icon" />
</button>
</div>
</div>
</>
) : (

View File

@ -682,6 +682,39 @@ textarea:focus-visible {
border-color: var(--line);
}
/* 保存按钮:悬停泛蓝 + 图标弹性放大,呼应"落盘"动作 */
.icon-btn.save-btn:not(:disabled):hover {
color: var(--blue);
border-color: var(--blue);
background: var(--blue-soft);
}
.icon-btn.save-btn:not(:disabled):hover .icon {
animation: save-pop 0.32s ease;
}
@keyframes save-pop {
0% { transform: scale(1); }
45% { transform: scale(1.22) translateY(1px); }
100% { transform: scale(1); }
}
/* 运行按钮:悬停上浮 + 光晕阴影 + 播放图标微放大 */
.toolbar-actions .btn-primary:not(:disabled):hover,
.toolbar-actions .btn-danger:not(:disabled):hover {
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(34, 100, 229, 0.32);
}
.toolbar-actions .btn-primary:not(:disabled):hover .icon {
transform: scale(1.12);
}
.toolbar-actions .btn-primary .icon,
.toolbar-actions .btn-danger .icon {
transition: transform 0.16s ease;
}
.icon-btn:disabled {
opacity: 0.4;
cursor: default;
@ -1018,6 +1051,37 @@ textarea:focus-visible {
flex: none;
}
/* 节点复制/删除:移到面板右上角,删除红色更醒目 */
.props-head-actions {
margin-left: auto;
display: flex;
gap: 4px;
flex: none;
}
.props-head-actions .head-action {
width: 28px;
height: 28px;
border-radius: 8px;
transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}
.props-head-actions .head-action:hover {
transform: translateY(-1px);
}
.props-head-actions .head-action:not(.head-action-danger):hover {
color: var(--blue);
border-color: var(--blue);
background: var(--blue-soft);
}
.props-head-actions .head-action-danger:hover {
color: #d64545;
border-color: #f2b8b8;
background: #fdeeee;
}
.props-icon {
width: 34px;
height: 34px;
@ -3229,7 +3293,7 @@ textarea:focus-visible {
.editor-breadcrumb {
display: flex;
align-items: center;
gap: 7px;
gap: 10px;
color: var(--ink-2);
font-size: 12.5px;
flex: none;
@ -3245,27 +3309,40 @@ textarea:focus-visible {
font-weight: 650;
}
.back-link {
/* 圆形返回按钮:边框 + 悬停反馈(背景加深 + 箭头左移动画),明确表达"返回" */
.back-btn {
display: inline-flex;
align-items: center;
gap: 5px;
color: var(--blue-dark);
font-size: 12.5px;
font-weight: 650;
padding: 4px 8px;
margin-left: -8px;
border-radius: 8px;
transition: background 0.14s ease;
justify-content: center;
width: 30px;
height: 30px;
padding: 0;
border: 1px solid var(--line);
border-radius: 50%;
background: #fff;
color: var(--ink-2);
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.back-link:hover {
.back-btn .icon {
width: 15px;
height: 15px;
transition: transform 0.15s ease;
}
.back-btn:hover {
border-color: var(--blue);
color: var(--blue);
background: var(--blue-soft);
}
.back-link .icon {
width: 15px;
height: 15px;
.back-btn:hover .icon {
transform: translateX(-2px);
}
.back-btn:active {
transform: scale(0.94);
}
.rpa-error-handle {