Skip to content

Commit 75d0892

Browse files
feat: application workflow
1 parent 5fa1843 commit 75d0892

14 files changed

Lines changed: 288 additions & 331 deletions

‎ui/src/api/API_README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ Action、Drawer 或 Dialog。复用方直接使用 `typeof XxxApi` 约束完整
101101
`getWorkflowVersions(applicationId)` 返回按创建时间倒序的完整 `WorkflowVersion[]`;
102102
`putWorkflowVersion(applicationId, versionId, payload)` 编辑标题与更新说明,返回更新后的版本。
103103
共用类型 `WorkflowVersion` 和 `WorkflowVersionPayload` 位于 `types/workflow-version.ts`,
104-
通过 `@/api/types` 导出。页面传入完整 API 对象,发布历史面板不推测其他工作流的接口地址。
104+
通过 `@/api/types` 导出。`ButtonApplicationPublishHistory` 内部调用智能体版本 API,公共发布历史
105+
UI 组件只接收数据和事件,不接收 API 或推测其他工作流的接口地址。
105106

106107
v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明上限 1000。
107108
当前仓库后端的版本编辑序列化器只处理 `name`,列表和详情也未返回 `description`;

‎ui/src/components/global/mk-list-item/index.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const hasActionDropdown = computed(() => hasRenderableSlotContent(slots['action-
3939
<!-- 操作区保留布局宽度,hover/focus 时显示,并阻止触发行点击。 -->
4040
<div v-if="$slots.action || hasActionDropdown" class="group-hover-visible ml-auto flex shrink-0 items-center font-normal text-N900" @click.stop @keydown.stop>
4141
<MkDropdown v-if="hasActionDropdown" trigger="click" :teleported="false">
42-
<el-button class="-mr-1" text>
42+
<el-button text>
4343
<MkIcon name="icon_more_outlined" />
4444
</el-button>
4545
<template #dropdown>

‎ui/src/styles/variables.scss‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111
--mk-success-rgb: 52 199 36;
1212
--mk-warning: #ff8800;
1313
--mk-warning-rgb: 255 136 0;
14-
// --mk-layout-gradient: linear-gradient(
15-
// 187.61deg,
16-
// rgba(235, 241, 255, 0.35) 39.6%,
17-
// rgba(231, 249, 255, 0.35) 94.3%
18-
// );
1914

2015
--mk-purple: #7f3bf5;
2116
--mk-blue: #14c0ff;

‎ui/src/views/VIEW_README.md‎

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -410,23 +410,29 @@ Dialog。新增或重命名文件时,应同步更新所有导入和页面功
410410

411411
## 工作流发布历史
412412

413-
`workflow/components/publish-history/ButtonPublishHistory.vue` 封装发布历史菜单入口与面板挂载,
414-
通过 `v-model:visible` 与页面共享显隐状态,接收 `resourceId`、完整版本 `api`、`selectedId` 和
415-
`disabled`,转发 `preview`、`restore`、`update`、`close`,打开时发出 `open`。
416-
面板通过 Teleport 展示在页面右侧、头部下方,页面无需再单独引用 `PublishHistory`。
417-
所在的 `MkDropdown` 必须设置 `persistent`,避免菜单收起后销毁面板入口。
418-
419-
`workflow/components/publish-history/PublishHistory.vue` 为工作流页面共用的发布历史面板,
420-
接收 `resourceId`、完整版本 `api`、`selectedId` 和 `disabled`。挂载时查询列表,保留服务端
421-
发布时间倒序,首项标记“最近发布”;显示标题、发布人和创建时间。面板绝对定位在父级右侧,
422-
调用方提供相对定位容器。通过 `preview(version)`、`restore(version)`、`update(version)` 和
423-
`close` 将画布与页面动作交给 View,不读取路由或操作画布。
424-
425-
同目录 `EditPublishVersionDialog.vue` 使用 `open(version)` 回填副本:标题必填、最多 64 字,
426-
更新说明可选、最多 1000 字;确认按钮沿设计显示“发布”,调用版本编辑接口,不创建新发布。
427-
成功后更新列表及预览标题,失败保留弹窗与草稿,提交期间禁止重复提交和关闭。
428-
`UpdateDescriptionDialog.vue` 通过 `open(content)` 展示纯文本更新说明,保留换行,无内容时显示
429-
“暂无更新说明”;两者复用 `MkDialog` 的延迟挂载与关闭销毁能力。
413+
`workflow/application/ButtonPublishHistory.vue` 封装智能体发布历史菜单入口、
414+
面板显隐、列表查询以及版本编辑请求。内部直接调用 application 的版本 API;页面仅传
415+
`applicationId`、`selectedId`、`disabled` 和 `v-model:visible`,接收 `open`、`preview`、
416+
`restore` 事件。每次打开重新查询,编辑成功后关闭弹窗并重新调用 `getWorkflowVersions` 刷新列表,
417+
不向页面发送更新事件;保存失败保留弹窗与草稿。所在 `MkDropdown` 设置 `persistent`,避免收起菜单时销毁面板入口。
418+
419+
`workflow/components/publish-history/PublishHistoryDrawer.vue` 为纯 UI 面板,接收 `versions`、`loading`、
420+
`saving`、`selectedId`,保留传入顺序并将首项标为“最近发布”,显示标题、发布人及创建时间。
421+
内部管理编辑与更新说明弹窗,通过 `submit(payload, versionId)` 交给业务组件保存,成功后由业务组件
422+
调用 `closeEdit()` 关闭编辑弹窗。通过 `preview`、`restore` 通知业务组件,不接收 API、不查询数据,
423+
也不操作路由或画布。面板复用 `MkDrawer`,通过 `v-model` 控制显隐,宽度 320,使用
424+
`top-header`、`h-layout-content` 留出页面头部,不显示遮罩、不锁定滚动,内部复用 Drawer 的滚动区。
425+
抽屉实例保留,由 `MkDrawer` 延迟渲染并在关闭动画结束后销毁内容,不再额外维护挂载状态或转发
426+
`close` / `closed` 事件。页面监听 `historyVisible`,关闭抽屉与头部返回统一恢复草稿并清理预览;
427+
恢复版本时先清空草稿快照再关闭,保留已恢复的版本。编辑弹窗的 `closeEdit()` 仅用于保存成功后关闭表单。
428+
429+
同目录 `EditPublishVersionDialog.vue` 只维护表单副本与校验,通过 `open(version)` 回填、
430+
`submit(payload)` 提交、`close()` 关闭,外部传入 `saving`。标题必填且最多 64 字,更新说明最多
431+
1000 字;按钮沿设计显示“发布”,实际编辑请求由业务组件执行,不创建新发布。
432+
`DescriptionDialog.vue` 通过 `open(content)` 展示纯文本更新说明并保留换行,空内容显示
433+
“暂无更新说明”。两个弹窗均不依赖业务 API,复用 `MkDialog` 的延迟挂载和关闭销毁能力。
434+
435+
后续 knowledge、tool 在各自目录实现业务入口,复用 `PublishHistoryDrawer`(内部包含两个弹窗),不引入通用 API 适配层。
430436

431437
`ApplicationWorkflowView` 已接入更多菜单中的发布历史。打开时关闭调试,面板打开期间跳过
432438
自动保存;首次预览保留当前画布草稿,切换版本不覆盖草稿,关闭预览恢复原草稿。

‎ui/src/views/workflow/application/ApplicationWorkflowView.vue‎

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<script setup lang="ts">
2-
import { nextTick, onBeforeUnmount, onMounted, provide, ref, useTemplateRef } from 'vue'
2+
import { nextTick, onBeforeUnmount, onMounted, provide, ref, useTemplateRef, watch } from 'vue'
33
import { useRoute } from 'vue-router'
44
import type LogicFlow from '@logicflow/core'
55
import type { Action } from 'element-plus'
66
import { cloneDeep } from 'lodash'
77
import ApplicationApi from '@/api/admin/workspace/application/application.ts'
8-
import WorkflowVersionApi from '@/api/admin/workspace/application/workflow-version'
98
import ModelApi from '@/api/admin/workspace/model/model'
109
import type { ApplicationDetail, ApplicationStoreTemplate, DefaultModelSettingPayload, WorkflowVersion } from '@/api/types'
1110
import { MsgConfirm, MsgError, MsgSuccess } from '@/utils/message'
@@ -14,7 +13,7 @@ import { defaultApplicationNodes } from '@/workflow-canvas/config/node-mapping'
1413
import { WorkflowMode } from '@/workflow-canvas/types'
1514
import ButtonDefaultModelSetting from '../components/default-model-setting/ButtonDefaultModelSetting.vue'
1615
import WorkflowViewLayout from '../components/WorkflowViewLayout.vue'
17-
import ButtonPublishHistory from '../components/publish-history/ButtonPublishHistory.vue'
16+
import ButtonPublishHistory from './ButtonPublishHistory.vue'
1817
import TemplateStoreDialog from '@/views/application/template-store/TemplateStoreDialog.vue'
1918
import DebugPanel from './debug/DebugPanel.vue'
2019
import { getResourceScope } from '@/utils/resource-context.ts'
@@ -151,26 +150,22 @@ function handlePreviewVersion(version: WorkflowVersion) {
151150
nextTick(() => workflowRef.value?.fitView())
152151
}
153152
154-
function handleCloseHistory() {
153+
// 所有退出入口统一通过显隐状态清理预览;恢复版本时提前清空草稿快照。
154+
watch(historyVisible, (visible) => {
155+
if (visible) return
155156
if (workflowBeforePreview) workflowRef.value?.render(cloneDeep(workflowBeforePreview))
156157
workflowBeforePreview = undefined
157158
previewVersion.value = undefined
158-
historyVisible.value = false
159-
}
159+
})
160160
161161
function handleRestoreVersion(version = previewVersion.value) {
162162
if (!version || loading.value || saving.value || publishing.value) return
163163
workflowRef.value?.render(cloneDeep(version.work_flow))
164164
workflowBeforePreview = undefined
165-
previewVersion.value = undefined
166165
historyVisible.value = false
167166
nextTick(() => workflowRef.value?.fitView())
168167
}
169168
170-
function handleUpdateVersion(version: WorkflowVersion) {
171-
if (previewVersion.value?.id === version.id) previewVersion.value = version
172-
}
173-
174169
/* 模板中心 */
175170
const templateStoreDialogRef = useTemplateRef<InstanceType<typeof TemplateStoreDialog>>('templateStoreDialogRef')
176171
@@ -219,26 +214,25 @@ function handleSaveDefaultModelSetting(settings: DefaultModelSettingPayload) {
219214
/* 发布工作流 */
220215
function handlePublish() {
221216
workflowRef.value?.validate().then(() => {
222-
// publishing.value = true
223-
// return saveApplication(undefined, false)
224-
// .then(() => ApplicationApi.putApplicationPublish(applicationId))
225-
// .then((application) => {
226-
// applicationDetail.value = application
227-
// saveTime.value = application.update_time || saveTime.value
228-
// MsgSuccess('发布成功')
229-
// })
230-
// .finally(() => {
231-
// publishing.value = false
232-
// })
217+
publishing.value = true
218+
return saveApplication(undefined, false)
219+
.then(() => ApplicationApi.putApplicationPublish(applicationId))
220+
.then((application) => {
221+
applicationDetail.value = application
222+
saveTime.value = application.update_time || saveTime.value
223+
MsgSuccess('发布成功')
224+
})
225+
.finally(() => {
226+
publishing.value = false
227+
})
233228
})
234229
}
235230
236231
/* 退出工作流 */
237232
function handleBack() {
238233
if (loading.value || saving.value || confirmingExit.value) return
239234
if (historyVisible.value) {
240-
handleCloseHistory()
241-
return
235+
historyVisible.value = false
242236
}
243237
if (!hasUnsavedChanges()) {
244238
goBack(applicationId)
@@ -301,7 +295,7 @@ onBeforeUnmount(() => stopAutoSave())
301295
:title="applicationDetail?.name"
302296
:save-time="saveTime"
303297
:history-visible="historyVisible"
304-
:can-restore-version="!!previewVersion && !loading && !saving && !publishing"
298+
:can-restore-version="!!previewVersion"
305299
@back="handleBack"
306300
@restore-version="handleRestoreVersion()"
307301
>
@@ -355,15 +349,11 @@ onBeforeUnmount(() => stopAutoSave())
355349
<!-- 发布历史 -->
356350
<ButtonPublishHistory
357351
v-model:visible="historyVisible"
358-
:resource-id="applicationId"
359-
:api="WorkflowVersionApi"
352+
:application-id="applicationId"
360353
:selected-id="previewVersion?.id"
361-
:disabled="loading || saving || publishing"
362354
@open="closeDebug"
363355
@preview="handlePreviewVersion"
364356
@restore="handleRestoreVersion"
365-
@update="handleUpdateVersion"
366-
@close="handleCloseHistory"
367357
/>
368358
<!-- 自动保存 -->
369359
<MkDropdownItem @click.stop>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<script setup lang="ts">
2+
import { ref, useTemplateRef } from 'vue'
3+
import WorkflowVersionApi from '@/api/admin/workspace/application/workflow-version'
4+
import type { WorkflowVersion, WorkflowVersionPayload } from '@/api/types'
5+
import { MsgSuccess } from '@/utils/message'
6+
import PublishHistoryDrawer from '@/views/workflow/components/publish-history/PublishHistoryDrawer.vue'
7+
8+
defineOptions({ name: 'ButtonApplicationPublishHistory' })
9+
10+
const props = defineProps<{ applicationId: string; selectedId?: string; disabled?: boolean }>()
11+
const visible = defineModel<boolean>('visible', { default: false })
12+
const emit = defineEmits<{
13+
open: []
14+
preview: [version: WorkflowVersion]
15+
restore: [version: WorkflowVersion]
16+
}>()
17+
18+
/* 智能体发布历史查询 */
19+
const versions = ref<WorkflowVersion[]>([])
20+
const loading = ref(false)
21+
22+
function handleOpen() {
23+
visible.value = true
24+
emit('open')
25+
versions.value = []
26+
return loadWorkflowVersions()
27+
}
28+
29+
function loadWorkflowVersions() {
30+
loading.value = true
31+
return WorkflowVersionApi.getWorkflowVersions(props.applicationId)
32+
.then((result) => {
33+
versions.value = result
34+
})
35+
.finally(() => {
36+
loading.value = false
37+
})
38+
}
39+
40+
/* 版本编辑:成功后重新查询列表,保存失败保留弹窗草稿。 */
41+
const saving = ref(false)
42+
const publishHistoryDrawerRef = useTemplateRef<InstanceType<typeof PublishHistoryDrawer>>('publishHistoryDrawerRef')
43+
44+
function handleSubmit(payload: WorkflowVersionPayload, versionId?: string) {
45+
saving.value = true
46+
if (versionId) {
47+
return WorkflowVersionApi.putWorkflowVersion(props.applicationId, versionId, payload)
48+
.then(() => {
49+
publishHistoryDrawerRef.value?.closeEdit()
50+
MsgSuccess('修改成功')
51+
return loadWorkflowVersions()
52+
})
53+
.finally(() => {
54+
saving.value = false
55+
})
56+
} else {
57+
return
58+
}
59+
}
60+
</script>
61+
62+
<template>
63+
<!-- 打开智能体发布历史 -->
64+
<MkDropdownItem :disabled="disabled || loading || saving" @click="handleOpen">
65+
<template #icon><MkIcon name="icon_history_outlined" /></template>
66+
<span>发布历史</span>
67+
</MkDropdownItem>
68+
<!-- 发布历史抽屉:由 MkDrawer 按需渲染内容。 -->
69+
<PublishHistoryDrawer
70+
ref="publishHistoryDrawerRef"
71+
v-model="visible"
72+
:versions="versions"
73+
:loading="loading"
74+
:selected-id="selectedId"
75+
@preview="emit('preview', $event)"
76+
@restore="emit('restore', $event)"
77+
@submit="handleSubmit"
78+
/>
79+
</template>

‎ui/src/views/workflow/components/WorkflowViewLayout.vue‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,7 @@ defineSlots<{
4141

4242
<div class="flex shrink-0 items-center">
4343
<!-- 恢复选中的历史版本 -->
44-
<el-button
45-
v-if="historyVisible"
46-
:type="canRestoreVersion ? 'primary' : 'info'"
47-
:disabled="!canRestoreVersion"
48-
@click="emit('restoreVersion')"
49-
>
50-
恢复此版本
51-
</el-button>
44+
<el-button v-if="historyVisible" type="primary" :disabled="!canRestoreVersion" @click="emit('restoreVersion')"> 恢复此版本 </el-button>
5245
<!-- 保留操作入口实例,避免切换头部时卸载其发布历史面板。 -->
5346
<div v-show="!historyVisible" class="flex items-center">
5447
<slot name="actions" />

‎ui/src/views/workflow/components/default-model-setting/DefaultModelSettingDrawer.vue‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,6 @@ function handleClosed() {
176176
emit('closed')
177177
}
178178
179-
function resetData() {
180-
savedSettings.value = {}
181-
modelSettings.value = normalizeSettings({})
182-
models.value = []
183-
providerOptions.value = []
184-
loading.value = false
185-
applying.value = false
186-
}
187-
188179
function handleBeforeClose(
189180
done = () => {
190181
visible.value = false
@@ -207,6 +198,14 @@ function handleBeforeClose(
207198
if (action === 'cancel') done()
208199
})
209200
}
201+
function resetData() {
202+
savedSettings.value = {}
203+
modelSettings.value = normalizeSettings({})
204+
models.value = []
205+
providerOptions.value = []
206+
loading.value = false
207+
applying.value = false
208+
}
210209
defineExpose({ open })
211210
</script>
212211

@@ -217,6 +216,7 @@ defineExpose({ open })
217216
size="420"
218217
class="top-header! h-layout-content! max-w-full rounded-tl-xl!"
219218
:modal="false"
219+
modal-penetrable
220220
:lock-scroll="false"
221221
:before-close="handleBeforeClose"
222222
@closed="handleClosed"

‎ui/src/views/workflow/components/publish-history/ButtonPublishHistory.vue‎

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)