Skip to content

Commit 2ec619c

Browse files
committed
feat: application publish content
1 parent 8918dc8 commit 2ec619c

11 files changed

Lines changed: 219 additions & 58 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 6.1 on 2026-09-16 08:54
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("application", "0018_application_default_model_setting_and_more"),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name="applicationversion",
14+
name="publish_desc",
15+
field=models.CharField(default="", max_length=1024, verbose_name="更新说明"),
16+
),
17+
]

apps/application/models/application.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class ApplicationVersion(AppModelMixin):
165165
name = models.CharField(verbose_name="版本名称", max_length=128, default="")
166166
publish_user_id = models.UUIDField(verbose_name="发布者id", max_length=128, default=None, null=True)
167167
publish_user_name = models.CharField(verbose_name="发布者名称", max_length=128, default="")
168+
publish_desc = models.CharField(verbose_name="更新说明", max_length=1024, default="")
168169
workspace_id = models.CharField(max_length=64, verbose_name="工作空间id", default="default", db_index=True)
169170
application_name = models.CharField(max_length=128, verbose_name="应用名称")
170171
desc = models.CharField(max_length=512, verbose_name="引用描述", default="")

apps/application/serializers/application.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import requests
2323
import uuid_utils.compat as uuid
24-
from application.workflow.common import Workflow
24+
from application.workflow.common import new_instance
2525
from application.long_term_memory import schedule_extract_long_term_memory
2626
from application.models.application import Application, ApplicationFolder, ApplicationTypeChoices, ApplicationVersion
2727
from application.models.application_access_token import ApplicationAccessToken
@@ -1107,6 +1107,12 @@ class ApplicationOperateSerializer(serializers.Serializer):
11071107
application_id = serializers.UUIDField(required=True, label=_("Application ID"))
11081108
user_id = serializers.UUIDField(required=True, label=_("User ID"))
11091109
workspace_id = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Workspace ID"))
1110+
publish_name = serializers.CharField(
1111+
required=False, max_length=128, allow_null=True, allow_blank=True, label=_("Publish Name")
1112+
)
1113+
publish_desc = serializers.CharField(
1114+
required=False, max_length=1024, allow_null=True, allow_blank=True, label=_("Publish Desc")
1115+
)
11101116

11111117
def is_valid(self, *, raise_exception=False):
11121118
super().is_valid(raise_exception=True)
@@ -1260,6 +1266,10 @@ def publish(self, instance, with_valid=True):
12601266
self.is_valid()
12611267
user_id = self.data.get("user_id")
12621268
workspace_id = self.data.get("workspace_id")
1269+
name = (instance or {}).get("publish_name")
1270+
if not name or not str(name).strip():
1271+
raise AppApiException(500, _("publish_name is required"))
1272+
publish_desc = (instance or {}).get("publish_desc") or ""
12631273
user = QuerySet(User).filter(id=user_id).first()
12641274
application = (
12651275
QuerySet(Application).filter(id=self.data.get("application_id"), workspace_id=workspace_id).first()
@@ -1268,7 +1278,7 @@ def publish(self, instance, with_valid=True):
12681278
work_flow = application.work_flow
12691279
if work_flow is None:
12701280
raise AppApiException(500, _("work_flow is a required field"))
1271-
Workflow.new_instance(work_flow).is_valid()
1281+
new_instance(work_flow).is_valid()
12721282
base_node = get_base_node_work_flow(work_flow)
12731283
if base_node is not None:
12741284
node_data = base_node.get("properties").get("node_data")
@@ -1283,9 +1293,10 @@ def publish(self, instance, with_valid=True):
12831293
work_flow_version = ApplicationVersion(
12841294
work_flow=application.work_flow,
12851295
application=application,
1286-
name=timezone.localtime(timezone.now()).strftime("%Y-%m-%d %H:%M:%S"),
1296+
name=name,
12871297
publish_user_id=user_id,
12881298
publish_user_name=user.username,
1299+
publish_desc=publish_desc,
12891300
workspace_id=workspace_id,
12901301
)
12911302
self.reset_application_version(work_flow_version, application)
Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# coding=utf-8
22
"""
3-
@project: MaxKB
4-
@Author:虎虎
5-
@file: application_version.py
6-
@date:2025/6/3 16:25
7-
@desc:
3+
@project: MaxKB
4+
@Author:虎虎
5+
@file: application_version.py
6+
@date:2025/6/3 16:25
7+
@desc:
88
"""
9+
910
from typing import Dict
1011

1112
from django.db.models import QuerySet
@@ -19,21 +20,33 @@
1920

2021
class ApplicationVersionQuerySerializer(serializers.Serializer):
2122
application_id = serializers.UUIDField(required=True, label=_("Application ID"))
22-
name = serializers.CharField(required=False, allow_null=True, allow_blank=True,
23-
label=_("summary"))
23+
name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("summary"))
2424

