|
38 | 38 | import modelengine.fit.jober.aipp.dto.AppBuilderConfigDto; |
39 | 39 | import modelengine.fit.jober.aipp.dto.AppBuilderConfigFormPropertyDto; |
40 | 40 | import modelengine.fit.jober.aipp.dto.AppBuilderFlowGraphDto; |
| 41 | +import modelengine.fit.jober.aipp.dto.AppBuilderNodeConfigsDto; |
41 | 42 | import modelengine.fit.jober.aipp.dto.AppBuilderSaveConfigDto; |
42 | 43 | import modelengine.fit.jober.aipp.dto.PublishedAppResDto; |
43 | 44 | import modelengine.fit.jober.aipp.dto.check.AppCheckDto; |
|
52 | 53 | import modelengine.fit.jober.aipp.service.Checker; |
53 | 54 | import modelengine.fit.jober.aipp.service.UploadedFileManageService; |
54 | 55 | import modelengine.fit.jober.aipp.util.ConvertUtils; |
| 56 | +import modelengine.fit.jober.aipp.util.JsonUtils; |
55 | 57 | import modelengine.fit.jober.aipp.util.RandomPathUtils; |
56 | 58 | import modelengine.fit.jober.common.RangedResultSet; |
57 | 59 | import modelengine.fitframework.annotation.Component; |
58 | 60 | import modelengine.fitframework.annotation.Fitable; |
59 | 61 | import modelengine.fitframework.annotation.Value; |
60 | 62 | import modelengine.fitframework.log.Logger; |
61 | 63 | import modelengine.fitframework.transaction.Transactional; |
| 64 | +import modelengine.fitframework.util.ObjectUtils; |
62 | 65 | import modelengine.fitframework.util.StringUtils; |
63 | 66 | import modelengine.jade.knowledge.KnowledgeCenterService; |
64 | 67 |
|
@@ -189,7 +192,11 @@ public void updateFlow(String appId, OperationContext contextOf) { |
189 | 192 | @Override |
190 | 193 | public AppBuilderAppDto queryLatestOrchestration(String appId, OperationContext context) { |
191 | 194 | AppVersion appVersion = this.appVersionService.retrieval(appId); |
192 | | - App app = this.appDomainFactory.create(appVersion.getData().getAppSuiteId()); |
| 195 | + return this.queryLatestOrchestrationBySuiteId(appVersion.getData().getAppSuiteId(), context); |
| 196 | + } |
| 197 | + |
| 198 | + private AppBuilderAppDto queryLatestOrchestrationBySuiteId(String appSuiteId, OperationContext context) { |
| 199 | + App app = this.appDomainFactory.create(appSuiteId); |
193 | 200 | AppVersion latestVersion = app.getLatestVersion() |
194 | 201 | .orElseThrow(() -> new AippException(OBTAIN_APP_ORCHESTRATION_INFO_FAILED)); |
195 | 202 | if (latestVersion.isPublished()) { |
@@ -309,6 +316,176 @@ public Rsp<AppBuilderAppDto> updateFlowGraph(String appId, AppBuilderFlowGraphDt |
309 | 316 | return Rsp.ok(this.converterFactory.convert(appVersion, AppBuilderAppDto.class)); |
310 | 317 | } |
311 | 318 |
|
| 319 | + @Override |
| 320 | + public void updateNodeConfigs(AppBuilderNodeConfigsDto nodeConfigs, OperationContext context) { |
| 321 | + if (StringUtils.isBlank(nodeConfigs.getAppSuiteId())) { |
| 322 | + throw new IllegalArgumentException("Id is not exist"); |
| 323 | + } |
| 324 | + AppVersion latestVersion = this.appVersionService.getLatestCreatedByAppSuiteId(nodeConfigs.getAppSuiteId()) |
| 325 | + .orElseThrow(() -> new AippException(AippErrCode.APP_NOT_FOUND)); |
| 326 | + boolean isPublished = latestVersion.isPublished(); |
| 327 | + if (isPublished) { |
| 328 | + // 如果是发布状态,则创建一个草稿态 |
| 329 | + this.queryLatestOrchestrationBySuiteId(nodeConfigs.getAppSuiteId(), context); |
| 330 | + latestVersion = this.appVersionService.getLatestCreatedByAppSuiteId(nodeConfigs.getAppSuiteId()) |
| 331 | + .orElseThrow(() -> new AippException(AippErrCode.APP_NOT_FOUND)); |
| 332 | + } |
| 333 | + Map<String, Object> appearances = JsonUtils.parseObject(latestVersion.getFlowGraph().getAppearance()); |
| 334 | + List<?> shapes = this.getShapes(appearances); |
| 335 | + for(Map.Entry<String, Object> nodeConfig: nodeConfigs.getNodeConfigs().entrySet()) { |
| 336 | + Map<String, Object> oldShape = this.getNodeShape(shapes, ObjectUtils.cast(nodeConfig.getKey())); |
| 337 | + Map<String, Object> params = this.getParams(oldShape); |
| 338 | + List<Map<String, Object>> inputParams = ObjectUtils.cast(params.get("inputParams")); |
| 339 | + Map<String, Object> newConfig = ObjectUtils.cast(nodeConfig.getValue()); |
| 340 | + this.updateValueParams(inputParams, ObjectUtils.cast(newConfig.get("valueParams"))); |
| 341 | + } |
| 342 | + AppBuilderFlowGraphDto flowGraphDto = this.buildAppBuilderFlowGraphDto(latestVersion, appearances); |
| 343 | + this.appVersionService.updateGraph(latestVersion, flowGraphDto, context); |
| 344 | + } |
| 345 | + |
| 346 | + @Override |
| 347 | + public Rsp<AippCreateDto> publishLatestVersion(String appSuiteId, OperationContext context) { |
| 348 | + AppVersion latestVersion = this.appVersionService.getLatestCreatedByAppSuiteId(appSuiteId) |
| 349 | + .orElseThrow(() -> new AippException(AippErrCode.APP_NOT_FOUND)); |
| 350 | + if (latestVersion.isPublished()) { |
| 351 | + throw new AippException(AippErrCode.APP_HAS_ALREADY); |
| 352 | + } |
| 353 | + AppBuilderAppDto appDto = this.converterFactory.convert(latestVersion, AppBuilderAppDto.class); |
| 354 | + return this.publish(appDto, context); |
| 355 | + } |
| 356 | + |
| 357 | + private AppBuilderFlowGraphDto buildAppBuilderFlowGraphDto(AppVersion appVersion, Map<String, Object> appearances) { |
| 358 | + return AppBuilderFlowGraphDto.builder() |
| 359 | + .name(appVersion.getFlowGraph().getName()) |
| 360 | + .appearance(appearances) |
| 361 | + .build(); |
| 362 | + } |
| 363 | + |
| 364 | + private void updateValueParams(List<Map<String, Object>> inputParams, Map<String, Object> newConfig) { |
| 365 | + if (inputParams == null || newConfig == null || newConfig.isEmpty()) { |
| 366 | + return; |
| 367 | + } |
| 368 | + for (Map.Entry<String, Object> entry : newConfig.entrySet()) { |
| 369 | + this.updateInputParam(inputParams, entry); |
| 370 | + } |
| 371 | + } |
| 372 | + |
| 373 | + private void updateInputParam(List<Map<String, Object>> inputParams, Map.Entry<String, Object> entry) { |
| 374 | + String key = entry.getKey(); |
| 375 | + Object value = entry.getValue(); |
| 376 | + String[] pathParts = key.split("\\."); |
| 377 | + if (pathParts.length == 0) { |
| 378 | + return; |
| 379 | + } |
| 380 | + |
| 381 | + // 从顶层inputParams开始查找目标节点 |
| 382 | + List<Map<String, Object>> currentLevel = inputParams; |
| 383 | + Map<String, Object> targetNode = null; |
| 384 | + for (int i = 0; i < pathParts.length; i++) { |
| 385 | + String part = pathParts[i]; |
| 386 | + |
| 387 | + // 在当前层级查找name匹配的节点 |
| 388 | + Map<String, Object> found = this.findConfigByName(currentLevel, part); |
| 389 | + if (found == null) { |
| 390 | + break; |
| 391 | + } |
| 392 | + |
| 393 | + // 如果是最后一层,找到目标节点 |
| 394 | + if (i == pathParts.length - 1) { |
| 395 | + targetNode = found; |
| 396 | + break; |
| 397 | + } |
| 398 | + |
| 399 | + // 非最后一层,进入下一层(value字段) |
| 400 | + Object nextLevelObj = found.get("value"); |
| 401 | + if (!(nextLevelObj instanceof List)) { |
| 402 | + // 下一层不是List,路径无效,跳过 |
| 403 | + break; |
| 404 | + } |
| 405 | + currentLevel = ObjectUtils.cast(nextLevelObj); |
| 406 | + } |
| 407 | + |
| 408 | + // 更新目标节点的value |
| 409 | + if (targetNode != null) { |
| 410 | + targetNode.put("value", value); |
| 411 | + } |
| 412 | + } |
| 413 | + |
| 414 | + private Map<String, Object> findConfigByName(List<Map<String, Object>> configs, String name) { |
| 415 | + if (configs == null) { |
| 416 | + return null; |
| 417 | + } |
| 418 | + for (Map<String, Object> config : configs) { |
| 419 | + Object nodeName = config.get("name"); |
| 420 | + if (nodeName != null && StringUtils.equals(name, ObjectUtils.cast(nodeName))) { |
| 421 | + return config; |
| 422 | + } |
| 423 | + } |
| 424 | + return null; |
| 425 | + } |
| 426 | + |
| 427 | + private Map<String, Object> getParams(Map<String, Object> config) { |
| 428 | + Map<String, Object> flowMetaMap = |
| 429 | + this.mapSearch(config, "flowMeta", "FlowMeta is not map", "FlowMeta is empty"); |
| 430 | + Map<String, Object> joberMap = this.mapSearch(flowMetaMap, "jober", "Jober is not map", "Jober is empty"); |
| 431 | + Map<String, Object> converterMap = |
| 432 | + this.mapSearch(joberMap, "converter", "Converter is not map", "Converter is empty"); |
| 433 | + return this.mapSearch(converterMap, "entity", "entity is not map", "Entity is empty"); |
| 434 | + } |
| 435 | + |
| 436 | + private Map<String, Object> mapSearch(Map<String, Object> config, String key, String typeErrorMsg, |
| 437 | + String emptyErrorMsg) { |
| 438 | + Object value = config.get(key); |
| 439 | + if (!(value instanceof Map)) { |
| 440 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, typeErrorMsg); |
| 441 | + } |
| 442 | + Map<String, Object> newMap = ObjectUtils.cast(value); |
| 443 | + if (newMap.isEmpty()) { |
| 444 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, emptyErrorMsg); |
| 445 | + } |
| 446 | + return newMap; |
| 447 | + } |
| 448 | + |
| 449 | + private Map<String, Object> getNodeShape(List<?> shapes, String targetId) { |
| 450 | + for (Object shape : shapes) { |
| 451 | + if (!(shape instanceof Map)) { |
| 452 | + continue; |
| 453 | + } |
| 454 | + Map<String, Object> shapeMap = ObjectUtils.cast(shape); |
| 455 | + String idObj = ObjectUtils.cast(shapeMap.get("id")); |
| 456 | + if (StringUtils.equals(idObj, targetId)) { |
| 457 | + return ObjectUtils.cast(shape); |
| 458 | + } |
| 459 | + } |
| 460 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, "Target node is not found"); |
| 461 | + } |
| 462 | + |
| 463 | + private List<?> getShapes(Map<String, Object> appearances) { |
| 464 | + Object pagesObj = appearances.get("pages"); |
| 465 | + if (!(pagesObj instanceof List)) { |
| 466 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, "Pages is not list"); |
| 467 | + } |
| 468 | + List<?> pages = ObjectUtils.cast(pagesObj); |
| 469 | + if (pages.isEmpty()) { |
| 470 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, "Pages is empty"); |
| 471 | + } |
| 472 | + Object pageConfig = pages.get(0); |
| 473 | + if (!(pageConfig instanceof Map)) { |
| 474 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, |
| 475 | + "The first element of pages is not of map type"); |
| 476 | + } |
| 477 | + Map<String, Object> pageConfigMap = ObjectUtils.cast(pageConfig); |
| 478 | + Object shapesObj = pageConfigMap.get("shapes"); |
| 479 | + if (!(shapesObj instanceof List)) { |
| 480 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, "Shapes is not an list type"); |
| 481 | + } |
| 482 | + List<?> shapes = ObjectUtils.cast(shapesObj); |
| 483 | + if (shapes.isEmpty()) { |
| 484 | + throw new AippException(AippErrCode.NODE_CONFIG_UPDATE_FAILED, "Shapes list is empty"); |
| 485 | + } |
| 486 | + return shapes; |
| 487 | + } |
| 488 | + |
312 | 489 | @Override |
313 | 490 | @Fitable(id = "default") |
314 | 491 | public void delete(String appId, OperationContext context) { |
|
0 commit comments