Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

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

v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明上限 1000。
当前仓库后端的版本编辑序列化器只处理 `name`,列表和详情也未返回 `description`;
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/global/mk-list-item/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const hasActionDropdown = computed(() => hasRenderableSlotContent(slots['action-
<!-- 操作区保留布局宽度,hover/focus 时显示,并阻止触发行点击。 -->
<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>
<MkDropdown v-if="hasActionDropdown" trigger="click" :teleported="false">
<el-button class="-mr-1" text>
<el-button text>
<MkIcon name="icon_more_outlined" />
</el-button>
<template #dropdown>
Expand Down
5 changes: 0 additions & 5 deletions ui/src/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
--mk-success-rgb: 52 199 36;
--mk-warning: #ff8800;
--mk-warning-rgb: 255 136 0;
// --mk-layout-gradient: linear-gradient(
// 187.61deg,
// rgba(235, 241, 255, 0.35) 39.6%,
// rgba(231, 249, 255, 0.35) 94.3%
// );

--mk-purple: #7f3bf5;
--mk-blue: #14c0ff;
Expand Down
40 changes: 23 additions & 17 deletions ui/src/views/VIEW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -410,23 +410,29 @@ Dialog。新增或重命名文件时,应同步更新所有导入和页面功

## 工作流发布历史

`workflow/components/publish-history/ButtonPublishHistory.vue` 封装发布历史菜单入口与面板挂载,
通过 `v-model:visible` 与页面共享显隐状态,接收 `resourceId`、完整版本 `api`、`selectedId` 和
`disabled`,转发 `preview`、`restore`、`update`、`close`,打开时发出 `open`。
面板通过 Teleport 展示在页面右侧、头部下方,页面无需再单独引用 `PublishHistory`。
所在的 `MkDropdown` 必须设置 `persistent`,避免菜单收起后销毁面板入口。

`workflow/components/publish-history/PublishHistory.vue` 为工作流页面共用的发布历史面板,
接收 `resourceId`、完整版本 `api`、`selectedId` 和 `disabled`。挂载时查询列表,保留服务端
发布时间倒序,首项标记“最近发布”;显示标题、发布人和创建时间。面板绝对定位在父级右侧,
调用方提供相对定位容器。通过 `preview(version)`、`restore(version)`、`update(version)` 和
`close` 将画布与页面动作交给 View,不读取路由或操作画布。

同目录 `EditPublishVersionDialog.vue` 使用 `open(version)` 回填副本:标题必填、最多 64 字,
更新说明可选、最多 1000 字;确认按钮沿设计显示“发布”,调用版本编辑接口,不创建新发布。
成功后更新列表及预览标题,失败保留弹窗与草稿,提交期间禁止重复提交和关闭。
`UpdateDescriptionDialog.vue` 通过 `open(content)` 展示纯文本更新说明,保留换行,无内容时显示
“暂无更新说明”;两者复用 `MkDialog` 的延迟挂载与关闭销毁能力。
`workflow/application/ButtonPublishHistory.vue` 封装智能体发布历史菜单入口、
面板显隐、列表查询以及版本编辑请求。内部直接调用 application 的版本 API;页面仅传
`applicationId`、`selectedId`、`disabled` 和 `v-model:visible`,接收 `open`、`preview`、
`restore` 事件。每次打开重新查询,编辑成功后关闭弹窗并重新调用 `getWorkflowVersions` 刷新列表,
不向页面发送更新事件;保存失败保留弹窗与草稿。所在 `MkDropdown` 设置 `persistent`,避免收起菜单时销毁面板入口。

`workflow/components/publish-history/PublishHistoryDrawer.vue` 为纯 UI 面板,接收 `versions`、`loading`、
`saving`、`selectedId`,保留传入顺序并将首项标为“最近发布”,显示标题、发布人及创建时间。
内部管理编辑与更新说明弹窗,通过 `submit(payload, versionId)` 交给业务组件保存,成功后由业务组件
调用 `closeEdit()` 关闭编辑弹窗。通过 `preview`、`restore` 通知业务组件,不接收 API、不查询数据,
也不操作路由或画布。面板复用 `MkDrawer`,通过 `v-model` 控制显隐,宽度 320,使用
`top-header`、`h-layout-content` 留出页面头部,不显示遮罩、不锁定滚动,内部复用 Drawer 的滚动区。
抽屉实例保留,由 `MkDrawer` 延迟渲染并在关闭动画结束后销毁内容,不再额外维护挂载状态或转发
`close` / `closed` 事件。页面监听 `historyVisible`,关闭抽屉与头部返回统一恢复草稿并清理预览;
恢复版本时先清空草稿快照再关闭,保留已恢复的版本。编辑弹窗的 `closeEdit()` 仅用于保存成功后关闭表单。

同目录 `EditPublishVersionDialog.vue` 只维护表单副本与校验,通过 `open(version)` 回填、
`submit(payload)` 提交、`close()` 关闭,外部传入 `saving`。标题必填且最多 64 字,更新说明最多
1000 字;按钮沿设计显示“发布”,实际编辑请求由业务组件执行,不创建新发布。
`DescriptionDialog.vue` 通过 `open(content)` 展示纯文本更新说明并保留换行,空内容显示
“暂无更新说明”。两个弹窗均不依赖业务 API,复用 `MkDialog` 的延迟挂载和关闭销毁能力。

后续 knowledge、tool 在各自目录实现业务入口,复用 `PublishHistoryDrawer`(内部包含两个弹窗),不引入通用 API 适配层。

`ApplicationWorkflowView` 已接入更多菜单中的发布历史。打开时关闭调试,面板打开期间跳过
自动保存;首次预览保留当前画布草稿,切换版本不覆盖草稿,关闭预览恢复原草稿。
Expand Down
50 changes: 20 additions & 30 deletions ui/src/views/workflow/application/ApplicationWorkflowView.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, provide, ref, useTemplateRef } from 'vue'
import { nextTick, onBeforeUnmount, onMounted, provide, ref, useTemplateRef, watch } from 'vue'
import { useRoute } from 'vue-router'
import type LogicFlow from '@logicflow/core'
import type { Action } from 'element-plus'
import { cloneDeep } from 'lodash'
import ApplicationApi from '@/api/admin/workspace/application/application.ts'
import WorkflowVersionApi from '@/api/admin/workspace/application/workflow-version'
import ModelApi from '@/api/admin/workspace/model/model'
import type { ApplicationDetail, ApplicationStoreTemplate, DefaultModelSettingPayload, WorkflowVersion } from '@/api/types'
import { MsgConfirm, MsgError, MsgSuccess } from '@/utils/message'
Expand All @@ -14,7 +13,7 @@ import { defaultApplicationNodes } from '@/workflow-canvas/config/node-mapping'
import { WorkflowMode } from '@/workflow-canvas/types'
import ButtonDefaultModelSetting from '../components/default-model-setting/ButtonDefaultModelSetting.vue'
import WorkflowViewLayout from '../components/WorkflowViewLayout.vue'
import ButtonPublishHistory from '../components/publish-history/ButtonPublishHistory.vue'
import ButtonPublishHistory from './ButtonPublishHistory.vue'
import TemplateStoreDialog from '@/views/application/template-store/TemplateStoreDialog.vue'
import DebugPanel from './debug/DebugPanel.vue'
import { getResourceScope } from '@/utils/resource-context.ts'
Expand Down Expand Up @@ -151,26 +150,22 @@ function handlePreviewVersion(version: WorkflowVersion) {
nextTick(() => workflowRef.value?.fitView())
}

function handleCloseHistory() {
// 所有退出入口统一通过显隐状态清理预览;恢复版本时提前清空草稿快照。
watch(historyVisible, (visible) => {
if (visible) return
if (workflowBeforePreview) workflowRef.value?.render(cloneDeep(workflowBeforePreview))
workflowBeforePreview = undefined
previewVersion.value = undefined
historyVisible.value = false
}
})

function handleRestoreVersion(version = previewVersion.value) {
if (!version || loading.value || saving.value || publishing.value) return
workflowRef.value?.render(cloneDeep(version.work_flow))
workflowBeforePreview = undefined
previewVersion.value = undefined
historyVisible.value = false
nextTick(() => workflowRef.value?.fitView())
}

function handleUpdateVersion(version: WorkflowVersion) {
if (previewVersion.value?.id === version.id) previewVersion.value = version
}

/* 模板中心 */
const templateStoreDialogRef = useTemplateRef<InstanceType<typeof TemplateStoreDialog>>('templateStoreDialogRef')

Expand Down Expand Up @@ -219,26 +214,25 @@ function handleSaveDefaultModelSetting(settings: DefaultModelSettingPayload) {
/* 发布工作流 */
function handlePublish() {
workflowRef.value?.validate().then(() => {
// publishing.value = true
// return saveApplication(undefined, false)
// .then(() => ApplicationApi.putApplicationPublish(applicationId))
// .then((application) => {
// applicationDetail.value = application
// saveTime.value = application.update_time || saveTime.value
// MsgSuccess('发布成功')
// })
// .finally(() => {
// publishing.value = false
// })
publishing.value = true
return saveApplication(undefined, false)
.then(() => ApplicationApi.putApplicationPublish(applicationId))
.then((application) => {
applicationDetail.value = application
saveTime.value = application.update_time || saveTime.value
MsgSuccess('发布成功')
})
.finally(() => {
publishing.value = false
})
})
}

/* 退出工作流 */
function handleBack() {
if (loading.value || saving.value || confirmingExit.value) return
if (historyVisible.value) {
handleCloseHistory()
return
historyVisible.value = false
}
if (!hasUnsavedChanges()) {
goBack(applicationId)
Expand Down Expand Up @@ -301,7 +295,7 @@ onBeforeUnmount(() => stopAutoSave())
:title="applicationDetail?.name"
:save-time="saveTime"
:history-visible="historyVisible"
:can-restore-version="!!previewVersion && !loading && !saving && !publishing"
:can-restore-version="!!previewVersion"
@back="handleBack"
@restore-version="handleRestoreVersion()"
>
Expand Down Expand Up @@ -355,15 +349,11 @@ onBeforeUnmount(() => stopAutoSave())
<!-- 发布历史 -->
<ButtonPublishHistory
v-model:visible="historyVisible"
:resource-id="applicationId"
:api="WorkflowVersionApi"
:application-id="applicationId"
:selected-id="previewVersion?.id"
:disabled="loading || saving || publishing"
@open="closeDebug"
@preview="handlePreviewVersion"
@restore="handleRestoreVersion"
@update="handleUpdateVersion"
@close="handleCloseHistory"
/>
<!-- 自动保存 -->
<MkDropdownItem @click.stop>
Expand Down
79 changes: 79 additions & 0 deletions ui/src/views/workflow/application/ButtonPublishHistory.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue'
import WorkflowVersionApi from '@/api/admin/workspace/application/workflow-version'
import type { WorkflowVersion, WorkflowVersionPayload } from '@/api/types'
import { MsgSuccess } from '@/utils/message'
import PublishHistoryDrawer from '@/views/workflow/components/publish-history/PublishHistoryDrawer.vue'

defineOptions({ name: 'ButtonApplicationPublishHistory' })

const props = defineProps<{ applicationId: string; selectedId?: string; disabled?: boolean }>()
const visible = defineModel<boolean>('visible', { default: false })
const emit = defineEmits<{
open: []
preview: [version: WorkflowVersion]
restore: [version: WorkflowVersion]
}>()

/* 智能体发布历史查询 */
const versions = ref<WorkflowVersion[]>([])
const loading = ref(false)

function handleOpen() {
visible.value = true
emit('open')
versions.value = []
return loadWorkflowVersions()
}

function loadWorkflowVersions() {
loading.value = true
return WorkflowVersionApi.getWorkflowVersions(props.applicationId)
.then((result) => {
versions.value = result
})
.finally(() => {
loading.value = false
})
}

/* 版本编辑:成功后重新查询列表,保存失败保留弹窗草稿。 */
const saving = ref(false)
const publishHistoryDrawerRef = useTemplateRef<InstanceType<typeof PublishHistoryDrawer>>('publishHistoryDrawerRef')

function handleSubmit(payload: WorkflowVersionPayload, versionId?: string) {
saving.value = true
if (versionId) {
return WorkflowVersionApi.putWorkflowVersion(props.applicationId, versionId, payload)
.then(() => {
publishHistoryDrawerRef.value?.closeEdit()
MsgSuccess('修改成功')
return loadWorkflowVersions()
})
.finally(() => {
saving.value = false
})
} else {
return
}
}
</script>

<template>
<!-- 打开智能体发布历史 -->
<MkDropdownItem :disabled="disabled || loading || saving" @click="handleOpen">
<template #icon><MkIcon name="icon_history_outlined" /></template>
<span>发布历史</span>
</MkDropdownItem>
<!-- 发布历史抽屉:由 MkDrawer 按需渲染内容。 -->
<PublishHistoryDrawer
ref="publishHistoryDrawerRef"
v-model="visible"
:versions="versions"
:loading="loading"
:selected-id="selectedId"
@preview="emit('preview', $event)"
@restore="emit('restore', $event)"
@submit="handleSubmit"
/>
</template>
9 changes: 1 addition & 8 deletions ui/src/views/workflow/components/WorkflowViewLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,7 @@ defineSlots<{

<div class="flex shrink-0 items-center">
<!-- 恢复选中的历史版本 -->
<el-button
v-if="historyVisible"
:type="canRestoreVersion ? 'primary' : 'info'"
:disabled="!canRestoreVersion"
@click="emit('restoreVersion')"
>
恢复此版本
</el-button>
<el-button v-if="historyVisible" type="primary" :disabled="!canRestoreVersion" @click="emit('restoreVersion')"> 恢复此版本 </el-button>
<!-- 保留操作入口实例,避免切换头部时卸载其发布历史面板。 -->
<div v-show="!historyVisible" class="flex items-center">
<slot name="actions" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,6 @@ function handleClosed() {
emit('closed')
}

function resetData() {
savedSettings.value = {}
modelSettings.value = normalizeSettings({})
models.value = []
providerOptions.value = []
loading.value = false
applying.value = false
}

function handleBeforeClose(
done = () => {
visible.value = false
Expand All @@ -207,6 +198,14 @@ function handleBeforeClose(
if (action === 'cancel') done()
})
}
function resetData() {
savedSettings.value = {}
modelSettings.value = normalizeSettings({})
models.value = []
providerOptions.value = []
loading.value = false
applying.value = false
}
defineExpose({ open })
</script>

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

This file was deleted.

Loading
Loading