Skip to content

Commit cc3813e

Browse files
committed
fix: refactoring embedded application logic
1 parent de97de6 commit cc3813e

File tree

6 files changed

+150
-6
lines changed

6 files changed

+150
-6
lines changed

apps/application/serializers/application_serializers.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from django.core import signing
2222
from django.db import transaction, models
2323
from django.db.models import QuerySet
24+
from django.db.models.expressions import RawSQL
2425
from django.http import HttpResponse
2526
from django.template import Template, Context
2627
from rest_framework import serializers, status
@@ -46,13 +47,15 @@
4647
from embedding.models import SearchMode
4748
from function_lib.models.function import FunctionLib, PermissionType
4849
from function_lib.serializers.function_lib_serializer import FunctionLibSerializer, FunctionLibModelSerializer
49-
from setting.models import AuthOperate
50+
from setting.models import AuthOperate, TeamMemberPermission
5051
from setting.models.model_management import Model
5152
from setting.models_provider import get_model_credential
5253
from setting.models_provider.tools import get_model_instance_by_model_user_id
5354
from setting.serializers.provider_serializers import ModelSerializer
5455
from smartdoc.conf import PROJECT_DIR
5556
from users.models import User
57+
from django.db.models import Value
58+
from django.db.models.fields.json import KeyTextTransform
5659

5760
chat_cache = cache.caches['chat_cache']
5861

@@ -1110,12 +1113,38 @@ def application_list(self, with_valid=True):
11101113
self.is_valid(raise_exception=True)
11111114
user_id = self.data.get('user_id')
11121115
application_id = self.data.get('application_id')
1113-
application = Application.objects.filter(user_id=user_id).exclude(id=application_id)
1116+
application = QuerySet(Application).get(id=application_id)
1117+
1118+
application_user_id = user_id if user_id == str(application.user_id) else None
1119+
1120+
if application_user_id is not None:
1121+
all_applications = Application.objects.filter(user_id=application_user_id).exclude(id=application_id)
1122+
else:
1123+
all_applications = Application.objects.none()
1124+
1125+
# 获取团队共享的应用
1126+
shared_applications = Application.objects.filter(
1127+
id__in=TeamMemberPermission.objects.filter(
1128+
auth_target_type='APPLICATION',
1129+
operate__contains=RawSQL("ARRAY['USE']", []),
1130+
member_id__team_id=application.user_id,
1131+
member_id__user_id=user_id
1132+
).values('target')
1133+
)
1134+
all_applications = all_applications.union(shared_applications)
1135+
11141136
# 把应用的type为WORK_FLOW的应用放到最上面 然后再按名称排序
1115-
serialized_data = ApplicationSerializerModel(application, many=True).data
1137+
serialized_data = ApplicationSerializerModel(all_applications, many=True).data
11161138
application = sorted(serialized_data, key=lambda x: (x['type'] != 'WORK_FLOW', x['name']))
11171139
return list(application)
11181140

1141+
def get_application(self, app_id, with_valid=True):
1142+
if with_valid:
1143+
self.is_valid(raise_exception=True)
1144+
application = QuerySet(Application).filter(id=self.data.get("application_id")).first()
1145+
return ApplicationSerializer.Operate(data={'user_id': application.user_id, 'application_id': app_id}).one(
1146+
with_valid=True)
1147+
11191148
class ApplicationKeySerializerModel(serializers.ModelSerializer):
11201149
class Meta:
11211150
model = ApplicationApiKey

apps/application/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
path('application/<str:application_id>/function_lib/<str:function_lib_id>',
2626
views.Application.FunctionLib.Operate.as_view()),
2727
path('application/<str:application_id>/application', views.Application.Application.as_view()),
28+
path('application/<str:application_id>/application/<str:app_id>',
29+
views.Application.Application.Operate.as_view()),
2830
path('application/<str:application_id>/model_params_form/<str:model_id>',
2931
views.Application.ModelParamsForm.as_view()),
3032
path('application/<str:application_id>/hit_test', views.Application.HitTest.as_view()),

apps/application/views/application_views.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,25 @@ def get(self, request: Request, application_id: str):
288288
data={'application_id': application_id,
289289
'user_id': request.user.id}).application_list())
290290

291+
class Operate(APIView):
292+
authentication_classes = [TokenAuth]
293+
294+
@action(methods=["GET"], detail=False)
295+
@swagger_auto_schema(operation_summary="获取应用数据",
296+
operation_id="获取应用数据",
297+
tags=["应用"],
298+
)
299+
@has_permissions(ViewPermission(
300+
[RoleConstants.ADMIN, RoleConstants.USER],
301+
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
302+
dynamic_tag=keywords.get('application_id'))],
303+
compare=CompareConstants.AND))
304+
def get(self, request: Request, application_id: str, app_id: str):
305+
return result.success(
306+
ApplicationSerializer.Operate(
307+
data={'application_id': application_id,
308+
'user_id': request.user.id}).get_application(app_id))
309+
291310
class Profile(APIView):
292311
authentication_classes = [TokenAuth]
293312

@@ -433,7 +452,6 @@ def post(self, request: Request):
433452
)
434453