2525

2626
class ApplicationVersionModelSerializer(serializers.ModelSerializer):
2727
class Meta:
2828
model = ApplicationVersion
29-
fields = ['id', 'name', 'workspace_id', 'application_id', 'work_flow', 'publish_user_id', 'publish_user_name',
30-
'create_time',
31-
'update_time']
29+
fields = [
30+
"id",
31+
"name",
32+
"publish_desc",
33+
"workspace_id",
34+
"application_id",
35+
"work_flow",
36+
"publish_user_id",
37+
"publish_user_name",
38+
"create_time",
39+
"update_time",
40+
]
3241

3342

3443
class ApplicationVersionEditSerializer(serializers.Serializer):
35-
name = serializers.CharField(required=False, max_length=128, allow_null=True, allow_blank=True,
36-
label=_("Version Name"))
44+
name = serializers.CharField(
45+
required=False, max_length=128, allow_null=True, allow_blank=True, label=_("Version Name")
46+
)
47+
publish_desc = serializers.CharField(
48+
required=False, max_length=1024, allow_null=True, allow_blank=True, label=_("Publish Description")
49+
)
3750

3851

3952
class ApplicationVersionSerializer(serializers.Serializer):
@@ -43,11 +56,11 @@ class Query(serializers.Serializer):
4356
workspace_id = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Workspace ID"))
4457

4558
def get_query_set(self, query):
46-
query_set = QuerySet(ApplicationVersion).filter(application_id=query.get('application_id'))
47-
if 'name' in query and query.get('name') is not None:
48-
query_set = query_set.filter(name__contains=query.get('name'))
49-
if 'workspace_id' in self.data and self.data.get('workspace_id') is not None:
50-
query_set = query_set.filter(workspace_id=self.data.get('workspace_id'))
59+
query_set = QuerySet(ApplicationVersion).filter(application_id=query.get("application_id"))
60+
if "name" in query and query.get("name") is not None:
61+
query_set = query_set.filter(name__contains=query.get("name"))
62+
if "workspace_id" in self.data and self.data.get("workspace_id") is not None:
63+
query_set = query_set.filter(workspace_id=self.data.get("workspace_id"))
5164
return query_set.order_by("-create_time")
5265

5366
def list(self, query, with_valid=True):
@@ -60,48 +73,57 @@ def list(self, query, with_valid=True):
6073
def page(self, query, current_page, page_size, with_valid=True):
6174
if with_valid:
6275
self.is_valid(raise_exception=True)
63-
return page_search(current_page, page_size,
64-
self.get_query_set(query),
65-
post_records_handler=lambda v: ApplicationVersionModelSerializer(v).data)
76+
return page_search(
77+
current_page,
78+
page_size,
79+
self.get_query_set(query),
80+
post_records_handler=lambda v: ApplicationVersionModelSerializer(v).data,
81+
)
6682

6783
class Operate(serializers.Serializer):
6884
workspace_id = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Workspace ID"))
6985
application_id = serializers.UUIDField(required=True, label=_("Application ID"))
70-
application_version_id = serializers.UUIDField(required=True,
71-
label=_("Application version ID"))
86+
application_version_id = serializers.UUIDField(required=True, label=_("Application version ID"))
7287

7388
def is_valid(self, *, raise_exception=False):
7489
super().is_valid(raise_exception=True)
75-
workspace_id = self.data.get('workspace_id')
76-
query_set = QuerySet(Application).filter(id=self.data.get('application_id'))
90+
workspace_id = self.data.get("workspace_id")
91+
query_set = QuerySet(Application).filter(id=self.data.get("application_id"))
7792
if workspace_id:
7893
query_set = query_set.filter(workspace_id=workspace_id)
7994
if not query_set.exists():
80-
raise AppApiException(500, _('Application id does not exist'))
95+
raise AppApiException(500, _("Application id does not exist"))
8196

8297
def one(self, with_valid=True):
8398
if with_valid:
8499
self.is_valid(raise_exception=True)
85-
application_version = QuerySet(ApplicationVersion).filter(application_id=self.data.get('application_id'),
86-
id=self.data.get(
87-
'application_version_id')).first()
100+
application_version = (
101+
QuerySet(ApplicationVersion)
102+
.filter(application_id=self.data.get("application_id"), id=self.data.get("application_version_id"))
103+
.first()
104+
)
88105
if application_version is not None:
89106
return ApplicationVersionModelSerializer(application_version).data
90107
else:
91-
raise AppApiException(500, _('Workflow version does not exist'))
108+
raise AppApiException(500, _("Workflow version does not exist"))
92109

