diff --git a/apps/application/flow/step_node/form_node/impl/base_form_node.py b/apps/application/flow/step_node/form_node/impl/base_form_node.py index e3d9e8f95..aaa0fe46f 100644 --- a/apps/application/flow/step_node/form_node/impl/base_form_node.py +++ b/apps/application/flow/step_node/form_node/impl/base_form_node.py @@ -22,7 +22,8 @@ def get_default_option(option_list, _type, value_field): if option_list is not None and isinstance(option_list, list) and len(option_list) > 0: default_value_list = [o.get(value_field) for o in option_list if o.get('default')] if len(default_value_list) == 0: - return option_list[0].get(value_field) + return [o.get(value_field) for o in option_list] if _type == 'MultiSelect' else option_list[0].get( + value_field) else: if _type == 'MultiSelect': return default_value_list diff --git a/apps/chat/urls.py b/apps/chat/urls.py index d5bdb60dd..2ba61084f 100644 --- a/apps/chat/urls.py +++ b/apps/chat/urls.py @@ -8,6 +8,7 @@ urlpatterns = [ path('embed', views.ChatEmbedView.as_view()), path('auth/anonymous', views.AnonymousAuthentication.as_view()), path('profile', views.AuthProfile.as_view()), + path('resource_proxy',views.ResourceProxy.as_view()), path('application/profile', views.ApplicationProfile.as_view(), name='profile'), path('chat_message/', views.ChatView.as_view(), name='chat'), path('open', views.OpenView.as_view(), name='open'), diff --git a/apps/chat/views/chat.py b/apps/chat/views/chat.py index 89a70569a..82c8bd8d0 100644 --- a/apps/chat/views/chat.py +++ b/apps/chat/views/chat.py @@ -6,7 +6,8 @@ @date:2025/6/6 11:18 @desc: """ -from django.http import HttpResponse +import requests +from django.http import HttpResponse, StreamingHttpResponse from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema from rest_framework.parsers import MultiPartParser @@ -30,6 +31,39 @@ from users.api import CaptchaAPI from users.serializers.login import CaptchaSerializer +def stream_image(response): + """生成器函数,用于流式传输图片数据""" + for chunk in response.iter_content(chunk_size=4096): + if chunk: # 过滤掉保持连接的空块 + yield chunk + + +class ResourceProxy(APIView): + def get(self, request: Request): + image_url = request.query_params.get("url") + if not image_url: + return result.error("Missing 'url' parameter") + try: + + # 发送GET请求,流式获取图片内容 + response = requests.get( + image_url, + stream=True, # 启用流式响应 + allow_redirects=True, + timeout=10 + ) + content_type = response.headers.get('Content-Type', '').split(';')[0] + # 创建Django流式响应 + django_response = StreamingHttpResponse( + stream_image(response), # 使用生成器 + content_type=content_type + ) + + return django_response + except Exception as e: + return result.error(f"Image request failed: {str(e)}") + + class OpenAIView(APIView): authentication_classes = [TokenAuth] diff --git a/ui/src/components/markdown/MdRenderer.vue b/ui/src/components/markdown/MdRenderer.vue index 67ec2f73a..3ef6f57d4 100644 --- a/ui/src/components/markdown/MdRenderer.vue +++ b/ui/src/components/markdown/MdRenderer.vue @@ -55,7 +55,7 @@ config({ } tokens[idx].attrSet( 'onerror', - 'this.src="/${window.MaxKB.prefix}/assets/load_error.png";this.onerror=null;this.height="33px"', + `this.src="./assets/load_error.png";this.onerror=null;this.height="33px"`, ) return md.renderer.renderToken(tokens, idx, options) } diff --git a/ui/src/components/pdf-export/index.vue b/ui/src/components/pdf-export/index.vue index 6ea6bc5c1..ab578966e 100644 --- a/ui/src/components/pdf-export/index.vue +++ b/ui/src/components/pdf-export/index.vue @@ -11,6 +11,7 @@ v-loading="loading" style="height: calc(70vh - 150px); overflow-y: auto; display: flex; justify-content: center" > +