From bf867f5736a78db4071fb0052283e8d07429a567 Mon Sep 17 00:00:00 2001 From: zhangzhanwei Date: Fri, 23 Jan 2026 13:57:29 +0800 Subject: [PATCH] feat: Trigger task popover --- apps/trigger/api/trigger.py | 69 ++++++++++- .../serializers/task_source_trigger.py | 112 ++++++++++++++++++ apps/trigger/serializers/trigger.py | 31 +++-- apps/trigger/urls.py | 3 + apps/trigger/views/trigger.py | 87 +++++++++++++- ui/src/views/trigger/index.vue | 41 +++++-- 6 files changed, 323 insertions(+), 20 deletions(-) create mode 100644 apps/trigger/serializers/task_source_trigger.py diff --git a/apps/trigger/api/trigger.py b/apps/trigger/api/trigger.py index 34b70298ff3..b8232ca7526 100644 --- a/apps/trigger/api/trigger.py +++ b/apps/trigger/api/trigger.py @@ -91,4 +91,71 @@ class RequestSE(serializers.Serializer): class TriggerEditAPI(APIMixin): @staticmethod def get_request(): - return TriggerCreateRequest \ No newline at end of file + return TriggerCreateRequest + + +class TaskSourceTriggerAPI(APIMixin): + @staticmethod + def get_parameters(): + return [ + OpenApiParameter( + name="workspace_id", + description="工作空间id", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + OpenApiParameter( + name="source_id", + description="资源id", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + OpenApiParameter( + name="source_type", + description="资源类型", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + ] + + @staticmethod + def get_response(): + return TriggerResponse + + +class TaskSourceTriggerOperateAPI(APIMixin): + @staticmethod + def get_parameters(): + return [ + OpenApiParameter( + name="workspace_id", + description="工作空间id", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + OpenApiParameter( + name="source_id", + description="资源id", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + OpenApiParameter( + name="source_type", + description="资源类型", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + OpenApiParameter( + name="trigger_id", + description="触发器id", + type=OpenApiTypes.STR, + location='path', + required=True, + ), + ] \ No newline at end of file diff --git a/apps/trigger/serializers/task_source_trigger.py b/apps/trigger/serializers/task_source_trigger.py new file mode 100644 index 00000000000..8090d1cd6ba --- /dev/null +++ b/apps/trigger/serializers/task_source_trigger.py @@ -0,0 +1,112 @@ +# coding=utf-8 +""" + @project: MaxKB + @Author:niu + @file: task_source_trigger.py + @date:2026/1/22 16:18 + @desc: +""" +import os.path +import re +from typing import Dict + +import uuid_utils.compat as uuid +from django.core import validators +from django.db import models, transaction +from django.db.models import QuerySet +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from application.models import Application +from common.db.search import page_search, get_dynamics_model, native_page_search, native_search +from common.exception.app_exception import AppApiException +from common.field.common import ObjectField +from common.utils.common import get_file_content +from knowledge.serializers.common import BatchSerializer +from maxkb.conf import PROJECT_DIR +from tools.models import Tool +from trigger.models import TriggerTypeChoices, Trigger, TriggerTaskTypeChoices, TriggerTask +from trigger.serializers.trigger import TriggerModelSerializer, TriggerSerializer, ApplicationTriggerTaskSerializer, \ + ToolTriggerTaskSerializer, TriggerTaskModelSerializer + + +class TaskSourceTriggerSerializer(serializers.Serializer): + workspace_id = serializers.CharField(required=True, label=_('workspace id')) + user_id = serializers.UUIDField(required=True, label=_("User ID")) + + def insert(self, instance, with_valid=True): + if with_valid: + self.is_valid(raise_exception=True) + return TriggerSerializer().insert(instance, with_valid=True) + + +class TaskSourceTriggerOperateSerializer(serializers.Serializer): + trigger_id = serializers.UUIDField(required=True, label=_('trigger id')) + user_id = serializers.UUIDField(required=True, label=_("User ID")) + workspace_id = serializers.CharField(required=True, label=_('workspace id')) + source_type = serializers.CharField(required=True, label=_('source type')) + source_id = serializers.CharField(required=True, label=_('source id')) + + def is_valid(self, *, raise_exception=False): + super().is_valid(raise_exception=True) + workspace_id = self.data.get('workspace_id') + query_set = QuerySet(Trigger).filter(id=self.data.get('trigger_id')) + if workspace_id: + query_set = query_set.filter(workspace_id=workspace_id) + if not query_set.exists(): + raise AppApiException(500, _('Trigger id does not exist')) + + def one(self, with_valid=True): + if with_valid: + self.is_valid() + trigger_id = self.data.get('trigger_id') + workspace_id = self.data.get('workspace_id') + source_id = self.data.get('source_id') + source_type = self.data.get('source_type') + + trigger = QuerySet(Trigger).filter(workspace_id=workspace_id, id=trigger_id).first() + trigger_task = TriggerTaskModelSerializer(TriggerTask.objects.filter( + trigger_id=trigger_id, source_id=source_id, source_type=source_type).first()).data + + if source_type == TriggerTaskTypeChoices.APPLICATION: + application_task = ApplicationTriggerTaskSerializer( + Application.objects.filter(workspace_id=workspace_id, id=source_id).first()).data + return { + **TriggerModelSerializer(trigger).data, + 'trigger_task': trigger_task, + 'application_task': application_task, + } + if source_type == TriggerTaskTypeChoices.TOOL: + tool_task = ToolTriggerTaskSerializer( + Tool.objects.filter(workspace_id=workspace_id, id=source_id).first()).data + return { + **TriggerModelSerializer(trigger).data, + 'trigger_task': trigger_task, + 'application_task': tool_task, + } + + def edit(self, instance: Dict, with_valid = True): + if with_valid: + self.is_valid(raise_exception=True) + + + + + + +class TaskSourceTriggerListSerializer(serializers.Serializer): + workspace_id = serializers.CharField(required=True, label=_('workspace id')) + source_type = serializers.CharField(required=True, label=_('source type')) + source_id = serializers.CharField(required=True, label=_('source id')) + + def list(self, with_valid=True): + if with_valid: + self.is_valid(raise_exception=True) + + triggers = Trigger.objects.filter(workspace_id=self.data.get("workspace_id"), + triggertask__source_id=self.data.get("source_id"), + triggertask__source_type=self.data.get("source_type"), + is_active=True + ).distinct() + + return [TriggerModelSerializer(trigger).data for trigger in triggers] diff --git a/apps/trigger/serializers/trigger.py b/apps/trigger/serializers/trigger.py index 2800f626d01..6258e4f4c7a 100644 --- a/apps/trigger/serializers/trigger.py +++ b/apps/trigger/serializers/trigger.py @@ -461,17 +461,26 @@ def one(self, with_valid=True): workspace_id = self.data.get('workspace_id') trigger = QuerySet(Trigger).filter(workspace_id=workspace_id, id=trigger_id).first() - trigger_tasks = QuerySet(TriggerTask).filter(trigger_id=trigger_id) - application_ids = [str(task.source_id) for task in trigger_tasks if - task.source_type == TriggerTaskTypeChoices.APPLICATION] - tool_ids = [str(task.source_id) for task in trigger_tasks if task.source_type == TriggerTaskTypeChoices.TOOL] - - trigger_task_list = [TriggerTaskModelSerializer(task).data for task in trigger_tasks] - application_task_list = [ApplicationTriggerTaskSerializer(application).data for application in - QuerySet(Application).filter(workspace_id=workspace_id, id__in=application_ids)] - - tool_task_list = [ToolTriggerTaskSerializer(tool).data for tool in - QuerySet(Tool).filter(workspace_id=workspace_id, id__in=tool_ids)] + trigger_tasks = list(QuerySet(TriggerTask).filter(trigger_id=trigger_id)) + + application_ids = [] + tool_ids = [] + for task in trigger_tasks: + if task.source_type == TriggerTaskTypeChoices.APPLICATION: + application_ids.append(task.source_id) + elif task.source_type == TriggerTaskTypeChoices.TOOL: + tool_ids.append(task.source_id) + + trigger_task_list = TriggerTaskModelSerializer(trigger_tasks, many=True).data + + application_task_list = [] + if application_ids: + applications =Application.objects.filter(workspace_id=workspace_id, id__in=application_ids) + application_task_list = ApplicationTriggerTaskSerializer(applications, many=True).data + tool_task_list = [] + if tool_ids: + tools = Tool.objects.filter(workspace_id=workspace_id, id__in=tool_ids) + tool_task_list = ToolTriggerTaskSerializer(tools, many=True).data return { **TriggerModelSerializer(trigger).data, diff --git a/apps/trigger/urls.py b/apps/trigger/urls.py index 2f91b564f67..ec991201b2e 100644 --- a/apps/trigger/urls.py +++ b/apps/trigger/urls.py @@ -22,6 +22,9 @@ path('workspace//trigger/', views.TriggerView.Operate.as_view(), name='trigger operate'), path('workspace//trigger//', views.TriggerView.Page.as_view(), name='trigger_page'), + path('workspace////trigger/', + views.TaskSourceTriggerView.Operate.as_view(), name='task source trigger operate'), + path('workspace////trigger', views.TaskSourceTriggerView.as_view(), name='task source trigger'), path('workspace//task', views.TriggerTaskView.as_view(), name='task'), path('trigger/v1/webhook/', EventTriggerView.as_view(), name='trigger_webhook') ] diff --git a/apps/trigger/views/trigger.py b/apps/trigger/views/trigger.py index 205228e35eb..3b19d9ef233 100644 --- a/apps/trigger/views/trigger.py +++ b/apps/trigger/views/trigger.py @@ -14,10 +14,12 @@ from application.api.application_api import ApplicationCreateAPI from common import result from common.auth import TokenAuth +from trigger.serializers.task_source_trigger import TaskSourceTriggerListSerializer, TaskSourceTriggerOperateSerializer, \ + TaskSourceTriggerSerializer from trigger.serializers.trigger import TriggerQuerySerializer, TriggerOperateSerializer from trigger.api.trigger import TriggerCreateAPI, TriggerOperateAPI, TriggerEditAPI, TriggerBatchDeleteAPI, \ - TriggerBatchActiveAPI + TriggerBatchActiveAPI, TaskSourceTriggerOperateAPI, TaskSourceTriggerAPI from trigger.serializers.trigger import TriggerSerializer @@ -162,3 +164,86 @@ def get(self, request: Request, workspace_id: str, current_page: int, page_size: 'is_active': request.query_params.get('is_active'), 'create_user': request.query_params.get('create_user'), }).page(current_page, page_size)) + + +class TaskSourceTriggerView(APIView): + authentication_classes = [TokenAuth] + + @extend_schema( + methods=['POST'], + description=_('Create trigger of source'), + summary=_('Create trigger of source'), + operation_id=_('Create trigger of source'), # type: ignore + parameters=TaskSourceTriggerAPI.get_parameters(), + request=TaskSourceTriggerAPI.get_request(), + responses=TaskSourceTriggerAPI.get_response(), + tags=[_('Trigger')] # type: ignore + ) + def post(self, request: Request, workspace_id: str, source_type: str, source_id: str): + return result.success(TaskSourceTriggerSerializer(data={ + 'workspace_id': workspace_id, + 'user_id': request.user.id + }).insert({**request.data, 'source_id': source_id, + 'source_type': source_type})) + + @extend_schema( + methods=['GET'], + description=_('Get the trigger list of source'), + summary=_('Get the trigger list of source'), + operation_id=_('Get the trigger list of source'), # type: ignore + parameters=TaskSourceTriggerAPI.get_parameters(), + responses=result.DefaultResultSerializer, + tags=[_('Trigger')] # type: ignore + ) + def get(self, request: Request, workspace_id: str, source_type: str, source_id: str): + return result.success(TaskSourceTriggerListSerializer(data={ + 'workspace_id': workspace_id, + 'source_id': source_id, + 'source_type': source_type, + }).list()) + + class Operate(APIView): + authentication_classes = [TokenAuth] + + @extend_schema( + methods=['GET'], + description=_('Get Task source trigger details'), + summary=_('Get Task source trigger details'), + operation_id=_('Get Task source trigger details'), # type: ignore + parameters=TaskSourceTriggerOperateAPI.get_parameters(), + responses=result.DefaultResultSerializer, + tags=[_('Trigger')] # type: ignore + ) + def get(self, request: Request, workspace_id: str, source_type: str, source_id: str, trigger_id: str): + return result.success(TaskSourceTriggerOperateSerializer( + data={'trigger_id': trigger_id, 'workspace_id': workspace_id, 'user_id': request.user.id, + 'source_id': source_id, 'source_type': source_type} + ).one()) + + + @extend_schema( + methods=['PUT'], + description=_('Modify the task source trigger'), + summary=_('Modify the task source trigger'), + operation_id=_('Modify the task source trigger'), # type: ignore + parameters=TaskSourceTriggerOperateAPI.get_parameters(), + request=TaskSourceTriggerOperateAPI.get_request(), + responses=result.DefaultResultSerializer, + tags=[_('Trigger')] # type: ignore + ) + def get(self, request: Request, workspace_id: str, source_type: str, source_id: str, trigger_id: str): + return result.success(TaskSourceTriggerOperateSerializer( + data={'trigger_id': trigger_id, 'workspace_id': workspace_id, 'user_id': request.user.id, + 'source_id': source_id, 'source_type': source_type} + ).edit(request.data)) + + + + + + + + + + + diff --git a/ui/src/views/trigger/index.vue b/ui/src/views/trigger/index.vue index 6f141854c37..579f6ddb1e9 100644 --- a/ui/src/views/trigger/index.vue +++ b/ui/src/views/trigger/index.vue @@ -143,13 +143,25 @@