Compare commits

..

1273 Commits

Author SHA1 Message Date
Dot.L a22759136e Merge pull request #298 from APIParkLab/feature/1.7-liujian
update docker build script
2025-04-24 16:03:14 +08:00
Liujian b8ebbac2b8 update docker build script 2025-04-24 16:02:32 +08:00
Dot.L 9c4590db07 Merge pull request #297 from APIParkLab/feature/1.7-liujian
Fix: Apikey getting md5 when calling MCP Server at service level
2025-04-22 18:08:51 +08:00
Liujian 7ba8a57793 Fix: Apikey getting md5 when calling MCP Server at service level 2025-04-22 18:08:24 +08:00
Dot.L 2dc16f4bb8 Merge pull request #295 from APIParkLab/feature/1.7-liujian
Fix: Issue where API portal's service list fails to retrieve when Influxdb is not initialized
2025-04-17 16:20:42 +08:00
Liujian b68496a82a Fix: Issue where API portal's service list fails to retrieve when Influxdb is not initialized 2025-04-17 16:20:17 +08:00
ningyv 6892fa34d8 Merge pull request #294 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP-analytics-table-optimize
2025-04-16 15:47:45 +08:00
ningyv cdbfd3400c feature/1.7-MCP-analytics-table-optimize 2025-04-16 15:46:48 +08:00
Liujian c7c3e8033b Merge remote-tracking branch 'github-pro/main' into feature/1.7-liujian 2025-04-16 15:38:08 +08:00
Dot.L cc524810e8 Merge pull request #293 from APIParkLab/feature/1.7-liujian
Fix: Dragging to modify the order of service categories will fail whe…
2025-04-16 15:22:26 +08:00
Liujian b6f593c8d0 Fix: Dragging to modify the order of service categories will fail when there are subcategories in the service category. 2025-04-16 15:20:57 +08:00
ningyv ca54fc581c Merge pull request #292 from APIParkLab/feature/1.7-cxx
Feature/1.7
2025-04-16 14:42:33 +08:00
ningyv 596f6f5668 feature/1.7-MCP 2025-04-16 14:36:17 +08:00
Dot.L e7372cb7f2 Merge pull request #291 from APIParkLab/feature/1.7-liujian
Feature/1.7 liujian
2025-04-16 14:35:50 +08:00
Liujian feac0428ef Fix: Issue of API duplicate publishing when publishing services 2025-04-16 14:34:18 +08:00
ningyv 7f83f9e37f feature/1.7-MCP 2025-04-16 14:26:17 +08:00
Liujian c8e5b7541d update 2025-04-16 14:12:20 +08:00
ningyv 638b87950d feature/1.7-MCP 2025-04-16 14:07:10 +08:00
ningyv 62b6476420 feature/1.7-MCP 2025-04-16 13:47:54 +08:00
ningyv 16b16bae32 feature/1.7-MCP 2025-04-16 13:44:40 +08:00
ningyv b872e695b0 feature/1.7-MCP 2025-04-16 11:52:32 +08:00
Liujian 8365f77c67 update api portal interface 2025-04-16 11:10:45 +08:00
ningyv 54c88e189e feature/1.7-MCP 2025-04-16 10:18:51 +08:00
ningyv 41dae0daf4 feature/1.7-MCP 2025-04-16 09:53:03 +08:00
ningyv 596be2cf7f feature/1.7-MCP 2025-04-16 09:47:33 +08:00
ningyv ddba01e3bd feature/1.7-MCP 2025-04-16 09:17:35 +08:00
Liujian 96f675ae9c update path 2025-04-16 00:00:58 +08:00
Liujian ae3c189089 MCP Server supports multiple languages. 2025-04-15 22:42:22 +08:00
ningyv 0ff5bcd8fa feature/1.7-MCP 2025-04-15 18:56:50 +08:00
ningyv 37d421ad8a Merge pull request #290 from APIParkLab/feature/1.7-cxx
Feature/1.7 cxx
2025-04-14 17:46:20 +08:00
ningyv 52a4ed8193 feature/1.7-MCP-Breadcrumb 2025-04-14 17:45:25 +08:00
ningyv 211f11b363 feature/1.7-MCP-Breadcrumb 2025-04-14 17:32:18 +08:00
ningyv 6c637bf78c Merge pull request #289 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-14 14:10:37 +08:00
ningyv f846836d5d feature/1.7-MCP 2025-04-14 14:09:09 +08:00
ningyv 43690156e3 Merge pull request #288 from APIParkLab/feature/1.7-cxx
Feature/1.7 cxx
2025-04-14 13:38:08 +08:00
ningyv 71cc0b8916 feature/1.7-MCP 2025-04-14 13:36:08 +08:00
Liujian b703ddaae8 Fix: Issue with invalid apikey parameter in service MCP path 2025-04-14 11:57:06 +08:00
ningyv 5ae9d5d3f1 feature/1.7-MCP 2025-04-14 11:38:13 +08:00
ningyv 061ea05935 Merge pull request #287 from APIParkLab/feature/1.7-cxx
Feature/1.7 cxx
2025-04-14 11:34:19 +08:00
ningyv ca6fdccdb2 feature/1.7-MCP 2025-04-14 11:33:10 +08:00
Liujian fb31ecc012 Merge remote-tracking branch 'github-pro/main' into feature/1.7-liujian 2025-04-14 11:30:13 +08:00
ningyv c2d7d96f9f feature/1.7-MCP 2025-04-14 11:11:48 +08:00
Liujian 741bdd682c Fix: API forwarding header setting failure issue 2025-04-14 10:19:49 +08:00
ningyv 70a8da7682 Merge pull request #286 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-14 09:54:55 +08:00
ningyv 7ccfb69e8d feature/1.7-MCP 2025-04-14 09:53:45 +08:00
ningyv 18615bad33 Merge pull request #285 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-11 18:42:29 +08:00
ningyv d9af85ce86 feature/1.7-MCP 2025-04-11 18:39:27 +08:00
ningyv 8f82436421 Merge pull request #284 from APIParkLab/feature/1.7-cxx
Feature/1.7 cxx
2025-04-11 18:31:52 +08:00
ningyv f42a80e56c feature/1.7-MCP 2025-04-11 18:30:36 +08:00
ningyv c2651d2e5f feature/1.7-MCP 2025-04-11 18:06:38 +08:00
ningyv 44bb977d1a feature/1.7-MCP 2025-04-11 17:28:09 +08:00
ningyv 71bbd9ac8f feature/1.7-MCP 2025-04-11 16:48:34 +08:00
Liujian 4beb497032 Add the openapiaddress field to the API portal to obtain detailed service information 2025-04-11 14:42:26 +08:00
ningyv 56d4a9b69d feature/1.7-MCP 2025-04-11 14:17:50 +08:00
Dot.L b6115faf7c Merge pull request #283 from APIParkLab/feature/1.7-liujian
Feature/1.7 liujian
2025-04-11 11:53:40 +08:00
Liujian 4fdb677103 service detail add invoke_count 2025-04-11 11:52:27 +08:00
Liujian 34cf8e2b26 update global mcp tool's description 2025-04-11 11:03:20 +08:00
ningyv 93f686af14 Merge pull request #282 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-11 10:06:43 +08:00
ningyv 1332770df4 feature/1.7-MCP 2025-04-11 10:05:28 +08:00
Liujian 48ab6d7c7e Merge remote-tracking branch 'github-pro/main' into feature/1.7-liujian 2025-04-10 18:26:12 +08:00
ningyv 08cecd8a0e Merge pull request #281 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-10 17:47:52 +08:00
ningyv 42678fce89 feature/1.7-MCP 2025-04-10 17:47:10 +08:00
ningyv 79f29254ca Merge pull request #280 from APIParkLab/feature/1.7-cxx
feature/1.7-MCP
2025-04-10 16:29:34 +08:00
ningyv 30f9d310e5 feature/1.7-MCP 2025-04-10 16:28:20 +08:00
Liujian cc34ca510c Merge remote-tracking branch 'github-pro/main' into feature/1.7-liujian 2025-04-10 16:23:40 +08:00
ningyv a285c54be2 Merge pull request #279 from APIParkLab/feature/1.7-cxx
Feature/1.7 cxx
2025-04-10 16:23:15 +08:00
ningyv b7119fe248 feature/1.7-MCP 2025-04-10 16:22:26 +08:00
ningyv 7b9f7d5acd feature/1.7-MCP 2025-04-10 16:10:24 +08:00
ningyv b0d642f5e3 feature/1.7-MCP 2025-04-10 15:26:28 +08:00
ningyv 4397784749 Merge pull request #278 from APIParkLab/feature/1.7-cxx
Feature/1.7 cx
2025-04-10 10:48:30 +08:00
ningyv 1eeba2d648 feature/1.7-MCP 2025-04-10 10:47:01 +08:00
ningyv 8cff5b3d40 feature/1.7-MCP 2025-04-10 10:46:54 +08:00
ningyv 2302f39d73 feature/1.7-MCP 2025-04-10 10:46:46 +08:00
Dot.L 114af0c6d2 Merge pull request #277 from APIParkLab/feature/1.7-liujian
Feature/1.7 liujian
2025-04-10 10:15:33 +08:00
Liujian 9069287cd8 update permission 2025-04-09 18:40:22 +08:00
Liujian ca9b127b8b add my apikeys 2025-04-09 18:32:33 +08:00
Liujian 2106836b2c Automatically update MCP server after service release 2025-04-09 15:15:25 +08:00
Liujian cf5cf5b574 fix: mcp response writer stack overflow 2025-04-09 11:40:46 +08:00
Liujian 34240a2609 Adjust the MCP service return result 2025-04-08 19:03:20 +08:00
Liujian eed1f41b29 update go-common version 2025-04-07 11:58:47 +08:00
Liujian 99c6aa19b3 Revert "Auxiliary commit to revert individual files from da05525cbbf2510a2cbc37d7eed6bfb8248e448b"
This reverts commit 202c65529646aa85697d1cce939224d48c67724f.
2025-04-07 11:52:59 +08:00
Liujian 9598254d18 Revert "Auxiliary commit to revert individual files from da05525cbbf2510a2cbc37d7eed6bfb8248e448b"
This reverts commit 1564022cae5da71efc060e576672d51b96051758.
2025-04-07 11:51:50 +08:00
Liujian da05525cbb finsh mcp api 2025-04-07 11:50:14 +08:00
Dot.L 0bc89cda8c Merge pull request #271 from APIParkLab/feature/1.6-liujian
update tongyi,bedrock define
2025-03-27 17:26:35 +08:00
Liujian 11a9b0200e update tongyi,bedrock define 2025-03-27 17:15:03 +08:00
Dot.L a38b244a68 Merge pull request #268 from APIParkLab/feature/1.6-liujian
update issue template: APINTO Dashboard -> ApiPark
2025-03-19 16:24:35 +08:00
Liujian 636fe2b27c update issue template: APINTO Dashboard -> ApiPark 2025-03-19 16:23:23 +08:00
ningyv 29603388a2 Merge pull request #267 from APIParkLab/feature/1.6-cx
fix: Display only file logs on the log page.
2025-03-19 16:19:03 +08:00
ningyv b9d3486f5b fix: Display only file logs on the log page. 2025-03-19 16:13:03 +08:00
Dot.L 09cc099dcd Merge pull request #266 from APIParkLab/feature/1.6-liujian
update tongyi define
2025-03-19 15:36:50 +08:00
Liujian 4f2c02704f update tongyi define 2025-03-19 15:32:36 +08:00
ningyv 93e0d51872 Merge pull request #264 from APIParkLab/feature/1.6-cx
fix: Header navigation click range issue
2025-03-19 14:18:19 +08:00
ningyv 776a410312 fix: Header navigation click range issue 2025-03-19 14:17:13 +08:00
Dot.L 2028f8167f Merge pull request #259 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-14 19:17:25 +08:00
Liujian 03269e703a update ai api schema 2025-03-14 19:16:31 +08:00
Liujian 9772b8123c Fix the issue of duplicate custom suppliers and built-in suppliers 2025-03-14 19:13:58 +08:00
ningyv 31dfe7e295 Merge pull request #258 from APIParkLab/feature/1.6-cx
feat: feature/1.6-Integrate custom model
2025-03-14 18:48:35 +08:00
ningyv 7c3985fea4 feat: feature/1.6-Integrate custom model 2025-03-14 18:47:04 +08:00
Liujian 9c18aa7f3b Add supplier differentiation, custom or built-in 2025-03-14 18:02:28 +08:00
Liujian bc85e59352 fix bug 2025-03-14 15:51:33 +08:00
Dot.L 68a294eb71 Merge pull request #257 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-13 22:17:32 +08:00
Liujian 33c61f6131 Fix the issue of local model data synchronization errors 2025-03-13 22:14:58 +08:00
Liujian 5dd055a43f fix bug 2025-03-13 17:51:27 +08:00
Liujian 937877fa7a fix bug 2025-03-13 14:47:36 +08:00
Liujian 8f994bbea7 Merge remote-tracking branch 'origin/main' into feature/1.6-liujian
# Conflicts:
#	.gitlab-ci.yml
2025-03-13 14:19:57 +08:00
Dot.L 6aca6600d7 Merge pull request #256 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-13 14:17:39 +08:00
Liujian e7aba90808 Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-13 14:16:37 +08:00
Liujian b2fa67c189 fix local model bug 2025-03-13 14:16:03 +08:00
ningyv 271bb32115 Merge pull request #255 from APIParkLab/feature/1.6-cx
feat: feature/1.6-Integrate custom model
2025-03-13 13:54:59 +08:00
lichunxian 7bb0771768 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!270
2025-03-13 13:54:52 +08:00
ningyv 76309c28d2 feat: feature/1.6-Integrate custom model 2025-03-13 13:46:32 +08:00
ningyv 1b55c5534f Merge pull request #254 from APIParkLab/feature/1.6-cx
Feature/1.6 cx
2025-03-13 12:01:10 +08:00
lichunxian 98de71c086 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!269
2025-03-13 12:00:17 +08:00
ningyv 9556fcdf5a feat: feature/1.6-Integrate custom model 2025-03-13 11:58:28 +08:00
Dot.L 68764a4403 Delete .gitlab-ci.yml 2025-03-13 09:18:50 +08:00
孙安智 0084ff260f Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!268
2025-03-12 20:25:24 +08:00
sunanzhi 0c729944b0 Merge pull request #252 from APIParkLab/feature/sunanzhi/1.6
refactor: adjust field requirements in Vertex AI config file
2025-03-12 20:25:13 +08:00
sunanzhi 22ccd3d59e refactor: adjust field requirements in Vertex AI config file 2025-03-12 20:23:41 +08:00
刘健 4c87b5a032 Merge branch 'feature/1.6-liujian' into 'main'
Feature/1.6 liujian

See merge request apipark/APIPark!267
2025-03-12 18:34:34 +08:00
Dot.L 7a5d4c6e9f Merge pull request #251 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-12 18:34:04 +08:00
Liujian 9c530ec470 Synchronize to gateway when custom model updates 2025-03-12 18:33:10 +08:00
Liujian 358459f37a Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-12 17:32:31 +08:00
孙安智 563b029801 Merge branch 'feature/sunanzhi/1.6' into 'main'
refactor: adjust vertex model ID

See merge request apipark/APIPark!266
2025-03-12 17:28:56 +08:00
sunanzhi 7005cb1e76 Merge pull request #250 from APIParkLab/feature/sunanzhi/1.6
refactor: adjust vertex model ID
2025-03-12 17:28:35 +08:00
sunanzhi c79216fd14 refactor: adjust vertex model ID 2025-03-12 17:28:01 +08:00
lichunxian 2fda023607 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!265
2025-03-12 15:43:30 +08:00
ningyv a52d8f1c1f feat: feature/1.6-Integrate custom model 2025-03-12 15:42:07 +08:00
Liujian a7fee633b0 Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-12 15:08:23 +08:00
Liujian 4d64be29ac Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-12 15:08:15 +08:00
sunanzhi 7dedf04e26 Merge pull request #249 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-12 14:55:04 +08:00
孙安智 9a9b4fc521 Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!264
2025-03-12 14:54:37 +08:00
sunanzhi debf9c820c fix: prevent duplicate model names 2025-03-12 14:53:06 +08:00
sunanzhi 51ea7e52b8 fix: resolve missing access config in model 2025-03-12 14:39:37 +08:00
sunanzhi aa1f34f157 Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-12 14:20:29 +08:00
sunanzhi 670b2d845f fix: resolve bug preventing re-adding vendor after deletion 2025-03-12 14:20:04 +08:00
ningyv d8da36d05d Merge pull request #248 from APIParkLab/feature/1.6-cx
feat: feature/1.6-Integrate custom model
2025-03-12 14:11:47 +08:00
lichunxian 0c2d47333f Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!263
2025-03-12 14:09:50 +08:00
ningyv 210cd2f93f feat: feature/1.6-Integrate custom model 2025-03-12 14:08:55 +08:00
sunanzhi 2c997398b9 Merge pull request #247 from APIParkLab/feature/sunanzhi/1.6
fix: resolve inaccurate display of model content
2025-03-12 14:04:20 +08:00
孙安智 57a3936a6d Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!262
2025-03-12 14:04:08 +08:00
sunanzhi fa09e991f4 fix: resolve inaccurate display of model content 2025-03-12 14:03:30 +08:00
刘健 680f814e6b Merge branch 'feature/1.6-liujian' into 'main'
Feature/1.6 liujian

See merge request apipark/APIPark!261
2025-03-12 10:56:45 +08:00
Dot.L afec1e681c Merge pull request #246 from APIParkLab/feature/1.6-liujian
update spark define
2025-03-12 10:09:20 +08:00
Liujian cf07a106b5 update spark define 2025-03-12 10:03:00 +08:00
孙安智 a79b7ec812 Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!260
2025-03-11 20:36:38 +08:00
sunanzhi d8d1cb5665 Merge pull request #245 from APIParkLab/feature/sunanzhi/1.6
refactor: adjust regex validation rules for model name
2025-03-11 20:36:08 +08:00
sunanzhi ac4b29d13c refactor: adjust regex validation rules for model name 2025-03-11 20:35:16 +08:00
Dot.L 5ae7749554 Merge pull request #244 from APIParkLab/feature/1.6-liujian
Local model compatibility testing completed
2025-03-11 19:45:33 +08:00
Liujian a9d5585ef9 Local model compatibility testing completed 2025-03-11 19:44:55 +08:00
Dot.L 224b28bc2c Merge pull request #243 from APIParkLab/feature/1.6-liujian
fix: fail to get ai api model name
2025-03-11 17:18:00 +08:00
Liujian 9fc48341f7 fix: fail to get ai api model name 2025-03-11 17:16:42 +08:00
Dot.L 8b83b2f7e0 Merge pull request #242 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 16:50:30 +08:00
Liujian 6bb818b9a1 update provider define 2025-03-11 16:49:17 +08:00
ningyv 1e8a75e8f7 Merge pull request #241 from APIParkLab/feature/1.6-cx
feat: feature/1.6-Integrate custom model
2025-03-11 16:43:18 +08:00
Liujian 6392272a2e Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-11 16:03:43 +08:00
lichunxian 51191c3eb6 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!259
2025-03-11 16:02:40 +08:00
ningyv 2aa021f74b feat: feature/1.6-Integrate custom model 2025-03-11 16:02:02 +08:00
Liujian 4ed8f01981 Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-11 16:01:58 +08:00
Dot.L 9f2eadbfad Merge pull request #240 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 15:27:47 +08:00
Liujian 084d2f6c09 update config of publishing provider 2025-03-11 15:27:01 +08:00
孙安智 737bf822d1 Merge branch 'feature/sunanzhi/1.6' into 'main'
refactor: remove validation for checking provider existence in model addition

See merge request apipark/APIPark!258
2025-03-11 15:23:28 +08:00
sunanzhi 00c7c4e205 Merge pull request #239 from APIParkLab/feature/sunanzhi/1.6
refactor: adjust character limit for custom provider/model name
2025-03-11 15:23:12 +08:00
sunanzhi c4670e1cb1 refactor: remove validation for checking provider existence in model addition 2025-03-11 15:22:06 +08:00
Liujian 4cfaf64de3 Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-11 15:16:59 +08:00
Liujian 2eb5d30e91 Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-11 14:28:09 +08:00
孙安智 0c6238e380 Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!257
2025-03-11 12:02:23 +08:00
sunanzhi 299ee0fd25 refactor: adjust character limit for custom provider/model name 2025-03-11 12:01:20 +08:00
Dot.L 4b610eceba Merge pull request #238 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 11:51:35 +08:00
lichunxian 84cf398cc5 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!256
2025-03-11 10:24:02 +08:00
ningyv 470a945bad feat: feature/1.6-Integrate custom model 2025-03-11 10:23:26 +08:00
刘健 ea28f6024f Merge branch 'feature/1.6-liujian' into 'main'
Feature/1.6 liujian

See merge request apipark/APIPark!255
2025-03-11 10:04:59 +08:00
Liujian c1ddfbf21c update ai provider define file 2025-03-11 10:04:14 +08:00
Liujian 490f9191ff Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-10 19:48:02 +08:00
Liujian dbdd0ac4bf Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-10 19:47:56 +08:00
Liujian a3b740a390 support service mapping 2025-03-10 19:47:45 +08:00
lichunxian cbcd693086 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!254
2025-03-10 18:03:46 +08:00
ningyv 428cfb144e feat: feature/1.6-Integrate custom model 2025-03-10 18:03:09 +08:00
孙安智 e352ddeb99 Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!253
2025-03-10 17:47:52 +08:00
sunanzhi 1e4ae7b4c7 fix: resolve null pointer caused by URI error 2025-03-10 17:41:04 +08:00
Dot.L cf48d2f3f1 Merge pull request #235 from APIParkLab/feature/1.6-liujian
Cancel publishing related comments
2025-03-10 14:54:54 +08:00
刘健 d462fda694 Merge branch 'feature/1.6-liujian' into 'main'
Feature/1.6 liujian

See merge request apipark/APIPark!252
2025-03-10 14:54:42 +08:00
Liujian 5089901491 Cancel publishing related comments 2025-03-10 14:53:17 +08:00
lichunxian 71d9dfc724 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!251
2025-03-10 11:41:45 +08:00
ningyv 92523eaf30 feat: feature/1.6-Integrate custom model 2025-03-10 11:40:18 +08:00
sunanzhi 2be3aecf39 Merge pull request #234 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-10 10:45:04 +08:00
孙安智 d206eafd77 Merge branch 'feature/sunanzhi/1.6' into 'main'
feat: add provider type field

See merge request apipark/APIPark!250
2025-03-10 10:44:42 +08:00
sunanzhi e9f259bf6f Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-10 10:43:45 +08:00
sunanzhi 897f2b5bd2 feat: add provider type field 2025-03-10 10:42:33 +08:00
lichunxian 7b414ce5b5 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!249
2025-03-10 10:35:10 +08:00
ningyv 35714779f9 feat: feature/1.6-Integrate custom model 2025-03-10 10:34:35 +08:00
lichunxian 1d926c2411 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!248
2025-03-10 10:10:30 +08:00
ningyv 753b81d3dd feat: feature/1.6-Integrate custom model 2025-03-10 10:09:42 +08:00
lichunxian 6078322db5 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!247
2025-03-10 09:45:58 +08:00
ningyv 4577aca730 feat: feature/1.6-Integrate custom model 2025-03-10 09:45:15 +08:00
sunanzhi a53a527d80 Merge pull request #233 from APIParkLab/feature/sunanzhi/1.6
fix: resolve duplicate linked list data in model caused by updating v…
2025-03-07 20:09:45 +08:00
孙安智 67a6501ee0 Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: resolve duplicate linked list data in model caused by updating vendor

See merge request apipark/APIPark!246
2025-03-07 20:09:21 +08:00
sunanzhi fce631cc87 fix: resolve duplicate linked list data in model caused by updating vendor 2025-03-07 20:08:56 +08:00
孙安智 2e4287d585 Merge branch 'feature/sunanzhi/1.6' into 'main'
Feature/sunanzhi/1.6

See merge request apipark/APIPark!245
2025-03-07 19:54:11 +08:00
sunanzhi 8624576bf8 Merge pull request #232 from APIParkLab/feature/sunanzhi/1.6
fix: resolve issue with adding vendor not loading
2025-03-07 19:54:09 +08:00
sunanzhi 4d72446c64 fix: resolve issue with adding vendor not loading 2025-03-07 19:52:47 +08:00
sunanzhi faf621b646 Merge pull request #231 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 18:54:06 +08:00
sunanzhi f2acea30e2 Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-07 18:50:34 +08:00
孙安智 c6dbe334e9 Merge branch 'feature/sunanzhi/1.6' into 'main'
refactor: adjust model_runtime structure of provider model

See merge request apipark/APIPark!244
2025-03-07 18:43:45 +08:00
sunanzhi a8c842b8d0 refactor: adjust model_runtime structure of provider model 2025-03-07 18:32:20 +08:00
孙安智 95e34f0b73 Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: resolve build failure due to unused model variable

See merge request apipark/APIPark!243
2025-03-07 15:09:25 +08:00
sunanzhi 69fd1b915b fix: resolve build failure due to unused model variable 2025-03-07 15:08:50 +08:00
孙安智 7483455bb8 Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: resolve null pointer due to empty validator and comment out release model code

See merge request apipark/APIPark!242
2025-03-07 14:58:33 +08:00
sunanzhi 77e6f100b7 fix: resolve null pointer due to empty validator and comment out release model code 2025-03-07 14:56:54 +08:00
sunanzhi 69a3a7d5ba Merge pull request #229 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 14:34:19 +08:00
孙安智 6dae2e7068 Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: resolve error caused by fetching empty vendor config model

See merge request apipark/APIPark!241
2025-03-07 14:33:49 +08:00
sunanzhi d3bd782165 fix: resolve error caused by fetching empty vendor config model 2025-03-07 14:33:23 +08:00
lichunxian b49782c7b4 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!240
2025-03-07 14:24:57 +08:00
ningyv 8ca8d51025 feat: feature/1.6-Integrate custom model 2025-03-07 14:24:14 +08:00
孙安智 f8affd2f29 Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: resolve package error when LLMs list is empty

See merge request apipark/APIPark!239
2025-03-07 14:14:53 +08:00
sunanzhi 3d4e2c3165 fix: resolve package error when LLMs list is empty 2025-03-07 14:07:53 +08:00
孙安智 7cca06377c Merge branch 'feature/sunanzhi/1.6' into 'main'
fix: fix null pointer in unconfigured provider fetch, add model name to list

See merge request apipark/APIPark!238
2025-03-07 11:41:31 +08:00
sunanzhi 22f15f5cbf fix: fix null pointer in unconfigured provider fetch, add model name to list 2025-03-07 11:38:14 +08:00
sunanzhi b8c73b7730 Merge pull request #228 from APIParkLab/feature/sunanzhi/1.6
feat: add API endpoint to retrieve model configuration template
2025-03-07 11:17:02 +08:00
孙安智 fb71498e6a Merge branch 'feature/sunanzhi/1.6' into 'main'
feat: add API endpoint to retrieve model configuration template

See merge request apipark/APIPark!237
2025-03-07 11:16:33 +08:00
sunanzhi bc16d7f5ce feat: add API endpoint to retrieve model configuration template
Introduce a new interface for fetching model configuration templates to enhance model management flexibility.
2025-03-07 11:15:49 +08:00
lichunxian 62bc87e251 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!236
2025-03-07 11:06:38 +08:00
ningyv b1f010ad60 feat: feature/1.6-Integrate custom model 2025-03-07 11:05:53 +08:00
sunanzhi 8e4a3fc42b Merge pull request #226 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 09:27:39 +08:00
孙安智 bf08952fe0 Merge branch 'feature/sunanzhi/1.6' into 'main'
Add support for creating online models and integrating custom model providers

See merge request apipark/APIPark!235
2025-03-07 09:26:32 +08:00
sunanzhi 51792a8eda Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6
# Conflicts:
#	.gitignore
2025-03-06 18:33:21 +08:00
dashenbibi dd4fdd8de3 Merge pull request #225 from APIParkLab/feature/dashen/model_mapping
Feature/dashen/model mapping
2025-03-06 18:27:32 +08:00
sunanzhi b9f6abc9b3 Add support for creating online models and integrating custom model providers 2025-03-06 17:42:17 +08:00
lichunxian 4ca4d9fd82 Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!234
2025-03-06 16:17:17 +08:00
ningyv 1ed05b96b4 feat: feature/1.6-Integrate custom model 2025-03-06 16:16:20 +08:00
lichunxian e9b7cb505d Merge branch 'feature/1.6-cx' into 'main'
feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!233
2025-03-06 11:34:50 +08:00
ningyv a7f1da85b1 Merge remote-tracking branch 'origin/main' into feature/1.6-cx 2025-03-06 11:31:29 +08:00
ningyv 59c0bfe3f5 feat: feature/1.6-Integrate custom model 2025-03-06 11:07:58 +08:00
李业昌 f893819f32 Merge branch 'feature/dashen/model_mapping' into 'main'
Feature/dashen/model mapping

See merge request apipark/APIPark!231
2025-03-05 10:50:06 +08:00
2944321442@qq.com 8c40e1cf05 .gitignore 2025-03-05 10:49:22 +08:00
2944321442@qq.com afb9cc2e44 feat:update .gitignore 2025-03-05 10:44:19 +08:00
2944321442@qq.com 8e854adaa3 feat:update .gitignore 2025-03-05 10:43:20 +08:00
2944321442@qq.com 860874ef5c feat:添加服务模型映射功能 2025-03-05 10:15:05 +08:00
2944321442@qq.com 4b263c1e7a Merge branch 'main' into feature/dashen/model_mapping 2025-03-05 10:15:00 +08:00
2944321442@qq.com eaeae88f04 feat: add service model mapping configuration 2025-03-04 15:19:27 +08:00
ningyv 7a84c5aec3 Merge pull request #222 from APIParkLab/feature/1.5-cx
fix: homepage Permission Configuration
2025-03-03 14:21:16 +08:00
lichunxian 1d91f9e78c Merge branch 'feature/1.5-cx' into 'main'
Feature/1.5 cx

See merge request apipark/APIPark!230
2025-03-03 14:20:46 +08:00
ningyv 1a8538b617 fix: homepage Permission Configuration 2025-03-03 14:20:20 +08:00
ningyv ddd1d662b1 Merge pull request #221 from APIParkLab/feature/1.5-cx
fix: homepage Permission Configuration
2025-03-03 14:15:27 +08:00
ningyv c56319d1c2 fix: homepage Permission Configuration 2025-03-03 14:14:20 +08:00
ningyv d489912705 Merge pull request #220 from APIParkLab/feature/1.6
fix: service configuration LLM API error
2025-03-03 09:51:49 +08:00
ningyv f95437ad1a fix: service configuration LLM API error 2025-03-03 09:51:14 +08:00
ningyv 04bbac1252 Merge pull request #212 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-20 18:36:42 +08:00
lichunxian f058f2bc71 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!229
2025-02-20 18:36:14 +08:00
ningyv aa873f75f2 feat: feature/1.5-Data Integration 2025-02-20 18:35:26 +08:00
Dot.L 70de481b52 Merge pull request #211 from APIParkLab/feature/1.5-local-model
This pull request includes several changes aimed at improving error handling, adding new functionalities, and refactoring existing code. The changes primarily focus on the AI provider and controller modules.

Error Handling Improvements:
Added checks to ensure the client is initialized before performing operations in multiple functions (PullModel, StopPull, CancelPipeline, RemoveModel, ModelsInstalled) in ai-provider/local/executor.go. [1] [2] [3] [4]
New Functionalities:
Introduced OllamaConfig and OllamaConfigUpdate methods to the ILocalModelController interface and implemented them in controller/ai-local/iml.go. These methods allow for getting and updating the Ollama configuration. [1] [2]
Added functionality to automatically subscribe all applications to new services in the Create method of controller/service/iml.go.
Refactoring:
Refactored the initialization of the Ollama client by replacing the static address with a ResetOllamaAddress function in ai-provider/local/local.go.
Removed unused code and imports, such as the newAIUpstream function and upstream_dto import in controller/service/iml.go. [1] [2]
Codebase Simplification:
Simplified the OnInit method in controller/system/iml.go by consolidating the creation of default entities and adding subscription logic. [1] [2] [3]
Additional Changes:
Added new imports and modules to support the new functionalities and refactoring efforts. [1] [2] [3]
2025-02-20 14:31:31 +08:00
刘健 b41e8bbb8c Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!228
2025-02-20 14:25:08 +08:00
Liujian 17f700c77d Fix: Failure to update local model configuration to gateway 2025-02-20 14:24:39 +08:00
ningyv 89b4a51774 Merge pull request #210 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-20 14:20:59 +08:00
lichunxian 92627b0a69 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!227
2025-02-20 14:20:14 +08:00
ningyv 8e974a4fe3 feat: feature/1.5-Data Integration 2025-02-20 14:19:34 +08:00
ningyv 60a151f798 Merge pull request #209 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-20 13:52:50 +08:00
lichunxian 6839539321 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!226
2025-02-20 13:52:30 +08:00
ningyv 0dc5685aa9 feat: feature/1.5-Data Integration 2025-02-20 13:51:53 +08:00
ningyv 35f8a1e539 Merge pull request #208 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-20 11:37:47 +08:00
lichunxian 3adbe4b74f Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!225
2025-02-20 11:37:17 +08:00
ningyv 179b9e16d6 feat: feature/1.5-Data Integration 2025-02-20 11:36:34 +08:00
Liujian b573b380ab Merge remote-tracking branch 'github-pro/main' into feature/1.5-local-model 2025-02-19 19:51:32 +08:00
Liujian fb9c92e941 fix: ai balance bug 2025-02-19 19:18:17 +08:00
ningyv 2ae6af46ef Merge pull request #207 from APIParkLab/feature/1.5-cx
Feature/1.5 cx
2025-02-19 18:41:45 +08:00
lichunxian 224411b593 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!224
2025-02-19 18:19:58 +08:00
ningyv e366f3545f feat: feature/1.5-Data Integration 2025-02-19 18:19:17 +08:00
刘健 3721eea772 Merge branch 'feature/1.5-local-model' into 'main'
Fix: Issue of failed update service

See merge request apipark/APIPark!223
2025-02-19 18:00:04 +08:00
Liujian e16e06d8b6 Fix: Issue of failed update service 2025-02-19 17:58:20 +08:00
lichunxian a60bd5eba7 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!222
2025-02-19 17:57:28 +08:00
ningyv 8dca13f4e5 feat: feature/1.5-Data Integration 2025-02-19 17:56:46 +08:00
刘健 d0464b988a Merge branch 'feature/1.5-local-model' into 'main'
Add model information field to service information

See merge request apipark/APIPark!221
2025-02-19 17:24:27 +08:00
Liujian 60662c443d Add model information field to service information 2025-02-19 17:24:12 +08:00
lichunxian 2420cfdd9a Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!220
2025-02-19 16:06:00 +08:00
ningyv 2aad0959c4 feat: feature/1.5-Data Integration 2025-02-19 16:05:19 +08:00
刘健 9a145cb0b0 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!219
2025-02-19 10:58:00 +08:00
Liujian 690c2fe2f7 Fix: Issue where the service status is not updated after the local model download is completed 2025-02-19 10:57:39 +08:00
Liujian 9a833023ce Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-19 10:27:11 +08:00
lichunxian 62456f632e Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!218
2025-02-19 10:23:47 +08:00
ningyv 4128de90fd feat: feature/1.5-Data Integration 2025-02-19 10:23:16 +08:00
Liujian 0eb24ef7b1 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-19 10:13:55 +08:00
lichunxian 1c96e82629 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!217
2025-02-19 09:35:31 +08:00
ningyv 7af43de521 feat: feature/1.5-Data Integration 2025-02-19 09:34:09 +08:00
lichunxian 502af9c782 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!216
2025-02-19 09:28:04 +08:00
ningyv 1897fe9467 feat: feature/1.5-Data Integration 2025-02-19 09:27:10 +08:00
lichunxian 1da4c35cdc Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!215
2025-02-18 22:18:03 +08:00
ningyv 9de48bf400 feat: feature/1.5-Data Integration 2025-02-18 21:55:58 +08:00
lichunxian ffb3f51fb6 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!214
2025-02-18 19:52:13 +08:00
ningyv 7e2852b7e6 feat: feature/1.5-Data Integration 2025-02-18 19:51:28 +08:00
Liujian 184db4c933 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-18 18:06:32 +08:00
lichunxian 6beb2576ce Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!212
2025-02-18 16:00:41 +08:00
ningyv 7f3e43d929 fix: route handling does not work on page reload 2025-02-18 16:00:12 +08:00
刘健 4dcb71042c Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!213
2025-02-18 15:43:45 +08:00
Liujian 30c09006b0 add api: get/set ollama api address 2025-02-18 15:42:57 +08:00
Dot.L fbd9e1d979 Merge pull request #205 from APIParkLab/feature/1.5-local-model
Feature/1.5 local model
2025-02-18 10:24:34 +08:00
Liujian d143aee8c3 fix: cancel deploy error 2025-02-18 10:20:33 +08:00
ningyv aaadc5e450 Merge pull request #204 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-18 10:18:17 +08:00
ningyv 861c389277 feat: feature/1.5-Data Integration 2025-02-18 10:08:20 +08:00
Liujian c3b41b047d Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-17 21:24:33 +08:00
lichunxian 1499036792 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!211
2025-02-17 20:15:54 +08:00
刘健 903f9a08a2 Update .gitlab-ci.yml file 2025-02-17 20:14:06 +08:00
ningyv 1228bdd756 feat: feature/1.5-Data Integration 2025-02-17 20:13:20 +08:00
刘健 9e35325600 Update .gitlab-ci.yml file 2025-02-17 19:37:30 +08:00
刘健 0ec9492838 Merge branch 'feature/1.5-local-model' into 'main'
update service list sort

See merge request apipark/APIPark!210
2025-02-17 18:32:34 +08:00
Liujian fc7fe48920 update service list sort 2025-02-17 18:31:05 +08:00
刘健 e3d272404d Merge branch 'feature/1.5-local-model' into 'main'
init service consumer

See merge request apipark/APIPark!209
2025-02-17 18:14:37 +08:00
Liujian 9e4efae3a5 init service consumer 2025-02-17 18:12:47 +08:00
刘健 df16946d37 Merge branch 'feature/1.5-local-model' into 'main'
init service consumer

See merge request apipark/APIPark!208
2025-02-17 18:12:32 +08:00
Liujian 61f4742d19 init service consumer 2025-02-17 18:08:29 +08:00
刘健 cad081f1bc Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!207
2025-02-17 17:42:16 +08:00
Liujian bc8870a735 fix: bug 2025-02-17 17:21:48 +08:00
Liujian 713227f0fe Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-17 16:38:07 +08:00
ningyv 661aa92732 Merge pull request #203 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-17 16:35:19 +08:00
lichunxian f8f15c51b1 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!206
2025-02-17 16:34:45 +08:00
ningyv 32805d9bf8 feat: feature/1.5-Data Integration 2025-02-17 16:33:49 +08:00
刘健 7767284c98 Merge branch 'feature/1.5-local-model' into 'main'
Fix: Service List AI Entry Error

See merge request apipark/APIPark!205
2025-02-17 16:12:38 +08:00
Liujian 9efb9600c9 Fix: Service List AI Entry Error 2025-02-17 16:12:21 +08:00
刘健 dcb3f2879a Merge branch 'feature/1.5-local-model' into 'main'
fix: ai deploy bug

See merge request apipark/APIPark!204
2025-02-17 15:24:28 +08:00
Liujian 6d12f251a1 fix: ai deploy bug 2025-02-17 15:23:57 +08:00
ningyv 8ae66e9a22 Merge pull request #202 from APIParkLab/feature/1.5-cx
feat: feature/1.5-Data Integration
2025-02-17 15:17:42 +08:00
lichunxian db74c102f9 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!203
2025-02-17 15:17:11 +08:00
ningyv d1eea10fe6 feat: feature/1.5-Data Integration 2025-02-17 15:16:45 +08:00
ningyv 1b4009e4a1 Merge pull request #201 from APIParkLab/feature/1.5
Feature/1.5
2025-02-17 13:42:36 +08:00
ningyv 983a5423c9 Merge pull request #190 from APIParkLab/feature/1.5-cx
feat:Feature/1.5
2025-02-17 13:38:22 +08:00
Dot.L 99934ec16c Merge pull request #200 from APIParkLab/feature/1.5-local-model
Feature/1.5 local model
2025-02-17 13:36:28 +08:00
刘健 7d59a6074f Merge branch 'feature/1.5-local-model' into 'main'
add:init ai balance

See merge request apipark/APIPark!202
2025-02-17 11:42:07 +08:00
Liujian 70972cc92e add:init ai balance 2025-02-17 11:41:07 +08:00
lichunxian c81f6d659d Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!201
2025-02-17 11:32:25 +08:00
ningyv 6097b0e946 feat: feature/1.5-Data Integration 2025-02-17 11:30:52 +08:00
lichunxian 7c1865f36f Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!200
2025-02-17 11:07:23 +08:00
ningyv 3a0c165cec feat: feature/1.5-Data Integration 2025-02-17 11:06:23 +08:00
刘健 e8a8d4ec19 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!199
2025-02-17 10:45:56 +08:00
Liujian cd0982ce20 update api: simple local models 2025-02-17 10:45:34 +08:00
Liujian b4aeb435c6 update provider model define 2025-02-17 10:25:12 +08:00
刘健 c51f9f1dcb Merge branch 'feature/1.5-local-model' into 'main'
fix: ai deploy bug

See merge request apipark/APIPark!198
2025-02-17 00:37:59 +08:00
Liujian 94d5ed0773 fix: ai deploy bug 2025-02-17 00:37:25 +08:00
刘健 baf1369f58 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!197
2025-02-16 21:51:20 +08:00
Liujian 35b25289bd fix: ai balance bug 2025-02-16 21:50:56 +08:00
Liujian e336b8324a Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-16 21:38:41 +08:00
刘健 d0e6162386 Merge branch 'feature/1.5-local-model' into 'main'
fix:bug

See merge request apipark/APIPark!196
2025-02-16 00:57:43 +08:00
Liujian c5e4316e37 fix:bug 2025-02-16 00:57:18 +08:00
lichunxian b52c12a922 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!195
2025-02-15 18:51:16 +08:00
ningyv 1127df66f7 feat: feature/1.5-Data Integration 2025-02-15 18:50:38 +08:00
lichunxian 4b98ceb2d4 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!194
2025-02-15 18:31:38 +08:00
ningyv 5286b90b27 feat: feature/1.5-Data Integration 2025-02-15 18:30:21 +08:00
lichunxian 9ffa194d6d Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!193
2025-02-15 18:12:31 +08:00
ningyv b9c6bac15b feat: feature/1.5-Data Integration 2025-02-15 18:11:36 +08:00
刘健 1aa18177c9 Merge branch 'feature/1.5-local-model' into 'main'
本地模型列表新增provider

See merge request apipark/APIPark!192
2025-02-15 17:59:48 +08:00
Liujian 068d852c20 本地模型列表新增provider 2025-02-15 17:59:03 +08:00
lichunxian 5caf9560cb Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!191
2025-02-15 17:45:01 +08:00
ningyv e1194ff391 feat: feature/1.5-Data Integration 2025-02-15 17:44:23 +08:00
lichunxian 6fb3bece43 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!190
2025-02-15 17:27:35 +08:00
ningyv 90ae7b0741 feat: feature/1.5-Data Integration 2025-02-15 17:26:58 +08:00
lichunxian 8a13c7b312 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!189
2025-02-15 17:16:20 +08:00
ningyv 519673ec01 feat: feature/1.5-Data Integration 2025-02-15 17:15:36 +08:00
刘健 b4a22b29f3 Merge branch 'feature/1.5-local-model' into 'main'
update api doc

See merge request apipark/APIPark!188
2025-02-15 10:58:52 +08:00
Liujian 2bbddc81b1 update api doc 2025-02-15 10:58:13 +08:00
刘健 e0171c45e1 Merge branch 'feature/1.5-local-model' into 'main'
fix:bug

See merge request apipark/APIPark!187
2025-02-15 10:57:04 +08:00
Liujian 3427d8fd07 fix:bug 2025-02-15 10:56:38 +08:00
lichunxian 2b3bfdec99 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!186
2025-02-15 10:14:02 +08:00
ningyv 2cca6d4bba feat: feature/1.5-Data Integration 2025-02-15 10:13:10 +08:00
刘健 c776dc2206 Merge branch 'feature/1.5-local-model' into 'main'
Fix: AI model list keyword query failure issue

See merge request apipark/APIPark!185
2025-02-14 23:47:05 +08:00
Liujian 34c971ad77 Fix: AI model list keyword query failure issue 2025-02-14 23:46:29 +08:00
刘健 91b2932d62 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!184
2025-02-14 23:27:54 +08:00
Liujian 3127cc6780 finish:quick create service 2025-02-14 23:27:24 +08:00
Liujian 0dc5439726 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 23:08:26 +08:00
lichunxian f7e3db9043 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!183
2025-02-14 22:24:15 +08:00
ningyv 7a635430f1 feat: feature/1.5-Data Integration 2025-02-14 22:23:21 +08:00
lichunxian 0bb11bcca5 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!182
2025-02-14 21:52:42 +08:00
ningyv 412d15a9b4 feat: feature/1.5-Data Integration 2025-02-14 21:51:46 +08:00
刘健 10eda384e6 Merge branch 'feature/1.5-local-model' into 'main'
update model colomn length

See merge request apipark/APIPark!181
2025-02-14 21:20:15 +08:00
Liujian 7866572191 update model colomn length 2025-02-14 21:19:55 +08:00
刘健 4b5cbb3fcc Merge branch 'feature/1.5-local-model' into 'main'
add ollama logo

See merge request apipark/APIPark!180
2025-02-14 21:10:43 +08:00
Liujian 614b46e6fc add ollama logo 2025-02-14 21:10:04 +08:00
lichunxian f7ad32c1cc Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!179
2025-02-14 20:57:39 +08:00
ningyv 2afb106ba9 feat: feature/1.5-Data Integration 2025-02-14 20:56:35 +08:00
lichunxian fce2cc8636 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!178
2025-02-14 20:45:18 +08:00
ningyv ba4362ae64 feat: feature/1.5-Data Integration 2025-02-14 20:44:40 +08:00
刘健 8545938654 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!177
2025-02-14 20:25:11 +08:00
Liujian 4d87b3aafb Improve deployment logic 2025-02-14 20:22:49 +08:00
Liujian 5784d3f5d1 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 19:15:31 +08:00
lichunxian fb1b5280fe Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!176
2025-02-14 18:51:23 +08:00
ningyv 253e655b31 feat: feature/1.5-Data Integration 2025-02-14 18:50:30 +08:00
刘健 13eb5bb1e8 Merge branch 'feature/1.5-local-model' into 'main'
update role permission

See merge request apipark/APIPark!175
2025-02-14 18:41:50 +08:00
Liujian 72dcd0a073 update role permission 2025-02-14 18:41:09 +08:00
刘健 1971db2405 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!174
2025-02-14 18:36:43 +08:00
Liujian 3093471063 Gin responds to cancel gzip compression 2025-02-14 18:36:25 +08:00
lichunxian 14874d7869 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!173
2025-02-14 18:05:18 +08:00
ningyv bfdec9e08b feat: feature/1.5-Data Integration 2025-02-14 18:04:38 +08:00
lichunxian cbec924300 Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Data Integration

See merge request apipark/APIPark!172
2025-02-14 17:44:15 +08:00
ningyv a03f87b907 feat: feature/1.5-Data Integration 2025-02-14 17:43:41 +08:00
Liujian e100f475ae Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 17:37:28 +08:00
刘健 76e66bcf6f Merge branch 'feature/1.5-local-model' into 'main'
Fix: Local model deployment status error

See merge request apipark/APIPark!171
2025-02-14 17:24:58 +08:00
Liujian 26a50b9a79 Fix: Local model deployment status error 2025-02-14 17:24:41 +08:00
刘健 4e38760b44 Merge branch 'feature/1.5-local-model' into 'main'
update deploy status

See merge request apipark/APIPark!170
2025-02-14 17:07:21 +08:00
Liujian aef9805bdf update deploy status 2025-02-14 17:06:34 +08:00
lichunxian bb7ccde958 Merge branch 'feature/1.5-cx' into 'main'
feat: Local deployment popup optimization

See merge request apipark/APIPark!169
2025-02-14 16:46:31 +08:00
ningyv 55aef95304 feat: Local deployment popup optimization 2025-02-14 16:45:39 +08:00
刘健 aa338f7aa7 Merge branch 'feature/1.5-local-model' into 'main'
Feature/1.5 local model

See merge request apipark/APIPark!168
2025-02-14 16:36:02 +08:00
Liujian ee06368a4e finish ai balance 2025-02-14 16:29:56 +08:00
Liujian edfb2006b2 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5/local-model 2025-02-14 15:43:38 +08:00
lichunxian 015ecfd182 Merge branch 'feature/1.5-cx' into 'main'
feat: Local deployment popup optimization

See merge request apipark/APIPark!167
2025-02-14 15:40:35 +08:00
ningyv 99b65bead6 feat: Local deployment popup optimization 2025-02-14 15:39:01 +08:00
Liujian 98efa0f804 Merge remote-tracking branch 'github-pro/feature/1.5-cx' into feature/1.5/local-model 2025-02-14 15:36:54 +08:00
Liujian 2ff7458c4e local model first commit 2025-02-14 15:34:41 +08:00
lichunxian 60fa35376b Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5-Model Deployment Process Popup Optimization

See merge request apipark/APIPark!166
2025-02-13 18:24:20 +08:00
ningyv 2fbaba710d feat: feature/1.5-Model Deployment Process Popup Optimization 2025-02-13 18:22:58 +08:00
lichunxian 222eafe86d Merge branch 'feature/1.5-cx' into 'main'
feat: feature/1.5

See merge request apipark/APIPark!165
2025-02-13 17:03:58 +08:00
ningyv 86bb513db6 feat: Style and Prompt Optimization 2025-02-13 17:02:40 +08:00
Liujian 88d4c5101e async excutor first commit 2025-02-13 11:53:52 +08:00
lichunxian df4126514f Merge branch 'feature/1.5-cx' into 'main'
feat:Feature/1.5 cx

See merge request apipark/APIPark!164
2025-02-13 10:09:18 +08:00
ningyv 471643d4ea feat: Multilingual Translation 2025-02-13 09:51:43 +08:00
ningyv 444a48c8f2 feat: progress log 2025-02-12 18:20:35 +08:00
ningyv ec951dd87f feat: local model list page 2025-02-12 16:45:57 +08:00
ningyv 7ac385b317 feat: local model list page 2025-02-12 15:28:17 +08:00
ningyv 2f435d561e feat: merge api model page 2025-02-12 11:27:47 +08:00
scarqin 3a718d2cd8 feat: delete model 2025-02-12 00:33:16 +08:00
scarqin d87a420752 feat: api list 2025-02-11 19:15:11 +08:00
scarqin 6491de3064 feat: online model settings 2025-02-11 19:01:15 +08:00
ningyv 5cc01d7aab feat: load banancing list 2025-02-11 18:27:14 +08:00
ningyv 628cd98fd0 feat: feature/1.5 Extract home page navigation component 2025-02-11 10:36:47 +08:00
ningyv 8ce65cbe3d feat: Deployment Progress Popup Development 2025-02-10 17:03:28 +08:00
ningyv 0b2928eb3c feat: Home Page AI Service Deployment 2025-02-08 18:47:08 +08:00
Dot.L 45ce43ab15 Merge pull request #189 from APIParkLab/feature/openapi
update workflows actions/download-artifact to v4
2025-02-08 16:15:32 +08:00
Liujian 637044e99d update workflows actions/download-artifact to v4 2025-02-08 16:14:01 +08:00
Dot.L 3a96e02fc7 Merge pull request #188 from APIParkLab/feature/openapi
update workflows actions/upload-artifact to v4
2025-02-08 15:59:53 +08:00
Liujian 18a3283cb4 update workflows actions/upload-artifact to v4 2025-02-08 15:57:36 +08:00
Dot.L c3b8ba4d04 Merge pull request #187 from APIParkLab/feature/openapi
Feature/openapi
2025-02-08 15:02:06 +08:00
Liujian a51ccf6d67 Merge remote-tracking branch 'github-pro/main' into feature/openapi 2025-02-08 15:01:27 +08:00
Liujian 6b1224f9f8 Fix: AI provider's default key synchronization to Apinto failed issue 2025-02-08 14:58:36 +08:00
Liujian 907f9c00fb Merge remote-tracking branch 'origin/main' into feature/openapi 2025-01-23 16:54:58 +08:00
ningyv ed72062d33 Merge pull request #183 from APIParkLab/feature/1.4
chroe: optimize AI model node graphics
2025-01-23 14:01:10 +08:00
ningyv af9f5cef2f Merge remote-tracking branch 'origin/main' into feature/1.4 2025-01-23 13:57:01 +08:00
lichunxian 2c205921d6 Merge branch 'feature/1.4' into 'main'
chroe: optimize AI model node graphics

See merge request apipark/APIPark!161
2025-01-21 11:52:02 +08:00
ningyv 4e2b424eeb chroe: optimize AI model node graphics 2025-01-21 11:50:58 +08:00
刘健 22e738a164 Merge branch 'feature/openapi' into 'main'
Feature/openapi

See merge request apipark/APIPark!160
2025-01-20 17:36:53 +08:00
Dot.L 6824cdd4a1 Merge pull request #181 from APIParkLab/feature/openapi
fix:ai init bug
2025-01-20 14:08:37 +08:00
Liujian d44dd05462 fix:ai init bug 2025-01-20 14:03:03 +08:00
Dot.L 7d6666c0b6 Merge pull request #180 from APIParkLab/feature/openapi
Feature/openapi
2025-01-20 13:55:59 +08:00
Liujian 070882655d update ai bug 2025-01-20 13:54:58 +08:00
刘健 cdb0831174 Merge branch 'feature/openapi' into 'main'
fix: Nsq returns no error directly after parsing JSON exceptionNsq returns no...

See merge request apipark/APIPark!159
2025-01-17 16:03:51 +08:00
Liujian 0a864aea41 add openapi 2025-01-17 16:03:09 +08:00
Dot.L a4464610eb Merge pull request #174 from jeak01/patch-2
Update readme-zh-cn.md
2025-01-17 15:55:09 +08:00
Dot.L 18a03d57b4 Merge pull request #175 from jeak01/patch-3
Update readme-zh-tw.md
2025-01-17 15:54:50 +08:00
Dot.L 49bbc0754a Merge pull request #176 from jeak01/patch-4
Update readme-jp.md
2025-01-17 15:54:37 +08:00
Dot.L f21b061443 Merge pull request #177 from jeak01/patch-1
Update README.md
2025-01-17 15:54:20 +08:00
jeak 34446fae37 Update readme-jp.md 2025-01-17 14:59:10 +08:00
jeak d1aeb621d4 Update readme-zh-tw.md 2025-01-17 14:58:46 +08:00
jeak 2f81e087e7 Update readme-zh-cn.md 2025-01-17 14:58:19 +08:00
jeak fe96afc8c3 Update README.md 2025-01-17 14:57:31 +08:00
Dot.L 9236993c22 Merge pull request #173 from APIParkLab/feature/ai-balance
fix: Nsq returns no error directly after parsing JSON exceptionNsq re…
2025-01-17 11:35:43 +08:00
Liujian ad2d62d13b fix: Nsq returns no error directly after parsing JSON exceptionNsq returns no error directly after parsing JSON exception 2025-01-17 11:34:34 +08:00
Dot.L 8f5833ca15 Merge pull request #172 from APIParkLab/feature/ai-balance
fix: ai event handler read event error
2025-01-17 10:42:14 +08:00
Liujian 1adf8c890f fix: ai event handler read event error 2025-01-17 10:38:35 +08:00
Dot.L 416c2a56fb Merge pull request #170 from APIParkLab/feature/ai-balance
update init plugin config
2025-01-16 18:58:36 +08:00
Liujian 1140e43d67 update init plugin config 2025-01-16 18:53:58 +08:00
Dot.L ab4faa36da Merge pull request #167 from APIParkLab/feature/ai-balance
Feature/ai balance
2025-01-16 16:37:41 +08:00
Liujian 38ca9815ba update provider status default value 2025-01-16 16:36:25 +08:00
Liujian 125965dabd update build script 2025-01-16 16:36:06 +08:00
刘健 ce4369976c Merge branch 'feature/merge' into 'main'
fix: login page redirect multiple times (#166)

See merge request apipark/APIPark!158
2025-01-16 14:57:39 +08:00
刘健 dc340fc766 Merge branch 'feature/ai-balance' into 'main'
Feature/1.4 (#154)

See merge request apipark/APIPark!157
2025-01-15 16:04:24 +08:00
ScarChin c28e3ec5c2 fix: 1.3-beta版本,超级管理员(admin)账户无法修改分类和添加子分类,页面显示无权限操作 (#164) 2025-01-14 17:52:07 +08:00
ScarChin 6fe7cf18bd fix: login page redirect multiple times (#166)
* fix: System Settings - General After changing the interface language, the internal pages do not automatically follow the language switch

* fix: login page language error
2025-01-13 18:33:55 +08:00
Dot.L 5af9577d31 Merge pull request #165 from APIParkLab/feature/ai-balance
update docker run script
2025-01-13 11:25:50 +08:00
Liujian c03c37420d update docker run script 2025-01-13 11:24:29 +08:00
Dot.L b818c0feac Merge pull request #162 from APIParkLab/feature/ai-balance
Feature/ai balance
2025-01-08 11:26:18 +08:00
Liujian bcb3003784 Merge branch 'main-github-pro' into feature/ai-balance
# Conflicts:
#	frontend/packages/core/src/pages/aiApis/aiApisLayout.tsx
#	frontend/packages/core/src/pages/aiSetting/AIFlowChart.tsx
#	frontend/packages/core/src/pages/aiSetting/components/ModelCardNode.tsx
2025-01-08 11:25:55 +08:00
Liujian ecd033ffd9 Merge remote-tracking branch 'github-pro/main' into main-github-pro
# Conflicts:
#	frontend/packages/common/src/components/aoplatform/LanguageSetting.tsx
#	frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx
#	frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx
#	frontend/packages/common/src/components/aoplatform/prompt-editor/PromptEditorResizable.tsx
#	frontend/packages/common/src/const/permissions.ts
#	frontend/packages/common/src/contexts/GlobalStateContext.tsx
#	frontend/packages/common/src/hooks/pluginLoader.ts
#	frontend/packages/common/src/utils/systemRunning.ts
#	frontend/packages/core/src/components/AIProviderSelect/index.tsx
#	frontend/packages/core/src/const/const.tsx
#	frontend/packages/core/src/const/system/const.tsx
#	frontend/packages/core/src/pages/aiApis/index.tsx
#	frontend/packages/core/src/pages/aiSetting/AIFlowChart.tsx
#	frontend/packages/core/src/pages/aiSetting/AiSettingList.tsx
#	frontend/packages/core/src/pages/aiSetting/AiSettingModal.tsx
#	frontend/packages/core/src/pages/aiSetting/components/CustomEdge.tsx
#	frontend/packages/core/src/pages/aiSetting/components/KeyStatusNode.tsx
#	frontend/packages/core/src/pages/aiSetting/components/ModelCardNode.tsx
#	frontend/packages/core/src/pages/aiSetting/components/ServiceCardNode.tsx
#	frontend/packages/core/src/pages/aiSetting/constants.ts
#	frontend/packages/core/src/pages/aiSetting/styles.css
#	frontend/packages/core/src/pages/aiSetting/types.ts
#	frontend/packages/core/src/pages/keySettings/components/ApiKeyContent.tsx
#	frontend/packages/core/src/pages/keySettings/components/StatusFilter.tsx
#	frontend/packages/core/src/pages/keySettings/index.tsx
#	frontend/packages/dashboard/src/component/MonitorApiPage.tsx
2025-01-08 11:20:57 +08:00
Liujian abadeef7d2 ignore config.yaml 2025-01-08 11:14:47 +08:00
Liujian 427212ed13 update package script 2025-01-08 11:11:41 +08:00
ScarChin 73435497a2 Feature/1.4 (#154)
- Load balancing (can connect to multiple accounts, automatically switch accounts when there is no quota)
- AI call log
- Model rate configuration
2025-01-07 18:47:08 +08:00
秦圆圆 067cb0f21d Merge branch 'feature/1.4' into 'main'
fix: In the supplier load chart, the mouse should not show a hand shape except...

See merge request apipark/APIPark!156
2025-01-07 18:41:58 +08:00
scarqin a087a535d2 fix: When the current supplier is abnormal, there should be a line on the model pointing to the next model, which means that the APIs on this link are associated with the next valid supplier. 2025-01-07 18:40:43 +08:00
scarqin 28745e81f8 fix: The language option is wrong. The current language is Chinese, but the option is displayed as English. 2025-01-07 18:14:25 +08:00
scarqin 29c74bbbe1 fix: jump link error 2025-01-07 17:56:16 +08:00
scarqin 35a7b13cde fix: When the current supplier is abnormal, there should be a line on the model pointing to the next model, which means that the APIs on this link are associated with the next valid supplier. 2025-01-07 17:54:53 +08:00
scarqin 62b77cc9fa fix: error line 2025-01-07 17:21:21 +08:00
Liujian 782314d5bd Merge remote-tracking branch 'github-pro/feature/1.4' into feature/ai-balance 2025-01-07 16:53:41 +08:00
刘健 33b5e02f23 Merge branch 'feature/ai-balance' into 'main'
fix: ai provider status error

See merge request apipark/APIPark!155
2025-01-07 16:50:27 +08:00
Liujian ec518c2ece fix: ai provider status error 2025-01-07 16:49:47 +08:00
scarqin b7b2dff26b fix: In the supplier load chart, the mouse should not show a hand shape except for the cards that can be dragged and sorted. 2025-01-07 16:17:50 +08:00
刘健 456ffb8586 Merge branch 'feature/ai-balance' into 'main'
AI API token quantity docking completed

See merge request apipark/APIPark!154
2025-01-07 12:49:51 +08:00
Liujian 1d09965d9a AI API token quantity docking completed 2025-01-07 12:49:23 +08:00
秦圆圆 82cff8f66e Merge branch 'feature/1.4' into 'main'
fix: After the release log configuration is successful, there is no success...

See merge request apipark/APIPark!153
2025-01-07 11:33:54 +08:00
scarqin b97acc7862 fix: Details has two slashes 2025-01-07 11:32:29 +08:00
scarqin 0adc963129 fix: After the release log configuration is successful, there is no success prompt and the list is not refreshed 2025-01-07 10:45:42 +08:00
scarqin 4be1387c62 fix: system logs lack of edit permission 2025-01-07 10:32:03 +08:00
scarqin f4e17f0de7 fix: i18n error 2025-01-07 10:04:18 +08:00
刘健 a03e1aa1f8 Merge branch 'feature/ai-balance' into 'main'
fix: ai key config error

See merge request apipark/APIPark!152
2025-01-07 09:23:34 +08:00
Liujian 7fcfbb2a54 fix: ai key config error 2025-01-07 01:42:36 +08:00
秦圆圆 59a4761424 Merge branch 'feature/1.4' into 'main'
Feature/1.4

See merge request apipark/APIPark!151
2025-01-06 19:45:37 +08:00
scarqin 6ceae331ce fix: AI API should remove prefix matching drop-down selection 2025-01-06 19:29:15 +08:00
scarqin 2a1f0175a9 fix: There is no slide rail, so the bottom part cannot be displayed. 2025-01-06 19:14:09 +08:00
scarqin e5fca5f545 fix: No refetching of lists after deleting keyword search 2025-01-06 17:53:30 +08:00
刘健 3f8ebc4a19 Merge branch 'feature/ai-balance' into 'main'
update ai key status to gateway

See merge request apipark/APIPark!150
2025-01-06 10:57:54 +08:00
Liujian ff99f55b0a update ai key status to gateway 2025-01-06 10:57:23 +08:00
刘健 d049658cdc Merge branch 'feature/ai-balance' into 'main'
fix: ai key sort

See merge request apipark/APIPark!149
2025-01-06 10:26:39 +08:00
Liujian e8103b0dbe fix: ai key sort 2025-01-06 10:22:01 +08:00
刘健 537ea1fd83 Merge branch 'feature/ai-balance' into 'main'
Feature/ai balance

See merge request apipark/APIPark!148
2025-01-06 10:02:19 +08:00
Liujian fd66b2b351 ai balance finish 2025-01-06 09:47:23 +08:00
Liujian ab6ffb74b7 Merge remote-tracking branch 'origin/main' into feature/ai-balance 2025-01-05 23:25:08 +08:00
Liujian 20fb2b3083 update ai key iml 2025-01-05 23:25:00 +08:00
lichunxian e9877bb52b Merge branch 'feature/1.4' into 'main'
feat: aiApi detail page

See merge request apipark/APIPark!147
2025-01-03 17:47:21 +08:00
ningyv 7debf34fb0 feat: aiApi detail page 2025-01-03 17:46:23 +08:00
ningyv 41afaf4f66 Merge branch 'feature/1.4' of http://gitlab.eolink.com/apipark/APIPark into feature/1.4 2025-01-03 17:33:17 +08:00
ningyv ee19c214e7 feat: aiApi detail page 2025-01-03 17:33:06 +08:00
秦圆圆 534ca2b042 Merge branch 'feature/1.4' into 'main'
fix: The load diagram moves as a whole to the left so that the main content is...

See merge request apipark/APIPark!146
2025-01-03 17:14:05 +08:00
scarqin ac5cbd2d22 fix: KEY pool adjustment order will fail 2025-01-03 17:13:40 +08:00
scarqin 17372cd0a4 fix: The bottom margin of the banner should be sufficient 2025-01-03 16:37:36 +08:00
scarqin 0bbeb481f4 fix: The load diagram moves as a whole to the left so that the main content is in the middle and the AI ​​Services icon is aligned to the left 2025-01-03 16:29:27 +08:00
秦圆圆 61c9709974 Merge branch 'feature/1.4' into 'main'
Feature/1.4

See merge request apipark/APIPark!144
2025-01-03 16:12:34 +08:00
Liujian d0364e3734 Merge remote-tracking branch 'origin/feature/1.4' into feature/ai-balance 2025-01-03 11:25:59 +08:00
刘健 5b5852e336 Merge branch 'feature/ai-balance' into 'main'
update ai api list

See merge request apipark/APIPark!145
2025-01-03 10:47:10 +08:00
Liujian 883aeebc8f update ai api list 2025-01-03 10:46:25 +08:00
scarqin c16e0edaf0 i18n 2025-01-03 09:42:17 +08:00
刘健 98bb6eaf2a Merge branch 'feature/ai-balance' into 'main'
update ai api list

See merge request apipark/APIPark!143
2025-01-03 09:33:46 +08:00
Liujian 36d8b96b61 update ai api list 2025-01-03 09:33:12 +08:00
scarqin 3bb3d6a6cd feat: navigate 2025-01-03 09:24:32 +08:00
scarqin 9971a86d5c chore: apis 2025-01-03 09:09:40 +08:00
scarqin 71ab2c8dea fix: api key timestamp error 2025-01-03 09:06:36 +08:00
秦圆圆 80561c8784 Merge branch 'feature/1.4' into 'main'
Feature/1.4

See merge request apipark/APIPark!138
2025-01-03 08:20:23 +08:00
scarqin 4be0b1b3b6 feat: api url 2025-01-02 10:07:54 +08:00
scarqin 48a32e8f6d fix: padding error 2025-01-02 09:45:32 +08:00
scarqin 9e6fe50aed fix: provider tips 2025-01-02 09:32:19 +08:00
scarqin fa4edcba93 fix: alert api list tips 2025-01-02 09:29:03 +08:00
scarqin b863e3892e feat: add banner 2025-01-02 08:21:33 +08:00
scarqin 0a57a7b7ee feat: apilist 2024-12-31 17:21:56 +08:00
scarqin e249b62d13 chore: change disable to disabled 2024-12-31 16:17:53 +08:00
刘健 5c015f275b Merge branch 'feature/ai-balance' into 'main'
update api disable to disabled

See merge request apipark/APIPark!142
2024-12-31 15:24:55 +08:00
Liujian 6faddc15e9 update api disable to disabled 2024-12-31 15:24:36 +08:00
scarqin 894cd21032 feat: ai column add disable 2024-12-31 15:17:36 +08:00
scarqin 7a1b56e202 feat: apikey 2024-12-31 15:07:43 +08:00
刘健 19911eb8c8 Merge branch 'feature/ai-balance' into 'main'
fix: provider status incorrect

See merge request apipark/APIPark!141
2024-12-31 14:50:41 +08:00
Liujian a307917b66 fix: provider status incorrect 2024-12-31 14:48:19 +08:00
scarqin cb5f45acc7 feat: stopaable tips 2024-12-31 14:24:15 +08:00
scarqin 0dbf9c907d feat: add llm status manage 2024-12-31 12:01:42 +08:00
scarqin 9fc8234eaf feat: add priority 2024-12-31 10:27:50 +08:00
刘健 61840de99f Merge branch 'feature/ai-balance' into 'main'
update go-common version

See merge request apipark/APIPark!140
2024-12-31 10:17:36 +08:00
Liujian 30da6e10a1 update go-common version 2024-12-31 10:16:44 +08:00
scarqin 4650edbd17 refacor: delete useless code 2024-12-30 17:03:36 +08:00
scarqin 7646e3d9a1 feat: update list after edit modal 2024-12-30 17:00:09 +08:00
scarqin c5198b198a feat: ai model 2024-12-30 15:59:43 +08:00
scarqin 87b70a3faf feat: ai model detail 2024-12-30 14:59:22 +08:00
刘健 1ef0c7bd14 Merge branch 'feature/ai-balance' into 'main'
update ai provider list key

See merge request apipark/APIPark!139
2024-12-30 13:50:18 +08:00
Liujian 02ee5b8c7e update ai provider list key 2024-12-30 13:49:59 +08:00
scarqin 5a2b509d68 feat: ai apis 2024-12-27 21:28:35 +08:00
刘健 11cbcd45bb Merge branch 'feature/ai-balance' into 'main'
Feature/ai balance

See merge request apipark/APIPark!137
2024-12-27 16:56:28 +08:00
Liujian e82d5be71d update simple/providers/configured api 2024-12-27 16:55:54 +08:00
scarqin 065d5ade3f feat: api tab 2024-12-27 09:56:15 +08:00
Liujian 464015bed6 Merge branch 'main-github-pro' into feature/ai-balance 2024-12-26 18:22:30 +08:00
Liujian 190323cf05 Merge remote-tracking branch 'origin/main' into main-github-pro 2024-12-26 18:21:30 +08:00
刘健 94654c753b Merge branch 'feature/ai-balance' into 'main'
Add filtering options to the list

See merge request apipark/APIPark!136
2024-12-26 18:07:17 +08:00
Liujian 8a589982d1 Add filtering options to the list 2024-12-26 18:06:54 +08:00
刘健 bd9325c66d Merge branch 'feature/ai-balance' into 'main'
Feature/ai balance

See merge request apipark/APIPark!135
2024-12-26 17:26:01 +08:00
Liujian 1bdd4720bb ai api list add filter condition 2024-12-26 17:25:36 +08:00
Liujian 55aec4cc8b Merge branch 'main-github-pro' into feature/ai-balance 2024-12-26 16:48:03 +08:00
Liujian 5ec294207d update service list api 2024-12-26 16:46:11 +08:00
scarqin 3b45a339d3 feat: ai model config 2024-12-26 16:05:56 +08:00
秦圆圆 0742c2be33 Merge branch 'feature/1.4' into 'main'
Feature/1.4

See merge request apipark/APIPark!134
2024-12-26 15:54:20 +08:00
scarqin e8730d6d18 feat: apikey 2024-12-26 15:52:43 +08:00
刘健 2bc3b72e15 Merge branch 'feature/ai-balance' into 'main'
update simple configured providers

See merge request apipark/APIPark!133
2024-12-26 15:41:24 +08:00
Liujian 56124fd90d update simple configured providers 2024-12-26 15:41:07 +08:00
scarqin 81ccba83c3 feat: add api key 2024-12-26 15:39:52 +08:00
刘健 5f64a3ae33 Merge branch 'feature/ai-balance' into 'main'
Feature/ai balance

See merge request apipark/APIPark!132
2024-12-26 15:10:24 +08:00
Liujian a80b1aed08 finish ai provider api 2024-12-26 15:09:44 +08:00
scarqin 3724045e37 feat: add key 2024-12-26 14:36:24 +08:00
scarqin a368af0598 feat: add modal 2024-12-26 14:20:06 +08:00
scarqin 8128a7acac feat: add api keys 2024-12-25 20:23:47 +08:00
scarqin 51910e6740 feat: support sort table 2024-12-25 17:53:15 +08:00
scarqin 8a2be8195a feat: delete apikey 2024-12-25 17:36:26 +08:00
scarqin ec2c418c4d fix: provider change 2024-12-25 17:15:42 +08:00
scarqin b89b9e4ebd feat: sort api 2024-12-25 17:08:26 +08:00
scarqin de008edc68 feat: pagination and search api 2024-12-25 16:51:41 +08:00
scarqin 129c7a15c7 feat: ai provider component 2024-12-25 15:41:20 +08:00
scarqin 29325aa341 style: apikey layout 2024-12-25 15:05:19 +08:00
scarqin a864e67a6c feat: encapsulation select options 2024-12-25 14:43:29 +08:00
scarqin 190aff51b6 style: remove keys card border 2024-12-25 14:12:43 +08:00
scarqin ab398032df fix: some type error 2024-12-25 14:08:22 +08:00
scarqin 8f1d127e96 feat: remove attribute 2024-12-25 13:52:00 +08:00
scarqin 01ea108ab9 feat: add token 2024-12-25 12:01:19 +08:00
Dot.L 2b10162d5e Merge pull request #159 from APIParkLab/feature/ai-balance
add get simple ai provider api
2024-12-25 12:01:03 +08:00
Liujian 4b1e1a22db add get simple ai provider api 2024-12-25 11:59:34 +08:00
scarqin f500adb158 feat: apikey get 2024-12-25 10:38:28 +08:00
scarqin 5ec7e680e6 feat: template modal 2024-12-25 10:14:07 +08:00
Dot.L 7277389c9a Merge pull request #158 from APIParkLab/feature/ai-balance
Feature/ai balance
2024-12-24 18:23:14 +08:00
刘健 4c7a2737d0 Merge branch 'feature/ai-balance' into 'main'
update go.mod

See merge request apipark/APIPark!131
2024-12-24 18:20:44 +08:00
Liujian cd4594f3ae update go.mod 2024-12-24 18:20:09 +08:00
scarqin 4733b3c919 feat: apikeys 2024-12-24 18:14:50 +08:00
刘健 aa78945ed8 Merge branch 'feature/ai-balance' into 'main'
finish ai apis

See merge request apipark/APIPark!130
2024-12-24 18:01:41 +08:00
Liujian 7ac8beb161 finish ai apis 2024-12-24 18:00:46 +08:00
scarqin 0f30d85ae8 feat: add route apikey and ai api 2024-12-24 17:29:31 +08:00
scarqin f8a976290c feat: flow chart 2024-12-24 16:36:23 +08:00
scarqin cd73e76712 feat: use translateExtent to limit scroll area 2024-12-24 15:41:14 +08:00
scarqin 4616470493 disable dragger 2024-12-24 15:36:55 +08:00
scarqin ac6afad280 feat: flow chart 2024-12-24 15:31:02 +08:00
scarqin dde76789a1 feat: remove fit view 2024-12-24 15:14:52 +08:00
scarqin b8c4482dad feat: custom edge 2024-12-24 15:06:48 +08:00
scarqin fb90189f3c feat: keycard change place 2024-12-24 14:37:45 +08:00
scarqin ac56f9f7a6 fet 2024-12-24 14:34:16 +08:00
scarqin 9fd9979ce3 feat: model 2024-12-24 14:28:10 +08:00
scarqin a1ae7ca119 feat: fetch data from api 2024-12-24 13:51:08 +08:00
scarqin 08f29b7067 feat: change component place 2024-12-24 11:58:51 +08:00
scarqin 503367b8e2 feat: dmo 2024-12-24 11:35:31 +08:00
scarqin 36aac1d8c8 refactor: encapsulation constant 2024-12-24 10:37:10 +08:00
scarqin 42229fe6bc feat: draggable button 2024-12-23 18:36:12 +08:00
scarqin 0ae824ec35 feat: draggable 2024-12-23 18:17:51 +08:00
scarqin 0a1d8245ee feat: draggable 2024-12-23 18:16:17 +08:00
scarqin 95c2288890 feat: add multiple data 2024-12-23 17:56:22 +08:00
scarqin 7ac97ca739 chore: 文件拆分 2024-12-23 17:45:50 +08:00
scarqin 14548e4bc5 feat: change type status 2024-12-23 17:42:55 +08:00
scarqin 72c5e7c35a feat: change group title 2024-12-23 17:31:58 +08:00
scarqin 4fbc4fccdc chore: card status 2024-12-23 17:14:23 +08:00
scarqin a4de291155 feat: add handler 2024-12-23 16:11:12 +08:00
Dot.L 67ea0a5c24 Merge pull request #156 from APIParkLab/feature/ai-balance
update go-common dependence in go.mod
2024-12-23 16:05:41 +08:00
刘健 d5eeab16b6 Merge branch 'feature/ai-balance' into 'main'
update go-common dependence in go.mod

See merge request apipark/APIPark!129
2024-12-23 15:58:43 +08:00
Liujian 0be2248f41 update go-common dependence in go.mod 2024-12-23 15:58:24 +08:00
刘健 7b7f968ae2 Merge branch 'feature/ai-balance' into 'main'
Feature/ai balance

See merge request apipark/APIPark!128
2024-12-23 15:51:09 +08:00
Dot.L ca1e1abeb8 Merge pull request #155 from APIParkLab/feature/ai-balance
finish ai key api
2024-12-23 15:49:27 +08:00
Liujian 00451ae78f finish ai key api 2024-12-23 15:48:19 +08:00
scarqin 04e9fc7315 feat: block 2024-12-23 14:09:53 +08:00
scarqin 6dbef3f743 feat: basic card component 2024-12-23 14:00:24 +08:00
scarqin 42cc086bd0 chore: add global rule 2024-12-23 11:36:25 +08:00
scarqin 4c40b04c8e chore: add global_rules.md 2024-12-23 10:16:59 +08:00
scarqin 6126ba8678 feat: chart 2024-12-20 20:26:18 +08:00
scarqin 51cc7692cb chore: refactor format eslint and prettier code 2024-12-19 16:17:50 +08:00
scarqin 414f8c64c0 chore: add remove unused 2024-12-19 15:49:20 +08:00
scarqin 60a735b726 change 2024-12-18 17:37:20 +08:00
scarqin d6f6642271 test 2024-12-18 17:33:39 +08:00
scarqin be3880a05d test 2024-12-18 17:33:08 +08:00
scarqin f40f1a4304 test 2024-12-18 17:32:23 +08:00
scarqin d8bb1d649c test 2024-12-18 17:31:03 +08:00
scarqin 1bf43cf137 test 2024-12-18 17:30:16 +08:00
scarqin 86fa87bb7a test 2024-12-18 17:28:17 +08:00
scarqin 5c89b5a7a2 test 2024-12-18 17:27:49 +08:00
scarqin 9a8b4cacff test 2024-12-18 17:25:54 +08:00
scarqin da6a54aa74 test 2024-12-18 17:24:02 +08:00
scarqin 478d65a649 test 2024-12-18 17:20:47 +08:00
scarqin abd391266a test 2024-12-18 17:19:10 +08:00
scarqin f282e0e69b test 2024-12-18 17:13:29 +08:00
scarqin f283cbbcca feat: push 2024-12-18 17:11:43 +08:00
scarqin 89a392b749 fix: login page refresh multiple times 2024-12-18 15:48:51 +08:00
Dot.L 2a3e016dc2 Merge pull request #149 from APIParkLab/feature/aibug-fix
add default router when create new rest service
2024-12-16 14:43:26 +08:00
刘健 5d56177bc7 Update .gitlab-ci.yml file 2024-12-16 14:34:33 +08:00
刘健 c043dbf8e5 Merge branch 'feature/aibug-fix' into 'main'
add default router when create new rest service

See merge request apipark/APIPark!127
2024-12-16 14:33:14 +08:00
Liujian af0ec4e3da add default router when create new rest service 2024-12-16 14:31:52 +08:00
刘健 618bc05a8b Merge branch 'feature/aibug-fix' into 'main'
chore: update index.tsx

See merge request apipark/APIPark!126
2024-12-13 20:06:43 +08:00
ningyv b86f0a874f Merge pull request #147 from APIParkLab/fix/fixbug-cx
fix: consumer permission
2024-12-13 20:02:45 +08:00
lichunxian c473c72b84 Merge branch 'fix/fixbug-cx' into 'main'
fix: consumer permission

See merge request apipark/APIPark!125
2024-12-13 20:01:59 +08:00
ningyv 87405dc9ea fix: consumer permission 2024-12-13 20:00:38 +08:00
Dot.L b01993fe28 Merge pull request #146 from APIParkLab/feature/aibug-fix
fix aksk bug
2024-12-13 19:41:10 +08:00
Liujian 24c7cd0c8d fix aksk bug 2024-12-13 18:52:21 +08:00
Dot.L 2739f84fea Merge pull request #145 from APIParkLab/feature/aibug-fix
fix ai provider upstream bug
2024-12-10 17:26:47 +08:00
Liujian 98304b8816 fix ai provider upstream bug 2024-12-10 17:24:51 +08:00
ningyv 9a29cef69a Merge branch 'main' of github.com:APIParkLab/APIPark 2024-12-10 15:34:44 +08:00
lichunxian ff9738f5cc Merge branch 'fix/certificatePermission' into 'main'
fix: table-permission

See merge request apipark/APIPark!124
2024-12-10 15:17:11 +08:00
ningyv a657908c20 fix: table-permission 2024-12-10 15:16:19 +08:00
Dot.L f59128f25d Merge pull request #143 from eltociear/patch-1
chore: update index.tsx
2024-12-09 21:48:14 +08:00
Liujian c08a617c65 Merge remote-tracking branch 'origin/main' into main-github-pro 2024-12-09 21:42:09 +08:00
Liujian 5017fce70c update init log 2024-12-09 21:32:57 +08:00
lichunxian 304cd9ddfc Merge branch 'fix/certificatePermission' into 'main'
fix: implement certificate popup permission handling

See merge request apipark/APIPark!123
2024-12-09 15:22:29 +08:00
ningyv e7eec6e160 fix: implement certificate popup permission handling 2024-12-09 15:18:59 +08:00
Liujian 3dd44c97e9 Automatically publish policies and logs during cluster initialization 2024-12-09 00:43:05 +08:00
Liujian bc00f2d577 update loki publish 2024-12-09 00:17:50 +08:00
Liujian d80bfe61df update .gitignore 2024-12-06 18:48:00 +08:00
lichunxian de3ac01b98 Merge branch 'feature/dataLogPage' into 'main'
fix: improve column width adjustment and optimize date picker performance

See merge request apipark/APIPark!122
2024-12-06 18:03:16 +08:00
ningyv 5c488fe4ea fix: improve column width adjustment and optimize date picker performance 2024-12-06 18:02:44 +08:00
刘健 1d7874fad6 Merge branch 'feature/data-mask' into 'main'
update publish problem

See merge request apipark/APIPark!121
2024-12-06 16:13:23 +08:00
Liujian c4f337f2ae update publish problem 2024-12-06 16:12:49 +08:00
lichunxian 09d70866e3 Merge branch 'feature/dataLogPage' into 'main'
Feature/data log page

See merge request apipark/APIPark!120
2024-12-06 15:25:51 +08:00
ningyv 5052720efb fix: refine time range calculation with second-level precision 2024-12-06 15:24:06 +08:00
ningyv 73f53a913c fix: resolve subscriber permissions 2024-12-06 14:22:59 +08:00
lichunxian 13ce234ac8 Merge branch 'feature/dataLogPage' into 'main'
feat: integrate global policy API and implement data log page

See merge request apipark/APIPark!119
2024-12-06 11:51:13 +08:00
ningyv a38ee5e16c feat: integrate global policy API and implement data log page 2024-12-06 11:50:32 +08:00
刘健 0a30ea157b Merge branch 'feature/data-mask' into 'main'
update service publish

See merge request apipark/APIPark!118
2024-12-06 11:32:15 +08:00
Liujian 658f0cbea5 update service publishing difference comparison field 2024-12-06 11:31:58 +08:00
Liujian 51378e922f update service publish 2024-12-06 11:02:40 +08:00
刘健 295aee494e Merge branch 'feature/data-mask' into 'main'
add service strategy log

See merge request apipark/APIPark!117
2024-12-06 10:49:21 +08:00
Liujian 72350f2fae add service strategy log 2024-12-06 10:47:47 +08:00
刘健 49bbadd721 Merge branch 'feature/data-mask' into 'main'
update service publish

See merge request apipark/APIPark!116
2024-12-06 10:40:20 +08:00
Liujian 220e062d1e update service publish 2024-12-06 10:39:59 +08:00
lichunxian b0ac98a5a9 Merge branch 'feature/dataLogPage' into 'main'
feat: integrate global policy API and implement data log page

See merge request apipark/APIPark!115
2024-12-05 18:53:51 +08:00
ningyv 84decf1310 feat: integrate global policy API and implement data log page 2024-12-05 18:53:11 +08:00
刘健 7d66f2628a Merge branch 'feature/data-mask' into 'main'
fix log bug:Keyword query failed

See merge request apipark/APIPark!114
2024-12-05 18:17:49 +08:00
Liujian 285e0c7a81 fix log bug:Keyword query failed 2024-12-05 18:17:29 +08:00
刘健 e0153d6c11 Merge branch 'feature/data-mask' into 'main'
fix logs bug

See merge request apipark/APIPark!113
2024-12-05 17:21:46 +08:00
Liujian c241a0ba8f fix logs bug 2024-12-05 17:20:11 +08:00
刘健 ca7c7efc9c Merge branch 'feature/data-mask' into 'main'
fix log bug

See merge request apipark/APIPark!112
2024-12-05 17:15:04 +08:00
Liujian 6a29b9492c fix log bug 2024-12-05 17:14:26 +08:00
刘健 599040d64a Merge branch 'feature/data-mask' into 'main'
update strategy publish bug

See merge request apipark/APIPark!111
2024-12-05 15:44:22 +08:00
Liujian ec6c2303be update strategy publish bug 2024-12-05 15:43:42 +08:00
刘健 f4419d2357 Merge branch 'feature/data-mask' into 'main'
update log label

See merge request apipark/APIPark!109
2024-12-05 15:06:28 +08:00
Liujian c75df95cce update log label 2024-12-05 15:04:43 +08:00
刘健 b2e8c75572 Merge branch 'feature/data-mask' into 'main'
Feature/data mask

See merge request apipark/APIPark!108
2024-12-05 14:50:19 +08:00
Liujian 6bf3737c24 Merge remote-tracking branch 'origin/main' into feature/data-mask
# Conflicts:
#	frontend/packages/core/src/pages/policy/dataMasking/DataMasking.tsx
2024-12-05 14:50:00 +08:00
Liujian 075c1f234a update eosc version 2024-12-05 14:43:24 +08:00
Liujian fd21273251 data mask log commit 2024-12-05 14:39:57 +08:00
Ikko Eltociear Ashimine bb822801fb chore: update index.tsx
protocal -> protocol
2024-12-04 15:54:09 +09:00
Liujian 8d1fc7faa5 Merge remote-tracking branch 'github-pro/feature/v1.3/mj' into feature/data-mask 2024-12-03 16:07:13 +08:00
ningyv 94728e7b6a Merge branch 'feature/v1.3/mj' of github.com:APIParkLab/APIPark into feature/v1.3/mj 2024-11-29 18:39:20 +08:00
ningyv e031f80b2e feature: dataMask logs dialog 2024-11-29 18:39:13 +08:00
lichunxian 6111dc69ad Merge branch 'fix/copyIssue' into 'main'
Fix/copy issue

See merge request apipark/APIPark!107
2024-11-29 10:39:28 +08:00
杨梦洁 49188b291b Merge branch 'feature/v1.3/mj' into 'main'
fix: Dashboard Table Height

See merge request apipark/APIPark!106
2024-11-29 10:36:45 +08:00
杨梦洁 ba8632aa22 fix: Dashboard Table Height 2024-11-29 10:35:32 +08:00
ningyv 726bbe4f6f fix: Fix the issue where copying the URL doesn't work 2024-11-29 10:22:40 +08:00
ningyv f1e1d94380 fix: Fixed side navigation disappearing 2024-11-29 10:08:06 +08:00
lichunxian 607970a1ed Merge branch 'fix/fix-table' into 'main'
Fix/fix table

See merge request apipark/APIPark!105
2024-11-29 09:55:26 +08:00
ningyv aef65d9d05 Merge branch 'main' of http://gitlab.eolink.com/apipark/APIPark 2024-11-29 09:45:55 +08:00
ningyv 4d26fe1edd Fix Set the header width 2024-11-29 09:41:50 +08:00
ningyv e0bc987c25 Fix icon issues 2024-11-28 19:15:02 +08:00
刘健 a07c5c8d9d Merge branch 'feature/data-mask' into 'main'
update transaction

See merge request apipark/APIPark!104
2024-11-28 18:41:56 +08:00
Liujian 777256bf30 update transaction 2024-11-28 18:40:00 +08:00
Maggie 60de3b3250 Merge pull request #141 from APIParkLab/feature/v1.3/mj
fix: get service remote option
2024-11-28 18:39:17 +08:00
杨梦洁 074919b70c Merge branch 'feature/v1.3/mj' into 'main'
fix: get service remote option

See merge request apipark/APIPark!103
2024-11-28 18:38:51 +08:00
杨梦洁 f90e9b4eba fix: get service remote option 2024-11-28 18:38:12 +08:00
刘健 6789b1c327 Merge branch 'feature/data-mask' into 'main'
fix strategy bug

See merge request apipark/APIPark!102
2024-11-28 18:35:20 +08:00
Liujian f46fe0ec4c fix strategy bug 2024-11-28 18:34:15 +08:00
Maggie f88aea2d32 Merge pull request #140 from APIParkLab/feature/v1.3/mj
fix: service data-masking layout
2024-11-28 18:24:44 +08:00
杨梦洁 29f534501c Merge branch 'feature/v1.3/mj' into 'main'
fix: service data-masking layout

See merge request apipark/APIPark!101
2024-11-28 18:22:44 +08:00
刘健 7b18e06006 Merge branch 'feature/data-mask' into 'main'
Feature/data mask

See merge request apipark/APIPark!100
2024-11-28 18:19:38 +08:00
Liujian 50567665ab openapi取消登录校验 2024-11-28 18:19:08 +08:00
杨梦洁 2135205f40 fix: service data-masking layout 2024-11-28 18:14:02 +08:00
Liujian 51241108fa Merge remote-tracking branch 'github-pro/main' into feature/data-mask 2024-11-28 17:35:53 +08:00
Maggie 05c5b2968d Merge pull request #139 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-28 17:01:32 +08:00
杨梦洁 00e6d1aa7a Merge branch 'feature/v1.3/mj' into 'main'
fix: Modify Context Arct

See merge request apipark/APIPark!99
2024-11-28 17:01:11 +08:00
杨梦洁 eb4fb872a3 fix: Modify Context Arct 2024-11-28 16:59:51 +08:00
杨梦洁 9e7825aee8 Merge branch 'feature/v1.3/mj' into 'main'
fix: add translation

See merge request apipark/APIPark!98
2024-11-28 13:49:43 +08:00
杨梦洁 f8b75c7237 fix: add translation 2024-11-28 13:47:31 +08:00
刘健 843b2f32e0 Merge branch 'feature/data-mask' into 'main'
add publish tip

See merge request apipark/APIPark!97
2024-11-28 11:17:36 +08:00
Liujian 4db7154130 add publish tip 2024-11-28 11:17:02 +08:00
刘健 c7190a0d07 Merge branch 'feature/data-mask' into 'main'
fix rest service publish

See merge request apipark/APIPark!95
2024-11-28 10:49:16 +08:00
Maggie 8bd273c48a Merge pull request #137 from APIParkLab/feature/v1.3/mj
fix: role list scroll bug and add translation
2024-11-28 10:47:44 +08:00
杨梦洁 9f0e9a5525 Merge branch 'feature/v1.3/mj' into 'main'
fix: role list scroll bug and add translation

See merge request apipark/APIPark!96
2024-11-28 10:41:45 +08:00
杨梦洁 1486c56249 fix: role list scroll bug and add translation 2024-11-28 10:40:43 +08:00
Liujian 53d895f046 fix rest service publish 2024-11-27 20:18:23 +08:00
刘健 d6e0ea049a Merge branch 'feature/data-mask' into 'main'
finish service publish

See merge request apipark/APIPark!94
2024-11-27 19:47:16 +08:00
Liujian 58f192b6e9 finish service publish 2024-11-27 19:46:52 +08:00
Maggie dba4bae830 Merge pull request #136 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-27 19:22:06 +08:00
杨梦洁 8df6362ac0 Merge branch 'feature/v1.3/mj' into 'main'
fix: data-masking and integration bugs

See merge request apipark/APIPark!93
2024-11-27 19:21:58 +08:00
杨梦洁 2a84bdcf9f fix: data-masking and integration bugs 2024-11-27 19:20:47 +08:00
刘健 158f94f069 Merge branch 'feature/data-mask' into 'main'
Feature/data mask

See merge request apipark/APIPark!92
2024-11-27 19:05:28 +08:00
Liujian 3fde0fa7a3 update service publish rule 2024-11-27 19:05:11 +08:00
Liujian 1ac9a0e154 Merge remote-tracking branch 'origin/main' into feature/data-mask 2024-11-27 18:30:46 +08:00
杨梦洁 8c816edab4 Merge branch 'feature/v1.3/mj' into 'main'
fix: data-masking bugs

See merge request apipark/APIPark!91
2024-11-27 18:22:41 +08:00
杨梦洁 858b8a25bb fix: data-masking bugs 2024-11-27 18:21:43 +08:00
刘健 9dfac9c5f5 Merge branch 'feature/data-mask' into 'main'
add open api swagger

See merge request apipark/APIPark!90
2024-11-27 13:52:15 +08:00
Liujian 0a828e843d add open api swagger 2024-11-27 13:51:55 +08:00
刘健 16414f6a4a Merge branch 'feature/data-mask' into 'main'
add strategy permit

See merge request apipark/APIPark!89
2024-11-27 11:47:22 +08:00
Liujian 4e902e891e add strategy permit 2024-11-27 11:46:56 +08:00
刘健 5cff8b3bed Merge branch 'feature/data-mask' into 'main'
add api: /simple/service/apis

See merge request apipark/APIPark!88
2024-11-27 00:35:11 +08:00
Liujian b5671d14a4 add api: /simple/service/apis 2024-11-27 00:34:24 +08:00
刘健 be202fd53b Merge branch 'feature/data-mask' into 'main'
Feature/data mask

See merge request apipark/APIPark!87
2024-11-26 23:50:14 +08:00
Liujian 601663b658 system setting add site_prefix 2024-11-26 23:49:44 +08:00
Liujian cb63931f30 finish data mask strategy 2024-11-26 23:44:00 +08:00
Liujian 651a1de601 Merge remote-tracking branch 'github-pro/main' into feature/data-mask 2024-11-25 10:35:21 +08:00
杨梦洁 841adc05cd Merge branch 'feature/v1.3/mj' into 'main'
fix: Change Dashboard Fields

See merge request apipark/APIPark!86
2024-11-21 18:38:13 +08:00
杨梦洁 e78f1b804f fix: Change Dashboard Fields 2024-11-21 18:37:39 +08:00
Liujian 8d94a7e872 Merge remote-tracking branch 'origin/feature/v1.3/mj' into feature/data-mask 2024-11-21 17:36:57 +08:00
Liujian ce53bb2d47 Initial submission of data desensitization strategy backend 2024-11-21 17:36:13 +08:00
Maggie 09a74768d5 Merge pull request #135 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-21 17:05:48 +08:00
杨梦洁 e4f89f7084 Merge branch 'feature/v1.3/mj' into 'main'
fix: Change Vite Config

See merge request apipark/APIPark!85
2024-11-21 16:43:53 +08:00
杨梦洁 a6df9e1f04 fix: Change Vite Config 2024-11-21 16:42:32 +08:00
杨梦洁 0e885d21f9 Merge branch 'feature/v1.3/mj' into 'main'
fix: Change File Name

See merge request apipark/APIPark!84
2024-11-21 16:34:31 +08:00
杨梦洁 387eccb44a fix: Change File Name 2024-11-21 16:32:07 +08:00
杨梦洁 7086073227 Merge branch 'feature/v1.3/mj' into 'main'
Feature/v1.3/mj

See merge request apipark/APIPark!83
2024-11-21 16:26:59 +08:00
杨梦洁 9006a9719e fix: Change File Name 2024-11-21 16:25:18 +08:00
杨梦洁 9e554ca0af fix: Change file name 2024-11-21 16:20:52 +08:00
杨梦洁 6899084f06 Merge branch 'main' into feature/v1.3/mj 2024-11-21 16:12:16 +08:00
杨梦洁 4396902982 Merge branch 'feature/v1.3/mj' into 'main'
Feature/v1.3/mj

See merge request apipark/APIPark!82
2024-11-21 16:11:42 +08:00
杨梦洁 73dc9c3439 feat: Complete static pages for Phase 1 of V1.3 2024-11-21 16:08:08 +08:00
Liujian 3c59985734 add gitlab-ci 2024-11-15 14:35:27 +08:00
Liujian 13a23a9753 Merge remote-tracking branch 'github-pro/main' 2024-11-15 14:21:23 +08:00
Dot.L 3c543d686a Merge pull request #134 from PeterDaveHelloKitchen/zh-TW
Improve zh-TW Traditional Chinese locale
2024-11-15 14:19:39 +08:00
杨梦洁 2bd0bb68a1 feat: Merge MF with data-masking list 2024-11-15 13:42:30 +08:00
lcx 9d9dbd0048 feat: Global/Service Policy Development, Add Service Details Integration Tab 2024-11-15 10:44:16 +08:00
杨梦洁 a1dcdd49fb feat: plugin system 2024-11-14 19:09:46 +08:00
Peter Dave Hello 880e97a922 Improve zh-TW Traditional Chinese locale 2024-11-14 05:49:34 +08:00
maggieyyy 9ba1537f18 fix: Move plugin code to common 2024-11-06 14:26:38 +08:00
maggieyyy c0d167a2b0 Merge branch 'main' into feature/mf 2024-11-06 11:33:21 +08:00
maggieyyy 3931f9c679 feat: plugin system 2024-11-05 16:20:40 +08:00
Dot.L 3e4d2b069a Merge pull request #130 from APIParkLab/feature/permit
Feature/permit
2024-11-04 11:06:03 +08:00
Liujian d679f69386 Merge branch 'main-github' into feature/permit
# Conflicts:
#	go.mod
2024-11-04 11:05:30 +08:00
Liujian 193276a0b2 update go.mod 2024-11-04 11:03:40 +08:00
Liujian 1e308eea98 Merge remote-tracking branch 'origin/main' into main-github 2024-11-04 11:00:05 +08:00
Liujian cc9ffdd182 fix service info no prefix 2024-11-04 10:59:13 +08:00
Liujian 1e4a8afc11 Merge remote-tracking branch 'origin/main' into main-github 2024-11-04 10:49:05 +08:00
杨梦洁 b6dee4671a Merge branch 'feature/v1.2' into 'main'
fix: Modify service inside access

See merge request apipark/APIPark!81
2024-11-04 10:46:21 +08:00
maggieyyy 98756d4c7f fix: Modify service inside access 2024-11-04 10:44:30 +08:00
Liujian 16c6535baf Merge remote-tracking branch 'github-pro/main' into main-github 2024-11-01 19:03:17 +08:00
Liujian fe2c6dafcd update .gitignore 2024-11-01 19:01:50 +08:00
刘健 1c531fb659 Merge branch 'feature/permit' into 'main'
Feature/permit

See merge request apipark/APIPark!80
2024-11-01 18:53:22 +08:00
Liujian 2ece064216 update ai permit 2024-11-01 18:52:50 +08:00
杨梦洁 fe74e18ea3 Merge branch 'feature/v1.2' into 'main'
fix: Modify link access

See merge request apipark/APIPark!79
2024-11-01 18:42:40 +08:00
Maggie fa714f7176 Merge pull request #129 from APIParkLab/feature/v1.2
fix: Modify link access
2024-11-01 18:42:26 +08:00
maggieyyy 7a057bda13 fix: Modify link access 2024-11-01 18:41:16 +08:00
maggieyyy 7348828cc3 fix: Modify execute list 2024-11-01 18:17:16 +08:00
Liujian 74ef7b58fb Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 18:05:14 +08:00
Liujian 3fc784ec9d Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 17:59:30 +08:00
Maggie 52292aefed Merge pull request #128 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 16:45:24 +08:00
杨梦洁 ba0088ed73 Merge branch 'feature/v1.2' into 'main'
fix: Modify consumer list reload and subscriber option

See merge request apipark/APIPark!78
2024-11-01 16:44:48 +08:00
maggieyyy 452e64c919 fix: Modify consumer list reload and subscriber option 2024-11-01 16:42:34 +08:00
Liujian ad7df9a6ef Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 16:19:35 +08:00
Liujian abb55346f9 update subscribe permit 2024-11-01 16:19:25 +08:00
杨梦洁 b16ed52378 Merge branch 'feature/v1.2' into 'main'
fix: Add team selector to consumer

See merge request apipark/APIPark!77
2024-11-01 15:49:53 +08:00
maggieyyy be8d347b0c fix: Add team selector to consumer 2024-11-01 15:48:51 +08:00
Dot.L 0146794b74 Update readme-zh-tw.md 2024-11-01 15:26:33 +08:00
Dot.L 996319a9cb Update readme-zh-cn.md 2024-11-01 15:26:15 +08:00
Dot.L a68b978044 Update readme-jp.md 2024-11-01 15:25:55 +08:00
Dot.L 556f8f1db0 Update README.md 2024-11-01 15:25:15 +08:00
Liujian bbee4b42ae Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 14:59:54 +08:00
杨梦洁 935227f104 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!76
2024-11-01 14:51:56 +08:00
Maggie 9e540a2128 Merge pull request #127 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 14:49:21 +08:00
maggieyyy 3c7dbd6b0b fix: consumer menu access bug 2024-11-01 14:48:18 +08:00
maggieyyy 4809299f86 fix: consumer menu access bug 2024-11-01 14:48:10 +08:00
杨梦洁 41ad5f5109 Merge branch 'feature/v1.2' into 'main'
fix: consumer menu access bug

See merge request apipark/APIPark!75
2024-11-01 14:46:49 +08:00
maggieyyy 104bd61576 fix: consumer menu access bug 2024-11-01 14:45:32 +08:00
Liujian e833233982 Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 14:26:37 +08:00
Maggie 8f83dc5fd4 Merge pull request #126 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 14:24:51 +08:00
杨梦洁 9f9d45e59c Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!74
2024-11-01 14:24:14 +08:00
maggieyyy bb27293aba fix: Modify department children type 2024-11-01 14:23:05 +08:00
maggieyyy 445b1277e9 fix: Modify department children type 2024-11-01 14:21:04 +08:00
刘健 3016f563bf Merge branch 'feature/permit' into 'main'
Feature/permit

See merge request apipark/APIPark!73
2024-11-01 14:19:48 +08:00
Liujian d1b9c29f0f update permit bug 2024-11-01 14:19:17 +08:00
maggieyyy 255c03a4a3 fix: Add empty to member transfer 2024-11-01 13:54:33 +08:00
maggieyyy b49c377b5f fix: plugin config 2024-11-01 13:39:52 +08:00
Liujian 45fcda443c Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 11:03:21 +08:00
Liujian 73daecf9b7 update permit 2024-11-01 11:01:45 +08:00
杨梦洁 e6f5e06ca5 Merge branch 'feature/v1.2' into 'main'
fix: Modify subscribe options

See merge request apipark/APIPark!72
2024-10-31 14:16:30 +08:00
maggieyyy 9677d1dba9 fix: Modify subscribe options 2024-10-31 14:14:44 +08:00
maggieyyy 134004e787 fix: Modify config 2024-10-31 13:59:06 +08:00
maggieyyy 6ea6d5e220 Merge branch 'main' into feature/mf 2024-10-31 09:27:08 +08:00
杨梦洁 003758e8cc Merge branch 'feature/v1.2' into 'main'
fix: delete log

See merge request apipark/APIPark!71
2024-10-31 09:25:28 +08:00
Maggie 3054a4ee49 Merge pull request #124 from APIParkLab/feature/v1.2
fix: delete log
2024-10-31 09:25:15 +08:00
maggieyyy 21aeadcc56 fix: delete log 2024-10-31 09:14:24 +08:00
Maggie d5b4374c0d Merge pull request #123 from APIParkLab/feature/v1.2
fix: Modify access
2024-10-30 18:40:10 +08:00
杨梦洁 39f6e449ed Merge branch 'feature/v1.2' into 'main'
fix: Modify access

See merge request apipark/APIPark!70
2024-10-30 18:39:59 +08:00
maggieyyy a87cbedd52 fix: Modify access 2024-10-30 18:38:39 +08:00
maggieyyy 90649ce00b fix: Modify mock plugin config 2024-10-30 17:52:41 +08:00
maggieyyy de3eb7f259 fix: Modify mock plugin config 2024-10-30 17:51:10 +08:00
maggieyyy 5298475de2 merge 2024-10-30 14:24:16 +08:00
Maggie 5f4c573282 Merge pull request #122 from APIParkLab/feature/v1.2
fix: Modify local path
2024-10-30 10:59:54 +08:00
Liujian 16084dabfe update ap-account version 2024-10-30 10:45:58 +08:00
杨梦洁 7c46243641 Merge branch 'feature/v1.2' into 'main'
fix: Modify local path

See merge request apipark/APIPark!69
2024-10-30 09:08:35 +08:00
maggieyyy 96f1913592 fix: Modify local path 2024-10-29 18:32:45 +08:00
杨梦洁 b92cad8d91 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!68
2024-10-29 17:46:36 +08:00
JackLiu f968dbe926 Merge pull request #121 from rolealiu/main
Update v1.2 translation
2024-10-29 17:29:21 +08:00
JackLiu c693a78cc1 Merge branch 'APIParkLab:main' into main 2024-10-29 17:28:51 +08:00
HaoZhen Liu 4aa1b6070b update v1.2 translation 2024-10-29 17:28:41 +08:00
Maggie 08724b1d53 Merge pull request #120 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-29 17:05:29 +08:00
杨梦洁 6c39c8c73b Merge branch 'feature/v1.2' into 'main'
fix: Add psw to account

See merge request apipark/APIPark!67
2024-10-29 16:47:44 +08:00
maggieyyy c3d35ac282 fix: Add psw to account 2024-10-29 16:44:31 +08:00
杨梦洁 37c6a562cd Merge branch 'feature/v1.2' into 'main'
fix: Modify member transfer icon and department

See merge request apipark/APIPark!66
2024-10-29 15:13:44 +08:00
maggieyyy 98ab569665 fix: Modify member transfer icon and department 2024-10-29 15:12:43 +08:00
Dot.L 318d4194c3 Merge pull request #119 from APIParkLab/feature/permission
update i18n
2024-10-29 14:20:19 +08:00
Liujian 4b50b27e14 update i18n 2024-10-29 14:19:36 +08:00
杨梦洁 af02d1727c Merge branch 'feature/v1.2' into 'main'
fix: update translation

See merge request apipark/APIPark!65
2024-10-29 13:54:49 +08:00
Maggie d2a39999be Merge pull request #118 from APIParkLab/feature/v1.2
fix: update translation
2024-10-29 13:54:42 +08:00
maggieyyy 3207a06e3f fix: update translation 2024-10-29 13:52:48 +08:00
Maggie 98457883cc Merge pull request #117 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-29 13:39:34 +08:00
杨梦洁 8e4ce11053 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!64
2024-10-29 13:39:06 +08:00
maggieyyy 6ae5b4992f fix: Modify guide link 2024-10-29 13:37:38 +08:00
maggieyyy 3c624d5039 fix: Modify member transfer 2024-10-29 11:58:09 +08:00
Maggie ddd2efe441 Merge pull request #116 from APIParkLab/feature/v1.2
fix: account translation
2024-10-29 09:21:36 +08:00
杨梦洁 7e419cb2de Merge branch 'feature/v1.2' into 'main'
fix: account translation

See merge request apipark/APIPark!62
2024-10-29 09:21:19 +08:00
maggieyyy 0093c7cfb7 fix: account translation 2024-10-29 09:19:35 +08:00
Dot.L 65c45d4c28 Merge pull request #114 from APIParkLab/feature/permission
update remark
2024-10-28 18:41:17 +08:00
Maggie 98fc9ea703 Merge pull request #113 from APIParkLab/feature/v1.2
fix: table fields
2024-10-28 18:40:48 +08:00
杨梦洁 dbeb08e5e1 Merge branch 'feature/v1.2' into 'main'
fix: table fields

See merge request apipark/APIPark!61
2024-10-28 18:40:09 +08:00
Liujian a48523c94b update remark 2024-10-28 18:39:55 +08:00
Dot.L 1335fffdaa Merge pull request #112 from APIParkLab/feature/permission
Feature/permission
2024-10-28 18:34:19 +08:00
Liujian 78f96dbcf9 Merge remote-tracking branch 'github-pro/main' into feature/permission
# Conflicts:
#	resources/access/access.yaml
2024-10-28 18:33:42 +08:00
maggieyyy 86afeea532 fix: table fields 2024-10-28 18:32:20 +08:00
Liujian 66559785ea update permission 2024-10-28 18:27:37 +08:00
Liujian f016fc4d06 update access 2024-10-28 16:48:18 +08:00
Maggie e0bddbc84a Merge pull request #111 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-28 16:22:58 +08:00
杨梦洁 3639dc93ef Merge branch 'feature/v1.2' into 'main'
fix: Modify access fields

See merge request apipark/APIPark!59
2024-10-28 16:17:09 +08:00
maggieyyy e1da4bd1f0 fix: Modify access fields 2024-10-28 16:15:38 +08:00
杨梦洁 99ef9118ee Merge branch 'feature/v1.2' into 'main'
fix: cosumer list bug

See merge request apipark/APIPark!58
2024-10-28 16:01:48 +08:00
maggieyyy 68b1c0eabb fix: cosumer list bug 2024-10-28 16:00:15 +08:00
杨梦洁 d73ca273e0 Merge branch 'feature/v1.2' into 'main'
fix: Consumer list bugs

See merge request apipark/APIPark!57
2024-10-28 15:45:11 +08:00
maggieyyy 9badf0e3e3 fix: Consumer list bugs 2024-10-28 15:44:10 +08:00
刘健 c720edcf41 Merge branch 'feature/translate' into 'main'
Feature/translate

See merge request apipark/APIPark!56
2024-10-28 15:15:00 +08:00
Dot.L 483c6a2758 Merge pull request #110 from APIParkLab/feature/translate
Feature/translate
2024-10-28 15:07:35 +08:00
Liujian 6168f4d758 Merge remote-tracking branch 'github-pro/main' into feature/translate
# Conflicts:
#	.github/ISSUE_TEMPLATE/bug_report.yml
#	.github/ISSUE_TEMPLATE/request_help.yml
2024-10-28 15:06:24 +08:00
Dot.L 687730be7b Merge pull request #96 from sunanzhi/main
fix:issue template content
2024-10-28 15:03:56 +08:00
Liujian cddb2bc2cf update access 2024-10-28 15:03:04 +08:00
Maggie fa7c9b4c47 Merge pull request #108 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-28 15:02:37 +08:00
杨梦洁 1fd429f582 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!55
2024-10-28 15:02:10 +08:00
maggieyyy 6d61c036f9 fix: Modify access 2024-10-28 15:00:59 +08:00
maggieyyy f82f4b0d7b fix: update message 2024-10-28 13:39:47 +08:00
maggieyyy fff39caa71 fix: Delete operation from team & Delete comments from publish 2024-10-28 11:52:51 +08:00
Liujian 5968d64e3d update action 2024-10-28 10:53:28 +08:00
Liujian 202c53375b update action 2024-10-28 10:46:17 +08:00
Liujian 9eea853724 Merge remote-tracking branch 'origin/main' into feature/translate 2024-10-28 10:43:23 +08:00
Dot.L 9526fa294a Merge pull request #1 from Dot-Liu/feature/translate
Feature/translate
2024-10-28 10:01:46 +08:00
Liujian e025fa2995 update go.mod 2024-10-28 10:00:34 +08:00
杨梦洁 5c15af2b9c Merge branch 'feature/v1.2' into 'main'
fix: Modify publish and title & add debug

See merge request apipark/APIPark!54
2024-10-28 09:59:00 +08:00
maggieyyy 3e094c7bf4 fix: Modify publish and title & add debug 2024-10-28 09:58:04 +08:00
Liujian 45a4b2b97d Merge remote-tracking branch 'origin/main' into feature/translate 2024-10-27 00:48:03 +08:00
Liujian 1d62a6613d role update 2024-10-27 00:47:48 +08:00
刘健 28f182a291 Merge branch 'feature/translate' into 'main'
create ai service add provider

See merge request apipark/APIPark!53
2024-10-26 21:25:40 +08:00
Liujian f78ba3ad1e create ai service add provider 2024-10-26 21:25:13 +08:00
刘健 e2ff036965 Merge branch 'feature/translate' into 'main'
update translate

See merge request apipark/APIPark!52
2024-10-25 18:47:48 +08:00
Liujian 7c7071a3a9 update translate 2024-10-25 18:45:38 +08:00
杨梦洁 e90809c010 Merge branch 'feature/v1.2' into 'main'
fix: update translation

See merge request apipark/APIPark!51
2024-10-25 16:35:30 +08:00
Maggie 2426fcd7d6 Merge pull request #101 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 16:35:27 +08:00
maggieyyy f433c28e75 fix: update translation 2024-10-25 16:34:06 +08:00
Maggie cac8755305 Merge pull request #100 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 16:20:02 +08:00
杨梦洁 a283dc0c62 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!50
2024-10-25 16:18:59 +08:00
maggieyyy 99002fa1cf fix: update translation 2024-10-25 16:16:15 +08:00
Maggie 9060c87d60 Merge pull request #99 from APIParkLab/docs-update-frontend-README
docs: Update README.md
2024-10-25 15:48:21 +08:00
Scarqin 1d275e3313 Update README.md 2024-10-25 15:44:42 +08:00
Maggie 77da2a7fd2 Merge pull request #95 from APIParkLab/feature/v1.2
fix: Remove guest's account setting & update translation
2024-10-25 15:24:37 +08:00
杨梦洁 b9cc53b694 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!49
2024-10-25 15:23:51 +08:00
maggieyyy 62d47077b1 fix: Remove guest's account setting & update translation 2024-10-25 15:22:06 +08:00
sunanzhi 3269e79ff3 fix:issue template content 2024-10-25 15:16:47 +08:00
刘健 307faed57b Merge branch 'feature/issue-templete' into 'main'
update ao-account dependent version

See merge request apipark/APIPark!48
2024-10-25 14:32:33 +08:00
Liujian dc6a9a53f0 update ao-account dependent version 2024-10-25 14:32:11 +08:00
JackLiu 285119852b Merge pull request #86 from rolealiu/main
update translation
2024-10-25 14:31:56 +08:00
JackLiu 65fa6517d3 Merge branch 'APIParkLab:main' into main 2024-10-25 14:31:26 +08:00
刘健 2c27074b04 Merge branch 'feature/issue-templete' into 'main'
update ao-account dependent version

See merge request apipark/APIPark!47
2024-10-25 14:31:21 +08:00
Liujian 66e4be0b57 update ao-account dependent version 2024-10-25 14:30:58 +08:00
HaoZhen Liu 14d94e33bb update translation 2024-10-25 14:30:57 +08:00
刘健 541f50aecc Merge branch 'feature/issue-templete' into 'main'
Feature/issue templete

See merge request apipark/APIPark!46
2024-10-25 14:22:21 +08:00
Liujian 95d87f7183 tmp commit 2024-10-25 14:21:50 +08:00
Maggie 6738960e46 Merge pull request #83 from APIParkLab/feature/v1.2
fix: AI Model config bug
2024-10-25 14:07:39 +08:00
杨梦洁 ab60eaac95 Merge branch 'feature/v1.2' into 'main'
fix: AI Model config bug

See merge request apipark/APIPark!45
2024-10-25 14:04:00 +08:00
maggieyyy 76f009c546 fix: AI Model config bug 2024-10-25 14:02:23 +08:00
Liujian b9c61f8b94 update issue templete 2024-10-25 09:32:12 +08:00
Maggie 125be3f2bf Merge pull request #70 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 09:28:32 +08:00
杨梦洁 9df44eeb87 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!44
2024-10-25 09:28:13 +08:00
maggieyyy 97aa6ee0d6 fix: update translation 2024-10-25 09:27:00 +08:00
刘健 80c9bca75b Merge branch 'feature/ai-service' into 'main'
Feature/ai service

See merge request apipark/APIPark!43
2024-10-24 23:43:36 +08:00
Liujian 9e253086ef fix get llm error 2024-10-24 23:42:55 +08:00
Dot.L 6aeb5299dc Merge pull request #68 from APIParkLab/feature/ai-service
Feature/ai service
2024-10-24 23:31:32 +08:00
Liujian 888eabe154 finish fake ai 2024-10-24 23:30:25 +08:00
杨梦洁 29d5c1bdd7 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!42
2024-10-24 18:28:36 +08:00
JackLiu eee33cda04 Merge pull request #67 from rolealiu/main
update translation
2024-10-24 18:25:40 +08:00
HaoZhen Liu df4f65d36d update translation 2024-10-24 18:24:51 +08:00
李冬杰 8e9335454e Merge branch 'feature/zhinao' into 'main'
Feature/zhinao

See merge request apipark/APIPark!41
2024-10-24 15:50:09 +08:00
lidongjie 4e4b0f2f51 add:ai provider 360-zhinao 2024-10-24 15:47:43 +08:00
杨梦洁 c28d6c85af Merge branch 'feature/v1.2' into 'main'
fix: Update translation

See merge request apipark/APIPark!40
2024-10-24 14:43:41 +08:00
Maggie 3cdbac76a5 Merge pull request #66 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-24 14:41:41 +08:00
maggieyyy 20bcc662c8 fix: Update translation 2024-10-24 14:39:49 +08:00
杨梦洁 908accd290 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!39
2024-10-24 13:52:16 +08:00
maggieyyy a621c5fc72 fix: Modify translation 2024-10-24 13:51:22 +08:00
maggieyyy 92f0ac1578 fix: Modify Ai setting 2024-10-24 11:40:14 +08:00
Liujian 8b3667ec9b Merge remote-tracking branch 'origin/main' into feature/ai-service 2024-10-23 18:41:14 +08:00
杨梦洁 875fa0936b Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!38
2024-10-23 18:23:12 +08:00
maggieyyy 669844f055 feat: Modify sevice type selector 2024-10-23 18:22:04 +08:00
maggieyyy 9785b930da fix: Password css 2024-10-23 17:41:40 +08:00
杨梦洁 f3195d257e Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!37
2024-10-23 16:59:51 +08:00
maggieyyy 349162852d fix: Add translation to api path match rule options 2024-10-23 16:52:36 +08:00
maggieyyy 69f330737f feat: Rename 'application' to 'consumer' and optimize consumer module display 2024-10-23 16:49:09 +08:00
刘健 7d10fbaa25 Merge branch 'feature/ai-service' into 'main'
upadte app list api

See merge request apipark/APIPark!36
2024-10-23 16:43:11 +08:00
Liujian 9d964b572b upadte app list api 2024-10-23 16:42:56 +08:00
刘健 a0978269f8 Merge branch 'feature/ai-service' into 'main'
update ai provider api

See merge request apipark/APIPark!35
2024-10-23 16:30:03 +08:00
Liujian 9a6196bbd7 update ai provider api 2024-10-23 16:29:18 +08:00
刘健 812f589762 Merge branch 'feature/ai-service' into 'main'
update provider logo

See merge request apipark/APIPark!34
2024-10-23 14:25:55 +08:00
Liujian b9e676d926 update provider logo 2024-10-23 14:22:44 +08:00
刘健 49e6e54c31 Merge branch 'feature/ai-service' into 'main'
update providers logo

See merge request apipark/APIPark!33
2024-10-23 13:39:04 +08:00
Liujian 4d398fd4d5 update providers logo 2024-10-23 13:38:16 +08:00
maggieyyy b74f4adfd8 feat: Add path match type before api path & Modify Login Page 2024-10-23 11:58:53 +08:00
JackLiu be5abccd81 Merge pull request #65 from rolealiu/main
update translation
2024-10-22 17:53:45 +08:00
JackLiu 1792489cd0 Merge branch 'APIParkLab:main' into main 2024-10-22 17:53:20 +08:00
HaoZhen Liu 4284fd8fc6 update translation 2024-10-22 17:53:48 +08:00
杨梦洁 036106db82 Merge branch 'feature/v1.2' into 'main'
Feature/v1.2

See merge request apipark/APIPark!32
2024-10-22 17:33:51 +08:00
Maggie c6ed032659 Merge pull request #64 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-22 17:33:21 +08:00
maggieyyy b521204c99 fix: Simplified Chinese not working 2024-10-22 17:32:25 +08:00
maggieyyy b38502e0bd Merge branch 'main' into feature/v1.2 2024-10-22 17:06:40 +08:00
maggieyyy 2fe03bd4b3 fix: Modify Login Page styles and Api document path 2024-10-22 17:05:40 +08:00
JackLiu 68a0f616dc Update readme-jp.md 2024-10-22 15:53:56 +08:00
JackLiu 1edce4295e Update readme-zh-tw.md 2024-10-22 15:53:42 +08:00
JackLiu ca386c343e Update README.md 2024-10-22 15:53:27 +08:00
JackLiu efb0b6526a Update readme-zh-cn.md 2024-10-22 15:53:10 +08:00
JackLiu 4a406ad261 Update readme-zh-tw.md 2024-10-22 15:51:30 +08:00
JackLiu fb701cc20d Update readme-jp.md 2024-10-22 15:49:41 +08:00
JackLiu 0b0478c9ba Update readme-zh-cn.md 2024-10-22 15:45:20 +08:00
JackLiu 79ff630c41 Update README.md 2024-10-22 15:40:14 +08:00
JackLiu 4679440520 Update feature_request.yml 2024-10-22 14:13:35 +08:00
maggieyyy b38f77acea fix: route config 2024-10-22 14:05:12 +08:00
HaoZhen Liu 896330d0ec update translation 2024-10-22 12:31:51 +08:00
JackLiu 205803a800 Merge pull request #60 from rolealiu/main
update translation
2024-10-22 12:31:22 +08:00
Maggie e6187f099a Merge pull request #59 from APIParkLab/feature/v1.2
fix: Modify peer address to use array format
2024-10-22 10:30:34 +08:00
杨梦洁 c148a5c797 Merge branch 'feature/v1.2' into 'main'
fix: Modify peer address to use array format

See merge request apipark/APIPark!31
2024-10-22 10:29:47 +08:00
maggieyyy 3d730547af fix: Modify peer address to use array format 2024-10-22 10:28:14 +08:00
maggieyyy c3f1b12b7e fix: aiservice router 2024-10-22 10:20:34 +08:00
Dot.L 9f9a347272 Merge pull request #58 from APIParkLab/feature/ai-service
Feature/ai service
2024-10-21 19:02:50 +08:00
Liujian d63869ca15 Merge remote-tracking branch 'origin/main' into feature/ai-service 2024-10-21 19:01:07 +08:00
刘健 d33a243020 Merge branch 'feature/auto-publish-to-gitlab' into 'main'
test frontend change

See merge request apipark/APIPark!30
2024-10-21 19:00:04 +08:00
Liujian 558e8fad61 test frontend change 2024-10-21 18:59:24 +08:00
刘健 b0f094a9d9 Merge branch 'feature/auto-publish-to-gitlab' into 'main'
copy frontend/dist to artifacts/dist

See merge request apipark/APIPark!29
2024-10-21 18:53:48 +08:00
Liujian 84e1528a1d copy frontend/dist to artifacts/dist 2024-10-21 18:53:28 +08:00
刘健 2a1372926f Merge branch 'feature/auto-publish-to-gitlab' into 'main'
print frontend dir

See merge request apipark/APIPark!28
2024-10-21 18:48:40 +08:00
Liujian 73b2fea954 print frontend dir 2024-10-21 18:47:54 +08:00
刘健 8263f1ec85 Merge branch 'feature/auto-publish-to-gitlab' into 'main'
print frontend dir

See merge request apipark/APIPark!27
2024-10-21 18:43:22 +08:00
Liujian 436ab32937 print frontend dir 2024-10-21 18:43:06 +08:00
刘健 cb904e5386 Merge branch 'feature/auto-publish-to-gitlab' into 'main'
update builder script

See merge request apipark/APIPark!26
2024-10-21 18:36:37 +08:00
Liujian 486bf0edcd update builder script 2024-10-21 18:36:19 +08:00
刘健 06e5f2878f Merge branch 'feature/auto-publish-to-gitlab' into 'main'
update builder script

See merge request apipark/APIPark!25
2024-10-21 18:31:57 +08:00
Liujian 5d1a7a7ca4 update builder script 2024-10-21 18:28:26 +08:00
刘健 197fe3c15b Merge branch 'feature/auto-publish-to-gitlab' into 'main'
update feishu informer rule

See merge request apipark/APIPark!24
2024-10-21 18:19:46 +08:00
Liujian 09ac4cf970 update feishu informer rule 2024-10-21 18:19:30 +08:00
Liujian f64a20fbac update feishu informer rule 2024-10-21 18:17:11 +08:00
Liujian 86b566a8cd update feishu informer rule 2024-10-21 18:12:44 +08:00
Maggie 2e7ecc93c8 Merge pull request #57 from maggieyyy/feature/v1.2
Feature/v1.2
2024-10-21 18:12:36 +08:00
Maggie c7f79d4b7b Merge branch 'APIParkLab:main' into feature/v1.2 2024-10-21 18:11:15 +08:00
杨梦洁 c452f092cc Merge branch 'feature/v1.2' into 'main'
frontend: delete comment

See merge request apipark/APIPark!23
2024-10-21 18:07:49 +08:00
maggieyyy 0764b4bfd4 frontend: delete comment 2024-10-21 18:07:10 +08:00
刘健 cd9552c9e0 Merge branch 'feature/auto-publish-to-gitlab' into 'main'
Gitlab automatically compiles and submits

See merge request apipark/APIPark!21
2024-10-21 18:05:46 +08:00
Liujian 508bfb7891 update gitlab runner exec rule 2024-10-21 18:01:47 +08:00
Liujian 998b5af4ae update deploy exec script 2024-10-21 18:00:20 +08:00
Liujian 5b1eac58e4 fix builder exec script 2024-10-21 17:56:50 +08:00
Maggie 9e0d25b77e Merge pull request #56 from maggieyyy/feature/v1.2
Feature/v1.2
2024-10-21 17:49:02 +08:00
杨梦洁 62488211f7 Merge branch 'feature/v1.2' into 'main'
frontend: update

See merge request apipark/APIPark!22
2024-10-21 17:47:06 +08:00
Liujian 0b4b183ba7 新建prefix.sh文件 2024-10-21 17:46:26 +08:00
maggieyyy f3532f6128 fix: service type field changes 2024-10-21 17:45:31 +08:00
maggieyyy a5e792d3ba fix: router config 2024-10-21 17:41:30 +08:00
Liujian 19fc1b6958 update run auto deploy condition 2024-10-21 17:06:52 +08:00
Liujian 2702b71cc6 update stage 2024-10-21 17:04:57 +08:00
刘健 97b3ef0f03 Merge branch 'feature/groq' into 'main'
add:添加GroqCloud供应商

See merge request apipark/APIPark!16
2024-10-21 17:02:46 +08:00
Liujian 3431805088 Gitlab automatically compiles and submits 2024-10-21 16:58:17 +08:00
Liujian 306da2fcc5 test frontend dir change 2024-10-21 16:16:46 +08:00
Liujian a7f2a91e6a Fix code errors caused by rebase 2024-10-21 15:51:15 +08:00
Liujian dcd85d0e9a Update ao-account dependency version 2024-10-21 15:48:01 +08:00
Liujian 82a3476f62 API Market Service Interface add service_kind Field 2024-10-21 15:07:13 +08:00
maggieyyy cf32ae9a00 fix: Add MF 2024-10-21 14:41:49 +08:00
maggieyyy 561c001b08 merge 2024-10-21 14:20:25 +08:00
JackLiu 26ff021887 Merge pull request #55 from rolealiu/main
update translation
2024-10-21 12:17:09 +08:00
HaoZhen Liu eb461b5bfa update translation 2024-10-21 12:17:34 +08:00
Maggie 42114a7f0d Merge pull request #54 from maggieyyy/main
fix: Add new fields for translation in Service Hub
2024-10-21 11:24:05 +08:00
maggieyyy 10b08ce42c fix: Add new fields for translation in Service Hub 2024-10-21 11:22:14 +08:00
Maggie c0934136d0 Merge pull request #53 from maggieyyy/main
fix: Add new fields for translation
2024-10-21 10:29:30 +08:00
maggieyyy fb77d33cb7 fix: Add new fields for translation 2024-10-21 10:27:37 +08:00
JackLiu 7ebbd8c0bf Merge pull request #52 from rolealiu/main
add chinese-tr and japanese lang readme
2024-10-19 00:55:00 +08:00
HaoZhen Liu 6c16251876 add chinese-tr and japanese lang readme 2024-10-19 00:55:13 +08:00
JackLiu dc18ce41f5 Update readme-zh-cn.md 2024-10-19 00:41:00 +08:00
JackLiu 2669e381b1 Update README.md 2024-10-19 00:40:24 +08:00
JackLiu 3deb9cbb35 Update readme-zh-cn.md 2024-10-19 00:27:31 +08:00
JackLiu eeaef841c8 Merge pull request #51 from rolealiu/main
improve translation
2024-10-19 00:08:18 +08:00
HaoZhen Liu 7f52cc95ec improve translation 2024-10-19 00:08:44 +08:00
JackLiu 71e9c464b9 Merge pull request #50 from rolealiu/main
improve translation
2024-10-19 00:05:41 +08:00
JackLiu 84fd74de4a Merge branch 'APIParkLab:main' into main 2024-10-19 00:04:08 +08:00
HaoZhen Liu f0661e6d19 improve translation 2024-10-19 00:04:26 +08:00
HaoZhen Liu 6f03c8f969 improve translation 2024-10-18 23:58:27 +08:00
JackLiu d38cff4def Merge pull request #49 from rolealiu/main
improve translation
2024-10-18 23:16:44 +08:00
HaoZhen Liu e45468cf3c improve translation 2024-10-18 23:15:29 +08:00
HaoZhen Liu ed843b7285 improve translation 2024-10-18 23:14:30 +08:00
Liujian 117dd82617 Initial installation of initialization data for simplified use. 2024-10-18 22:15:55 +08:00
Liujian b043db8237 注释ap-account本地依赖 2024-10-18 19:51:42 +08:00
Liujian ee703df2f3 新增i18n操作 2024-10-18 19:50:20 +08:00
Maggie 8b7cf85f23 Merge pull request #48 from maggieyyy/main
fix:  delete files & width of pic in editor & timing bug & remove roles i18n & update i18n scanner & update i18n files
2024-10-18 19:19:15 +08:00
maggieyyy c44bd22108 fix: update i18n files 2024-10-18 19:13:37 +08:00
maggieyyy 5c245c70f7 merge 2024-10-18 18:49:32 +08:00
maggieyyy debdd18a58 fix: remove roles i18n & update i18n scanner 2024-10-18 18:47:17 +08:00
JackLiu 29504e8d62 Merge pull request #47 from rolealiu/main
re-translate i18n language file
2024-10-18 18:34:31 +08:00
JackLiu a0edee3c45 Merge branch 'APIParkLab:main' into main 2024-10-18 18:33:36 +08:00
HaoZhen Liu 7f457d9ae8 modify i18n language file 2024-10-18 18:33:40 +08:00
maggieyyy dd5ac2d87b fix: delete files & width of pic in editor & timing bug 2024-10-18 18:05:47 +08:00
Liujian 76172d49c3 Initialize deployment with built-in data optimization 2024-10-18 15:38:39 +08:00
Liujian 7b6fc8e03e finish ai router 2024-10-18 12:10:27 +08:00
JackLiu 0be7620209 Merge pull request #46 from rolealiu/main
add zh-tw and japaness lang
2024-10-18 01:42:17 +08:00
HaoZhen Liu 3b6a38dd90 add zh-tw and japaness lang 2024-10-18 01:42:14 +08:00
Dot.L 0b001913de Merge pull request #45 from Dot-Liu/main
AI service experience optimization
2024-10-17 23:50:59 +08:00
Liujian b293b5b30e Merge remote-tracking branch 'origin/main' into main-github
# Conflicts:
#	gateway/apinto/entity/router.go
#	module/publish/iml.go
#	service/api/service.go
2024-10-17 23:49:41 +08:00
Liujian 9f7f6ab157 Experience optimization 2024-10-17 23:47:26 +08:00
Maggie b5c88a59bf Merge pull request #44 from maggieyyy/main
fix: delete useless file
2024-10-17 18:49:02 +08:00
Maggie 040c10596e Merge branch 'APIParkLab:main' into main 2024-10-17 18:48:06 +08:00
maggieyyy 1f1c7c0668 feat: delete en-GB file 2024-10-17 18:47:33 +08:00
Maggie ad1561f090 Merge pull request #43 from maggieyyy/main
frontend: update service & support more language
2024-10-17 18:44:25 +08:00
maggieyyy 83306364ce frontend: update service & support more language 2024-10-17 18:42:52 +08:00
Liujian 8ba0d49fb3 系统常规设置完成 2024-10-17 12:00:19 +08:00
Liujian e1c7c16d91 服务列表接口合并 2024-10-16 19:26:33 +08:00
lidongjie 01cca463bb modify:删除oci和lepton 2024-10-16 16:30:43 +08:00
Liujian 44aa842f20 finish nvidia 2024-10-16 16:17:32 +08:00
李冬杰 2d94bbaef7 Merge branch 'feature/chatglm' into 'main'
fix:添加chatglm address

See merge request apipark/APIPark!20
2024-10-16 15:01:34 +08:00
lidongjie b2bc656e15 fix:添加chatglm address 2024-10-16 15:00:06 +08:00
Liujian 21b2f554df 修改讯飞星火定义 2024-10-16 14:52:56 +08:00
JackLiu cd4795d50a Update README.md 2024-10-15 22:27:33 +08:00
JackLiu 583141a374 Update readme-zh-cn.md 2024-10-15 22:23:50 +08:00
JackLiu 816cc11a19 Update README.md 2024-10-15 22:19:07 +08:00
李冬杰 d27729d110 Merge branch 'feature/chatglm' into 'main'
add:添加chatglm供应商

See merge request apipark/APIPark!19
2024-10-15 16:34:41 +08:00
lidongjie f4a37539a0 add:添加chatglm供应商 2024-10-15 16:33:30 +08:00
李冬杰 cec2100915 Merge branch 'feature/minimax' into 'main'
add:添加minimax供应商

See merge request apipark/APIPark!18
2024-10-15 16:20:38 +08:00
lidongjie cab4629c4b add:添加minimax供应商 2024-10-15 16:03:04 +08:00
李冬杰 6f3c389e22 Merge branch 'feature/upstage' into 'main'
add:添加upstage供应商

See merge request apipark/APIPark!17
2024-10-14 18:05:56 +08:00
lidongjie 729e2882b5 add:添加upstage供应商 2024-10-14 18:02:43 +08:00
lidongjie b786ee4a36 add:添加GroqCloud供应商 2024-10-14 17:51:28 +08:00
李冬杰 7569ca1fd4 Merge branch 'feature/openrouter' into 'main'
add:添加openrouter供应商

See merge request apipark/APIPark!15
2024-10-14 17:31:10 +08:00
lidongjie 93925c1bfb add:添加openrouter供应商 2024-10-14 17:30:02 +08:00
李冬杰 658179d9c3 Merge branch 'feature/deepseek' into 'main'
add:添加deepseek供应商

See merge request apipark/APIPark!14
2024-10-14 17:01:24 +08:00
lidongjie bc74168e36 add:添加deepseek供应商 2024-10-14 17:01:01 +08:00
李冬杰 22afea72f5 Merge branch 'feature/cohere' into 'main'
add:添加cohere供应商

See merge request apipark/APIPark!13
2024-10-14 16:36:09 +08:00
lidongjie a2d42af747 add:添加cohere供应商 2024-10-14 16:34:57 +08:00
Liujian b04d06da4c 修复供应商修改配置失败的问题 2024-10-14 16:29:32 +08:00
李冬杰 f1052ae2f3 Merge branch 'feature/perfxcloud' into 'main'
add:添加perfxcloud供应商

See merge request apipark/APIPark!12
2024-10-14 15:08:17 +08:00
lidongjie c660aadf90 add:添加perfxcloud供应商 2024-10-14 15:06:04 +08:00
李冬杰 0fd8abe0ff Merge branch 'feature/yi' into 'main'
add:添加零一万物供应商

See merge request apipark/APIPark!11
2024-10-14 14:40:03 +08:00
lidongjie fcb3183e71 add:添加零一万物供应商 2024-10-14 14:37:03 +08:00
Liujian 3f2ed774ad Finish anthropic 2024-10-14 10:05:37 +08:00
李冬杰 6c90612fd2 Merge branch 'feature/stepfun' into 'main'
add:添加阶跃星辰供应商

See merge request apipark/APIPark!10
2024-10-12 18:34:02 +08:00
lidongjie ffb10a588e add:添加阶跃星辰供应商 2024-10-12 18:32:50 +08:00
李冬杰 43069c396d Merge branch 'feature/baichuan' into 'main'
add:添加baichuan供应商

See merge request apipark/APIPark!9
2024-10-12 18:05:04 +08:00
lidongjie 974c5cf8a2 add:添加baichuan供应商 2024-10-12 18:03:19 +08:00
Liujian c434d7c954 后端优化完成 2024-10-12 10:42:52 +08:00
Liujian 518846a281 Merge remote-tracking branch 'origin/main' 2024-10-11 18:41:13 +08:00
Liujian ec316f589b 修改model字段长度为255 2024-10-11 18:40:54 +08:00
李冬杰 92ea8e4308 Merge branch 'feature/mistralai' into 'main'
add:添加mistralai供应商

See merge request apipark/APIPark!8
2024-10-11 18:04:23 +08:00
lidongjie 0a6fc1e020 add:添加mistralai供应商 2024-10-11 18:02:23 +08:00
李冬杰 d06cf41581 Merge branch 'feature/novita' into 'main'
add:添加novita供应商

See merge request apipark/APIPark!7
2024-10-11 17:41:45 +08:00
lidongjie c94c746120 add:添加novita供应商 2024-10-11 17:41:02 +08:00
李冬杰 324c8a2b98 Merge branch 'feature/fireworks' into 'main'
add:添加fireworks

See merge request apipark/APIPark!6
2024-10-11 17:16:47 +08:00
lidongjie 0a2b191711 add:添加fireworks 2024-10-11 17:16:16 +08:00
李冬杰 334db692b2 Merge branch 'feature/zhipuai' into 'main'
add:智谱ai

See merge request apipark/APIPark!5
2024-10-11 17:00:57 +08:00
lidongjie 458176a0af add:智谱ai 2024-10-11 17:00:11 +08:00
李冬杰 954cf5af1f Merge branch 'feature/zhipuai' into 'main'
add:智谱ai

See merge request apipark/APIPark!4
2024-10-11 16:28:56 +08:00
lidongjie d46158b381 add:智谱ai 2024-10-11 16:28:29 +08:00
李冬杰 f883525c27 Merge branch 'feature/tongyi' into 'main'
Feature/tongyi

See merge request apipark/APIPark!3
2024-10-11 16:04:04 +08:00
lidongjie 453412ad4d modify:tongyi host 2024-10-11 16:02:15 +08:00
lidongjie 5f80f8e3af fix:通义千问 2024-10-11 14:42:58 +08:00
Liujian 61c308a0e3 优化schema 2024-10-11 14:29:38 +08:00
lidongjie 96a7394aaf add:添加通义千问 2024-10-11 14:13:25 +08:00
lidongjie 429e153cd4 add:添加通义千问 2024-10-11 14:04:49 +08:00
Liujian d856554aa4 Merge remote-tracking branch 'origin/main' 2024-10-10 21:50:12 +08:00
Liujian 227552f54b 发布流程优化 2024-10-10 21:48:42 +08:00
刘健 32ed7faff2 Merge branch 'feature/moonshot' into 'main'
Feature/moonshot

See merge request apipark/APIPark!2
2024-10-10 19:15:30 +08:00
lidongjie 35481c1f59 合并代码,月之暗面 2024-10-10 19:09:45 +08:00
Liujian f6510bd667 模型列表接入 2024-10-10 18:28:27 +08:00
lidongjie b51eb92256 add:Moonshot ai provider 2024-10-10 18:18:59 +08:00
Liujian 2b48c779ef apinto对接完成 2024-10-08 12:09:33 +08:00
Liujian 9783f77110 修复bug 2024-09-29 14:46:58 +08:00
Liujian e764fd07b9 多模型对接完成 2024-09-27 19:14:52 +08:00
Maggie 5aa8e88381 Merge pull request #41 from maggieyyy/main
feat: ai-service ui
2024-09-26 21:04:28 +08:00
Maggie 2775aa023b Merge branch 'APIParkLab:main' into main 2024-09-26 21:02:54 +08:00
maggieyyy 096adebb48 feat: ai-service ui 2024-09-26 21:01:51 +08:00
Liujian 1ba08ec630 修改权限名称 2024-09-26 18:08:29 +08:00
Liujian d72337b770 权限更新 2024-09-26 17:59:31 +08:00
Liujian c053aa6299 ai路由完成 2024-09-25 20:28:01 +08:00
Liujian 5d70b98cd4 AI服务接口完成 2024-09-25 11:56:51 +08:00
Liujian ea0812da97 AI供应商接口修复bug 2024-09-25 11:39:22 +08:00
Dot.L a771eda369 Modify Chinese Readme incorrect link
Modify Chinese Readme incorrect link
2024-09-25 09:46:44 +08:00
Liujian be40015526 新增AI服务接口 2024-09-25 09:35:58 +08:00
Liujian c56f6ff1fb 修改获取模型列表接口 2024-09-24 15:06:44 +08:00
Liujian 6dab6c327c AI供应商相关接口完成 2024-09-24 14:15:52 +08:00
maggieyyy 4f4e4e7b1d Merge pull request #39 from maggieyyy/main
fix: english version & tags id bugs
2024-09-14 14:38:08 +08:00
maggieyyy 259a1b9566 fix:tags id 2024-09-14 14:36:31 +08:00
maggieyyy 43533b5f3a fix:team member tranlated 2024-09-09 14:09:15 +08:00
maggieyyy 51f7628564 fix:english style 2024-09-09 13:48:39 +08:00
Dot.L 2aa2591f0f Merge pull request #37 from Dot-Liu/main
修复_commit表和_latest表初始化失败的问题
2024-09-06 10:37:04 +08:00
Liujian 6301b8f2fe 修复_commit表和_latest表初始化失败的问题 2024-09-06 10:32:54 +08:00
maggieyyy dbc29b86d8 Merge pull request #35 from maggieyyy/main
frontend: fix router list view
2024-09-03 10:07:27 +08:00
maggieyyy 5e1e088edd frontend: fix router list view 2024-09-03 10:06:19 +08:00
Dot.L 1c74f3d2ce Merge pull request #34 from Dot-Liu/main
修复服务获取API列表是获取到别的服务的API
2024-09-02 21:20:31 +08:00
Liujian 583918d617 修复服务获取API列表是获取到别的服务的API 2024-09-02 21:14:30 +08:00
Dot.L a15e1fbca0 Merge pull request #33 from Dot-Liu/main
初始化时当角色存在时,更新角色权限信息
2024-09-02 19:57:03 +08:00
Liujian 8699a7e97c 初始化时当角色存在时,更新角色权限信息 2024-09-02 19:56:04 +08:00
Dot.L a3869c3be0 Merge pull request #32 from Dot-Liu/main
修复报错:undefined: pm3.CreateRouterSimple
2024-09-02 19:32:46 +08:00
Liujian f777103030 修复报错:undefined: pm3.CreateRouterSimple 2024-09-02 19:32:02 +08:00
Dot.L 09eabbf773 Merge pull request #31 from Dot-Liu/main
修复openapiv2保存失败的问题
2024-09-02 19:09:11 +08:00
Liujian 64932c97a4 修复openapiv2保存失败的问题 2024-09-02 19:07:57 +08:00
Liujian 00e3710d66 Merge remote-tracking branch 'github-pro/main' into main-github 2024-09-02 19:03:23 +08:00
Dot.L bd99164416 Merge pull request #30 from Dot-Liu/main
1.1.0-beta后端代码提交
2024-09-02 18:28:45 +08:00
Liujian e37cee3be7 修复更新集群时配置不重新初始化的问题 2024-09-02 18:27:27 +08:00
Liujian 7c33abdbe6 Merge branch 'main' into main-github 2024-09-02 18:00:18 +08:00
maggieyyy e6bb9a972b Merge pull request #29 from maggieyyy/main
fix:change route & permission btn & datasource access
2024-09-02 17:53:56 +08:00
maggieyyy e40773e436 fix:change route & permission btn & datasource access 2024-09-02 17:09:44 +08:00
rolea liu 3c4c8b8fe6 Merge pull request #28 from rolealiu/main
update translate
2024-09-02 14:25:55 +08:00
HaoZhen Liu 5aaa32b788 add english readme 2024-09-02 14:25:39 +08:00
HaoZhen Liu e6f53ce2e7 add english readme 2024-09-02 14:21:56 +08:00
rolea liu f18d7c484b Merge pull request #27 from rolealiu/main
update translate
2024-09-02 14:21:47 +08:00
rolea liu fefc0fec76 Merge pull request #26 from rolealiu/main
update translation
2024-09-02 14:18:15 +08:00
rolea liu 2949c65c79 Merge branch 'APIParkLab:main' into main 2024-09-02 14:17:43 +08:00
HaoZhen Liu 19dcc1a914 add english readme 2024-09-02 14:18:19 +08:00
maggieyyy 64cdbb37f5 Merge pull request #25 from maggieyyy/main
fix: router match bugs
2024-09-02 13:43:54 +08:00
maggieyyy c31f8865c5 Merge branch 'main' of github.com:maggieyyy/APIPark into mainGithub 2024-09-02 13:42:44 +08:00
maggieyyy 9698ba0f5d fix: match type is empty 2024-09-02 13:40:50 +08:00
Liujian 836f15f5d7 修复路由详情没有返回协议的问题 2024-09-02 11:24:46 +08:00
Liujian 0d863b781f 修复上游保存失败问题 2024-09-02 10:20:06 +08:00
Liujian c016524079 修复发布报错 2024-09-02 10:02:33 +08:00
Liujian d85773c2da 发布自测完毕 2024-09-01 23:55:45 +08:00
maggieyyy 00c123fd1e fix:publish status & api doc 2024-08-30 19:38:59 +08:00
Liujian 48a8811026 发布功能完成 2024-08-30 19:35:18 +08:00
maggieyyy ab01f59eae Merge pull request #24 from maggieyyy/main
feat:openapi ui
2024-08-30 19:23:17 +08:00
maggieyyy 2bdd24180c feat:openapi ui 2024-08-30 19:22:38 +08:00
Liujian 126d1e4c58 发布初始提交 2024-08-30 18:33:35 +08:00
Liujian 582072e174 路由、权限相关接口完成 2024-08-30 16:48:43 +08:00
Liujian fbbea88502 api文档完成 2024-08-30 09:55:56 +08:00
maggieyyy 100841d6f7 Merge pull request #23 from maggieyyy/main
fix: change build config
2024-08-28 18:01:49 +08:00
maggieyyy cc096a548f Merge branch 'APIParkLab:main' into main 2024-08-28 18:01:19 +08:00
maggieyyy f6c9680551 Merge branch 'main' of github.com:maggieyyy/APIPark into mainGithub 2024-08-28 18:00:50 +08:00
maggieyyy 1f7951bf9f fix:change vite build config 2024-08-28 18:00:30 +08:00
maggieyyy a96e465b13 Merge pull request #22 from maggieyyy/main
fix:intelligent plugin & browser lang & check monitor config
2024-08-28 14:09:32 +08:00
maggieyyy bf6c955cd0 Merge branch 'APIParkLab:main' into main 2024-08-28 14:08:29 +08:00
maggieyyy 854578d300 fix:intelligent plugin & browser lang & check monitor config 2024-08-28 14:07:55 +08:00
maggieyyy beb0a2007e Merge pull request #21 from maggieyyy/main
fix:intelligent i18next
2024-08-27 10:47:15 +08:00
maggieyyy e0ab35920e fix:intelligent i18next 2024-08-27 10:45:27 +08:00
rolea liu 75cff407bf Merge pull request #20 from rolealiu/main
add english readme
2024-08-26 17:48:37 +08:00
HaoZhen Liu 297b20857c add english readme 2024-08-26 17:48:45 +08:00
rolea liu 04ccc272e1 Merge pull request #19 from rolealiu/main
add english readme
2024-08-26 17:46:17 +08:00
HaoZhen Liu 22f6267a50 Merge remote-tracking branch 'upstream/main' 2024-08-26 17:46:12 +08:00
HaoZhen Liu 8fed0c2b1f add english readme 2024-08-26 17:40:48 +08:00
HaoZhen Liu 154527947d add english readme 2024-08-26 17:33:30 +08:00
HaoZhen Liu a8b29b388b add english readme 2024-08-26 17:29:18 +08:00
HaoZhen Liu df845a0db4 add english readme 2024-08-26 17:27:43 +08:00
rolea liu 43b769e3e8 Merge pull request #18 from rolealiu/main
Improve translation
2024-08-26 17:18:10 +08:00
rolea liu ea58b708f8 Merge branch 'APIParkLab:main' into main 2024-08-26 17:16:00 +08:00
HaoZhen Liu 917786f8b8 Improve translation 2024-08-26 17:05:26 +08:00
HaoZhen Liu 8402209afd Improve translation 2024-08-26 16:17:57 +08:00
HaoZhen Liu 5c0b661189 Improve translation 2024-08-26 16:14:11 +08:00
HaoZhen Liu 47f7d78258 Improve translation 2024-08-26 16:12:40 +08:00
HaoZhen Liu c50becc085 Improve translation 2024-08-26 16:07:07 +08:00
rolea liu 0771b831e7 Merge pull request #17 from rolealiu/main
Improve translation
2024-08-26 15:39:38 +08:00
HaoZhen Liu b47e1c22c5 Merge remote-tracking branch 'upstream/main' 2024-08-26 15:37:26 +08:00
HaoZhen Liu 166d223577 Improve translation 2024-08-26 15:19:45 +08:00
rolea liu 310f983075 Merge pull request #16 from rolealiu/main
Improve translation
2024-08-26 15:09:43 +08:00
HaoZhen Liu ac0f472ac6 Improve translation 2024-08-26 15:09:03 +08:00
maggieyyy 977163588f Merge pull request #15 from maggieyyy/main
fix:i18next
2024-08-26 14:44:21 +08:00
maggieyyy da0b6e557e fix:i18next 2024-08-26 14:42:34 +08:00
Liujian 411a74b2aa 新增检测是否开启监控接口 2024-08-26 11:13:11 +08:00
Dot.L 0380353ff4 Merge pull request #13 from Dot-Liu/main
监控后端完成
2024-08-23 19:51:38 +08:00
Liujian c0590ddc0f Merge remote-tracking branch 'github-pro/main' into main-github 2024-08-23 19:49:28 +08:00
maggieyyy 020aba1c90 Merge pull request #12 from maggieyyy/main
fix:login with language setting
2024-08-23 19:45:53 +08:00
maggieyyy d46c5a10fc fix:login with language setting 2024-08-23 19:44:14 +08:00
maggieyyy 1e24758b21 Merge pull request #11 from maggieyyy/main
fix:i18next
2024-08-23 19:19:30 +08:00
maggieyyy 308b41a1ec Merge branch 'main' of github.com:maggieyyy/APIPark 2024-08-23 19:17:38 +08:00
maggieyyy e07e6b0f0f fix:i18next 2024-08-23 19:16:21 +08:00
Liujian 35ec6677ba Merge branch 'main' into main-github 2024-08-23 19:14:37 +08:00
Liujian 2110788f43 Merge remote-tracking branch 'github-pro/main' into main-github 2024-08-23 18:59:49 +08:00
Liujian d61e250e0b 修改依赖 2024-08-23 18:58:13 +08:00
maggieyyy 3d3c0377ff Merge pull request #10 from maggieyyy/main
fix:i18next
2024-08-23 18:51:48 +08:00
maggieyyy 1c8135388f merge 2024-08-23 18:18:45 +08:00
maggieyyy e47ccfc58d fix: i18n bugs 2024-08-23 18:16:48 +08:00
rolea liu 768cc5e10b Merge pull request #9 from rolealiu/main
Translate chinese to english
2024-08-23 16:36:51 +08:00
HaoZhen Liu 2be5cf5ee8 translate chinese to english 2024-08-23 16:33:26 +08:00
HaoZhen Liu 0ac1e42658 translate chinese to english 2024-08-23 16:32:42 +08:00
Dot.L 131851e650 Merge pull request #8 from maggieyyy/main
feat: guide
2024-08-23 15:43:23 +08:00
maggieyyy 56bb0b26ca Merge branch 'main' of github.com:maggieyyy/APIPark 2024-08-23 15:41:41 +08:00
maggieyyy 3d8a1eb8ae feat:guide 2024-08-23 15:41:26 +08:00
Dot.L a930dda037 Merge pull request #7 from maggieyyy/main
fix:access &  monitor style
2024-08-23 10:41:48 +08:00
maggieyyy 97154f97f1 fix:access & monitor style 2024-08-22 18:30:20 +08:00
Liujian 626077d625 修复监控获取数据失败问题 2024-08-22 18:08:18 +08:00
Liujian f45b83e947 监控接口完成 2024-08-22 11:24:41 +08:00
Liujian a2ea577fd8 修改go-common和ap-account依赖 2024-08-22 09:37:30 +08:00
Liujian 3a69a179bc 监控部分迁移 2024-08-21 23:42:15 +08:00
Dot.L 703d33b69c Merge pull request #6 from maggieyyy/main
dashboard && tour && guest_login
2024-08-21 18:39:45 +08:00
maggieyyy ef5b68cb9b Merge branch 'APIParkLab:main' into main 2024-08-21 18:11:26 +08:00
maggieyyy bf6017c60c feat:dashboard && tour && guest_login 2024-08-21 18:09:11 +08:00
Dot.L 097a588fc1 Merge pull request #5 from maggieyyy/main
feat:多语言
2024-08-20 18:51:06 +08:00
maggieyyy cac2cb2bac feat:多语言 2024-08-20 18:49:14 +08:00
Liujian ef571ba096 Merge remote-tracking branch 'github/main' 2024-08-20 14:32:59 +08:00
Liujian 419702a1ee 七牛云登录 2024-08-20 11:38:01 +08:00
Liujian 2c249f5167 新增登录操作 2024-08-20 11:23:17 +08:00
Liujian b90660f46c github action新增变量QINIU_BUCKET 2024-08-20 11:02:45 +08:00
Liujian 578999e705 修改qshell版本号为2.9.0 2024-08-20 10:55:18 +08:00
Liujian e2d6e9d812 修改七牛云脚本命令 2024-08-20 10:33:24 +08:00
Liujian 250937bd51 修改七牛云上传依赖 2024-08-20 10:23:11 +08:00
Liujian d85532ca85 修改github action脚本 2024-08-20 10:05:54 +08:00
Liujian 862c762eaa 新增上传到七牛云操作 2024-08-20 10:01:51 +08:00
Dot.L 8e6c4ec683 Merge pull request #1 from Dot-Liu/main
APIPark-1.0-beta完成
2024-08-16 20:56:44 +08:00
Liujian d82fe39a17 APIPark访客模式完成 2024-08-16 20:55:16 +08:00
rolea liu ca43a5ff43 Update README.md 2024-08-16 18:24:20 +08:00
rolea liu 449254581f Update README.md 2024-08-16 18:15:31 +08:00
Liujian 7a8557590c 修改依赖版本号 2024-08-16 18:06:32 +08:00
Liujian be6ecaa380 frontend:服务详情宽度 2024-08-16 18:01:09 +08:00
Liujian 54a29b39bf 修复可删除唯一团队管理员的问题 2024-08-16 17:59:04 +08:00
rolea liu a000ce2ec5 Update README.md 2024-08-16 17:39:14 +08:00
Liujian 44436ab29d Merge remote-tracking branch 'github/main' 2024-08-16 16:35:48 +08:00
Liujian 4863b8c9a3 修复新增订阅方失败的问题 2024-08-16 16:35:34 +08:00
Liujian 1662faafd2 新增访客模式 2024-08-16 11:27:41 +08:00
Liujian 693b76ee18 前端代码更新 2024-08-15 18:28:46 +08:00
Liujian 7da4235fc8 Merge branch 'main' into main-github 2024-08-15 11:34:48 +08:00
Liujian 66b5315a13 新增自动打包脚本 2024-08-15 11:34:33 +08:00
Liujian 5dd04479c2 修复动态模块上下线失败的问题 2024-08-15 09:53:01 +08:00
Liujian 469a612e41 首次提交APIPark代码,面向开源 2024-08-12 21:38:09 +08:00
rolea liu 7c8d175c9c Initial commit 2024-08-12 10:26:35 +08:00
146 changed files with 6867 additions and 1443 deletions
+2 -1
View File
@@ -7,4 +7,5 @@
/.vscode/
.air.toml
/tmp/
/work
/work
/cmd/
+13 -1
View File
@@ -3,6 +3,7 @@ package catalogue
import (
"github.com/APIParkLab/APIPark/module/catalogue"
catalogue_dto "github.com/APIParkLab/APIPark/module/catalogue/dto"
"github.com/APIParkLab/APIPark/module/service"
"github.com/APIParkLab/APIPark/module/tag"
tag_dto "github.com/APIParkLab/APIPark/module/tag/dto"
"github.com/gin-gonic/gin"
@@ -14,6 +15,7 @@ var (
type imlCatalogueController struct {
catalogueModule catalogue.ICatalogueModule `autowired:""`
appModule service.IAppModule `autowired:""`
tagModule tag.ITagModule `autowired:""`
}
@@ -26,7 +28,17 @@ func (i *imlCatalogueController) Subscribe(ctx *gin.Context, subscribeInfo *cata
}
func (i *imlCatalogueController) ServiceDetail(ctx *gin.Context, sid string) (*catalogue_dto.ServiceDetail, error) {
return i.catalogueModule.ServiceDetail(ctx, sid)
detail, err := i.catalogueModule.ServiceDetail(ctx, sid)
if err != nil {
return nil, err
}
_, canSubscribe, err := i.appModule.SearchCanSubscribe(ctx, sid)
if err != nil {
return nil, err
}
detail.CanSubscribe = canSubscribe
return detail, nil
}
func (i *imlCatalogueController) Search(ctx *gin.Context, keyword string) ([]*catalogue_dto.Item, []*tag_dto.Item, error) {
+277
View File
@@ -0,0 +1,277 @@
package mcp
import (
"fmt"
"net/http"
"strings"
"sync"
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
mcp_server "github.com/APIParkLab/APIPark/mcp-server"
"github.com/APIParkLab/APIPark/module/mcp"
"github.com/APIParkLab/APIPark/module/system"
"github.com/eolinker/go-common/utils"
"github.com/gin-gonic/gin"
mcp2 "github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
var _ IMcpController = (*imlMcpController)(nil)
type imlMcpController struct {
settingModule system.ISettingModule `autowired:""`
authorizationModule application_authorization.IAuthorizationModule `autowired:""`
mcpModule mcp.IMcpModule `autowired:""`
sessionKeys sync.Map
server map[string]http.Handler
openServer http.Handler
}
var mcpDefaultConfig = `{
"mcpServers": {
"%s": {
"url": "%s"
}
}
}
`
func (i *imlMcpController) GlobalMCPConfig(ctx *gin.Context) (string, error) {
cfg := i.settingModule.Get(ctx)
if cfg.SitePrefix == "" {
return "", fmt.Errorf("site prefix is empty")
}
return fmt.Sprintf(mcpDefaultConfig, "APIPark-MCP-Server", fmt.Sprintf("%s/openapi/v1/%s/sse?apikey={your_api_key}", strings.TrimSuffix(cfg.SitePrefix, "/"), mcp_server.GlobalBasePath)), nil
}
func (i *imlMcpController) generateZhCNMCPServer() *server.MCPServer {
s := server.NewMCPServer("APIPark MCP Server", "1.0.0", server.WithLogging())
s.AddTool(
mcp2.NewTool(
"service_list",
mcp2.WithDescription("此工具用于获取 APIPark 中已注册服务的列表。每个服务包含其唯一标识(service ID)、名称、描述及包含的 API 列表等关键信息。支持通过关键词进行模糊搜索,以便快速缩小查找范围。在获得某个服务的 ID 后,可以调用 openapi_document 工具来获取该服务的 OpenAPI 文档,以便后续调用其提供的 API 接口。"),
mcp2.WithString("keyword", mcp2.Description("关键词,用于模糊搜索服务")),
),
i.mcpModule.Services,
)
s.AddTool(
mcp2.NewTool(
"openapi_document",
mcp2.WithDescription("此工具用于获取指定服务的 OpenAPI 接口文档。返回内容支持 OpenAPI v3 与 v2 两种规范格式。通过传入服务 ID,可以查看该服务的所有 API 定义、参数结构、请求方式等详细信息,为后续构造请求做准备。"),
mcp2.WithString("service", mcp2.Description("服务的唯一标识 ID")),
),
i.mcpModule.APIs,
)
s.AddTool(
mcp2.NewTool(
"invoke_api",
mcp2.WithDescription("此工具用于直接调用指定的 API 接口。调用前需根据该接口的 OpenAPI 文档构造必要的请求参数,如请求路径、方法、查询参数、请求头、请求体等。调用过程中无需传递认证信息,例如请求头中的 Authorization 字段不需要提供。"),
mcp2.WithString("path", mcp2.Description("API 请求路径"), mcp2.Required()),
mcp2.WithString("method", mcp2.Description("API 请求方法,例如 GET、POST、PUT"), mcp2.Required()),
mcp2.WithString("content-type", mcp2.Description("请求的 Content-Type 类型。如果方法为 POST、PUT 或 PATCH,则必须指定该字段。")),
mcp2.WithObject("query", mcp2.Description("请求的查询参数,类型为 map[string]string")),
mcp2.WithObject("header", mcp2.Description("请求的头部参数,类型为 map[string]string")),
mcp2.WithString("body", mcp2.Description("请求体内容,通常为 JSON 字符串")),
),
i.mcpModule.Invoke,
)
return s
}
func (i *imlMcpController) generateZhTWMCPServer() *server.MCPServer {
s := server.NewMCPServer("APIPark MCP Server", "1.0.0", server.WithLogging())
s.AddTool(
mcp2.NewTool(
"service_list",
mcp2.WithDescription("此工具用於獲取 APIPark 中已註冊服務的清單。每個服務包含其唯一識別碼(service ID)、名稱、描述以及該服務所包含的 API 列表。支援關鍵字模糊搜尋,可快速縮小查詢範圍。獲取到服務 ID 後,可使用 openapi_document 工具來查詢該服務對應的 OpenAPI 文件,為後續 API 呼叫做準備。"),
mcp2.WithString("keyword", mcp2.Description("關鍵字,用於模糊搜尋服務")),
),
i.mcpModule.Services,
)
s.AddTool(
mcp2.NewTool(
"openapi_document",
mcp2.WithDescription("此工具用於查詢指定服務的 OpenAPI 文件。返回的格式支援 OpenAPI v3 與 v2 標準。透過輸入服務 ID,可查閱該服務所有 API 的定義、參數結構、請求方式等細節,有助於後續構造 API 呼叫請求。"),
mcp2.WithString("service", mcp2.Description("欲查詢的服務唯一識別碼")),
),
i.mcpModule.APIs,
)
s.AddTool(
mcp2.NewTool(
"invoke_api",
mcp2.WithDescription("此工具可直接發送 API 請求。在呼叫此工具之前,需根據該 API 的 OpenAPI 文件構造所需的請求參數,如請求路徑、方法、查詢參數、標頭、主體等。使用此工具時不需傳送任何認證資訊,例如 Authorization 標頭可省略。"),
mcp2.WithString("path", mcp2.Description("API 的請求路徑"), mcp2.Required()),
mcp2.WithString("method", mcp2.Description("API 的請求方法,例如 GET、POST、PUT"), mcp2.Required()),
mcp2.WithString("content-type", mcp2.Description("請求的 Content-Type。若方法為 POST、PUT 或 PATCH,則必須指定")),
mcp2.WithObject("query", mcp2.Description("請求的查詢參數,類型為 map[string]string")),
mcp2.WithObject("header", mcp2.Description("請求的標頭,類型為 map[string]string")),
mcp2.WithString("body", mcp2.Description("請求主體內容,通常為 JSON 字串")),
),
i.mcpModule.Invoke,
)
return s
}
func (i *imlMcpController) generateEnMCPServer() *server.MCPServer {
s := server.NewMCPServer("APIPark MCP Server", "1.0.0", server.WithLogging())
s.AddTool(
mcp2.NewTool(
"service_list",
mcp2.WithDescription("This tool can retrieve a list of registered services on APIPark, including key information such as service ID, name, description, and API list within the service. Support keyword search to quickly narrow down the search scope. After obtaining the service ID, you can use this ID to call the tool openapi_document to obtain the openapi document of the service for the corresponding service, preparing for subsequent API calls."),
mcp2.WithString("keyword", mcp2.Description("Keyword for fuzzy search")),
),
i.mcpModule.Services,
)
s.AddTool(
mcp2.NewTool(
"openapi_document",
mcp2.WithDescription("This tool returns the openAPI documentation for the corresponding service. The format supports the specifications of OpenAPI v3 and OpenAPI v2."),
mcp2.WithString("service", mcp2.Description("Service ID")),
),
i.mcpModule.APIs,
)
s.AddTool(
mcp2.NewTool(
"invoke_api",
mcp2.WithDescription("This tool can directly make API calls. Before calling this tool, it is necessary to construct relevant parameters based on the corresponding API's openAPI documentation, including query, header, body, method, path, and other parameters. By using this tool, no authentication related information needs to be transmitted, that is, no request header Authorization needs to be transmitted."),
mcp2.WithString("path", mcp2.Description("API path"), mcp2.Required()),
mcp2.WithString("method", mcp2.Description("API method"), mcp2.Required()),
mcp2.WithString("content-type", mcp2.Description("API Request Content-Type. If method is POST,PUT,PATCH, it must be set. If not set, it will be ignored.")),
mcp2.WithObject("query", mcp2.Description("API Request query,param type is map[string]string")),
mcp2.WithObject("header", mcp2.Description("API Request header,param type is map[string]string")),
mcp2.WithString("body", mcp2.Description("API Request body")),
),
i.mcpModule.Invoke,
)
return s
}
func (i *imlMcpController) generateJPMCPServer() *server.MCPServer {
s := server.NewMCPServer("APIPark MCP Server", "1.0.0", server.WithLogging())
s.AddTool(
mcp2.NewTool(
"service_list",
mcp2.WithDescription("このツールは、APIPark に登録されているサービスの一覧を取得するためのものです。各サービスには、サービスID、名称、説明、およびそのサービスに含まれるAPI一覧といった重要な情報が含まれます。キーワードによるあいまい検索が可能で、目的のサービスを素早く絞り込むことができます。取得したサービスIDを使用して openapi_document ツールを呼び出すことで、そのサービスの OpenAPI ドキュメントを取得でき、APIの利用準備が整います。"),
mcp2.WithString("keyword", mcp2.Description("キーワード。サービスをあいまい検索するための文字列")),
),
i.mcpModule.Services,
)
s.AddTool(
mcp2.NewTool(
"openapi_document",
mcp2.WithDescription("指定されたサービスの OpenAPI ドキュメントを取得するためのツールです。OpenAPI v3 および v2 のフォーマットに対応しています。このドキュメントを使用することで、APIのエンドポイント、リクエスト方法、パラメータなどの詳細を確認でき、API呼び出しの準備に役立ちます。"),
mcp2.WithString("service", mcp2.Description("対象のサービスID")),
),
i.mcpModule.APIs,
)
s.AddTool(
mcp2.NewTool(
"invoke_api",
mcp2.WithDescription("このツールは、指定された API を直接呼び出すためのものです。呼び出し前に、OpenAPI ドキュメントに基づいて必要なパラメータ(パス、メソッド、クエリ、ヘッダー、ボディなど)を構築する必要があります。呼び出し時に認証情報(例:Authorization ヘッダー)を送信する必要はありません。"),
mcp2.WithString("path", mcp2.Description("API のリクエストパス"), mcp2.Required()),
mcp2.WithString("method", mcp2.Description("HTTPメソッド(GET、POST、PUTなど)。"), mcp2.Required()),
mcp2.WithString("content-type", mcp2.Description("リクエストの Content-Type。メソッドが POST、PUT、PATCH の場合に必須。")),
mcp2.WithObject("query", mcp2.Description("リクエストのクエリパラメータ。型は map[string]string")),
mcp2.WithObject("header", mcp2.Description("リクエストヘッダー。型は map[string]string")),
mcp2.WithString("body", mcp2.Description("リクエストボディ。通常はJSON文字列")),
),
i.mcpModule.Invoke,
)
return s
}
func (i *imlMcpController) OnComplete() {
i.server = make(map[string]http.Handler)
enSer := i.generateEnMCPServer()
i.server["en-US"] = server.NewSSEServer(enSer, server.WithBasePath(fmt.Sprintf("/api/v1/%s", mcp_server.GlobalBasePath)))
i.server["zh-CN"] = server.NewSSEServer(i.generateZhCNMCPServer(), server.WithBasePath(fmt.Sprintf("/api/v1/%s", mcp_server.GlobalBasePath)))
i.server["zh-TW"] = server.NewSSEServer(i.generateZhTWMCPServer(), server.WithBasePath(fmt.Sprintf("/api/v1/%s", mcp_server.GlobalBasePath)))
i.server["ja-JP"] = server.NewSSEServer(i.generateJPMCPServer(), server.WithBasePath(fmt.Sprintf("/api/v1/%s", mcp_server.GlobalBasePath)))
i.openServer = server.NewSSEServer(enSer, server.WithBasePath(fmt.Sprintf("/openapi/v1/%s", strings.Trim(mcp_server.GlobalBasePath, "/"))))
}
func (i *imlMcpController) GlobalMCPHandle(ctx *gin.Context) {
cfg := i.settingModule.Get(ctx)
req := ctx.Request.WithContext(utils.SetGatewayInvoke(ctx.Request.Context(), cfg.InvokeAddress))
locale := utils.I18n(ctx)
if v, ok := i.server[locale]; ok {
v.ServeHTTP(ctx.Writer, req)
return
}
i.server["en-US"].ServeHTTP(ctx.Writer, req)
}
func (i *imlMcpController) GlobalHandleSSE(ctx *gin.Context) {
apikey := ctx.Request.URL.Query().Get("apikey")
i.handleSSE(ctx, i.openServer, apikey)
}
func (i *imlMcpController) handleSSE(ctx *gin.Context, server http.Handler, apikey string) {
writer := &ResponseWriter{
Writer: ctx.Writer,
sessionId: make(chan string),
}
defer close(writer.sessionId)
sessionId := ""
go func() {
var ok bool
sessionId, ok = <-writer.sessionId
if !ok {
return
}
i.sessionKeys.Store(sessionId, apikey)
}()
server.ServeHTTP(writer, ctx.Request)
i.sessionKeys.Delete(sessionId)
}
func (i *imlMcpController) GlobalHandleMessage(ctx *gin.Context) {
i.handleMessage(ctx, i.openServer)
}
func (i *imlMcpController) MCPHandle(ctx *gin.Context) {
cfg := i.settingModule.Get(ctx)
req := ctx.Request.WithContext(utils.SetGatewayInvoke(ctx.Request.Context(), cfg.InvokeAddress))
mcp_server.ServeHTTP(ctx.Writer, req)
}
func (i *imlMcpController) ServiceHandleSSE(ctx *gin.Context) {
apikey := ctx.Request.URL.Query().Get("apikey")
serviceId := ctx.Param("serviceId")
if serviceId == "" {
ctx.AbortWithStatusJSON(403, gin.H{"code": -1, "msg": "invalid service id", "success": "fail"})
return
}
ok, err := i.authorizationModule.CheckAPIKeyAuthorization(ctx, serviceId, apikey)
if err != nil {
ctx.AbortWithStatusJSON(403, gin.H{"code": -1, "msg": err.Error(), "success": "fail"})
return
}
if !ok {
ctx.AbortWithStatusJSON(403, gin.H{"code": -1, "msg": "invalid apikey", "success": "fail"})
return
}
i.handleSSE(ctx, mcp_server.DefaultMCPServer(), apikey)
}
func (i *imlMcpController) ServiceHandleMessage(ctx *gin.Context) {
i.handleMessage(ctx, mcp_server.DefaultMCPServer())
}
func (i *imlMcpController) handleMessage(ctx *gin.Context, server http.Handler) {
sessionId := ctx.Request.URL.Query().Get("sessionId")
apikey, ok := i.sessionKeys.Load(sessionId)
if !ok {
ctx.String(403, "sessionId not found")
return
}
cfg := i.settingModule.Get(ctx)
req := ctx.Request.WithContext(utils.SetGatewayInvoke(ctx.Request.Context(), cfg.InvokeAddress))
req = req.WithContext(utils.SetLabel(req.Context(), "apikey", apikey.(string)))
server.ServeHTTP(ctx.Writer, req)
}
+24
View File
@@ -0,0 +1,24 @@
package mcp
import (
"reflect"
"github.com/eolinker/go-common/autowire"
"github.com/gin-gonic/gin"
)
type IMcpController interface {
MCPHandle(ctx *gin.Context)
GlobalMCPHandle(ctx *gin.Context)
GlobalHandleSSE(ctx *gin.Context)
GlobalHandleMessage(ctx *gin.Context)
ServiceHandleSSE(ctx *gin.Context)
ServiceHandleMessage(ctx *gin.Context)
GlobalMCPConfig(ctx *gin.Context) (string, error)
}
func init() {
autowire.Auto[IMcpController](func() reflect.Value {
return reflect.ValueOf(new(imlMcpController))
})
}
+35
View File
@@ -0,0 +1,35 @@
package mcp
import (
"net/http"
"regexp"
)
type ResponseWriter struct {
Writer http.ResponseWriter
sessionId chan string
}
func (r *ResponseWriter) Flush() {
fluster, ok := r.Writer.(http.Flusher)
if ok {
fluster.Flush()
}
}
func (r *ResponseWriter) Header() http.Header {
return r.Writer.Header()
}
func (r *ResponseWriter) Write(bytes []byte) (int, error) {
re := regexp.MustCompile(`sessionId=([^&?\s]+)`)
match := re.FindStringSubmatch(string(bytes))
if len(match) > 1 {
r.sessionId <- match[1]
}
return r.Writer.Write(bytes)
}
func (r *ResponseWriter) WriteHeader(statusCode int) {
r.Writer.WriteHeader(statusCode)
}
+3 -2
View File
@@ -542,8 +542,9 @@ type imlAppController struct {
authModule application_authorization.IAuthorizationModule `autowired:""`
}
func (i *imlAppController) SearchCanSubscribe(ctx *gin.Context, serviceId string) ([]*service_dto.SimpleAppItem, error) {
return i.module.SearchCanSubscribe(ctx, serviceId)
func (i *imlAppController) SearchCanSubscribe(ctx *gin.Context, serviceId string) ([]*service_dto.SubscribeAppItem, error) {
items, _, err := i.module.SearchCanSubscribe(ctx, serviceId)
return items, err
}
func (i *imlAppController) Search(ctx *gin.Context, teamId string, keyword string) ([]*service_dto.AppItem, error) {
+1 -1
View File
@@ -44,7 +44,7 @@ type IAppController interface {
// SimpleApps 获取简易项目列表
SimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
MySimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
SearchCanSubscribe(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
SearchCanSubscribe(ctx *gin.Context, serviceId string) ([]*service_dto.SubscribeAppItem, error)
GetApp(ctx *gin.Context, appId string) (*service_dto.App, error)
DeleteApp(ctx *gin.Context, appId string) error
}
+26
View File
@@ -0,0 +1,26 @@
package system_apikey
import (
"reflect"
system_apikey_dto "github.com/APIParkLab/APIPark/module/system-apikey/dto"
"github.com/eolinker/go-common/autowire"
"github.com/gin-gonic/gin"
)
type IAPIKeyController interface {
Create(ctx *gin.Context, input *system_apikey_dto.Create) error
Update(ctx *gin.Context, id string, input *system_apikey_dto.Update) error
Delete(ctx *gin.Context, id string) error
Get(ctx *gin.Context, id string) (*system_apikey_dto.APIKey, error)
Search(ctx *gin.Context, keyword string) ([]*system_apikey_dto.Item, error)
SimpleList(ctx *gin.Context) ([]*system_apikey_dto.SimpleItem, error)
MyAPIKeys(ctx *gin.Context) ([]*system_apikey_dto.SimpleItem, error)
MyAPIKeysByService(ctx *gin.Context, serviceId string) ([]*system_apikey_dto.AuthorizationItem, error)
}
func init() {
autowire.Auto[IAPIKeyController](func() reflect.Value {
return reflect.ValueOf(new(imlAPIKeyController))
})
}
+45
View File
@@ -0,0 +1,45 @@
package system_apikey
import (
system_apikey "github.com/APIParkLab/APIPark/module/system-apikey"
system_apikey_dto "github.com/APIParkLab/APIPark/module/system-apikey/dto"
"github.com/gin-gonic/gin"
)
var _ IAPIKeyController = new(imlAPIKeyController)
type imlAPIKeyController struct {
apikeyModule system_apikey.IAPIKeyModule `autowired:""`
}
func (i *imlAPIKeyController) MyAPIKeysByService(ctx *gin.Context, serviceId string) ([]*system_apikey_dto.AuthorizationItem, error) {
return i.apikeyModule.MyAPIKeysByService(ctx, serviceId)
}
func (i *imlAPIKeyController) MyAPIKeys(ctx *gin.Context) ([]*system_apikey_dto.SimpleItem, error) {
return i.apikeyModule.MyAPIKeys(ctx)
}
func (i *imlAPIKeyController) Create(ctx *gin.Context, input *system_apikey_dto.Create) error {
return i.apikeyModule.Create(ctx, input)
}
func (i *imlAPIKeyController) Update(ctx *gin.Context, id string, input *system_apikey_dto.Update) error {
return i.apikeyModule.Update(ctx, id, input)
}
func (i *imlAPIKeyController) Delete(ctx *gin.Context, id string) error {
return i.apikeyModule.Delete(ctx, id)
}
func (i *imlAPIKeyController) Get(ctx *gin.Context, id string) (*system_apikey_dto.APIKey, error) {
return i.apikeyModule.Get(ctx, id)
}
func (i *imlAPIKeyController) Search(ctx *gin.Context, keyword string) ([]*system_apikey_dto.Item, error) {
return i.apikeyModule.Search(ctx, keyword)
}
func (i *imlAPIKeyController) SimpleList(ctx *gin.Context) ([]*system_apikey_dto.SimpleItem, error) {
return i.apikeyModule.SimpleList(ctx)
}
+4 -1
View File
@@ -47,7 +47,10 @@
"swagger-ui-react": "^5.17.14",
"tailwindcss": "^3.3.5",
"uuid": "^9.0.1",
"vite-tsconfig-paths": "^4.3.2"
"vite-tsconfig-paths": "^4.3.2",
"react-json-view": "^1.21.3",
"zod": "^3.23.8",
"@modelcontextprotocol/sdk": "^1.9.0"
},
"devDependencies": {
"@ant-design/cssinjs": "^1.18.2",
@@ -1,11 +1,25 @@
import { Breadcrumb } from 'antd'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
import { FC, useEffect } from 'react'
import { LeftOutlined } from '@ant-design/icons'
const TopBreadcrumb: FC = () => {
const TopBreadcrumb: FC<{ handleBackCallback?: () => void }> = ({ handleBackCallback }) => {
const { breadcrumb } = useBreadcrumb()
useEffect(() => {}, [breadcrumb])
return <Breadcrumb items={breadcrumb} />
const handleBack = () => {
handleBackCallback?.()
}
return (
<div className="flex text-[18px] leading-[25px] pb-[12px]">
<div
onClick={handleBack}
className="hover:bg-gray-100 items-center mt-[1px] mr-[12px] flex justify-center rounded-lg border cursor-pointer border-gray-300 w-[30px] h-[30px] border border-solid "
>
<LeftOutlined className="text-xs" />
</div>
<Breadcrumb items={breadcrumb} className="flex-1" />
</div>
)
}
export default TopBreadcrumb
@@ -4,11 +4,12 @@ import { $t } from '@common/locales'
import { Button, Tag } from 'antd'
import { FC, ReactNode } from 'react'
import { useNavigate } from 'react-router-dom'
import TopBreadcrumb from './Breadcrumb'
class InsidePageProps {
showBanner?: boolean = true
pageTitle: string | React.ReactNode = ''
tagList?: Array<{ label: string | ReactNode }> = []
tagList?: Array<{ label: string | ReactNode; className?: string; color?: string }> = []
children: React.ReactNode
showBtn?: boolean = false
btnTitle?: string = ''
@@ -64,14 +65,7 @@ const InsidePage: FC<InsidePageProps> = ({
<></>
) : (
<div className={customPadding ? '' : 'mb-[30px]'}>
{backUrl && (
<div className="text-[18px] leading-[25px] mb-[12px]">
<Button type="text" onClick={goBack}>
<ArrowLeftOutlined className="max-h-[14px]" />
{$t('返回')}
</Button>
</div>
)}
{backUrl && <TopBreadcrumb handleBackCallback={() => goBack()} />}
<div className="flex justify-between mb-[20px] items-center ">
<div className="flex items-center gap-TAG_LEFT">
<div className="text-theme text-[26px] ">{pageTitle}</div>
@@ -79,7 +73,7 @@ const InsidePage: FC<InsidePageProps> = ({
tagList?.length > 0 &&
tagList?.map((tag) => {
return (
<Tag key={tag.label as string} bordered={false}>
<Tag key={tag.label as string} bordered={false} color={tag.color} className={tag.className}>
{tag.label}
</Tag>
)
@@ -55,6 +55,8 @@ export const TranslateWord = () => {
{$t('打开 OpenAPI YAML 编辑器')}
{$t('无需审核:允许任何消费者调用该服务')}
{$t('人工审核:仅允许通过人工审核的消费者调用该服务')}
{$t('开启:AI Agent 等产品能够通过 MCP 方式调用服务')}
{$t('总览')}
{$t('永久')}
{$t('否')}
{$t('是')}
@@ -234,12 +234,16 @@ export default function ApiEdit({
<>
<Space.Compact className="w-full mb-btnybase">
<Select
showSearch
optionFilterProp="label"
className="w-[15%] min-w-[100px]"
value={apiInfo?.protocol || 'HTTP'}
disabled={true}
options={protocolOptionList}
/>
<Select
showSearch
optionFilterProp="label"
className="w-[15%] min-w-[100px]"
value={apiInfo?.method}
disabled={true}
@@ -254,6 +254,21 @@ export const PERMISSION_DEFINITION = [
anyOf: [{ backend: ['system.settings.ai_balance.manager'] }]
}
},
'system.settings.mcp.manager': {
granted: {
anyOf: [{ backend: ['system.settings.mcp.manager'] }]
}
},
'system.settings.mcp.view': {
granted: {
anyOf: [{ backend: ['system.settings.mcp.view'] }]
}
},
'system.settings.apikey.view': {
granted: {
anyOf: [{ backend: ['system.settings.apikey.view'] }]
}
},
'system.devops.policy.view': {
granted: {
anyOf: [{ backend: ['system.settings.strategy.view'] }]
@@ -81,6 +81,7 @@ export type MatchItem = {
export type EntityItem = {
id: string
name: string
isSubscribed: boolean
}
export type DynamicMenuItem = {
@@ -18,5 +18,19 @@ export const useBreadcrumb = () => {
export const BreadcrumbProvider = ({ children }: unknown) => {
const [breadcrumb, setBreadcrumb] = useState<BreadcrumbItemType[]>([])
return <BreadcrumbContext.Provider value={{ setBreadcrumb, breadcrumb }}>{children}</BreadcrumbContext.Provider>
return (
<BreadcrumbContext.Provider
value={{
setBreadcrumb: (newItems) => {
newItems.slice(0, newItems.length - 1).forEach((item) => {
item.title = <span className="cursor-pointer hover:text-theme">{item.title}</span>
})
setBreadcrumb(newItems)
},
breadcrumb
}}
>
{children}
</BreadcrumbContext.Provider>
)
}
@@ -99,10 +99,31 @@ const mockData = [
icon: 'ic:baseline-bar-chart',
children: [
{
name: '运行视图',
key: 'analytics',
path: '/analytics',
icon: 'ic:baseline-bar-chart',
name: '总览',
key: 'analyticsTotal',
path: '/analytics/total',
icon: 'material-symbols:bar-chart',
access: 'system.analysis.run_view.view'
},
{
name: '服务',
key: 'analyticsSubscriber',
path: '/analytics/subscriber/list',
icon: 'ic:baseline-blinds-closed',
access: 'system.analysis.run_view.view'
},
{
name: '消费者',
key: 'analyticsProvider',
path: '/analytics/provider/list',
icon: 'ic:baseline-apps',
access: 'system.analysis.run_view.view'
},
{
name: 'API',
key: 'analyticsApi',
path: '/analytics/api/list',
icon: 'gravity-ui:plug-connection',
access: 'system.analysis.run_view.view'
}
],
@@ -196,6 +217,20 @@ const mockData = [
key: 'maintenanceCenter',
path: '/datasourcing',
children: [
{
name: 'MCP 服务',
key: 'mcpService',
path: '/mcpService',
icon: 'ph:network-x',
access: 'system.settings.mcp.view'
},
{
name: 'API Key',
key: 'mcpKey',
path: '/mcpKey',
icon: 'material-symbols:key',
access: 'system.settings.apikey.view'
},
{
name: '数据源',
key: 'datasourcing',
@@ -220,6 +220,26 @@ const mockData = {
}
]
},
{
driver: 'apipark.builtIn.component',
name: 'mcpService',
router: [
{
path: 'mcpService',
type: 'normal'
}
]
},
{
driver: 'apipark.builtIn.component',
name: 'mcpKey',
router: [
{
path: 'mcpKey',
type: 'normal'
}
]
},
{
driver: 'apipark.builtIn.component',
name: 'loadBalancing',
@@ -16,7 +16,6 @@
"添加(0)": "Ka7aaaeb",
"请输入Key": "Kaff78ecf",
"请输入Value": "K65d46535",
"返回": "Kc14b2ea3",
"ID": "K11d3633a",
"名称": "Kbff43de3",
"Driver": "K16ca79ef",
@@ -114,6 +113,7 @@
"打开 OpenAPI YAML 编辑器": "Kdac8ce7e",
"无需审核:允许任何消费者调用该服务": "K1fc2cc28",
"人工审核:仅允许通过人工审核的消费者调用该服务": "K8dabb98e",
"开启:AI Agent 等产品能够通过 MCP 方式调用服务": "Ke959f135",
"永久": "Kbfe02d7f",
"否": "K1e9c479e",
"是": "Kaddfcb6b",
@@ -345,10 +345,11 @@
"重置": "K50d471b2",
"查询": "Kee8ae330",
"请输入 APIURL 搜索": "Kf8187c33",
"服务": "Kb58e0c3f",
"说明文档": "K6cd677b",
"最近一次更新者": "K617f34f1",
"最近一次更新时间": "K6ebca204",
"保存": "Kabfe9512",
"服务": "Kb58e0c3f",
"API 路由": "K51d1eb5d",
"API 文档": "Ka2b6d281",
"使用说明": "Kdefa9caa",
@@ -365,6 +366,9 @@
"手动添加": "K18307d56",
"订阅申请": "K705fe9f5",
"订阅方": "K3a67ea90",
"API": "K3ba29a85",
"编辑 API": "Ke93388fd",
"添加 API": "K84aabfd4",
"AI 路由设置": "Kefa2a4cf",
"路由名称": "K66060758",
"请求路径": "K5582ac8",
@@ -414,17 +418,16 @@
"启用": "K52c8a730",
"Ollama 地址": "K6b99dce8",
"输入例如:https://www.apipark.com": "K8d4f5b44",
"自定义": "K8929cbb1",
"自定义(空模板)": "K24f6a5b4",
"模型名称": "K1fd51aaa",
"访问配置": "Kd6285399",
"模型参数模板": "K7eb03edd",
"模型参数": "K49b434e9",
"载入预置模板": "Kea608112",
"供应商名称": "K16ef56b1",
"注意:": "K484de451",
"仅支持使用 OpenAI 输入输出格式和认证方法(APIKey)的供应商。如果不满足此条件,创建后自定义供应商将不可用。": "Kbd80dde0",
"从 (0) 获取 API KEY": "Kb3e34847",
"该模型为官方模型,不可编辑": "Kcb6a1c57",
"存在使用当前模型的接口,需要先解绑后才能编辑": "Kf9300eb4",
"该模型为官方模型,不可删除": "K8af71816",
"存在使用当前模型的接口,需要先解绑后才能删除": "Kb8ad0af5",
"模型值": "K73cb9ff1",
@@ -450,6 +453,7 @@
"Models": "Ke37a353f",
"Keys": "K14bcebd2",
"添加供应商": "Kd87397b0",
"编辑供应商( (0) )": "Kee7de862",
"编辑供应商": "K5bcf8c48",
"(0) 模型": "Kf7a916be",
"待审核": "K35612f29",
@@ -457,7 +461,7 @@
"发布申请": "K56b4254f",
"API 调用地址": "Kea2f9279",
"API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。": "K7fc496a1",
"集成地址": "K508d8bf4",
"OpenAPI & MCP 调用地址": "Ka7ca8fde",
"与外部平台集成时,获取 API 市场中文档信息的域名": "K67f4e9bb",
"常规设置": "K8ab0fc95",
"API 请求设置": "Kb66fec9d",
@@ -469,6 +473,7 @@
"分类名称": "Ke595a20a",
"父分类 ID": "K9679728f",
"子分类名称": "K9b2d08fd",
"暂无权限": "Kce2fcdbf",
"添加 Rest 服务": "K2c93168c",
"导入OpenAPI文档,将现有系统的API发布到APIPark。": "K39a8d392",
"添加在线 AI API": "K68932d54",
@@ -551,6 +556,13 @@
"Version (0)-(1)": "K480045ce",
"日志配置": "Kadee8e49",
"提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K2724314b",
"MCP 配置": "K6e9c928f",
"Open API 文档": "Kb6d0eb39",
"AI 代理集成": "Ke6908f16",
"新增 API Key": "Kb0e0aeda",
"API 密钥可用于调用系统级 Open API 和 MCP。": "K9d81999c",
"MCP 服务": "Kf106bc62",
"MCP Service 充当 AI 模型与 API 之间的桥梁,允许智能助手(如 Claude)动态发现和调用 Gateway 上的 API,无需繁琐的手动配置或自定义集成。": "K7c2bfeff",
"部门名称": "K33c76dbc",
"父部门 ID": "K84829ca9",
"子部门名称": "K4d7fc74b",
@@ -615,6 +627,8 @@
"处理日志": "Ke429194e",
"脱敏前": "K8c34c02f",
"脱敏后": "K8e3d388d",
"编辑服务策略": "Kf06f6737",
"添加服务策略": "K205971e1",
"编辑策略": "Kc82b8374",
"策略类型": "K4b34a5e5",
"匹配条件": "K57f0fee8",
@@ -641,6 +655,7 @@
"支持对系统全局进行统一的策略配置,从而简化管理并确保一致性。全局策略的优先级比服务策略略低。": "Kc975cd5a",
"资源配置": "K8e7a0f80",
"角色": "Kf644225f",
"角色配置": "Kc9f2249c",
"设置角色的权限范围。": "K95c3fd8b",
"系统级别角色": "K138facd3",
"添加角色": "K6eac768d",
@@ -662,9 +677,13 @@
"停止": "K24540de",
"继续等待": "Kd85b3f64",
"只允许上传PNG、JPG或SVG格式的图片": "Ka9c08390",
"关闭 MCP": "K30595880",
"关闭后将无法通过MCP方式调用服务": "Kc081047c",
"了解": "Ka73a5801",
"服务名称": "K413b9869",
"服务类型": "K9919285b",
"REST 服务": "K62840d62",
"MCP": "K373c8ab3",
"默认 AI 供应商": "Kcef64f4d",
"创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API": "K300c89d4",
"未配置任何 AI 模型供应商,": "Kcab588a9",
@@ -811,6 +830,7 @@
"添加授权": "Kd23d1716",
"到期时间": "Kfa920c0",
"订阅的服务": "Kcce1af60",
"返回": "Kc14b2ea3",
"审核详情": "Kfefa9b58",
"取消订阅": "K3118fdb0",
"请确认是否取消订阅?": "Ked811bb1",
@@ -823,22 +843,21 @@
"创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务": "K5c4e2865",
"订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f",
"输入名称、ID 查找消费者": "K3a6f905d",
"服务市场": "K370a3eb2",
"API 门户": "Kc84dbd1a",
"服务详情": "Kf7ec36d",
"申请服务": "K58ca9485",
"介绍": "K59cdbec3",
"Base URL": "Kc29dabf2",
"申请": "K4aa9ed2c",
"服务信息": "K6c060779",
"接入消费者": "Kba74f26d",
"供应方": "Kb97544cb",
"分类": "Kb32f0afe",
"版本": "K81634069",
"更新时间": "Keefda53d",
"无标签": "K96a2f1c8",
"介绍": "K59cdbec3",
"暂无服务描述": "Ka4b45550",
"申请": "K4aa9ed2c",
"无标签": "K96a2f1c8",
"分类": "Kb32f0afe",
"服务市场": "K370a3eb2",
"API 数量": "K72b0c0b3",
"接入消费者数量": "K70b79760",
"30天内调用次数": "K3d52b756",
"关联标签": "K96059c69",
"更新者": "K8b7c2592",
"添加 Open Api": "K32263abd",
@@ -498,7 +498,7 @@
"K370a3eb2": "Service Marketplace",
"Kf7ec36d": "Service Details",
"K58ca9485": "Subscribe",
"K59cdbec3": "Intro",
"K59cdbec3": "Readme",
"K4aa9ed2c": "Subscribe",
"K6c060779": "Service Information",
"Kb97544cb": "Provider",
@@ -898,5 +898,34 @@
"Kce2fcdbf": "No Permission",
"K24f6a5b4": "Custom (Empty Template)",
"Kea608112": "Load Preset Template",
"Kee7de862": "Edit Provider( (0) )"
"Kee7de862": "Edit Provider( (0) )",
"Kb0e0aeda": "New API Key",
"K9d81999c": "The API Key can be used to call system-level Open API and MCP.",
"Ka7ca8fde": "OpenAPI & MCP Invocation Address",
"K6e9c928f": "MCP Config",
"Kb6d0eb39": "Open API Docs",
"Ke6908f16": "Integration to AI Agent",
"Kf106bc62": "MCP Service",
"K7c2bfeff": "MCP Service acts as a bridge between AI models and APIs, enabling intelligent assistants (such as Claude) to dynamically discover and invoke APIs on the Gateway without the need for tedious manual configuration or custom integration.",
"K30595880": "Disable MCP",
"Kc081047c": "After turning it off, you wont be able to use the service through the MCP.",
"K373c8ab3": "MCP",
"K3ba29a85": "API",
"K3d52b756": "Number of invocations within 30 days",
"Ke959f135": "Enable: AI Agent and other products can invoke services through MCP.",
"Ka73a5801": "I Understand",
"K6cd677b": "Documentation",
"Kec68fe24": "Edit API Settings",
"Kc9aeee51": "Add API Settings",
"Kf06f6737": "Edit Service Policy",
"K205971e1": "Add Service Policy",
"Kc9f2249c": "Role Configuration",
"Kba68dfc1": "Add API Settings",
"Kc84dbd1a": "API Portal",
"Ke93388fd": "Edit API",
"K84aabfd4": "Add API",
"K71ed51fa": "Please subscribe to the service first",
"K1bec8cbe": "Select API Key",
"K5611e01e": "This consumer is already subscribed",
"Kaf9e8011": "Overview"
}
@@ -920,5 +920,34 @@
"Kce2fcdbf": "権限がありません",
"K24f6a5b4": "カスタム(空のテンプレート)",
"Kea608112": "プリセットテンプレートを読み込む",
"Kee7de862": "サプライヤーを編集( (0) )"
"Kee7de862": "サプライヤーを編集( (0) )",
"Kb0e0aeda": "APIキーを新規作成",
"K9d81999c": "APIキーは、システムレベルのOpen APIおよびMCPの呼び出しに使用できます。",
"Ka7ca8fde": "OpenAPI & MCP 呼び出しアドレス",
"K6e9c928f": "MCP 設定",
"Kb6d0eb39": "Open API ドキュメント",
"Ke6908f16": "AI プロキシ統合",
"Kf106bc62": "MCP サービス",
"K7c2bfeff": "MCP サービスは、AI モデルと API の間の橋渡し役を果たし、スマートアシスタント(Claude など)が、面倒な手動設定やカスタム統合なしで、ゲートウェイ上の API を動的に発見し、呼び出すことを可能にします。",
"K30595880": "MCP 無効化",
"Kc081047c": "無効化すると、MCP を通じてサービスを呼び出すことができなくなります。",
"K373c8ab3": "MCP",
"K3ba29a85": "API",
"K3d52b756": "30日以内の呼び出し回数",
"Ke959f135": "有効化:AI Agent などの製品が MCP 経由でサービスを呼び出すことができる",
"Ka73a5801": "理解する",
"K6cd677b": "説明書",
"Kec68fe24": "API設定の編集",
"Kc9aeee51": "API設定の追加",
"Kf06f6737": "サービスポリシーの編集",
"K205971e1": "サービスポリシーの追加",
"Kc9f2249c": "役割の設定",
"Kba68dfc1": "API設定の追加",
"Kc84dbd1a": "APIポータル",
"Ke93388fd": "APIの編集",
"K84aabfd4": "APIの追加",
"K71ed51fa": "このサービスに先にサブスクリプションしてください",
"K1bec8cbe": "APIキーを選択してください",
"K5611e01e": "この消費者はすでに購読しています",
"Kaf9e8011": "概要"
}
@@ -44,7 +44,6 @@
"Kd2850420": "待删除",
"K83237c89": "输入的IP或CIDR不符合格式",
"K5ae2c87a": "请正确输入路径,如/usr/*或*/usr/*",
"K508d8bf4": "集成地址",
"K67f4e9bb": "与外部平台集成时,获取 API 市场中文档信息的域名",
"Kc82b8374": "编辑策略",
"K4b34a5e5": "策略类型",
@@ -851,5 +851,34 @@
"Kce2fcdbf": "暂无权限",
"K24f6a5b4": "自定义(空模板)",
"Kea608112": "载入预置模板",
"Kee7de862": "编辑供应商( (0) )"
"Kee7de862": "编辑供应商( (0) )",
"Kb0e0aeda": "新增 API Key",
"K9d81999c": "API 密钥可用于调用系统级 Open API 和 MCP。",
"Ka7ca8fde": "OpenAPI & MCP 调用地址",
"K6e9c928f": "MCP 配置",
"Kb6d0eb39": "Open API 文档",
"Ke6908f16": "AI 代理集成",
"Kf106bc62": "MCP 服务",
"K7c2bfeff": "MCP Service 充当 AI 模型与 API 之间的桥梁,允许智能助手(如 Claude)动态发现和调用 Gateway 上的 API,无需繁琐的手动配置或自定义集成。",
"K30595880": "关闭 MCP",
"Kc081047c": "关闭后将无法通过MCP方式调用服务",
"K373c8ab3": "MCP",
"K3ba29a85": "API",
"K3d52b756": "30天内调用次数",
"Ke959f135": "开启:AI Agent 等产品能够通过 MCP 方式调用服务",
"Ka73a5801": "了解",
"K6cd677b": "说明文档",
"Kec68fe24": "编辑 API 设置",
"Kc9aeee51": "新增 API 设置",
"Kf06f6737": "编辑服务策略",
"K205971e1": "添加服务策略",
"Kc9f2249c": "角色配置",
"Kba68dfc1": "添加 API 设置",
"Kc84dbd1a": "API 门户",
"Ke93388fd": "编辑 API",
"K84aabfd4": "添加 API",
"K71ed51fa": "请先订阅该服务",
"K1bec8cbe": "选择 API Key",
"K5611e01e": "该消费者已订阅",
"Kaf9e8011": "总览"
}
@@ -920,5 +920,34 @@
"Kce2fcdbf": "暫無權限",
"K24f6a5b4": "自訂(空模板)",
"Kea608112": "載入預設模板",
"Kee7de862": "編輯供應商( (0) )"
"Kee7de862": "編輯供應商( (0) )",
"Kb0e0aeda": "新增 API 金鑰",
"K9d81999c": "API 金鑰可用於調用系統級 Open API 和 MCP。",
"Ka7ca8fde": "OpenAPI & MCP 呼叫地址",
"K6e9c928f": "MCP 設定",
"Kb6d0eb39": "Open API 文件",
"Ke6908f16": "AI 代理整合",
"Kf106bc62": "MCP 服務",
"K7c2bfeff": "MCP 服務作為 AI 模型與 API 之間的橋樑,允許智能助手(如 Claude)動態發現並呼叫 Gateway 上的 API,而無需繁瑣的手動設定或自訂整合。",
"K30595880": "關閉 MCP",
"Kc081047c": "關閉後將無法透過 MCP 方式呼叫服務",
"K373c8ab3": "MCP",
"K3ba29a85": "API",
"K3d52b756": "30 天內呼叫次數",
"Ke959f135": "開啟:AI Agent 等產品能夠透過 MCP 方式呼叫服務",
"Ka73a5801": "了解",
"K6cd677b": "說明文檔",
"Kec68fe24": "編輯 API 設定",
"Kc9aeee51": "新增 API 設定",
"Kf06f6737": "編輯服務策略",
"K205971e1": "新增服務策略",
"Kc9f2249c": "角色配置",
"Kba68dfc1": "新增 API 設定",
"Kc84dbd1a": "API 門戶",
"Ke93388fd": "編輯 API",
"K84aabfd4": "新增 API",
"K71ed51fa": "請先訂閱該服務",
"K1bec8cbe": "選擇 API Key",
"K5611e01e": "該消費者已訂閱",
"Kaf9e8011": "總覽"
}
@@ -21,6 +21,7 @@ export type AiServiceConfigFieldType = {
catalogue?:string | string[];
approvalType?:string;
providerType?:string
enable_mcp?: boolean
};
export type AiServiceSubServiceTableListItem = {
@@ -800,6 +800,22 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
]
}
],
[
'mcpService',
{
type: 'module',
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/mcpService/McpServiceContainer')),
key: 'mcpService'
}
],
[
'mcpKey',
{
type: 'module',
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/mcpService/McpKeyContainer')),
key: 'mcpKey'
}
],
[
'loadBalancing',
{
@@ -85,7 +85,7 @@ export const SYSTEM_TABLE_COLUMNS: PageProColumns<SystemTableListItem>[] = [
title: '服务名称',
dataIndex: 'name',
ellipsis: true,
width: 160,
width: 220,
fixed: 'left',
sorter: (a, b) => {
return a.name.localeCompare(b.name)
@@ -100,24 +100,20 @@ export const SYSTEM_TABLE_COLUMNS: PageProColumns<SystemTableListItem>[] = [
{
title: '类型',
dataIndex: 'service_kind',
width: 140,
width: 120,
ellipsis: true
},
{
title: '所属团队',
dataIndex: ['team', 'name'],
ellipsis: true
},
{
title: '状态',
width: 140,
dataIndex: 'state',
ellipsis: true
ellipsis: true,
width: 200
},
{
title: 'API 数量',
dataIndex: 'apiNum',
ellipsis: true,
width: 140,
sorter: (a, b) => {
return a.apiNum - b.apiNum
}
@@ -362,6 +358,10 @@ export const SERVICE_APPROVAL_OPTIONS = [
{ label: '无需审核:允许任何消费者调用该服务', value: 'auto' },
{ label: '人工审核:仅允许通过人工审核的消费者调用该服务', value: 'manual' }
]
export const MCP_OPTIONS = [
{ label: '禁用', value: false },
{ label: '开启:AI Agent 等产品能够通过 MCP 方式调用服务', value: true }
]
export const SERVICE_KIND_OPTIONS = [
{ label: 'REST', value: 'rest' },
{ label: 'AI', value: 'ai' }
@@ -31,6 +31,7 @@ export type SystemConfigFieldType = {
catalogue?:string | string[];
approvalType?:string;
modelMapping?: string;
enable_mcp?: boolean;
};
export type SystemSubServiceTableListItem = {
+37
View File
@@ -1109,6 +1109,11 @@ p{
width: 16px !important;
justify-content:center;
}
.ant-select .ant-select-clear {
height:16px !important;
width: 16px !important;
top: 45%;
}
.ant-table-wrapper .ant-table{
scrollbar-color: none !important;
@@ -1213,6 +1218,38 @@ p{
display: none;
}
/* 将折叠图标移到右侧 */
.service-hub-custom-switcher .ant-tree-switcher {
position: absolute !important;
right: 0 !important;
left: auto !important;
z-index: 10 !important;
}
/* 设置节点内容宽度 */
.service-hub-custom-switcher .ant-tree-node-content-wrapper {
width: calc(100% - 24px) !important;
padding-left: 8px !important;
padding-right: 24px !important;
box-sizing: border-box !important;
}
/* 强制控制标题元素的样式 */
.service-hub-custom-switcher .ant-tree-title {
display: inline-block !important;
width: calc(100% - 10px) !important;
overflow: hidden !important;
white-space: nowrap !important;
text-overflow: ellipsis !important;
vertical-align: middle !important;
}
/* 确保选中框的间距 */
.service-hub-custom-switcher .ant-tree-checkbox {
margin-right: 8px !important;
}
.no-selected-tree .ant-tree-node-selected{
background-color: transparent !important;
}
@@ -1,145 +1,203 @@
import { Editor } from '@tinymce/tinymce-react';
import hljs from 'highlight.js';
import 'highlight.js/styles/default.css';
import {useEffect, useState} from "react";
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
import {App, Button} from "antd";
import { EntityItem } from '@common/const/type.ts';
import WithPermission from '@common/components/aoplatform/WithPermission.tsx';
import { RouterParams } from '@core/components/aoplatform/RenderRoutes';
import { useParams } from 'react-router-dom';
import { $t } from '@common/locales';
const ServiceInsideDocument = ()=>{
const { message } = App.useApp()
const [updater,setUpdater] = useState<string>()
const [updateTime,setUpdateTime]=useState<string>()
const [initDoc, setInitDoc] = useState<string>()
const [doc, setDoc] = useState<string>()
const {fetchData} = useFetch()
const { serviceId, teamId} = useParams<RouterParams>();
import { Editor } from '@tinymce/tinymce-react'
import hljs from 'highlight.js'
import 'highlight.js/styles/default.css'
import { useEffect, useState } from 'react'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { useFetch } from '@common/hooks/http.ts'
import { App, Button } from 'antd'
import { EntityItem } from '@common/const/type.ts'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes'
import { useNavigate, useParams } from 'react-router-dom'
import { $t } from '@common/locales'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
const ServiceInsideDocument = () => {
const { message } = App.useApp()
const [updater, setUpdater] = useState<string>()
const [updateTime, setUpdateTime] = useState<string>()
const [initDoc, setInitDoc] = useState<string>()
const [doc, setDoc] = useState<string>()
const { fetchData } = useFetch()
const { serviceId, teamId } = useParams<RouterParams>()
const { setBreadcrumb } = useBreadcrumb()
const navigator = useNavigate()
const save = ()=>{
fetchData<BasicResponse<{service:{ id:string,name:string,updater:string,updateTime:string, doc:string} }>>('service/doc',{method:'PUT',eoBody:({doc:doc}) ,eoParams:{service:serviceId,team:teamId},eoTransformKeys:['update_time']}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
getServiceDoc()
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
const handleEditorChange = (content:string, editor:unknown) => {
setDoc(content)
};
const setupEditor = (editor:unknown) => {
editor.on('init', () => {
editor.contentDocument.querySelectorAll('pre code').forEach((block:HTMLElement) => {
hljs.highlightBlock(block);
});
});
editor.on('SetContent', () => {
editor.contentDocument.querySelectorAll('pre code').forEach((block:HTMLElement) => {
hljs.highlightBlock(block);
});
});
};
const getServiceDoc = ()=>{
fetchData<BasicResponse<{doc:{ id:string,name:string,updater:EntityItem,updateTime:string,creater:EntityItem, doc:string} }>>('service/doc',{method:'GET',eoParams:{service:serviceId,team:teamId},eoTransformKeys:['update_time']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setUpdater(data.doc.updater.id === '' ? '-' : data.doc.updater.name)
setUpdateTime(data.doc.updater.id === '' ? '-' : data.doc.updateTime)
setInitDoc(data.doc.doc)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
useEffect(() => {
const save = () => {
fetchData<
BasicResponse<{ service: { id: string; name: string; updater: string; updateTime: string; doc: string } }>
>('service/doc', {
method: 'PUT',
eoBody: { doc: doc },
eoParams: { service: serviceId, team: teamId },
eoTransformKeys: ['update_time']
}).then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
getServiceDoc()
}, []);
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
return (
<div className="flex flex-col h-full border-[1px] rounded-[10px] border-BORDER border-solid mr-PAGE_INSIDE_X">
<Editor
tinymceScriptSrc={'/tinymce/tinymce.min.js'}
initialValue={initDoc}
init={{
height: '100%',
menubar: false,
plugins: [
'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview', 'anchor', 'pagebreak',
'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'codesample', 'fullscreen', 'insertdatetime',
'media', 'table', 'emoticons', 'help'
], toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | codesample |table|' +
'bullist numlist outdent indent | link image | print preview media fullscreen | ' +
'forecolor backcolor emoticons | help',
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px; } img { max-width: 100%; }',
setup: setupEditor,
codesample_languages:[
{
text: 'HTML/XML',
value: 'markup'
},
{
text: 'JavaScript',
value: 'javascript'
},
{
text: 'CSS',
value: 'css'
},
{
text: 'PHP',
value: 'php'
},
{
text: 'Ruby',
value: 'ruby'
},
{
text:'GO',
value:'go'
},
{
text: 'Python',
value: 'python'
},
{
text: 'Java',
value: 'java'
},
{
text: 'C',
value: 'c'
},
{
text: 'C#',
value: 'csharp'
},
{
text: 'C++',
value: 'cpp'
},
{ text: 'Bash/Shell', value: 'bash' },
{ text: 'SQL', value: 'sql' }
]
}}
onEditorChange={handleEditorChange}
/>
<div className=" pl-[8px] py-btnbase ">
<div className="flex justify-between items-center">
<p className="text-[14px] leading-[20px] text-[#999999]"><span className="mr-[20px]">{$t('最近一次更新者')}{updater || '-'}</span><span>{$t('最近一次更新时间')}{updateTime || '-'}</span></p>
<WithPermission access="team.service.service_intro.edit"><Button type="primary" className="mr-btnbase" onClick={save}>{$t('保存')}</Button></WithPermission>
</div>
</div>
</div>)
const handleEditorChange = (content: string, editor: unknown) => {
setDoc(content)
}
const setupEditor = (editor: unknown) => {
editor.on('init', () => {
editor.contentDocument.querySelectorAll('pre code').forEach((block: HTMLElement) => {
hljs.highlightBlock(block)
})
})
editor.on('SetContent', () => {
editor.contentDocument.querySelectorAll('pre code').forEach((block: HTMLElement) => {
hljs.highlightBlock(block)
})
})
}
const getServiceDoc = () => {
fetchData<
BasicResponse<{
doc: { id: string; name: string; updater: EntityItem; updateTime: string; creater: EntityItem; doc: string }
}>
>('service/doc', {
method: 'GET',
eoParams: { service: serviceId, team: teamId },
eoTransformKeys: ['update_time']
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setUpdater(data.doc.updater.id === '' ? '-' : data.doc.updater.name)
setUpdateTime(data.doc.updater.id === '' ? '-' : data.doc.updateTime)
setInitDoc(data.doc.doc)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('使用说明')
}
])
getServiceDoc()
}, [])
return (
<div className="flex flex-col h-full border-[1px] rounded-[10px] border-BORDER border-solid mr-PAGE_INSIDE_X">
<Editor
tinymceScriptSrc={'/tinymce/tinymce.min.js'}
initialValue={initDoc}
init={{
height: '100%',
menubar: false,
plugins: [
'advlist',
'autolink',
'link',
'image',
'lists',
'charmap',
'preview',
'anchor',
'pagebreak',
'searchreplace',
'wordcount',
'visualblocks',
'visualchars',
'codesample',
'fullscreen',
'insertdatetime',
'media',
'table',
'emoticons',
'help'
],
toolbar:
'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | codesample |table|' +
'bullist numlist outdent indent | link image | print preview media fullscreen | ' +
'forecolor backcolor emoticons | help',
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px; } img { max-width: 100%; }',
setup: setupEditor,
codesample_languages: [
{
text: 'HTML/XML',
value: 'markup'
},
{
text: 'JavaScript',
value: 'javascript'
},
{
text: 'CSS',
value: 'css'
},
{
text: 'PHP',
value: 'php'
},
{
text: 'Ruby',
value: 'ruby'
},
{
text: 'GO',
value: 'go'
},
{
text: 'Python',
value: 'python'
},
{
text: 'Java',
value: 'java'
},
{
text: 'C',
value: 'c'
},
{
text: 'C#',
value: 'csharp'
},
{
text: 'C++',
value: 'cpp'
},
{ text: 'Bash/Shell', value: 'bash' },
{ text: 'SQL', value: 'sql' }
]
}}
onEditorChange={handleEditorChange}
/>
<div className=" pl-[8px] py-btnbase ">
<div className="flex justify-between items-center">
<p className="text-[14px] leading-[20px] text-[#999999]">
<span className="mr-[20px]">
{$t('最近一次更新者')}{updater || '-'}
</span>
<span>
{$t('最近一次更新时间')}{updateTime || '-'}
</span>
</p>
<WithPermission access="team.service.service_intro.edit">
<Button type="primary" className="mr-btnbase" onClick={save}>
{$t('保存')}
</Button>
</WithPermission>
</div>
</div>
</div>
)
}
export default ServiceInsideDocument
export default ServiceInsideDocument
@@ -221,6 +221,10 @@ const AiServiceInsidePage: FC = () => {
useEffect(() => {
serviceId && getAiServiceInfo()
}, [serviceId])
// 创建一个回调函数
const onSaveCallback = () => {
getAiServiceInfo()
}
return (
<>
@@ -228,6 +232,7 @@ const AiServiceInsidePage: FC = () => {
<InsidePage
pageTitle={aiServiceInfo?.name || '-'}
tagList={[
...(aiServiceInfo?.enable_mcp ? [{ label: 'MCP', color: '#FFF0C1', className: 'text-[#000]' }] : []),
{
label: (
<Paragraph className="mb-0" copyable={serviceId ? { text: serviceId } : false}>
@@ -250,7 +255,7 @@ const AiServiceInsidePage: FC = () => {
<div
className={` ${['setting', 'upstream'].indexOf(activeMenu!) !== -1 ? '' : ''} w-full h-full flex flex-1 flex-col overflow-auto bg-MAIN_BG pt-[20px] pl-[20px] pb-PAGE_INSIDE_B `}
>
<Outlet />
<Outlet context={{ onSaveComplete: onSaveCallback }} />
</div>
</div>
</InsidePage>
@@ -1,6 +1,6 @@
import {ActionType} from "@ant-design/pro-components";
import {FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import {Link, useParams} from "react-router-dom";
import {Link, useNavigate, useParams} from "react-router-dom";
import {App, Form,TreeSelect} from "antd";
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
import {useFetch} from "@common/hooks/http.ts";
@@ -26,6 +26,7 @@ const AiServiceInsideSubscriber:FC = ()=>{
const pageListRef = useRef<ActionType>(null);
const [memberValueEnum, setMemberValueEnum] = useState<SimpleMemberItem[]>([])
const {accessData,state} = useGlobalContext()
const navigator = useNavigate()
const getAiServiceSubscriber = ()=>{
return fetchData<BasicResponse<{subscribers:AiServiceSubscriberTableListItem[]}>>('service/subscribers',{method:'GET',eoParams:{service:serviceId,team:teamId},eoTransformKeys:['apply_time']}).then(response=>{
const {code,data,msg} = response
@@ -121,7 +122,8 @@ const AiServiceInsideSubscriber:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('订阅方管理')
@@ -1,58 +1,84 @@
import {forwardRef, useEffect, useState} from "react";
import { Empty, Spin, message} from "antd";
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
import { LoadingOutlined } from "@ant-design/icons";
import { forwardRef, useEffect, useState } from 'react'
import { Empty, Spin, message } from 'antd'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { useFetch } from '@common/hooks/http.ts'
import { LoadingOutlined } from '@ant-design/icons'
import EmptySVG from '@common/assets/empty.svg'
import { $t } from "@common/locales/index.ts";
import { $t } from '@common/locales/index.ts'
import ApiDocument from '@common/components/aoplatform/ApiDocument.tsx'
import { useParams } from "react-router-dom";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx";
import { AiServiceInsideApiDocumentHandle, AiServiceInsideApiDocumentProps, AiServiceApiDetail } from "@core/const/ai-service/type.ts";
import { useNavigate, useParams } from 'react-router-dom'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import {
AiServiceInsideApiDocumentHandle,
AiServiceInsideApiDocumentProps,
AiServiceApiDetail
} from '@core/const/ai-service/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
const AiServiceInsideApiDocument = forwardRef<AiServiceInsideApiDocumentHandle,AiServiceInsideApiDocumentProps>(() => {
const {serviceId, teamId} = useParams<RouterParams>()
const {fetchData} = useFetch()
const [apiDetail, setApiDetail] = useState<AiServiceApiDetail>()
const [loading, setLoading] = useState<boolean>(false)
useEffect(() => {
getApiDetail()
}, []);
const AiServiceInsideApiDocument = forwardRef<AiServiceInsideApiDocumentHandle, AiServiceInsideApiDocumentProps>(() => {
const { serviceId, teamId } = useParams<RouterParams>()
const { fetchData } = useFetch()
const [apiDetail, setApiDetail] = useState<AiServiceApiDetail>()
const [loading, setLoading] = useState<boolean>(false)
const { setBreadcrumb } = useBreadcrumb()
const navigator = useNavigate()
const getApiDetail = ()=>{
setLoading(true)
fetchData<BasicResponse<{doc:AiServiceApiDetail}>>('service/api_doc',{method:'GET',eoParams:{service:serviceId,team:teamId },eoTransformKeys:['update_time']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setApiDetail(data.doc?.content)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
}).finally(()=>{setLoading(false)})
}
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('API 文档')
}
])
getApiDetail()
}, [])
const getApiDetail = () => {
setLoading(true)
fetchData<BasicResponse<{ doc: AiServiceApiDetail }>>('service/api_doc', {
method: 'GET',
eoParams: { service: serviceId, team: teamId },
eoTransformKeys: ['update_time']
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setApiDetail(data.doc?.content)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
.finally(() => {
setLoading(false)
})
}
const ApiPreview = ({spec}:{spec?:string | object})=>{
return (
<div className="h-full overflow-hidden">
<div className="flex-1 h-full overflow-auto pr-PAGE_INSIDE_X">
<ApiDocument spec={spec}/>
</div>
const ApiPreview = ({ spec }: { spec?: string | object }) => {
return (
<div className="h-full overflow-hidden">
<div className="flex-1 h-full overflow-auto pr-PAGE_INSIDE_X">
<ApiDocument spec={spec} />
</div>
)
}
</div>
)
}
return (<>
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading} wrapperClassName=' h-full overflow-hidden '>
<div className=" h-full ai-service-api-preview">
{ apiDetail ? <ApiPreview spec={apiDetail} />
: <Empty image={EmptySVG} >
</Empty>}
</div>
</Spin>
</>)
return (
<>
<Spin
indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
spinning={loading}
wrapperClassName=" h-full overflow-hidden "
>
<div className=" h-full ai-service-api-preview">
{apiDetail ? <ApiPreview spec={apiDetail} /> : <Empty image={EmptySVG}></Empty>}
</div>
</Spin>
</>
)
})
export default AiServiceInsideApiDocument
export default AiServiceInsideApiDocument
@@ -21,6 +21,7 @@ import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import AiServiceRouterModelConfig, { AiServiceRouterModelConfigHandle } from './AiServiceInsideRouterModelConfig'
import { AiProviderDefaultConfig, AiProviderLlmsItems } from '@core/pages/aiSetting/types'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
type AiServiceRouterField = {
name: string
@@ -66,6 +67,7 @@ const AiServiceInsideRouterCreate = () => {
const [variablesTableRef, setVariablesTableRef] = useState<MutableRefObject<EditableFormInstance<T> | undefined>>()
const { state } = useGlobalContext()
const [resultPath, setResultPath] = useState<string>('')
const { setBreadcrumb } = useBreadcrumb()
const onFinish = () => {
return variablesTableRef?.current
@@ -289,6 +291,19 @@ const AiServiceInsideRouterCreate = () => {
}
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('API'),
onClick: () => navigator(backUrl)
},
{
title: routeId ? $t('编辑 API') : $t('添加 API')
}
])
!routeId && aiServiceInfo?.provider && getDefaultModelConfig()
}, [aiServiceInfo])
@@ -363,11 +378,6 @@ const AiServiceInsideRouterCreate = () => {
setDrawerType(undefined)
}
const apiPathMatchRulesOptions = useMemo(
() => API_PATH_MATCH_RULES.map((x) => ({ label: $t(x.label), value: x.value })),
[state.language]
)
return (
<InsidePage
pageTitle={$t('AI 路由设置') || '-'}
@@ -158,18 +158,21 @@ const AiServiceInsideRouterList: FC = () => {
}
}
useEffect(() => {
getMemberList()
manualReloadTable()
}, [serviceId])
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('路由')
}
])
getMemberList()
manualReloadTable()
}, [serviceId])
}, [state.language])
const columns = useMemo(() => {
return [...AI_SERVICE_ROUTER_TABLE_COLUMNS].map((x) => {
@@ -163,6 +163,8 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
>
<Form.Item<AiServiceRouterModelConfigField> label={$t('模型类型')} name="type" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={modelTypeList}
@@ -1,7 +1,7 @@
import {ActionType} from "@ant-design/pro-components";
import {FC, useEffect, useMemo, useRef, useState} from "react";
import {Link, useLocation, useParams} from "react-router-dom";
import {Link, useLocation, useNavigate, useParams} from "react-router-dom";
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx";
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
import {App, Button} from "antd";
@@ -40,6 +40,7 @@ const AiServiceInsideApprovalList:FC = ()=>{
const [approvalBtnLoading,setApprovalBtnLoading] = useState<boolean>(false)
const [memberValueEnum, setMemberValueEnum] = useState<SimpleMemberItem[]>([])
const {accessData,state} = useGlobalContext()
const navigator = useNavigate()
const openModal = async (type:'approval'|'view',entity:SubscribeApprovalTableListItem)=>{
message.loading($t(RESPONSE_TIPS.loading))
@@ -143,7 +144,8 @@ const AiServiceInsideApprovalList:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('订阅审核')
@@ -28,7 +28,8 @@ const AiServiceInsidePublic:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigateTo('/service/list')
},
{
title:$t('发布')
@@ -1,7 +1,7 @@
import { ActionType, ParamsType } from "@ant-design/pro-components";
import { App, Button, Divider } from "antd";
import { useState, useRef, useEffect, useMemo, FC } from "react";
import { useParams, Link, useLocation } from "react-router-dom";
import { useParams, Link, useLocation, useNavigate } from "react-router-dom";
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList";
import { PublishApprovalModalContent } from "@common/components/aoplatform/PublishApprovalModalContent";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
@@ -45,6 +45,7 @@ const AiServiceInsidePublicList:FC = ()=>{
const [drawerData, setDrawerData] = useState<PublishTableListItem|PublishVersionTableListItem >({} as PublishTableListItem)
const [drawerOkTitle, setDrawerOkTitle] = useState<string>('确认')
const [isOkToPublish, setIsOkToPublish] = useState<boolean>(false)
const navigator = useNavigate()
const getAiServicePublishList = (params?: ParamsType & {
pageSize?: number | undefined;
current?: number | undefined;
@@ -352,10 +353,11 @@ const AiServiceInsidePublicList:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('发布')
title: $t('发布')
}
])
getMemberList()
@@ -390,6 +390,8 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
{source === 'guide' && (
<Form.Item label={$t('所属团队')} name="team" className="mt-[16px]" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={teamList}
@@ -86,9 +86,9 @@ export default function ApiRequestSetting() {
</Form.Item>
<Form.Item<ApiRequestSettingFieldType>
label={$t('集成地址')}
label={$t('OpenAPI & MCP 调用地址')}
name="sitePrefix"
rules={[{ whitespace: true }]}
rules={[{ required: true, whitespace: true }]}
extra={$t('与外部平台集成时,获取 API 市场中文档信息的域名')}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
@@ -181,6 +181,8 @@ const LocalAiDeploy = forwardRef<LocalAiDeployHandle, any>((props: any, ref: any
</Form.Item>
<Form.Item label={$t('所属团队')} name="team" className="mt-[16px]" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={teamList}
@@ -106,6 +106,8 @@ const RestAIDeploy = forwardRef<RestAIDeployHandle, any>((props: any, ref: any)
</Form.Item>
<Form.Item label={$t('所属团队')} name="team" className="mt-[16px]" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={teamList}
@@ -171,6 +171,8 @@ const AddLoadBalancingModel = forwardRef<LoadBalancingHandle>((props, ref: any)
>
<Form.Item<LoadModelDetailData> label={$t('模型类型')} name="type" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={modelTypeList}
@@ -0,0 +1,101 @@
import { App, Form, Input } from 'antd'
import { $t } from '@common/locales'
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { v4 as uuidv4 } from 'uuid'
import { forwardRef, useEffect, useImperativeHandle } from 'react'
type modelFieldType = {
name: string
type: string
model_parameters: string
access_configuration: string
}
export type addMcpKeysHandle = {
save: () => Promise<boolean | string>
}
type addMcpKeysProps = {
name?: string
value?: string
type?: string
apikey?: string
}
const AddMcpKey = forwardRef<addMcpKeysHandle, addMcpKeysProps>((props, ref) => {
const { name = '', value: editValue = '', type = 'new', apikey = '' } = props
const [form] = Form.useForm()
const { message } = App.useApp()
const { fetchData } = useFetch()
useEffect(() => {
form.setFieldsValue({
name,
value: editValue
})
}, [])
/**
*
* @returns
*/
const save: () => Promise<boolean | string> = () => {
return new Promise((resolve, reject) => {
try {
form
.validateFields()
.then((value) => {
console.log('value', value)
const finalValue = {
...value,
value: editValue ? editValue : uuidv4(),
expired: 0
}
fetchData<BasicResponse<any>>('system/apikey', {
method: type === 'new' ? 'POST' : 'PUT',
eoBody: finalValue,
...(type === 'edit' ? {
eoParams: { apikey }
} : {})
})
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success($t(RESPONSE_TIPS.success) || msg)
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => reject(errorInfo))
})
.catch((errorInfo) => reject(errorInfo))
} catch (error) {
reject(error)
}
})
}
useImperativeHandle(ref, () => ({
save
}))
return (
<Form
form={form}
layout="vertical"
labelAlign="left"
scrollToFirstError
className="flex flex-col mx-auto h-full"
name="mcpKeyModalConfig"
autoComplete="off"
>
<Form.Item<modelFieldType> label={$t('名称')} name="name" rules={[{ required: true }]}>
<Input autoFocus className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
</Form>
)
})
export default AddMcpKey
@@ -0,0 +1,601 @@
import { App, Button, Card, CascaderProps, Empty, Select } from 'antd'
import { $t } from '@common/locales/index.ts'
import { Icon } from '@iconify/react/dist/iconify.js'
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react'
import ReactJson from 'react-json-view'
import { IconButton } from '@common/components/postcat/api/IconButton'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { useConnection } from './hook/useConnection'
import { ClientRequest, Tool, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'
import { z } from 'zod'
import { useNavigate } from 'react-router-dom'
import { ServiceDetailType } from '@market/const/serviceHub/type'
import useCopyToClipboard from '@common/hooks/copy'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
import { Cascader } from 'antd/lib'
type ConfigList = {
openApi?: {
title: string
configContent: string
apiKeys: string[]
}
mcp: {
title: string
configContent: string
apiKeys: string[]
}
}
type ApiKeyItem = {
expired: number
id: string
name: string
value: string
}
interface Option {
value: string
label: string
children?: Option[]
}
type ServiceApiKeyList = {
id: string
name: string
apikeys: Array<{
id: string
name: string
value: string
expired: number
}>
}
export interface IntegrationAIContainerRef {
getServiceKeysList: () => void;
}
export interface IntegrationAIContainerProps {
type: 'global' | 'service'
handleToolsChange: (value: Tool[]) => void
customClassName?: string
service?: ServiceDetailType
serviceId?: string
currentTab?: string
openModal?: (type: 'apply') => void
}
export const IntegrationAIContainer = forwardRef<IntegrationAIContainerRef, IntegrationAIContainerProps>(
({
type,
handleToolsChange,
customClassName,
service,
serviceId,
currentTab,
openModal
}: IntegrationAIContainerProps, ref) => {
/** 当前激活的标签 */
const [activeTab, setActiveTab] = useState(type === 'service' ? 'openApi' : 'mcp')
/** 弹窗组件 */
const { message } = App.useApp()
/** 配置内容 */
const [configContent, setConfigContent] = useState<string>('')
/** 当前选中 API Key */
const [apiKey, setApiKey] = useState<string>('')
/** API Key 列表 */
const [apiKeyList, setApiKeyList] = useState<any[]>([])
/** Cascader Key 列表 */
const [cascaderKeyList, setCascaderKeyList] = useState<string[]>([])
/** MCP 服务器地址 */
const [mcpServerUrl, setMcpServerUrl] = useState<string>('')
/** 全局状态 */
const { state } = useGlobalContext()
const navigator = useNavigate()
/** 复制组件 */
const { copyToClipboard } = useCopyToClipboard()
/** 错误提示 */
const [errors, setErrors] = useState<Record<string, string | null>>({
resources: null,
prompts: null,
tools: null
})
/** 标签内容 */
const [tabContent, setTabContent] = useState<ConfigList>({
mcp: {
title: $t('MCP 配置'),
configContent: '',
apiKeys: []
}
})
/** HTTP 请求 */
const { fetchData } = useFetch()
/**
*
*/
const initTabsData = () => {
const params: ConfigList = {
mcp: {
title: $t('MCP 配置'),
configContent: service?.mcpAccessConfig || '',
apiKeys: []
}
}
if (type === 'service') {
params.openApi = {
title: $t('Open API 文档'),
configContent: service?.openapiAddress || '',
apiKeys: []
}
}
setTabContent(params)
}
/**
*
* @param value
* @returns
*/
const handleCopy = async (value: string): Promise<void> => {
if (value) {
copyToClipboard(value)
message.success($t(RESPONSE_TIPS.copySuccess))
}
}
/**
* API Key
* @param value
*/
const handleSelectChange = (value: string) => {
setApiKey(value)
}
/**
* Cascader
* @param value
*/
const handleCascaderChange: CascaderProps<Option>['onChange'] = (value) => {
setApiKey(value.at(-1) || '')
setCascaderKeyList(value)
}
/**
* MCP
* @returns
*/
const getGlobalMcpConfig = () => {
fetchData<BasicResponse<null>>('global/mcp/config', {
method: 'GET'
})
.then((response) => {
const { code, msg, data } = response
if (code === STATUS_CODE.SUCCESS) {
setTabContent((prevTabContent) => ({
...prevTabContent,
mcp: {
...prevTabContent.mcp,
configContent: data.config || ''
}
}))
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => {
message.error(errorInfo || $t(RESPONSE_TIPS.error))
})
}
/**
* MCP
*/
const addKey = () => {
navigator('/mcpKey')
}
/**
* API Key
*/
const getGlobalKeysList = () => {
fetchData<BasicResponse<null>>('simple/system/apikeys', {
method: 'GET'
})
.then((response) => {
const { code, msg, data } = response
if (code === STATUS_CODE.SUCCESS) {
if (data.apikeys && data.apikeys.length > 0) {
setApiKeyList(
data.apikeys.map((item: ApiKeyItem) => {
return {
label: item.name,
value: item.value
}
})
)
setApiKey(data.apikeys[0].value)
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => {
message.error(errorInfo || $t(RESPONSE_TIPS.error))
})
}
/**
* API Key
*/
useImperativeHandle(ref, () => ({
getServiceKeysList
}))
/**
* API Key
*/
const getServiceKeysList = () => {
fetchData<BasicResponse<null>>(`my/app/apikeys`, {
method: 'GET',
eoParams: { service: serviceId }
})
.then((response) => {
const { code, msg, data } = response
if (code === STATUS_CODE.SUCCESS) {
if (data.apps && data.apps.length > 0) {
// 转换数据结构为 Cascader 所需格式
const transformedData = data.apps.map((app: ServiceApiKeyList) => ({
value: app.id,
label: app.name,
children: app.apikeys.map((key) => ({
...key,
label: key.name
}))
}))
setApiKeyList(transformedData)
if (data.apps[0].apikeys?.length) {
setApiKey(data.apps[0].apikeys[0].value)
setCascaderKeyList([data.apps[0].id, data.apps[0].apikeys[0].value])
}
}
}
})
.catch((errorInfo) => {
message.error(errorInfo || $t(RESPONSE_TIPS.error))
})
}
/**
*
*/
const clearError = (tabKey: keyof typeof errors) => {
setErrors((prev) => ({ ...prev, [tabKey]: null }))
}
/**
*
*/
const makeRequest = async <T extends z.ZodType>(request: ClientRequest, schema: T, tabKey?: keyof typeof errors) => {
try {
const response = await makeConnectionRequest(request, schema)
if (tabKey !== undefined) {
clearError(tabKey)
}
return response
} catch (e) {
const errorString = (e as Error).message ?? String(e)
if (tabKey !== undefined) {
setErrors((prev) => ({
...prev,
[tabKey]: errorString
}))
}
throw e
}
}
/**
* MCP tools
*/
const listTools = async () => {
const response = await makeRequest(
{
method: 'tools/list' as const,
params: {}
},
ListToolsResultSchema,
'tools'
)
handleToolsChange(response.tools)
}
/**
* mcp
*/
const {
connectionStatus,
serverCapabilities,
mcpClient,
requestHistory,
makeRequest: makeConnectionRequest,
sendNotification,
handleCompletion,
completionsSupported,
connect: connectMcpServer,
disconnect: disconnectMcpServer
} = useConnection({
transportType: 'sse',
sseUrl: '',
proxyServerUrl: mcpServerUrl,
requestTimeout: 1000
})
// 使用 useRef 保存最新的连接状态和断开函数
const connectionStatusRef = useRef(connectionStatus)
const disconnectFnRef = useRef(disconnectMcpServer)
// 当连接状态或断开函数变化时更新 ref
useEffect(() => {
connectionStatusRef.current = connectionStatus
disconnectFnRef.current = disconnectMcpServer
}, [connectionStatus, disconnectMcpServer])
/**
*
*/
const setupComponent = () => {
initTabsData()
if (type === 'global') {
getGlobalMcpConfig()
setMcpServerUrl('mcp/global/sse')
getGlobalKeysList()
} else {
service?.basic.enableMcp && setMcpServerUrl(`mcp/service/${serviceId}/sse`)
getServiceKeysList()
}
}
/**
*
*/
useEffect(() => {
setupComponent()
}, [service])
/**
*
*/
useEffect(() => {
initTabsData()
type === 'global' && getGlobalMcpConfig()
}, [state.language])
/**
*
*/
useEffect(() => {
if (type === 'service') {
currentTab === 'MCP' ? setActiveTab('mcp') : setActiveTab('openApi')
}
}, [currentTab])
/**
*
*/
useEffect(() => {
// 返回清理函数,只会在组件卸载时执行
return () => {
try {
// 使用 ref 中保存的最新函数强制断开连接
const disconnectFn = disconnectFnRef.current
if (disconnectFn) {
disconnectFn()
}
} catch (err) {
console.error('断开连接时出错:', err)
}
}
}, [type])
/**
*
*/
useEffect(() => {
if (activeTab === 'openApi' && tabContent?.openApi?.configContent) {
setConfigContent(tabContent?.openApi?.configContent)
} else if (activeTab === 'mcp' && tabContent?.mcp?.configContent) {
setConfigContent(tabContent.mcp.configContent?.replace('{your_api_key}', apiKey || '{your_api_key}'))
}
}, [service, apiKey, activeTab, tabContent])
/**
* MCP
*/
useEffect(() => {
if (mcpServerUrl) {
if (connectionStatus === 'connected') {
disconnectMcpServer()
}
connectMcpServer()
}
}, [mcpServerUrl, ...(type === 'global' ? [state.language] : [])])
/**
* MCP tools
*/
useEffect(() => {
if (connectionStatus === 'connected') {
listTools()
}
}, [connectionStatus])
return (
<>
<Card
style={{ borderRadius: '10px' }}
className={`w-[400px] h-fit ${customClassName}`}
classNames={{
body: 'p-[10px]'
}}
>
<p>
<Icon
icon="icon-park-solid:connection-point-two"
className="align-text-bottom mr-[5px]"
width="16"
height="16"
/>
{$t('AI 代理集成')}
</p>
{type === 'service' && service?.basic.enableMcp && (
<div className="mt-3 tab-nav flex rounded-md overflow-hidden border border-solid border-[#3D46F2] w-fit">
<div
className={`tab-item px-5 py-1.5 cursor-pointer text-sm transition-colors ${activeTab === 'openApi' ? 'bg-[#3D46F2] text-white' : 'bg-white text-[#3D46F2]'}`}
onClick={() => setActiveTab('openApi')}
>
Open API
</div>
<div
className={`tab-item px-5 py-1.5 cursor-pointer text-sm transition-colors ${activeTab === 'mcp' ? 'bg-[#3D46F2] text-white' : 'bg-white text-[#3D46F2]'}`}
onClick={() => setActiveTab('mcp')}
>
MCP
</div>
</div>
)}
{type === 'service' && !apiKeyList.length ? (
<>
<Card
style={{ borderRadius: '10px' }}
className={`w-full mt-3`}
classNames={{
body: 'p-[10px]'
}}
>
<div className="flex flex-col items-center justify-center py-3">
<span className="text-[14px] mb-5">{$t('请先订阅该服务')}</span>
<Button type="primary" onClick={() => openModal?.('apply')}>
{$t('申请')}
</Button>
</div>
</Card>
</>
) : (
<>
<div className="tab-container mt-3">
<div className="tab-content font-semibold mt-[10px]">
{activeTab === 'openApi' ? tabContent.openApi?.title : tabContent.mcp.title}
</div>
{/* 标签页内容区域 */}
<div className="bg-[#0a0b21] text-white p-4 rounded-md my-2 font-mono text-sm overflow-auto relative">
{activeTab === 'mcp' ? (
<ReactJson
src={
configContent
? typeof configContent === 'string'
? (() => {
try {
return JSON.parse(configContent)
} catch (e) {
return {}
}
})()
: configContent
: {}
}
theme="monokai"
indentWidth={2}
displayDataTypes={false}
displayObjectSize={false}
name={false}
collapsed={false}
enableClipboard={false}
style={{
backgroundColor: 'transparent',
wordBreak: 'break-word',
whiteSpace: 'normal'
}}
/>
) : (
<>
<pre className="whitespace-pre-wrap break-words">{configContent || ''}</pre>
</>
)}
<IconButton
name="copy"
onClick={() => handleCopy(configContent)}
sx={{
position: 'absolute',
top: '5px',
right: '5px',
color: '#999',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
</div>
</div>
{activeTab === 'mcp' && (
<>
<div className="tab-content font-semibold my-[10px]">API Key</div>
{apiKeyList.length ? (
<>
{type === 'global' ? (
<>
<Select
showSearch
optionFilterProp="label"
value={apiKey}
className="w-full"
onChange={handleSelectChange}
options={apiKeyList}
/>
<Card
style={{ borderRadius: '5px' }}
className="w-full mt-[5px] "
classNames={{
body: 'p-[5px]'
}}
>
<div className="relative h-[25px]">
{apiKey}
<IconButton
name="copy"
onClick={() => handleCopy(apiKey)}
sx={{
position: 'absolute',
top: '0px',
right: '5px',
color: '#999',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
</div>
</Card>
</>
) : (
<>
<Cascader
className='w-full'
allowClear={false}
options={apiKeyList}
value={cascaderKeyList}
onChange={handleCascaderChange}
placeholder={$t('选择 API Key')}
/>
</>
)}
</>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={''}>
<Button onClick={addKey} type="primary">
{$t('新增 API Key')}
</Button>
</Empty>
)}
</>
)}
</>
)}
</Card>
</>
)
})
@@ -0,0 +1,209 @@
import InsidePage from '@common/components/aoplatform/InsidePage'
import { IconButton } from '@common/components/postcat/api/IconButton'
import { $t } from '@common/locales/index.ts'
import { Button, Card, App, Empty } from 'antd'
import { useFetch } from '@common/hooks/http'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useEffect, useRef, useState } from 'react'
import AddMcpKey, { addMcpKeysHandle } from './AddMcpKey'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
const McpKeyContainer = () => {
const { fetchData } = useFetch()
const { message, modal } = App.useApp()
const [keys, setKeys] = useState<any[]>([])
const [, forceUpdate] = useState<unknown>(null)
const { state } = useGlobalContext()
const addMcpKeyModalRef = useRef<addMcpKeysHandle>(null)
/**
* API Key
*/
const addKey = () => {
modal.confirm({
title: $t('新增 API Key'),
content: <AddMcpKey ref={addMcpKeyModalRef}></AddMcpKey>,
onOk: () => {
return addMcpKeyModalRef.current?.save().then((res) => {
if (res) {
getKeysList()
}
})
},
width: 600,
okText: $t('确认'),
cancelText: $t('取消'),
closable: true,
icon: <></>
})
}
/**
* API Key
*/
const getKeysList = () => {
fetchData<BasicResponse<null>>('system/apikeys', {
method: 'GET'
})
.then((response) => {
const { code, msg, data } = response
if (code === STATUS_CODE.SUCCESS) {
setKeys(data.apikeys || [])
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => {
message.error(errorInfo || $t(RESPONSE_TIPS.error))
})
}
/**
* API Key
*/
const copyCode = async (value: string): Promise<void> => {
if (value) {
await navigator.clipboard.writeText(value)
message.success($t(RESPONSE_TIPS.copySuccess))
}
}
/**
* API Key
*/
const deleteKey = (id: string) => {
modal.confirm({
title: $t('删除'),
content: $t('确定删除吗?'),
onOk: async () => {
try {
const response = await fetchData<BasicResponse<'success'>>('system/apikey', {
method: 'DELETE',
eoParams: { apikey: id }
})
if (response.code === STATUS_CODE.SUCCESS) {
message.success($t('删除成功'))
getKeysList()
}
} catch (error) {
message.error($t('删除失败'))
}
},
width: 600,
okText: $t('确认'),
cancelText: $t('取消'),
closable: true,
icon: <></>
})
}
/**
* API Key
*/
const editKey = (key: any) => {
modal.confirm({
title: $t('编辑'),
content: (
<AddMcpKey ref={addMcpKeyModalRef} name={key.name} value={key.value} apikey={key.id} type={'edit'}></AddMcpKey>
),
onOk: () => {
return addMcpKeyModalRef.current?.save().then((res) => {
if (res) {
getKeysList()
}
})
},
width: 600,
okText: $t('确认'),
cancelText: $t('取消'),
closable: true,
icon: <></>
})
}
useEffect(() => {
getKeysList()
}, [])
useEffect(() => {
forceUpdate({})
}, [state.language])
return (
<>
<InsidePage
pageTitle={$t('API Key')}
description={$t('API 密钥可用于调用系统级 Open API 和 MCP。')}
showBorder={false}
scrollPage={false}
>
<Button type="primary" onClick={addKey}>
{$t('新增 API Key')}
</Button>
<div className="api-key-container mt-[20px]">
{keys.length ? (
keys.map((key, index) => (
<Card style={{ width: 600, borderRadius: '10px' }} key={index} className="mt-[10px]">
<div className="flex">
<div className="flex-1">
<p className="text-[14px] font-bold">{key.name}</p>
<div className="flex">
<span className="h-[26px] leading-[28px]">{key.value}</span>
<IconButton
name="copy"
onClick={() => {
copyCode(key?.value)
}}
sx={{
color: '#333',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
</div>
</div>
<div className="w-[30px] flex justify-center items-center">
<IconButton
name="edit"
onClick={() => {
editKey(key)
}}
sx={{
color: '#333',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
<IconButton
name="delete"
onClick={() => {
deleteKey(key.id)
}}
sx={{
color: '#333',
transition: 'none',
'&.MuiButtonBase-root:hover': { background: 'transparent', color: 'red', transition: 'none' }
}}
></IconButton>
</div>
</div>
</Card>
))
) : (
<>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</>
)}
</div>
</InsidePage>
</>
)
}
export default McpKeyContainer
@@ -0,0 +1,37 @@
import InsidePage from "@common/components/aoplatform/InsidePage"
import { $t } from '@common/locales/index.ts'
import { IntegrationAIContainer } from "./IntegrationAIContainer"
import { Tool } from "@modelcontextprotocol/sdk/types.js"
import { useEffect, useState } from "react"
import McpToolsContainer from "./McpToolsContainer"
import { useGlobalContext } from "@common/contexts/GlobalStateContext"
const McpServiceContainer = () => {
const [tools, setTools] = useState<Tool[]>([]);
const [, forceUpdate] = useState<unknown>(null)
const { state } = useGlobalContext()
const handleToolsChange = (value: Tool[]) => {
setTools(value)
}
useEffect(() => {
forceUpdate({})
}, [state.language])
return (
<>
<InsidePage
pageTitle={$t('MCP 服务')}
description={$t('MCP Service 充当 AI 模型与 API 之间的桥梁,允许智能助手(如 Claude)动态发现和调用 Gateway 上的 API,无需繁琐的手动配置或自定义集成。')}
showBorder={false}
scrollPage={false}
>
<div className="flex mt-[10px] pr-[40px]">
<McpToolsContainer tools={tools} />
<IntegrationAIContainer type={'global'} handleToolsChange={handleToolsChange}></IntegrationAIContainer>
</div>
</InsidePage>
</>
)
}
export default McpServiceContainer
@@ -0,0 +1,30 @@
import { Icon } from '@iconify/react/dist/iconify.js'
import { Tool } from '@modelcontextprotocol/sdk/types.js'
import { Card } from 'antd'
const McpToolsContainer = ({ tools = [], customClassName }: { tools: Tool[]; customClassName?: string }) => {
return (
<>
<Card
style={{ borderRadius: '10px' }}
className={`w-full flex-1 mr-[10px] ${customClassName}`}
classNames={{
body: 'p-[10px]'
}}
>
<div className="mb-[10px]">
<Icon icon="gravity-ui:plug-connection" className="align-text-bottom mr-[5px]" width="16" height="16" />
<span className="text-[14px] font-bold align-middle">Tools</span>
</div>
{tools.map((tool, index) => (
<Card style={{ borderRadius: '10px' }} key={index} className={`w-full ${index > 0 ? 'mt-[10px]' : ''}`}>
<p className="text-[14px] font-bold">{tool.name}</p>
<div className="leading-[28px]">{tool.description}</div>
</Card>
))}
</Card>
</>
)
}
export default McpToolsContainer
@@ -0,0 +1,33 @@
// import { InspectorConfig } from "./configurationTypes";
// OAuth-related session storage keys
export const SESSION_KEYS = {
CODE_VERIFIER: "mcp_code_verifier",
SERVER_URL: "mcp_server_url",
TOKENS: "mcp_tokens",
CLIENT_INFORMATION: "mcp_client_information",
} as const;
export type ConnectionStatus =
| "disconnected"
| "connected"
| "error"
| "error-connecting-to-proxy";
export const DEFAULT_MCP_PROXY_LISTEN_PORT = "6277";
/**
* Default configuration for the MCP Inspector, Currently persisted in local_storage in the Browser.
* Future plans: Provide json config file + Browser local_storage to override default values
**/
export const DEFAULT_INSPECTOR_CONFIG: any = {
MCP_SERVER_REQUEST_TIMEOUT: {
description: "Timeout for requests to the MCP server (ms)",
value: 10000,
},
MCP_PROXY_FULL_ADDRESS: {
description:
"Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577",
value: "",
},
} as const;
@@ -0,0 +1,22 @@
import {
NotificationSchema as BaseNotificationSchema,
ClientNotificationSchema,
ServerNotificationSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
export const StdErrNotificationSchema = BaseNotificationSchema.extend({
method: z.literal("notifications/stderr"),
params: z.object({
content: z.string(),
}),
});
export const NotificationSchema = ClientNotificationSchema.or(
StdErrNotificationSchema,
)
.or(ServerNotificationSchema)
.or(BaseNotificationSchema);
export type StdErrNotification = z.infer<typeof StdErrNotificationSchema>;
export type Notification = z.infer<typeof NotificationSchema>;
@@ -0,0 +1,391 @@
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import {
SSEClientTransport,
SseError,
} from "@modelcontextprotocol/sdk/client/sse.js";
import { App } from 'antd'
import {
ClientNotification,
ClientRequest,
CreateMessageRequestSchema,
ListRootsRequestSchema,
ProgressNotificationSchema,
ResourceUpdatedNotificationSchema,
LoggingMessageNotificationSchema,
Request,
Result,
ServerCapabilities,
PromptReference,
ResourceReference,
McpError,
CompleteResultSchema,
ErrorCode,
CancelledNotificationSchema,
ResourceListChangedNotificationSchema,
ToolListChangedNotificationSchema,
PromptListChangedNotificationSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { useState } from "react";
import { z } from "zod";
import { ConnectionStatus, SESSION_KEYS } from "./constants";
import { Notification, StdErrNotificationSchema } from "./notificationTypes";
// import { auth } from "@modelcontextprotocol/sdk/client/auth.js";
// import { authProvider } from "../auth";
// import packageJson from "../../../package.json";
interface UseConnectionOptions {
transportType: "stdio" | "sse";
command?: string;
args?: string;
sseUrl: string;
env?: Record<string, string>;
proxyServerUrl: string;
bearerToken?: string;
requestTimeout?: number;
onNotification?: (notification: Notification) => void;
onStdErrNotification?: (notification: Notification) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onPendingRequest?: (request: any, resolve: any, reject: any) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getRoots?: () => any[];
}
interface RequestOptions {
signal?: AbortSignal;
timeout?: number;
suppressToast?: boolean;
}
export function useConnection({
transportType,
command,
args,
sseUrl,
env,
proxyServerUrl,
bearerToken,
requestTimeout,
onNotification,
onStdErrNotification,
onPendingRequest,
getRoots,
}: UseConnectionOptions) {
const [connectionStatus, setConnectionStatus] =
useState<ConnectionStatus>("disconnected");
const { message } = App.useApp()
const [serverCapabilities, setServerCapabilities] =
useState<ServerCapabilities | null>(null);
const [mcpClient, setMcpClient] = useState<Client | null>(null);
const [requestHistory, setRequestHistory] = useState<
{ request: string; response?: string }[]
>([]);
const [completionsSupported, setCompletionsSupported] = useState(true);
const pushHistory = (request: object, response?: object) => {
setRequestHistory((prev) => [
...prev,
{
request: JSON.stringify(request),
response: response !== undefined ? JSON.stringify(response) : undefined,
},
]);
};
const makeRequest = async <T extends z.ZodType>(
request: ClientRequest,
schema: T,
options?: RequestOptions,
): Promise<z.output<T>> => {
if (!mcpClient) {
throw new Error("MCP client not connected");
}
try {
const abortController = new AbortController();
const timeoutId = setTimeout(() => {
abortController.abort("Request timed out");
}, options?.timeout ?? requestTimeout);
let response;
try {
response = await mcpClient.request(request, schema, {
signal: options?.signal ?? abortController.signal,
});
pushHistory(request, response);
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
pushHistory(request, { error: errorMessage });
throw error;
} finally {
clearTimeout(timeoutId);
}
return response;
} catch (e: unknown) {
if (!options?.suppressToast) {
const errorString = (e as Error).message ?? String(e);
message.error(errorString)
}
throw e;
}
};
const handleCompletion = async (
ref: ResourceReference | PromptReference,
argName: string,
value: string,
signal?: AbortSignal,
): Promise<string[]> => {
if (!mcpClient || !completionsSupported) {
return [];
}
const request: ClientRequest = {
method: "completion/complete",
params: {
argument: {
name: argName,
value,
},
ref,
},
};
try {
const response = await makeRequest(request, CompleteResultSchema, {
signal,
suppressToast: true,
});
return response?.completion.values || [];
} catch (e: unknown) {
// Disable completions silently if the server doesn't support them.
// See https://github.com/modelcontextprotocol/specification/discussions/122
if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {
setCompletionsSupported(false);
return [];
}
// Unexpected errors - show toast and rethrow
message.error(e instanceof Error ? e.message : String(e))
throw e;
}
};
const sendNotification = async (notification: ClientNotification) => {
if (!mcpClient) {
const error = new Error("MCP client not connected");
message.error(error.message)
throw error;
}
try {
await mcpClient.notification(notification);
// Log successful notifications
pushHistory(notification);
} catch (e: unknown) {
if (e instanceof McpError) {
// Log MCP protocol errors
pushHistory(notification, { error: e.message });
}
message.error(e instanceof Error ? e.message : String(e))
throw e;
}
};
// TODO_先屏蔽,暂时不需要
// const checkProxyHealth = async () => {
// try {
// const proxyHealthUrl = new URL(`${proxyServerUrl}/health`);
// const proxyHealthResponse = await fetch(proxyHealthUrl);
// const proxyHealth = await proxyHealthResponse.json();
// if (proxyHealth?.status !== "ok") {
// throw new Error("MCP Proxy Server is not healthy");
// }
// } catch (e) {
// console.error("Couldn't connect to MCP Proxy Server", e);
// throw e;
// }
// };
// TODO_先屏蔽,暂时不需要
// const handleAuthError = async (error: unknown) => {
// if (error instanceof SseError && error.code === 401) {
// sessionStorage.setItem(SESSION_KEYS.SERVER_URL, sseUrl);
// const result = await auth(authProvider, { serverUrl: sseUrl });
// return result === "AUTHORIZED";
// }
// return false;
// };
const connect = async (_e?: unknown, retryCount: number = 0) => {
const client = new Client<Request, Notification, Result>(
{
name: "mcp-inspector",
version: '0.0.1',
},
{
capabilities: {
sampling: {},
roots: {
listChanged: true,
},
},
},
);
// TODO_暂时不需要
// try {
// await checkProxyHealth();
// } catch {
// setConnectionStatus("error-connecting-to-proxy");
// return;
// }
// 使用与http.ts一致的方式处理URL
// 注意:proxyServerUrl应该是完整URL,或者我们需要为其添加基础URL
// 处理两种情况:完整URL或相对路径
let fullUrl;
if (proxyServerUrl.startsWith('http://') || proxyServerUrl.startsWith('https://')) {
// 如果是完整URL,直接使用
fullUrl = `${proxyServerUrl}/sse`;
} else {
// 如果是相对路径,添加基础URL和API前缀
const baseUrl = window.location.origin;
const apiPrefix = '/api/v1/';
fullUrl = `${baseUrl}${apiPrefix}${proxyServerUrl}`;
}
// let newSseUrl = ''
// if (sseUrl.startsWith('http://') || sseUrl.startsWith('https://')) {
// // 如果是完整URL,直接使用
// newSseUrl = sseUrl
// } else {
// // 如果是相对路径,添加基础URL和API前缀
// const baseUrl = window.location.origin;
// const apiPrefix = '/api/v1/';
// newSseUrl = `${baseUrl}${apiPrefix}${sseUrl}`;
// }
const mcpProxyServerUrl = new URL(fullUrl);
// mcpProxyServerUrl.searchParams.append("transportType", transportType);
// if (transportType === "stdio") {
// mcpProxyServerUrl.searchParams.append("command", command || '');
// mcpProxyServerUrl.searchParams.append("args", args || '');
// mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env || {}));
// } else {
// mcpProxyServerUrl.searchParams.append("url", newSseUrl);
// }
// console.log('sseUrl===', newSseUrl)
try {
// Inject auth manually instead of using SSEClientTransport, because we're
// proxying through the inspector server first.
const headers: HeadersInit = {};
// TODO_暂时不需要。Use manually provided bearer token if available, otherwise use OAuth tokens
// const token = bearerToken || (await authProvider.tokens())?.access_token;
// if (token) {
// headers["Authorization"] = `Bearer ${token}`;
// }
// 创建SSE客户端传输层
const clientTransport = new SSEClientTransport(mcpProxyServerUrl, {
eventSourceInit: {
fetch: (url, init) => fetch(url, { ...init, headers }),
},
requestInit: {
headers,
},
});
// TODO_暂时不需要
// if (onNotification) {
// [
// CancelledNotificationSchema,
// ProgressNotificationSchema,
// LoggingMessageNotificationSchema,
// ResourceUpdatedNotificationSchema,
// ResourceListChangedNotificationSchema,
// ToolListChangedNotificationSchema,
// PromptListChangedNotificationSchema,
// ].forEach((notificationSchema) => {
// client.setNotificationHandler(notificationSchema, onNotification);
// });
// client.fallbackNotificationHandler = (
// notification: Notification,
// ): Promise<void> => {
// onNotification(notification);
// return Promise.resolve();
// };
// }
// if (onStdErrNotification) {
// client.setNotificationHandler(
// StdErrNotificationSchema,
// onStdErrNotification,
// );
// }
try {
await client.connect(clientTransport);
} catch (error) {
console.error(
`Failed to connect to MCP Server via the MCP Inspector Proxy: ${mcpProxyServerUrl}:`,
error,
);
// TODO_先屏蔽,后续如果需要再处理
// const shouldRetry = await handleAuthError(error);
// if (shouldRetry) {
// return connect(undefined, retryCount + 1);
// }
if (error instanceof SseError && error.code === 401) {
// Don't set error state if we're about to redirect for auth
return;
}
throw error;
}
const capabilities = client.getServerCapabilities();
setServerCapabilities(capabilities ?? null);
setCompletionsSupported(true); // Reset completions support on new connection
// TODO_暂时不需要
// if (onPendingRequest) {
// client.setRequestHandler(CreateMessageRequestSchema, (request) => {
// return new Promise((resolve, reject) => {
// onPendingRequest(request, resolve, reject);
// });
// });
// }
// if (getRoots) {
// client.setRequestHandler(ListRootsRequestSchema, async () => {
// return { roots: getRoots() };
// });
// }
setMcpClient(client);
setConnectionStatus("connected");
} catch (e) {
console.error(e);
setConnectionStatus("error");
}
};
const disconnect = async () => {
await mcpClient?.close();
setMcpClient(null);
setConnectionStatus("disconnected");
setCompletionsSupported(false);
setServerCapabilities(null);
};
return {
connectionStatus,
serverCapabilities,
mcpClient,
requestHistory,
makeRequest,
sendNotification,
handleCompletion,
completionsSupported,
connect,
disconnect,
};
}
@@ -480,6 +480,8 @@ const MemberList = () => {
render: (_, entity) => (
<WithPermission access="system.organization.member.edit">
<Select
showSearch
optionFilterProp="label"
className="w-full"
mode="multiple"
value={entity.roles?.map((x: EntityItem) => x.id)}
@@ -60,7 +60,13 @@ export type DashboardSettingEditProps = {
name="driver"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={[...DASHBOARD_SETTING_DRIVER_OPTION_LIST]}/>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={[...DASHBOARD_SETTING_DRIVER_OPTION_LIST]}
/>
</Form.Item>
<Form.Item<PartitionDashboardConfigFieldType>
@@ -301,7 +301,13 @@ const FilterForm = forwardRef<FilterFormHandle, FilterFormProps>(
return (
<Form form={form} layout="vertical" onValuesChange={handleValuesChange}>
<Form.Item name="name" label={$t('属性名称')} rules={[{ required: true }]}>
<Select disabled={disabled} onChange={handleTypeChange} options={filterOptionsList} />
<Select
showSearch
optionFilterProp="label"
disabled={disabled}
onChange={handleTypeChange}
options={filterOptionsList}
/>
</Form.Item>
<Form.Item
name="values"
@@ -1,15 +1,27 @@
import { useEffect } from "react";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
import { useEffect } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { $t } from '@common/locales'
export default function ServicePolicyLayout(){
const location = useLocation()
const pathName = location.pathname
const navigator = useNavigate()
useEffect(()=>{
const tmpPath = pathName.split('/')
if(tmpPath[tmpPath.length -1 ] === 'servicepolicy'){
navigator('datamasking/list')
export default function ServicePolicyLayout() {
const location = useLocation()
const pathName = location.pathname
const navigator = useNavigate()
const { setBreadcrumb } = useBreadcrumb()
useEffect(() => {
const tmpPath = pathName.split('/')
if (tmpPath[tmpPath.length - 1] === 'servicepolicy') {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('服务策略')
}
},[pathName])
return (<Outlet></Outlet>)
}
])
navigator('datamasking/list')
}
}, [pathName])
return <Outlet></Outlet>
}
@@ -14,6 +14,7 @@ import FilterTable from "../FilterTable"
import { DataMaskingConfigHandle ,DataMaskingConfigFieldType, PolicyMatchType} from "@common/const/policy/type"
import {PolicyOptions} from '@common/const/policy/consts'
import {v4 as uuidv4} from 'uuid'
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"
const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
const { message,modal } = App.useApp()
@@ -24,6 +25,7 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
const { state } = useGlobalContext()
const [ loading, setLoading ] = useState<boolean>(false)
const navigator = useNavigate()
const { setBreadcrumb } = useBreadcrumb()
useImperativeHandle(ref, () => ({
save:onFinish
@@ -78,6 +80,19 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
};
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('服务策略'),
onClick: () => navigator(serviceId ? `/service/${teamId}/aiInside/${serviceId}/servicepolicy` : '')
},
{
title: policyId !== undefined ? $t('编辑服务策略') : $t('添加服务策略')
}
])
if (policyId !== undefined) {
setOnEdit(true);
getPolicyInfo();
@@ -96,7 +111,7 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
showBorder={false}
scrollPage={false}
className="overflow-y-auto"
backUrl={serviceId ? '../list' : undefined}
backUrl={serviceId ? `/service/${teamId}/aiInside/${serviceId}/servicepolicy` : undefined}
>
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading} wrapperClassName=' pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X'>
<WithPermission access={onEdit ? [`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`] :''}>
@@ -124,8 +139,13 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
name="type"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} options={policyOptions} >
</Select>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={policyOptions}
></Select>
</Form.Item>
<Form.Item<DataMaskingConfigFieldType>
@@ -146,6 +146,8 @@ const DataMaskRuleForm: React.FC<DataMaskRuleFormProps> = ({
<Form form={form} layout="vertical" className="p-4">
<Form.Item name={['match', 'type']} label={$t('匹配类型')} rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
onChange={handleMatchTypeChange}
options={matchRuleOptions}
@@ -156,6 +158,8 @@ const DataMaskRuleForm: React.FC<DataMaskRuleFormProps> = ({
<Form.Item name={['match', 'value']} label={$t('匹配值')} rules={[{ required: true }]}>
{matchType === 'inner' ? (
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
onChange={handleMatchValueChange}
options={dataFormatOptions}
@@ -168,6 +172,8 @@ const DataMaskRuleForm: React.FC<DataMaskRuleFormProps> = ({
<Form.Item name={['mask', 'type']} label={$t('脱敏类型')} rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
onChange={handleMaskTypeChange}
options={
@@ -197,6 +203,8 @@ const DataMaskRuleForm: React.FC<DataMaskRuleFormProps> = ({
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
onChange={handleReplaceTypeChange}
options={dataMaskReplaceStrOptions}
@@ -1,251 +1,313 @@
import { useEffect, useMemo, useState} from "react";
import {App, Button, Checkbox, Collapse, Form, GetProp, Input} from "antd";
import {useFetch} from "@common/hooks/http.ts";
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { useNavigate, useParams } from "react-router-dom";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx";
import { ArrowLeftOutlined } from "@ant-design/icons";
import { $t } from "@common/locales";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
import { useEffect, useMemo, useState } from 'react'
import { App, Button, Checkbox, Collapse, Form, GetProp, Input } from 'antd'
import { useFetch } from '@common/hooks/http.ts'
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { useNavigate, useParams } from 'react-router-dom'
import { $t } from '@common/locales'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
import TopBreadcrumb from '@common/components/aoplatform/Breadcrumb.tsx'
type PermissionItem = {
name:string
value:string
name: string
value: string
}
type PermissionClassify = PermissionItem & {children : ( PermissionItem & {dependents:string[]})[]}
type PermissionClassify = PermissionItem & { children: (PermissionItem & { dependents: string[] })[] }
type RolePermissionItem = PermissionItem & {
children:PermissionClassify[]}
children: PermissionClassify[]
}
type DependenciesMapType = Map<string, {dependents:string[], control:string[]}>
type DependenciesMapType = Map<string, { dependents: string[]; control: string[] }>
type PermissionCollapseProps = {
id?: string;
value?: string[];
onChange?: (value:string[]) => void;
permissionTemplate:RolePermissionItem[]
dependenciesMap?: DependenciesMapType
id?: string
value?: string[]
onChange?: (value: string[]) => void
permissionTemplate: RolePermissionItem[]
dependenciesMap?: DependenciesMapType
}
type PermissionInfo = {
permit: string[]
description: string
update_time: string
create_time: string
name: string
permit: string[]
description: string
update_time: string
create_time: string
name: string
}
const PermissionContent = ({permits,onChange,value=[],id,dependenciesMap}:{permits:PermissionClassify[],dependenciesMap:DependenciesMapType,value:string[],id:string, onChange?: (value:string[]) => void;})=>{
const onSingleCheckboxChange: GetProp<typeof Checkbox, 'onChange'> = (e) => {
if(e.target.checked){
onChange?.(Array.from(new Set([...value, e.target.id, ...(dependenciesMap?.get(e.target.id!)?.dependents || [])] as string[])))
}else{
const cancelValue = [...dependenciesMap?.get(e.target.id!)?.control || [], e.target.id]
onChange?.(value.filter(x=>!cancelValue.includes(x)))
}
};
return (
<div id={id} className="flex flex-col gap-btnbase p-btnbase">
{
permits.map((item:PermissionClassify)=>(
<>
<div className="flex flex-col gap-btnbase" key={`group-${item.name}`}>
{item.name !== '' && <p className="">{(item.name)}</p>}
<div className=" pl-[20px]">
{item.children.map(x=><Checkbox id={x.value} key={x.value} checked={value && value.length > 0 && value.indexOf(x.value)>-1} onChange={onSingleCheckboxChange}>{(x.name)}</Checkbox>)}
</div>
</div>
</>
))
}</div>
)
}
// 自定义表单控件
const PermissionCollapse:React.FC<PermissionCollapseProps> = (props)=>{
const { id, value = [], onChange,permissionTemplate ,dependenciesMap} = props;
const [openCollapses, setOpenCollapses] = useState<string[]>([])
const {state} = useGlobalContext()
const items = useMemo(()=>{
const generatePermissionItem = (permissionItem:RolePermissionItem[])=> permissionItem.map((item:RolePermissionItem)=>({
key:item.name,
label:(item.name),
children:<PermissionContent value={value} permits={item.children} onChange={(e)=>onChange?.(e)} id={id!} dependenciesMap={dependenciesMap!}/>
}))
return permissionTemplate && permissionTemplate.length > 0 ? generatePermissionItem(permissionTemplate) : []
},[permissionTemplate,value,state.language])
useEffect(()=>{
permissionTemplate && setOpenCollapses(permissionTemplate?.map(x=>x.name))
},[permissionTemplate])
const onCollapseChange = (keys: string | string[]) => {
setOpenCollapses(keys as string[])
};
return <Collapse items={items} activeKey={openCollapses} onChange={onCollapseChange} />
const PermissionContent = ({
permits,
onChange,
value = [],
id,
dependenciesMap
}: {
permits: PermissionClassify[]
dependenciesMap: DependenciesMapType
value: string[]
id: string
onChange?: (value: string[]) => void
}) => {
const onSingleCheckboxChange: GetProp<typeof Checkbox, 'onChange'> = (e) => {
if (e.target.checked) {
onChange?.(
Array.from(
new Set([...value, e.target.id, ...(dependenciesMap?.get(e.target.id!)?.dependents || [])] as string[])
)
)
} else {
const cancelValue = [...(dependenciesMap?.get(e.target.id!)?.control || []), e.target.id]
onChange?.(value.filter((x) => !cancelValue.includes(x)))
}
}
const RoleConfig = ()=>{
const { message } = App.useApp()
const [form] = Form.useForm();
const {fetchData} = useFetch()
const navigateTo = useNavigate()
const { roleType, roleId} = useParams<RouterParams>()
const [permissionTemplate, setPermissionTemplate] = useState<RolePermissionItem[]>()
const [dependenciesMap, setDependenciesMap] = useState<DependenciesMapType>()
const APP_MODE = import.meta.env.VITE_APP_MODE;
const [permissionInfo, setPermissionInfo] = useState<PermissionInfo>()
const { state } = useGlobalContext()
const generateDependenciesMap = (data:RolePermissionItem[])=>{
const map = new Map<string, {dependents:string[], control:string[]}>()
data.forEach((item:RolePermissionItem)=>{
item.children.forEach((child:PermissionClassify)=>{
child.children.forEach((permission:PermissionItem & {dependents:string[]})=>{
if (permission.dependents && permission.dependents.length > 0) {
// 获取当前权限的依赖
const currentDependents = map.get(permission.value);
if (currentDependents) {
currentDependents.dependents.push(...permission.dependents);
} else {
map.set(permission.value, { dependents: [...permission.dependents], control: [] });
}
// 更新依赖项的控制项
permission.dependents.forEach((dependent: string) => {
const dependentEntry = map.get(dependent);
if (dependentEntry) {
dependentEntry.control.push(permission.value);
} else {
map.set(dependent, { dependents: [], control: [permission.value] });
}
});
}
})
})
})
setDependenciesMap(map)
}
const generateNewPermit:(data:RolePermissionItem[])=>RolePermissionItem[] = (data:RolePermissionItem[]) =>{
return data.map((item:RolePermissionItem)=>({
...item,children:item.children.map((child:PermissionClassify)=>({
...child,
children:child.children.map((permission:PermissionItem & {dependents:string[]})=>({
...permission, value:`${roleType}.${item.value}.${child.value}.${permission.value}`
}))
}))
}))
}
const getPermissionTemplate = ()=>{
return fetchData<BasicResponse<{permits:RolePermissionItem[]}>>(`${roleType}/role/template`,{method:'GET'}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
const newPermits = generateNewPermit(data.permits)
generateDependenciesMap(newPermits)
setPermissionTemplate(newPermits)
}else{
message.error(msg || $t(RESPONSE_TIPS.dataError))
}
})
}
const getPermissionInfo = ()=>{
fetchData<BasicResponse<{role:PermissionInfo}>>(`${roleType}/role`,{method:'GET',eoParams:{role:roleId}}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setPermissionInfo(data.role)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errInfo)=>console.error(errInfo))
}
useEffect(()=>{
form.setFieldsValue({name:$t(permissionInfo?.name || ''),permits:permissionInfo?.permit})
},[permissionInfo, state.language])
useEffect(() => {
form.setFieldsValue({name:'',permits:[]})
if(roleId){
getPermissionInfo()
}
}, []);
useEffect(()=>{
getPermissionTemplate()
},[state.language])
const onFinish =async() => {
const body = await form.validateFields()
return fetchData<BasicResponse<null>>(`${roleType}/role`,{method:roleId === undefined? 'POST' : 'PUT',eoBody:({...body}),...(roleId !== undefined?{eoParams:{role:roleId}}:{})}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
return Promise.resolve(true)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
return Promise.reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errInfo)=>Promise.reject(errInfo))
};
return (<div className="h-full flex flex-col overflow-hidden ">
<div className="text-[18px] leading-[25px] pb-[12px]">
<Button className="flex items-center" type="text" onClick={()=>navigateTo(-1)}><ArrowLeftOutlined className="max-h-[14px]" /><span>{$t('返回')}</span></Button>
</div>
<WithPermission access={roleId !== undefined ? `system.organization.role.${roleType}.edit`: `system.organization.role.${roleType}.add`}>
<Form
id="permission"
layout='vertical'
labelAlign='left'
scrollToFirstError
form={form}
className="mx-auto w-full flex-1 no-bg-form overflow-hidden "
name="rolePermissionConfig"
onFinish={onFinish}
autoComplete="off"
return (
<div id={id} className="flex flex-col gap-btnbase p-btnbase">
{permits.map((item: PermissionClassify) => (
<>
<div className="flex flex-col gap-btnbase" key={`group-${item.name}`}>
{item.name !== '' && <p className="">{item.name}</p>}
<div className=" pl-[20px]">
{item.children.map((x) => (
<Checkbox
id={x.value}
key={x.value}
checked={value && value.length > 0 && value.indexOf(x.value) > -1}
onChange={onSingleCheckboxChange}
>
<div className="flex flex-col h-full">
<Form.Item
className=" m-btnbase mr-PAGE_INSIDE_X"
name="name"
rules={[{ required: true,whitespace:true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item
name="permits"
className="m-btnbase mr-0 flex-1 overflow-auto pr-PAGE_INSIDE_X"
>
<PermissionCollapse permissionTemplate={permissionTemplate!} dependenciesMap={dependenciesMap} />
</Form.Item>
{APP_MODE === 'pro' && <div className="p-btnbase">
<WithPermission access={roleId === undefined ?`system.organization.role.${roleType}.edit`:`system.organization.role.${roleType}.add`}>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
</WithPermission>
<Button className="ml-btnrbase" type="default" onClick={() => navigateTo(-1)}>
{$t('取消')}
</Button>
</div>}
</div>
</Form>
</WithPermission>
</div>)
{x.name}
</Checkbox>
))}
</div>
</div>
</>
))}
</div>
)
}
export default RoleConfig
// 自定义表单控件
const PermissionCollapse: React.FC<PermissionCollapseProps> = (props) => {
const { id, value = [], onChange, permissionTemplate, dependenciesMap } = props
const [openCollapses, setOpenCollapses] = useState<string[]>([])
const { state } = useGlobalContext()
const items = useMemo(() => {
const generatePermissionItem = (permissionItem: RolePermissionItem[]) =>
permissionItem.map((item: RolePermissionItem) => ({
key: item.name,
label: item.name,
children: (
<PermissionContent
value={value}
permits={item.children}
onChange={(e) => onChange?.(e)}
id={id!}
dependenciesMap={dependenciesMap!}
/>
)
}))
return permissionTemplate && permissionTemplate.length > 0 ? generatePermissionItem(permissionTemplate) : []
}, [permissionTemplate, value, state.language])
useEffect(() => {
permissionTemplate && setOpenCollapses(permissionTemplate?.map((x) => x.name))
}, [permissionTemplate])
const onCollapseChange = (keys: string | string[]) => {
setOpenCollapses(keys as string[])
}
return <Collapse items={items} activeKey={openCollapses} onChange={onCollapseChange} />
}
const RoleConfig = () => {
const { message } = App.useApp()
const [form] = Form.useForm()
const { fetchData } = useFetch()
const navigateTo = useNavigate()
const { roleType, roleId } = useParams<RouterParams>()
const [permissionTemplate, setPermissionTemplate] = useState<RolePermissionItem[]>()
const [dependenciesMap, setDependenciesMap] = useState<DependenciesMapType>()
const APP_MODE = import.meta.env.VITE_APP_MODE
const [permissionInfo, setPermissionInfo] = useState<PermissionInfo>()
const { state } = useGlobalContext()
const { setBreadcrumb } = useBreadcrumb()
const generateDependenciesMap = (data: RolePermissionItem[]) => {
const map = new Map<string, { dependents: string[]; control: string[] }>()
data.forEach((item: RolePermissionItem) => {
item.children.forEach((child: PermissionClassify) => {
child.children.forEach((permission: PermissionItem & { dependents: string[] }) => {
if (permission.dependents && permission.dependents.length > 0) {
// 获取当前权限的依赖
const currentDependents = map.get(permission.value)
if (currentDependents) {
currentDependents.dependents.push(...permission.dependents)
} else {
map.set(permission.value, { dependents: [...permission.dependents], control: [] })
}
// 更新依赖项的控制项
permission.dependents.forEach((dependent: string) => {
const dependentEntry = map.get(dependent)
if (dependentEntry) {
dependentEntry.control.push(permission.value)
} else {
map.set(dependent, { dependents: [], control: [permission.value] })
}
})
}
})
})
})
setDependenciesMap(map)
}
const generateNewPermit: (data: RolePermissionItem[]) => RolePermissionItem[] = (data: RolePermissionItem[]) => {
return data.map((item: RolePermissionItem) => ({
...item,
children: item.children.map((child: PermissionClassify) => ({
...child,
children: child.children.map((permission: PermissionItem & { dependents: string[] }) => ({
...permission,
value: `${roleType}.${item.value}.${child.value}.${permission.value}`
}))
}))
}))
}
const getPermissionTemplate = () => {
return fetchData<BasicResponse<{ permits: RolePermissionItem[] }>>(`${roleType}/role/template`, {
method: 'GET'
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const newPermits = generateNewPermit(data.permits)
generateDependenciesMap(newPermits)
setPermissionTemplate(newPermits)
} else {
message.error(msg || $t(RESPONSE_TIPS.dataError))
}
})
}
const getPermissionInfo = () => {
fetchData<BasicResponse<{ role: PermissionInfo }>>(`${roleType}/role`, {
method: 'GET',
eoParams: { role: roleId }
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setPermissionInfo(data.role)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errInfo) => console.error(errInfo))
}
useEffect(() => {
form.setFieldsValue({ name: $t(permissionInfo?.name || ''), permits: permissionInfo?.permit })
}, [permissionInfo, state.language])
useEffect(() => {
form.setFieldsValue({ name: '', permits: [] })
if (roleId) {
getPermissionInfo()
}
}, [])
useEffect(() => {
setBreadcrumb([
{
title: $t('角色'),
onClick: () => navigateTo(-1)
},
{ title: $t('角色配置') }
])
getPermissionTemplate()
}, [state.language])
const onFinish = async () => {
const body = await form.validateFields()
return fetchData<BasicResponse<null>>(`${roleType}/role`, {
method: roleId === undefined ? 'POST' : 'PUT',
eoBody: { ...body },
...(roleId !== undefined ? { eoParams: { role: roleId } } : {})
})
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
return Promise.resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return Promise.reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errInfo) => Promise.reject(errInfo))
}
return (
<div className="h-full flex flex-col overflow-hidden ">
<TopBreadcrumb handleBackCallback={() => navigateTo(-1)} />
<WithPermission
access={
roleId !== undefined
? `system.organization.role.${roleType}.edit`
: `system.organization.role.${roleType}.add`
}
>
<Form
id="permission"
layout="vertical"
labelAlign="left"
scrollToFirstError
form={form}
className="mx-auto w-full flex-1 no-bg-form overflow-hidden "
name="rolePermissionConfig"
onFinish={onFinish}
autoComplete="off"
>
<div className="flex flex-col h-full">
<Form.Item
className=" m-btnbase mr-PAGE_INSIDE_X"
name="name"
rules={[{ required: true, whitespace: true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
<Form.Item name="permits" className="m-btnbase mr-0 flex-1 overflow-auto pr-PAGE_INSIDE_X">
<PermissionCollapse permissionTemplate={permissionTemplate!} dependenciesMap={dependenciesMap} />
</Form.Item>
{APP_MODE === 'pro' && (
<div className="p-btnbase">
<WithPermission
access={
roleId === undefined
? `system.organization.role.${roleType}.edit`
: `system.organization.role.${roleType}.add`
}
>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
</WithPermission>
<Button className="ml-btnrbase" type="default" onClick={() => navigateTo(-1)}>
{$t('取消')}
</Button>
</div>
)}
</div>
</Form>
</WithPermission>
</div>
)
}
export default RoleConfig
@@ -11,14 +11,26 @@ import { normFile } from '@common/utils/uploadPic.ts'
import { validateUrlSlash } from '@common/utils/validate.ts'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { AiServiceConfigFieldType } from '@core/const/ai-service/type.ts'
import { SERVICE_APPROVAL_OPTIONS } from '@core/const/system/const.tsx'
import { MCP_OPTIONS, SERVICE_APPROVAL_OPTIONS } from '@core/const/system/const.tsx'
import { Icon } from '@iconify/react/dist/iconify.js'
import { CategorizesType } from '@market/const/serviceHub/type.ts'
import { App, Button, Form, Input, Radio, Row, Select, Tooltip, TreeSelect, Upload } from 'antd'
import {
App,
Button,
Form,
Input,
Radio,
RadioChangeEvent,
Row,
Select,
Tooltip,
TreeSelect,
Upload
} from 'antd'
import { DefaultOptionType } from 'antd/es/cascader'
import { RcFile, UploadChangeParam, UploadFile, UploadProps } from 'antd/es/upload/interface'
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
import { Link, useLocation, useNavigate, useOutletContext, useParams } from 'react-router-dom'
import { v4 as uuidv4 } from 'uuid'
import { SystemConfigFieldType, SystemConfigHandle } from '../../const/system/type.ts'
import { useSystemContext } from '../../contexts/SystemContext.tsx'
@@ -43,6 +55,8 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
const [showAI, setShowAI] = useState<boolean>(false)
const [imageBase64, setImageBase64] = useState<string | null>(null)
const [tagOptionList, setTagOptionList] = useState<DefaultOptionType[]>([])
const context = useOutletContext<{ onSaveComplete?: () => void }>()
const onSaveComplete = context?.onSaveComplete
const [serviceClassifyOptionList, setServiceClassifyOptionList] = useState<DefaultOptionType[]>()
const [uploadLoading, setUploadLoading] = useState<boolean>(false)
const { checkPermission, accessInit, getGlobalAccessData, state, aiConfigFlushed, setAiConfigFlushed } =
@@ -274,6 +288,7 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
setSystemInfo(data.service)
onSaveComplete?.()
return Promise.resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -342,7 +357,8 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
getSystemInfo()
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigate('/service/list')
},
{
title: $t('设置')
@@ -359,10 +375,32 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
form.setFieldValue('team', teamId)
form.setFieldValue('serviceType', 'public')
form.setFieldValue('approvalType', 'auto')
form.setFieldValue('enable_mcp', false)
}
return form.setFieldsValue({})
}, [serviceId])
const handleMcpChange = (e: RadioChangeEvent) => {
if (e.target.value) {
return
}
modal.confirm({
title: $t('关闭 MCP'),
content: $t('关闭后将无法通过MCP方式调用服务'),
onOk: () => {
form.setFieldValue('enable_mcp', false)
},
onCancel: () => {
form.setFieldValue('enable_mcp', true)
},
width: 600,
okText: $t('了解'),
cancelText: $t('取消'),
closable: true,
icon: <></>
})
}
const deleteSystemModal = async () => {
modal.confirm({
title: $t('删除'),
@@ -387,6 +425,7 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
() => SERVICE_APPROVAL_OPTIONS.map((x) => ({ ...x, label: $t(x.label) })),
[state.language]
)
const mcpOptions = useMemo(() => MCP_OPTIONS.map((x) => ({ ...x, label: $t(x.label) })), [state.language])
return (
<>
@@ -440,6 +479,13 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
</Radio.Group>
</Form.Item>
)}
<Form.Item<AiServiceConfigFieldType> label={$t('MCP')} name="enable_mcp" rules={[{ required: true }]}>
<Radio.Group
className="flex flex-col"
options={mcpOptions}
onChange={serviceId ? handleMcpChange : undefined}
/>
</Form.Item>
{showAI && (
<>
<Form.Item<AiServiceConfigFieldType>
@@ -477,10 +523,14 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={modelList ? modelList.map((x) => ({
...x,
searchText: x.name.toLowerCase()
})) : []}
options={
modelList
? modelList.map((x) => ({
...x,
searchText: x.name.toLowerCase()
}))
: []
}
></Select>
</Form.Item>
</>
@@ -501,6 +551,8 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
{!onEdit && (
<Form.Item<SystemConfigFieldType> label={$t('所属团队')} name="team" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
disabled={onEdit}
placeholder={$t(PLACEHOLDER.input)}
@@ -577,6 +629,8 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
<Form.Item<SystemConfigFieldType> label={$t('标签')} name="tags">
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
mode="tags"
placeholder={$t(PLACEHOLDER.select)}
@@ -1,6 +1,7 @@
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { EntityItem } from '@common/const/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
import { useFetch } from '@common/hooks/http.ts'
import { $t } from '@common/locales'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes'
@@ -9,7 +10,7 @@ import { App, Button } from 'antd'
import hljs from 'highlight.js'
import 'highlight.js/styles/default.css'
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useNavigate, useParams } from 'react-router-dom'
const ServiceInsideDocument = () => {
const { message } = App.useApp()
const [updater, setUpdater] = useState<string>()
@@ -18,7 +19,8 @@ const ServiceInsideDocument = () => {
const [doc, setDoc] = useState<string>()
const { fetchData } = useFetch()
const { serviceId, teamId } = useParams<RouterParams>()
const { setBreadcrumb } = useBreadcrumb()
const navigator = useNavigate()
const save = () => {
fetchData<
BasicResponse<{
@@ -86,6 +88,15 @@ const ServiceInsideDocument = () => {
}
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('使用说明')
}
])
getServiceDoc()
}, [])
@@ -234,6 +234,7 @@ const SystemInsidePage: FC = () => {
<InsidePage
pageTitle={systemInfo?.name || '-'}
tagList={[
...(systemInfo?.enable_mcp ? [{ label: 'MCP', color: '#FFF0C1', className: 'text-[#000]' }] : []),
{
label: (
<Paragraph className="mb-0" copyable={serviceId ? { text: serviceId } : false}>
@@ -20,7 +20,7 @@ import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { App, Form, TreeSelect } from 'antd'
import { DefaultOptionType } from 'antd/es/cascader'
import { FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { SYSTEM_SUBSCRIBER_TABLE_COLUMNS } from '../../const/system/const.tsx'
import {
SimpleSystemItem,
@@ -39,6 +39,7 @@ const SystemInsideSubscriber: FC = () => {
const pageListRef = useRef<ActionType>(null)
const [memberValueEnum, setMemberValueEnum] = useState<SimpleMemberItem[]>([])
const { accessData, state } = useGlobalContext()
const navigator = useNavigate()
const getSystemSubscriber = () => {
return fetchData<BasicResponse<{ subscribers: SystemSubscriberTableListItem[] }>>(
'service/subscribers',
@@ -163,7 +164,8 @@ const SystemInsideSubscriber: FC = () => {
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('订阅方管理')
@@ -8,7 +8,7 @@ import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'
import { useFetch } from '@common/hooks/http.ts'
import { $t } from '@common/locales/index.ts'
import { App } from 'antd'
import { App, Tag } from 'antd'
import { FC, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { SERVICE_KIND_OPTIONS, SYSTEM_TABLE_COLUMNS } from '../../const/system/const.tsx'
@@ -176,10 +176,30 @@ const SystemList: FC = () => {
x.valueEnum = teamList
}
if ((x.dataIndex as string) === 'service_kind') {
x.valueEnum = {}
SERVICE_KIND_OPTIONS.forEach((option) => {
;(x.valueEnum as any)[option.value] = { text: $t(option.label) }
})
x.render = (dom: React.ReactNode, record: any) => (
<span
className={`text-[13px] `}
>
<Tag
color={`#${record.service_kind === 'ai' ? 'EADEFF' : 'DEFFE7'}`}
className={`text-[#000] font-normal border-0 mr-[10px] max-w-[150px] truncate`}
bordered={false}
title={record.service_kind || '-'}
>
{SERVICE_KIND_OPTIONS.find((x) => x.value === record.service_kind)?.label || '-'}
</Tag>
{record?.enable_mcp && (
<Tag
color="#FFF0C1"
className="text-[#000] font-normal border-0 mr-[12px] max-w-[150px] truncate"
bordered={false}
title={'MCP'}
>
MCP
</Tag>
)}
</span>
)
}
if ((x.dataIndex as string) === 'state') {
x.render = (dom: React.ReactNode, record: any) => (
@@ -28,6 +28,8 @@ export default function SystemTopology() {
const { systemInfo } = useSystemContext()
const { setBreadcrumb } = useBreadcrumb()
const [zoomNum, setZoomNum] = useState<number>(1)
const navigate = useNavigate()
const getNodeData = () => {
fetchData<BasicResponse<SystemTopologyResponse>>('service/topology', {
@@ -105,7 +107,8 @@ export default function SystemTopology() {
getNodeData()
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigate('/service/list')
},
{
title: $t('调用拓扑图')
@@ -9,12 +9,13 @@ import { $t } from '@common/locales/index.ts'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { Button, Empty, Spin, Upload, message } from 'antd'
import { forwardRef, useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useNavigate, useParams } from 'react-router-dom'
import {
SystemApiDetail,
SystemInsideApiDocumentHandle,
SystemInsideApiDocumentProps
} from '../../../const/system/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
const SystemInsideApiDocument = forwardRef<
SystemInsideApiDocumentHandle,
@@ -25,7 +26,18 @@ const SystemInsideApiDocument = forwardRef<
const [apiDetail, setApiDetail] = useState<SystemApiDetail>()
const [loading, setLoading] = useState<boolean>(false)
const [showEditor, setShowEditor] = useState<boolean>(false)
const { setBreadcrumb } = useBreadcrumb()
const navigator = useNavigate()
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('API 文档')
}
])
getApiDetail()
}, [])
@@ -30,7 +30,10 @@ const SystemInsideApiProxy = forwardRef<SystemInsideApiProxyHandle,SystemInsideA
const ProxyHeadeerConfig = useMemo(()=>PROXY_HEADER_CONFIG.map((x)=>({
...x,
...(x.key === 'optType' ? {
component: <Select className="w-INPUT_NORMAL" options={UPSTREAM_PROXY_HEADER_TYPE_OPTIONS.map((x)=>({...x, label:$t(x.label)}))}/>
component: <Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL" options={UPSTREAM_PROXY_HEADER_TYPE_OPTIONS.map((x)=>({...x, label:$t(x.label)}))}/>
} : {})
}))
,[state.language])
@@ -26,6 +26,7 @@ import {
SystemInsideRouterCreateHandle,
SystemInsideRouterCreateProps
} from '../../../const/system/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, SystemInsideRouterCreateProps>(
(props, ref) => {
@@ -38,6 +39,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
const { state } = useGlobalContext()
const { apiPrefix, prefixForce } = useSystemContext()
const navigator = useNavigate()
const { setBreadcrumb } = useBreadcrumb()
const onFinish = () => {
return Promise.all([proxyRef.current?.validate?.(), form.validateFields()]).then(([, formValue]) => {
@@ -144,6 +147,19 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
}
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('API'),
onClick: () => navigator(`/service/${teamId}/inside/${serviceId}/route`)
},
{
title: routeId ? $t('编辑 API') : $t('添加 API')
}
])
if (routeId) {
getRouterConfig()
} else {
@@ -163,6 +179,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
...item,
component: (
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
options={Object.entries(MatchPositionEnum)?.map(([key, value]) => {
return { label: $t(value), value: key }
@@ -176,6 +194,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
...item,
component: (
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
options={Object.entries(MatchTypeEnum)?.map(([key, value]) => {
return { label: $t(value), value: key }
@@ -236,6 +256,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
<Form.Item<SystemApiProxyFieldType> label={$t('请求协议')} name="protocols" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
mode="multiple"
@@ -255,6 +277,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
noStyle
>
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
options={apiPathMatchRulesOptions}
className="w-[30%] min-w-[100px]"
@@ -262,8 +286,12 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
</Form.Item>
<Form.Item<SystemApiProxyFieldType>
name="path"
dependencies={['pathMatch']}
rules={[
{ required: true, whitespace: true },
({ getFieldValue }) => ({
required: getFieldValue('pathMatch') !== 'prefix',
whitespace: true
}),
{
validator: validateUrlSlash
}
@@ -287,6 +315,8 @@ const SystemInsideRouterCreate = forwardRef<SystemInsideRouterCreateHandle, Syst
<Form.Item<SystemApiProxyFieldType> label={$t('请求方式')} name="methods" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
mode="multiple"
@@ -158,18 +158,21 @@ const SystemInsideRouterList: FC = () => {
}
}
useEffect(() => {
getMemberList()
manualReloadTable()
}, [serviceId])
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title: $t('路由')
}
])
getMemberList()
manualReloadTable()
}, [serviceId])
}, [state.language])
const columns = useMemo(() => {
return [...SYSTEM_API_TABLE_COLUMNS].map((x) => {
@@ -1,7 +1,7 @@
import {ActionType} from "@ant-design/pro-components";
import {FC, useEffect, useMemo, useRef, useState} from "react";
import {Link, useLocation, useParams} from "react-router-dom";
import {Link, useLocation, useNavigate, useParams} from "react-router-dom";
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx";
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
import {App, Button} from "antd";
@@ -40,6 +40,7 @@ const SystemInsideApprovalList:FC = ()=>{
const [approvalBtnLoading,setApprovalBtnLoading] = useState<boolean>(false)
const [memberValueEnum, setMemberValueEnum] = useState<SimpleMemberItem[]>([])
const {accessData,state} = useGlobalContext()
const navigator = useNavigate()
const openModal = async (type:'approval'|'view',entity:SubscribeApprovalTableListItem)=>{
message.loading($t(RESPONSE_TIPS.loading))
@@ -143,7 +144,8 @@ const SystemInsideApprovalList:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigator('/service/list')
},
{
title:$t('订阅审核')
@@ -28,7 +28,8 @@ const SystemInsidePublic:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigateTo('/service/list')
},
{
title:$t('发布')
@@ -1,7 +1,7 @@
import { ActionType, ParamsType } from "@ant-design/pro-components";
import { App, Button, Divider } from "antd";
import { useState, useRef, useEffect, useMemo, FC } from "react";
import { useParams, Link, useLocation } from "react-router-dom";
import { useParams, Link, useLocation, useNavigate } from "react-router-dom";
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList";
import { PublishApprovalModalContent } from "@common/components/aoplatform/PublishApprovalModalContent";
import { PUBLISH_APPROVAL_RECORD_INNER_TABLE_COLUMN, PUBLISH_APPROVAL_VERSION_INNER_TABLE_COLUMN, PublishApplyStatusEnum, PublishStatusEnum, PublishTableStatusColorClass } from "@common/const/approval/const";
@@ -44,6 +44,7 @@ const SystemInsidePublicList:FC = ()=>{
const [drawerData, setDrawerData] = useState<PublishTableListItem|PublishVersionTableListItem >({} as PublishTableListItem)
const [drawerOkTitle, setDrawerOkTitle] = useState<string>('确认')
const [isOkToPublish, setIsOkToPublish] = useState<boolean>(false)
const navigateTo = useNavigate()
const getSystemPublishList = (params?: ParamsType & {
pageSize?: number | undefined;
current?: number | undefined;
@@ -351,7 +352,8 @@ const SystemInsidePublicList:FC = ()=>{
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigateTo('/service/list')
},
{
title:$t('发布')
@@ -8,7 +8,7 @@ import EditableTable from "@common/components/aoplatform/EditableTable.tsx";
import EditableTableWithModal from "@common/components/aoplatform/EditableTableWithModal.tsx";
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { UPSTREAM_TYPE_OPTIONS, SYSTEM_UPSTREAM_GLOBAL_CONFIG_TABLE_COLUMNS, schemeOptions, UPSTREAM_BALANCE_OPTIONS, UPSTREAM_PASS_HOST_OPTIONS, PROXY_HEADER_CONFIG, UPSTREAM_PROXY_HEADER_TYPE_OPTIONS } from "../../../const/system/const.tsx";
import { Link, useParams } from "react-router-dom";
import { Link, useNavigate, useParams } from "react-router-dom";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx";
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const.tsx";
import { useFetch } from "@common/hooks/http.ts";
@@ -36,6 +36,7 @@ const SystemInsideUpstreamContent= forwardRef<SystemInsideUpstreamContentHandle>
const { setBreadcrumb } = useBreadcrumb()
const [form] = Form.useForm();
const {state} = useGlobalContext()
const navigate = useNavigate()
useImperativeHandle(ref, () => ({
save:()=>formRef.current?.save()
@@ -110,7 +111,8 @@ const globalConfigNodesRule: FormItemProps['rules'] = [
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
title: $t('服务'),
onClick: () => navigate('/service/list')
},
{
title: $t('上游')
@@ -127,7 +129,7 @@ const globalConfigNodesRule: FormItemProps['rules'] = [
const ProxyHeadeerConfig = useMemo(()=>PROXY_HEADER_CONFIG.map((x)=>({
...x,
...(x.key === 'optType' ? {
component: <Select className="w-INPUT_NORMAL" options={UPSTREAM_PROXY_HEADER_TYPE_OPTIONS.map((x)=>({...x, label:$t(x.label)}))}/>
component: <Select showSearch optionFilterProp="label" className="w-INPUT_NORMAL" options={UPSTREAM_PROXY_HEADER_TYPE_OPTIONS.map((x)=>({...x, label:$t(x.label)}))}/>
} : {})
}))
,[state.language])
@@ -173,7 +175,7 @@ const globalConfigNodesRule: FormItemProps['rules'] = [
name="scheme"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={schemeOptions}>
<Select showSearch optionFilterProp="label" className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={schemeOptions}>
</Select>
</Form.Item>
@@ -190,7 +192,7 @@ const globalConfigNodesRule: FormItemProps['rules'] = [
name="passHost"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={passHostOptions} onChange={(val)=>setFormShowHost(val === 'rewrite')}>
<Select showSearch optionFilterProp="label" className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={passHostOptions} onChange={(val)=>setFormShowHost(val === 'rewrite')}>
</Select>
</Form.Item>
@@ -1,215 +1,257 @@
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState} from "react";
import {App, Button, Form, Input, Row, Select} from "antd";
import {Link, useLocation, useNavigate, useParams} from "react-router-dom";
import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx";
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'
import { App, Button, Form, Input, Row, Select } from 'antd'
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { v4 as uuidv4 } from 'uuid'
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {MemberItem} from "@common/const/type.ts";
import {useFetch} from "@common/hooks/http.ts";
import {DefaultOptionType} from "antd/es/cascader";
import { TeamConfigFieldType } from "../../const/team/type.ts";
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext.tsx";
import { useTeamContext } from "../../contexts/TeamContext.tsx";
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
import { $t } from "@common/locales/index.ts";
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { MemberItem } from '@common/const/type.ts'
import { useFetch } from '@common/hooks/http.ts'
import { DefaultOptionType } from 'antd/es/cascader'
import { TeamConfigFieldType } from '../../const/team/type.ts'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
import { useTeamContext } from '../../contexts/TeamContext.tsx'
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'
import { $t } from '@common/locales/index.ts'
export type TeamConfigHandle = {
save:()=>Promise<string|boolean>|undefined
save: () => Promise<string | boolean> | undefined
}
type TeamConfigProps = {
entity?:TeamConfigFieldType
entity?: TeamConfigFieldType
}
const TeamConfig= forwardRef<TeamConfigHandle,TeamConfigProps>((props,ref) => {
const {entity} = props
const { message } = App.useApp()
const { teamId } = useParams<RouterParams>();
const [onEdit, setOnEdit] = useState<boolean>(!!teamId)
const [form] = Form.useForm();
const location = useLocation()
const currentUrl = location.pathname
const {fetchData} = useFetch()
const [managerOption, setManagerOption] = useState<DefaultOptionType[]>([])
const { setBreadcrumb} = useBreadcrumb()
const { setTeamInfo } =useTeamContext()
const {checkPermission,accessInit,state} = useGlobalContext()
const pageType= useMemo(()=>{
if(!accessInit) return 'myteam'
return checkPermission('system.workspace.team.view_all') ? 'manage' : 'myteam'
},[checkPermission,accessInit])
const [canDelete, setCanDelete] = useState<boolean>(false)
const navigateTo = useNavigate()
useImperativeHandle(ref, () => ({
save:onFinish
}));
const onFinish = () => {
return form.validateFields().then((value)=>{
let params:{[k:string]:string} = {}
if(pageType === 'manage'){
params = {id:teamId!}
}else{
params = {team:teamId!}
}
return fetchData<BasicResponse<{team:TeamConfigFieldType}>>(pageType === 'manage'?'manager/team' : 'team',{method:onEdit ? 'PUT' : 'POST', eoParams:params,eoBody:(value),eoTransformKeys:['teamId']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
setTeamInfo?.(data.team)
return Promise.resolve(true)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
return Promise.reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=>{
return Promise.reject(errorInfo)
})
})
};
const TeamConfig = forwardRef<TeamConfigHandle, TeamConfigProps>((props, ref) => {
const { entity } = props
const { message } = App.useApp()
const { teamId } = useParams<RouterParams>()
const [onEdit, setOnEdit] = useState<boolean>(!!teamId)
const [form] = Form.useForm()
const location = useLocation()
const currentUrl = location.pathname
const { fetchData } = useFetch()
const [managerOption, setManagerOption] = useState<DefaultOptionType[]>([])
const { setBreadcrumb } = useBreadcrumb()
const { setTeamInfo } = useTeamContext()
const { checkPermission, accessInit, state } = useGlobalContext()
const pageType = useMemo(() => {
if (!accessInit) return 'myteam'
return checkPermission('system.workspace.team.view_all') ? 'manage' : 'myteam'
}, [checkPermission, accessInit])
// 获取表单默认值
const getTeamInfo = () => {
fetchData<BasicResponse<{ team: TeamConfigFieldType }>>(pageType === 'manage'?'manager/team' : 'team',{method:'GET',eoParams:(pageType === 'manage'? {id:teamId}:{team:teamId}),eoTransformKeys:['can_delete']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setCanDelete(data.team.canDelete)
setTimeout(()=>{form.setFieldsValue({...data.team})},0)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
};
const [canDelete, setCanDelete] = useState<boolean>(false)
const navigateTo = useNavigate()
useImperativeHandle(ref, () => ({
save: onFinish
}))
const getManagerList = ()=>{
setManagerOption([])
fetchData<BasicResponse<{ members: MemberItem[] }>>('simple/member',{method:'GET'}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setManagerOption(data.members?.map((x:MemberItem)=>{return {
label:x.name, value:x.id
}}) || [])
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
const onFinish = () => {
return form.validateFields().then((value) => {
let params: { [k: string]: string } = {}
if (pageType === 'manage') {
params = { id: teamId! }
} else {
params = { team: teamId! }
}
return fetchData<BasicResponse<{ team: TeamConfigFieldType }>>(pageType === 'manage' ? 'manager/team' : 'team', {
method: onEdit ? 'PUT' : 'POST',
eoParams: params,
eoBody: value,
eoTransformKeys: ['teamId']
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
setTeamInfo?.(data.team)
return Promise.resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return Promise.reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => {
return Promise.reject(errorInfo)
})
})
}
// 获取表单默认值
const getTeamInfo = () => {
fetchData<BasicResponse<{ team: TeamConfigFieldType }>>(pageType === 'manage' ? 'manager/team' : 'team', {
method: 'GET',
eoParams: pageType === 'manage' ? { id: teamId } : { team: teamId },
eoTransformKeys: ['can_delete']
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setCanDelete(data.team.canDelete)
setTimeout(() => {
form.setFieldsValue({ ...data.team })
}, 0)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
const getManagerList = () => {
setManagerOption([])
fetchData<BasicResponse<{ members: MemberItem[] }>>('simple/member', { method: 'GET' }).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setManagerOption(
data.members?.map((x: MemberItem) => {
return {
label: x.name,
value: x.id
}
}) || []
)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
const deleteTeam = () => {
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>(`manager/team`, { method: 'DELETE', eoParams: { id: form.getFieldValue('id') } })
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
navigateTo('/team/list')
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => reject(errorInfo))
})
}
useEffect(() => {
setBreadcrumb([
{
title: $t('团队'),
onClick: () => navigateTo('/team/list')
},
{ title: $t('设置') }
])
}, [state.language])
useEffect(() => {
getManagerList()
if (entity) {
setOnEdit(true)
form.setFieldsValue(entity)
} else if (teamId !== undefined) {
setOnEdit(true)
getTeamInfo()
} else {
setOnEdit(false)
form.setFieldsValue({ id: uuidv4(), master: state?.userData?.uid }) // 清空 initialValues
}
const deleteTeam = ()=>{
return new Promise((resolve, reject)=>{
fetchData<BasicResponse<null>>(`manager/team`,{method:'DELETE',eoParams:{id:form.getFieldValue('id')}}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
navigateTo('/team/list')
return form.setFieldsValue({})
}, [teamId])
resolve(true)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=> reject(errorInfo))
})
}
return (
<>
<div className="overflow-auto h-full w-full pr-PAGE_INSIDE_X">
<WithPermission
access={
onEdit
? currentUrl.split('/')[1] === 'myteam'
? 'team.team.team.edit'
: 'system.organization.team.edit'
: 'system.organization.team.add'
}
>
<Form
layout="vertical"
labelAlign="left"
scrollToFirstError
form={form}
className={`mx-auto`}
name="teamConfig"
onFinish={onFinish}
autoComplete="off"
>
<Form.Item<TeamConfigFieldType>
label={$t('团队名称')}
name="name"
rules={[{ required: true, whitespace: true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
useEffect(() => {
getManagerList()
if(entity){
setOnEdit(true);
form.setFieldsValue(entity)
}else if (teamId !== undefined) {
setBreadcrumb([
{title:<Link to="/team/list">{$t('团队')}</Link>},
{title:$t('设置')}
])
setOnEdit(true);
getTeamInfo();
} else {
setOnEdit(false);
form.setFieldsValue(
{id:uuidv4(),
master:state?.userData?.uid
}); // 清空 initialValues
}
return (form.setFieldsValue({}))
}, [teamId]);
<Form.Item<TeamConfigFieldType>
label={$t('团队 ID')}
name="id"
extra={$t('团队 ID(team_id)可用于检索团队,一旦保存无法修改。')}
rules={[{ required: true, whitespace: true }]}
>
<Input className="w-INPUT_NORMAL" disabled={onEdit} placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
return (
<>
<div className='overflow-auto h-full w-full pr-PAGE_INSIDE_X'>
<WithPermission access={onEdit ?(currentUrl.split('/')[1] === 'myteam'? 'team.team.team.edit':'system.organization.team.edit') : 'system.organization.team.add'}>
<Form
layout='vertical'
labelAlign='left'
scrollToFirstError
form={form}
className={`mx-auto`}
name="teamConfig"
onFinish={onFinish}
autoComplete="off"
>
<Form.Item<TeamConfigFieldType>
label={$t("团队名称")}
name="name"
rules={[{ required: true,whitespace:true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
{!onEdit && (
<Form.Item<TeamConfigFieldType>
label={$t('团队负责人')}
name="master"
extra={$t('负责人对团队内的团队、服务、成员有管理权限')}
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={managerOption}
></Select>
</Form.Item>
)}
<Form.Item<TeamConfigFieldType>
label={$t("团队 ID")}
name="id"
extra={$t("团队 ID(team_id)可用于检索团队,一旦保存无法修改。")}
rules={[{ required: true,whitespace:true }]}
>
<Input className="w-INPUT_NORMAL" disabled={onEdit} placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<TeamConfigFieldType> label={$t('描述')} name="description">
<Input.TextArea className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
{!onEdit &&
<Form.Item<TeamConfigFieldType>
label={$t("团队负责人")}
name="master"
extra={$t("负责人对团队内的团队、服务、成员有管理权限")}
rules={[{required: true}]}
>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={managerOption}>
</Select>
</Form.Item>}
<Form.Item<TeamConfigFieldType>
label={$t("描述")}
name="description"
>
<Input.TextArea className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
{ onEdit &&
<Row className="mb-[10px]"
>
<WithPermission access={['system.organization.team.edit','team.team.team.edit']}><Button type="primary" htmlType="submit">
{$t('保存')}
</Button></WithPermission>
</Row>
}
{onEdit &&
<WithPermission access="system.organization.team.delete" showDisabled={false}>
<div className="bg-[rgb(255_120_117_/_5%)] rounded-[10px] mt-[50px] p-btnrbase pb-0">
<p className="text-left"><span className="font-bold">{$t('删除团队')}</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
<div className="text-left">
<WithPermission access="system.organization.team.delete" disabled={!canDelete} tooltip={canDelete ? '':$t('服务数据清除后,方可删除')}>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger onClick={()=>deleteTeam()}>{$t('删除')}</Button>
</WithPermission>
</div>
</div>
</WithPermission>
}
</Form>
{onEdit && (
<Row className="mb-[10px]">
<WithPermission access={['system.organization.team.edit', 'team.team.team.edit']}>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
</WithPermission>
</div>
</>
)
</Row>
)}
{onEdit && (
<WithPermission access="system.organization.team.delete" showDisabled={false}>
<div className="bg-[rgb(255_120_117_/_5%)] rounded-[10px] mt-[50px] p-btnrbase pb-0">
<p className="text-left">
<span className="font-bold">{$t('删除团队')}</span>
{$t('删除操作不可恢复,请谨慎操作!')}
</p>
<div className="text-left">
<WithPermission
access="system.organization.team.delete"
disabled={!canDelete}
tooltip={canDelete ? '' : $t('服务数据清除后,方可删除')}
>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger onClick={() => deleteTeam()}>
{$t('删除')}
</Button>
</WithPermission>
</div>
</div>
</WithPermission>
)}
</Form>
</WithPermission>
</div>
</>
)
})
export default TeamConfig
export default TeamConfig
@@ -1,347 +1,433 @@
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx"
import {ActionType} from "@ant-design/pro-components";
import {FC, useEffect, useMemo, useRef, useState} from "react";
import {Link, useParams} from "react-router-dom";
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
import {App, Button, Modal, Select} from "antd";
import {BasicResponse, COLUMNS_TITLE, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx";
import {EntityItem, MemberItem} from "@common/const/type.ts";
import { TeamMemberTableListItem } from "../../const/team/type.ts";
import { TEAM_MEMBER_TABLE_COLUMNS } from "../../const/team/const.tsx";
import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx";
import { checkAccess } from "@common/utils/permission.ts";
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
import MemberTransfer, { TransferTableHandle } from "@common/components/aoplatform/MemberTransfer.tsx";
import { DepartmentListItem } from "../../const/member/type.ts";
import {v4 as uuidv4} from 'uuid'
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { $t } from "@common/locales/index.ts";
import PageList, { PageProColumns } from '@common/components/aoplatform/PageList.tsx'
import { ActionType } from '@ant-design/pro-components'
import { FC, useEffect, useMemo, useRef, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
import { App, Button, Modal, Select } from 'antd'
import { BasicResponse, COLUMNS_TITLE, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { useFetch } from '@common/hooks/http.ts'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { EntityItem, MemberItem } from '@common/const/type.ts'
import { TeamMemberTableListItem } from '../../const/team/type.ts'
import { TEAM_MEMBER_TABLE_COLUMNS } from '../../const/team/const.tsx'
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission.tsx'
import { checkAccess } from '@common/utils/permission.ts'
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'
import MemberTransfer, { TransferTableHandle } from '@common/components/aoplatform/MemberTransfer.tsx'
import { DepartmentListItem } from '../../const/member/type.ts'
import { v4 as uuidv4 } from 'uuid'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { $t } from '@common/locales/index.ts'
export const getDepartmentWithMember = (department:(DepartmentListItem & {type?:'department'|'member'})[],departmentMap:Map<string, (MemberItem & {type:'department'|'member'})[]>) : (DepartmentWithMemberItem | undefined)[] =>{
return department?.map((x:DepartmentListItem & {type?:'department'|'member'})=>{
const res = ({
...x,
key:x.id,
title:x.name,
type: x.type || 'department',
children:((x.type === 'member' || (!x.children||x.children.length === 0 )&& (!departmentMap.get(x.id) || departmentMap.get(x.id)!.length === 0))? undefined : [...(x.children && x.children.length > 0 ? getDepartmentWithMember(x.children,departmentMap) : []),...departmentMap.get(x.id) || []])
});
return res})?.filter(node=>node.type === 'member' ||( node.children && node.children.length > 0)) || []
export const getDepartmentWithMember = (
department: (DepartmentListItem & { type?: 'department' | 'member' })[],
departmentMap: Map<string, (MemberItem & { type: 'department' | 'member' })[]>
): (any)[] => {
return (
department
?.map((x: DepartmentListItem & { type?: 'department' | 'member' }) => {
const res = {
...x,
key: x.id,
title: x.name,
type: x.type || 'department',
children:
x.type === 'member' ||
((!x.children || x.children.length === 0) &&
(!departmentMap.get(x.id) || departmentMap.get(x.id)!.length === 0))
? undefined
: [
...(x.children && x.children.length > 0 ? getDepartmentWithMember(x.children, departmentMap) : []),
...(departmentMap.get(x.id) || [])
]
}
return res
})
?.filter((node) => node.type === 'member' || (node.children && node.children.length > 0)) || []
)
}
export const addMemberToDepartment = (departmentMap: Map<string, (MemberItem & {type:'department'|'member'})[]>, departmentId: string, member: MemberItem) => {
const members = departmentMap.get(departmentId) || [];
members.push({...member, type: 'member'});
departmentMap.set(departmentId, members);
export const addMemberToDepartment = (
departmentMap: Map<string, (MemberItem & { type: 'department' | 'member' })[]>,
departmentId: string,
member: MemberItem
) => {
const members = departmentMap.get(departmentId) || []
members.push({ ...member, type: 'member' })
departmentMap.set(departmentId, members)
}
const TeamInsideMember: FC = () => {
const [searchWord, setSearchWord] = useState<string>('')
const { setBreadcrumb } = useBreadcrumb()
const { modal, message } = App.useApp()
const { fetchData } = useFetch()
const { teamId } = useParams<RouterParams>()
const addRef = useRef<TransferTableHandle<TeamMemberTableListItem>>(null)
const pageListRef = useRef<ActionType>(null)
const [allMemberIds, setAllMemberIds] = useState<string[]>([])
const { accessData, state } = useGlobalContext()
const [selectableMemberIds, setSelectableMemberIds] = useState<Set<string>>(new Set())
const [addMemberBtnLoading, setAddMemberBtnLoading] = useState<boolean>(false)
const [modalVisible, setModalVisible] = useState<boolean>(false)
const [addMemberBtnDisabled, setAddMemberBtnDisabled] = useState<boolean>(true)
const [allMemberSelectedDepartIds, setAllMemberSelectedDepartIds] = useState<string[]>([])
const [roleList, setRoleList] = useState<EntityItem[]>([])
const navigator = useNavigate()
const operation: PageProColumns<TeamMemberTableListItem>[] = [
{
title: COLUMNS_TITLE.operate,
key: 'option',
btnNums: 1,
fixed: 'right',
valueType: 'option',
render: (_: React.ReactNode, entity: TeamMemberTableListItem) => [
<TableBtnWithPermission
disabled={!entity.isDelete}
tooltip="暂无权限"
access="team.team.member.edit"
key="delete"
btnType="delete"
onClick={() => {
openModal('remove', entity)
}}
btnTitle="移出团队"
/>
]
}
]
const getDepartmentMemberList = () => {
const topDepartmentId: string = uuidv4()
return Promise.all([
fetchData<BasicResponse<{ department: DepartmentListItem }>>('simple/departments', { method: 'GET' }),
fetchData<BasicResponse<{ members: MemberItem }>>('simple/member', {
method: 'GET',
eoParams: {},
eoTransformKeys: []
})
])
.then(([departmentResponse, memberResponse]) => {
const departmentMap = new Map<string, (MemberItem & { type: 'department' | 'member' })[]>()
memberResponse.data.members.forEach((member: MemberItem) => {
setSelectableMemberIds((pre) => {
pre.add(member.id)
return pre
})
member = { ...member, title: member.name, key: member.id }
if (member.department) {
member.department.forEach((department: EntityItem) => {
addMemberToDepartment(departmentMap, department.id, member)
})
} else {
addMemberToDepartment(departmentMap, '_withoutDepartment', member)
}
})
const finalData = departmentResponse.data.department
? [
{
id: topDepartmentId,
key: topDepartmentId,
name: departmentResponse.data.department.name,
title: departmentResponse.data.department.name,
children: [
...getDepartmentWithMember(departmentResponse.data.department?.children || [], departmentMap),
...(departmentMap.get('_withoutDepartment') || [])
]
}
]
: [...(departmentMap.get('_withoutDepartment') || [])]
let allMemberSelectedFlag: boolean = true
for (const [k, v] of departmentMap) {
if (k !== '_withoutDepartment' && allMemberIds.length > 0) {
// 筛选出部门内没被勾选的用户,如果不存在没勾选用户,需要将部门id放入ids中
if (v.filter((m) => allMemberIds.indexOf(m.id) === -1).length === 0) {
setAllMemberSelectedDepartIds((pre) => [...pre, k])
} else if (['unknown', 'disable'].indexOf(k) === -1) {
allMemberSelectedFlag = false
}
}
}
if (
departmentMap.get('_withoutDepartment')?.filter((x) => allMemberIds.indexOf(x) !== -1).length === 0 &&
allMemberSelectedFlag
) {
setAllMemberSelectedDepartIds((pre) => [...pre, topDepartmentId])
}
return { data: finalData, success: true }
})
.catch(() => ({ data: [], success: false }))
}
const TeamInsideMember:FC = ()=>{
const [searchWord, setSearchWord] = useState<string>('')
const { setBreadcrumb} = useBreadcrumb()
const { modal,message } = App.useApp()
const {fetchData} = useFetch()
const {teamId} = useParams<RouterParams>();
const addRef = useRef<TransferTableHandle<TeamMemberTableListItem>>(null)
const pageListRef = useRef<ActionType>(null);
const [allMemberIds, setAllMemberIds] = useState<string[]>([])
const {accessData,state} = useGlobalContext()
const [selectableMemberIds,setSelectableMemberIds] = useState<Set<string>>(new Set())
const [addMemberBtnLoading, setAddMemberBtnLoading] = useState<boolean>(false)
const [modalVisible, setModalVisible] = useState<boolean>(false)
const [addMemberBtnDisabled, setAddMemberBtnDisabled] = useState<boolean>(true)
const [allMemberSelectedDepartIds, setAllMemberSelectedDepartIds] = useState<string[]>([])
const [roleList, setRoleList] = useState<EntityItem[]>([])
const operation:PageProColumns<TeamMemberTableListItem>[] =[
{
title: COLUMNS_TITLE.operate,
key: 'option',
btnNums:1,
fixed:'right',
valueType: 'option',
render: (_: React.ReactNode, entity: TeamMemberTableListItem) => [
<TableBtnWithPermission disabled={!entity.isDelete} tooltip="暂无权限" access="team.team.member.edit" key="delete" btnType="delete" onClick={()=>{openModal('remove',entity)}} btnTitle="移出团队"/>]
}
]
const getDepartmentMemberList = () => {
const topDepartmentId:string = uuidv4()
return Promise.all([
fetchData<BasicResponse<{department:DepartmentListItem}>>('simple/departments', {method:'GET'}),
fetchData<BasicResponse<{members:MemberItem}>>('simple/member', {method:'GET', eoParams:{}, eoTransformKeys:[]})
]).then(([departmentResponse, memberResponse])=>{
const departmentMap = new Map<string, (MemberItem & {type:'department'|'member'})[]>();
memberResponse.data.members.forEach((member: MemberItem) => {
setSelectableMemberIds((pre)=>{pre.add(member.id);return pre})
member = {...member, title:member.name, key:member.id}
if (member.department) {
member.department.forEach((department: EntityItem) => {
addMemberToDepartment(departmentMap, department.id, member);
});
} else {
addMemberToDepartment(departmentMap, '_withoutDepartment', member);
}
});
const finalData = departmentResponse.data.department
? [
{
id: topDepartmentId,
key:topDepartmentId,
name: departmentResponse.data.department.name,
title:departmentResponse.data.department.name,
children: [
...getDepartmentWithMember(departmentResponse.data.department?.children || [], departmentMap),
...departmentMap.get('_withoutDepartment') || []
]
}
]
: [...departmentMap.get('_withoutDepartment') || []];
let allMemberSelectedFlag:boolean = true
for(const [k,v] of departmentMap){
if(k !== '_withoutDepartment' && allMemberIds.length > 0 ){
// 筛选出部门内没被勾选的用户,如果不存在没勾选用户,需要将部门id放入ids中
if(v.filter(m => allMemberIds.indexOf(m.id) === -1).length === 0){
setAllMemberSelectedDepartIds((pre)=>[...pre, k])
}else if(['unknown','disable'].indexOf(k) === -1){
allMemberSelectedFlag = false
}
}
}
if(departmentMap.get('_withoutDepartment')?.filter(x=>allMemberIds.indexOf(x)!==-1).length === 0 && allMemberSelectedFlag){
setAllMemberSelectedDepartIds((pre)=>[...pre, topDepartmentId])
}
return {data:finalData, success: true}
}).catch(()=>({data:[], success:false}))
}
const getMemberList = ()=>{
return fetchData<BasicResponse<{members:TeamMemberTableListItem}>>('team/members',{method:'GET',eoParams:{keyword:searchWord, team:teamId},eoTransformKeys:['attach_time','is_delete']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
if(!searchWord){
setAllMemberIds(data.members?.map((x:TeamMemberTableListItem)=>x.user.id) || [])
}
return {data:data.members, success: true}
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
return {data:[], success:false}
}
}).catch(() => {
return {data:[], success:false}
})
}
const addMember = (selectableMemberIds:Set<string>)=>{
setAddMemberBtnLoading(true)
const keyFromModal = addRef.current?.selectedRowKeys()
const memberKeyFromModal = keyFromModal?.filter(x => allMemberIds.indexOf(x as string) === -1 && selectableMemberIds.has(x)) || [];
return new Promise((resolve, reject)=>{
fetchData<BasicResponse<null>>('team/member',{method:'POST' ,eoBody:({users:memberKeyFromModal}),eoParams:{team:teamId}}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
manualReloadTable()
cleanModalData()
resolve(true)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=> reject(errorInfo)).finally(()=>setAddMemberBtnLoading(false))
const getMemberList = () => {
return fetchData<BasicResponse<{ members: TeamMemberTableListItem }>>('team/members', {
method: 'GET',
eoParams: { keyword: searchWord, team: teamId },
eoTransformKeys: ['attach_time', 'is_delete']
})
}
const removeMember = (entity:TeamMemberTableListItem) =>{
return new Promise((resolve, reject)=>{
fetchData<BasicResponse<null>>(`team/member`,{method:'DELETE',eoParams:{team:teamId,user:entity.user.id}}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
resolve(true)
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=> reject(errorInfo))
})
}
const cleanModalData = ()=>{
setModalVisible(false);setAddMemberBtnDisabled(true);setAddMemberBtnLoading(false)
}
const openModal = async (type:'add'|'remove',entity?:TeamMemberTableListItem)=>{
let title:string = ''
let content:string|React.ReactNode = ''
switch(type){
case 'add':
setModalVisible(true)
setAddMemberBtnDisabled(true)
setAddMemberBtnLoading(false)
return
case 'remove':
title=$t('移除成员')
content=<span>{$t('确定删除成员?此操作无法恢复,确认操作?')}</span>
break
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
if (!searchWord) {
setAllMemberIds(data.members?.map((x: TeamMemberTableListItem) => x.user.id) || [])
}
return { data: data.members, success: true }
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return { data: [], success: false }
}
modal.confirm({
title,
content,
onOk:()=>{
return removeMember(entity!).then((res)=>{if(res === true) manualReloadTable()})
},
width:600,
okText:$t('确认'),
okButtonProps:{
disabled: !checkAccess(`team.team.member.edit`,accessData)
},
cancelText:$t('取消'),
closable:true,
icon:<></>
})
.catch(() => {
return { data: [], success: false }
})
}
const addMember = (selectableMemberIds: Set<string>) => {
setAddMemberBtnLoading(true)
const keyFromModal = addRef.current?.selectedRowKeys()
const memberKeyFromModal =
keyFromModal?.filter((x) => allMemberIds.indexOf(x as string) === -1 && selectableMemberIds.has(x)) || []
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>('team/member', {
method: 'POST',
eoBody: { users: memberKeyFromModal },
eoParams: { team: teamId }
})
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
manualReloadTable()
cleanModalData()
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => reject(errorInfo))
.finally(() => setAddMemberBtnLoading(false))
})
}
const removeMember = (entity: TeamMemberTableListItem) => {
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>(`team/member`, {
method: 'DELETE',
eoParams: { team: teamId, user: entity.user.id }
})
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
})
.catch((errorInfo) => reject(errorInfo))
})
}
const cleanModalData = () => {
setModalVisible(false)
setAddMemberBtnDisabled(true)
setAddMemberBtnLoading(false)
}
const openModal = async (type: 'add' | 'remove', entity?: TeamMemberTableListItem) => {
let title: string = ''
let content: string | React.ReactNode = ''
switch (type) {
case 'add':
setModalVisible(true)
setAddMemberBtnDisabled(true)
setAddMemberBtnLoading(false)
return
case 'remove':
title = $t('移除成员')
content = <span>{$t('确定删除成员?此操作无法恢复,确认操作?')}</span>
break
}
const manualReloadTable = () => {
pageListRef.current?.reload()
};
const changeMemberInfo = (value:string[],entity:TeamMemberTableListItem )=>{
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>(`team/member/role`, {method: 'PUT',eoBody:({roles:value, users:[entity.user.id]}), eoParams: {team:teamId}}).then(response => {
const {code, msg} = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=> reject(errorInfo))
modal.confirm({
title,
content,
onOk: () => {
return removeMember(entity!).then((res) => {
if (res === true) manualReloadTable()
})
}
const getRoleList = ()=>{
fetchData<BasicResponse<{roles:EntityItem[]}>>('simple/roles', {method: 'GET', eoParams: {group:'team'}}).then(response => {
const {code, data,msg} = response
if (code === STATUS_CODE.SUCCESS) {
setRoleList(data.roles)
return
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
},
width: 600,
okText: $t('确认'),
okButtonProps: {
disabled: !checkAccess(`team.team.member.edit`, accessData)
},
cancelText: $t('取消'),
closable: true,
icon: <></>
})
}
const manualReloadTable = () => {
pageListRef.current?.reload()
}
const changeMemberInfo = (value: string[], entity: TeamMemberTableListItem) => {
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>(`team/member/role`, {
method: 'PUT',
eoBody: { roles: value, users: [entity.user.id] },
eoParams: { team: teamId }
})
.then((response) => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t(RESPONSE_TIPS.success))
resolve(true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
}
})
}
.catch((errorInfo) => reject(errorInfo))
})
}
const translatedCol = useMemo(()=>{
const res = TEAM_MEMBER_TABLE_COLUMNS?.map(x=>{
if(x.dataIndex === 'roles'){
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title,
render: (_,entity)=>(
<WithPermission access="team.team.member.edit">
<Select
className="w-full"
mode="multiple"
maxTagCount="responsive"
value={entity.roles?.map((x:EntityItem)=>x.id)}
options={roleList?.map((x:{id:string,name:string})=>({label:(x.name), value:x.id}))}
onChange={(value)=>{
changeMemberInfo(value,entity ).then((res)=>{
if(res) manualReloadTable()
})
}}
/>
</WithPermission>
),
filters:roleList?.map((x:{id:string,name:string})=>({text:x.name, value:x.id})),
onFilter:(value: unknown, record:TeamMemberTableListItem) =>{
return record.roles ? record.roles?.map((x)=>x.id).indexOf(value as string) !== -1 : false;}
}
}
return({...x, title: typeof x.title === 'string' ? $t(x.title as string) : x.title}) })
return res
},[ state.language,roleList])
const getRoleList = () => {
fetchData<BasicResponse<{ roles: EntityItem[] }>>('simple/roles', {
method: 'GET',
eoParams: { group: 'team' }
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setRoleList(data.roles)
return
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
useEffect(() => {
setBreadcrumb([
{title:<Link to="/team/list">{$t('团队')}</Link>},
{title:$t('成员')}
])
manualReloadTable()
}, [teamId]);
const translatedCol = useMemo(() => {
const res = TEAM_MEMBER_TABLE_COLUMNS?.map((x) => {
if (x.dataIndex === 'roles') {
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title,
render: (_, entity) => (
<WithPermission access="team.team.member.edit">
<Select
showSearch
optionFilterProp="label"
className="w-full"
mode="multiple"
maxTagCount="responsive"
value={entity.roles?.map((x: EntityItem) => x.id)}
options={roleList?.map((x: { id: string; name: string }) => ({ label: x.name, value: x.id }))}
onChange={(value) => {
changeMemberInfo(value, entity).then((res) => {
if (res) manualReloadTable()
})
}}
/>
</WithPermission>
),
filters: roleList?.map((x: { id: string; name: string }) => ({ text: x.name, value: x.id })),
onFilter: (value: unknown, record: TeamMemberTableListItem) => {
return record.roles ? record.roles?.map((x) => x.id).indexOf(value as string) !== -1 : false
}
}
}
return { ...x, title: typeof x.title === 'string' ? $t(x.title as string) : x.title }
})
return res
}, [state.language, roleList])
useEffect(() => {
manualReloadTable()
}, [teamId])
useEffect(()=>{
getRoleList()
},[state.language])
useEffect(() => {
setBreadcrumb([
{
title: $t('团队'),
onClick: () => navigator('/team/list')
},
{ title: $t('成员') }
])
getRoleList()
}, [state.language])
const treeDisabledData = useMemo(()=>{ return [...allMemberIds,...allMemberSelectedDepartIds]},[allMemberIds,allMemberSelectedDepartIds])
return (
<>
<PageList
id="global_team_member"
ref={pageListRef}
columns = {[...translatedCol,...operation]}
request={()=>getMemberList()}
primaryKey="user.id"
addNewBtnTitle={$t('添加成员')}
className="ml-[20px] mt-[20px] "
searchPlaceholder={$t("输入姓名查找")}
onAddNewBtnClick={()=>{openModal('add')}}
addNewBtnAccess="team.team.member.add"
tableClickAccess="team.team.member.edit"
onSearchWordChange={(e)=>{setSearchWord(e.target.value)}}
const treeDisabledData = useMemo(() => {
return [...allMemberIds, ...allMemberSelectedDepartIds]
}, [allMemberIds, allMemberSelectedDepartIds])
return (
<>
<PageList
id="global_team_member"
ref={pageListRef}
columns={[...translatedCol, ...operation]}
request={() => getMemberList()}
primaryKey="user.id"
addNewBtnTitle={$t('添加成员')}
className="ml-[20px] mt-[20px] "
searchPlaceholder={$t('输入姓名查找')}
onAddNewBtnClick={() => {
openModal('add')
}}
addNewBtnAccess="team.team.member.add"
tableClickAccess="team.team.member.edit"
onSearchWordChange={(e) => {
setSearchWord(e.target.value)
}}
/>
<Modal
title={$t('添加成员')}
open={modalVisible}
destroyOnClose={true}
width={600}
onCancel={() => cleanModalData()}
maskClosable={false}
footer={[
<Button key="back" onClick={() => cleanModalData()}>
{$t('取消')}
</Button>,
<WithPermission access="team.team.member.add">
<Button
key="submit"
type="primary"
disabled={addMemberBtnDisabled}
loading={addMemberBtnLoading}
onClick={() => addMember(selectableMemberIds as Set<string>)}
>
{$t('确认')}
</Button>
</WithPermission>
]}
>
<MemberTransfer
ref={addRef}
primaryKey="id"
disabledData={treeDisabledData}
request={() => getDepartmentMemberList()}
onSelect={(selectedData: Set<string>) => {
const memberKeyFromModal =
Array.from(selectedData)?.filter((x) => allMemberIds.indexOf(x) === -1 && selectableMemberIds.has(x)) ||
[]
setAddMemberBtnDisabled(memberKeyFromModal.length === 0)
}}
searchPlaceholder={$t('输入名称查找用户')}
/>
<Modal
title={$t("添加成员")}
open={modalVisible}
destroyOnClose={true}
width={600}
onCancel={() => cleanModalData()}
maskClosable={false}
footer={[
<Button key="back" onClick={() => cleanModalData()}>
{$t('取消')}
</Button>,
<WithPermission access="team.team.member.add"><Button
key="submit"
type="primary"
disabled={addMemberBtnDisabled}
loading={addMemberBtnLoading}
onClick={()=>addMember(selectableMemberIds as Set<string>)}
>
{$t('确认')}
</Button></WithPermission>,
]}
>
<MemberTransfer
ref={addRef}
primaryKey="id"
disabledData={treeDisabledData}
request={()=>getDepartmentMemberList()}
onSelect={(selectedData: Set<string>) => {
const memberKeyFromModal = Array.from(selectedData)?.filter(x => allMemberIds.indexOf(x) === -1 &&selectableMemberIds.has(x)) || [];
setAddMemberBtnDisabled((memberKeyFromModal.length === 0));
}}
searchPlaceholder={$t("输入名称查找用户")}
/>
</Modal>
</>
)
</Modal>
</>
)
}
export default TeamInsideMember
export default TeamInsideMember
@@ -187,7 +187,7 @@ export default function MonitorApiPage(props: MonitorApiPageProps) {
}
return (
<div className="overflow-hidden h-full">
<div className="overflow-hidden h-full pr-PAGE_INSIDE_X">
<ScrollableSection>
<div className="pl-btnbase pr-btnrbase pb-btnbase content-before">
<TimeRangeSelector
@@ -200,6 +200,8 @@ export default function MonitorApiPage(props: MonitorApiPageProps) {
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
<label className="inline-block whitespace-nowrap">{$t('服务')}</label>
<Select
showSearch
optionFilterProp="label"
className="w-[346px]"
value={queryData?.services}
options={projectOptionList}
@@ -216,6 +218,8 @@ export default function MonitorApiPage(props: MonitorApiPageProps) {
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
<label className=" whitespace-nowrap inline-block w-[42px] text-right">API </label>
<Select
showSearch
optionFilterProp="label"
className="w-[346px]"
value={queryData?.apis}
options={apiOptionList}
@@ -164,7 +164,7 @@ export default function MonitorAppPage(props: MonitorAppPageProps) {
}
return (
<div className="h-full overflow-hidden">
<div className="h-full overflow-hidden pr-PAGE_INSIDE_X">
<div className="pl-btnbase pr-btnrbase pb-btnybase">
<TimeRangeSelector
initialTimeButton={timeButton}
@@ -176,6 +176,8 @@ export default function MonitorAppPage(props: MonitorAppPageProps) {
<div>
<label className="inline-block whitespace-nowrap">{$t('消费者')}</label>
<Select
showSearch
optionFilterProp="label"
className="w-[346px]"
mode="multiple"
maxTagCount={1}
@@ -169,7 +169,7 @@ export default function MonitorSubPage(props: MonitorSubPageProps) {
}
return (
<div className="overflow-hidden h-full">
<div className="overflow-hidden h-full pr-PAGE_INSIDE_X">
<div className="pl-btnbase pr-btnrbase pb-btnybase">
<TimeRangeSelector
initialTimeButton={timeButton}
@@ -181,6 +181,8 @@ export default function MonitorSubPage(props: MonitorSubPageProps) {
<div>
<label className="inline-block whitespace-nowrap"></label>
<Select
showSearch
optionFilterProp="label"
className="w-[346px]"
mode="multiple"
maxTagCount={1}
@@ -7,49 +7,16 @@ import { RouterParams } from '@common/const/type'
export default function DashboardTabPage() {
const { dashboardType } = useParams<RouterParams>()
const [activeKey, setActiveKey] = useState<string>('total')
const navigateTo = useNavigate()
useEffect(() => {
setActiveKey(dashboardType || 'total')
const activeKey = dashboardType || 'total'
navigateTo(`/analytics/${activeKey === 'total' ? activeKey : `${activeKey}/list`}`)
}, [dashboardType])
const monitorTabItems: TabsProps['items'] = [
{
label: $t('监控总览'),
key: 'total',
children: <DashboardTotal />
},
{
label: $t('服务被调用统计'),
key: 'subscriber',
children: <Outlet />
},
{
label: $t('消费者调用统计'),
key: 'provider',
children: <Outlet />
},
{
label: $t('API 调用统计'),
key: 'api',
children: <Outlet />
}
]
return (
<>
<Tabs
activeKey={activeKey}
onChange={(val) => {
setActiveKey(val)
navigateTo(`/analytics/${val === 'total' ? val : `${val}/list`}`)
}}
items={monitorTabItems}
className="h-full overflow-hidden mt-[6px] [&>.ant-tabs-content-holder]:overflow-auto [&>.ant-tabs-content-holder]:pr-PAGE_INSIDE_X [&>.ant-tabs-content-holder>.ant-tabs-content]:h-full [&>.ant-tabs-content-holder>.ant-tabs-content>.ant-tabs-tabpane]:h-full"
size="small"
tabBarStyle={{ paddingLeft: '10px', marginTop: '0px', marginBottom: '0px' }}
/>
<Outlet />
</>
)
}
@@ -17,6 +17,8 @@ export type ServiceBasicInfoType = {
approvalType: 'auto' | 'manual'
serviceKind: 'ai' | 'rest'
sitePrefix?: string
enableMcp: boolean
invokeCount: number
}
export type ServiceDetailType = {
@@ -25,6 +27,9 @@ export type ServiceDetailType = {
basic: ServiceBasicInfoType
apiDoc: string
applied: boolean
mcpServerAddress?: string
mcpAccessConfig?: string
openapiAddress?: string
}
export type ServiceHubCategoryConfigFieldType = {
@@ -54,9 +59,12 @@ export type ServiceHubTableListItem = {
tags?: EntityItem[]
catalogue: EntityItem
apiNum: number
subscribeNum: number
subscriberNum: number
description: string
logo: string
enableMcp: boolean
serviceKind: 'ai' | 'rest'
invokeCount: number
}
export type ApplyServiceProps = {
+5
View File
@@ -1053,6 +1053,11 @@ p{
.ant-table-wrapper .ant-table{
scrollbar-color: none !important;
}
.ant-select .ant-select-clear {
height:16px !important;
width: 16px !important;
top: 45%;
}
.eo_page_drag .ant-table-body{
overflow-y: auto !important;
@@ -2,7 +2,7 @@ import WithPermission from '@common/components/aoplatform/WithPermission'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import { App, Col, Form, Input, Row, Select } from 'antd'
import { App, Col, Form, Input, Row, Select, Tooltip } from 'antd'
import { forwardRef, useEffect, useImperativeHandle } from 'react'
import { ApplyServiceHandle, ApplyServiceProps } from '../../const/serviceHub/type'
@@ -70,11 +70,23 @@ export const ApplyServiceModal = forwardRef<ApplyServiceHandle, ApplyServiceProp
</Row>
<Form.Item label={$t('消费者')} name="applications" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
disabled={reApply}
placeholder={$t('搜索或选择消费者')}
mode="multiple"
options={mySystemOptionList?.filter((x) => x.value !== entity.id)}
optionRender={(option) => {
if (option.data.disabled) {
return (
<Tooltip title={$t('该消费者已订阅')}>
<div>{option.data.label}</div>
</Tooltip>
)
}
return <div>{option.data.label}</div>
}}
/>
</Form.Item>
{entity.approvalType === 'manual' && (
@@ -1,4 +1,4 @@
import { ApiFilled, ArrowLeftOutlined } from '@ant-design/icons'
import { ApiFilled, ApiOutlined, ArrowLeftOutlined } from '@ant-design/icons'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { EntityItem, RouterParams } from '@common/const/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
@@ -6,15 +6,27 @@ import { useFetch } from '@common/hooks/http.ts'
import { $t } from '@common/locales/index.ts'
import { Icon } from '@iconify/react/dist/iconify.js'
import { approvalTypeTranslate } from '@market/const/serviceHub/const.tsx'
import { App, Avatar, Button, Descriptions, Divider, Tabs } from 'antd'
import { App, Avatar, Button, Card, Descriptions, Divider, Tabs, Tag, Tooltip } from 'antd'
import { DefaultOptionType } from 'antd/es/cascader'
import DOMPurify from 'dompurify'
import { useEffect, useRef, useState } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { ApplyServiceHandle, ServiceBasicInfoType, ServiceDetailType } from '../../const/serviceHub/type.ts'
import { ApplyServiceModal } from './ApplyServiceModal.tsx'
import ServiceHubApiDocument from './ServiceHubApiDocument.tsx'
import Integrate from './integrate.tsx'
import { SERVICE_KIND_OPTIONS } from '@core/const/system/const.tsx'
import { IntegrationAIContainer, IntegrationAIContainerRef } from '@core/pages/mcpService/IntegrationAIContainer.tsx'
import { Tool } from '@modelcontextprotocol/sdk/types.js'
import McpToolsContainer from '@core/pages/mcpService/McpToolsContainer.tsx'
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'
import TopBreadcrumb from '@common/components/aoplatform/Breadcrumb.tsx'
type TabItemType = {
key: string
label: string
children: React.ReactNode
icon?: React.ReactNode
}
const ServiceHubDetail = () => {
const { serviceId } = useParams<RouterParams>()
@@ -28,14 +40,24 @@ const ServiceHubDetail = () => {
const { modal, message } = App.useApp()
const [mySystemOptionList, setMySystemOptionList] = useState<DefaultOptionType[]>()
const [service, setService] = useState<ServiceDetailType>()
const [serviceMetrics, setServiceMetrics] = useState<{ title: string; icon: React.ReactNode; value: string }[]>([])
const [serviceTags, setServiceTags] = useState<
{ color: string; textColor: string; title: string; content: React.ReactNode }[]
>([])
const [tools, setTools] = useState<Tool[]>([])
const [tabItem, setTabItem] = useState<TabItemType[]>([])
const [currentTab, setCurrentTab] = useState('')
const { state } = useGlobalContext()
const integrationAIContainerRef = useRef<IntegrationAIContainerRef>(null)
const navigate = useNavigate()
const modifyApiDoc = (apiDoc: string, apiPrefix: string) => {
if (!apiDoc) return ''
if (!apiPrefix) return apiDoc
try {
const openApiSpec = JSON.parse(apiDoc)
// 遍历并修改 paths,给每个路径添加前缀
// 遍历并修改paths,给每个路径添加前缀
const modifiedPaths: Record<string, unknown> = {}
for (const [path, pathItem] of Object.entries(openApiSpec.paths)) {
modifiedPaths[apiPrefix + path] = pathItem
@@ -43,7 +65,59 @@ const ServiceHubDetail = () => {
openApiSpec.paths = modifiedPaths
return JSON.stringify(openApiSpec)
} catch (err) {
console.warn('拼接api前缀失败', err)
// 针对YAML格式或特殊格式的文本,直接进行字符串处理
try {
if (apiDoc.includes('paths:') && apiDoc.includes('openapi:')) {
// 在paths:后面的路径前添加前缀
// 找到paths:行的位置
const pathsIndex = apiDoc.indexOf('paths:')
if (pathsIndex !== -1) {
try {
// 在paths:之后的每个路径(以/开头的行)添加前缀
let result = apiDoc.substring(0, pathsIndex + 6) // 包含'paths:'
const rest = apiDoc.substring(pathsIndex + 6)
// 添加servers部分
if (!apiDoc.includes('servers:')) {
const serverConfig = `info:
title: API Space API
version: 1.0.0
openapi: 3.0.1
servers:
- url: ${apiPrefix}
description: 默认服务器
`
result = serverConfig + result.substring(result.indexOf('paths:'))
}
// 处理路径
const lines = rest.split('\n')
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
const trimmedLine = line.trim()
// 检测是否是路径行
if (trimmedLine.match(/^\//)) {
// 这是一个路径行
const indentation = line.substring(0, line.indexOf('/'))
const pathWithoutIndent = line.substring(line.indexOf('/'))
lines[i] = indentation + apiPrefix + pathWithoutIndent
}
}
return result + lines.join('\n')
} catch (yamlProcessingError) {
console.warn('处理YAML格式的API文档时出错', yamlProcessingError)
// 处理失败时返回原始文档
return apiDoc
}
}
}
} catch (outerError) {
console.warn('拼接api前缀失败', outerError)
return apiDoc
}
}
return apiDoc
}
@@ -60,7 +134,12 @@ const ServiceHubDetail = () => {
'invoke_address',
'approval_type',
'service_kind',
'site_prefix'
'site_prefix',
'enable_mcp',
'mcp_server_address',
'mcp_access_config',
'openapi_address',
'invoke_count'
]
}).then((response) => {
const { code, data, msg } = response
@@ -73,12 +152,66 @@ const ServiceHubDetail = () => {
setServiceName(data.service.name)
setServiceDesc(data.service.description)
setServiceDoc(DOMPurify.sanitize(data.service.document))
setServiceMetricsList(data.service.basic)
setTabItemList(data.service.basic)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
const handleTabChange = (value: any) => {
setCurrentTab(value)
}
const setServiceMetricsList = (serviceBasicInfo: ServiceBasicInfoType) => {
// 设置服务指标数据
setServiceMetrics([
{
title: 'API 数量',
icon: <ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]" />,
value: serviceBasicInfo.apiNum.toString()
},
{
title: '接入消费者数量',
icon: <Icon icon="tabler:api-app" width="14" height="14" />,
value: serviceBasicInfo.appNum.toString()
},
{
title: '30天内调用次数',
icon: <Icon icon="iconoir:graph-up" width="14" height="14" />,
value: formatInvokeCount(serviceBasicInfo.invokeCount ?? 0)
}
])
// 设置服务标签数据
const tags = [
{
color: '#7371fc1b',
textColor: 'text-theme',
title: serviceBasicInfo?.catalogue?.name || '-',
content: serviceBasicInfo?.catalogue?.name || '-'
},
{
color: `#${serviceBasicInfo?.serviceKind === 'ai' ? 'EADEFF' : 'DEFFE7'}`,
textColor: 'text-[#000]',
title: serviceBasicInfo?.serviceKind || '-',
content: SERVICE_KIND_OPTIONS.find((x) => x.value === serviceBasicInfo?.serviceKind)?.label || '-'
}
]
// 如果启用了MCP,添加MCP标签
if (serviceBasicInfo?.enableMcp) {
tags.push({
color: '#FFF0C1',
textColor: 'text-[#000]',
title: 'MCP',
content: 'MCP'
})
}
setServiceTags(tags)
}
useEffect(() => {
if (!serviceId) {
console.warn('缺少serviceId')
@@ -89,21 +222,41 @@ const ServiceHubDetail = () => {
useEffect(() => {
getMySelectList()
setBreadcrumb([{ title: <Link to={`/serviceHub/list`}>{$t('服务市场')}</Link> }, { title: $t('服务详情') }])
}, [])
useEffect(() => {
setBreadcrumb([
{
title: $t('API 门户'),
onClick: () => navigate(`/serviceHub/list`)
},
{ title: $t('服务详情') }
])
}, [state.language])
const getMySelectList = () => {
setMySystemOptionList([])
fetchData<BasicResponse<{ app: EntityItem[] }>>('apps/can_subscribe', { method: 'GET' }).then((response) => {
fetchData<BasicResponse<{ app: EntityItem[] }>>('apps/can_subscribe', {
method: 'GET',
eoParams: { service: serviceId },
eoTransformKeys: ['is_subscribed']
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setMySystemOptionList(
data.app?.map((x: EntityItem) => {
return {
label: x.name,
value: x.id
}
})
data.app
?.sort((a: EntityItem, b: EntityItem) => {
// 已订阅的排在后面
if (a.isSubscribed && !b.isSubscribed) return 1
if (!a.isSubscribed && b.isSubscribed) return -1
return 0
})
.map((x: EntityItem) => {
return {
label: x.name,
value: x.id,
disabled: x.isSubscribed // 已订阅的设为禁用
}
})
)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -123,7 +276,10 @@ const ServiceHubDetail = () => {
),
onOk: () => {
return applyRef.current?.apply().then((res) => {
// if(res === true) setApplied(true)
if (res === true) {
integrationAIContainerRef.current?.getServiceKeysList()
getMySelectList()
}
})
},
okText: $t('确认'),
@@ -134,120 +290,233 @@ const ServiceHubDetail = () => {
})
}
const items = [
{
key: 'introduction',
label: $t('介绍'),
children: (
<>
<div
className="p-btnbase preview-document mb-PAGE_INSIDE_B"
dangerouslySetInnerHTML={{ __html: serviceDoc || '' }}
></div>
</>
),
icon: <Icon icon="ic:baseline-space-dashboard" width="14" height="14" />
},
{
key: 'api-document',
label: $t('API 文档'),
children: (
<div
className={`p-btnbase ${serviceBasicInfo?.serviceKind?.toLocaleLowerCase() === 'ai' ? 'ai-service-api-preview' : ''}`}
>
<ServiceHubApiDocument service={service!} />
</div>
),
icon: <ApiFilled />
},
{
key: 'api-integrate',
label: $t('集成'),
children: (
<div
className={`p-btnbase ${serviceBasicInfo?.serviceKind?.toLocaleLowerCase() === 'ai' ? 'ai-service-api-preview' : ''}`}
>
<Integrate service={service!} />
</div>
),
icon: <Icon icon="icon-park-solid:whole-site-accelerator" width="15" height="15" />
const handleToolsChange = (value: Tool[]) => {
setTools(value)
}
// 格式化调用次数,添加K和M单位
const formatInvokeCount = (count: number | null | undefined): string => {
if (count === null || count === undefined) return '-'
if (count >= 1000000) {
const value = Math.floor(count / 100000) / 10
return `${value}M`
}
]
if (count >= 1000) {
const value = Math.floor(count / 100) / 10
return `${value}K`
}
return count.toString()
}
/**
* serviceBasicInfo或tools变化时调用
*/
const updateTabItems = useCallback(() => {
if (!serviceBasicInfo) return
const descriptionItem = [
{
label: $t('供应方'),
value: serviceBasicInfo?.team?.name || '-',
className: 'pb-[10px]'
},
{
label: $t('版本'),
value: serviceBasicInfo?.version || '-',
className: 'pb-[10px]'
},
{
label: $t('更新时间'),
value: serviceBasicInfo?.updateTime || '-',
className: 'pb-[10px]',
isTimeString: true
},
{
label: $t('审核'),
value: serviceBasicInfo?.approvalType ? $t(approvalTypeTranslate[serviceBasicInfo?.approvalType] || '-') : '-',
className: 'pb-[0px]'
}
]
const items: TabItemType[] = [
{
key: 'introduction',
label: $t('介绍'),
children: (
<>
<Card
style={{
borderRadius: '10px'
}}
className="w-full h-[calc(100vh-420px)] overflow-auto"
classNames={{
body: 'p-[10px]'
}}
>
<Card
style={{
borderRadius: '10px'
}}
className={`w-full`}
classNames={{
body: 'p-[15px] h-auto bg-[#f8f8f8]'
}}
>
<Descriptions column={1}>
{descriptionItem.map((item, index) => (
<Descriptions.Item key={index} label={item.label} className={item.className}>
{item.isTimeString ? (
<span className="truncate" title={item.value}>
{item.value}
</span>
) : (
item.value
)}
</Descriptions.Item>
))}
</Descriptions>
</Card>
<div
className="p-btnbase preview-document mb-PAGE_INSIDE_B"
dangerouslySetInnerHTML={{ __html: serviceDoc || '' }}
></div>
</Card>
</>
),
icon: <Icon icon="ic:baseline-space-dashboard" width="14" height="14" />
},
{
key: 'api-document',
label: $t('API'),
children: (
<Card
style={{
borderRadius: '10px'
}}
className="w-full h-[calc(100vh-420px)] overflow-auto"
classNames={{
body: 'p-[10px] pt-[0px]'
}}
>
<ServiceHubApiDocument service={service!} />
</Card>
),
icon: <ApiFilled />
}
]
if (serviceBasicInfo.enableMcp) {
items.push({
key: 'MCP',
label: 'MCP',
children: <McpToolsContainer tools={tools} customClassName="h-[calc(100vh-420px)] overflow-auto" />,
icon: <Icon icon="ph:network-x-fill" width="15" height="15" />
})
}
setTabItem(items)
}, [serviceBasicInfo, serviceDoc, service, tools, state.language])
/**
* serviceBasicInfo时调用的函数
* @param _serviceBasicInfo
*/
const setTabItemList = (_serviceBasicInfo: ServiceBasicInfoType) => {
// 只调用更新函数,更新将由useEffect处理
updateTabItems()
}
useEffect(() => {
if (serviceBasicInfo) {
updateTabItems()
}
}, [tools, updateTabItems, serviceBasicInfo])
return (
<section className="grid grid-cols-5 h-full mr-PAGE_INSIDE_X">
<section className="col-span-4 border-0 border-r-[1px] border-solid border-BORDER flex flex-col overflow-hidden">
<section className="flex flex-col gap-btnbase p-btnbase">
<div className="text-[18px] leading-[25px] pb-[12px]">
<Button type="text" onClick={() => navigate(`/serviceHub/list`)}>
<ArrowLeftOutlined className="max-h-[14px]" />
{$t('返回')}
</Button>
</div>
<div className="flex">
{/* <Avatar shape="square" size={50} className=" bg-[linear-gradient(135deg,white,#f0f0f0)] text-[#333] rounded-[12px]" > {service?.name?.substring(0,1)}</Avatar> */}
<Avatar
shape="square"
size={50}
className={`rounded-[12px] border-none rounded-[12px] ${serviceBasicInfo?.logo ? 'bg-[linear-gradient(135deg,white,#f0f0f0)]' : 'bg-theme'}`}
src={
serviceBasicInfo?.logo ? (
<img
src={serviceBasicInfo?.logo}
alt="Logo"
style={{ maxWidth: '200px', width: '45px', height: '45px', objectFit: 'unset' }}
/>
) : undefined
}
icon={serviceBasicInfo?.logo ? '' : <iconpark-icon name="auto-generate-api"></iconpark-icon>}
>
{' '}
</Avatar>
<div className="pl-[20px] w-[calc(100%-50px)]">
<p className="text-[14px] h-[20px] leading-[20px] truncate font-bold flex items-center gap-[4px]">
<div className="pr-[40px]">
<header>
<TopBreadcrumb handleBackCallback={() => navigate(`/serviceHub/list`)} />
</header>
<Card
style={{
borderRadius: '10px',
background: 'linear-gradient(35deg, rgb(246, 246, 260) 0%, rgb(255, 255, 255) 40%)'
}}
className={`w-full mt-[20px]`}
classNames={{
body: 'p-[15px] h-[180px]'
}}
>
<div className="service-info">
<div className="flex items-center">
<div>
<Avatar
shape="square"
size={50}
className={`rounded-[12px] border-none rounded-[12px] ${serviceBasicInfo?.logo ? 'bg-[linear-gradient(135deg,white,#f0f0f0)]' : 'bg-theme'}`}
src={
serviceBasicInfo?.logo ? (
<img
src={serviceBasicInfo?.logo}
alt="Logo"
style={{ maxWidth: '200px', width: '45px', height: '45px', objectFit: 'unset' }}
/>
) : undefined
}
icon={serviceBasicInfo?.logo ? '' : <Icon icon="tabler:api-app" />}
>
{' '}
</Avatar>
</div>
<div className="pl-[20px] w-[calc(100%-50px)] overflow-hidden">
<p className="text-[14px] h-[20px] leading-[20px] truncate font-bold w-full flex items-center gap-[4px]">
{serviceName}
</p>
<div className="mt-[10px] flex flex-col gap-btnrbase font-normal">
<p>{serviceDesc || '-'}</p>
<p className="flex items-center gap-[4px]">
<Icon icon="ic:baseline-link" width="18" height="18" />
<span className="font-bold">{$t('Base URL')}</span>: {serviceBasicInfo?.invokeAddress || '-'}
</p>
<div>
<Button type="primary" onClick={() => openModal('apply')}>
{$t('申请')}
</Button>
</div>
<div className="mt-[5px] h-[20px] flex items-center font-normal">
{serviceTags.map((tag, index) => (
<Tag
key={index}
color={tag.color}
className={`${tag.textColor} font-normal border-0 mr-[12px] max-w-[150px] truncate`}
bordered={false}
title={tag.title}
>
{tag.content}
</Tag>
))}
{serviceMetrics.map((item, index) => (
<Tooltip key={index} title={$t(item.title)}>
<span className="mr-[12px] flex items-center">
<span className="h-[14px] mr-[4px] flex items-center">{item.icon}</span>
<span className="font-normal text-[14px]">{item.value}</span>
</span>
</Tooltip>
))}
</div>
</div>
</div>
</section>
<Tabs className="p-btnbase pr-0 overflow-hidden [&>.ant-tabs-content-holder]:overflow-auto" items={items} />
</section>
<section className="col-span-1 p-btnbase px-btnrbase">
<Descriptions title={$t('服务信息')} column={1} size={'small'}>
<Descriptions.Item label={$t('接入消费者')}>{serviceBasicInfo?.appNum ?? '-'}</Descriptions.Item>
<Descriptions.Item label={$t('供应方')}>{serviceBasicInfo?.team?.name || '-'}</Descriptions.Item>
<Descriptions.Item label={$t('审核')}>
{serviceBasicInfo?.approvalType ? $t(approvalTypeTranslate[serviceBasicInfo?.approvalType] || '-') : '-'}
</Descriptions.Item>
<Descriptions.Item label={$t('分类')}>{serviceBasicInfo?.catalogue?.name || '-'}</Descriptions.Item>
<Descriptions.Item label={$t('标签')}>
{serviceBasicInfo?.tags?.map((x) => x.name)?.join(',') || '-'}
</Descriptions.Item>
</Descriptions>
<Divider />
<Descriptions column={1}>
<Descriptions.Item label={$t('版本')}>{serviceBasicInfo?.version || '-'}</Descriptions.Item>
<Descriptions.Item label={$t('更新时间')}>
<span className="truncate" title={serviceBasicInfo?.updateTime}>
{serviceBasicInfo?.updateTime || '-'}
</span>
</Descriptions.Item>
</Descriptions>
</section>
</section>
<span className="line-clamp-2 mt-[15px] text-[12px] text-[#666]" title={serviceDesc}>
{serviceDesc || $t('暂无服务描述')}
</span>
</div>
<div className="absolute bottom-[15px]">
<Button type="primary" onClick={() => openModal('apply')}>
{$t('申请')}
</Button>
</div>
</Card>
<div className="flex">
<Tabs
className="p-btnbase pr-0 overflow-hidden [&>.ant-tabs-content-holder]:overflow-auto w-full flex-1 mr-[10px]"
onChange={handleTabChange}
items={tabItem}
/>
<IntegrationAIContainer
ref={integrationAIContainerRef}
service={service}
currentTab={currentTab}
serviceId={serviceId}
customClassName="mt-[70px] max-h-[calc(100vh-420px)] overflow-auto"
type={'service'}
openModal={openModal}
handleToolsChange={handleToolsChange}
></IntegrationAIContainer>
</div>
</div>
)
}
@@ -39,6 +39,20 @@ export const ServiceHubGroup = ({ children, filterOption, dispatch }: ServiceHub
dispatch({ type: SERVICE_HUB_LIST_ACTIONS.LIST_LOADING, payload: false })
}
// 递归获取所有分类ID(包括子分类)
const getAllCategoryIds = (categories: CategorizesType[]): string[] => {
let ids: string[] = []
categories.forEach((category) => {
// 添加当前分类ID
ids.push(category.id)
// 如果有子分类,递归获取子分类ID
if (category.children && category.children.length > 0) {
ids = [...ids, ...getAllCategoryIds(category.children)]
}
})
return ids
}
const getTagAndServiceClassifyList = () => {
fetchData<BasicResponse<{ catalogues: CategorizesType[]; tags: EntityItem[] }>>('catalogues', {
method: 'GET'
@@ -50,9 +64,11 @@ export const ServiceHubGroup = ({ children, filterOption, dispatch }: ServiceHub
type: SERVICE_HUB_LIST_ACTIONS.GET_TAGS,
payload: [...data.tags, { id: 'empty', name: $t('无标签') }]
})
// 使用递归函数获取所有分类ID
const allCategoryIds = getAllCategoryIds(data.catalogues)
dispatch({
type: SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_CATE,
payload: [...data.catalogues.map((x: CategorizesType) => x.id)]
payload: allCategoryIds
})
dispatch({
type: SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_TAG,
@@ -103,7 +119,7 @@ export const ServiceHubGroup = ({ children, filterOption, dispatch }: ServiceHub
return (
<div className="flex flex-1 h-full">
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER">
<div className="w-[220px] border-0">
<div className=" h-full">
<Input
className="rounded-SEARCH_RADIUS m-[10px] h-[40px] bg-[#f8f8f8] w-[200px]"
@@ -116,7 +132,7 @@ export const ServiceHubGroup = ({ children, filterOption, dispatch }: ServiceHub
<div className="mt-[20px] ml-[20px] pr-[10px] ">
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">{$t('分类')}</p>
<Tree
className={`no-selected-tree ${transferToTreeData(filterOption.categoriesList).filter((x) => x.children && x.children.length > 0).length > 0 ? '' : 'no-first-switch-tree'}`}
className={`no-selected-tree service-hub-custom-switcher ${transferToTreeData(filterOption.categoriesList).filter((x) => x.children && x.children.length > 0).length > 0 ? '' : 'no-first-switch-tree'}`}
checkable
blockNode={true}
checkedKeys={filterOption.selectedCate}
@@ -130,7 +146,7 @@ export const ServiceHubGroup = ({ children, filterOption, dispatch }: ServiceHub
<div className="ml-[20px] pr-[10px]">
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">{$t('标签')}</p>
<Tree
className="no-first-switch-tree no-selected-tree"
className="no-first-switch-tree no-selected-tree service-hub-custom-switcher"
checkable
blockNode={true}
checkedKeys={filterOption.selectedTag}
@@ -12,6 +12,8 @@ import { useNavigate, useParams } from 'react-router-dom'
import { VirtuosoGrid } from 'react-virtuoso'
import { CategorizesType, ServiceHubTableListItem } from '../../const/serviceHub/type.ts'
import ServiceHubGroup from './ServiceHubGroup.tsx'
import { SERVICE_KIND_OPTIONS } from '@core/const/system/const.tsx'
import { Icon } from '@iconify/react/dist/iconify.js'
export enum SERVICE_HUB_LIST_ACTIONS {
GET_CATEGORIES = 'GET_CATEGORIES',
@@ -43,7 +45,7 @@ export const initialServiceHubListState = {
selectedTag: [] as string[],
keyword: '',
getCateAndTagData: false,
listLoading: false
listLoading: true
}
function reducer(state: typeof initialServiceHubListState, action: ServiceHubListActionType) {
@@ -103,7 +105,7 @@ const ServiceHubList: FC = () => {
dispatch({ type: SERVICE_HUB_LIST_ACTIONS.LIST_LOADING, payload: true })
fetchData<BasicResponse<{ services: ServiceHubTableListItem }>>('catalogue/services', {
method: 'GET',
eoTransformKeys: ['api_num', 'subscriber_num']
eoTransformKeys: ['api_num', 'subscriber_num', 'enable_mcp', 'service_kind', 'invoke_count']
})
.then((response) => {
const { code, data, msg } = response
@@ -140,7 +142,13 @@ const ServiceHubList: FC = () => {
<Spin
className="h-full"
wrapperClassName="h-full"
indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
indicator={
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ transform: 'scale(1.5)' }}>
<LoadingOutlined style={{ fontSize: 30 }} spin />
</div>
</div>
}
spinning={filterOption.listLoading}
>
{filterOption.showServicesList && filterOption.showServicesList.length > 0 ? (
@@ -154,13 +162,14 @@ const ServiceHubList: FC = () => {
<div className="pt-[20px]">
<Card
title={CardTitle(item)}
className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] m-0 transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]"
classNames={{ header: 'border-b-[0px] p-[20px] ', body: 'pt-0' }}
className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[200px] m-0 transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]"
classNames={{ header: 'border-b-[0px] p-[20px] ', body: 'pt-0 h-[110px]' }}
onClick={() => showDocumentDetail(item)}
>
<span className="line-clamp-3 text-[12px] text-[#666] " style={{ 'word-break': 'auto-phrase' }}>
<span className="line-clamp-3 text-[12px] text-[#666]" title={item.description}>
{item.description || $t('暂无服务描述')}
</span>
<CardAction service={item} />
</Card>
</div>
)
@@ -186,7 +195,12 @@ const ServiceHubList: FC = () => {
}}
/>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
<>
{!filterOption.listLoading &&
(!filterOption.showServicesList || filterOption.showServicesList.length === 0) && (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</>
)}
</Spin>
</div>
@@ -222,30 +236,77 @@ const CardTitle = (service: ServiceHubTableListItem) => {
<div className="mt-[10px] h-[20px] flex items-center font-normal">
<Tag
color="#7371fc1b"
className="text-theme font-normal border-0 mr-[12px] max-w-[150px] truncate"
className="text-theme font-normal border-0 mr-[12px] max-w-[100px] truncate"
key={service.id}
bordered={false}
title={service.catalogue?.name || '-'}
>
{service.catalogue?.name || '-'}
</Tag>
<Tooltip title={$t('API 数量')}>
<span className="mr-[12px] flex items-center">
<ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]" />
<span className="font-normal text-[14px]">{service.apiNum ?? '-'}</span>
</span>
</Tooltip>
<Tooltip title={$t('接入消费者数量')}>
<span className="mr-[12px] flex items-center">
<span className="h-[14px] mr-[4px] flex items-center ">
<iconpark-icon size="14px" name="auto-generate-api"></iconpark-icon>
</span>
<span className="font-normal text-[14px]">{service.subscriberNum ?? '-'}</span>
</span>
</Tooltip>
<Tag
color={`#${service.serviceKind === 'ai' ? 'EADEFF' : 'DEFFE7'}`}
className={`text-[#000] font-normal border-0 mr-[12px] max-w-[150px] truncate`}
bordered={false}
title={service.serviceKind || '-'}
>
{SERVICE_KIND_OPTIONS.find((x) => x.value === service.serviceKind)?.label || '-'}
</Tag>
{service?.enableMcp && (
<Tag
color="#FFF0C1"
className="text-[#000] font-normal border-0 mr-[12px] max-w-[150px] truncate"
bordered={false}
title={'MCP'}
>
MCP
</Tag>
)}
</div>
</div>
</div>
)
}
// 格式化调用次数,添加K和M单位
const formatInvokeCount = (count: number | null | undefined): string => {
if (count === null || count === undefined) return '-'
if (count >= 1000000) {
const value = Math.floor(count / 100000) / 10
return `${value}M`
}
if (count >= 1000) {
const value = Math.floor(count / 100) / 10
return `${value}K`
}
return count.toString()
}
const CardAction = (props: { service: ServiceHubTableListItem }) => {
const { service } = props
return (
<div className="absolute bottom-[20px] h-[20px] flex items-center font-normal">
<Tooltip title={$t('API 数量')}>
<span className="mr-[12px] flex items-center">
<ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]" />
<span className="font-normal text-[14px]">{service.apiNum ?? '-'}</span>
</span>
</Tooltip>
<Tooltip title={$t('接入消费者数量')}>
<span className="mr-[12px] flex items-center">
<span className="h-[14px] mr-[4px] flex items-center ">
<Icon icon="tabler:api-app" width="14" height="14" />
</span>
<span className="font-normal text-[14px]">{service.subscriberNum ?? '-'}</span>
</span>
</Tooltip>
<Tooltip title={$t('30天内调用次数')}>
<span className="mr-[12px] flex items-center">
<span className="h-[14px] mr-[4px] flex items-center ">
<Icon icon="iconoir:graph-up" width="14" height="14" />
</span>
<span className="font-normal text-[14px]">{formatInvokeCount(service.invokeCount ?? 0)}</span>
</span>
</Tooltip>
</div>
)
}
@@ -65,6 +65,8 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
const prefixSelector = (
<Form.Item name="position" noStyle>
<Select
showSearch
optionFilterProp="label"
style={{ width: 90 }}
options={[
{ label: 'Header', value: 'Header' },
@@ -127,6 +129,8 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
<Form.Item<EditAuthFieldType> label={$t('鉴权类型')} name="driver" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
disabled={type === 'edit'}
className="w-INPUT_NORMAL"
options={[
@@ -179,6 +183,8 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
options={ALGORITHM_ITEM}
onChange={(value) => {
@@ -205,6 +211,8 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
<Form.Item<EditAuthFieldType> label={$t('校验字段')} name={['config', 'claimsToVerify']}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
mode="multiple"
options={[
@@ -204,6 +204,8 @@ const ManagementConfig = forwardRef<ManagementConfigHandle, ManagementConfigProp
{dataShowType === 'list' && (
<Form.Item<ManagementConfigFieldType> label={$t('所属团队')} name="team" rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
disabled={type === 'edit'}
placeholder={$t(PLACEHOLDER.input)}
+4 -1
View File
@@ -7,7 +7,7 @@ toolchain go1.23.6
require (
github.com/eolinker/ap-account v1.0.15
github.com/eolinker/eosc v0.18.3
github.com/eolinker/go-common v1.1.5
github.com/eolinker/go-common v1.1.6
github.com/gabriel-vasile/mimetype v1.4.4
github.com/getkin/kin-openapi v0.127.0
github.com/gin-contrib/gzip v1.0.1
@@ -15,6 +15,8 @@ require (
github.com/go-sql-driver/mysql v1.7.0
github.com/google/uuid v1.6.0
github.com/influxdata/influxdb-client-go/v2 v2.14.0
github.com/mark3labs/mcp-go v0.17.0
github.com/mitchellh/mapstructure v1.5.0
github.com/nsqio/go-nsq v1.1.0
github.com/ollama/ollama v0.5.8
github.com/urfave/cli v1.22.16
@@ -63,6 +65,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
+8 -2
View File
@@ -32,8 +32,8 @@ github.com/eolinker/ap-account v1.0.15 h1:n6DJeL6RHZ8eLlZUcY2U3H4d/GPaA5oelAx3R0
github.com/eolinker/ap-account v1.0.15/go.mod h1:zm/Ivs6waJ/M/nEszhpPmM6g50y/MKO+5eABFAdeD0g=
github.com/eolinker/eosc v0.18.3 h1:3IK5HkAPnJRfLbQ0FR7kWsZr6Y/OiqqGazvN1q2BL5A=
github.com/eolinker/eosc v0.18.3/go.mod h1:O9PQQXFCpB6fjHf+oFt/LN6EOAv779ItbMixMKCfTfk=
github.com/eolinker/go-common v1.1.5 h1:unYPcpptqL2zk+BNuzc4cJVJBDEpjs918nTkGUw+q7U=
github.com/eolinker/go-common v1.1.5/go.mod h1:Kb/jENMN1mApnodvRgV4YwO9FJby1Jkt2EUjrBjvSX4=
github.com/eolinker/go-common v1.1.6 h1:s+NaQL0InjX/MwWY53+8y8qzAgsULIUc4U6nWXWQ2Nw=
github.com/eolinker/go-common v1.1.6/go.mod h1:Kb/jENMN1mApnodvRgV4YwO9FJby1Jkt2EUjrBjvSX4=
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY=
@@ -101,8 +101,12 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mark3labs/mcp-go v0.17.0 h1:5Ps6T7qXr7De/2QTqs9h6BKeZ/qdeUeGrgM5lPzi930=
github.com/mark3labs/mcp-go v0.17.0/go.mod h1:KmJndYv7GIgcPVwEKJjNcbhVQ+hJGJhrCCB/9xITzpE=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -149,6 +153,8 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg=
go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+152
View File
@@ -0,0 +1,152 @@
package mcp_server
import (
"encoding/json"
"net/http"
"github.com/getkin/kin-openapi/openapi3"
)
var (
openapi3Loader = openapi3.NewLoader()
)
type MCPInfo struct {
Name string
Description string
Apis []*API
}
type API struct {
Path string `json:"path"`
Method string `json:"method"`
ContentType string `json:"content_type"`
Summary string `json:"summary"`
Description string `json:"description"`
Params []*openapi3.Parameter `json:"params"`
Body map[string]interface{} `json:"body"`
}
func ConvertMCPFromOpenAPI3Data(data []byte) (*MCPInfo, error) {
spec, err := openapi3Loader.LoadFromData(data)
if err != nil {
return nil, err
}
return parseOpenAPI3(spec)
}
func parseOpenAPI3(spec *openapi3.T) (*MCPInfo, error) {
items := spec.Paths.Map()
apis := make([]*API, 0, len(items)*4)
for path, item := range items {
pathApis, err := genAPIs(path, item)
if err != nil {
return nil, err
}
apis = append(apis, pathApis...)
}
return &MCPInfo{
Name: spec.Info.Title,
Description: spec.Info.Description,
Apis: apis,
}, nil
}
var (
validMethods = []string{
http.MethodGet,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodHead,
http.MethodOptions,
}
)
func genAPIs(path string, item *openapi3.PathItem) ([]*API, error) {
apis := make([]*API, 0, 8)
for _, method := range validMethods {
opt := item.GetOperation(method)
if opt == nil {
continue
}
api, err := genAPI(method, path, opt, item.Parameters)
if err != nil {
return nil, err
}
apis = append(apis, api)
}
return apis, nil
}
func genAPI(method string, path string, opt *openapi3.Operation, params openapi3.Parameters) (*API, error) {
api := &API{
Method: method,
Path: path,
Summary: opt.Summary,
Description: opt.Description,
Params: make([]*openapi3.Parameter, 0, len(params)+len(opt.Parameters)),
}
if api.Summary == "" {
api.Summary = opt.Description
}
parameters := make([]*openapi3.ParameterRef, 0, len(params)+len(opt.Parameters))
parameters = append(parameters, opt.Parameters...)
parameters = append(parameters, params...)
for _, param := range parameters {
if param.Value != nil {
api.Params = append(api.Params, param.Value)
}
}
if opt.RequestBody != nil && opt.RequestBody.Value != nil && opt.RequestBody.Value.Content != nil {
for mediaType, media := range opt.RequestBody.Value.Content {
if media != nil && media.Schema != nil {
api.ContentType = mediaType
body, err := recurseSchemaRef(media.Schema)
if err != nil {
return nil, err
}
api.Body = body
}
}
}
return api, nil
}
func recurseSchemaRef(ref *openapi3.SchemaRef) (map[string]interface{}, error) {
if ref == nil || ref.Value == nil {
return nil, nil
}
data, err := json.Marshal(ref.Value)
if err != nil {
return nil, err
}
m := make(map[string]interface{})
err = json.Unmarshal(data, &m)
if err != nil {
return nil, err
}
if ref.Value.Properties != nil {
m["properties"] = make(map[string]interface{})
for k, v := range ref.Value.Properties {
v, err := recurseSchemaRef(v)
if err != nil {
return nil, err
}
m["properties"].(map[string]interface{})[k] = v
}
}
if ref.Value.Items != nil {
v, err := recurseSchemaRef(ref.Value.Items)
if err != nil {
return nil, err
}
m["items"] = v
}
return m, nil
}
+78
View File
@@ -0,0 +1,78 @@
package mcp_server
import (
"fmt"
"net/http"
"strings"
"github.com/mark3labs/mcp-go/server"
"github.com/eolinker/eosc"
)
var (
mcpServer = NewServer()
ServiceBasePath = "mcp/service"
GlobalBasePath = "mcp/global"
)
func NewServer() *Server {
return &Server{
sseServers: eosc.BuildUntyped[string, *server.SSEServer](),
}
}
type Server struct {
sseServers eosc.Untyped[string, *server.SSEServer]
}
func (s *Server) Set(path string, sseServer *server.SSEServer) {
s.sseServers.Set(path, sseServer)
}
func (s *Server) Del(path string) {
s.sseServers.Del(path)
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sseServer, has := s.sseServers.Get(trimPath(r.URL.Path))
if has {
sseServer.ServeHTTP(w, r)
return
}
http.NotFound(w, r)
return
}
func trimPath(path string) string {
path = strings.TrimSuffix(path, "/")
path = strings.TrimSuffix(path, "/message")
path = strings.TrimSuffix(path, "/sse")
return path
}
func SetSSEServer(sid string, name string, version string, tools ...ITool) {
s := server.NewMCPServer(name, version)
for _, tool := range tools {
tool.RegisterMCP(s)
}
apiPath := fmt.Sprintf("/api/v1/%s/%s", ServiceBasePath, sid)
openAPIPath := fmt.Sprintf("/openapi/v1/%s/%s", ServiceBasePath, sid)
mcpServer.Set(apiPath, server.NewSSEServer(s, server.WithBasePath(apiPath)))
mcpServer.Set(openAPIPath, server.NewSSEServer(s, server.WithBasePath(openAPIPath)))
}
func DelSSEServer(sid string) {
apiPath := fmt.Sprintf("/api/v1/%s/%s", ServiceBasePath, sid)
openAPIPath := fmt.Sprintf("/openapi/v1/%s/%s", ServiceBasePath, sid)
mcpServer.Del(apiPath)
mcpServer.Del(openAPIPath)
}
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
mcpServer.ServeHTTP(w, r)
}
func DefaultMCPServer() *Server {
return mcpServer
}
+147
View File
@@ -0,0 +1,147 @@
package mcp_server
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/eolinker/go-common/utils"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
type ITool interface {
RegisterMCP(s *server.MCPServer)
}
const (
MCPBody = "Body"
MCPHeader = "Header"
MCPQuery = "Query"
MCPPath = "Path"
)
type Tool struct {
name string
url string
method string
contentType string
opts []mcp.ToolOption
}
func NewTool(name string, uri string, method string, contentType string, opts ...mcp.ToolOption) ITool {
return &Tool{
name: name,
url: uri,
method: method,
contentType: contentType,
opts: opts,
}
}
func (t *Tool) RegisterMCP(s *server.MCPServer) {
s.AddTool(mcp.NewTool(t.name, t.opts...), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
invokeAddress := utils.GatewayInvoke(ctx)
if invokeAddress == "" {
return nil, fmt.Errorf("invoke address is empty")
}
u, err := url.Parse(invokeAddress)
if err != nil {
return nil, fmt.Errorf("invalid invoke address %s", invokeAddress)
}
if u.Scheme == "" {
u.Scheme = "http"
}
path := t.url
queries := url.Values{}
headers := make(map[string]string)
body := ""
for k, v := range request.Params.Arguments {
if k == "Body" {
switch a := v.(type) {
case string:
body = a
case map[string]interface{}:
switch t.contentType {
case "application/json":
tmp, _ := json.Marshal(a)
body = string(tmp)
case "application/x-www-form-urlencoded":
bodyValue := url.Values{}
for kk, vv := range a {
bodyValue.Set(kk, fmt.Sprintf("%v", vv))
}
body = bodyValue.Encode()
}
default:
tmp, _ := json.Marshal(a)
body = string(tmp)
}
continue
}
tmp, ok := v.(map[string]interface{})
if !ok {
continue
}
switch k {
case MCPHeader:
for kk, vv := range tmp {
headers[kk] = fmt.Sprintf("%v", vv)
}
case MCPQuery:
for kk, vv := range tmp {
queries.Set(kk, fmt.Sprintf("%v", vv))
}
case MCPPath:
for kk, vv := range tmp {
p, ok := vv.(string)
if !ok {
return nil, fmt.Errorf("invalid path %s", v)
}
path = strings.Replace(path, fmt.Sprintf("{%s}", kk), p, -1)
}
}
}
u.Path = path
u.RawQuery = queries.Encode()
req, err := http.NewRequest(t.method, u.String(), strings.NewReader(body))
if err != nil {
return nil, err
}
for k, v := range headers {
req.Header.Set(k, v)
}
if t.contentType != "" {
req.Header.Set("Content-Type", t.contentType)
}
apikey := utils.Label(ctx, "apikey")
if apikey != "" {
req.Header.Set("Authorization", apikey)
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
d, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status code %d, %s", resp.StatusCode, string(d))
}
return mcp.NewToolResultText(string(d)), nil
})
}
var client = http.Client{}
+52 -44
View File
@@ -35,43 +35,6 @@ func genOperation(summary string, description string, variables []*ai_api_dto.Ai
return operation
}
func genRequestHeaders() openapi3.Parameters {
return openapi3.Parameters{
{
Value: &openapi3.Parameter{
Name: "Authorization",
In: "header",
Description: "your_apipark_apikey", // 替换Prompt的变量列表
Required: true,
Example: "your_apipark_apikey",
},
},
}
}
func genRequestParameters(variables []*ai_api_dto.AiPromptVariable) openapi3.Parameters {
return openapi3.Parameters{
{
Value: &openapi3.Parameter{
Name: "variables",
In: "body",
Description: "Replace the variable list of Prompt", // 替换Prompt的变量列表
Schema: genVariableSchema(variables).NewRef(),
Required: true,
},
},
{
Value: &openapi3.Parameter{
Name: "messages",
In: "body",
Description: "Chat Message",
Schema: messagesSchemaRef,
Required: true,
},
},
}
}
func genRequestBody(variables []*ai_api_dto.AiPromptVariable) *openapi3.RequestBodyRef {
requestBody := openapi3.NewRequestBody()
requestBody.Content = openapi3.NewContentWithSchema(genRequestBodySchema(variables), []string{"application/json"})
@@ -96,6 +59,10 @@ func genRequestBodySchema(variables []*ai_api_dto.AiPromptVariable) *openapi3.Sc
result.WithProperty("variables", genVariableSchema(variables))
result.WithRequired([]string{"variables", "messages"})
}
streamSchema := openapi3.NewBoolSchema()
streamSchema.Title = "stream"
streamSchema.Description = "Whether to stream the response"
result.WithProperty("stream", streamSchema)
result.WithPropertyRef("messages", messagesSchemaRef)
@@ -176,17 +143,58 @@ func genMessagesSchema() *openapi3.Schema {
func genResponseSchema() *openapi3.Schema {
result := openapi3.NewObjectSchema()
result.Description = "Response from the server"
result.WithPropertyRef("message", messageSchemaRef)
openapi3.NewIntegerSchema()
result.WithProperty("code", openapi3.NewIntegerSchema())
result.WithProperty("error", openapi3.NewStringSchema())
result.WithProperty("finish_reason", openapi3.NewStringSchema().WithEnum(
// 创建 choices 数组
choicesSchema := openapi3.NewArraySchema()
choiceItemSchema := openapi3.NewObjectSchema()
// choice 中的 message 字段
choiceItemSchema.WithPropertyRef("message", messageSchemaRef)
// finish_reason 字段
finishReasonSchema := openapi3.NewStringSchema().WithEnum(
"stop",
"length",
"function_call",
"content_filter",
"null",
))
)
choiceItemSchema.WithProperty("finish_reason", finishReasonSchema)
// index 字段
choiceItemSchema.WithProperty("index", openapi3.NewIntegerSchema())
// logprobs 字段,可以为 null
choiceItemSchema.WithProperty("logprobs", openapi3.NewSchema().WithNullable())
choicesSchema.Items = &openapi3.SchemaRef{Value: choiceItemSchema}
result.WithProperty("choices", choicesSchema)
// object 字段
result.WithProperty("object", openapi3.NewStringSchema().WithEnum("chat.completion"))
// usage 字段
usageSchema := openapi3.NewObjectSchema()
usageSchema.WithProperty("prompt_tokens", openapi3.NewIntegerSchema())
usageSchema.WithProperty("completion_tokens", openapi3.NewIntegerSchema())
usageSchema.WithProperty("total_tokens", openapi3.NewIntegerSchema())
// prompt_tokens_details 字段
promptTokensDetailsSchema := openapi3.NewObjectSchema()
promptTokensDetailsSchema.WithProperty("cached_tokens", openapi3.NewIntegerSchema())
usageSchema.WithProperty("prompt_tokens_details", promptTokensDetailsSchema)
result.WithProperty("usage", usageSchema)
// 其他字段
result.WithProperty("created", openapi3.NewIntegerSchema())
result.WithProperty("system_fingerprint", openapi3.NewStringSchema().WithNullable())
result.WithProperty("model", openapi3.NewStringSchema())
result.WithProperty("id", openapi3.NewStringSchema())
// 保留原有的错误字段
result.WithProperty("code", openapi3.NewIntegerSchema())
result.WithProperty("error", openapi3.NewStringSchema())
return result
}
+2 -1
View File
@@ -718,7 +718,8 @@ func (i *imlProviderModule) getAiProviders(ctx context.Context) ([]*gateway.Dyna
}
model, has := driver.GetModel(l.DefaultLLM)
if !has {
return nil, fmt.Errorf("model not found: %s", l.DefaultLLM)
continue
//return nil, fmt.Errorf("model not found: %s", l.DefaultLLM)
}
cfg := make(map[string]interface{})
cfg["provider"] = l.Id
@@ -3,7 +3,7 @@ package auth_driver
import (
"encoding/json"
"fmt"
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
)
@@ -83,6 +83,6 @@ func generateStruct[T any](cfg interface{}) (*T, error) {
return nil, err
}
}
return result, nil
}
@@ -3,9 +3,9 @@ package oauth2
import (
"encoding/json"
"strconv"
auth_driver "github.com/APIParkLab/APIPark/module/application-authorization/auth-driver"
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
)
@@ -33,7 +33,7 @@ func (cfg *Config) ID() string {
}
func (cfg *Config) Valid() ([]byte, error) {
if cfg.HashSecret && !cfg.Hashed {
// 未加密
secret, err := hashSecret([]byte(cfg.ClientSecret), 0, 0, 0)
@@ -48,9 +48,9 @@ func (cfg *Config) Valid() ([]byte, error) {
}
func (cfg *Config) Detail() []application_authorization_dto.DetailItem {
redirectURLs, _ := json.Marshal(cfg.RedirectUrls)
return []application_authorization_dto.DetailItem{
{Key: "客户端ID", Value: cfg.ClientId},
{Key: "客户端密钥", Value: cfg.ClientSecret},
@@ -2,9 +2,10 @@ package application_authorization
import (
"context"
"github.com/APIParkLab/APIPark/module/system"
"reflect"
"github.com/APIParkLab/APIPark/module/system"
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
"github.com/APIParkLab/APIPark/gateway"
@@ -31,6 +32,9 @@ type IAuthorizationModule interface {
Detail(ctx context.Context, appId string, aid string) ([]application_authorization_dto.DetailItem, error)
// Info 获取项目鉴权详情
Info(ctx context.Context, appId string, aid string) (*application_authorization_dto.Authorization, error)
CheckAPIKeyAuthorization(ctx context.Context, serviceId string, apikey string) (bool, error)
//ExportAll(ctx context.Context) ([]*application_authorization_dto.ExportAuthorization, error)
}
+75 -2
View File
@@ -7,6 +7,8 @@ import (
"fmt"
"time"
"github.com/APIParkLab/APIPark/service/subscribe"
application_authorization "github.com/APIParkLab/APIPark/service/application-authorization"
"github.com/eolinker/eosc/log"
@@ -36,11 +38,80 @@ var (
type imlAuthorizationModule struct {
serviceService service.IServiceService `autowired:""`
subscribeService subscribe.ISubscribeService `autowired:""`
authorizationService application_authorization.IAuthorizationService `autowired:""`
clusterService cluster.IClusterService `autowired:""`
transaction store.ITransaction `autowired:""`
}
func (i *imlAuthorizationModule) CheckAPIKeyAuthorization(ctx context.Context, serviceId string, apikey string) (bool, error) {
list, err := i.subscribeService.ListBySubscribeStatus(ctx, serviceId, subscribe.ApplyStatusSubscribe)
if err != nil {
return false, err
}
if len(list) < 1 {
return false, fmt.Errorf("no application found")
}
appIds := utils.SliceToSlice(list, func(s *subscribe.Subscribe) string {
return s.Application
})
authorizations, err := i.authorizationService.ListByApp(ctx, appIds...)
if err != nil {
return false, err
}
for _, a := range authorizations {
if a.Type != "apikey" {
continue
}
cfg := make(map[string]interface{})
if a.Config != "" {
json.Unmarshal([]byte(a.Config), &cfg)
}
if cfg["apikey"] == apikey {
return true, nil
}
}
return false, nil
}
func (i *imlAuthorizationModule) AuthorizationsByService(ctx context.Context, serviceId string, authorizationType string) ([]*application_authorization_dto.Authorization, error) {
list, err := i.subscribeService.ListBySubscribeStatus(ctx, serviceId, subscribe.ApplyStatusSubscribe)
if err != nil {
return nil, err
}
if len(list) < 1 {
return nil, fmt.Errorf("no application found")
}
appIds := utils.SliceToSlice(list, func(s *subscribe.Subscribe) string {
return s.Application
})
authorizations, err := i.authorizationService.ListByApp(ctx, appIds...)
if err != nil {
return nil, err
}
result := make([]*application_authorization_dto.Authorization, 0, len(authorizations))
for _, a := range authorizations {
if authorizationType != "" && a.Type != authorizationType {
continue
}
cfg := make(map[string]interface{})
if a.Config != "" {
json.Unmarshal([]byte(a.Config), &cfg)
}
result = append(result, &application_authorization_dto.Authorization{
UUID: a.UUID,
Name: a.Name,
Driver: a.Type,
Position: a.Position,
TokenName: a.TokenName,
Config: cfg,
ExpireTime: a.ExpireTime,
HideCredential: a.HideCredential,
})
}
return result, nil
}
func (i *imlAuthorizationModule) ExportAll(ctx context.Context) ([]*application_authorization_dto.ExportAuthorization, error) {
list, err := i.authorizationService.List(ctx)
if err != nil {
@@ -110,7 +181,7 @@ func (i *imlAuthorizationModule) getApplications(ctx context.Context, appIds []s
}
func (i *imlAuthorizationModule) initGateway(ctx context.Context, partitionId string, clientDriver gateway.IClientDriver) error {
services, err := i.serviceService.List(ctx)
services, err := i.serviceService.AppList(ctx)
if err != nil {
return err
}
@@ -129,11 +200,13 @@ func (i *imlAuthorizationModule) initGateway(ctx context.Context, partitionId st
}
func (i *imlAuthorizationModule) online(ctx context.Context, s *service.Service) error {
clusters, err := i.clusterService.List(ctx)
if err != nil {
return err
}
if len(clusters) < 1 {
return nil
}
authorizations, err := i.authorizationService.ListByApp(ctx, s.Id)
if err != nil {
return err
+7
View File
@@ -3,6 +3,7 @@ package catalogue
import (
"context"
"reflect"
"time"
"github.com/APIParkLab/APIPark/module/system"
@@ -47,3 +48,9 @@ func init() {
return reflect.ValueOf(catalogueModule)
})
}
func formatTimeByMinute(org int64) time.Time {
t := time.Unix(org, 0)
location, _ := time.LoadLocation("Asia/Shanghai")
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), 0, 0, location)
}

Some files were not shown because too many files have changed in this diff Show More