feat(flow): 添加流程信息展示组件及后端支持
新增左上角流程信息展示组件,显示流程编码和名称 后端 FlowDoc 结构增加 name/code/remark 字段支持 添加从 YAML 提取名称的兜底逻辑
This commit is contained in:
@ -14,7 +14,7 @@ import { TestRunButton } from '../testrun/testrun-button';
|
||||
import { AddNode } from '../add-node';
|
||||
import { ZoomSelect } from './zoom-select';
|
||||
import { SwitchLine } from './switch-line';
|
||||
import { ToolContainer, ToolSection } from './styles';
|
||||
import { ToolContainer, ToolSection, FlowInfoBadge } from './styles';
|
||||
import { Readonly } from './readonly';
|
||||
import { MinimapSwitch } from './minimap-switch';
|
||||
import { Minimap } from './minimap';
|
||||
@ -29,6 +29,8 @@ import { Save } from './save';
|
||||
// 基础信息编辑:对齐新建流程弹窗,使用 Antd 的 Modal/Form
|
||||
import { Modal as AModal, Form as AForm, Input as AInput, message } from 'antd'
|
||||
import api from '../../../utils/axios'
|
||||
// 新增:兜底从 YAML 提取流程名称
|
||||
import { parseFlowYaml } from '../../utils/yaml'
|
||||
|
||||
// 兼容 BrowserRouter 与 HashRouter:优先从 search 获取,若无则从 hash 的查询串中获取
|
||||
function getFlowIdFromUrl(): string {
|
||||
@ -70,6 +72,44 @@ export const FlowTools = () => {
|
||||
const [baseLoading, setBaseLoading] = useState(false)
|
||||
const [baseForm] = AForm.useForm()
|
||||
|
||||
// 新增:显示名称与编码的状态
|
||||
const [metaLoading, setMetaLoading] = useState(false)
|
||||
const [flowName, setFlowName] = useState<string>('')
|
||||
const [flowCode, setFlowCode] = useState<string>('')
|
||||
|
||||
const loadFlowMeta = async () => {
|
||||
const id = getFlowIdFromUrl()
|
||||
if (!id) { setFlowName(''); setFlowCode(''); return }
|
||||
try{
|
||||
setMetaLoading(true)
|
||||
const { data } = await api.get(`/flows/${id}`)
|
||||
const detail: any = data?.data || {}
|
||||
const yaml = String(detail?.yaml || '')
|
||||
const nameFromYaml = (() => { try { return parseFlowYaml(yaml).name || '' } catch { return '' } })()
|
||||
const nextName = String(detail?.name || nameFromYaml || '')
|
||||
const nextCode = String(detail?.code || id)
|
||||
setFlowName(nextName)
|
||||
setFlowCode(nextCode)
|
||||
}catch(e:any){
|
||||
// 失败时至少展示 ID,确保可识别
|
||||
setFlowName('')
|
||||
setFlowCode(id)
|
||||
}finally{
|
||||
setMetaLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadFlowMeta()
|
||||
const handler = () => loadFlowMeta()
|
||||
window.addEventListener('hashchange', handler)
|
||||
window.addEventListener('popstate', handler)
|
||||
return () => {
|
||||
window.removeEventListener('hashchange', handler)
|
||||
window.removeEventListener('popstate', handler)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const openBaseInfo = async () => {
|
||||
setBaseOpen(true)
|
||||
// 预填现有数据
|
||||
@ -111,6 +151,8 @@ export const FlowTools = () => {
|
||||
if (data?.code === 0){
|
||||
message.success('已保存')
|
||||
setBaseOpen(false)
|
||||
// 保存后刷新顶部信息
|
||||
loadFlowMeta()
|
||||
}else{
|
||||
throw new Error(data?.message || '保存失败')
|
||||
}
|
||||
@ -124,6 +166,19 @@ export const FlowTools = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 左上角流程信息展示 */}
|
||||
{(flowName || flowCode) && (
|
||||
<FlowInfoBadge>
|
||||
{flowCode ? <span className="code">{flowCode}</span> : null}
|
||||
{flowName ? <span className="name" title={flowName}>{flowName}</span> : null}
|
||||
<span className="actions">
|
||||
<Tooltip content={I18n.t('Edit Base Info')}>
|
||||
<IconButton type="tertiary" theme="borderless" icon={<IconEdit />} onClick={openBaseInfo} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</FlowInfoBadge>
|
||||
)}
|
||||
|
||||
<ToolContainer className="flow-tools">
|
||||
<ToolSection>
|
||||
{/* 返回列表 */}
|
||||
@ -136,16 +191,6 @@ export const FlowTools = () => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider layout="vertical" style={{ height: '16px' }} margin={3} />
|
||||
{/* 基础信息(名称/编号/备注) */}
|
||||
<Tooltip content={I18n.t('Edit Base Info')}>
|
||||
<IconButton
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
icon={<IconEdit />}
|
||||
onClick={openBaseInfo}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider layout="vertical" style={{ height: '16px' }} margin={3} />
|
||||
<Interactive />
|
||||
<AutoLayout />
|
||||
<SwitchLine />
|
||||
|
||||
@ -50,3 +50,50 @@ export const MinimapContainer = styled.div`
|
||||
export const UIIconMinimap = styled(IconMinimap)<{ visible: boolean }>`
|
||||
color: ${(props) => (props.visible ? undefined : '#060709cc')};
|
||||
`;
|
||||
|
||||
// 新增:左上角流程信息展示(编码 + 名称)
|
||||
export const FlowInfoBadge = styled.div`
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(68, 83, 130, 0.25);
|
||||
border-radius: 8px;
|
||||
box-shadow: rgba(0, 0, 0, 0.04) 0px 2px 6px 0px, rgba(0, 0, 0, 0.02) 0px 4px 12px 0px;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
z-index: 100;
|
||||
pointer-events: auto;
|
||||
max-width: 60vw;
|
||||
|
||||
.code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
color: #2f54eb;
|
||||
background: #f0f5ff;
|
||||
border: 1px solid #adc6ff;
|
||||
border-radius: 6px;
|
||||
padding: 2px 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-left: 8px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user