93110
def edit(self, instance: Dict, with_valid=True):
94111
if with_valid:
95112
self.is_valid(raise_exception=True)
96113
ApplicationVersionEditSerializer(data=instance).is_valid(raise_exception=True)
97-
application_version = QuerySet(ApplicationVersion).filter(application_id=self.data.get('application_id'),
98-
id=self.data.get(
99-
'application_version_id')).first()
114+
application_version = (
115+
QuerySet(ApplicationVersion)
116+
.filter(application_id=self.data.get("application_id"), id=self.data.get("application_version_id"))
117+
.first()
118+
)
100119
if application_version is not None:
101-
name = instance.get('name', None)
120+
name = instance.get("name", None)
121+
publish_desc = instance.get("publish_desc", None)
102122
if name is not None and len(name) > 0:
103123
application_version.name = name
124+
if publish_desc is not None and len(publish_desc) > 0:
125+
application_version.publish_desc = publish_desc
104126
application_version.save()
105127
return ApplicationVersionModelSerializer(application_version).data
106128
else:
107-
raise AppApiException(500, _('Workflow version does not exist'))
129+
raise AppApiException(500, _("Workflow version does not exist"))

apps/application/workflow/common.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ def reset_prompt(self, prompt):
194194
prompt = node_field.reset_variable(prompt)
195195
return prompt
196196

197+
def is_valid(self):
198+
pass
199+
197200

198201
class WorkflowType(Enum):
199202
# 应用

ui/src/api/admin/workspace/application/application.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,11 @@ const putBatchMoveApplications = (applicationIds: string[], folderId: string) =>
6969
}
7070

7171
/** 发布工作空间智能体。 */
72-
const putApplicationPublish = (applicationId: string) => {
73-
return put<Record<string, never>, ApplicationDetail>(`${getPrefix()}/${applicationId}/publish`, {})
72+
const putApplicationPublish = (applicationId: string, publishName: string, publishDesc?: string) => {
73+
return put<Record<string, unknown>, ApplicationDetail>(`${getPrefix()}/${applicationId}/publish`, {
74+
publish_name: publishName,
75+
publish_desc: publishDesc,
76+
})
7477
}
7578

7679
/** 使用指定模型流式生成或优化系统提示词。 */

ui/src/api/types/workflow-version.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export interface WorkflowVersion {
55
id: string
66
name: string
77
/** 更新说明;旧版本接口可能不返回。 */
8-
description?: string | null
8+
publish_desc?: string | null
99
work_flow: LogicFlow.GraphConfigData
1010
publish_user_name: string
1111
create_time: string
@@ -15,5 +15,5 @@ export interface WorkflowVersion {
1515
/** 发布历史的标题和更新说明编辑内容。 */
1616
export interface WorkflowVersionPayload {
1717
name: string
18-
description: string
18+
publish_desc: string
1919
}

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

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import WorkflowViewLayout from '../components/WorkflowViewLayout.vue'
1616
import ButtonPublishHistory from './ButtonPublishHistory.vue'
1717
import TemplateStoreDialog from '@/views/application/template-store/TemplateStoreDialog.vue'
1818
import DebugPanel from './debug/DebugPanel.vue'
19+
import ApplicationPublishDialog from './components/ApplicationPublishDialog.vue'
1920
import { getResourceScope } from '@/utils/resource-context.ts'
2021
import { goBack } from './navigation'
2122
@@ -211,23 +212,21 @@ function handleSaveDefaultModelSetting(settings: DefaultModelSettingPayload) {
211212
return handleSave()
212213
}
213214
214-
/* 发布工作流 */
215+
/* 发布工作流:先校验画布,再由弹窗收集发布标题与更新说明 */
216+
const publishDialogRef = useTemplateRef<InstanceType<typeof ApplicationPublishDialog>>('publishDialogRef')
217+
215218
function handlePublish() {
216219
workflowRef.value?.validate().then(() => {
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-
})
220+
publishDialogRef.value?.open()
228221
})
229222
}
230223
224+
/* 发布成功:更新详情与保存时间,保持与保存流程一致 */
225+
function handlePublished(application: ApplicationDetail) {
226+
applicationDetail.value = application
227+
saveTime.value = application.update_time || saveTime.value
228+
}
229+
231230
/* 退出工作流 */
232231
function handleBack() {
233232
if (loading.value || saving.value || confirmingExit.value) return
@@ -382,5 +381,7 @@ onBeforeUnmount(() => stopAutoSave())
382381
<DebugPanel ref="debugPanelRef" />
383382
<!-- 模版中心 -->
384383
<TemplateStoreDialog ref="templateStoreDialogRef" source="work_flow" :applying="saving" @use="handleUseTemplate" />
384+
<!-- 发布弹窗 -->
385+
<ApplicationPublishDialog ref="publishDialogRef" :resource-id="applicationId" @published="handlePublished" />
385386
</WorkflowViewLayout>
386387
</template>

0 commit comments

Comments
 (0)