435454
@action(methods=['POST'], detail=False)
436-
437455
@swagger_auto_schema(operation_summary="创建应用",
438456
operation_id="创建应用",
439457
request_body=ApplicationApi.Create.get_request_body_api(),

ui/src/api/application.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,14 @@ const getFunctionLib: (
349349
) => Promise<Result<any>> = (application_id, function_lib_id, loading) => {
350350
return get(`${prefix}/${application_id}/function_lib/${function_lib_id}`, undefined, loading)
351351
}
352+
353+
const getApplicationById: (
354+
application_id: String,
355+
app_id: String,
356+
loading?: Ref<boolean>
357+
) => Promise<Result<any>> = (application_id, app_id, loading) => {
358+
return get(`${prefix}/${application_id}/application/${app_id}`, undefined, loading)
359+
}
352360
/**
353361
* 获取模型参数表单
354362
* @param application_id 应用id
@@ -567,5 +575,6 @@ export default {
567575
getApplicationList,
568576
uploadFile,
569577
exportApplication,
570-
importApplication
578+
importApplication,
579+
getApplicationById
571580
}

ui/src/workflow/common/NodeContainer.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
<el-alert
8080
v-if="node_status != 200"
8181
class="mb-16"
82-
title="该函数不可用"
82+
:title="props.nodeModel.type === 'application-node' ? '该应用不可用' : '该函数不可用'"
8383
type="error"
8484
show-icon
8585
:closable="false"

ui/src/workflow/nodes/application-node/index.vue

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
148148
import { ref, computed, onMounted } from 'vue'
149149
import NodeCascader from '@/workflow/common/NodeCascader.vue'
150150
import type { FormInstance } from 'element-plus'
151+
import applicationApi from '@/api/application'
152+
import { isWorkFlow } from '@/utils/application'
151153
152154
const form = {
153155
question_reference_address: ['start-node', 'question'],
@@ -158,6 +160,10 @@ const form = {
158160
audio_list: ['start-node', 'audio']
159161
}
160162
163+
const {
164+
params: { id }
165+
} = app.config.globalProperties.$route as any
166+
161167
const applicationNodeFormRef = ref<FormInstance>()
162168
163169
const form_data = computed({
@@ -174,6 +180,85 @@ const form_data = computed({
174180
}
175181
})
176182
183+
function handleFileUpload(type: string, isEnabled: boolean) {
184+
const listKey = `${type}_list`
185+
if (isEnabled) {
186+
if (!props.nodeModel.properties.node_data[listKey]) {
187+
set(props.nodeModel.properties.node_data, listKey, [])
188+
}
189+
} else {
190+
// eslint-disable-next-line vue/no-mutating-props
191+
delete props.nodeModel.properties.node_data[listKey]
192+
}
193+
}
194+
195+
const update_field = () => {
196+
if (!props.nodeModel.properties.node_data.application_id) {
197+
set(props.nodeModel.properties, 'status', 500)
198+
return
199+
}
200+
applicationApi
201+
.getApplicationById(id, props.nodeModel.properties.node_data.application_id)
202+
.then((ok) => {
203+
const old_api_input_field_list = props.nodeModel.properties.node_data.api_input_field_list
204+
const old_user_input_field_list = props.nodeModel.properties.node_data.user_input_field_list
205+
206+
if (isWorkFlow(ok.data.type)) {
207+
const nodeData = ok.data.work_flow.nodes[0].properties.node_data
208+
const new_api_input_field_list = ok.data.work_flow.nodes[0].properties.api_input_field_list
209+
const new_user_input_field_list =
210+
ok.data.work_flow.nodes[0].properties.user_input_field_list
211+
const merge_api_input_field_list = new_api_input_field_list.map((item: any) => {
212+
const find_field = old_api_input_field_list.find(
213+
(old_item: any) => old_item.variable == item.variable
214+
)
215+
if (find_field) {
216+
return { ...item, default_value: JSON.parse(JSON.stringify(find_field.default_value)) }
217+
} else {
218+
return item
219+
}
220+
})
221+
set(
222+
props.nodeModel.properties.node_data,
223+
'api_input_field_list',
224+
merge_api_input_field_list
225+
)
226+
const merge_user_input_field_list = new_user_input_field_list.map((item: any) => {
227+
const find_field = old_user_input_field_list.find(
228+
(old_item: any) => old_item.field == item.field
229+
)
230+
if (find_field) {
231+
return { ...item, default_value: JSON.parse(JSON.stringify(find_field.default_value)) }
232+
} else {
233+
return item
234+
}
235+
})
236+
console.log(merge_user_input_field_list)
237+
set(
238+
props.nodeModel.properties.node_data,
239+
'user_input_field_list',
240+
merge_user_input_field_list
241+
)
242+
const fileUploadSetting = nodeData.file_upload_setting
243+
// 如果是true,说明有文件上传
244+
if (fileUploadSetting) {
245+
handleFileUpload('document', fileUploadSetting.document)
246+
handleFileUpload('image', fileUploadSetting.image)
247+
handleFileUpload('audio', fileUploadSetting.audio)
248+
} else {
249+
;['document_list', 'image_list', 'audio_list'].forEach((list) => {
250+
// eslint-disable-next-line vue/no-mutating-props
251+
delete props.nodeModel.properties.node_data[list]
252+
})
253+
}
254+
set(props.nodeModel.properties, 'status', ok.data.id ? 200 : 500)
255+
}
256+
})
257+
.catch((err) => {
258+
set(props.nodeModel.properties, 'status', 500)
259+
})
260+
}
261+
177262
const props = defineProps<{ nodeModel: any }>()
178263
179264
const validate = () => {
@@ -183,6 +268,7 @@ const validate = () => {
183268
}
184269
185270
onMounted(() => {
271+
update_field()
186272
set(props.nodeModel, 'validate', validate)
187273
})
188274
</script>

0 commit comments

Comments
 (0)