Compare commits

..

1190 Commits

Author SHA1 Message Date
Dot.L 9617ddc02c Merge pull request #271 from APIParkLab/feature/1.6-liujian
update tongyi,bedrock define
2025-03-27 17:26:35 +08:00
Liujian 8083090414 update tongyi,bedrock define 2025-03-27 17:15:03 +08:00
Dot.L 60296bf3c9 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 77d0d9bfb8 update issue template: APINTO Dashboard -> ApiPark 2025-03-19 16:23:23 +08:00
ningyv 6e0c66d982 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 07b49030a2 fix: Display only file logs on the log page. 2025-03-19 16:13:03 +08:00
Dot.L 203c3e4c4b Merge pull request #266 from APIParkLab/feature/1.6-liujian
update tongyi define
2025-03-19 15:36:50 +08:00
Liujian e434c7867f update tongyi define 2025-03-19 15:32:36 +08:00
ningyv f3059f8df8 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 0b0cd25d2c fix: Header navigation click range issue 2025-03-19 14:17:13 +08:00
Dot.L 4e0239d282 Merge pull request #259 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-14 19:17:25 +08:00
Liujian 2574b2814b update ai api schema 2025-03-14 19:16:31 +08:00
Liujian 1564bd977e Fix the issue of duplicate custom suppliers and built-in suppliers 2025-03-14 19:13:58 +08:00
ningyv 92e47812bd 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 2e867da093 feat: feature/1.6-Integrate custom model 2025-03-14 18:47:04 +08:00
Liujian da85269c9f Add supplier differentiation, custom or built-in 2025-03-14 18:02:28 +08:00
Liujian 15f803a511 fix bug 2025-03-14 15:51:33 +08:00
Dot.L 7eca309eac Merge pull request #257 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-13 22:17:32 +08:00
Liujian 414308802c Fix the issue of local model data synchronization errors 2025-03-13 22:14:58 +08:00
Liujian 7333e4fda3 fix bug 2025-03-13 17:51:27 +08:00
Liujian 1cdaa29764 fix bug 2025-03-13 14:47:36 +08:00
Liujian 9d270b7b0e 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 31abd609e6 Merge pull request #256 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-13 14:17:39 +08:00
Liujian fdd1cd32a8 Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-13 14:16:37 +08:00
Liujian 6210a06d43 fix local model bug 2025-03-13 14:16:03 +08:00
ningyv 807132014a 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 041817cc3c 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 acb0ceb9a9 feat: feature/1.6-Integrate custom model 2025-03-13 13:46:32 +08:00
ningyv 417dab7ddc Merge pull request #254 from APIParkLab/feature/1.6-cx
Feature/1.6 cx
2025-03-13 12:01:10 +08:00
lichunxian 3a9a07c109 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 a02d505e2e feat: feature/1.6-Integrate custom model 2025-03-13 11:58:28 +08:00
Dot.L bcee9315d5 Delete .gitlab-ci.yml 2025-03-13 09:18:50 +08:00
孙安智 a0266b061f 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 0e19f37a68 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 c70aeaa3cd refactor: adjust field requirements in Vertex AI config file 2025-03-12 20:23:41 +08:00
刘健 f22738ec2b 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 f69f304ebf Merge pull request #251 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-12 18:34:04 +08:00
Liujian 111877a1e4 Synchronize to gateway when custom model updates 2025-03-12 18:33:10 +08:00
Liujian c924b0ce1d Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-12 17:32:31 +08:00
孙安智 fed8e62965 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 987488c928 Merge pull request #250 from APIParkLab/feature/sunanzhi/1.6
refactor: adjust vertex model ID
2025-03-12 17:28:35 +08:00
sunanzhi 8efa20e03a refactor: adjust vertex model ID 2025-03-12 17:28:01 +08:00
lichunxian ced2143a6e 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 a58e2c4e67 feat: feature/1.6-Integrate custom model 2025-03-12 15:42:07 +08:00
Liujian d26f3a8082 Merge remote-tracking branch 'github-pro/main' into feature/1.6-liujian 2025-03-12 15:08:23 +08:00
Liujian 0337c3a2a2 Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-12 15:08:15 +08:00
sunanzhi 67c4eea64f Merge pull request #249 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-12 14:55:04 +08:00
孙安智 64c59e4886 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 3392abaf4b fix: prevent duplicate model names 2025-03-12 14:53:06 +08:00
sunanzhi 29da1c441a fix: resolve missing access config in model 2025-03-12 14:39:37 +08:00
sunanzhi 53735cff61 Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-12 14:20:29 +08:00
sunanzhi 80d59f5856 fix: resolve bug preventing re-adding vendor after deletion 2025-03-12 14:20:04 +08:00
ningyv fb5203c356 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 49f353033c 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 1fd3e5689d feat: feature/1.6-Integrate custom model 2025-03-12 14:08:55 +08:00
sunanzhi 021ec6fbee 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
孙安智 eb7b9acb26 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 1042f8808c fix: resolve inaccurate display of model content 2025-03-12 14:03:30 +08:00
刘健 093c698cf0 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 9ebf8e217b Merge pull request #246 from APIParkLab/feature/1.6-liujian
update spark define
2025-03-12 10:09:20 +08:00
Liujian 3f4b6865fe update spark define 2025-03-12 10:03:00 +08:00
孙安智 977665fac7 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 e16a7f6705 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 ab642000d4 refactor: adjust regex validation rules for model name 2025-03-11 20:35:16 +08:00
Dot.L efdb5eebbe Merge pull request #244 from APIParkLab/feature/1.6-liujian
Local model compatibility testing completed
2025-03-11 19:45:33 +08:00
Liujian 6872ef74ca Local model compatibility testing completed 2025-03-11 19:44:55 +08:00
Dot.L 55d649e56e 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 43c3e7a818 fix: fail to get ai api model name 2025-03-11 17:16:42 +08:00
Dot.L 158008d836 Merge pull request #242 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 16:50:30 +08:00
Liujian 7d7e9581d4 update provider define 2025-03-11 16:49:17 +08:00
ningyv b25b4075cd 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 1f0c467e8e Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-11 16:03:43 +08:00
lichunxian a153bfef02 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 941690038b feat: feature/1.6-Integrate custom model 2025-03-11 16:02:02 +08:00
Liujian a8a6b8278a Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-11 16:01:58 +08:00
Dot.L b13eb59396 Merge pull request #240 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 15:27:47 +08:00
Liujian fde94b2851 update config of publishing provider 2025-03-11 15:27:01 +08:00
孙安智 ccca43f3dc 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 60e33a0305 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 933cf44839 refactor: remove validation for checking provider existence in model addition 2025-03-11 15:22:06 +08:00
Liujian dda842d468 Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-11 15:16:59 +08:00
Liujian 98b65ed437 Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-11 14:28:09 +08:00
孙安智 bde2cca414 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 20657f22d6 refactor: adjust character limit for custom provider/model name 2025-03-11 12:01:20 +08:00
Dot.L 762b604e60 Merge pull request #238 from APIParkLab/feature/1.6-liujian
Feature/1.6 liujian
2025-03-11 11:51:35 +08:00
lichunxian d29d198c88 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 a9168c7b91 feat: feature/1.6-Integrate custom model 2025-03-11 10:23:26 +08:00
刘健 cfafd043e9 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 bf6c62a57f update ai provider define file 2025-03-11 10:04:14 +08:00
Liujian 9831730b28 Merge remote-tracking branch 'origin/feature/sunanzhi/1.6' into feature/1.6-liujian 2025-03-10 19:48:02 +08:00
Liujian 02fa2dc086 Merge remote-tracking branch 'origin/feature/1.6-cx' into feature/1.6-liujian 2025-03-10 19:47:56 +08:00
Liujian 3cd3794cf1 support service mapping 2025-03-10 19:47:45 +08:00
lichunxian 4723114bf5 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 7aa2512ad9 feat: feature/1.6-Integrate custom model 2025-03-10 18:03:09 +08:00
孙安智 11e74fd08e 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 ba115f7a3c fix: resolve null pointer caused by URI error 2025-03-10 17:41:04 +08:00
Dot.L f03f5f81d1 Merge pull request #235 from APIParkLab/feature/1.6-liujian
Cancel publishing related comments
2025-03-10 14:54:54 +08:00
刘健 afc8fe4167 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 0ed51b28ab Cancel publishing related comments 2025-03-10 14:53:17 +08:00
lichunxian f1333b68b6 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 c8bd6f63a3 feat: feature/1.6-Integrate custom model 2025-03-10 11:40:18 +08:00
sunanzhi 61598b49ef Merge pull request #234 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-10 10:45:04 +08:00
孙安智 69bbdb3d02 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 6598b6fc9e Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-10 10:43:45 +08:00
sunanzhi bd7008d8c3 feat: add provider type field 2025-03-10 10:42:33 +08:00
lichunxian 7645134b35 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 3e9e83cd03 feat: feature/1.6-Integrate custom model 2025-03-10 10:34:35 +08:00
lichunxian 0250e65959 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 2c4a22e921 feat: feature/1.6-Integrate custom model 2025-03-10 10:09:42 +08:00
lichunxian fecfea5dad 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 ff157fbdd3 feat: feature/1.6-Integrate custom model 2025-03-10 09:45:15 +08:00
sunanzhi 402a3c2d15 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
孙安智 cac95019b6 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 e247972624 fix: resolve duplicate linked list data in model caused by updating vendor 2025-03-07 20:08:56 +08:00
孙安智 88022a8edd 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 e5bdadc016 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 68bf7081e6 fix: resolve issue with adding vendor not loading 2025-03-07 19:52:47 +08:00
sunanzhi 85e530a122 Merge pull request #231 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 18:54:06 +08:00
sunanzhi 7a7569a63f Merge branch 'main' of https://github.com/APIParkLab/APIPark into feature/sunanzhi/1.6 2025-03-07 18:50:34 +08:00
孙安智 b6ededa2c4 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 22b1b50429 refactor: adjust model_runtime structure of provider model 2025-03-07 18:32:20 +08:00
孙安智 b098a09425 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 35f018544d fix: resolve build failure due to unused model variable 2025-03-07 15:08:50 +08:00
孙安智 a1dcbd23b7 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 3a6ad62cad fix: resolve null pointer due to empty validator and comment out release model code 2025-03-07 14:56:54 +08:00
sunanzhi 80adb6b62f Merge pull request #229 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 14:34:19 +08:00
孙安智 b71615597b 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 80b388bfc6 fix: resolve error caused by fetching empty vendor config model 2025-03-07 14:33:23 +08:00
lichunxian 32b5f90e86 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 79b40ced37 feat: feature/1.6-Integrate custom model 2025-03-07 14:24:14 +08:00
孙安智 7ff4b77505 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 d979eb7c2a fix: resolve package error when LLMs list is empty 2025-03-07 14:07:53 +08:00
孙安智 75a5416fad 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 7d3d9605cb fix: fix null pointer in unconfigured provider fetch, add model name to list 2025-03-07 11:38:14 +08:00
sunanzhi 77b4a8e9d4 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
孙安智 4c415a47f8 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 56289058fc 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 954c7f2192 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 2065126bcb feat: feature/1.6-Integrate custom model 2025-03-07 11:05:53 +08:00
sunanzhi b8e9b87c88 Merge pull request #226 from APIParkLab/feature/sunanzhi/1.6
Feature/sunanzhi/1.6
2025-03-07 09:27:39 +08:00
孙安智 1aa95fb972 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 00061bbf19 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 f95f28cd67 Merge pull request #225 from APIParkLab/feature/dashen/model_mapping
Feature/dashen/model mapping
2025-03-06 18:27:32 +08:00
sunanzhi eca864a80b Add support for creating online models and integrating custom model providers 2025-03-06 17:42:17 +08:00
lichunxian 5d71a8d7c5 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 78a892dcda feat: feature/1.6-Integrate custom model 2025-03-06 16:16:20 +08:00
lichunxian 4f7ca8018c 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 4fe55593b7 Merge remote-tracking branch 'origin/main' into feature/1.6-cx 2025-03-06 11:31:29 +08:00
ningyv 9b8a3256bd feat: feature/1.6-Integrate custom model 2025-03-06 11:07:58 +08:00
李业昌 c167712b0e 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 c7f561a55d .gitignore 2025-03-05 10:49:22 +08:00
2944321442@qq.com 30bead497e feat:update .gitignore 2025-03-05 10:44:19 +08:00
2944321442@qq.com 34ecd56cc4 feat:update .gitignore 2025-03-05 10:43:20 +08:00
2944321442@qq.com e4b46ea2e2 feat:添加服务模型映射功能 2025-03-05 10:15:05 +08:00
2944321442@qq.com 9e520be8b5 Merge branch 'main' into feature/dashen/model_mapping 2025-03-05 10:15:00 +08:00
2944321442@qq.com 2f7db1c871 feat: add service model mapping configuration 2025-03-04 15:19:27 +08:00
ningyv 0aa526b6d4 Merge pull request #222 from APIParkLab/feature/1.5-cx
fix: homepage Permission Configuration
2025-03-03 14:21:16 +08:00
lichunxian a8b4599c4f 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 9c54fec65e fix: homepage Permission Configuration 2025-03-03 14:20:20 +08:00
ningyv 9315a5de4c Merge pull request #221 from APIParkLab/feature/1.5-cx
fix: homepage Permission Configuration
2025-03-03 14:15:27 +08:00
ningyv e09d35ec53 fix: homepage Permission Configuration 2025-03-03 14:14:20 +08:00
ningyv 07c904be75 Merge pull request #220 from APIParkLab/feature/1.6
fix: service configuration LLM API error
2025-03-03 09:51:49 +08:00
ningyv c2c6f2b3f6 fix: service configuration LLM API error 2025-03-03 09:51:14 +08:00
ningyv 0a3fdd61c8 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 25ad26ad55 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 d424b68b2b feat: feature/1.5-Data Integration 2025-02-20 18:35:26 +08:00
Dot.L 3c29a0a5c6 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
刘健 cf27da94a7 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 6eaa946be6 Fix: Failure to update local model configuration to gateway 2025-02-20 14:24:39 +08:00
ningyv 06aa17d0c3 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 a43880fbcc 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 94503a4ab6 feat: feature/1.5-Data Integration 2025-02-20 14:19:34 +08:00
ningyv 718f37e0da 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 e04282e3a4 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 587eec4f15 feat: feature/1.5-Data Integration 2025-02-20 13:51:53 +08:00
ningyv e760ce953b 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 98bde0a1c0 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 5759195b23 feat: feature/1.5-Data Integration 2025-02-20 11:36:34 +08:00
Liujian dcf18705da Merge remote-tracking branch 'github-pro/main' into feature/1.5-local-model 2025-02-19 19:51:32 +08:00
Liujian 61ae37d3d9 fix: ai balance bug 2025-02-19 19:18:17 +08:00
ningyv 10488a6308 Merge pull request #207 from APIParkLab/feature/1.5-cx
Feature/1.5 cx
2025-02-19 18:41:45 +08:00
lichunxian 3e3227755b 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 bd4ad2bac8 feat: feature/1.5-Data Integration 2025-02-19 18:19:17 +08:00
刘健 5c58283264 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 b55d68ed39 Fix: Issue of failed update service 2025-02-19 17:58:20 +08:00
lichunxian 2c7680bedc 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 6b9df8c5e9 feat: feature/1.5-Data Integration 2025-02-19 17:56:46 +08:00
刘健 db2e05889d 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 273f9ace58 Add model information field to service information 2025-02-19 17:24:12 +08:00
lichunxian 517ac1eeac 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 bb1371090c feat: feature/1.5-Data Integration 2025-02-19 16:05:19 +08:00
刘健 63fbd35c63 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 e8887c1454 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 7cc4a92015 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-19 10:27:11 +08:00
lichunxian 6d55676aa9 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 4c35a51f64 feat: feature/1.5-Data Integration 2025-02-19 10:23:16 +08:00
Liujian 2a977b37d4 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-19 10:13:55 +08:00
lichunxian 48f8bc0c8e 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 0b6aa6b343 feat: feature/1.5-Data Integration 2025-02-19 09:34:09 +08:00
lichunxian 463f063932 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 1218ac43f8 feat: feature/1.5-Data Integration 2025-02-19 09:27:10 +08:00
lichunxian 11bc0331cf 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 04a5da862f feat: feature/1.5-Data Integration 2025-02-18 21:55:58 +08:00
lichunxian 6af33ee5b7 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 66d0653dc6 feat: feature/1.5-Data Integration 2025-02-18 19:51:28 +08:00
Liujian f356df7f74 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-18 18:06:32 +08:00
lichunxian e289537fd9 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 4390e9767c fix: route handling does not work on page reload 2025-02-18 16:00:12 +08:00
刘健 7adbbc31c2 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 e9b40d8b27 add api: get/set ollama api address 2025-02-18 15:42:57 +08:00
Dot.L 3b1c9d9f67 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 1011302721 fix: cancel deploy error 2025-02-18 10:20:33 +08:00
ningyv 55e9744321 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 0481d42929 feat: feature/1.5-Data Integration 2025-02-18 10:08:20 +08:00
Liujian c10fa95cb3 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-17 21:24:33 +08:00
lichunxian 2e383282c8 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
刘健 7c913a4cb6 Update .gitlab-ci.yml file 2025-02-17 20:14:06 +08:00
ningyv 3140589299 feat: feature/1.5-Data Integration 2025-02-17 20:13:20 +08:00
刘健 42e3384ebb Update .gitlab-ci.yml file 2025-02-17 19:37:30 +08:00
刘健 8610cd5770 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 3132d48813 update service list sort 2025-02-17 18:31:05 +08:00
刘健 1f240581d2 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 ecf259a9e7 init service consumer 2025-02-17 18:12:47 +08:00
刘健 a0b2148b65 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 4371715b32 init service consumer 2025-02-17 18:08:29 +08:00
刘健 2619493362 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 50faa4af80 fix: bug 2025-02-17 17:21:48 +08:00
Liujian 267e019864 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-17 16:38:07 +08:00
ningyv 9b35281d04 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 da37970a43 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 27ba933099 feat: feature/1.5-Data Integration 2025-02-17 16:33:49 +08:00
刘健 6879a97e36 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 0fa8f6e6e4 Fix: Service List AI Entry Error 2025-02-17 16:12:21 +08:00
刘健 dd7f9c9f5f 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 5ee4f34624 fix: ai deploy bug 2025-02-17 15:23:57 +08:00
ningyv 04fd862b11 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 31a1703ba8 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 e74b022986 feat: feature/1.5-Data Integration 2025-02-17 15:16:45 +08:00
ningyv 6419cdaf13 Merge pull request #201 from APIParkLab/feature/1.5
Feature/1.5
2025-02-17 13:42:36 +08:00
ningyv 4b03c56315 Merge pull request #190 from APIParkLab/feature/1.5-cx
feat:Feature/1.5
2025-02-17 13:38:22 +08:00
Dot.L 3e50895af2 Merge pull request #200 from APIParkLab/feature/1.5-local-model
Feature/1.5 local model
2025-02-17 13:36:28 +08:00
刘健 81a9c35cda 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 620bd4cd49 add:init ai balance 2025-02-17 11:41:07 +08:00
lichunxian bd9e99890d 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 eaecc5c80a feat: feature/1.5-Data Integration 2025-02-17 11:30:52 +08:00
lichunxian fe30521c24 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 ed8c2f286c feat: feature/1.5-Data Integration 2025-02-17 11:06:23 +08:00
刘健 06e7d96f67 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 3c807cfdcf update api: simple local models 2025-02-17 10:45:34 +08:00
Liujian 1d3d4e2075 update provider model define 2025-02-17 10:25:12 +08:00
刘健 666acb6241 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 7243684977 fix: ai deploy bug 2025-02-17 00:37:25 +08:00
刘健 1c499ae805 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 0dabe4d0e5 fix: ai balance bug 2025-02-16 21:50:56 +08:00
Liujian f7f802639e Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-16 21:38:41 +08:00
刘健 0153612020 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 6d03f67ffd fix:bug 2025-02-16 00:57:18 +08:00
lichunxian d27f7eba4d 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 7b2356f8f3 feat: feature/1.5-Data Integration 2025-02-15 18:50:38 +08:00
lichunxian 4c60acb5bb 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 6ddd2f2389 feat: feature/1.5-Data Integration 2025-02-15 18:30:21 +08:00
lichunxian 3de5221b4a 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 4e98b09fa4 feat: feature/1.5-Data Integration 2025-02-15 18:11:36 +08:00
刘健 3e0070db80 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 10f852803a 本地模型列表新增provider 2025-02-15 17:59:03 +08:00
lichunxian b347d8f08c 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 e786393523 feat: feature/1.5-Data Integration 2025-02-15 17:44:23 +08:00
lichunxian 11ae2969b4 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 4a2995b533 feat: feature/1.5-Data Integration 2025-02-15 17:26:58 +08:00
lichunxian b6d2abaa64 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 1495451901 feat: feature/1.5-Data Integration 2025-02-15 17:15:36 +08:00
刘健 3e79f117a3 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 7489a8f601 update api doc 2025-02-15 10:58:13 +08:00
刘健 13517c835c 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 70cab89511 fix:bug 2025-02-15 10:56:38 +08:00
lichunxian 8ec82bc9ba 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 d4ef5a7516 feat: feature/1.5-Data Integration 2025-02-15 10:13:10 +08:00
刘健 5205764fae 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 23c36cc68b Fix: AI model list keyword query failure issue 2025-02-14 23:46:29 +08:00
刘健 16d1e8f3d7 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 ee0f45a6e1 finish:quick create service 2025-02-14 23:27:24 +08:00
Liujian f402bcaae9 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 23:08:26 +08:00
lichunxian e6684244d1 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 044e31dd8a feat: feature/1.5-Data Integration 2025-02-14 22:23:21 +08:00
lichunxian 976f3505bf 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 bd33dff2f3 feat: feature/1.5-Data Integration 2025-02-14 21:51:46 +08:00
刘健 f91b83385f 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 80bcc6a058 update model colomn length 2025-02-14 21:19:55 +08:00
刘健 6797ff023d 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 24a26f3394 add ollama logo 2025-02-14 21:10:04 +08:00
lichunxian 528bb727ad 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 edf30ac61f feat: feature/1.5-Data Integration 2025-02-14 20:56:35 +08:00
lichunxian e0c482efbc 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 c67964045d feat: feature/1.5-Data Integration 2025-02-14 20:44:40 +08:00
刘健 cf285f0637 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 28cc30b8a7 Improve deployment logic 2025-02-14 20:22:49 +08:00
Liujian 286387440c Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 19:15:31 +08:00
lichunxian d4c697d680 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 92a6f777ed feat: feature/1.5-Data Integration 2025-02-14 18:50:30 +08:00
刘健 d90dc847ef 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 a6d3fd807a update role permission 2025-02-14 18:41:09 +08:00
刘健 8707a01fd3 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 815cc61607 Gin responds to cancel gzip compression 2025-02-14 18:36:25 +08:00
lichunxian 2c95e440d1 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 12ed7aafee feat: feature/1.5-Data Integration 2025-02-14 18:04:38 +08:00
lichunxian b06c880a9c 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 3becd8a0a7 feat: feature/1.5-Data Integration 2025-02-14 17:43:41 +08:00
Liujian b7efd2e5c5 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5-local-model 2025-02-14 17:37:28 +08:00
刘健 b5d70ca524 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 3b5195a6ba Fix: Local model deployment status error 2025-02-14 17:24:41 +08:00
刘健 d41afdd2da 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 d94fc09d07 update deploy status 2025-02-14 17:06:34 +08:00
lichunxian 5253a62f9a 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 818436c946 feat: Local deployment popup optimization 2025-02-14 16:45:39 +08:00
刘健 125f59b1e1 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 50d0923bce finish ai balance 2025-02-14 16:29:56 +08:00
Liujian b41152f4d9 Merge remote-tracking branch 'origin/feature/1.5-cx' into feature/1.5/local-model 2025-02-14 15:43:38 +08:00
lichunxian e18a6ef1c6 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 d0813e8595 feat: Local deployment popup optimization 2025-02-14 15:39:01 +08:00
Liujian eef14f36a1 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 47cdc6bf18 local model first commit 2025-02-14 15:34:41 +08:00
lichunxian f65a908661 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 3c0140f3b8 feat: feature/1.5-Model Deployment Process Popup Optimization 2025-02-13 18:22:58 +08:00
lichunxian 93f1a76efb 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 8d415fa273 feat: Style and Prompt Optimization 2025-02-13 17:02:40 +08:00
Liujian 244a3c784f async excutor first commit 2025-02-13 11:53:52 +08:00
lichunxian c36ff21b91 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 f8fad4caf4 feat: Multilingual Translation 2025-02-13 09:51:43 +08:00
ningyv 3b54c03027 feat: progress log 2025-02-12 18:20:35 +08:00
ningyv a5f46a930f feat: local model list page 2025-02-12 16:45:57 +08:00
ningyv 6157a9d1fa feat: local model list page 2025-02-12 15:28:17 +08:00
ningyv f910fc84e5 feat: merge api model page 2025-02-12 11:27:47 +08:00
scarqin 9cb09905f9 feat: delete model 2025-02-12 00:33:16 +08:00
scarqin eeb2fbcad6 feat: api list 2025-02-11 19:15:11 +08:00
scarqin 400faf92c0 feat: online model settings 2025-02-11 19:01:15 +08:00
ningyv fb023a039b feat: load banancing list 2025-02-11 18:27:14 +08:00
ningyv 95b5d848f7 feat: feature/1.5 Extract home page navigation component 2025-02-11 10:36:47 +08:00
ningyv ded5e064e6 feat: Deployment Progress Popup Development 2025-02-10 17:03:28 +08:00
ningyv 7ea50ec380 feat: Home Page AI Service Deployment 2025-02-08 18:47:08 +08:00
Dot.L 901bef1463 Merge pull request #189 from APIParkLab/feature/openapi
update workflows actions/download-artifact to v4
2025-02-08 16:15:32 +08:00
Liujian 8d44d796b4 update workflows actions/download-artifact to v4 2025-02-08 16:14:01 +08:00
Dot.L 5a10ad478e Merge pull request #188 from APIParkLab/feature/openapi
update workflows actions/upload-artifact to v4
2025-02-08 15:59:53 +08:00
Liujian fd6680d615 update workflows actions/upload-artifact to v4 2025-02-08 15:57:36 +08:00
Dot.L e03cdfc42b Merge pull request #187 from APIParkLab/feature/openapi
Feature/openapi
2025-02-08 15:02:06 +08:00
Liujian 945d53fcfd Merge remote-tracking branch 'github-pro/main' into feature/openapi 2025-02-08 15:01:27 +08:00
Liujian ac7045b724 Fix: AI provider's default key synchronization to Apinto failed issue 2025-02-08 14:58:36 +08:00
Liujian c907bdc4a5 Merge remote-tracking branch 'origin/main' into feature/openapi 2025-01-23 16:54:58 +08:00
ningyv 733ed9ac2f Merge pull request #183 from APIParkLab/feature/1.4
chroe: optimize AI model node graphics
2025-01-23 14:01:10 +08:00
ningyv 1d8e579a10 Merge remote-tracking branch 'origin/main' into feature/1.4 2025-01-23 13:57:01 +08:00
lichunxian 567cac9c95 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 095c09c8c0 chroe: optimize AI model node graphics 2025-01-21 11:50:58 +08:00
刘健 e9c949822d Merge branch 'feature/openapi' into 'main'
Feature/openapi

See merge request apipark/APIPark!160
2025-01-20 17:36:53 +08:00
Dot.L 3482d5416c Merge pull request #181 from APIParkLab/feature/openapi
fix:ai init bug
2025-01-20 14:08:37 +08:00
Liujian d8cb4a0c94 fix:ai init bug 2025-01-20 14:03:03 +08:00
Dot.L 59acfa7a47 Merge pull request #180 from APIParkLab/feature/openapi
Feature/openapi
2025-01-20 13:55:59 +08:00
Liujian 2eb2e690d1 update ai bug 2025-01-20 13:54:58 +08:00
刘健 f7801261c3 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 7e7be7f040 add openapi 2025-01-17 16:03:09 +08:00
Dot.L 0187fd16b2 Merge pull request #174 from jeak01/patch-2
Update readme-zh-cn.md
2025-01-17 15:55:09 +08:00
Dot.L ba0bdb5e99 Merge pull request #175 from jeak01/patch-3
Update readme-zh-tw.md
2025-01-17 15:54:50 +08:00
Dot.L 9d3e4f07bf Merge pull request #176 from jeak01/patch-4
Update readme-jp.md
2025-01-17 15:54:37 +08:00
Dot.L bd81d7584d Merge pull request #177 from jeak01/patch-1
Update README.md
2025-01-17 15:54:20 +08:00
jeak 9577339e14 Update readme-jp.md 2025-01-17 14:59:10 +08:00
jeak 5c292ef1cb Update readme-zh-tw.md 2025-01-17 14:58:46 +08:00
jeak 4f3de85068 Update readme-zh-cn.md 2025-01-17 14:58:19 +08:00
jeak 07a25c9643 Update README.md 2025-01-17 14:57:31 +08:00
Dot.L 8f60426b4c 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 37f87615bd 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 3f96de660b 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 e86999770f fix: ai event handler read event error 2025-01-17 10:38:35 +08:00
Dot.L a8bb0c24ec Merge pull request #170 from APIParkLab/feature/ai-balance
update init plugin config
2025-01-16 18:58:36 +08:00
Liujian 6ba2a08b62 update init plugin config 2025-01-16 18:53:58 +08:00
Dot.L d232269416 Merge pull request #167 from APIParkLab/feature/ai-balance
Feature/ai balance
2025-01-16 16:37:41 +08:00
Liujian 9d2208e14d update provider status default value 2025-01-16 16:36:25 +08:00
Liujian 8d69d45d1d update build script 2025-01-16 16:36:06 +08:00
刘健 b0c37918b5 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
刘健 d5af1c8da3 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 a6105cfc3c fix: 1.3-beta版本,超级管理员(admin)账户无法修改分类和添加子分类,页面显示无权限操作 (#164) 2025-01-14 17:52:07 +08:00
ScarChin 0aa5ffd2c2 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 968f5b986f Merge pull request #165 from APIParkLab/feature/ai-balance
update docker run script
2025-01-13 11:25:50 +08:00
Liujian 014a7e0362 update docker run script 2025-01-13 11:24:29 +08:00
Dot.L a92baf09d9 Merge pull request #162 from APIParkLab/feature/ai-balance
Feature/ai balance
2025-01-08 11:26:18 +08:00
Liujian 46e2edbe13 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 5aba86965e 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 5924208aaa ignore config.yaml 2025-01-08 11:14:47 +08:00
Liujian 526390816b update package script 2025-01-08 11:11:41 +08:00
ScarChin d7e28c9704 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
秦圆圆 7c827804f4 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 b0dacbda0d 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 d5abde2593 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 bc3290de3b fix: jump link error 2025-01-07 17:56:16 +08:00
scarqin 7f438bf776 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 13cfe24b2f fix: error line 2025-01-07 17:21:21 +08:00
Liujian 9cf1cd99c2 Merge remote-tracking branch 'github-pro/feature/1.4' into feature/ai-balance 2025-01-07 16:53:41 +08:00
刘健 f5cfd77550 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 f27abbd454 fix: ai provider status error 2025-01-07 16:49:47 +08:00
scarqin 6a7a11a811 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
刘健 4a8f5152b3 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 599ee6b9b8 AI API token quantity docking completed 2025-01-07 12:49:23 +08:00
秦圆圆 83ac747cb1 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 09b98c6c0d fix: Details has two slashes 2025-01-07 11:32:29 +08:00
scarqin 13eac21609 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 d0d9e2a9a8 fix: system logs lack of edit permission 2025-01-07 10:32:03 +08:00
scarqin b047c93965 fix: i18n error 2025-01-07 10:04:18 +08:00
刘健 d5eedd1dd2 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 9cc6696340 fix: ai key config error 2025-01-07 01:42:36 +08:00
秦圆圆 86758383c4 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 150a0264c5 fix: AI API should remove prefix matching drop-down selection 2025-01-06 19:29:15 +08:00
scarqin 558a2d8aad fix: There is no slide rail, so the bottom part cannot be displayed. 2025-01-06 19:14:09 +08:00
scarqin fa327114f7 fix: No refetching of lists after deleting keyword search 2025-01-06 17:53:30 +08:00
刘健 6ce3e0bfac 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 4f7dee570a update ai key status to gateway 2025-01-06 10:57:23 +08:00
刘健 e4eadf863e 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 7a70a6ce01 fix: ai key sort 2025-01-06 10:22:01 +08:00
刘健 ca328e784c 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 9871e252bc ai balance finish 2025-01-06 09:47:23 +08:00
Liujian d40eb6c4e1 Merge remote-tracking branch 'origin/main' into feature/ai-balance 2025-01-05 23:25:08 +08:00
Liujian a7b0e6d0bf update ai key iml 2025-01-05 23:25:00 +08:00
lichunxian f4f546e654 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 1fcbb3ecbc feat: aiApi detail page 2025-01-03 17:46:23 +08:00
ningyv 98e3cc973b 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 220ab53ef2 feat: aiApi detail page 2025-01-03 17:33:06 +08:00
秦圆圆 9ba70063d2 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 076277d0a9 fix: KEY pool adjustment order will fail 2025-01-03 17:13:40 +08:00
scarqin bcd2ba1ec9 fix: The bottom margin of the banner should be sufficient 2025-01-03 16:37:36 +08:00
scarqin 5827afd09c 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
秦圆圆 4a3e49f4e3 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 95d24aca41 Merge remote-tracking branch 'origin/feature/1.4' into feature/ai-balance 2025-01-03 11:25:59 +08:00
刘健 345e37bd81 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 91b2fabf10 update ai api list 2025-01-03 10:46:25 +08:00
scarqin bae1803157 i18n 2025-01-03 09:42:17 +08:00
刘健 911d16de31 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 1efe924221 update ai api list 2025-01-03 09:33:12 +08:00
scarqin 0230235427 feat: navigate 2025-01-03 09:24:32 +08:00
scarqin 58e737ee28 chore: apis 2025-01-03 09:09:40 +08:00
scarqin 78c98f121d fix: api key timestamp error 2025-01-03 09:06:36 +08:00
秦圆圆 2e3b86741b 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 fcd9869caa feat: api url 2025-01-02 10:07:54 +08:00
scarqin f60579b735 fix: padding error 2025-01-02 09:45:32 +08:00
scarqin 6574f36c73 fix: provider tips 2025-01-02 09:32:19 +08:00
scarqin 246ce245b9 fix: alert api list tips 2025-01-02 09:29:03 +08:00
scarqin fa0a211db9 feat: add banner 2025-01-02 08:21:33 +08:00
scarqin 1c536df3c8 feat: apilist 2024-12-31 17:21:56 +08:00
scarqin 82fa1b5b1c chore: change disable to disabled 2024-12-31 16:17:53 +08:00
刘健 dacce748a1 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 b59088c598 update api disable to disabled 2024-12-31 15:24:36 +08:00
scarqin 26dbce9dbf feat: ai column add disable 2024-12-31 15:17:36 +08:00
scarqin 9b6d07dc4c feat: apikey 2024-12-31 15:07:43 +08:00
刘健 00e21c8000 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 8c5f5326d5 fix: provider status incorrect 2024-12-31 14:48:19 +08:00
scarqin 3ebafcbc03 feat: stopaable tips 2024-12-31 14:24:15 +08:00
scarqin 9777859f42 feat: add llm status manage 2024-12-31 12:01:42 +08:00
scarqin 54f76d6576 feat: add priority 2024-12-31 10:27:50 +08:00
刘健 3bb8293478 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 16e899cab7 update go-common version 2024-12-31 10:16:44 +08:00
scarqin b4b9469284 refacor: delete useless code 2024-12-30 17:03:36 +08:00
scarqin e0896864c2 feat: update list after edit modal 2024-12-30 17:00:09 +08:00
scarqin c7b16e0ea9 feat: ai model 2024-12-30 15:59:43 +08:00
scarqin f6d6920cfb feat: ai model detail 2024-12-30 14:59:22 +08:00
刘健 8b4059a249 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 94b19e7589 update ai provider list key 2024-12-30 13:49:59 +08:00
scarqin a090bb7caa feat: ai apis 2024-12-27 21:28:35 +08:00
刘健 101e97dfec 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 31054a2df7 update simple/providers/configured api 2024-12-27 16:55:54 +08:00
scarqin 58231eb19c feat: api tab 2024-12-27 09:56:15 +08:00
Liujian 8f8b5d2684 Merge branch 'main-github-pro' into feature/ai-balance 2024-12-26 18:22:30 +08:00
Liujian ca5e497dbb Merge remote-tracking branch 'origin/main' into main-github-pro 2024-12-26 18:21:30 +08:00
刘健 13aabcacd2 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 3afd0bb609 Add filtering options to the list 2024-12-26 18:06:54 +08:00
刘健 e250a8b57f 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 051fa7647d ai api list add filter condition 2024-12-26 17:25:36 +08:00
Liujian 9c4c794d0f Merge branch 'main-github-pro' into feature/ai-balance 2024-12-26 16:48:03 +08:00
Liujian 9211a28675 update service list api 2024-12-26 16:46:11 +08:00
scarqin 8d660ec7c0 feat: ai model config 2024-12-26 16:05:56 +08:00
秦圆圆 ed8109fc30 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 37fc63def8 feat: apikey 2024-12-26 15:52:43 +08:00
刘健 8c1a8f67d8 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 94ed7581bb update simple configured providers 2024-12-26 15:41:07 +08:00
scarqin 4a84a69fe7 feat: add api key 2024-12-26 15:39:52 +08:00
刘健 1ebf6c9319 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 d0fc353d0b finish ai provider api 2024-12-26 15:09:44 +08:00
scarqin 977919fdb1 feat: add key 2024-12-26 14:36:24 +08:00
scarqin ae2e37cedb feat: add modal 2024-12-26 14:20:06 +08:00
scarqin 02e5394924 feat: add api keys 2024-12-25 20:23:47 +08:00
scarqin cdc9bb73bb feat: support sort table 2024-12-25 17:53:15 +08:00
scarqin 3a2c0c744c feat: delete apikey 2024-12-25 17:36:26 +08:00
scarqin ffeb76f608 fix: provider change 2024-12-25 17:15:42 +08:00
scarqin 3748cb39b2 feat: sort api 2024-12-25 17:08:26 +08:00
scarqin 543ea52bb3 feat: pagination and search api 2024-12-25 16:51:41 +08:00
scarqin 2ad508ec60 feat: ai provider component 2024-12-25 15:41:20 +08:00
scarqin f9501d6f60 style: apikey layout 2024-12-25 15:05:19 +08:00
scarqin 6bbdf9600d feat: encapsulation select options 2024-12-25 14:43:29 +08:00
scarqin c554c010c5 style: remove keys card border 2024-12-25 14:12:43 +08:00
scarqin 075c976d19 fix: some type error 2024-12-25 14:08:22 +08:00
scarqin 6da49e78ee feat: remove attribute 2024-12-25 13:52:00 +08:00
scarqin 59ce2e0623 feat: add token 2024-12-25 12:01:19 +08:00
Dot.L 09b2a7f1a4 Merge pull request #159 from APIParkLab/feature/ai-balance
add get simple ai provider api
2024-12-25 12:01:03 +08:00
Liujian bd466ac420 add get simple ai provider api 2024-12-25 11:59:34 +08:00
scarqin 96183eb5df feat: apikey get 2024-12-25 10:38:28 +08:00
scarqin 21164859cf feat: template modal 2024-12-25 10:14:07 +08:00
Dot.L 9b50fe68c9 Merge pull request #158 from APIParkLab/feature/ai-balance
Feature/ai balance
2024-12-24 18:23:14 +08:00
刘健 d8576e4dc6 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 9fc23ad4be update go.mod 2024-12-24 18:20:09 +08:00
scarqin 6c997c0b51 feat: apikeys 2024-12-24 18:14:50 +08:00
刘健 9b10421882 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 e5bc98cac0 finish ai apis 2024-12-24 18:00:46 +08:00
scarqin e98f320f41 feat: add route apikey and ai api 2024-12-24 17:29:31 +08:00
scarqin d0ef35fb92 feat: flow chart 2024-12-24 16:36:23 +08:00
scarqin 8c512f3163 feat: use translateExtent to limit scroll area 2024-12-24 15:41:14 +08:00
scarqin 8cc0fc9987 disable dragger 2024-12-24 15:36:55 +08:00
scarqin 604200e1db feat: flow chart 2024-12-24 15:31:02 +08:00
scarqin 2a1581acdb feat: remove fit view 2024-12-24 15:14:52 +08:00
scarqin 39e3198821 feat: custom edge 2024-12-24 15:06:48 +08:00
scarqin b4c2b3614b feat: keycard change place 2024-12-24 14:37:45 +08:00
scarqin 5ea0cc7838 fet 2024-12-24 14:34:16 +08:00
scarqin a9b7fc525a feat: model 2024-12-24 14:28:10 +08:00
scarqin b05874fb0a feat: fetch data from api 2024-12-24 13:51:08 +08:00
scarqin 5fdd142a17 feat: change component place 2024-12-24 11:58:51 +08:00
scarqin 243e1da716 feat: dmo 2024-12-24 11:35:31 +08:00
scarqin 772217258c refactor: encapsulation constant 2024-12-24 10:37:10 +08:00
scarqin 57cc9c9db7 feat: draggable button 2024-12-23 18:36:12 +08:00
scarqin e6f6560f3a feat: draggable 2024-12-23 18:17:51 +08:00
scarqin cbce30b4d7 feat: draggable 2024-12-23 18:16:17 +08:00
scarqin 23c8a84b4c feat: add multiple data 2024-12-23 17:56:22 +08:00
scarqin a521bff1f1 chore: 文件拆分 2024-12-23 17:45:50 +08:00
scarqin 986784b128 feat: change type status 2024-12-23 17:42:55 +08:00
scarqin 238c2b8cd3 feat: change group title 2024-12-23 17:31:58 +08:00
scarqin c6a418e00c chore: card status 2024-12-23 17:14:23 +08:00
scarqin e59ea1f84d feat: add handler 2024-12-23 16:11:12 +08:00
Dot.L a1acde5df0 Merge pull request #156 from APIParkLab/feature/ai-balance
update go-common dependence in go.mod
2024-12-23 16:05:41 +08:00
刘健 3ec61165ca 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 cc823a18d4 update go-common dependence in go.mod 2024-12-23 15:58:24 +08:00
刘健 b6aa865a67 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 86f83d995b Merge pull request #155 from APIParkLab/feature/ai-balance
finish ai key api
2024-12-23 15:49:27 +08:00
Liujian e314e09fdb finish ai key api 2024-12-23 15:48:19 +08:00
scarqin 4aa4238943 feat: block 2024-12-23 14:09:53 +08:00
scarqin 5d638b8bf4 feat: basic card component 2024-12-23 14:00:24 +08:00
scarqin 5027d817c5 chore: add global rule 2024-12-23 11:36:25 +08:00
scarqin 40b92330eb chore: add global_rules.md 2024-12-23 10:16:59 +08:00
scarqin b990447226 feat: chart 2024-12-20 20:26:18 +08:00
scarqin 482019f514 chore: refactor format eslint and prettier code 2024-12-19 16:17:50 +08:00
scarqin 2027af3a3f chore: add remove unused 2024-12-19 15:49:20 +08:00
scarqin c1a55385d3 change 2024-12-18 17:37:20 +08:00
scarqin 8be47c99dd test 2024-12-18 17:33:39 +08:00
scarqin 10d11f5b99 test 2024-12-18 17:33:08 +08:00
scarqin 3db2c66f12 test 2024-12-18 17:32:23 +08:00
scarqin e8614c0072 test 2024-12-18 17:31:03 +08:00
scarqin 11b4c43845 test 2024-12-18 17:30:16 +08:00
scarqin 36fec4ddbe test 2024-12-18 17:28:17 +08:00
scarqin bb64039a0d test 2024-12-18 17:27:49 +08:00
scarqin 7b43b0b300 test 2024-12-18 17:25:54 +08:00
scarqin fd270c80f5 test 2024-12-18 17:24:02 +08:00
scarqin 12b5801b1b test 2024-12-18 17:20:47 +08:00
scarqin 23a6b38a7d test 2024-12-18 17:19:10 +08:00
scarqin 296118470c test 2024-12-18 17:13:29 +08:00
scarqin 6d4dccc6b7 feat: push 2024-12-18 17:11:43 +08:00
scarqin e449f86c01 fix: login page refresh multiple times 2024-12-18 15:48:51 +08:00
Dot.L a1bdc048a7 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
刘健 b5be78416f Update .gitlab-ci.yml file 2024-12-16 14:34:33 +08:00
刘健 89d1fe2c49 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 0a1b08157d add default router when create new rest service 2024-12-16 14:31:52 +08:00
刘健 61503f4146 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 d36c66371f Merge pull request #147 from APIParkLab/fix/fixbug-cx
fix: consumer permission
2024-12-13 20:02:45 +08:00
lichunxian 34b259562d 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 b7bb409e96 fix: consumer permission 2024-12-13 20:00:38 +08:00
Dot.L 517007c941 Merge pull request #146 from APIParkLab/feature/aibug-fix
fix aksk bug
2024-12-13 19:41:10 +08:00
Liujian 4c685a9ec6 fix aksk bug 2024-12-13 18:52:21 +08:00
Dot.L 1aca2099de Merge pull request #145 from APIParkLab/feature/aibug-fix
fix ai provider upstream bug
2024-12-10 17:26:47 +08:00
Liujian a93e5b4ff8 fix ai provider upstream bug 2024-12-10 17:24:51 +08:00
ningyv 85d25bebe2 Merge branch 'main' of github.com:APIParkLab/APIPark 2024-12-10 15:34:44 +08:00
lichunxian 9fa43ccc00 Merge branch 'fix/certificatePermission' into 'main'
fix: table-permission

See merge request apipark/APIPark!124
2024-12-10 15:17:11 +08:00
ningyv c2a11050dd fix: table-permission 2024-12-10 15:16:19 +08:00
Dot.L 080bfc3a44 Merge pull request #143 from eltociear/patch-1
chore: update index.tsx
2024-12-09 21:48:14 +08:00
Liujian f6956ddeca Merge remote-tracking branch 'origin/main' into main-github-pro 2024-12-09 21:42:09 +08:00
Liujian 9f56fa5e14 update init log 2024-12-09 21:32:57 +08:00
lichunxian ccc39b95de 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 9a2782e54b fix: implement certificate popup permission handling 2024-12-09 15:18:59 +08:00
Liujian 22455e2301 Automatically publish policies and logs during cluster initialization 2024-12-09 00:43:05 +08:00
Liujian 8ed2c84b68 update loki publish 2024-12-09 00:17:50 +08:00
Liujian ccd2a209e2 update .gitignore 2024-12-06 18:48:00 +08:00
lichunxian baf8ed4830 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 dedb586daf fix: improve column width adjustment and optimize date picker performance 2024-12-06 18:02:44 +08:00
刘健 21cd823791 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 c8ab65ef1b update publish problem 2024-12-06 16:12:49 +08:00
lichunxian f1c16fd992 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 52035341f6 fix: refine time range calculation with second-level precision 2024-12-06 15:24:06 +08:00
ningyv aa62d44717 fix: resolve subscriber permissions 2024-12-06 14:22:59 +08:00
lichunxian a072d1fc8d 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 38a00570d0 feat: integrate global policy API and implement data log page 2024-12-06 11:50:32 +08:00
刘健 43283b9da3 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 ef82cdbed6 update service publishing difference comparison field 2024-12-06 11:31:58 +08:00
Liujian 2bafe6f31f update service publish 2024-12-06 11:02:40 +08:00
刘健 3eb4f98fd8 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 bb5acad033 add service strategy log 2024-12-06 10:47:47 +08:00
刘健 b8308a446b 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 c86f99ce45 update service publish 2024-12-06 10:39:59 +08:00
lichunxian 952c519e45 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 07d97fa0bf feat: integrate global policy API and implement data log page 2024-12-05 18:53:11 +08:00
刘健 b0defedf04 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 edc2fccdeb fix log bug:Keyword query failed 2024-12-05 18:17:29 +08:00
刘健 a75b8a3f13 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 5aab5f7913 fix logs bug 2024-12-05 17:20:11 +08:00
刘健 9ab7989c8b 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 e3e11d740a fix log bug 2024-12-05 17:14:26 +08:00
刘健 4bae2edc49 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 4eaa47ca25 update strategy publish bug 2024-12-05 15:43:42 +08:00
刘健 e01f596525 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 912e8d0d04 update log label 2024-12-05 15:04:43 +08:00
刘健 570c80af91 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 7aa0ec0d67 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 2fea6cb622 update eosc version 2024-12-05 14:43:24 +08:00
Liujian 2195ff900f data mask log commit 2024-12-05 14:39:57 +08:00
Ikko Eltociear Ashimine 836c7699b8 chore: update index.tsx
protocal -> protocol
2024-12-04 15:54:09 +09:00
Liujian 72ed6c814e Merge remote-tracking branch 'github-pro/feature/v1.3/mj' into feature/data-mask 2024-12-03 16:07:13 +08:00
ningyv c33b070509 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 de12d5686c feature: dataMask logs dialog 2024-11-29 18:39:13 +08:00
lichunxian c55a8ac805 Merge branch 'fix/copyIssue' into 'main'
Fix/copy issue

See merge request apipark/APIPark!107
2024-11-29 10:39:28 +08:00
杨梦洁 df3626f3f0 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
杨梦洁 28bef97faa fix: Dashboard Table Height 2024-11-29 10:35:32 +08:00
ningyv 9897b6e9dc fix: Fix the issue where copying the URL doesn't work 2024-11-29 10:22:40 +08:00
ningyv 9af6963901 fix: Fixed side navigation disappearing 2024-11-29 10:08:06 +08:00
lichunxian c2d3ebecda 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 ba543311fc Merge branch 'main' of http://gitlab.eolink.com/apipark/APIPark 2024-11-29 09:45:55 +08:00
ningyv 87b8dda97b Fix Set the header width 2024-11-29 09:41:50 +08:00
ningyv e7facf5686 Fix icon issues 2024-11-28 19:15:02 +08:00
刘健 4dd57837c5 Merge branch 'feature/data-mask' into 'main'
update transaction

See merge request apipark/APIPark!104
2024-11-28 18:41:56 +08:00
Liujian d4ebc68e30 update transaction 2024-11-28 18:40:00 +08:00
Maggie 1f8e089e51 Merge pull request #141 from APIParkLab/feature/v1.3/mj
fix: get service remote option
2024-11-28 18:39:17 +08:00
杨梦洁 ce6f463fe8 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
杨梦洁 a37fe1d794 fix: get service remote option 2024-11-28 18:38:12 +08:00
刘健 818d1ec6bf 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 fc4a5f7e28 fix strategy bug 2024-11-28 18:34:15 +08:00
Maggie 0e3568b584 Merge pull request #140 from APIParkLab/feature/v1.3/mj
fix: service data-masking layout
2024-11-28 18:24:44 +08:00
杨梦洁 3617e4fe29 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
刘健 f2fddc1727 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 3b7204f1a6 openapi取消登录校验 2024-11-28 18:19:08 +08:00
杨梦洁 6646bb1e56 fix: service data-masking layout 2024-11-28 18:14:02 +08:00
Liujian c27533f802 Merge remote-tracking branch 'github-pro/main' into feature/data-mask 2024-11-28 17:35:53 +08:00
Maggie 613a47c181 Merge pull request #139 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-28 17:01:32 +08:00
杨梦洁 90138a142b 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
杨梦洁 4bf8db4898 fix: Modify Context Arct 2024-11-28 16:59:51 +08:00
杨梦洁 4f887f7204 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
杨梦洁 14e17ccf2c fix: add translation 2024-11-28 13:47:31 +08:00
刘健 5975670b8c 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 dbc4bc3343 add publish tip 2024-11-28 11:17:02 +08:00
刘健 ada7635703 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 943a77f718 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
杨梦洁 ef02c11efa 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
杨梦洁 8c166dae9b fix: role list scroll bug and add translation 2024-11-28 10:40:43 +08:00
Liujian b23da78c26 fix rest service publish 2024-11-27 20:18:23 +08:00
刘健 93ac7310e8 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 9376acc456 finish service publish 2024-11-27 19:46:52 +08:00
Maggie b70a1f9a51 Merge pull request #136 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-27 19:22:06 +08:00
杨梦洁 ac90a134b4 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
杨梦洁 96bd1cf9f6 fix: data-masking and integration bugs 2024-11-27 19:20:47 +08:00
刘健 960e37a81a 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 044bd550c9 update service publish rule 2024-11-27 19:05:11 +08:00
Liujian 0a9a903d1b Merge remote-tracking branch 'origin/main' into feature/data-mask 2024-11-27 18:30:46 +08:00
杨梦洁 84d7606e12 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
杨梦洁 febb64b8bb fix: data-masking bugs 2024-11-27 18:21:43 +08:00
刘健 932e433c46 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 b7307cd36d add open api swagger 2024-11-27 13:51:55 +08:00
刘健 7a0f3efd83 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 28af1f691c add strategy permit 2024-11-27 11:46:56 +08:00
刘健 796bc7bc15 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 8f06073783 add api: /simple/service/apis 2024-11-27 00:34:24 +08:00
刘健 7d6251b191 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 e13fff633e system setting add site_prefix 2024-11-26 23:49:44 +08:00
Liujian d984be4b85 finish data mask strategy 2024-11-26 23:44:00 +08:00
Liujian 213bdbd9d5 Merge remote-tracking branch 'github-pro/main' into feature/data-mask 2024-11-25 10:35:21 +08:00
杨梦洁 6a59d27b84 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
杨梦洁 ad45ab2e82 fix: Change Dashboard Fields 2024-11-21 18:37:39 +08:00
Liujian 8982a63283 Merge remote-tracking branch 'origin/feature/v1.3/mj' into feature/data-mask 2024-11-21 17:36:57 +08:00
Liujian 1b1515a8bd Initial submission of data desensitization strategy backend 2024-11-21 17:36:13 +08:00
Maggie df50e13db0 Merge pull request #135 from APIParkLab/feature/v1.3/mj
Feature/v1.3/mj
2024-11-21 17:05:48 +08:00
杨梦洁 89d91c14c9 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
杨梦洁 3a57c609f7 fix: Change Vite Config 2024-11-21 16:42:32 +08:00
杨梦洁 2cd331ec50 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
杨梦洁 3fa02ec65c fix: Change File Name 2024-11-21 16:32:07 +08:00
杨梦洁 f33f1965b4 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
杨梦洁 a70ecea02b fix: Change File Name 2024-11-21 16:25:18 +08:00
杨梦洁 8e68eb35f3 fix: Change file name 2024-11-21 16:20:52 +08:00
杨梦洁 2893331ff5 Merge branch 'main' into feature/v1.3/mj 2024-11-21 16:12:16 +08:00
杨梦洁 1a3d14cdd6 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
杨梦洁 dce9a7addb feat: Complete static pages for Phase 1 of V1.3 2024-11-21 16:08:08 +08:00
Liujian f3e7487482 add gitlab-ci 2024-11-15 14:35:27 +08:00
Liujian 86c39237dc Merge remote-tracking branch 'github-pro/main' 2024-11-15 14:21:23 +08:00
Dot.L b5ad739b93 Merge pull request #134 from PeterDaveHelloKitchen/zh-TW
Improve zh-TW Traditional Chinese locale
2024-11-15 14:19:39 +08:00
杨梦洁 0b7f0405d5 feat: Merge MF with data-masking list 2024-11-15 13:42:30 +08:00
lcx 1ab56708a5 feat: Global/Service Policy Development, Add Service Details Integration Tab 2024-11-15 10:44:16 +08:00
杨梦洁 522489c9e9 feat: plugin system 2024-11-14 19:09:46 +08:00
Peter Dave Hello a9eb2a790f Improve zh-TW Traditional Chinese locale 2024-11-14 05:49:34 +08:00
maggieyyy a092ed1108 fix: Move plugin code to common 2024-11-06 14:26:38 +08:00
maggieyyy 503515281d Merge branch 'main' into feature/mf 2024-11-06 11:33:21 +08:00
maggieyyy 2326d4dfb5 feat: plugin system 2024-11-05 16:20:40 +08:00
Dot.L 42e8030cf7 Merge pull request #130 from APIParkLab/feature/permit
Feature/permit
2024-11-04 11:06:03 +08:00
Liujian 17b4ede566 Merge branch 'main-github' into feature/permit
# Conflicts:
#	go.mod
2024-11-04 11:05:30 +08:00
Liujian bbc3fea848 update go.mod 2024-11-04 11:03:40 +08:00
Liujian 82e46b872b Merge remote-tracking branch 'origin/main' into main-github 2024-11-04 11:00:05 +08:00
Liujian 0f6a091c73 fix service info no prefix 2024-11-04 10:59:13 +08:00
Liujian 4e87adb4b3 Merge remote-tracking branch 'origin/main' into main-github 2024-11-04 10:49:05 +08:00
杨梦洁 320a2b6cf8 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 b216556867 fix: Modify service inside access 2024-11-04 10:44:30 +08:00
Liujian 7fbb98a2a9 Merge remote-tracking branch 'github-pro/main' into main-github 2024-11-01 19:03:17 +08:00
Liujian 461a8edbea update .gitignore 2024-11-01 19:01:50 +08:00
刘健 cdef179bed Merge branch 'feature/permit' into 'main'
Feature/permit

See merge request apipark/APIPark!80
2024-11-01 18:53:22 +08:00
Liujian a067388d79 update ai permit 2024-11-01 18:52:50 +08:00
杨梦洁 2d5e541593 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 be40186ad3 Merge pull request #129 from APIParkLab/feature/v1.2
fix: Modify link access
2024-11-01 18:42:26 +08:00
maggieyyy c9ae05b22e fix: Modify link access 2024-11-01 18:41:16 +08:00
maggieyyy 2b874fe59f fix: Modify execute list 2024-11-01 18:17:16 +08:00
Liujian 9da5e5d6c0 Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 18:05:14 +08:00
Liujian a6bfce2a5f Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 17:59:30 +08:00
Maggie 8cbeabe917 Merge pull request #128 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 16:45:24 +08:00
杨梦洁 1db354077f 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 e31d41a276 fix: Modify consumer list reload and subscriber option 2024-11-01 16:42:34 +08:00
Liujian 21d2abf716 Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 16:19:35 +08:00
Liujian 3a86a88870 update subscribe permit 2024-11-01 16:19:25 +08:00
杨梦洁 6117a840e1 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 0e20987fb8 fix: Add team selector to consumer 2024-11-01 15:48:51 +08:00
Dot.L 65e7cab772 Update readme-zh-tw.md 2024-11-01 15:26:33 +08:00
Dot.L 935f2ac766 Update readme-zh-cn.md 2024-11-01 15:26:15 +08:00
Dot.L 3e12d7eb9c Update readme-jp.md 2024-11-01 15:25:55 +08:00
Dot.L d6095269b7 Update README.md 2024-11-01 15:25:15 +08:00
Liujian 0c415b4e32 Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 14:59:54 +08:00
杨梦洁 bc1819b368 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 a9be016c87 Merge pull request #127 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 14:49:21 +08:00
maggieyyy 11da5e9d26 fix: consumer menu access bug 2024-11-01 14:48:18 +08:00
maggieyyy 2c6c194821 fix: consumer menu access bug 2024-11-01 14:48:10 +08:00
杨梦洁 aedd8b4cc6 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 fa2607e9b8 fix: consumer menu access bug 2024-11-01 14:45:32 +08:00
Liujian 3783e5ee5d Merge remote-tracking branch 'github-pro/main' into feature/permit 2024-11-01 14:26:37 +08:00
Maggie fd56b8ffed Merge pull request #126 from APIParkLab/feature/v1.2
Feature/v1.2
2024-11-01 14:24:51 +08:00
杨梦洁 07e288be16 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 46143c3fe0 fix: Modify department children type 2024-11-01 14:23:05 +08:00
maggieyyy 83e3cc85f2 fix: Modify department children type 2024-11-01 14:21:04 +08:00
刘健 a4b50ae60a Merge branch 'feature/permit' into 'main'
Feature/permit

See merge request apipark/APIPark!73
2024-11-01 14:19:48 +08:00
Liujian a30d0c37eb update permit bug 2024-11-01 14:19:17 +08:00
maggieyyy 64fdf59905 fix: Add empty to member transfer 2024-11-01 13:54:33 +08:00
maggieyyy 1aa3f2fb05 fix: plugin config 2024-11-01 13:39:52 +08:00
Liujian 68e8cb72d3 Merge remote-tracking branch 'origin/main' into feature/permit 2024-11-01 11:03:21 +08:00
Liujian a86d3cd65a update permit 2024-11-01 11:01:45 +08:00
杨梦洁 a4b4cbf60f 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 2dcb7ebd74 fix: Modify subscribe options 2024-10-31 14:14:44 +08:00
maggieyyy ad6b64ca74 fix: Modify config 2024-10-31 13:59:06 +08:00
maggieyyy d27a2b8cf3 Merge branch 'main' into feature/mf 2024-10-31 09:27:08 +08:00
杨梦洁 8fa1985feb 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 451efb8d3e Merge pull request #124 from APIParkLab/feature/v1.2
fix: delete log
2024-10-31 09:25:15 +08:00
maggieyyy d6bf3139ff fix: delete log 2024-10-31 09:14:24 +08:00
Maggie 309b9ea937 Merge pull request #123 from APIParkLab/feature/v1.2
fix: Modify access
2024-10-30 18:40:10 +08:00
杨梦洁 554bff38c6 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 d5e6062ec9 fix: Modify access 2024-10-30 18:38:39 +08:00
maggieyyy bcb68d552f fix: Modify mock plugin config 2024-10-30 17:52:41 +08:00
maggieyyy 3de87723ae fix: Modify mock plugin config 2024-10-30 17:51:10 +08:00
maggieyyy 535d70ac5a merge 2024-10-30 14:24:16 +08:00
Maggie d588d43aa1 Merge pull request #122 from APIParkLab/feature/v1.2
fix: Modify local path
2024-10-30 10:59:54 +08:00
Liujian f455cecb54 update ap-account version 2024-10-30 10:45:58 +08:00
杨梦洁 b88c0a9305 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 9030cff8ba fix: Modify local path 2024-10-29 18:32:45 +08:00
杨梦洁 98f73f799a 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 d2e428ada8 Merge pull request #121 from rolealiu/main
Update v1.2 translation
2024-10-29 17:29:21 +08:00
JackLiu 74156ec84c Merge branch 'APIParkLab:main' into main 2024-10-29 17:28:51 +08:00
HaoZhen Liu f9e6bc92d7 update v1.2 translation 2024-10-29 17:28:41 +08:00
Maggie 9884586cc9 Merge pull request #120 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-29 17:05:29 +08:00
杨梦洁 ac717a6efb 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 2b7c1ded15 fix: Add psw to account 2024-10-29 16:44:31 +08:00
杨梦洁 daac27712d 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 1080f33282 fix: Modify member transfer icon and department 2024-10-29 15:12:43 +08:00
Dot.L cc5c0a0a89 Merge pull request #119 from APIParkLab/feature/permission
update i18n
2024-10-29 14:20:19 +08:00
Liujian 85971447e1 update i18n 2024-10-29 14:19:36 +08:00
杨梦洁 256e8ef275 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 c07e54ec03 Merge pull request #118 from APIParkLab/feature/v1.2
fix: update translation
2024-10-29 13:54:42 +08:00
maggieyyy 70f834e1cf fix: update translation 2024-10-29 13:52:48 +08:00
Maggie c320c6f2a2 Merge pull request #117 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-29 13:39:34 +08:00
杨梦洁 256eb60df8 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 5f03973bf2 fix: Modify guide link 2024-10-29 13:37:38 +08:00
maggieyyy ab2a0d8ae2 fix: Modify member transfer 2024-10-29 11:58:09 +08:00
Maggie 7e48402591 Merge pull request #116 from APIParkLab/feature/v1.2
fix: account translation
2024-10-29 09:21:36 +08:00
杨梦洁 aa85f6fcd1 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 cd441ccfe7 fix: account translation 2024-10-29 09:19:35 +08:00
Dot.L 47f6519006 Merge pull request #114 from APIParkLab/feature/permission
update remark
2024-10-28 18:41:17 +08:00
Maggie 9679376cb2 Merge pull request #113 from APIParkLab/feature/v1.2
fix: table fields
2024-10-28 18:40:48 +08:00
杨梦洁 efa97c3bbc 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 087e598be0 update remark 2024-10-28 18:39:55 +08:00
Dot.L 31aa8243ee Merge pull request #112 from APIParkLab/feature/permission
Feature/permission
2024-10-28 18:34:19 +08:00
Liujian d3d05ef539 Merge remote-tracking branch 'github-pro/main' into feature/permission
# Conflicts:
#	resources/access/access.yaml
2024-10-28 18:33:42 +08:00
maggieyyy d6062ea4e7 fix: table fields 2024-10-28 18:32:20 +08:00
Liujian 7949748951 update permission 2024-10-28 18:27:37 +08:00
Liujian 94f7392060 update access 2024-10-28 16:48:18 +08:00
Maggie 0d737bad57 Merge pull request #111 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-28 16:22:58 +08:00
杨梦洁 1225db50c9 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 e5d85bb3df fix: Modify access fields 2024-10-28 16:15:38 +08:00
杨梦洁 0f09e5c236 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 0f0204b647 fix: cosumer list bug 2024-10-28 16:00:15 +08:00
杨梦洁 94421d2622 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 44f0b70461 fix: Consumer list bugs 2024-10-28 15:44:10 +08:00
刘健 f58768237b Merge branch 'feature/translate' into 'main'
Feature/translate

See merge request apipark/APIPark!56
2024-10-28 15:15:00 +08:00
Dot.L 588cf839e3 Merge pull request #110 from APIParkLab/feature/translate
Feature/translate
2024-10-28 15:07:35 +08:00
Liujian 76872b3a97 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 d253d68a12 Merge pull request #96 from sunanzhi/main
fix:issue template content
2024-10-28 15:03:56 +08:00
Liujian 4de0d29f30 update access 2024-10-28 15:03:04 +08:00
Maggie 0f0480db63 Merge pull request #108 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-28 15:02:37 +08:00
杨梦洁 aa40b62e0a 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 68309ac582 fix: Modify access 2024-10-28 15:00:59 +08:00
maggieyyy 522183eb4d fix: update message 2024-10-28 13:39:47 +08:00
maggieyyy 4f6fee4d73 fix: Delete operation from team & Delete comments from publish 2024-10-28 11:52:51 +08:00
Liujian c5fecf73c8 update action 2024-10-28 10:53:28 +08:00
Liujian ee8e93d1e8 update action 2024-10-28 10:46:17 +08:00
Liujian 9d0fa5ea4a Merge remote-tracking branch 'origin/main' into feature/translate 2024-10-28 10:43:23 +08:00
Dot.L b0b9affbe7 Merge pull request #1 from Dot-Liu/feature/translate
Feature/translate
2024-10-28 10:01:46 +08:00
Liujian 1d1c7c78e8 update go.mod 2024-10-28 10:00:34 +08:00
杨梦洁 d7f5b87e70 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 1048666972 fix: Modify publish and title & add debug 2024-10-28 09:58:04 +08:00
Liujian 217f5d61c7 Merge remote-tracking branch 'origin/main' into feature/translate 2024-10-27 00:48:03 +08:00
Liujian 2f1677f581 role update 2024-10-27 00:47:48 +08:00
刘健 afd7ea6a1c 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 7155e14e64 create ai service add provider 2024-10-26 21:25:13 +08:00
刘健 68e5b49f46 Merge branch 'feature/translate' into 'main'
update translate

See merge request apipark/APIPark!52
2024-10-25 18:47:48 +08:00
Liujian c01e95c716 update translate 2024-10-25 18:45:38 +08:00
杨梦洁 ffa7e5130e 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 7ce33bfd4c Merge pull request #101 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 16:35:27 +08:00
maggieyyy 0c64fa9986 fix: update translation 2024-10-25 16:34:06 +08:00
Maggie 07e8b347e1 Merge pull request #100 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 16:20:02 +08:00
杨梦洁 38a402adef 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 7ab2e29101 fix: update translation 2024-10-25 16:16:15 +08:00
Maggie b96796793b Merge pull request #99 from APIParkLab/docs-update-frontend-README
docs: Update README.md
2024-10-25 15:48:21 +08:00
Scarqin baa073b05d Update README.md 2024-10-25 15:44:42 +08:00
Maggie c944f9de52 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
杨梦洁 5567a65e4b 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 c6c775f436 fix: Remove guest's account setting & update translation 2024-10-25 15:22:06 +08:00
sunanzhi c0c43be6b9 fix:issue template content 2024-10-25 15:16:47 +08:00
刘健 9b6074318a 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 ada121015d update ao-account dependent version 2024-10-25 14:32:11 +08:00
JackLiu 9d7b6c4bc6 Merge pull request #86 from rolealiu/main
update translation
2024-10-25 14:31:56 +08:00
JackLiu c262fc4f4d Merge branch 'APIParkLab:main' into main 2024-10-25 14:31:26 +08:00
刘健 335317bd86 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 396464c573 update ao-account dependent version 2024-10-25 14:30:58 +08:00
HaoZhen Liu d93c76ca36 update translation 2024-10-25 14:30:57 +08:00
刘健 60ad6007e5 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 ceee520102 tmp commit 2024-10-25 14:21:50 +08:00
Maggie a053557000 Merge pull request #83 from APIParkLab/feature/v1.2
fix: AI Model config bug
2024-10-25 14:07:39 +08:00
杨梦洁 e7c14b0817 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 727fd0bd36 fix: AI Model config bug 2024-10-25 14:02:23 +08:00
Liujian 885cec57db update issue templete 2024-10-25 09:32:12 +08:00
Maggie 4ba2b0c9ab Merge pull request #70 from APIParkLab/feature/v1.2
fix: update translation
2024-10-25 09:28:32 +08:00
杨梦洁 b3672b8c66 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 b33dda4a32 fix: update translation 2024-10-25 09:27:00 +08:00
刘健 450e565718 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 00bd72c1e4 fix get llm error 2024-10-24 23:42:55 +08:00
Dot.L 81da1f45f1 Merge pull request #68 from APIParkLab/feature/ai-service
Feature/ai service
2024-10-24 23:31:32 +08:00
Liujian fd3d6433e2 finish fake ai 2024-10-24 23:30:25 +08:00
杨梦洁 24c24c1307 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 2bcee5e362 Merge pull request #67 from rolealiu/main
update translation
2024-10-24 18:25:40 +08:00
HaoZhen Liu 74d402a330 update translation 2024-10-24 18:24:51 +08:00
李冬杰 08bd8a9942 Merge branch 'feature/zhinao' into 'main'
Feature/zhinao

See merge request apipark/APIPark!41
2024-10-24 15:50:09 +08:00
lidongjie 6944260767 add:ai provider 360-zhinao 2024-10-24 15:47:43 +08:00
杨梦洁 3ada2d1d9d 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 4a48255be1 Merge pull request #66 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-24 14:41:41 +08:00
maggieyyy 25f8712a9f fix: Update translation 2024-10-24 14:39:49 +08:00
杨梦洁 f83b8c74ca 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 7a4f3dc4c5 fix: Modify translation 2024-10-24 13:51:22 +08:00
maggieyyy 26b52b1ab0 fix: Modify Ai setting 2024-10-24 11:40:14 +08:00
Liujian 9592a0ddda Merge remote-tracking branch 'origin/main' into feature/ai-service 2024-10-23 18:41:14 +08:00
杨梦洁 c48c3a4a1c 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 3e92b8dc97 feat: Modify sevice type selector 2024-10-23 18:22:04 +08:00
maggieyyy 0be33f019c fix: Password css 2024-10-23 17:41:40 +08:00
杨梦洁 68bda077e9 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 c956ebf618 fix: Add translation to api path match rule options 2024-10-23 16:52:36 +08:00
maggieyyy 041f4463f6 feat: Rename 'application' to 'consumer' and optimize consumer module display 2024-10-23 16:49:09 +08:00
刘健 1b217f1a54 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 db1d24bf54 upadte app list api 2024-10-23 16:42:56 +08:00
刘健 a67b5a5829 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 a606d0e8b1 update ai provider api 2024-10-23 16:29:18 +08:00
刘健 05b62016cd 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 a0853fc621 update provider logo 2024-10-23 14:22:44 +08:00
刘健 469c5ed7d3 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 920588057a update providers logo 2024-10-23 13:38:16 +08:00
maggieyyy 9c044b232a feat: Add path match type before api path & Modify Login Page 2024-10-23 11:58:53 +08:00
JackLiu 00764d9ac9 Merge pull request #65 from rolealiu/main
update translation
2024-10-22 17:53:45 +08:00
JackLiu d30897ac4c Merge branch 'APIParkLab:main' into main 2024-10-22 17:53:20 +08:00
HaoZhen Liu 49138e87c1 update translation 2024-10-22 17:53:48 +08:00
杨梦洁 1ddc5fb924 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 2a2ca248b1 Merge pull request #64 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-22 17:33:21 +08:00
maggieyyy ca06e100d3 fix: Simplified Chinese not working 2024-10-22 17:32:25 +08:00
maggieyyy 5fbc05f9ec Merge branch 'main' into feature/v1.2 2024-10-22 17:06:40 +08:00
maggieyyy 97d2d0e250 fix: Modify Login Page styles and Api document path 2024-10-22 17:05:40 +08:00
JackLiu 67549661c5 Update readme-jp.md 2024-10-22 15:53:56 +08:00
JackLiu 91666efc94 Update readme-zh-tw.md 2024-10-22 15:53:42 +08:00
JackLiu d173d82714 Update README.md 2024-10-22 15:53:27 +08:00
JackLiu 6621f93342 Update readme-zh-cn.md 2024-10-22 15:53:10 +08:00
JackLiu 4cdba13c8c Update readme-zh-tw.md 2024-10-22 15:51:30 +08:00
JackLiu 1d4ea6559a Update readme-jp.md 2024-10-22 15:49:41 +08:00
JackLiu 002db4bbf6 Update readme-zh-cn.md 2024-10-22 15:45:20 +08:00
JackLiu ae0c77ea0e Update README.md 2024-10-22 15:40:14 +08:00
JackLiu 1b9980c980 Update feature_request.yml 2024-10-22 14:13:35 +08:00
maggieyyy bf2aefe2da fix: route config 2024-10-22 14:05:12 +08:00
HaoZhen Liu bdea9ad4f2 update translation 2024-10-22 12:31:51 +08:00
JackLiu d21247c0a6 Merge pull request #60 from rolealiu/main
update translation
2024-10-22 12:31:22 +08:00
Maggie c1994bd3a8 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
杨梦洁 67c9e95017 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 0ea7467a4e fix: Modify peer address to use array format 2024-10-22 10:28:14 +08:00
maggieyyy 540a31f237 fix: aiservice router 2024-10-22 10:20:34 +08:00
Dot.L 18214653d0 Merge pull request #58 from APIParkLab/feature/ai-service
Feature/ai service
2024-10-21 19:02:50 +08:00
Liujian 83337945dc Merge remote-tracking branch 'origin/main' into feature/ai-service 2024-10-21 19:01:07 +08:00
刘健 9c19da7cd5 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 cfa1f2e9e6 test frontend change 2024-10-21 18:59:24 +08:00
刘健 ab9dccedc9 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 58a870449c copy frontend/dist to artifacts/dist 2024-10-21 18:53:28 +08:00
刘健 04146e9bd2 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 e9bfcef165 print frontend dir 2024-10-21 18:47:54 +08:00
刘健 c98f3f20cb 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 a4bae6d826 print frontend dir 2024-10-21 18:43:06 +08:00
刘健 8c5a60c083 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 4ead565142 update builder script 2024-10-21 18:36:19 +08:00
刘健 3eaa877567 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 d026f13a06 update builder script 2024-10-21 18:28:26 +08:00
刘健 ff48f27700 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 f507fbc111 update feishu informer rule 2024-10-21 18:19:30 +08:00
Liujian 064c3bc02f update feishu informer rule 2024-10-21 18:17:11 +08:00
Liujian f877363158 update feishu informer rule 2024-10-21 18:12:44 +08:00
Maggie b6c53cc5c6 Merge pull request #57 from maggieyyy/feature/v1.2
Feature/v1.2
2024-10-21 18:12:36 +08:00
Maggie 8eda537d7c Merge branch 'APIParkLab:main' into feature/v1.2 2024-10-21 18:11:15 +08:00
杨梦洁 e65a9cdee4 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 2fd3a78cf8 frontend: delete comment 2024-10-21 18:07:10 +08:00
刘健 e06abd3c7a 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 0d8f5c4eb5 update gitlab runner exec rule 2024-10-21 18:01:47 +08:00
Liujian ddd5db032e update deploy exec script 2024-10-21 18:00:20 +08:00
Liujian 76f418d3df fix builder exec script 2024-10-21 17:56:50 +08:00
Maggie 131112f00c Merge pull request #56 from maggieyyy/feature/v1.2
Feature/v1.2
2024-10-21 17:49:02 +08:00
杨梦洁 04737dbfae Merge branch 'feature/v1.2' into 'main'
frontend: update

See merge request apipark/APIPark!22
2024-10-21 17:47:06 +08:00
Liujian 3d86672b52 新建prefix.sh文件 2024-10-21 17:46:26 +08:00
maggieyyy 601ff0571b fix: service type field changes 2024-10-21 17:45:31 +08:00
maggieyyy 0505045c81 fix: router config 2024-10-21 17:41:30 +08:00
Liujian aab47ec0c6 update run auto deploy condition 2024-10-21 17:06:52 +08:00
Liujian 7bc60c0574 update stage 2024-10-21 17:04:57 +08:00
刘健 a64246f2c0 Merge branch 'feature/groq' into 'main'
add:添加GroqCloud供应商

See merge request apipark/APIPark!16
2024-10-21 17:02:46 +08:00
Liujian b5447a6a41 Gitlab automatically compiles and submits 2024-10-21 16:58:17 +08:00
Liujian adb15b2cae test frontend dir change 2024-10-21 16:16:46 +08:00
Liujian 533ec2b0f8 Fix code errors caused by rebase 2024-10-21 15:51:15 +08:00
Liujian c2f9526c6b Update ao-account dependency version 2024-10-21 15:48:01 +08:00
Liujian 4348ad1c3e API Market Service Interface add service_kind Field 2024-10-21 15:07:13 +08:00
maggieyyy 1a18d79d94 fix: Add MF 2024-10-21 14:41:49 +08:00
maggieyyy cef90dd2e4 merge 2024-10-21 14:20:25 +08:00
JackLiu 63565b04d5 Merge pull request #55 from rolealiu/main
update translation
2024-10-21 12:17:09 +08:00
HaoZhen Liu 6ad7666b93 update translation 2024-10-21 12:17:34 +08:00
Maggie 7975875b07 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 0760929963 fix: Add new fields for translation in Service Hub 2024-10-21 11:22:14 +08:00
Maggie 57c4e7f267 Merge pull request #53 from maggieyyy/main
fix: Add new fields for translation
2024-10-21 10:29:30 +08:00
maggieyyy f7e6578043 fix: Add new fields for translation 2024-10-21 10:27:37 +08:00
JackLiu 7717af32d6 Merge pull request #52 from rolealiu/main
add chinese-tr and japanese lang readme
2024-10-19 00:55:00 +08:00
HaoZhen Liu ba9321e442 add chinese-tr and japanese lang readme 2024-10-19 00:55:13 +08:00
JackLiu f79641c1dd Update readme-zh-cn.md 2024-10-19 00:41:00 +08:00
JackLiu 9ef2cd9963 Update README.md 2024-10-19 00:40:24 +08:00
JackLiu 67866a671c Update readme-zh-cn.md 2024-10-19 00:27:31 +08:00
JackLiu c865349b27 Merge pull request #51 from rolealiu/main
improve translation
2024-10-19 00:08:18 +08:00
HaoZhen Liu d95f1b67d2 improve translation 2024-10-19 00:08:44 +08:00
JackLiu 961a2e41e9 Merge pull request #50 from rolealiu/main
improve translation
2024-10-19 00:05:41 +08:00
JackLiu 5d2be6e20e Merge branch 'APIParkLab:main' into main 2024-10-19 00:04:08 +08:00
HaoZhen Liu e59131dcc9 improve translation 2024-10-19 00:04:26 +08:00
HaoZhen Liu 2bdc46e50e improve translation 2024-10-18 23:58:27 +08:00
JackLiu 41705fd929 Merge pull request #49 from rolealiu/main
improve translation
2024-10-18 23:16:44 +08:00
HaoZhen Liu 6dd5089866 improve translation 2024-10-18 23:15:29 +08:00
HaoZhen Liu 126b38a19a improve translation 2024-10-18 23:14:30 +08:00
Liujian 06b1cb3400 Initial installation of initialization data for simplified use. 2024-10-18 22:15:55 +08:00
Liujian 7101584d75 注释ap-account本地依赖 2024-10-18 19:51:42 +08:00
Liujian 6e9939f96e 新增i18n操作 2024-10-18 19:50:20 +08:00
Maggie 42f312d97b 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 e52f107dbe fix: update i18n files 2024-10-18 19:13:37 +08:00
maggieyyy 22898a3019 merge 2024-10-18 18:49:32 +08:00
maggieyyy ff1d58e4f7 fix: remove roles i18n & update i18n scanner 2024-10-18 18:47:17 +08:00
JackLiu 25f448b377 Merge pull request #47 from rolealiu/main
re-translate i18n language file
2024-10-18 18:34:31 +08:00
JackLiu 258d9cd314 Merge branch 'APIParkLab:main' into main 2024-10-18 18:33:36 +08:00
HaoZhen Liu f1943096f2 modify i18n language file 2024-10-18 18:33:40 +08:00
maggieyyy 67deef3c4f fix: delete files & width of pic in editor & timing bug 2024-10-18 18:05:47 +08:00
Liujian 86129c3158 Initialize deployment with built-in data optimization 2024-10-18 15:38:39 +08:00
Liujian 95dde4dd5d finish ai router 2024-10-18 12:10:27 +08:00
JackLiu 27294a10a7 Merge pull request #46 from rolealiu/main
add zh-tw and japaness lang
2024-10-18 01:42:17 +08:00
HaoZhen Liu e19b6c8740 add zh-tw and japaness lang 2024-10-18 01:42:14 +08:00
Dot.L bc3cd9e0fd Merge pull request #45 from Dot-Liu/main
AI service experience optimization
2024-10-17 23:50:59 +08:00
Liujian b47c0558ab 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 9ae1f62555 Experience optimization 2024-10-17 23:47:26 +08:00
Maggie 87b077234a Merge pull request #44 from maggieyyy/main
fix: delete useless file
2024-10-17 18:49:02 +08:00
Maggie b27df509f2 Merge branch 'APIParkLab:main' into main 2024-10-17 18:48:06 +08:00
maggieyyy c339ae16c2 feat: delete en-GB file 2024-10-17 18:47:33 +08:00
Maggie 35943d990c Merge pull request #43 from maggieyyy/main
frontend: update service & support more language
2024-10-17 18:44:25 +08:00
maggieyyy 35e0806a59 frontend: update service & support more language 2024-10-17 18:42:52 +08:00
Liujian ad017d9f97 系统常规设置完成 2024-10-17 12:00:19 +08:00
Liujian c0ddcf7c5f 服务列表接口合并 2024-10-16 19:26:33 +08:00
lidongjie 2f7de57e21 modify:删除oci和lepton 2024-10-16 16:30:43 +08:00
Liujian 3e353f4eff finish nvidia 2024-10-16 16:17:32 +08:00
李冬杰 35dc9ca1ad Merge branch 'feature/chatglm' into 'main'
fix:添加chatglm address

See merge request apipark/APIPark!20
2024-10-16 15:01:34 +08:00
lidongjie 0c488c1f90 fix:添加chatglm address 2024-10-16 15:00:06 +08:00
Liujian 85321b87c0 修改讯飞星火定义 2024-10-16 14:52:56 +08:00
JackLiu ce5b5982a3 Update README.md 2024-10-15 22:27:33 +08:00
JackLiu 28a99c42f1 Update readme-zh-cn.md 2024-10-15 22:23:50 +08:00
JackLiu 1e8a3060ec Update README.md 2024-10-15 22:19:07 +08:00
李冬杰 41dc311fd9 Merge branch 'feature/chatglm' into 'main'
add:添加chatglm供应商

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

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

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

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

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

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

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

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

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

See merge request apipark/APIPark!9
2024-10-12 18:05:04 +08:00
lidongjie 1a0805722d add:添加baichuan供应商 2024-10-12 18:03:19 +08:00
Liujian b3d2fb0bcc 后端优化完成 2024-10-12 10:42:52 +08:00
Liujian 59877b2a20 Merge remote-tracking branch 'origin/main' 2024-10-11 18:41:13 +08:00
Liujian 6aef15666a 修改model字段长度为255 2024-10-11 18:40:54 +08:00
李冬杰 7247d157a7 Merge branch 'feature/mistralai' into 'main'
add:添加mistralai供应商

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

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

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

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

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

See merge request apipark/APIPark!3
2024-10-11 16:04:04 +08:00
lidongjie 80f8b91631 modify:tongyi host 2024-10-11 16:02:15 +08:00
lidongjie 864591a37a fix:通义千问 2024-10-11 14:42:58 +08:00
Liujian 1a703bf738 优化schema 2024-10-11 14:29:38 +08:00
lidongjie 1762386336 add:添加通义千问 2024-10-11 14:13:25 +08:00
lidongjie b002392c21 add:添加通义千问 2024-10-11 14:04:49 +08:00
Liujian 4de0c3789a Merge remote-tracking branch 'origin/main' 2024-10-10 21:50:12 +08:00
Liujian 84c33ef8f6 发布流程优化 2024-10-10 21:48:42 +08:00
刘健 93295ab7f4 Merge branch 'feature/moonshot' into 'main'
Feature/moonshot

See merge request apipark/APIPark!2
2024-10-10 19:15:30 +08:00
lidongjie cc9f06384d 合并代码,月之暗面 2024-10-10 19:09:45 +08:00
Liujian 18b7e89b6c 模型列表接入 2024-10-10 18:28:27 +08:00
lidongjie 214419ff57 add:Moonshot ai provider 2024-10-10 18:18:59 +08:00
Liujian 9982cf6d0e apinto对接完成 2024-10-08 12:09:33 +08:00
Liujian 9a2ba0943c 修复bug 2024-09-29 14:46:58 +08:00
Liujian 1c71a0b226 多模型对接完成 2024-09-27 19:14:52 +08:00
Maggie 9349a83479 Merge pull request #41 from maggieyyy/main
feat: ai-service ui
2024-09-26 21:04:28 +08:00
Maggie 3454fdeec0 Merge branch 'APIParkLab:main' into main 2024-09-26 21:02:54 +08:00
maggieyyy 939d02f833 feat: ai-service ui 2024-09-26 21:01:51 +08:00
Liujian 03079e23a6 修改权限名称 2024-09-26 18:08:29 +08:00
Liujian 2e8ddb52eb 权限更新 2024-09-26 17:59:31 +08:00
Liujian ea62e9cd3f ai路由完成 2024-09-25 20:28:01 +08:00
Liujian cb9f048f15 AI服务接口完成 2024-09-25 11:56:51 +08:00
Liujian d9eccb6bf5 AI供应商接口修复bug 2024-09-25 11:39:22 +08:00
Dot.L 981a338e9b Modify Chinese Readme incorrect link
Modify Chinese Readme incorrect link
2024-09-25 09:46:44 +08:00
Liujian b930916ccd 新增AI服务接口 2024-09-25 09:35:58 +08:00
Liujian 83afaab6bf 修改获取模型列表接口 2024-09-24 15:06:44 +08:00
Liujian a104902abd AI供应商相关接口完成 2024-09-24 14:15:52 +08:00
maggieyyy 12ff850742 Merge pull request #39 from maggieyyy/main
fix: english version & tags id bugs
2024-09-14 14:38:08 +08:00
maggieyyy 252cdfef35 fix:tags id 2024-09-14 14:36:31 +08:00
maggieyyy b2861fd7fd fix:team member tranlated 2024-09-09 14:09:15 +08:00
maggieyyy 64a2a4c5da fix:english style 2024-09-09 13:48:39 +08:00
Dot.L bd64c39882 Merge pull request #37 from Dot-Liu/main
修复_commit表和_latest表初始化失败的问题
2024-09-06 10:37:04 +08:00
Liujian 1a856a917e 修复_commit表和_latest表初始化失败的问题 2024-09-06 10:32:54 +08:00
maggieyyy c1275c4033 Merge pull request #35 from maggieyyy/main
frontend: fix router list view
2024-09-03 10:07:27 +08:00
maggieyyy f00e909a64 frontend: fix router list view 2024-09-03 10:06:19 +08:00
Dot.L fed865872e Merge pull request #34 from Dot-Liu/main
修复服务获取API列表是获取到别的服务的API
2024-09-02 21:20:31 +08:00
Liujian fd270f2c02 修复服务获取API列表是获取到别的服务的API 2024-09-02 21:14:30 +08:00
Dot.L f2635bf457 Merge pull request #33 from Dot-Liu/main
初始化时当角色存在时,更新角色权限信息
2024-09-02 19:57:03 +08:00
Liujian 4e0813d49e 初始化时当角色存在时,更新角色权限信息 2024-09-02 19:56:04 +08:00
Dot.L 1f8e2bf6c3 Merge pull request #32 from Dot-Liu/main
修复报错:undefined: pm3.CreateRouterSimple
2024-09-02 19:32:46 +08:00
Liujian b58a031a69 修复报错:undefined: pm3.CreateRouterSimple 2024-09-02 19:32:02 +08:00
Dot.L d96f11d968 Merge pull request #31 from Dot-Liu/main
修复openapiv2保存失败的问题
2024-09-02 19:09:11 +08:00
Liujian b22b160aad 修复openapiv2保存失败的问题 2024-09-02 19:07:57 +08:00
Liujian debf19b059 Merge remote-tracking branch 'github-pro/main' into main-github 2024-09-02 19:03:23 +08:00
Dot.L 0f8c14971e Merge pull request #30 from Dot-Liu/main
1.1.0-beta后端代码提交
2024-09-02 18:28:45 +08:00
Liujian fdd4ce3c19 修复更新集群时配置不重新初始化的问题 2024-09-02 18:27:27 +08:00
Liujian 9317f20917 Merge branch 'main' into main-github 2024-09-02 18:00:18 +08:00
maggieyyy 4228cf45f5 Merge pull request #29 from maggieyyy/main
fix:change route & permission btn & datasource access
2024-09-02 17:53:56 +08:00
maggieyyy 1bedad903b fix:change route & permission btn & datasource access 2024-09-02 17:09:44 +08:00
rolea liu e281282514 Merge pull request #28 from rolealiu/main
update translate
2024-09-02 14:25:55 +08:00
HaoZhen Liu 298789e0e2 add english readme 2024-09-02 14:25:39 +08:00
HaoZhen Liu 007e4bdcfb add english readme 2024-09-02 14:21:56 +08:00
rolea liu a7378492ef Merge pull request #27 from rolealiu/main
update translate
2024-09-02 14:21:47 +08:00
rolea liu 4ad23acfb6 Merge pull request #26 from rolealiu/main
update translation
2024-09-02 14:18:15 +08:00
rolea liu 5dfa1170ba Merge branch 'APIParkLab:main' into main 2024-09-02 14:17:43 +08:00
HaoZhen Liu a4d9b0202b add english readme 2024-09-02 14:18:19 +08:00
maggieyyy 3a23ec2ab3 Merge pull request #25 from maggieyyy/main
fix: router match bugs
2024-09-02 13:43:54 +08:00
maggieyyy 0dcea3f03a Merge branch 'main' of github.com:maggieyyy/APIPark into mainGithub 2024-09-02 13:42:44 +08:00
maggieyyy 851c54b6af fix: match type is empty 2024-09-02 13:40:50 +08:00
Liujian bf78926b31 修复路由详情没有返回协议的问题 2024-09-02 11:24:46 +08:00
Liujian 2aada85662 修复上游保存失败问题 2024-09-02 10:20:06 +08:00
Liujian 7d569a49cb 修复发布报错 2024-09-02 10:02:33 +08:00
Liujian 6d69a06935 发布自测完毕 2024-09-01 23:55:45 +08:00
maggieyyy 77aa0080d9 fix:publish status & api doc 2024-08-30 19:38:59 +08:00
Liujian 2ef746bf37 发布功能完成 2024-08-30 19:35:18 +08:00
maggieyyy 809959289c Merge pull request #24 from maggieyyy/main
feat:openapi ui
2024-08-30 19:23:17 +08:00
maggieyyy de74542e78 feat:openapi ui 2024-08-30 19:22:38 +08:00
Liujian 2ae0cb8b51 发布初始提交 2024-08-30 18:33:35 +08:00
Liujian cea880ad5c 路由、权限相关接口完成 2024-08-30 16:48:43 +08:00
Liujian f570c8b174 api文档完成 2024-08-30 09:55:56 +08:00
maggieyyy 6f4a95b0da Merge pull request #23 from maggieyyy/main
fix: change build config
2024-08-28 18:01:49 +08:00
maggieyyy 2817974672 Merge branch 'APIParkLab:main' into main 2024-08-28 18:01:19 +08:00
maggieyyy 1f8ad0fda3 Merge branch 'main' of github.com:maggieyyy/APIPark into mainGithub 2024-08-28 18:00:50 +08:00
maggieyyy 189a1c8fa3 fix:change vite build config 2024-08-28 18:00:30 +08:00
maggieyyy 35de0c003c Merge pull request #22 from maggieyyy/main
fix:intelligent plugin & browser lang & check monitor config
2024-08-28 14:09:32 +08:00
maggieyyy 7ccaa8972c Merge branch 'APIParkLab:main' into main 2024-08-28 14:08:29 +08:00
maggieyyy 9c8418ab40 fix:intelligent plugin & browser lang & check monitor config 2024-08-28 14:07:55 +08:00
maggieyyy c9a2a56dd9 Merge pull request #21 from maggieyyy/main
fix:intelligent i18next
2024-08-27 10:47:15 +08:00
maggieyyy 31cb70ed02 fix:intelligent i18next 2024-08-27 10:45:27 +08:00
rolea liu 1fc2113c9a Merge pull request #20 from rolealiu/main
add english readme
2024-08-26 17:48:37 +08:00
HaoZhen Liu 8c07b63dec add english readme 2024-08-26 17:48:45 +08:00
rolea liu 13ec24d95e Merge pull request #19 from rolealiu/main
add english readme
2024-08-26 17:46:17 +08:00
HaoZhen Liu fd5357a736 Merge remote-tracking branch 'upstream/main' 2024-08-26 17:46:12 +08:00
HaoZhen Liu b349f8b156 add english readme 2024-08-26 17:40:48 +08:00
HaoZhen Liu 30d446aa16 add english readme 2024-08-26 17:33:30 +08:00
HaoZhen Liu a5e19c2705 add english readme 2024-08-26 17:29:18 +08:00
HaoZhen Liu d7ac23235a add english readme 2024-08-26 17:27:43 +08:00
rolea liu 9e95144e86 Merge pull request #18 from rolealiu/main
Improve translation
2024-08-26 17:18:10 +08:00
rolea liu 999957ef56 Merge branch 'APIParkLab:main' into main 2024-08-26 17:16:00 +08:00
HaoZhen Liu 4a523c611d Improve translation 2024-08-26 17:05:26 +08:00
HaoZhen Liu 438d0a7fa2 Improve translation 2024-08-26 16:17:57 +08:00
HaoZhen Liu 045a8abcfb Improve translation 2024-08-26 16:14:11 +08:00
HaoZhen Liu f5a141daf0 Improve translation 2024-08-26 16:12:40 +08:00
HaoZhen Liu d77025cb9e Improve translation 2024-08-26 16:07:07 +08:00
rolea liu 167d2e5c1f Merge pull request #17 from rolealiu/main
Improve translation
2024-08-26 15:39:38 +08:00
HaoZhen Liu 36e72169b8 Merge remote-tracking branch 'upstream/main' 2024-08-26 15:37:26 +08:00
HaoZhen Liu 0d67eab7f7 Improve translation 2024-08-26 15:19:45 +08:00
rolea liu c7bfbe6b9f Merge pull request #16 from rolealiu/main
Improve translation
2024-08-26 15:09:43 +08:00
HaoZhen Liu 577f846545 Improve translation 2024-08-26 15:09:03 +08:00
maggieyyy 05f6071119 Merge pull request #15 from maggieyyy/main
fix:i18next
2024-08-26 14:44:21 +08:00
maggieyyy b57c80a5ae fix:i18next 2024-08-26 14:42:34 +08:00
Liujian f3a00814a5 新增检测是否开启监控接口 2024-08-26 11:13:11 +08:00
Dot.L d40e88c945 Merge pull request #13 from Dot-Liu/main
监控后端完成
2024-08-23 19:51:38 +08:00
Liujian 7671bb3a8c Merge remote-tracking branch 'github-pro/main' into main-github 2024-08-23 19:49:28 +08:00
maggieyyy 6bc93f8176 Merge pull request #12 from maggieyyy/main
fix:login with language setting
2024-08-23 19:45:53 +08:00
maggieyyy c5cee7c6de fix:login with language setting 2024-08-23 19:44:14 +08:00
maggieyyy 118b847995 Merge pull request #11 from maggieyyy/main
fix:i18next
2024-08-23 19:19:30 +08:00
maggieyyy b5a701d560 Merge branch 'main' of github.com:maggieyyy/APIPark 2024-08-23 19:17:38 +08:00
maggieyyy b84910f7d5 fix:i18next 2024-08-23 19:16:21 +08:00
Liujian 92230b6dda Merge branch 'main' into main-github 2024-08-23 19:14:37 +08:00
Liujian 1d2edf8ca7 Merge remote-tracking branch 'github-pro/main' into main-github 2024-08-23 18:59:49 +08:00
Liujian 8012ac42fe 修改依赖 2024-08-23 18:58:13 +08:00
maggieyyy 16d401ffa6 Merge pull request #10 from maggieyyy/main
fix:i18next
2024-08-23 18:51:48 +08:00
maggieyyy 75569097b2 merge 2024-08-23 18:18:45 +08:00
maggieyyy 61c0f94538 fix: i18n bugs 2024-08-23 18:16:48 +08:00
rolea liu 9378188b59 Merge pull request #9 from rolealiu/main
Translate chinese to english
2024-08-23 16:36:51 +08:00
HaoZhen Liu fa49bf7fc0 translate chinese to english 2024-08-23 16:33:26 +08:00
HaoZhen Liu ee5edd1abc translate chinese to english 2024-08-23 16:32:42 +08:00
Dot.L 1f43f1ad66 Merge pull request #8 from maggieyyy/main
feat: guide
2024-08-23 15:43:23 +08:00
maggieyyy d7d12d7ac0 Merge branch 'main' of github.com:maggieyyy/APIPark 2024-08-23 15:41:41 +08:00
maggieyyy 26493be5ee feat:guide 2024-08-23 15:41:26 +08:00
Dot.L 7e399cc181 Merge pull request #7 from maggieyyy/main
fix:access &  monitor style
2024-08-23 10:41:48 +08:00
maggieyyy c1a1d16ca8 fix:access & monitor style 2024-08-22 18:30:20 +08:00
Liujian d6d0c9f914 修复监控获取数据失败问题 2024-08-22 18:08:18 +08:00
Liujian 9ece54b099 监控接口完成 2024-08-22 11:24:41 +08:00
Liujian 09130df02d 修改go-common和ap-account依赖 2024-08-22 09:37:30 +08:00
Liujian 428cbf4781 监控部分迁移 2024-08-21 23:42:15 +08:00
Dot.L 1be6f4e814 Merge pull request #6 from maggieyyy/main
dashboard && tour && guest_login
2024-08-21 18:39:45 +08:00
maggieyyy 11df2331cd Merge branch 'APIParkLab:main' into main 2024-08-21 18:11:26 +08:00
maggieyyy 5ebda41e96 feat:dashboard && tour && guest_login 2024-08-21 18:09:11 +08:00
Dot.L ec1eeb6368 Merge pull request #5 from maggieyyy/main
feat:多语言
2024-08-20 18:51:06 +08:00
maggieyyy 49efc0e4df feat:多语言 2024-08-20 18:49:14 +08:00
Liujian 49ef8d54db Merge remote-tracking branch 'github/main' 2024-08-20 14:32:59 +08:00
Liujian 276b88274f 七牛云登录 2024-08-20 11:38:01 +08:00
Liujian 5c239a2c53 新增登录操作 2024-08-20 11:23:17 +08:00
Liujian b6161813cb github action新增变量QINIU_BUCKET 2024-08-20 11:02:45 +08:00
Liujian eeeb9a3815 修改qshell版本号为2.9.0 2024-08-20 10:55:18 +08:00
Liujian 924e6c8a2e 修改七牛云脚本命令 2024-08-20 10:33:24 +08:00
Liujian b4d2071ba7 修改七牛云上传依赖 2024-08-20 10:23:11 +08:00
Liujian 3c7c6e6c41 修改github action脚本 2024-08-20 10:05:54 +08:00
Liujian 6c4704de1a 新增上传到七牛云操作 2024-08-20 10:01:51 +08:00
Dot.L 92a3abea89 Merge pull request #1 from Dot-Liu/main
APIPark-1.0-beta完成
2024-08-16 20:56:44 +08:00
Liujian 2e3bfffc41 APIPark访客模式完成 2024-08-16 20:55:16 +08:00
rolea liu 7190c32ebe Update README.md 2024-08-16 18:24:20 +08:00
rolea liu 7506fac410 Update README.md 2024-08-16 18:15:31 +08:00
Liujian 03d76ce154 修改依赖版本号 2024-08-16 18:06:32 +08:00
Liujian e29d76f2dc frontend:服务详情宽度 2024-08-16 18:01:09 +08:00
Liujian 56c0c00cba 修复可删除唯一团队管理员的问题 2024-08-16 17:59:04 +08:00
rolea liu c823c34ac8 Update README.md 2024-08-16 17:39:14 +08:00
Liujian 0424165a2f Merge remote-tracking branch 'github/main' 2024-08-16 16:35:48 +08:00
Liujian aa8548d90d 修复新增订阅方失败的问题 2024-08-16 16:35:34 +08:00
Liujian 400687914a 新增访客模式 2024-08-16 11:27:41 +08:00
Liujian 9525b0622b 前端代码更新 2024-08-15 18:28:46 +08:00
Liujian 98b59c760b Merge branch 'main' into main-github 2024-08-15 11:34:48 +08:00
Liujian 040d657ef6 新增自动打包脚本 2024-08-15 11:34:33 +08:00
Liujian 70ea4c77ae 修复动态模块上下线失败的问题 2024-08-15 09:53:01 +08:00
Liujian 215b87f83c 首次提交APIPark代码,面向开源 2024-08-12 21:38:09 +08:00
rolea liu 34dc99ff23 Initial commit 2024-08-12 10:26:35 +08:00
215 changed files with 2719 additions and 14987 deletions
+1 -2
View File
@@ -7,5 +7,4 @@
/.vscode/
.air.toml
/tmp/
/work
/cmd/
/work
-88
View File
@@ -1,88 +0,0 @@
variables:
PATH: /opt/go-1.23/go/bin/:/opt/node-1.22/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
GOROOT: /opt/go-1.23/go
GOPROXY: https://goproxy.cn
VERSION: $CI_COMMIT_SHORT_SHA
APP: apipark
APP_PRE: ${APP}_${VERSION}
BUILD_DIR: ${APP}-build
DEPLOY_DESC: "DEV 环境"
VIEW_ADDR: http://172.18.166.219:8288
SAVE_DIR: /opt/${APP}
NODE_OPTIONS: --max_old_space_size=8192
stages:
# - notice
- build
- deploy
- webhook
#
#feishu-informer: # 飞书回调
# stage: notice
# variables:
# DIFF_URL: "$CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID/diffs"
# rules:
# - if: $CI_PIPELINE_SOURCE=="merge_request_event" && $CI_COMMIT_BRANCH =~ "main-github-pro"
# script:
# - echo "merge request"
# - |
# curl -X POST -H "Content-Type: application/json" \
# -d "{\"msg_type\":\"text\",\"content\":{\"text\":\"项目:${CI_PROJECT_NAME}\\n提交人:${GITLAB_USER_NAME}\\n提交信息:${CI_MERGE_REQUEST_TITLE}\\n合并分支信息:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} -> ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}\\n差异性地址:${DIFF_URL}\\n请及时review代码\"}}" \
# ${FEISHU_WEBHOOK}
builder:
stage: build
rules:
- if: $CI_COMMIT_BRANCH == "main-github-pro" || $CI_COMMIT_BRANCH == "main"
script:
- set -e
- |
if [ ! -d "../artifacts" ]; then
mkdir -p ../artifacts
fi
if [ -d "../artifacts/dist" ]; then
cp -r ../artifacts/dist frontend/dist
fi
- |
if [ -n "$(git diff --name-status HEAD~1 HEAD -- frontend)" ]; then
./scripts/build.sh $BUILD_DIR ${VERSION} all ""
else
./scripts/build.sh $BUILD_DIR ${VERSION}
fi
if [ -d "frontend/dist" ]; then
echo "copy frontend/dist to artifacts/dist"
rm -fr ../artifacts/dist
cp -r frontend/dist ../artifacts/dist
fi
cp $BUILD_DIR/${APP_PRE}_linux_amd64.tar.gz ${SAVE_DIR}
deployer:
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == "main-github-pro" || $CI_COMMIT_BRANCH == "main"
variables:
APIPARK_GUEST_MODE: allow
APIPARK_GUEST_ID: dklejrfbhjqwdh
script:
- cd ${SAVE_DIR};mkdir -p ${APP_PRE};tar -zxvf ${APP_PRE}_linux_amd64.tar.gz -C ${APP_PRE};cd ${APP_PRE};./install.sh ${SAVE_DIR};./run.sh restart;cd ${SAVE_DIR} && ./clean.sh ${APP_PRE}
when: on_success
success:
stage: webhook
rules:
- if: $CI_COMMIT_BRANCH == "main-github-pro" || $CI_COMMIT_BRANCH == "main"
script:
- |
curl -X POST -H "Content-Type: application/json" \
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署完成.\\n访问地址:${VIEW_ADDR}\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
${FEISHU_WEBHOOK}
when: on_success
failure:
stage: webhook
rules:
- if: $CI_COMMIT_BRANCH == "main-github-pro" || $CI_COMMIT_BRANCH == "main"
script:
- |
curl -X POST -H "Content-Type: application/json" \
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署失败,请及时到gitlab上查看\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
${FEISHU_WEBHOOK}
when: on_failure
-77
View File
@@ -1,77 +0,0 @@
package common
import (
"fmt"
"strconv"
)
func FormatCountInt64(count int64) string {
switch {
case count < 1000:
return strconv.FormatInt(count, 10)
case count < 1000000:
return fmt.Sprintf("%.1fK", float64(count)/1000)
case count < 1000000000:
return fmt.Sprintf("%.1fM", float64(count)/1000000)
case count < 1000000000000:
return fmt.Sprintf("%.1fB", float64(count)/1000000000)
default:
return fmt.Sprintf("%.1fT", float64(count)/1000000000000)
}
}
func FormatCountFloat64(count float64) string {
switch {
case count < 1000:
return fmt.Sprintf("%.1f", count)
case count < 1000000:
return fmt.Sprintf("%.1fK", count/1000)
case count < 1000000000:
return fmt.Sprintf("%.1fM", count/1000000)
case count < 1000000000000:
return fmt.Sprintf("%.1fB", count/1000000000)
default:
return fmt.Sprintf("%.1fT", count/1000000000000)
}
}
func FormatTime(t int64) string {
if t < 1000 {
return strconv.FormatInt(t, 10) + "ms"
}
if t < 1000000 {
return fmt.Sprintf("%.1fs", float64(t)/1000)
}
if t < 1000000000 {
return fmt.Sprintf("%.1fmin", float64(t)/1000000)
}
if t < 1000000000000 {
return fmt.Sprintf("%.1fhour", float64(t)/1000000000)
}
return fmt.Sprintf("%.1D", float64(t)/1000000000000)
}
func FormatByte(b int64) string {
const (
KB = 1000
MB = KB * 1000
GB = MB * 1000
TB = GB * 1000
PB = TB * 1000
)
switch {
case b < KB:
return fmt.Sprintf("%dB", b)
case b < MB:
return fmt.Sprintf("%.1fKB", float64(b)/KB)
case b < GB:
return fmt.Sprintf("%.1fMB", float64(b)/MB)
case b < TB:
return fmt.Sprintf("%.1fGB", float64(b)/GB)
case b < PB:
return fmt.Sprintf("%.1fTB", float64(b)/TB)
default:
return fmt.Sprintf("%.1fPB", float64(b)/PB)
}
}
-2
View File
@@ -29,8 +29,6 @@ func FmtIntFromInterface(val interface{}) int64 {
return int64(ret)
case int:
return int64(ret)
case float64:
return int64(ret)
default:
return 0
}
+1 -13
View File
@@ -3,7 +3,6 @@ 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"
@@ -15,7 +14,6 @@ var (
type imlCatalogueController struct {
catalogueModule catalogue.ICatalogueModule `autowired:""`
appModule service.IAppModule `autowired:""`
tagModule tag.ITagModule `autowired:""`
}
@@ -28,17 +26,7 @@ func (i *imlCatalogueController) Subscribe(ctx *gin.Context, subscribeInfo *cata
}
func (i *imlCatalogueController) ServiceDetail(ctx *gin.Context, sid string) (*catalogue_dto.ServiceDetail, error) {
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
return i.catalogueModule.ServiceDetail(ctx, sid)
}
func (i *imlCatalogueController) Search(ctx *gin.Context, keyword string) ([]*catalogue_dto.Item, []*tag_dto.Item, error) {
-277
View File
@@ -1,277 +0,0 @@
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
@@ -1,24 +0,0 @@
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
@@ -1,35 +0,0 @@
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)
}
-61
View File
@@ -2,7 +2,6 @@ package monitor
import (
"fmt"
"strconv"
"time"
"github.com/APIParkLab/APIPark/module/monitor"
@@ -18,66 +17,6 @@ type imlMonitorStatisticController struct {
module monitor.IMonitorStatisticModule `autowired:""`
}
func (i *imlMonitorStatisticController) ChartRestOverview(ctx *gin.Context, start string, end string) (*monitor_dto.ChartRestOverview, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, err
}
return i.module.RestChartOverview(ctx, "", s, e)
}
func (i *imlMonitorStatisticController) ChartAIOverview(ctx *gin.Context, start string, end string) (*monitor_dto.ChartAIOverview, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, err
}
return i.module.AIChartOverview(ctx, "", s, e)
}
func (i *imlMonitorStatisticController) AITopN(ctx *gin.Context, start string, end string, limit string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, nil, err
}
l, err := strconv.Atoi(limit)
if err != nil {
if limit == "" {
l = 10
} else {
return nil, nil, fmt.Errorf("parse limit %s error: %w", limit, err)
}
}
return i.module.Top(ctx, "", s, e, l, "ai")
}
func formatTime(start string, end string) (int64, int64, error) {
s, err := strconv.ParseInt(start, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse start time %s error: %w", start, err)
}
e, err := strconv.ParseInt(end, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse end time %s error: %w", end, err)
}
return s, e, nil
}
func (i *imlMonitorStatisticController) RestTopN(ctx *gin.Context, start string, end string, limit string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, nil, err
}
l, err := strconv.Atoi(limit)
if err != nil {
if limit == "" {
l = 10
} else {
return nil, nil, fmt.Errorf("parse limit %s error: %w", limit, err)
}
}
return i.module.Top(ctx, "", s, e, l, "rest")
}
func (i *imlMonitorStatisticController) Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error) {
switch dataType {
case monitor_dto.DataTypeApi:
-5
View File
@@ -22,11 +22,6 @@ type IMonitorStatisticController interface {
InvokeTrendInner(ctx *gin.Context, dataType string, typ string, api string, provider string, subscriber string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
StatisticsInner(ctx *gin.Context, dataType string, typ string, id string, input *monitor_dto.StatisticInput) (interface{}, error)
ChartRestOverview(ctx *gin.Context, start string, end string) (*monitor_dto.ChartRestOverview, error)
ChartAIOverview(ctx *gin.Context, start string, end string) (*monitor_dto.ChartAIOverview, error)
AITopN(ctx *gin.Context, start string, end string, limit string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error)
RestTopN(ctx *gin.Context, start string, end string, limit string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error)
}
type IMonitorConfigController interface {
+20 -211
View File
@@ -5,13 +5,9 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
"github.com/APIParkLab/APIPark/module/monitor"
monitor_dto "github.com/APIParkLab/APIPark/module/monitor/dto"
ai_provider_local "github.com/APIParkLab/APIPark/ai-provider/local"
subscribe_dto "github.com/APIParkLab/APIPark/module/subscribe/dto"
@@ -59,6 +55,10 @@ import (
"github.com/google/uuid"
)
//var (
// ollamaConfig = "{\n \"mirostat\": 0,\n \"mirostat_eta\": 0.1,\n \"mirostat_tau\": 5.0,\n \"num_ctx\": 4096,\n \"repeat_last_n\":64,\n \"repeat_penalty\": 1.1,\n \"temperature\": 0.7,\n \"seed\": 42,\n \"num_predict\": 42,\n \"top_k\": 40,\n \"top_p\": 0.9,\n \"min_p\": 0.5\n}\n"
//)
var (
_ IServiceController = (*imlServiceController)(nil)
@@ -66,210 +66,20 @@ var (
)
type imlServiceController struct {
module service.IServiceModule `autowired:""`
docModule service.IServiceDocModule `autowired:""`
subscribeModule subscribe.ISubscribeModule `autowired:""`
aiAPIModule ai_api.IAPIModule `autowired:""`
routerModule router.IRouterModule `autowired:""`
apiDocModule api_doc.IAPIDocModule `autowired:""`
providerModule ai.IProviderModule `autowired:""`
aiLocalModel ai_local.ILocalModelModule `autowired:""`
appModule service.IAppModule `autowired:""`
upstreamModule upstream.IUpstreamModule `autowired:""`
settingModule system.ISettingModule `autowired:""`
teamModule team.ITeamModule `autowired:""`
catalogueModule catalogue.ICatalogueModule `autowired:""`
monitorModule monitor.IMonitorStatisticModule `autowired:""`
monitorConfigModule monitor.IMonitorConfigModule `autowired:""`
transaction store.ITransaction `autowired:""`
}
func (i *imlServiceController) RestLogInfo(ctx *gin.Context, serviceId string, logId string) (*service_dto.RestLogInfo, error) {
return i.module.RestLogInfo(ctx, serviceId, logId)
}
func (i *imlServiceController) AILogInfo(ctx *gin.Context, serviceId string, logId string) (*service_dto.AILogInfo, error) {
return i.module.AILogInfo(ctx, serviceId, logId)
}
func (i *imlServiceController) AILogs(ctx *gin.Context, serviceId string, start string, end string, page string, size string) ([]*service_dto.AILogItem, int64, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, 0, err
}
if serviceId == "" {
return nil, 0, fmt.Errorf("service id is empty")
}
if page == "" {
page = "1"
}
if size == "" {
size = "20"
}
p, err := strconv.Atoi(page)
if err != nil {
return nil, 0, err
}
ps, err := strconv.Atoi(size)
if err != nil {
return nil, 0, err
}
return i.module.AILogs(ctx, serviceId, s, e, p, ps)
}
func (i *imlServiceController) RestLogs(ctx *gin.Context, serviceId string, start string, end string, page string, size string) ([]*service_dto.RestLogItem, int64, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, 0, err
}
if serviceId == "" {
return nil, 0, fmt.Errorf("service id is empty")
}
if page == "" {
page = "1"
}
if size == "" {
size = "20"
}
p, err := strconv.Atoi(page)
if err != nil {
return nil, 0, err
}
ps, err := strconv.Atoi(size)
if err != nil {
return nil, 0, err
}
return i.module.RestLogs(ctx, serviceId, s, e, p, ps)
}
func (i *imlServiceController) ServiceOverview(ctx *gin.Context, serviceId string) (*service_dto.Overview, error) {
o, err := i.module.ServiceOverview(ctx, serviceId)
if err != nil {
return nil, err
}
cfg, err := i.monitorConfigModule.GetMonitorConfig(ctx)
if err != nil {
return nil, err
}
if len(cfg.Config) < 1 {
return o, nil
}
statistics, err := i.monitorModule.ProviderStatistics(ctx, &monitor_dto.StatisticInput{
Services: []string{serviceId},
CommonInput: &monitor_dto.CommonInput{
Start: time.Now().Add(-24 * 30 * time.Hour).Unix(),
End: time.Now().Unix(),
},
})
if err != nil {
return nil, err
}
if len(statistics) < 1 {
return o, nil
}
o.InvokeNum = statistics[0].RequestTotal
return o, nil
}
func (i *imlServiceController) AIChartOverview(ctx *gin.Context, serviceId string, start string, end string) (*monitor_dto.ServiceChartAIOverview, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, err
}
if serviceId == "" {
return nil, fmt.Errorf("service is required")
}
so, err := i.module.ServiceOverview(ctx, serviceId)
if err != nil {
return nil, err
}
result := &monitor_dto.ServiceChartAIOverview{
EnableMCP: so.EnableMCP,
SubscriberNum: so.SubscriberNum,
APINum: so.APINum,
ServiceKind: so.ServiceKind,
}
cfg, err := i.monitorConfigModule.GetMonitorConfig(ctx)
if err != nil {
return nil, err
}
if len(cfg.Config) < 1 {
return result, nil
}
o, err := i.monitorModule.AIChartOverview(ctx, serviceId, s, e)
if err != nil {
return nil, err
}
result.AvailableMonitor = true
result.ChartAIOverview = o
return result, nil
}
func (i *imlServiceController) RestChartOverview(ctx *gin.Context, serviceId string, start string, end string) (*monitor_dto.ServiceChartRestOverview, error) {
s, e, err := formatTime(start, end)
if err != nil {
return nil, err
}
if serviceId == "" {
return nil, fmt.Errorf("service is required")
}
so, err := i.module.ServiceOverview(ctx, serviceId)
if err != nil {
return nil, err
}
result := &monitor_dto.ServiceChartRestOverview{
EnableMCP: so.EnableMCP,
SubscriberNum: so.SubscriberNum,
APINum: so.APINum,
ServiceKind: so.ServiceKind,
}
cfg, err := i.monitorConfigModule.GetMonitorConfig(ctx)
if err != nil {
return nil, err
}
if len(cfg.Config) < 1 {
return result, nil
}
o, err := i.monitorModule.RestChartOverview(ctx, serviceId, s, e)
if err != nil {
return nil, err
}
result.AvailableMonitor = true
result.ChartRestOverview = o
return result, nil
}
func formatTime(start string, end string) (int64, int64, error) {
s, err := strconv.ParseInt(start, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse start time %s error: %w", start, err)
}
e, err := strconv.ParseInt(end, 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("parse end time %s error: %w", end, err)
}
return s, e, nil
}
func (i *imlServiceController) Top10(ctx *gin.Context, serviceId string, start string, end string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error) {
if serviceId == "" {
return nil, nil, fmt.Errorf("serviceId is required")
}
info, err := i.module.Get(ctx, serviceId)
if err != nil {
return nil, nil, err
}
s, e, err := formatTime(start, end)
if err != nil {
return nil, nil, err
}
return i.monitorModule.Top(ctx, serviceId, s, e, 10, info.ServiceKind)
module service.IServiceModule `autowired:""`
docModule service.IServiceDocModule `autowired:""`
subscribeModule subscribe.ISubscribeModule `autowired:""`
aiAPIModule ai_api.IAPIModule `autowired:""`
routerModule router.IRouterModule `autowired:""`
apiDocModule api_doc.IAPIDocModule `autowired:""`
providerModule ai.IProviderModule `autowired:""`
aiLocalModel ai_local.ILocalModelModule `autowired:""`
appModule service.IAppModule `autowired:""`
upstreamModule upstream.IUpstreamModule `autowired:""`
settingModule system.ISettingModule `autowired:""`
teamModule team.ITeamModule `autowired:""`
catalogueModule catalogue.ICatalogueModule `autowired:""`
transaction store.ITransaction `autowired:""`
}
func (i *imlServiceController) QuickCreateAIService(ctx *gin.Context, input *service_dto.QuickCreateAIService) error {
@@ -732,9 +542,8 @@ type imlAppController struct {
authModule application_authorization.IAuthorizationModule `autowired:""`
}
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) SearchCanSubscribe(ctx *gin.Context, serviceId string) ([]*service_dto.SimpleAppItem, error) {
return i.module.SearchCanSubscribe(ctx, serviceId)
}
func (i *imlAppController) Search(ctx *gin.Context, teamId string, keyword string) ([]*service_dto.AppItem, error) {
+1 -16
View File
@@ -3,8 +3,6 @@ package service
import (
"reflect"
monitor_dto "github.com/APIParkLab/APIPark/module/monitor/dto"
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
"github.com/gin-gonic/gin"
@@ -34,19 +32,6 @@ type IServiceController interface {
Swagger(ctx *gin.Context)
ExportSwagger(ctx *gin.Context)
Top10(ctx *gin.Context, serviceId string, start string, end string) ([]*monitor_dto.TopN, []*monitor_dto.TopN, error)
AIChartOverview(ctx *gin.Context, serviceId string, start string, end string) (*monitor_dto.ServiceChartAIOverview, error)
RestChartOverview(ctx *gin.Context, serviceId string, start string, end string) (*monitor_dto.ServiceChartRestOverview, error)
ServiceOverview(ctx *gin.Context, serviceId string) (*service_dto.Overview, error)
AILogs(ctx *gin.Context, serviceId string, start string, end string, page string, size string) ([]*service_dto.AILogItem, int64, error)
RestLogs(ctx *gin.Context, serviceId string, start string, end string, page string, size string) ([]*service_dto.RestLogItem, int64, error)
RestLogInfo(ctx *gin.Context, serviceId string, logId string) (*service_dto.RestLogInfo, error)
AILogInfo(ctx *gin.Context, serviceId string, logId string) (*service_dto.AILogInfo, error)
}
type IAppController interface {
@@ -59,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, serviceId string) ([]*service_dto.SubscribeAppItem, error)
SearchCanSubscribe(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
GetApp(ctx *gin.Context, appId string) (*service_dto.App, error)
DeleteApp(ctx *gin.Context, appId string) error
}
-26
View File
@@ -1,26 +0,0 @@
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
@@ -1,45 +0,0 @@
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)
}
+1 -5
View File
@@ -47,11 +47,7 @@
"swagger-ui-react": "^5.17.14",
"tailwindcss": "^3.3.5",
"uuid": "^9.0.1",
"vite-tsconfig-paths": "^4.3.2",
"react-json-view": "^1.21.3",
"zod": "^3.23.8",
"@modelcontextprotocol/sdk": "^1.9.0",
"echarts-for-react": "^3.0.2"
"vite-tsconfig-paths": "^4.3.2"
},
"devDependencies": {
"@ant-design/cssinjs": "^1.18.2",
@@ -36,7 +36,7 @@ function BasicLayout({ project = 'core' }: { project: string }) {
const { state, accessData, checkPermission, accessInit, dispatch, resetAccess, getGlobalAccessData, menuList } =
useGlobalContext()
const [pathname, setPathname] = useState(currentUrl)
const mainPage = project === 'core' ? '/service/list' : '/portal/list'
const mainPage = project === 'core' ? '/service/list' : '/serviceHub/list'
const [menuItems, setMenuItems] = useState<MenuProps['items']>()
const pluginSlotHub = usePluginSlotHub()
@@ -1,25 +1,11 @@
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<{ handleBackCallback?: () => void }> = ({ handleBackCallback }) => {
const TopBreadcrumb: FC = () => {
const { breadcrumb } = useBreadcrumb()
useEffect(() => {}, [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>
)
return <Breadcrumb items={breadcrumb} />
}
export default TopBreadcrumb
@@ -4,12 +4,11 @@ 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; className?: string; color?: string }> = []
tagList?: Array<{ label: string | ReactNode }> = []
children: React.ReactNode
showBtn?: boolean = false
btnTitle?: string = ''
@@ -26,7 +25,6 @@ class InsidePageProps {
scrollInsidePage?: boolean = false
customPadding?: boolean
customBtn?: ReactNode
customBanner?: ReactNode
}
const InsidePage: FC<InsidePageProps> = ({
@@ -47,8 +45,7 @@ const InsidePage: FC<InsidePageProps> = ({
scrollPage = true,
scrollInsidePage = false,
customPadding = false,
customBtn,
customBanner
customBtn
}) => {
const navigate = useNavigate()
@@ -63,16 +60,18 @@ const InsidePage: FC<InsidePageProps> = ({
<div
className={`border-[0px] mr-PAGE_INSIDE_X ${showBorder ? 'border-solid border-b-[1px] border-BORDER' : ''} ${headerClassName}`}
>
{!pageTitle && !description && !backUrl && !customBtn && !customBanner ? (
{!pageTitle && !description && !backUrl && !customBtn ? (
<></>
) : customBanner ? (
<div className={customPadding ? '' : 'mb-[15px]'}>
{backUrl && <TopBreadcrumb handleBackCallback={() => goBack()} />}
{customBanner}
</div>
) : (
<div className={customPadding ? '' : 'mb-[30px]'}>
{backUrl && <TopBreadcrumb handleBackCallback={() => goBack()} />}
{backUrl && (
<div className="text-[18px] leading-[25px] mb-[12px]">
<Button type="text" onClick={goBack}>
<ArrowLeftOutlined className="max-h-[14px]" />
{$t('返回')}
</Button>
</div>
)}
<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>
@@ -80,7 +79,7 @@ const InsidePage: FC<InsidePageProps> = ({
tagList?.length > 0 &&
tagList?.map((tag) => {
return (
<Tag key={tag.label as string} bordered={false} color={tag.color} className={tag.className}>
<Tag key={tag.label as string} bordered={false}>
{tag.label}
</Tag>
)
@@ -58,7 +58,7 @@ interface PageListProps<T> extends ProTableProps<T, unknown>, RefAttributes<Acti
delayLoading?: boolean
noScroll?: boolean
/* 前端分页的表格,需要传入该字段以支持后端搜索 */
manualReloadTable?: () => void
manualReloadTable?: () => void,
customEmptyRender?: () => React.ReactNode
}
@@ -109,7 +109,6 @@ const PageList = <T extends Record<string, unknown>>(
const [allowTableClick, setAllowTableClick] = useState<boolean>(false)
const { accessData, checkPermission, accessInit, state } = useGlobalContext()
const [minTableWidth, setMinTableWidth] = useState<number>(0)
const [enableVirtual, setEnableVirtual] = useState(false)
useImperativeHandle(ref, () => actionRef.current!)
@@ -302,7 +301,7 @@ const PageList = <T extends Record<string, unknown>>(
<ProTable<T>
actionRef={actionRef}
columns={newColumns}
virtual={enableVirtual}
virtual
scroll={noScroll ? undefined : { x: tableWidth, y: tableHeight }}
size="middle"
rowSelection={rowSelection}
@@ -329,10 +328,6 @@ const PageList = <T extends Record<string, unknown>>(
}
: false
}}
postData={(data: any) => {
setEnableVirtual(!!data?.length)
return data
}}
showSorterTooltip={false}
columnsState={{ persistenceType: 'localStorage', persistenceKey: id }}
pagination={
@@ -27,7 +27,6 @@ type TimeRangeSelectorProps = {
bindRef?: any
hideBtns?: TimeRangeButton[]
defaultTimeButton?: TimeRangeButton
customClassNames?: string
}
const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
const {
@@ -39,8 +38,7 @@ const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
labelSize = 'default',
bindRef,
hideBtns = [],
defaultTimeButton = 'hour',
customClassNames = 'pt-btnybase'
defaultTimeButton = 'hour'
} = props
const [timeButton, setTimeButton] = useState(initialTimeButton || '')
const [datePickerValue, setDatePickerValue] = useState<RangeValue>(initialDatePickerValue || [null, null])
@@ -112,12 +110,8 @@ const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
return current && current.valueOf() > dayjs().startOf('day').valueOf()
}
useEffect(() => {
setTimeButton(initialTimeButton || '')
}, [initialTimeButton])
return (
<div className={`flex flex-nowrap items-center ${customClassNames} mr-btnybase`}>
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
{!hideTitle && <label className={`whitespace-nowrap `}>{$t('时间')}</label>}
<Radio.Group className="whitespace-nowrap" value={timeButton} onChange={handleRadioChange} buttonStyle="solid">
{hideBtns?.length && hideBtns.includes('hour') ? null : (
@@ -55,8 +55,6 @@ export const TranslateWord = () => {
{$t('打开 OpenAPI YAML 编辑器')}
{$t('无需审核:允许任何消费者调用该服务')}
{$t('人工审核:仅允许通过人工审核的消费者调用该服务')}
{$t('开启:AI Agent 等产品能够通过 MCP 方式调用服务')}
{$t('总览')}
{$t('永久')}
{$t('否')}
{$t('是')}
@@ -187,9 +185,6 @@ export const TranslateWord = () => {
{$t('调用地址')}
{$t('消费者 IP')}
{$t('鉴权名称')}
{$t('日志输出')}
{$t('响应时间')}
{$t('时间戳')}
</>
)
}
@@ -1,293 +0,0 @@
import { Avatar, Button, Card, Tag, Tooltip, App } from 'antd'
import { Icon } from '@iconify/react/dist/iconify.js'
import { $t } from '@common/locales/index.ts'
import { ApiOutlined } from '@ant-design/icons'
import { useEffect, useState } from 'react'
import { SERVICE_KIND_OPTIONS } from '@core/const/system/const'
import { IconButton } from '@common/components/postcat/api/IconButton'
import useCopyToClipboard from '@common/hooks/copy'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
export type ServiceBasicInfoType = {
id?: string
logo?: string
name: string
description: string
appNum: number
apiNum: number
serviceName: string
serviceDesc: string
invokeCount: number
catalogue: {
name: string
}
serviceKind: string
service_kind: string
enableMcp: boolean
enable_mcp: boolean
isReleased?: boolean
}
type ServiceInfoCardProps = {
actionSlot?: React.ReactNode
customClassName?: string
serviceId?: string
serviceBasicInfo?: ServiceBasicInfoType
teamId?: string
}
const ServiceInfoCard = ({
actionSlot,
customClassName,
serviceId,
serviceBasicInfo,
teamId
}: ServiceInfoCardProps) => {
/** 服务指标 */
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 { copyToClipboard } = useCopyToClipboard()
/** 弹窗组件 */
const { message } = App.useApp()
/** 获取服务信息 */
const { fetchData } = useFetch()
/** 服务信息 */
const [serviceOverview, setServiceOverview] = useState<ServiceBasicInfoType>()
/**
* 复制
* @param value
* @returns
*/
const handleCopy = async (value: string): Promise<void> => {
if (value) {
copyToClipboard(value)
message.success($t(RESPONSE_TIPS.copySuccess))
}
}
/** 获取服务信息 */
const getServiceOverview = () => {
fetchData<BasicResponse<{ overview: ServiceBasicInfoType }>>('service/overview/basic', {
method: 'GET',
eoParams: { service: serviceId, team: teamId },
eoTransformKeys: [
'api_num',
'enable_mcp',
'service_kind',
'subscriber_num',
'invoke_num',
'avaliable_monitor',
'is_released'
]
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const serviceOverview = {
...data.overview,
appNum: data.overview.subscriberNum,
invokeCount: data.overview.invokeNum,
serviceName: data.overview.name,
serviceDesc: data.overview.description
}
setServiceOverview(serviceOverview)
setServiceMetricsList(serviceOverview)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
/**
* 打开服务详情页面
*/
const openInPortal = () => {
window.open(`/portal/detail/${serviceOverview?.id}`, '_blank')
}
// 格式化调用次数,添加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 setServiceMetricsList = (serviceOverview: ServiceBasicInfoType) => {
// 设置服务指标数据
setServiceMetrics([
{
title: 'API 数量',
icon: <ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]" />,
value: serviceOverview.apiNum?.toString() || '0'
},
{
title: '接入消费者数量',
icon: <Icon icon="tabler:api-app" width="14" height="14" />,
value: serviceOverview.appNum?.toString() || '0'
},
{
title: '30天内调用次数',
icon: <Icon icon="iconoir:graph-up" width="14" height="14" />,
value: formatInvokeCount(serviceOverview.invokeCount ?? 0)
}
])
const serviceKind = serviceOverview?.serviceKind || serviceOverview?.service_kind
// 设置服务标签数据
const tags = [
{
color: '#7371fc1b',
textColor: 'text-theme',
title: serviceOverview?.catalogue?.name || '-',
content: serviceOverview?.catalogue?.name || '-'
},
{
color: `#${serviceKind === 'ai' ? 'EADEFF' : 'DEFFE7'}`,
textColor: 'text-[#000]',
title: serviceKind || '-',
content: SERVICE_KIND_OPTIONS.find((x) => x.value === serviceKind)?.label || '-'
}
]
// 如果启用了MCP,添加MCP标签
if (serviceOverview?.enableMcp) {
tags.push({
color: '#FFF0C1',
textColor: 'text-[#000]',
title: 'MCP',
content: 'MCP'
})
}
setServiceTags(tags)
}
useEffect(() => {
if (!serviceId && serviceBasicInfo) {
setServiceMetricsList(serviceBasicInfo)
setServiceOverview(serviceBasicInfo)
return
}
getServiceOverview()
}, [serviceId, serviceBasicInfo])
return (
<>
<Card
style={{
borderRadius: '10px',
background: 'linear-gradient(35deg, rgb(246, 246, 260) 0%, rgb(255, 255, 255) 40%)'
}}
className={`w-full ${customClassName}`}
classNames={{
body: `p-[15px] ${actionSlot ? 'h-[180px]' : 'max-h-[130px]'}`
}}
>
{serviceOverview && (
<>
<div className="service-info">
<div className="flex items-center">
<div>
<Avatar
shape="square"
size={50}
className={`rounded-[12px] border-none rounded-[12px] ${serviceOverview.logo ? 'bg-[linear-gradient(135deg,white,#f0f0f0)]' : 'bg-theme'}`}
src={
serviceOverview.logo ? (
<img
src={serviceOverview.logo}
alt="Logo"
style={{ maxWidth: '200px', width: '45px', height: '45px', objectFit: 'unset' }}
/>
) : undefined
}
icon={serviceOverview.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]`}
>
{serviceOverview.serviceName}
</p>
<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>
{serviceOverview.id && (
<>
<div className="absolute top-[14px] right-[20px]">
<span className="bg-white relative py-[2px] pl-[10px] pr-[30px] inline-block border-solid border-[1px] border-BORDER rounded-lg">
{$t('服务 ID')}{serviceOverview.id || '-'}
<IconButton
name="copy"
onClick={() => handleCopy(serviceOverview.id || '')}
sx={{
position: 'absolute',
top: '0px',
right: '5px',
color: '#999',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
</span>
<Tooltip title={serviceOverview.isReleased ? '' : $t('服务尚未发布')}>
<Button
disabled={!serviceOverview.isReleased}
className="ml-[10px] !max-h-[28px] rounded-[13px]"
type="primary"
onClick={() => openInPortal()}
>
{$t('跳转至详情页')}
</Button>
</Tooltip>
</div>
</>
)}
</div>
<span className="line-clamp-2 mt-[15px] text-[12px] text-[#666]" title={serviceOverview.serviceDesc}>
{serviceOverview.serviceDesc || $t('暂无服务描述')}
</span>
</div>
</>
)}
<div className="absolute bottom-[15px]">{actionSlot}</div>
</Card>
</>
)
}
export default ServiceInfoCard
@@ -234,16 +234,12 @@ 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}
@@ -1,431 +0,0 @@
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'));
} else {
// Browser globals
factory({}, root.echarts);
}
}(this, function (exports, echarts) {
var log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg);
}
};
if (!echarts) {
log('ECharts is not Loaded');
return;
}
echarts.registerTheme('apipark chart palette', {
"color": [
"#4429e6",
"#fd6280",
"#28dbe2",
"#ffc404",
"#b92325",
"#1b9f17",
"#fe8705",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#333333"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#333333"
},
"subtextStyle": {
"color": "#999999"
}
},
"line": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "2"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true
},
"radar": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "2"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderWidth": "2",
"barBorderColor": "rgba(255,255,255,0.3)"
}
},
"pie": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"scatter": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"parallel": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"sankey": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"funnel": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"gauge": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"candlestick": {
"itemStyle": {
"color": "#d87a80",
"color0": "#2ec7c9",
"borderColor": "#d87a80",
"borderColor0": "#2ec7c9",
"borderWidth": 1
}
},
"graph": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
},
"lineStyle": {
"width": 1,
"color": "#aaaaaa"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true,
"color": [
"#4429e6",
"#fd6280",
"#28dbe2",
"#ffc404",
"#b92325",
"#1b9f17",
"#fe8705",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#333333"
],
"label": {
"color": "#fefefe"
}
},
"map": {
"itemStyle": {
"areaColor": "#dddddd",
"borderColor": "#eeeeee",
"borderWidth": 0.5
},
"label": {
"color": "#d87a80"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(254,153,78,1)",
"borderColor": "#444",
"borderWidth": 1
},
"label": {
"color": "rgb(100,0,0)"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#dddddd",
"borderColor": "#eeeeee",
"borderWidth": 0.5
},
"label": {
"color": "#d87a80"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(254,153,78,1)",
"borderColor": "#444",
"borderWidth": 1
},
"label": {
"color": "rgb(100,0,0)"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333333"
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": true,
"areaStyle": {
"color": [
"#ffffff",
"rgba(0,0,0,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": true,
"areaStyle": {
"color": [
"#ffffff",
"rgba(0,0,0,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#000000"
},
"emphasis": {
"iconStyle": {
"borderColor": "#000000"
}
}
},
"legend": {
"textStyle": {
"color": "#333333"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "rgba(0,0,0,0.3)",
"width": "1"
},
"crossStyle": {
"color": "rgba(0,0,0,0.3)",
"width": "1"
}
}
},
"timeline": {
"lineStyle": {
"color": "#008acd",
"width": 1
},
"itemStyle": {
"color": "#008acd",
"borderWidth": 1
},
"controlStyle": {
"color": "#008acd",
"borderColor": "#008acd",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#2ec7c9",
"borderColor": "#2ec7c9"
},
"label": {
"color": "#008acd"
},
"emphasis": {
"itemStyle": {
"color": "#a9334c"
},
"controlStyle": {
"color": "#008acd",
"borderColor": "#008acd",
"borderWidth": 0.5
},
"label": {
"color": "#008acd"
}
}
},
"visualMap": {
"color": [
"#ffffff",
"#4429e6"
]
},
"dataZoom": {
"backgroundColor": "rgba(47,69,84,0)",
"dataBackgroundColor": "#efefff",
"fillerColor": "rgba(182,162,222,0.2)",
"handleColor": "#008acd",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"color": "#fefefe"
},
"emphasis": {
"label": {
"color": "#fefefe"
}
}
}
});
}));
@@ -1,409 +0,0 @@
{
"color": [
"#4429e6",
"#fd6280",
"#28dbe2",
"#ffc404",
"#b92325",
"#1b9f17",
"#fe8705",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#333333"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#333333"
},
"subtextStyle": {
"color": "#999999"
}
},
"line": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "2"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true
},
"radar": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "2"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderWidth": "2",
"barBorderColor": "rgba(255,255,255,0.3)"
}
},
"pie": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"scatter": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"parallel": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"sankey": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"funnel": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"gauge": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
}
},
"candlestick": {
"itemStyle": {
"color": "#d87a80",
"color0": "#2ec7c9",
"borderColor": "#d87a80",
"borderColor0": "#2ec7c9",
"borderWidth": 1
}
},
"graph": {
"itemStyle": {
"borderWidth": "2",
"borderColor": "rgba(255,255,255,0.3)"
},
"lineStyle": {
"width": 1,
"color": "#aaaaaa"
},
"symbolSize": "5",
"symbol": "circle",
"smooth": true,
"color": [
"#4429e6",
"#fd6280",
"#28dbe2",
"#ffc404",
"#b92325",
"#1b9f17",
"#fe8705",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#333333"
],
"label": {
"color": "#fefefe"
}
},
"map": {
"itemStyle": {
"areaColor": "#dddddd",
"borderColor": "#eeeeee",
"borderWidth": 0.5
},
"label": {
"color": "#d87a80"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(254,153,78,1)",
"borderColor": "#444",
"borderWidth": 1
},
"label": {
"color": "rgb(100,0,0)"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#dddddd",
"borderColor": "#eeeeee",
"borderWidth": 0.5
},
"label": {
"color": "#d87a80"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(254,153,78,1)",
"borderColor": "#444",
"borderWidth": 1
},
"label": {
"color": "rgb(100,0,0)"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333333"
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": true,
"areaStyle": {
"color": [
"#ffffff",
"rgba(0,0,0,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": true,
"areaStyle": {
"color": [
"#ffffff",
"rgba(0,0,0,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "rgba(0,0,0,0.1)"
}
},
"axisLabel": {
"show": true,
"color": "#333"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#000000"
},
"emphasis": {
"iconStyle": {
"borderColor": "#000000"
}
}
},
"legend": {
"textStyle": {
"color": "#333333"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "rgba(0,0,0,0.3)",
"width": "1"
},
"crossStyle": {
"color": "rgba(0,0,0,0.3)",
"width": "1"
}
}
},
"timeline": {
"lineStyle": {
"color": "#008acd",
"width": 1
},
"itemStyle": {
"color": "#008acd",
"borderWidth": 1
},
"controlStyle": {
"color": "#008acd",
"borderColor": "#008acd",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#2ec7c9",
"borderColor": "#2ec7c9"
},
"label": {
"color": "#008acd"
},
"emphasis": {
"itemStyle": {
"color": "#a9334c"
},
"controlStyle": {
"color": "#008acd",
"borderColor": "#008acd",
"borderWidth": 0.5
},
"label": {
"color": "#008acd"
}
}
},
"visualMap": {
"color": [
"#ffffff",
"#4429e6"
]
},
"dataZoom": {
"backgroundColor": "rgba(47,69,84,0)",
"dataBackgroundColor": "#efefff",
"fillerColor": "rgba(182,162,222,0.2)",
"handleColor": "#008acd",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"color": "#fefefe"
},
"emphasis": {
"label": {
"color": "#fefefe"
}
}
}
}
@@ -1,12 +0,0 @@
// 导入echarts核心模块
import * as echarts from 'echarts/core'
// 导入主题JSON
import themeJson from './apipark-chart-palette.json'
// 全局注册主题
export function registerApiparkTheme() {
echarts.registerTheme('apipark', themeJson)
}
// 导出主题名称,方便组件使用
export const THEME_NAME = 'apipark'
@@ -1,11 +0,0 @@
// 导入主题配置
import themeJson from './apipark-chart-palette.json'
// 导出主题配置
export const apiparkTheme = themeJson
// 导出颜色列表,方便单独使用
export const chartColors = themeJson.color
// 导出默认颜色
export const defaultColor = chartColors[0]
@@ -254,21 +254,6 @@ 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,7 +81,6 @@ export type MatchItem = {
export type EntityItem = {
id: string
name: string
isSubscribed: boolean
}
export type DynamicMenuItem = {
@@ -18,21 +18,5 @@ export const useBreadcrumb = () => {
export const BreadcrumbProvider = ({ children }: unknown) => {
const [breadcrumb, setBreadcrumb] = useState<BreadcrumbItemType[]>([])
return (
<BreadcrumbContext.Provider
value={{
setBreadcrumb: (newItems) => {
newItems.forEach((item) => {
item.title = (
<span className={`${item.onClick ? 'cursor-pointer hover:text-theme' : ''}`}>{item.title}</span>
)
})
setBreadcrumb(newItems)
},
breadcrumb
}}
>
{children}
</BreadcrumbContext.Provider>
)
return <BreadcrumbContext.Provider value={{ setBreadcrumb, breadcrumb }}>{children}</BreadcrumbContext.Provider>
}
@@ -87,8 +87,8 @@ const mockData = [
},
{
name: 'API 市场',
key: 'portal',
path: '/portal',
key: 'serviceHub',
path: '/serviceHub',
icon: 'ic:baseline-hub',
access: 'system.api_portal.api_portal.view'
},
@@ -99,31 +99,10 @@ const mockData = [
icon: 'ic:baseline-bar-chart',
children: [
{
name: '总览',
key: 'analyticsTotal',
path: '/analytics/total',
icon: 'material-symbols:bar-chart',
access: 'system.analysis.run_view.view'
},
{
name: '服务',
key: 'analyticsService',
path: '/analytics/service/list',
icon: 'ic:baseline-blinds-closed',
access: 'system.analysis.run_view.view'
},
{
name: '消费者',
key: 'analyticsConsumer',
path: '/analytics/consumer/list',
icon: 'ic:baseline-apps',
access: 'system.analysis.run_view.view'
},
{
name: 'API',
key: 'analyticsApi',
path: '/analytics/api/list',
icon: 'gravity-ui:plug-connection',
name: '运行视图',
key: 'analytics',
path: '/analytics',
icon: 'ic:baseline-bar-chart',
access: 'system.analysis.run_view.view'
}
],
@@ -217,20 +196,6 @@ 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',
@@ -253,7 +218,7 @@ const mockData = [
access: 'system.settings.ssl_certificate.view'
},
{
name: '日志输出',
name: '日志',
key: 'logsettings',
path: '/logsettings',
icon: 'ic:baseline-sticky-note-2',
@@ -112,10 +112,10 @@ const mockData = {
},
{
driver: 'apipark.builtIn.component',
name: 'portal',
name: 'serviceHub',
router: [
{
path: 'portal',
path: 'serviceHub',
type: 'normal'
}
]
@@ -220,26 +220,6 @@ 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,6 +16,7 @@
"添加(0)": "Ka7aaaeb",
"请输入Key": "Kaff78ecf",
"请输入Value": "K65d46535",
"返回": "Kc14b2ea3",
"ID": "K11d3633a",
"名称": "Kbff43de3",
"Driver": "K16ca79ef",
@@ -54,10 +55,6 @@
"上游列表": "K54e44357",
"备注": "Kb8e8e6f5",
"上线情况": "K7e52ffa3",
"服务 ID": "K1e84ad04",
"服务尚未发布": "Ke1e649cb",
"跳转至详情页": "K2e683a7d",
"暂无服务描述": "Ka4b45550",
"申请原因": "K1ab0ae5b",
"审核意见": "K53c00c3c",
"暂无(0)权限,请联系管理员分配。": "Kfd50704d",
@@ -117,8 +114,6 @@
"打开 OpenAPI YAML 编辑器": "Kdac8ce7e",
"无需审核:允许任何消费者调用该服务": "K1fc2cc28",
"人工审核:仅允许通过人工审核的消费者调用该服务": "K8dabb98e",
"开启:AI Agent 等产品能够通过 MCP 方式调用服务": "Ke959f135",
"总览": "Kaf9e8011",
"永久": "Kbfe02d7f",
"否": "K1e9c479e",
"是": "Kaddfcb6b",
@@ -246,9 +241,6 @@
"调用地址": "K2f5fdf5e",
"消费者 IP": "K1bc5e0a3",
"鉴权名称": "K6f39ea21",
"日志输出": "K3c722abd",
"响应时间": "K1be06929",
"时间戳": "K5e51f5d",
"暂无操作权限,请联系管理员分配。": "K23fda291",
"微信小程序": "K4618cb0a",
"获取文件,需填路径": "Ka854f511",
@@ -368,6 +360,7 @@
"管理": "K5974bf24",
"调用拓扑图": "K3fa5c4c3",
"设置": "Kb5c7b82d",
"服务 ID": "K1e84ad04",
"新增订阅方": "K39ab0358",
"手动添加": "K18307d56",
"订阅申请": "K705fe9f5",
@@ -382,6 +375,7 @@
"拦截接口": "Kee4139c2",
"开启拦截后,网关会拦截所有该路径的请求。": "K3e38ea",
"模型配置": "K8a35059b",
"路由": "Kf9dcef3a",
"添加路由": "K6134bbe8",
"输入 URL 查找路由": "Kf85b83a0",
"线上模型": "K84b2cf2d",
@@ -420,16 +414,17 @@
"启用": "K52c8a730",
"Ollama 地址": "K6b99dce8",
"输入例如:https://www.apipark.com": "K8d4f5b44",
"自定义(空模板)": "K24f6a5b4",
"自定义": "K8929cbb1",
"模型名称": "K1fd51aaa",
"访问配置": "Kd6285399",
"模型参数模板": "K7eb03edd",
"模型参数": "K49b434e9",
"载入预置模板": "Kea608112",
"供应商名称": "K16ef56b1",
"注意:": "K484de451",
"仅支持使用 OpenAI 输入输出格式和认证方法(APIKey)的供应商。如果不满足此条件,创建后自定义供应商将不可用。": "Kbd80dde0",
"从 (0) 获取 API KEY": "Kb3e34847",
"该模型为官方模型,不可编辑": "Kcb6a1c57",
"存在使用当前模型的接口,需要先解绑后才能编辑": "Kf9300eb4",
"该模型为官方模型,不可删除": "K8af71816",
"存在使用当前模型的接口,需要先解绑后才能删除": "Kb8ad0af5",
"模型值": "K73cb9ff1",
@@ -455,7 +450,6 @@
"Models": "Ke37a353f",
"Keys": "K14bcebd2",
"添加供应商": "Kd87397b0",
"编辑供应商( (0) )": "Kee7de862",
"编辑供应商": "K5bcf8c48",
"(0) 模型": "Kf7a916be",
"待审核": "K35612f29",
@@ -463,7 +457,7 @@
"发布申请": "K56b4254f",
"API 调用地址": "Kea2f9279",
"API base URL 一般设置为API 网关的外部网络访问地址,或者是API网关绑定的域名。": "K7fc496a1",
"OpenAPI & MCP 调用地址": "Ka7ca8fde",
"集成地址": "K508d8bf4",
"与外部平台集成时,获取 API 市场中文档信息的域名": "K67f4e9bb",
"常规设置": "K8ab0fc95",
"API 请求设置": "Kb66fec9d",
@@ -475,7 +469,6 @@
"分类名称": "Ke595a20a",
"父分类 ID": "K9679728f",
"子分类名称": "K9b2d08fd",
"暂无权限": "Kce2fcdbf",
"添加 Rest 服务": "K2c93168c",
"导入OpenAPI文档,将现有系统的API发布到APIPark。": "K39a8d392",
"添加在线 AI API": "K68932d54",
@@ -556,19 +549,8 @@
"访客模式": "K192b3e38",
"您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。": "K91aa4801",
"Version (0)-(1)": "K480045ce",
"日志输出设置": "K74a5fbc0",
"提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K2724314b",
"日志配置": "Kadee8e49",
"MCP 配置": "K6e9c928f",
"Open API 文档": "Kb6d0eb39",
"AI 代理集成": "Ke6908f16",
"请先订阅该服务": "K71ed51fa",
"申请": "K4aa9ed2c",
"选择 API Key": "K1bec8cbe",
"新增 API Key": "Kb0e0aeda",
"API 密钥可用于调用系统级 Open API 和 MCP。": "K9d81999c",
"MCP 服务": "Kf106bc62",
"MCP Service 充当 AI 模型与 API 之间的桥梁,允许智能助手(如 Claude)动态发现和调用 Gateway 上的 API,无需繁琐的手动配置或自定义集成。": "K7c2bfeff",
"提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K2724314b",
"部门名称": "K33c76dbc",
"父部门 ID": "K84829ca9",
"子部门名称": "K4d7fc74b",
@@ -625,7 +607,7 @@
"数据源": "K8fa58214",
"设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。": "Kdbafd6f9",
"统计图表": "K1358acf",
"请求日志": "Kc8bf447",
"数据日志": "K17dc3a62",
"地址(IP:端口)": "K62dabdf6",
"组织(Organization": "K2db12335",
"添加策略": "K34d0d409",
@@ -659,33 +641,10 @@
"支持对系统全局进行统一的策略配置,从而简化管理并确保一致性。全局策略的优先级比服务策略略低。": "Kc975cd5a",
"资源配置": "K8e7a0f80",
"角色": "Kf644225f",
"角色配置": "Kc9f2249c",
"设置角色的权限范围。": "K95c3fd8b",
"系统级别角色": "K138facd3",
"添加角色": "K6eac768d",
"团队级别角色": "Kb9c2cf02",
"API / Tools": "K9d526cac",
"消费者": "K7acfcfad",
"HTTP 状态": "Kc68ba0f4",
"IP": "Kb09b747",
"通过系统级别的 API Key 来调用": "K2eacb44f",
"日志详情": "K764bca7c",
"暂无数据": "Kf8525cf2",
"输入 Token": "K33bc1ad1",
"输出 Token": "Ke00ff18b",
"订阅数量": "Ke04bc00d",
"已开启": "K1b97ae0a",
"开启 MCP": "K19ec733b",
"API 使用排名": "Kbee2340",
"消费者使用排名": "Kf6af1f40",
"请求次数": "K9d3f2d9d",
"网络流量": "Ke2241377",
"平均响应时间": "K7c8d5c23",
"平均每消费者的请求次数": "K6c267c7b",
"平均每消费者的网络流量": "K133d4291",
"Token 消耗": "K37c5f1d0",
"平均 Token 消耗": "K10a8bee3",
"平均每消费者的 Token 消耗": "Kb98264d4",
"单位:ms,最小值:1": "K2a16c93b",
"API 路由设置": "Ka945cfb1",
"API 基础信息": "K2e050340",
@@ -703,13 +662,9 @@
"停止": "K24540de",
"继续等待": "Kd85b3f64",
"只允许上传PNG、JPG或SVG格式的图片": "Ka9c08390",
"关闭 MCP": "K30595880",
"关闭后将无法通过MCP方式调用服务": "Kc081047c",
"了解": "Ka73a5801",
"服务名称": "K413b9869",
"服务类型": "K9919285b",
"REST 服务": "K62840d62",
"MCP": "K373c8ab3",
"默认 AI 供应商": "Kcef64f4d",
"创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API": "K300c89d4",
"未配置任何 AI 模型供应商,": "Kcab588a9",
@@ -768,6 +723,7 @@
"退出全屏": "Kaf70c3b",
"(0)调用详情": "Kd22841a4",
"消费者调用统计": "K61cca533",
"消费者": "K7acfcfad",
"请选择消费者": "Kdfff59d4",
"调用趋势": "K8c7f2d2e",
"(0)-(1)调用趋势": "K657c3452",
@@ -808,13 +764,14 @@
"配置集群信息": "Ke5ed9810",
"监控设置": "K1a132228",
"配置监控信息": "K6af08c3c",
"加载数据失败,请重试": "K6c2d93b6",
"监控总览": "K4a1a14",
"服务被调用统计": "K69741ea7",
"API 调用统计": "K9c8d9933",
"亿": "K145e4941",
"万": "Ke6a935d",
"搜索分类或标签": "Kd59290a2",
"暂无API数据": "K6b75bdbc",
"搜索或选择消费者": "Kb684c806",
"该消费者已订阅": "K5611e01e",
"申请理由": "K4b15d6f5",
"支持把当前服务对接主流的 AI Agent平台,实现在 Agent 平台上快速、安全和合规地使用企业开放的 API 能力。": "K2ec0fa56",
"可按以下步骤进行对接:": "K35f23b64",
@@ -854,7 +811,6 @@
"添加授权": "Kd23d1716",
"到期时间": "Kfa920c0",
"订阅的服务": "Kcce1af60",
"返回": "Kc14b2ea3",
"审核详情": "Kfefa9b58",
"取消订阅": "K3118fdb0",
"请确认是否取消订阅?": "Ked811bb1",
@@ -867,20 +823,22 @@
"创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务": "K5c4e2865",
"订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f",
"输入名称、ID 查找消费者": "K3a6f905d",
"API 门户": "Kc84dbd1a",
"服务市场": "K370a3eb2",
"服务详情": "Kf7ec36d",
"申请服务": "K58ca9485",
"介绍": "K59cdbec3",
"Base URL": "Kc29dabf2",
"申请": "K4aa9ed2c",
"服务信息": "K6c060779",
"接入消费者": "Kba74f26d",
"供应方": "Kb97544cb",
"分类": "Kb32f0afe",
"版本": "K81634069",
"更新时间": "Keefda53d",
"介绍": "K59cdbec3",
"API": "K3ba29a85",
"无标签": "K96a2f1c8",
"分类": "Kb32f0afe",
"服务市场": "K370a3eb2",
"暂无服务描述": "Ka4b45550",
"API 数量": "K72b0c0b3",
"接入消费者数量": "K70b79760",
"30天内调用次数": "K3d52b756",
"关联标签": "K96059c69",
"更新者": "K8b7c2592",
"添加 Open Api": "K32263abd",
@@ -4,7 +4,7 @@
"Kb58e0c3f": "Service",
"Kc9e489f5": "Team",
"K61c89f5f": "API Portal",
"K16d71239": "Analytics",
"K16d71239": "Analysis",
"K714c192d": "Call Statistics",
"Kd57dfe97": "Topology",
"K3fe97dcc": "System Settings",
@@ -186,7 +186,7 @@
"K617f34f1": "Updated By",
"K6ebca204": "Update Time",
"Kabfe9512": "Save",
"K51d1eb5d": "API Routes",
"K51d1eb5d": "API",
"Ka2b6d281": "API Docs",
"Kdefa9caa": "Usage Instructions",
"K36856e71": "Publish",
@@ -210,7 +210,7 @@
"K469e475a": "Max Retry Times",
"K8a35059b": "Model Settings",
"Kf9dcef3a": "API",
"K6134bbe8": "Add API Route",
"K6134bbe8": "Add API",
"Kf85b83a0": "Enter URL to Search",
"Kcf9f90b8": "Model Provider",
"Kfede1c7c": "Model",
@@ -498,7 +498,7 @@
"K370a3eb2": "Service Marketplace",
"Kf7ec36d": "Service Details",
"K58ca9485": "Subscribe",
"K59cdbec3": "Readme",
"K59cdbec3": "Intro",
"K4aa9ed2c": "Subscribe",
"K6c060779": "Service Information",
"Kb97544cb": "Provider",
@@ -898,79 +898,5 @@
"Kce2fcdbf": "No Permission",
"K24f6a5b4": "Custom (Empty Template)",
"Kea608112": "Load Preset Template",
"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",
"Ke1e649cb": "Service not released",
"K2e683a7d": "Open in Portal",
"Ke04bc00d": "Subscribers",
"K1b97ae0a": "Enabled",
"K19ec733b": "Enable MCP",
"Kbee2340": "Top API",
"Kf6af1f40": "Top Consumer",
"K318a7519": "Requests",
"K9ef68e3f": "Token",
"Kfb14ccb0": "Models",
"K10a8bee3": "Avg Token per Second",
"K2727b76b": "Avg Requests per Subscriber",
"K4c7a6704": "Avg Token per Subscriber",
"K53eb7414": "Traffic",
"K7c8d5c23": "Avg Response Time",
"Kf9eb702": "QRS",
"K7f0aa740": "Avg Traffic per Subscriber",
"K9d526cac": "API / Tools",
"Kc68ba0f4": "HTTP Status",
"Kb09b747": "IP",
"K2eacb44f": "Request the API using a system-level API Key",
"K764bca7c": "Log Detail",
"K6c016898": "Avg Token per Second",
"K652843b0": "Avg Requests per Subscriber",
"Kdbf831a0": "Avg Token per Subscriber",
"K8158a6e4": "Avg Traffic per Subscriber",
"K6b882d4a": "Avg Token per Subscriber",
"K6c2d93b6": "Failed to load data, please try again",
"Kf5eeb9c5": "Avg Token per Subscriber",
"K1639a17a": "API Routes Docs",
"K33bc1ad1": "Input Token",
"Ke00ff18b": "Output Token",
"K81140e5b": "Total Token",
"K3c722abd": "Log Output",
"K74a5fbc0": "Log Output Settings",
"Kc8bf447": "Request Log",
"Kf8525cf2": "No Data",
"K1be06929": "Response Time",
"K5e51f5d": "Timestamp",
"K9d3f2d9d": "Requests",
"Ke2241377": "Traffic",
"K6c267c7b": "Avg Requests per Subscriber",
"K133d4291": "Avg Traffic per Subscriber",
"K37c5f1d0": "Token",
"Kb98264d4": "Avg Token per Subscriber"
"Kee7de862": "Edit Provider( (0) )"
}
@@ -189,7 +189,7 @@
"K617f34f1": "更新者",
"K6ebca204": "更新日時",
"Kabfe9512": "保存",
"K51d1eb5d": "APIルート",
"K51d1eb5d": "API",
"Ka2b6d281": "API ドキュメント",
"Kdefa9caa": "説明ドキュメント",
"K36856e71": "公開",
@@ -213,7 +213,7 @@
"K469e475a": "リトライ回数",
"K8a35059b": "モデル設定",
"Kf9dcef3a": "API",
"K6134bbe8": "APIルートを追加する",
"K6134bbe8": "API を追加",
"Kf85b83a0": "URL を入力して検索",
"Kcf9f90b8": "モデルプロバイダー",
"Kfede1c7c": "モデル",
@@ -920,79 +920,5 @@
"Kce2fcdbf": "権限がありません",
"K24f6a5b4": "カスタム(空のテンプレート)",
"Kea608112": "プリセットテンプレートを読み込む",
"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": "概要",
"Ke1e649cb": "サービスはまだ公開されていません",
"K2e683a7d": "詳細ページへ移動",
"Ke04bc00d": "サブスクリプション数",
"K1b97ae0a": "有効",
"K19ec733b": "MCP を有効にする",
"Kbee2340": "API 使用ランキング",
"Kf6af1f40": "コンシューマー使用ランキング",
"K318a7519": "リクエスト数",
"K9ef68e3f": "トークン",
"Kfb14ccb0": "モデル使用量",
"K10a8bee3": "平均トークン消費量",
"K2727b76b": "ユーザーあたり平均リクエスト数",
"K4c7a6704": "ユーザーあたり平均トークン消費量",
"K53eb7414": "トラフィック",
"K7c8d5c23": "平均応答時間",
"Kf9eb702": "毎秒リクエスト数",
"K7f0aa740": "ユーザーあたり平均トラフィック",
"K9d526cac": "API / ツール",
"Kc68ba0f4": "HTTP ステータス",
"Kb09b747": "IP",
"K2eacb44f": "システムレベルの API Key で呼び出し",
"K764bca7c": "ログ詳細",
"K6c016898": "平均トークン/s 統計",
"K652843b0": "平均リクエスト数",
"Kdbf831a0": "平均トークン/加入者 統計",
"K8158a6e4": "平均トラフィック",
"K6b882d4a": "平均トークン/加入者",
"K6c2d93b6": "データの読み込みに失敗しました。もう一度お試しください",
"Kf5eeb9c5": "平均トークン/加入者 統計",
"K1639a17a": "APIルートのドキュメント",
"K33bc1ad1": "入力トークン",
"Ke00ff18b": "出力トークン",
"K81140e5b": "合計トークン",
"K3c722abd": "ログ出力",
"K74a5fbc0": "ログ出力設定",
"Kc8bf447": "リクエストログ",
"Kf8525cf2": "データがありません",
"K1be06929": "応答時間",
"K5e51f5d": "タイムスタンプ",
"K9d3f2d9d": "リクエスト数",
"Ke2241377": "ネットワークトラフィック",
"K6c267c7b": "消費者あたりの平均リクエスト数",
"K133d4291": "消費者あたりの平均ネットワークトラフィック",
"K37c5f1d0": "トークン消費量",
"Kb98264d4": "消費者あたりの平均トークン消費量"
"Kee7de862": "サプライヤーを編集( (0) )"
}
@@ -1 +1,70 @@
{}
{
"K630c9e6d": "APIPark",
"Ka3e9f580": "发布名称",
"Kb2480682": "策略列表",
"K76036e25": "HTTP 请求头",
"K44607e3f": "全等匹配",
"Kc287500a": "前缀匹配",
"Kfc0b1147": "后缀匹配",
"Ka4a92043": "子串匹配",
"K30b2e44f": "非等匹配",
"Kb1587991": "空值匹配",
"K1e97dbd8": "存在匹配",
"Kc8ee3e62": "不存在匹配",
"K87c5a801": "区分大小写的正则匹配",
"K95f062f1": "不区分大小写的正则匹配",
"Kfbd230a5": "任意匹配",
"Kd85208a3": "驳回",
"Kad6aa439": "已订阅",
"K9a68443b": "取消申请",
"Kaeba0229": "透传客户端请求 Host",
"K6d7e2fd0": "使用上游服务 Host",
"K31332633": "重写 Host",
"K2c2bc64f": "动态服务发现",
"K78b1ca25": "地址",
"K1644b775": "新增",
"Kec91f0db": "申请方消费者",
"K118d8d74": "数据格式",
"Kfe7c7d2d": "关键字",
"K2f57a694": "正则表达式",
"K8953e0a6": "手机号",
"K6f86a038": "身份证号",
"K7954e7c8": "银行卡号",
"K320fdb17": "金额",
"K7867acda": "日期",
"K7d327ae8": "局部显示",
"Kfbf38e3c": "局部遮蔽",
"Kd8c1fbb0": "截取",
"K89829921": "替换",
"K480a7165": "乱序",
"Kea0d69df": "随机字符串",
"Ke7c84d1d": "自定义字符串",
"K49731763": "请输入IP地址或CIDR范围,每条以换行分割",
"K3a34d49b": "待更新",
"Kd2850420": "待删除",
"K83237c89": "输入的IP或CIDR不符合格式",
"K5ae2c87a": "请正确输入路径,如/usr/*或*/usr/*",
"K508d8bf4": "集成地址",
"K67f4e9bb": "与外部平台集成时,获取 API 市场中文档信息的域名",
"Kc82b8374": "编辑策略",
"K4b34a5e5": "策略类型",
"K57f0fee8": "匹配条件",
"K10650c58": "数据脱敏规则",
"K1b34a9ab": "配置脱敏规则",
"K26d22405": "匹配值",
"K1546e1fe": "脱敏类型",
"K9b9b0629": "起始位置",
"K52c84fe1": "长度",
"Kde84409c": "替换类型",
"K338653b4": "替换值",
"Kbaeed3b7": "JSON Path",
"K4cd91d61": "脱敏规则",
"K8dcad979": "自定义字符串; 值:",
"K82e3f7b7": "起始位置:(0)位;长度:(1)位",
"K49dfc123": "已选择(0)项(1)数据",
"K8457ea34": "所有(0)",
"K7ca9a795": "属性名称",
"Kc4391744": "属性值",
"K678e13fc": "配置(0)",
"Kf5fd27ed": "输入名称查找用户"
}
@@ -189,7 +189,7 @@
"K617f34f1": "更新者",
"K6ebca204": "更新时间",
"Kabfe9512": "保存",
"K51d1eb5d": "API 路由",
"K51d1eb5d": "API",
"Ka2b6d281": "API 文档",
"Kdefa9caa": "说明文档",
"K36856e71": "发布",
@@ -213,7 +213,7 @@
"K469e475a": "最大重试次数",
"K8a35059b": "模型设置",
"Kf9dcef3a": "API",
"K6134bbe8": "添加 API 路由",
"K6134bbe8": "添加 API",
"Kf85b83a0": "输入 URL 查找",
"Kcf9f90b8": "模型供应商",
"Kfede1c7c": "模型",
@@ -851,77 +851,5 @@
"Kce2fcdbf": "暂无权限",
"K24f6a5b4": "自定义(空模板)",
"Kea608112": "载入预置模板",
"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": "总览",
"Ke1e649cb": "服务尚未发布",
"K2e683a7d": "跳转至详情页",
"Ke04bc00d": "订阅方数量",
"K1b97ae0a": "已开启",
"K19ec733b": "开启 MCP",
"Kbee2340": "API 使用排名",
"Kf6af1f40": "消费者使用排名",
"K318a7519": "请求数",
"K9ef68e3f": "Token",
"Kfb14ccb0": "模型使用量",
"K10a8bee3": "平均 Token 消耗",
"K2727b76b": "人均请求数",
"K4c7a6704": "人均 Token 消耗",
"K53eb7414": "流量",
"K7c8d5c23": "平均响应时间",
"Kf9eb702": "每秒请求数量",
"K7f0aa740": "人均流量",
"K9d526cac": "API / Tools",
"Kc68ba0f4": "HTTP 状态",
"Kb09b747": "IP",
"K2eacb44f": "通过系统级别的 API Key 来调用",
"K764bca7c": "日志详情",
"K6c016898": "平均 Token/s 统计",
"K652843b0": "平均请求数",
"K8158a6e4": "平均流量",
"K6c2d93b6": "加载数据失败,请重试",
"Kf5eeb9c5": "平均 Token/订阅者统计",
"K1639a17a": "API 路由文档",
"K33bc1ad1": "输入 Token",
"Ke00ff18b": "输出 Token",
"K81140e5b": "总 Token",
"K3c722abd": "日志输出",
"K74a5fbc0": "日志输出设置",
"Kc8bf447": "请求日志",
"Kf8525cf2": "暂无数据",
"K1be06929": "响应时间",
"K5e51f5d": "时间",
"K9d3f2d9d": "请求次数",
"Ke2241377": "网络流量",
"K6c267c7b": "平均每消费者的请求次数",
"K133d4291": "平均每消费者的网络流量",
"K37c5f1d0": "Token 消耗",
"Kb98264d4": "平均每消费者的 Token 消耗"
"Kee7de862": "编辑供应商( (0) )"
}
@@ -189,7 +189,7 @@
"K617f34f1": "更新者",
"K6ebca204": "更新時間",
"Kabfe9512": "保存",
"K51d1eb5d": "API 路由",
"K51d1eb5d": "API",
"Ka2b6d281": "API 文檔",
"Kdefa9caa": "說明文檔",
"K36856e71": "發布",
@@ -213,7 +213,7 @@
"K469e475a": "最大重試次數",
"K8a35059b": "模型設置",
"Kf9dcef3a": "API",
"K6134bbe8": "添加 API 路由",
"K6134bbe8": "添加 API",
"Kf85b83a0": "輸入 URL 查找",
"Kcf9f90b8": "模型供應商",
"Kfede1c7c": "模型",
@@ -920,79 +920,5 @@
"Kce2fcdbf": "暫無權限",
"K24f6a5b4": "自訂(空模板)",
"Kea608112": "載入預設模板",
"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": "總覽",
"Ke1e649cb": "服務尚未發布",
"K2e683a7d": "跳轉至詳情頁",
"Ke04bc00d": "訂閱數量",
"K1b97ae0a": "已開啟",
"K19ec733b": "開啟 MCP",
"Kbee2340": "API 使用排名",
"Kf6af1f40": "消費者使用排名",
"K318a7519": "請求數",
"K9ef68e3f": "Token",
"Kfb14ccb0": "模型使用量",
"K10a8bee3": "平均 Token 消耗",
"K2727b76b": "人均請求數",
"K4c7a6704": "人均 Token 消耗",
"K53eb7414": "流量",
"K7c8d5c23": "平均回應時間",
"Kf9eb702": "每秒請求數量",
"K7f0aa740": "人均流量",
"K9d526cac": "API / 工具",
"Kc68ba0f4": "HTTP 狀態",
"Kb09b747": "IP",
"K2eacb44f": "透過系統級 API Key 調用",
"K764bca7c": "日誌詳情",
"K6c016898": "平均 Token/s 統計",
"K652843b0": "平均請求數",
"Kdbf831a0": "每位訂閱者平均 Token 統計",
"K8158a6e4": "平均流量",
"K6b882d4a": "每位訂閱者平均 Token",
"K6c2d93b6": "載入資料失敗,請重試",
"Kf5eeb9c5": "每位訂閱者平均 Token 統計",
"K1639a17a": "API 路由文件",
"K33bc1ad1": "輸入 Token",
"Ke00ff18b": "輸出 Token",
"K81140e5b": "總計 Token",
"K3c722abd": "日誌輸出",
"K74a5fbc0": "日誌輸出設定",
"Kc8bf447": "請求日誌",
"Kf8525cf2": "暫無資料",
"K1be06929": "回應時間",
"K5e51f5d": "時間",
"K9d3f2d9d": "請求次數",
"Ke2241377": "網路流量",
"K6c267c7b": "平均每位使用者的請求次數",
"K133d4291": "平均每位使用者的網路流量",
"K37c5f1d0": "Token 消耗",
"Kb98264d4": "平均每位使用者的 Token 消耗"
"Kee7de862": "編輯供應商( (0) )"
}
-4
View File
@@ -6,7 +6,6 @@ import { PluginEventHubProvider } from '@common/contexts/PluginEventHubContext'
import { PluginSlotHubProvider } from '@common/contexts/PluginSlotHubContext'
import useInitializeMonaco from '@common/hooks/useInitializeMonaco'
import { $t } from '@common/locales'
import { registerApiparkTheme } from '@common/const/charts/initChartTheme'
import RenderRoutes from '@core/components/aoplatform/RenderRoutes'
import { App as AppAntd, ConfigProvider } from 'antd'
import { useMemo } from 'react'
@@ -131,9 +130,6 @@ const antdComponentThemeToken = {
}
}
// 注册 ECharts 主题
registerApiparkTheme()
function App() {
const { locale } = useLocaleContext()
useInitializeMonaco()
@@ -6,18 +6,17 @@ import { AiServiceRouterTableListItem, VariableItems } from './type'
import { PageProColumns } from '@common/components/aoplatform/PageList'
export const AI_SERVICE_ROUTER_TABLE_COLUMNS: PageProColumns<AiServiceRouterTableListItem>[] = [
{
title: '名称',
dataIndex: 'name',
width: 200,
ellipsis: true
},
{
title: 'URL',
dataIndex: 'requestPath',
ellipsis: true,
width: 200
},
{
title: '名称',
dataIndex: 'name',
ellipsis: true
},
{
title: '模型',
dataIndex: ['model', 'name'],
@@ -15,13 +15,12 @@ export type AiServiceConfigFieldType = {
logoFile?:UploadFile;
tags?:Array<string>;
description?: string;
team?:EntityItem;
team?:string;
master?:string;
serviceType?:'public'|'inner';
catalogue?:string | string[];
approvalType?:string;
providerType?:string
enable_mcp?: boolean
};
export type AiServiceSubServiceTableListItem = {
+3 -47
View File
@@ -96,20 +96,6 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
key: 'restServiceInside',
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsidePage.tsx')),
children: [
{
path: 'overview',
key: 'restServiceInsideOverview',
lazy: lazy(
() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceOverview/RestServiceContainer')
)
},
{
path: 'logs',
key: 'restServiceInsideLogs',
lazy: lazy(
() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceLogs/RestServiceLogsContainer')
)
},
{
path: 'api',
key: 'restServiceInsideApi',
@@ -282,20 +268,6 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsidePage.tsx')
),
children: [
{
path: 'overview',
key: 'aiServiceInsideOverview',
lazy: lazy(
() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceOverview/AiServiceContainer')
)
},
{
path: 'logs',
key: 'aiServiceInsideLogs',
lazy: lazy(
() => import(/* webpackChunkName: "[request]" */ '@core/pages/serviceLogs/AiServiceLogsContainer')
)
},
{
path: 'api',
key: 'aiServiceInsideApi',
@@ -535,7 +507,7 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
],
[
'portal',
'serviceHub',
{
type: 'module',
component: <Outlet />,
@@ -702,12 +674,12 @@ export const routerMap: Map<string, RouterMapConfig> = new Map([
children: [
{
path: 'total',
key: 'analyticsTotal',
key: 'analytics2',
lazy: lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardTotal.tsx'))
},
{
path: ':dashboardType',
key: 'analyticsOther',
key: 'analytics3',
component: <Outlet />,
children: [
{
@@ -828,22 +800,6 @@ 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',
{
@@ -123,7 +123,6 @@ export type PartitionDataLogHeaderListFieldType = {
export type PartitionDataLogConfigFieldType = {
headers: PartitionDataLogHeaderListFieldType[]
url: string
driver?: string
}
export const PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS: PageProColumns<PartitionDataLogConfigFieldType & { _id: string }>[] = [
@@ -13,7 +13,6 @@ import {
} from './type'
import { PageProColumns } from '@common/components/aoplatform/PageList'
import { LogItem } from '@core/pages/serviceLogs/ServiceLogs'
export enum SubscribeEnum {
Rejected = 0,
@@ -86,7 +85,7 @@ export const SYSTEM_TABLE_COLUMNS: PageProColumns<SystemTableListItem>[] = [
title: '服务名称',
dataIndex: 'name',
ellipsis: true,
width: 220,
width: 160,
fixed: 'left',
sorter: (a, b) => {
return a.name.localeCompare(b.name)
@@ -101,20 +100,24 @@ export const SYSTEM_TABLE_COLUMNS: PageProColumns<SystemTableListItem>[] = [
{
title: '类型',
dataIndex: 'service_kind',
width: 120,
width: 140,
ellipsis: true
},
{
title: '所属团队',
dataIndex: ['team', 'name'],
ellipsis: true,
width: 200
ellipsis: true
},
{
title: '状态',
width: 140,
dataIndex: 'state',
ellipsis: true
},
{
title: 'API 数量',
dataIndex: 'apiNum',
ellipsis: true,
width: 140,
sorter: (a, b) => {
return a.apiNum - b.apiNum
}
@@ -242,12 +245,6 @@ export const MATCH_CONFIG: ConfigField<MatchItem>[] = [
]
export const SYSTEM_API_TABLE_COLUMNS: PageProColumns<SystemApiTableListItem>[] = [
{
title: '名称',
dataIndex: 'name',
width: 200,
ellipsis: true
},
{
title: 'URL',
dataIndex: 'requestPath',
@@ -365,10 +362,6 @@ 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' }
@@ -507,133 +500,3 @@ export const SYSTEM_PUBLISH_ONLINE_COLUMNS = [
}
}
]
/** AI 服务排行 */
export const AI_SERVICE_TOP_RANKING_LIST: PageProColumns<any>[] = [
{
title: '名称',
dataIndex: 'name',
ellipsis: true
},
{
title: '请求总数',
dataIndex: 'request',
ellipsis: true
},
{
title: 'Token',
dataIndex: 'token',
ellipsis: true
}
]
/** REST 服务排行 */
export const REST_SERVICE_TOP_RANKING_LIST: PageProColumns<any>[] = [
{
title: '名称',
dataIndex: 'name',
ellipsis: true
},
{
title: '请求总数',
dataIndex: 'request',
ellipsis: true
},
{
title: '流量',
dataIndex: 'traffic',
ellipsis: true
}
]
/** REST 服务日志 */
export const REST_SERVICE_LOG_LIST: PageProColumns<LogItem>[] = [
{
title: '时间戳',
dataIndex: 'logTime',
copyable: false,
width: 180,
ellipsis: true
},
{
title: 'API / Tools',
dataIndex: ['api', 'name'],
ellipsis: true
},
{
title: '消费者',
dataIndex: ['consumer', 'name'],
ellipsis: true
},
{
title: 'HTTP 状态',
dataIndex: 'status',
ellipsis: true
},
{
title: 'IP',
dataIndex: 'ip',
copyable: true,
width: 140,
ellipsis: true
},
{
title: '响应时间',
dataIndex: 'responseTime',
width: 130,
ellipsis: true
},
{
title: '流量',
dataIndex: 'traffic',
ellipsis: true
}
]
/** AI 服务日志 */
export const AI_SERVICE_LOG_LIST: PageProColumns<LogItem>[] = [
{
title: '时间戳',
dataIndex: 'logTime',
copyable: false,
width: 200,
ellipsis: true
},
{
title: 'API / Tools',
dataIndex: ['api', 'name'],
ellipsis: true
},
{
title: '消费者',
dataIndex: ['consumer', 'name'],
ellipsis: true
},
{
title: 'HTTP 状态',
dataIndex: 'status',
ellipsis: true
},
{
title: '模型',
dataIndex: 'model',
ellipsis: true
},
{
title: 'IP',
dataIndex: 'ip',
copyable: true,
width: 140,
ellipsis: true
},
{
title: 'Token/s',
dataIndex: 'tokenPerSecond',
ellipsis: true
},
{
title: 'Token',
dataIndex: 'token',
ellipsis: true
}
]
@@ -31,7 +31,6 @@ export type SystemConfigFieldType = {
catalogue?:string | string[];
approvalType?:string;
modelMapping?: string;
enable_mcp?: boolean;
};
export type SystemSubServiceTableListItem = {
@@ -97,7 +96,6 @@ export type SystemApiProxyType = {
export type SystemApiProxyFieldType = {
protocols: string[];
id:string;
name:string
description?:string;
disable:boolean;
path:string;
-60
View File
@@ -1109,11 +1109,6 @@ 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;
@@ -1156,32 +1151,9 @@ p{
align-items: center;
}
.ranking-list .ant-pro-table{
overflow: hidden;
border-radius: 10px;
border: none !important;
}
.ranking-list .ant-table-tbody:not(tbody) .ant-table-cell{
padding: 10px 10px !important;
}
.ranking-list .ant-table-container .ant-table-thead th{
background-color: #fff !important;
padding: 10px 10px !important;
}
.ranking-list .ant-table-container .ant-table-thead th::before{
display: none;
}
.ant-alert-info{
background: #1784FC1A !important;
}
.service-log-tab .ant-tabs .ant-tabs-nav .ant-tabs-tab{
padding-left: 0px;
padding-right: 0px;
}
.service-log-tab .ant-tabs .ant-tabs-tab+.ant-tabs-tab {
margin-left: 15px;
}
.monaco-editor .find-widget .monaco-inputbox.synthetic-focus{
outline-color: var(--primary-color) !important;
@@ -1241,38 +1213,6 @@ 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,191 +1,145 @@
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 { 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>();
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))
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(() => {
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(() => {
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>
)
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
@@ -9,12 +9,11 @@ import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { AiServiceConfigFieldType } from '@core/const/ai-service/type.ts'
import { App, Menu, MenuProps } from 'antd'
import { ItemType, MenuItemGroupType, MenuItemType } from 'antd/es/menu/interface'
import ServiceInfoCard from '@common/components/aoplatform/serviceInfoCard.tsx'
import Paragraph from 'antd/es/typography/Paragraph'
import { cloneDeep } from 'lodash-es'
import { FC, useEffect, useMemo, useState } from 'react'
import { Link, Outlet, useLocation, useNavigate, useParams } from 'react-router-dom'
import { useAiServiceContext } from '../../contexts/AiServiceContext.tsx'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
const APP_MODE = import.meta.env.VITE_APP_MODE
const AiServiceInsidePage: FC = () => {
@@ -28,7 +27,6 @@ const AiServiceInsidePage: FC = () => {
const [activeMenu, setActiveMenu] = useState<string>()
const navigateTo = useNavigate()
const [showMenu, setShowMenu] = useState<boolean>(false)
const { setBreadcrumb } = useBreadcrumb()
const getAiServiceInfo = () => {
fetchData<BasicResponse<{ service: AiServiceConfigFieldType }>>('service/info', {
@@ -69,7 +67,6 @@ const AiServiceInsidePage: FC = () => {
'assets',
null,
[
getItem(<Link to="./overview">{$t('总览')}</Link>, 'overview', undefined, undefined, undefined, ''),
getItem(
<Link to="./route">{$t('API 路由')}</Link>,
'route',
@@ -152,8 +149,7 @@ const AiServiceInsidePage: FC = () => {
'project.myAiService.topology.view'
)
: null,
getItem(<Link to="./setting">{$t('设置')}</Link>, 'setting', undefined, undefined, undefined, ''),
getItem(<Link to="./logs">{$t('日志')}</Link>, 'logs', undefined, undefined, undefined, '')
getItem(<Link to="./setting">{$t('设置')}</Link>, 'setting', undefined, undefined, undefined, '')
],
'group'
)
@@ -206,7 +202,7 @@ const AiServiceInsidePage: FC = () => {
} else if (serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]) {
setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1])
} else {
setActiveMenu('overview')
setActiveMenu('route')
}
}, [currentUrl])
@@ -217,35 +213,30 @@ const AiServiceInsidePage: FC = () => {
}, [accessData])
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigateTo('/service/list')
},
{
title: aiServiceInfo?.name || ''
}
])
if (activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]) {
navigateTo(`/service/${teamId}/aiInside/${serviceId}/${activeMenu}`)
}
}, [activeMenu, state.language, aiServiceInfo])
}, [activeMenu])
useEffect(() => {
serviceId && getAiServiceInfo()
}, [serviceId])
// 创建一个回调函数
const onSaveCallback = () => {
getAiServiceInfo()
}
return (
<>
{showMenu ? (
<InsidePage
pageTitle={aiServiceInfo?.name || '-'}
tagList={[
{
label: (
<Paragraph className="mb-0" copyable={serviceId ? { text: serviceId } : false}>
{$t('服务 ID')}{serviceId || '-'}
</Paragraph>
)
}
]}
backUrl="/service/list"
customBanner={<ServiceInfoCard serviceId={serviceId} teamId={teamId} />}
>
<div className="flex flex-1 h-full">
<Menu
@@ -259,7 +250,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 context={{ onSaveComplete: onSaveCallback }} />
<Outlet />
</div>
</div>
</InsidePage>
@@ -1,7 +1,8 @@
import {ActionType} from "@ant-design/pro-components";
import {FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import {useParams} from "react-router-dom";
import {Link, 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";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx";
import {BasicResponse, COLUMNS_TITLE, DELETE_TIPS, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
@@ -17,6 +18,7 @@ import { checkAccess } from "@common/utils/permission.ts";
import { $t } from "@common/locales/index.ts";
const AiServiceInsideSubscriber:FC = ()=>{
const { setBreadcrumb } = useBreadcrumb()
const { modal,message } = App.useApp()
const {fetchData} = useFetch()
const {serviceId, teamId} = useParams<RouterParams>()
@@ -117,6 +119,14 @@ const AiServiceInsideSubscriber:FC = ()=>{
]
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title:$t('订阅方管理')
}
])
getMemberList()
manualReloadTable()
}, [serviceId]);
@@ -1,72 +1,58 @@
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 { useParams } from "react-router-dom";
import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx";
import { AiServiceInsideApiDocumentHandle, AiServiceInsideApiDocumentProps, AiServiceApiDetail } from "@core/const/ai-service/type.ts";
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 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()
}, []);
useEffect(() => {
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 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} />
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>
</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,7 +21,6 @@ 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
@@ -67,7 +66,6 @@ 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
@@ -365,6 +363,11 @@ 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 路由设置') || '-'}
@@ -3,6 +3,7 @@ import PageList, { PageProColumns } from '@common/components/aoplatform/PageList
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission.tsx'
import { BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { SimpleMemberItem } from '@common/const/type.ts'
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'
@@ -16,6 +17,7 @@ import { Link, useNavigate, useParams } from 'react-router-dom'
const AiServiceInsideRouterList: FC = () => {
const [searchWord, setSearchWord] = useState<string>('')
const { setBreadcrumb } = useBreadcrumb()
const { modal, message } = App.useApp()
const [tableListDataSource, setTableListDataSource] = useState<AiServiceRouterTableListItem[]>([])
const [tableHttpReload, setTableHttpReload] = useState(true)
@@ -157,6 +159,14 @@ const AiServiceInsideRouterList: FC = () => {
}
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title: $t('路由')
}
])
getMemberList()
manualReloadTable()
}, [serviceId])
@@ -163,8 +163,6 @@ 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,8 +1,9 @@
import {ActionType} from "@ant-design/pro-components";
import {FC, useEffect, useMemo, useRef, useState} from "react";
import {Link, useLocation, useNavigate, useParams} from "react-router-dom";
import {Link, useLocation, 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";
import {
SUBSCRIBE_APPROVAL_INNER_DONE_TABLE_COLUMN,
@@ -25,6 +26,7 @@ import { SubscribeApprovalInfoType } from "@common/const/approval/type.tsx";
import { $t } from "@common/locales";
const AiServiceInsideApprovalList:FC = ()=>{
const { setBreadcrumb } = useBreadcrumb()
const { modal,message } = App.useApp()
const {serviceId, teamId} = useParams<RouterParams>();
const [init, setInit] = useState<boolean>(true)
@@ -139,6 +141,14 @@ const AiServiceInsideApprovalList:FC = ()=>{
}, [query]);
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title:$t('订阅审核')
}
])
getMemberList()
manualReloadTable()
}, [serviceId]);
@@ -2,11 +2,13 @@
import { Tabs } from "antd"
import { useState, useEffect, FC, useMemo } from "react"
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom"
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"
import { SYSTEM_PUBLISH_TAB_ITEMS } from "../../../const/system/const"
import { $t } from "@common/locales"
import { useGlobalContext } from "@common/contexts/GlobalStateContext"
const AiServiceInsidePublic:FC = ()=>{
const { setBreadcrumb } = useBreadcrumb()
const query =new URLSearchParams(useLocation().search)
const location = useLocation()
const currentUrl = location.pathname
@@ -23,6 +25,17 @@ const AiServiceInsidePublic:FC = ()=>{
setPageStatus(Number(query.get('status') ||0) as 0|1)
}, [currentUrl]);
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title:$t('发布')
}
])
}, []);
const tabItems = useMemo(()=>SYSTEM_PUBLISH_TAB_ITEMS?.map((x)=>({...x, label:$t(x.label as string) })),[state.language])
return (
<>
@@ -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, useNavigate } from "react-router-dom";
import { useParams, Link, useLocation } 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";
@@ -9,6 +9,7 @@ import { PUBLISH_APPROVAL_RECORD_INNER_TABLE_COLUMN, PUBLISH_APPROVAL_VERSION_IN
import { BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { SimpleMemberItem } from "@common/const/type.ts";
import { MemberTableListItem } from "../../../const/member/type";
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
import { useFetch } from "@common/hooks/http";
import WithPermission from "@common/components/aoplatform/WithPermission";
import { AiServicePublishReleaseItem } from "../../../const/system/type";
@@ -22,6 +23,7 @@ import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter
import { $t } from "@common/locales";
const AiServiceInsidePublicList:FC = ()=>{
const { setBreadcrumb } = useBreadcrumb()
const { modal,message } = App.useApp()
const pageListRef = useRef<ActionType>(null);
const [tableHttpReload, setTableHttpReload] = useState(true);
@@ -348,6 +350,14 @@ const AiServiceInsidePublicList:FC = ()=>{
]
useEffect(() => {
setBreadcrumb([
{
title:<Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title:$t('发布')
}
])
getMemberList()
manualReloadTable()
}, [serviceId]);
@@ -390,8 +390,6 @@ 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('OpenAPI & MCP 调用地址')}
label={$t('集成地址')}
name="sitePrefix"
rules={[{ required: true, whitespace: true }]}
rules={[{ whitespace: true }]}
extra={$t('与外部平台集成时,获取 API 市场中文档信息的域名')}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
@@ -181,8 +181,6 @@ 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,8 +106,6 @@ 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}
@@ -39,7 +39,6 @@ const ApiKeyContent: React.FC<ApiKeyContentProps> = forwardRef(({ provider, enti
const handleOk = async () => {
try {
// 表单校验
const values = await form.validateFields()
const { expire_time, ...restValues } = values
const expireTime = neverExpire ? 0 : Math.trunc(expire_time.valueOf() / 1000)
@@ -171,8 +171,6 @@ 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}
@@ -68,7 +68,7 @@ const LogSettings = () => {
<>
<Skeleton className="m-btnbase w-calc-100vw-minus-padding-r" active loading={loading}>
<InsidePage
pageTitle={$t('日志输出设置')}
pageTitle={$t('日志置')}
description={'APIPark ' + $t('提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。')}
>
<div className="flex h-full">
@@ -1,101 +0,0 @@
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
@@ -1,601 +0,0 @@
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>
</>
)
})
@@ -1,209 +0,0 @@
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
@@ -1,37 +0,0 @@
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
@@ -1,30 +0,0 @@
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
@@ -1,33 +0,0 @@
// 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;
@@ -1,22 +0,0 @@
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>;
@@ -1,391 +0,0 @@
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,8 +480,6 @@ 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,13 +60,7 @@ export type DashboardSettingEditProps = {
name="driver"
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={[...DASHBOARD_SETTING_DRIVER_OPTION_LIST]}
/>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.select)} options={[...DASHBOARD_SETTING_DRIVER_OPTION_LIST]}/>
</Form.Item>
<Form.Item<PartitionDashboardConfigFieldType>
@@ -1,15 +1,11 @@
import EditableTable from '@common/components/aoplatform/EditableTable'
import WithPermission from '@common/components/aoplatform/WithPermission'
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import {
PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS,
PartitionDataLogConfigFieldType,
PartitionDataLogHeaderListFieldType
} from '@core/const/partitions/types'
import { Button, Form, Input, message, Select } from 'antd'
import { useEffect } from 'react'
import EditableTable from "@common/components/aoplatform/EditableTable"
import WithPermission from "@common/components/aoplatform/WithPermission"
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const"
import { useFetch } from "@common/hooks/http"
import { $t } from "@common/locales"
import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDataLogConfigFieldType, PartitionDataLogHeaderListFieldType } from "@core/const/partitions/types"
import { Button, Form, Input, message } from "antd"
import { useEffect } from "react"
export type DashboardPageShowStatus = 'view' | 'edit'
export type DashboardSettingEditProps = {
@@ -19,7 +15,7 @@ export type DashboardSettingEditProps = {
}
const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
const { changeStatus, refreshData, data } = props
const [form] = Form.useForm()
const [form] = Form.useForm();
const { fetchData } = useFetch()
const onFinish = () => {
@@ -27,16 +23,10 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
const formData = {
config: {
url: value.url,
headers: value.headers
.filter((item: PartitionDataLogHeaderListFieldType) => item.key)
.map((item: PartitionDataLogHeaderListFieldType) => ({ key: item.key, value: item.value || '' }))
headers: value.headers.filter((item: PartitionDataLogHeaderListFieldType) => item.key).map((item: PartitionDataLogHeaderListFieldType) => ({key:item.key, value:item.value || ''}))
}
}
fetchData<BasicResponse<{ info: PartitionDataLogConfigFieldType }>>('log/loki', {
method: 'POST',
body: JSON.stringify(formData),
eoParams: {}
}).then((response) => {
fetchData<BasicResponse<{ info: PartitionDataLogConfigFieldType }>>('log/loki', { method: 'POST', body: JSON.stringify(formData), eoParams: {} }).then(response => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t('操作成功,即将刷新页面'))
@@ -48,26 +38,15 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
})
}
useEffect(() => {
form.setFieldsValue({
...data,
headers: data?.headers?.length ? data.headers : [
{
key: '',
value: ''
}
],
driver: 'loki'
})
}, [data])
useEffect(() => { form.setFieldsValue(data) }, [data])
useEffect(() => {
return form.setFieldsValue({})
}, [])
return (form.setFieldsValue({}))
}, []);
return (
<>
<div className="overflow-auto h-full">
<WithPermission access={''}>
<WithPermission access={''} >
<Form
form={form}
className="mx-auto flex flex-col justify-between h-full"
@@ -76,29 +55,23 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
autoComplete="off"
>
<Form.Item<PartitionDataLogConfigFieldType>
label={$t('数据源类型')}
name="driver"
label={$t("请求前缀")}
name="url"
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
options={[{ label: 'Loki', value: 'loki' }]}
></Select>
</Form.Item>
<Form.Item<PartitionDataLogConfigFieldType> label={$t('请求前缀')} name="url" rules={[{ required: true }]}>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
<Form.Item<PartitionDataLogConfigFieldType> label={$t('HTTP 头部')} name="headers">
<Form.Item<PartitionDataLogConfigFieldType>
label={$t("HTTP 头部")}
name="headers"
>
<EditableTable<PartitionDataLogConfigFieldType & { _id: string }>
configFields={PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS}
/>
</Form.Item>
<div className="flex gap-btnbase">
<WithPermission access="system.devops.data_source.edit">
<WithPermission access='system.devops.data_source.edit'>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
@@ -111,7 +84,7 @@ const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
</WithPermission>
</div>
</>
)
);
}
export default DataLogSettingEdit
export default DataLogSettingEdit;
@@ -161,7 +161,7 @@ const PartitionInsideDashboardSetting: FC = () => {
className="overflow-hidden mt-[30px] w-full max-h-full flex flex-col justify-between"
title={
<div>
<span className="text-MAIN_TEXT my-btnybase mr-btnbase"> {$t('请求日志')}</span>
<span className="text-MAIN_TEXT my-btnybase mr-btnbase"> {$t('数据日志')}</span>
{!dataLogLoading && !dataLogData && <Tag color="#f50">{$t('未配置')}</Tag>}
</div>
}
@@ -220,11 +220,6 @@ export function DataLogConfigPreview(x: PartitionDataLogConfigFieldType) {
return (
<div className="flex flex-col gap-[4px] ">
<Row className="">
<Col className="font-bold text-right pr-[4px]">{$t('数据源')}</Col>
{/* 先写死,或许会有选择列表,但现在可以不用 */}
<Col>Loki</Col>
</Row>
<Row className="">
<Col className="font-bold text-right pr-[4px]">{$t('请求前缀')}</Col>
<Col>{x?.url}</Col>
@@ -301,13 +301,7 @@ const FilterForm = forwardRef<FilterFormHandle, FilterFormProps>(
return (
<Form form={form} layout="vertical" onValuesChange={handleValuesChange}>
<Form.Item name="name" label={$t('属性名称')} rules={[{ required: true }]}>
<Select
showSearch
optionFilterProp="label"
disabled={disabled}
onChange={handleTypeChange}
options={filterOptionsList}
/>
<Select disabled={disabled} onChange={handleTypeChange} options={filterOptionsList} />
</Form.Item>
<Form.Item
name="values"
@@ -1,15 +1,15 @@
import { useEffect } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { useEffect } from "react";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
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')
}
}, [pathName])
return <Outlet></Outlet>
}
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')
}
},[pathName])
return (<Outlet></Outlet>)
}
@@ -14,7 +14,6 @@ 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()
@@ -25,7 +24,6 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
const { state } = useGlobalContext()
const [ loading, setLoading ] = useState<boolean>(false)
const navigator = useNavigate()
const { setBreadcrumb } = useBreadcrumb()
useImperativeHandle(ref, () => ({
save:onFinish
@@ -98,7 +96,7 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
showBorder={false}
scrollPage={false}
className="overflow-y-auto"
backUrl={serviceId ? `/service/${teamId}/aiInside/${serviceId}/servicepolicy` : undefined}
backUrl={serviceId ? '../list' : 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`] :''}>
@@ -126,13 +124,8 @@ const DataMaskingConfig = forwardRef<DataMaskingConfigHandle>((_,ref) => {
name="type"
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.input)}
options={policyOptions}
></Select>
<Select className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} options={policyOptions} >
</Select>
</Form.Item>
<Form.Item<DataMaskingConfigFieldType>
@@ -146,8 +146,6 @@ 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}
@@ -158,8 +156,6 @@ 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}
@@ -172,8 +168,6 @@ 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={
@@ -203,8 +197,6 @@ const DataMaskRuleForm: React.FC<DataMaskRuleFormProps> = ({
rules={[{ required: true }]}
>
<Select
showSearch
optionFilterProp="label"
placeholder={$t(PLACEHOLDER.select)}
onChange={handleReplaceTypeChange}
options={dataMaskReplaceStrOptions}
@@ -1,313 +1,251 @@
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'
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";
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)))
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} />
}
}
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])
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()
useEffect(() => {
permissionTemplate && setOpenCollapses(permissionTemplate?.map((x) => x.name))
}, [permissionTemplate])
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[]})=>{
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] })
}
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()
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}`
}))
}))
}))
}
}, [])
useEffect(() => {
setBreadcrumb([
{
title: $t('角色'),
onClick: () => navigateTo(-1)
},
{ title: $t('角色配置') }
])
getPermissionTemplate()
}, [state.language])
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 onFinish = async () => {
const body = await form.validateFields()
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))
}
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))
useEffect(()=>{
form.setFieldsValue({name:$t(permissionInfo?.name || ''),permits:permissionInfo?.permit})
},[permissionInfo, state.language])
useEffect(() => {
form.setFieldsValue({name:'',permits:[]})
if(roleId){
getPermissionInfo()
}
})
.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>
useEffect(()=>{
getPermissionTemplate()
{APP_MODE === 'pro' && (
<div className="p-btnbase">
<WithPermission
access={
roleId === undefined
? `system.organization.role.${roleType}.edit`
: `system.organization.role.${roleType}.add`
}
},[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"
>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
</WithPermission>
<Button className="ml-btnrbase" type="default" onClick={() => navigateTo(-1)}>
{$t('取消')}
</Button>
</div>
)}
</div>
</Form>
</WithPermission>
</div>
)
<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
export default RoleConfig
@@ -1,6 +0,0 @@
import ServiceLogs from "./ServiceLogs"
const AiServiceLogsContainer = () => {
return <ServiceLogs serviceType="aiService" />
}
export default AiServiceLogsContainer
@@ -1,89 +0,0 @@
import { IconButton } from '@common/components/postcat/api/IconButton'
import useCopyToClipboard from '@common/hooks/copy'
import { RESPONSE_TIPS } from '@common/const/const'
import { $t } from '@common/locales/index.ts'
import { App } from 'antd'
import ReactJson from 'react-json-view'
const ApiNetWorkDataPreview = ({ configContent = {} }: { configContent?: { [key: string]: string | undefined } }) => {
/** 复制组件 */
const { copyToClipboard } = useCopyToClipboard()
/** 弹窗组件 */
const { message } = App.useApp()
/**
*
* @param value
* @returns
*/
const handleCopy = async (value: string): Promise<void> => {
if (value) {
copyToClipboard(value)
message.success($t(RESPONSE_TIPS.copySuccess))
}
}
/**
* JSON对象字符串
*/
const isJsonString = (str: string): boolean => {
try {
const parsed = JSON.parse(str)
return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
} catch (e) {
return false
}
}
return (
<>
{Object.keys(configContent).filter((item) => !!configContent[item]).map((item) => {
return (
<div className="overflow-auto mb-[15px]">
<div className="font-semibold text-[16px] mb-[10px]">{item}</div>
<div className="bg-[#0a0b21] text-white p-4 rounded-md my-2 font-mono text-sm overflow-auto relative">
{!configContent[item] ? (
<pre className="whitespace-pre-wrap break-words"></pre>
) : isJsonString(configContent[item] || '') ? (
// 如果是有效的JSON对象字符串,使用ReactJson渲染
<ReactJson
src={JSON.parse(configContent[item] || '')}
theme="monokai"
indentWidth={2}
displayDataTypes={false}
displayObjectSize={false}
name={false}
collapsed={false}
enableClipboard={false}
style={{
backgroundColor: 'transparent',
wordBreak: 'break-word',
whiteSpace: 'normal'
}}
/>
) : (
// 如果是普通字符串,直接用pre渲染
<pre className="whitespace-pre-wrap break-words my-[8px]">{configContent[item]}</pre>
)}
<IconButton
name="copy"
onClick={() => handleCopy(configContent[item] || '')}
sx={{
position: 'absolute',
top: '5px',
right: '5px',
color: '#999',
transition: 'none',
'&.MuiButtonBase-root:hover': {
background: 'transparent',
color: '#3D46F2',
transition: 'none'
}
}}
></IconButton>
</div>
</div>
)
})}
</>
)
}
export default ApiNetWorkDataPreview
@@ -1,362 +0,0 @@
import { Descriptions, DescriptionsProps, Spin, Tabs, Tooltip, message } from 'antd'
import { useEffect, useMemo, useState } from 'react'
import { $t } from '@common/locales/index.ts'
import React from 'react'
import { ExclamationCircleOutlined, LoadingOutlined } from '@ant-design/icons'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
import ApiNetWorkDataPreview from './ApiNetWorkDataPreview'
import { LogItem } from './ServiceLogs'
import { useFetch } from '@common/hooks/http'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
// 定义状态码颜色映射枚举
export enum HttpStatusColor {
SUCCESS = '#7EC26A',
CLIENT_ERROR = '#F2CF59',
SERVER_ERROR = '#f80f34'
}
type LogDetailProps = {
selectedRow?: LogItem
serviceType: 'aiService' | 'restService'
serviceId?: string
teamId?: string
}
type AIServiceDetailType = {
id: string
api: {
id: string
name: string
}
logTime: string
consumer: {
id: string
name: string
}
isSystemConsumer: boolean
status: string
provider: {
id: string
name: string
}
model: string
ip: string
request: {
header: string
body: string
origin: string
token: number
}
response: {
header: string
body: string
origin: string
token: string
}
}
type RestServiceDetailType = {
id: string
api: {
id: string
name: string
}
logTime: string
consumer: {
id: string
name: string
}
isSystemConsumer: boolean
status: string
ip: string
request: {
header: string
origin: string
}
response: {
header: string
origin: string
}
}
const LogDetail = ({ selectedRow, serviceType, serviceId, teamId }: LogDetailProps) => {
/** 顶部描述 */
const [descriptionItems, setDescriptionItems] = useState<DescriptionsProps['items']>()
/** 全局状态 */
const { state } = useGlobalContext()
/** Request 标签页数据 */
const [requestInfoData, setRequestInfoData] = useState<{ [key: string]: string | undefined }>()
/** Response 标签页数据 */
const [responseInfoData, setResponseInfoData] = useState<{ [key: string]: string | undefined }>()
/** 面板 loading */
const [dashboardLoading, setDashboardLoading] = useState(true)
/**
*
*/
const { fetchData } = useFetch()
/**
*
* @param status
* @returns
*/
const renderStatusWithColor = (status: string) => {
// 获取状态码首位数字
const firstDigit = String(status).charAt(0)
let color = ''
switch (firstDigit) {
case '2':
color = HttpStatusColor.SUCCESS
break
case '4':
color = HttpStatusColor.CLIENT_ERROR
break
case '5':
color = HttpStatusColor.SERVER_ERROR
break
default:
break
}
return color ? <span style={{ color }}>{status}</span> : status
}
/**
*
*/
const tabItems = useMemo(
() => [
{
key: 'request',
label: 'Request',
children: <ApiNetWorkDataPreview configContent={requestInfoData} />
},
{
key: 'response',
label: 'Response',
children: <ApiNetWorkDataPreview configContent={responseInfoData} />
}
],
[state.language, requestInfoData, responseInfoData]
)
/**
* AI
*/
const getAIServiceDescriptionItemsList = ({
time,
api,
consumer,
status,
model,
ip
}: {
time: string
api: string
consumer: string
status: string
model: string
ip: string
}) => {
setDescriptionItems([
{
key: 'time',
label: $t('时间戳'),
children: time
},
{
key: 'api',
label: $t('API / Tools'),
children: api
},
{
key: 'consumer',
label: $t('消费者'),
children: consumer
},
{
key: 'httpStatus',
label: $t('HTTP 状态'),
children: renderStatusWithColor(status)
},
{
key: 'model',
label: $t('模型'),
children: model
},
{
key: 'ip',
label: $t('IP'),
children: ip
}
])
}
/**
* REST
*/
const getRestServiceDescriptionItemsList = ({
time,
api,
consumer,
isSystemConsumer,
status,
ip
}: {
time: string
api: string
consumer: string
isSystemConsumer?: boolean
status: string
ip: string
}) => {
setDescriptionItems([
{
key: 'time',
label: $t('时间戳'),
children: time
},
{
key: 'api',
label: $t('API / Tools'),
children: api
},
{
key: 'consumer',
label: $t('消费者'),
children: (
<>
<span className="mr-[50px]">{consumer}</span>
{isSystemConsumer && (
<span>
<span>System-level API Key</span>
<Tooltip title={$t('通过系统级别的 API Key 来调用')}>
<span className="ml-[12px] items-center">
<ExclamationCircleOutlined className="text-[14px] h-[14px] w-[14px]" />
</span>
</Tooltip>
</span>
)}
</>
)
},
{
key: 'httpStatus',
label: $t('HTTP 状态'),
children: renderStatusWithColor(status)
},
{
key: 'ip',
label: $t('IP'),
children: ip
}
])
}
/**
* AI
*/
const getAIServiceLogDetail = () => {
fetchData<BasicResponse<{ log: AIServiceDetailType }>>('service/log/ai', {
method: 'GET',
eoParams: { log: selectedRow?.id, service: serviceId, team: teamId },
eoTransformKeys: ['is_system_consumer', 'log_time']
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const result = data.log
getAIServiceDescriptionItemsList({
time: result.logTime,
api: result.api.name,
consumer: result.consumer.name,
status: result.status,
model: result.model,
ip: result.ip
})
setRequestInfoData({
Header: result.request.header,
Body: result.request.body
})
setResponseInfoData({
Header: result.response.header,
Body: result.response.body
})
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
setDashboardLoading(false)
})
}
/**
* REST
*/
const getRestServiceLogDetail = () => {
fetchData<BasicResponse<{ log: RestServiceDetailType }>>('service/log/rest', {
method: 'GET',
eoParams: { log: selectedRow?.id, service: serviceId, team: teamId },
eoTransformKeys: ['is_system_consumer', 'log_time']
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const result = data.log
getRestServiceDescriptionItemsList({
time: result.logTime,
api: result.api.name,
consumer: result.consumer.name,
status: result.status,
ip: result.ip,
isSystemConsumer: result.isSystemConsumer
})
setRequestInfoData({
Header: result.request.header,
Body: result.request.body
})
setResponseInfoData({
Header: result.response.header,
Body: result.response.body
})
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
setDashboardLoading(false)
})
}
useEffect(() => {
setDashboardLoading(true)
serviceType === 'aiService' ? getAIServiceLogDetail() : getRestServiceLogDetail()
}, [serviceType])
return (
<Spin
className="h-full pb-[20px]"
wrapperClassName="h-full min-h-[150px]"
indicator={
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ transform: 'scale(1.5)' }}>
<LoadingOutlined style={{ fontSize: 30 }} spin />
</div>
</div>
}
spinning={dashboardLoading}
>
<Descriptions
column={1}
className="[&_.ant-descriptions-item]:p-0 [&_.ant-descriptions-item]:py-[5px]"
colon={false}
items={descriptionItems}
classNames={{
label: 'w-[250px] text-right pr-[12px]'
}}
contentStyle={{ fontWeight: '600' }}
/>
<div className="mt-[5px] service-log-tab">
<Tabs
className="overflow-hidden h-full [&>.ant-tabs-content-holder]:overflow-auto global-policy-tabs"
items={tabItems}
/>
</div>
</Spin>
)
}
export default LogDetail
@@ -1,7 +0,0 @@
import ServiceLogs from "./ServiceLogs"
const RestServiceLogsContainer = () => {
return <ServiceLogs serviceType="restService" />
}
export default RestServiceLogsContainer
@@ -1,263 +0,0 @@
import { LoadingOutlined } from '@ant-design/icons'
import { Drawer, Spin, message } from 'antd'
import { useEffect, useMemo, useRef, useState } from 'react'
import DateSelectFilter, { TimeOption } from '../serviceOverview/filter/DateSelectFilter'
import { TimeRange } from '@common/components/aoplatform/TimeRangeSelector'
import PageList from '@common/components/aoplatform/PageList'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
import { REST_SERVICE_LOG_LIST, AI_SERVICE_LOG_LIST } from '@core/const/system/const'
import { $t } from '@common/locales/index.ts'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import LogDetail, { HttpStatusColor } from './LogDetail'
import { useParams } from 'react-router-dom'
import { ActionType, ParamsType } from '@ant-design/pro-components'
import { getTime } from '@dashboard/utils/dashboard'
export type LogItem = {
id: string
api: {
id: string
name: string
}
status: number
logTime: string
responseTime: string
token?: number
model?: string
tokenPerSecond?: string
traffic?: string
consumers?: {
id: string
name: string
}
provider?: {
id: string
name: string
}
}
const ServiceLogs = ({ serviceType }: { serviceType: 'aiService' | 'restService' }) => {
/** 路由参数 */
const { serviceId, teamId } = useParams<{ serviceId: string; teamId: string }>()
/** 面板 loading */
const [dashboardLoading, setDashboardLoading] = useState(true)
/** 当前选中的时间范围 */
const [timeRange, setTimeRange] = useState<TimeRange | undefined>()
/** 默认时间 */
const [defaultTime] = useState<TimeOption>('day')
/** 全局状态 */
const { state } = useGlobalContext()
/**
*
*/
const { fetchData } = useFetch()
// 打开侧边弹窗
const [drawerOpen, setDrawerOpen] = useState<boolean>(false)
/** 选中的行 */
const [selectedRow, setSelectedRow] = useState<LogItem>()
/**
* ref
*/
const pageListRef = useRef<ActionType>(null)
/** 列 */
const columns = useMemo(() => {
return [...(serviceType === 'aiService' ? AI_SERVICE_LOG_LIST : REST_SERVICE_LOG_LIST)].map((x) => {
if (x.dataIndex === 'status') {
x.render = (text: any, record: any) => (
<>
<div className="w-full">{renderStatusWithColor(record.status)}</div>
</>
)
}
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title
}
})
}, [state.language])
/**
*
* @param status
* @returns
*/
const renderStatusWithColor = (status: string | number) => {
// 获取状态码首位数字
const firstDigit = status.toString().charAt(0)
let color = ''
switch (firstDigit) {
case '2':
color = HttpStatusColor.SUCCESS
break
case '4':
color = HttpStatusColor.CLIENT_ERROR
break
case '5':
color = HttpStatusColor.SERVER_ERROR
break
default:
break
}
return color ? <span style={{ color }}>{status}</span> : status
}
/**
* AI
* @param dataType
* @returns
*/
const getAiServiceLogList = (
params: ParamsType & {
pageSize?: number | undefined
current?: number | undefined
keyword?: string | undefined
}
) => {
return fetchData<BasicResponse<{ log: LogItem[] }>>(`service/logs/ai`, {
method: 'GET',
eoParams: {
service: serviceId,
team: teamId,
start: timeRange?.start,
end: timeRange?.end,
page: params?.current,
page_size:params?.pageSize
},
eoTransformKeys: ['log_time', 'response_time', 'token_per_second']
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 保存数据
return {
data: data.logs,
total: data.total,
success: true
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return { data: [], success: false }
}
})
.catch(() => {
return { data: [], success: false }
})
}
/**
* REST
* @param dataType
* @returns
*/
const getRestServiceLogList = (
params: ParamsType & {
pageSize?: number | undefined
current?: number | undefined
keyword?: string | undefined
}
) => {
console.log('params===', params)
return fetchData<BasicResponse<{ log: LogItem[] }>>(`service/logs/rest`, {
method: 'GET',
eoParams: {
service: serviceId,
team: teamId,
start: timeRange?.start,
end: timeRange?.end,
page: params?.current,
page_size:params?.pageSize
},
eoTransformKeys: ['log_time', 'response_time', 'token_per_second']
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 保存数据
return {
data: data.logs,
total: data.total,
success: true
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return { data: [], success: false }
}
})
.catch(() => {
return { data: [], success: false }
})
}
useEffect(() => {
const { startTime, endTime } = getTime(defaultTime, [])
setTimeRange({
start: startTime,
end: endTime
})
}, [])
useEffect(() => {
if (timeRange) {
pageListRef.current?.reload()
}
}, [timeRange])
/** 行点击 */
const handleRowClick = (record: LogItem) => {
setSelectedRow(record)
setDrawerOpen(true)
}
/** 时间选择回调 */
const selectCallback = (date: TimeRange) => {
setTimeRange(date)
}
useEffect(() => {
setDashboardLoading(false)
}, [])
return (
<Spin
className="h-full pb-[20px]"
wrapperClassName="h-full min-h-[150px] overflow-hidden"
indicator={
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ transform: 'scale(1.5)' }}>
<LoadingOutlined style={{ fontSize: 30 }} spin />
</div>
</div>
}
spinning={dashboardLoading}
>
<div className="h-full mr-PAGE_INSIDE_X">
<DateSelectFilter selectCallback={selectCallback} customClassNames={'pt-[0px]'} defaultTime={defaultTime} />
<div style={{ height: 'calc(100% - -3px)' }} className="mt-[20px] overflow-hidden">
<PageList
ref={pageListRef}
id={`${serviceType}_logs`}
columns={[...columns]}
request={async (
params: ParamsType & {
pageSize?: number | undefined
current?: number | undefined
keyword?: string | undefined
}
) => (serviceType === 'aiService' ? getAiServiceLogList(params) : getRestServiceLogList(params))}
onRowClick={(row: LogItem) => handleRowClick(row)}
/>
</div>
<Drawer
destroyOnClose={true}
maskClosable={false}
title={$t('日志详情')}
width={'40%'}
onClose={() => setDrawerOpen(false)}
open={drawerOpen}
>
<LogDetail selectedRow={selectedRow} serviceId={serviceId} teamId={teamId} serviceType={serviceType} />
</Drawer>
</div>
</Spin>
)
}
export default ServiceLogs
@@ -1,7 +0,0 @@
import ServiceOverview from "./serviceOverview"
const AiServiceContainer = () => {
return <ServiceOverview serviceType="aiService" />
}
export default AiServiceContainer
@@ -1,12 +0,0 @@
import { FC } from 'react'
import ServiceOverview from './serviceOverview'
const RestServiceContainer: FC = () => {
return (
<>
<ServiceOverview serviceType="restService" />
</>
)
}
export default RestServiceContainer
@@ -1,278 +0,0 @@
import { useEffect, useRef, useState } from 'react'
import ECharts, { EChartsOption } from 'echarts-for-react'
import { $t } from '@common/locales'
type AreaChartInfo = {
title: string
value: string
date: string[]
data: number[]
max: string
min: string
originValue?: number
showXAxis?: boolean
}
type ServiceAreaCharProps = {
customClassNames?: string
dataInfo?: AreaChartInfo
height?: number
showAvgLine?: boolean
customMarkLineValue?: number
}
const ServiceAreaChart = ({ customClassNames, dataInfo, height, showAvgLine, customMarkLineValue }: ServiceAreaCharProps) => {
const chartRef = useRef<ECharts>(null)
const [option, setOption] = useState<EChartsOption | undefined>({})
const [hasData, setHasData] = useState(true)
const setChartOption = (dataInfo: AreaChartInfo) => {
const dataExists = dataInfo.data && dataInfo.data.length > 0
// 更新hasData状态
setHasData(dataExists)
const option = {
tooltip: dataExists ? {
trigger: 'axis',
formatter: function (value: any) {
// 如果是数组,取第一个参数的name
const param = Array.isArray(value) ? value[0] : value
let tooltipContent = `<div style="min-width:140px;padding:8px;">`
const marker = `<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>`
tooltipContent += `<div style="margin-top: 8px; display: flex; justify-content: space-between; align-items: center;">
<div style="margin-right: 4px;">${marker}</div>${param.name} <div style="font-weight:bold; margin-left: 20px;">${param.value}</div>
</div>`
tooltipContent += '</div>'
return tooltipContent
}
} : {
show: false // 没有数据时不显示tooltip
},
title: [
{
text: '{titleStyle|' + $t(dataInfo.title) + '}\n\n{valueStyle|' + dataInfo.value + '}',
left: '2%',
top: '0',
textStyle: {
rich: {
titleStyle: {
fontSize: 14,
color: '#999999',
fontWeight: 'normal',
lineHeight: 20
},
valueStyle: {
fontSize: 32,
color: '#101010',
fontWeight: 500,
lineHeight: 40
}
}
}
}
],
toolbox: {
show: false
},
grid: {
left: '3%',
right: '3%',
bottom: '0%',
top: '110px',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: dataInfo.date,
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#ccc'
}
},
show: false
},
yAxis: {
type: 'value',
boundaryGap: [0, '5%'],
show: dataExists, // 没有数据时不显示Y轴
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
}
},
// 添加数据缩放组件,实现鼠标放大缩小,后续可能需要
// dataZoom: [
// {
// type: 'inside', // 内置的数据区域缩放组件(使用鼠标滚轮缩放)
// xAxisIndex: 0, // 设置缩放作用在第一个x轴
// filterMode: 'filter',
// start: 0,
// end: 100
// },
// {
// type: 'slider', // 滑动条型数据区域缩放组件
// xAxisIndex: 0,
// filterMode: 'filter',
// height: 20,
// bottom: 0,
// start: 0,
// end: 100,
// handleIcon:
// 'path://M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
// handleSize: '80%',
// handleStyle: {
// color: '#fff',
// shadowBlur: 3,
// shadowColor: 'rgba(0, 0, 0, 0.6)',
// shadowOffsetX: 2,
// shadowOffsetY: 2
// },
// show: false // 默认隐藏底部的滑动条,可以改为 true 显示
// }
// ],
// 添加空状态提示
silent: !dataExists,
graphic: !dataExists
? [
{
type: 'text',
left: 'center',
top: 'middle',
style: {
text: $t('暂无数据'),
fontSize: 14,
fill: '#999'
}
}
]
: [],
series: [
{
name: dataInfo.title,
type: 'line',
symbol: 'none',
sampling: 'lttb',
itemStyle: {
color: 'rgb(255, 70, 131)'
},
markLine: showAvgLine ? {
silent: false,
symbol: 'none',
lineStyle: {
width: 1,
type: 'dashed'
},
label: {
show: false,
position: 'insideEndTop',
formatter: '{c}',
color: '#000',
fontSize: 10,
backgroundColor: 'transparent',
padding: [10, 4],
borderRadius: 2,
distance: -5
},
emphasis: {
lineStyle: {
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
},
label: {
show: false // 悬停时不显示标签
}
},
data: dataInfo?.originValue !== undefined ?
[{ yAxis: dataInfo?.originValue, name: '自定义值' }] :
[{ type: 'average', name: 'Avg' }]
} : undefined,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgb(255, 158, 68)'
},
{
offset: 1,
color: 'rgb(255, 70, 131)'
}
]
}
},
data: dataInfo.data
}
]
}
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
echartsInstance.setOption(option)
}
}
// 使用深度监听来确保图表数据更新
useEffect(() => {
if (!dataInfo) return
// 直接获取 ECharts 实例并设置选项
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
// 清除已有的图表
echartsInstance.clear()
// 重新设置选项
setChartOption(dataInfo)
}
}, [dataInfo, JSON.stringify(dataInfo)])
// 添加窗口大小变化监听,实现自适应
useEffect(() => {
// 定义resize处理函数
const handleResize = () => {
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
echartsInstance.resize()
}
}
// 添加监听
window.addEventListener('resize', handleResize)
// 组件卸载时移除监听
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
return (
<div className={`w-full ${customClassNames}`}>
<div className="absolute top-[10px] left-[10px] w-full">
<div className="relative top-[5px]">
<div className="absolute top-[23px] right-[5%] grid grid-cols-[auto_auto] justify-items-end">
<div className="flex justify-center items-center">
<span className="text-[#FE564D] text-[9px]"></span>
</div>
<span className="ml-1 text-right">{dataInfo?.max}</span>
<div className="flex justify-center items-center">
<span className="text-[#27B148] text-[9px]"></span>
</div>
<span className="ml-1 text-right">{dataInfo?.min}</span>
</div>
</div>
</div>
<div style={!hasData ? { cursor: 'default', pointerEvents: 'none' } : {}}>
<ECharts ref={chartRef} option={option} theme="apipark" style={{ height: height || 400 }} opts={{ renderer: 'svg' }} />
</div>
</div>
)
}
export default ServiceAreaChart
@@ -1,395 +0,0 @@
import ECharts, { EChartsOption } from 'echarts-for-react'
import { useEffect, useRef, useState } from 'react'
import { $t } from '@common/locales/index.ts'
import { chartColors, defaultColor } from '@common/const/charts/theme'
export type BarChartInfo = {
title: string
value: string
date: string[]
data: {
name: string
color: string
value: number[]
}[]
showXAxis?: boolean
inputTokenTotal?: string
outputTokenTotal?: string
request2xxTotal?: string
request4xxTotal?: string
request5xxTotal?: string
traffic2xxTotal?: string
traffic4xxTotal?: string
traffic5xxTotal?: string
max?: string | number
min?: string | number
}
type ServiceBarCharProps = {
customClassNames?: string
dataInfo?: BarChartInfo
height?: number
showAvgLine?: boolean
showLegendIndicator?: boolean
hideIndicatorValue?: boolean
}
const ServiceBarChar = ({
customClassNames,
dataInfo,
height,
showAvgLine,
showLegendIndicator,
hideIndicatorValue
}: ServiceBarCharProps) => {
const chartRef = useRef<ECharts>(null)
const [option, setOption] = useState<EChartsOption | undefined>({})
// 使用从主题配置中导入的默认颜色,而不是硬编码的颜色值
const [detaultColor] = useState(defaultColor)
const [hasData, setHasData] = useState(true)
const tokenMap = {
inputToken: $t('输入 Token'),
outputToken: $t('输出 Token')
}
const setChartOption = (dataInfo: BarChartInfo) => {
const isNumberArray = typeof dataInfo.data[0] !== 'object'
const legendData = isNumberArray ? [dataInfo.title] : dataInfo.data.map((item) => item.name)
const dataExists = dataInfo.data && dataInfo.data.length > 0
// 更新hasData状态
setHasData(dataExists)
const tooltipFormatter = (params: { name: string; color: string; seriesIndex?: number }) => {
let tooltipContent = `<div style="min-width:140px;padding:8px;">
<div>${isNumberArray ? '' : params.name}</div>`
const data = isNumberArray
? [
{
name: params.name,
color: detaultColor,
value: dataInfo.data
}
]
: dataInfo.data
// 为每个数据系列添加一行
data.forEach((item, index) => {
// 使用与柱状图相同的颜色策略,确保颜色一致性
const color = item.color ? item.color : index < chartColors.length ? chartColors[index] : detaultColor
const name = tokenMap[item.name as keyof typeof tokenMap] || item.name
const value = item.value[dataInfo.date.indexOf(params.name)] || 0
const marker = `<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:${color};"></span>`
tooltipContent += `<div style="margin-top: ${index === 0 ? 8 : 4}px; display: flex; justify-content: space-between; align-items: center;">
<div>${marker} ${name}</div> <div style="font-weight:bold; margin-left: 20px;">${value}</div>
</div>`
})
tooltipContent += '</div>'
return tooltipContent
}
const option: EChartsOption = {
title: [
{
text:
'{titleStyle|' +
$t(dataInfo.title) +
`}${hideIndicatorValue ? '' : '\n\n{valueStyle|' + dataInfo.value + '}'}`,
left: '2%',
top: '0',
textStyle: {
rich: {
titleStyle: {
fontSize: 14,
color: '#999999',
fontWeight: 'normal',
lineHeight: 20
},
valueStyle: {
fontSize: 32,
color: '#101010',
fontWeight: 500,
lineHeight: 40
}
}
}
}
],
grid: {
left: '3%',
right: '3%',
bottom: '0%',
top: '110px',
containLabel: true
},
tooltip: dataExists
? {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params: any) {
// 如果是数组,取第一个参数的name
const param = Array.isArray(params) ? params[0] : params
return tooltipFormatter(param)
}
}
: {
show: false // 没有数据时不显示tooltip
},
legend: {
show: !isNumberArray,
data: legendData,
right: '10px',
top: hideIndicatorValue ? '10px' : '60px',
itemWidth: 10,
itemHeight: 10,
textStyle: {
color: '#333'
},
icon: 'rect',
formatter: function (name: string): string {
// 这里可以映射或自定义图例文本
const customNames: Record<string, string> = {
inputToken: `${$t('输入 Token')} ${showLegendIndicator ? `(${dataInfo.inputTokenTotal})` : ''}`,
outputToken: `${$t('输出 Token')} ${showLegendIndicator ? `(${dataInfo.outputTokenTotal})` : ''}`,
'2xx': `${'2xx'} ${showLegendIndicator ? `(${dataInfo.request2xxTotal || dataInfo.traffic2xxTotal})` : ''}`,
'4xx': `${'4xx'} ${showLegendIndicator ? `(${dataInfo.request4xxTotal || dataInfo.traffic4xxTotal})` : ''}`,
'5xx': `${'5xx'} ${showLegendIndicator ? `(${dataInfo.request5xxTotal || dataInfo.traffic5xxTotal})` : ''}`
}
return customNames[name] || name
}
},
xAxis: {
type: 'category',
data: dataInfo.date,
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#ccc'
}
},
show: false
},
yAxis: {
type: 'value',
name: '',
min: 0,
...(showAvgLine ? {} : { minInterval: 1 }),
show: dataExists, // 没有数据时不显示Y轴
splitLine: {
show: dataExists, // 没有数据时不显示网格线
lineStyle: {
type: 'dashed',
color: '#eee'
}
},
axisLabel: {
formatter: '{value}'
}
},
// 添加数据缩放组件,实现鼠标放大缩小,后续可能需要
// dataZoom: [
// {
// type: 'inside', // 内置的数据区域缩放组件(使用鼠标滚轮缩放)
// xAxisIndex: 0, // 设置缩放作用在第一个x轴
// filterMode: 'filter',
// start: 0,
// end: 100
// },
// {
// type: 'slider', // 滑动条型数据区域缩放组件
// xAxisIndex: 0,
// filterMode: 'filter',
// height: 20,
// bottom: 0,
// start: 0,
// end: 100,
// handleIcon: 'path://M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
// handleSize: '80%',
// handleStyle: {
// color: '#fff',
// shadowBlur: 3,
// shadowColor: 'rgba(0, 0, 0, 0.6)',
// shadowOffsetX: 2,
// shadowOffsetY: 2
// },
// show: false // 默认隐藏底部的滑动条,可以改为 true 显示
// }
// ],
// 添加空状态提示
silent: !dataExists,
graphic: !dataExists
? [
{
type: 'text',
left: 'center',
top: 'middle',
style: {
text: $t('暂无数据'),
fontSize: 14,
fill: '#999'
}
}
]
: [],
series: isNumberArray
? [
{
name: dataInfo.title,
type: 'bar',
stack: '总量',
emphasis: {
focus: 'series'
},
itemStyle: {
color: detaultColor
},
markLine: showAvgLine
? {
silent: false,
symbol: 'none',
lineStyle: {
width: 1,
type: 'dashed'
},
label: {
show: false,
position: 'insideEndTop',
formatter: '{c}',
color: '#000',
fontSize: 10,
backgroundColor: 'transparent',
padding: [10, 4],
borderRadius: 2,
distance: -5
},
emphasis: {
lineStyle: {
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
},
label: {
show: false // 悬停时不显示标签
}
},
data: [{ type: 'average', name: 'Avg' }]
}
: undefined,
data: dataInfo.data
}
]
: dataInfo.data.map((item, index) => ({
name: item.name,
type: 'bar',
stack: '总量',
markLine: showAvgLine
? {
silent: false,
symbol: 'none',
lineStyle: {
width: 1,
type: 'dashed'
},
label: {
show: false,
position: 'insideEndTop',
formatter: '{c}',
color: '#000',
fontSize: 10,
backgroundColor: 'transparent',
padding: [10, 4],
borderRadius: 2,
distance: -5
},
emphasis: {
lineStyle: {
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
},
label: {
show: false // 悬停时不显示标签
}
},
data: [{ type: 'average', name: 'Avg' }]
}
: undefined,
emphasis: {
focus: 'series'
},
itemStyle: {
// 使用主题中的颜色列表,如果索引超出范围则使用项目自带的颜色
color: item.color ? item.color : index < chartColors.length ? chartColors[index] : detaultColor
},
data: item.value
}))
}
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
echartsInstance.setOption(option)
}
}
// 使用深度监听来确保图表数据更新
useEffect(() => {
if (!dataInfo) return
// 直接获取 ECharts 实例并设置选项
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
// 清除已有的图表
echartsInstance.clear()
// 重新设置选项
setChartOption(dataInfo)
}
}, [dataInfo, JSON.stringify(dataInfo)])
// 添加窗口大小变化监听,实现自适应
useEffect(() => {
// 定义resize处理函数
const handleResize = () => {
const echartsInstance = chartRef.current?.getEchartsInstance()
if (echartsInstance) {
echartsInstance.resize()
}
}
// 添加监听
window.addEventListener('resize', handleResize)
// 组件卸载时移除监听
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
return (
<div className={`w-full ${customClassNames}`}>
{
hideIndicatorValue && (
<div className="absolute top-[26px] left-[10px] w-full">
<div className="relative top-[5px]">
<div className="absolute top-[23px] right-[5%] grid grid-cols-[auto_auto] justify-items-end">
<div className="flex justify-center items-center">
<span className="text-[#FE564D] text-[9px]"></span>
</div>
<span className="ml-1 text-right">{dataInfo?.max}</span>
<div className="flex justify-center items-center">
<span className="text-[#27B148] text-[9px]"></span>
</div>
<span className="ml-1 text-right">{dataInfo?.min}</span>
</div>
</div>
</div>
)
}
<div style={!hasData ? { cursor: 'default', pointerEvents: 'none' } : {}}>
<ECharts
ref={chartRef}
option={option}
style={{ height: height || 400 }}
opts={{ renderer: 'svg' }}
theme="apipark" // 这里应用主题名称,需要先在应用入口注册
/>
</div>
</div>
)
}
export default ServiceBarChar
@@ -1,37 +0,0 @@
import TimeRangeSelector, { RangeValue, TimeRange } from '@common/components/aoplatform/TimeRangeSelector'
import { useState } from 'react'
export type TimeOption = '' | 'hour' | 'day' | 'threeDays' | 'sevenDays'
const DateSelectFilter = ({
selectCallback,
defaultTime,
customClassNames
}: {
selectCallback: (timeRange: TimeRange) => void
defaultTime: TimeOption
customClassNames?: string
}) => {
/** 默认时间 */
const [timeButton, setTimeButton] = useState<TimeOption>(defaultTime || 'hour')
/** 日期选择 */
const [datePickerValue, setDatePickerValue] = useState<RangeValue>()
/** 时间范围变化 */
const handleTimeRangeChange = (timeRange: TimeRange) => {
selectCallback(timeRange)
}
return (
<div>
<TimeRangeSelector
labelSize="small"
customClassNames={customClassNames}
initialTimeButton={timeButton}
onTimeButtonChange={setTimeButton}
initialDatePickerValue={datePickerValue}
onTimeRangeChange={handleTimeRangeChange}
/>
</div>
)
}
export default DateSelectFilter
@@ -1,88 +0,0 @@
import { Button, Card } from 'antd'
import { useEffect, useState } from 'react'
import { $t } from '@common/locales'
import { useNavigate } from 'react-router-dom'
import { Icon } from '@iconify/react/dist/iconify.js'
/** 服务指标 */
type IndicatorType = {
title: string
link?: string
content: string | React.ReactNode
}
const Indicator = ({ indicatorInfo }: { indicatorInfo: any }) => {
/** 服务指标 */
const [indicatorList, setIndicator] = useState<IndicatorType[]>([])
/** 路由跳转 */
const navigateTo = useNavigate()
/** 设置服务指标 */
const setIndicatorList = () => {
const side = indicatorInfo?.serviceKind === 'ai' ? 'aiInside' : 'inside'
setIndicator([
{
title: indicatorInfo?.enableMcp ? 'APIs / Tools' : 'APIs',
link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/route`,
content: indicatorInfo?.apiNum ?? 0
},
{
title: $t('订阅数量'),
link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/subscriber`,
content: indicatorInfo?.subscriberNum ?? 0
},
{
title: 'MCP',
link: `/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/setting`,
content: (
<>
<Button
color={indicatorInfo?.enableMcp ? 'green' : 'primary'}
className="w-full rounded-[10px]"
variant="outlined"
onClick={(e) => {
e.stopPropagation()
navigateTo(`/service/${indicatorInfo?.teamId}/${side}/${indicatorInfo?.serviceId}/setting`)
}}
>
{indicatorInfo?.enableMcp ? $t('已开启') : $t('开启 MCP')}
</Button>
</>
)
}
])
}
useEffect(() => {
if (!indicatorInfo) return
setIndicatorList()
}, [indicatorInfo])
return (
<div className="flex">
{indicatorList.map((item, index) => (
<Card
key={index}
className={`flex-1 cursor-pointer rounded-[10px] ${index > 0 ? 'ml-[10px]' : ''}`}
classNames={{
body: 'py-[20px] px-[18px]'
}}
onClick={() => {
if (item.link) {
navigateTo(item.link)
}
}}
>
<div className="text-[14px] text-[#999999] mb-[10px]" style={{ fontFamily: 'Microsoft YaHei' }}>
{item.title}
{item.link && <Icon icon="uiw:right" width="16" height="16" className="absolute top-[14px] right-[14px]" />}
</div>
<div className={`${index < 2 ? 'text-[32px] font-medium text-[#101010]' : 'block mt-[30px]'}`} style={{ fontFamily: 'Microsoft YaHei' }}>
{item.content}
</div>
</Card>
))}
</div>
)
}
export default Indicator
@@ -1,96 +0,0 @@
import { useMemo, useRef, useEffect } from 'react'
import PageList from '@common/components/aoplatform/PageList'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
import { $t } from '@common/locales/index.ts'
import { Card } from 'antd'
import { AI_SERVICE_TOP_RANKING_LIST, REST_SERVICE_TOP_RANKING_LIST } from '@core/const/system/const'
interface RankingListData {
[key: string]: Array<{
id: string;
name: string;
request: number;
token?: number;
traffic?: number;
}>;
}
interface PageListRef {
reload: () => void;
[key: string]: any;
}
/**
*
* @returns
*/
const RankingList = ({ topRankingList, serviceType }: { topRankingList: RankingListData; serviceType: 'aiService' | 'restService' }) => {
/** 全局状态 */
const { state } = useGlobalContext()
/** 表格 ref */
const tableRefs = useRef<{ [key: string]: PageListRef | null }>({});
/** 列 */
const columns = useMemo(() => {
return [...(serviceType === 'aiService' ? AI_SERVICE_TOP_RANKING_LIST : REST_SERVICE_TOP_RANKING_LIST)].map((x) => {
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title
}
})
}, [serviceType, state.language])
/** 监听 serviceType 变化,刷新所有表格 */
useEffect(() => {
// 重新加载所有表格数据
if (Object.keys(tableRefs.current).length > 0) {
Object.values(tableRefs.current).forEach(ref => {
// 如果组件实例存在并且有reload方法
if (ref && typeof ref.reload === 'function') {
ref.reload();
}
});
}
}, [serviceType, topRankingList])
/**
*
* @param item
* @returns
*/
const getTableData = (item: string) => {
return new Promise((resolve, reject) => {
resolve({ data: topRankingList[item], success: true })
})
}
return (
<div className="flex w-full pb-[10px]">
{Object.keys(topRankingList)?.map((item: any, index: number) => (
<Card
key={index}
className={`flex-1 min-w-[430px] h-fit rounded-[10px] ${index > 0 ? 'ml-[10px]' : ''}`}
classNames={{
body: 'p-[15px]'
}}
>
<div className="mb-[10px]">
<span className="text-[14px] text-[#999999]" style={{ fontFamily: 'Microsoft YaHei' }}>{item === 'TOP API' ? $t('API 使用排名') : $t('消费者使用排名')}</span>
</div>
<PageList
id={item}
columns={[...columns]}
minVirtualHeight={430}
noScroll
request={() => getTableData(item)}
showPagination={false}
tableClass="ranking-list"
ref={ref => {
if (ref) tableRefs.current[item] = ref;
}}
/>
</Card>
))}
</div>
)
}
export default RankingList
@@ -1,428 +0,0 @@
import { Card, Spin } from 'antd'
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { $t } from '@common/locales/index.ts'
import Indicator from './indicator/Indicator'
import { LoadingOutlined } from '@ant-design/icons'
import DateSelectFilter, { TimeOption } from './filter/DateSelectFilter'
import { TimeRange } from '@common/components/aoplatform/TimeRangeSelector'
import ServiceBarChar, { BarChartInfo } from './charts/ServiceBarChar'
import { useFetch } from '@common/hooks/http'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { App } from 'antd'
import ServiceAreaChart from './charts/ServiceAreaChart'
import RankingList from './rankingList/RankingList'
import { abbreviateFloat, formatBytes, formatDuration, formatNumberWithUnit, getTime } from '@dashboard/utils/dashboard'
import { setBarChartInfoData } from './utils'
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restService' }) => {
/** 路由参数 */
const { serviceId, teamId } = useParams<{ serviceId: string; teamId: string }>()
/** 面板 loading */
const [dashboardLoading, setDashboardLoading] = useState(true)
/** 默认时间 */
const [defaultTime] = useState<TimeOption>('day')
/** 当前选中的时间范围 */
const [timeRange, setTimeRange] = useState<TimeRange | undefined>()
/** 总数数据 */
const [barChartInfo, setBarChartInfo] = useState<any>()
/** 平均值数据 */
const [perBarChartInfo, setPerBarChartInfo] = useState<any>()
/** 指标数据 */
const [indicatorInfo, setIndicatorInfo] = useState<any>([])
/** 排名表格数据 */
const [topRankingList, setTopRankingList] = useState<any>([])
/** 获取服务信息 */
const { fetchData } = useFetch()
/** 弹窗组件 */
const { message } = App.useApp()
/** 全局状态 */
const { state } = useGlobalContext()
/** AI 服务数据 */
const [aiServiceOverview, setAiServiceOverview] = useState<any>()
/** REST 服务数据 */
const [restServiceOverview, setRestServiceOverview] = useState<any>()
/** 时间选择回调 */
const selectCallback = (date: TimeRange) => {
setTimeRange(date)
}
/** 获取 AI 服务信息 */
const getAIServiceOverview = () => {
fetchData<BasicResponse<{ overview: any }>>('service/overview/monitor/ai', {
method: 'GET',
eoParams: { service: serviceId, team: teamId, start: timeRange?.start, end: timeRange?.end },
eoTransformKeys: [
'enable_mcp',
'subscriber_num',
'api_num',
'service_kind',
'avaliable_monitor',
'request_overview',
'token_overview',
'avg_token_overview',
'avg_request_per_subscriber_overview',
'avg_token_per_subscriber_overview',
'request_total',
'token_total',
'avg_token',
'max_token',
'min_token',
'avg_request_per_subscriber',
'avg_token_per_subscriber',
'input_token',
'output_token',
'total_token',
'request_2xx_total',
'request_4xx_total',
'request_5xx_total',
'input_token_total',
'output_token_total',
'max_token_per_subscriber',
'min_token_per_subscriber',
'max_request_per_subscriber',
'min_request_per_subscriber'
]
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 存储 AI 服务数据
setAiServiceOverview(data.overview)
// 设置 AI 报表数据
setAiChartInfoData(data.overview)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
setDashboardLoading(false)
})
}
/**
* REST
* */
const setRestChartInfoData = (serviceOverview: any) => {
// 设置指标数据
setIndicatorInfo({
apiNum: serviceOverview.apiNum,
subscriberNum: serviceOverview.subscriberNum,
teamId: teamId,
enableMcp: serviceOverview.enableMcp,
serviceKind: serviceOverview.serviceKind,
serviceId: serviceId
})
// 设置总数数据
setBarChartInfo([
// 服务请求次数
{
...setBarChartInfoData({
title: $t('请求次数'),
data: serviceOverview.requestOverview,
value: formatNumberWithUnit(serviceOverview.requestTotal),
date: serviceOverview.date
}),
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
},
// 流量消耗总数
{
...setBarChartInfoData({
title: $t('网络流量'),
data: serviceOverview.trafficOverview,
value: formatBytes(serviceOverview.trafficTotal),
date: serviceOverview.date
}),
traffic2xxTotal: formatBytes(serviceOverview.traffic2xxTotal),
traffic4xxTotal: formatBytes(serviceOverview.traffic4xxTotal),
traffic5xxTotal: formatBytes(serviceOverview.traffic5xxTotal)
}
])
// 设置平均值数据
setPerBarChartInfo([
// 各个模型使用量
{
title: $t('平均响应时间'),
data: serviceOverview.avgResponseTimeOverview,
value: formatDuration(serviceOverview.avgResponseTime),
originValue: serviceOverview.avgResponseTime,
date: serviceOverview.date,
max: formatDuration(serviceOverview.maxResponseTime),
min: formatDuration(serviceOverview.minResponseTime),
type: 'area',
showXAxis: false
},
// 平均请求
{
...setBarChartInfoData({
title: $t('平均每消费者的请求次数'),
data: serviceOverview.avgRequestPerSubscriberOverview,
date: serviceOverview.date,
showXAxis: false
}),
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
},
// 平均流量消耗
{
...setBarChartInfoData({
title: $t('平均每消费者的网络流量'),
data: serviceOverview.avgTrafficPerSubscriberOverview,
date: serviceOverview.date,
showXAxis: false
}),
max: formatBytes(serviceOverview.maxTrafficPerSubscriber),
min: formatBytes(serviceOverview.minTrafficPerSubscriber)
}
])
}
/**
* AI
* */
const setAiChartInfoData = (serviceOverview: any) => {
// 设置指标数据
setIndicatorInfo({
apiNum: serviceOverview.apiNum,
subscriberNum: serviceOverview.subscriberNum,
teamId: teamId,
enableMcp: serviceOverview.enableMcp,
serviceKind: serviceOverview.serviceKind,
serviceId: serviceId
})
// 设置总数数据
setBarChartInfo([
// 服务请求次数
{
...setBarChartInfoData({
title: $t('请求次数'),
data: serviceOverview.requestOverview,
value: formatNumberWithUnit(serviceOverview.requestTotal),
date: serviceOverview.date
}),
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
},
// token 消耗总数
{
...setBarChartInfoData({
title: $t('Token 消耗'),
data: serviceOverview.tokenOverview.map((item: { inputToken: number; outputToken: number }) => ({
inputToken: item.inputToken,
outputToken: item.outputToken
})),
value: formatNumberWithUnit(serviceOverview.tokenTotal),
date: serviceOverview.date
}),
inputTokenTotal: formatNumberWithUnit(serviceOverview.inputTokenTotal),
outputTokenTotal: formatNumberWithUnit(serviceOverview.outputTokenTotal)
}
])
// 设置平均值数据
setPerBarChartInfo([
// 平均 token 消耗
{
title: $t('平均 Token 消耗'),
data: serviceOverview.avgTokenOverview,
value: formatNumberWithUnit(serviceOverview.avgToken) + ' Token/s',
originValue: serviceOverview.avgToken,
date: serviceOverview.date,
min: formatNumberWithUnit(serviceOverview.minToken) + ' Token/s',
max: formatNumberWithUnit(serviceOverview.maxToken) + ' Token/s',
type: 'area'
},
{
// 平均请求
...setBarChartInfoData({
title: $t('平均每消费者的请求次数'),
data: serviceOverview.avgRequestPerSubscriberOverview,
date: serviceOverview.date
}),
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
},
// 评价 token 消耗
{
...setBarChartInfoData({
title: $t('平均每消费者的 Token 消耗'),
data: serviceOverview.avgTokenPerSubscriberOverview.map(
(item: { inputToken: number; outputToken: number }) => ({
inputToken: item.inputToken,
outputToken: item.outputToken
})
),
date: serviceOverview.date
}),
max: abbreviateFloat(serviceOverview.maxTokenPerSubscriber),
min: abbreviateFloat(serviceOverview.minTokenPerSubscriber)
}
])
}
/** 获取 REST 服务信息 */
const getRestServiceOverview = () => {
fetchData<BasicResponse<{ overview: any }>>('service/overview/monitor/rest', {
method: 'GET',
eoParams: { service: serviceId, team: teamId, start: timeRange?.start, end: timeRange?.end },
eoTransformKeys: [
'enable_mcp',
'subscriber_num',
'api_num',
'service_kind',
'avaliable_monitor',
'request_overview',
'traffic_overview',
'avg_request_per_subscriber_overview',
'avg_response_time_overview',
'avg_traffic_per_subscriber_overview',
'request_total',
'traffic_total',
'max_response_time',
'min_response_time',
'avg_response_time',
'avg_request_per_subscriber',
'avg_traffic_per_subscriber',
'request_2xx_total',
'request_4xx_total',
'request_5xx_total',
'traffic_2xx_total',
'traffic_4xx_total',
'traffic_5xx_total',
'max_request_per_subscriber',
'min_request_per_subscriber',
'max_traffic_per_subscriber',
'min_traffic_per_subscriber'
]
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 存储 REST 服务数据
setRestServiceOverview(data.overview)
// 设置 REST 报表数据
setRestChartInfoData(data.overview)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
setDashboardLoading(false)
})
}
/** 获取排名列表 */
const getTopRankingList = () => {
fetchData<BasicResponse<{ overview: any }>>('service/monitor/top10', {
method: 'GET',
eoParams: { service: serviceId, team: teamId, start: timeRange?.start, end: timeRange?.end }
}).then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 设置排名表格数据
setTopRankingList({
'TOP API': data.apis,
'TOP Consumer': data.consumers
})
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
setDashboardLoading(false)
})
}
useEffect(() => {
const { startTime, endTime } = getTime(defaultTime, [])
setTimeRange({
start: startTime,
end: endTime
})
}, [])
useEffect(() => {
if (timeRange) {
serviceType === 'aiService' ? getAIServiceOverview() : getRestServiceOverview()
getTopRankingList()
}
}, [timeRange])
useEffect(() => {
if (serviceType === 'aiService') {
aiServiceOverview && setAiChartInfoData(aiServiceOverview)
} else {
restServiceOverview && setRestChartInfoData(restServiceOverview)
}
}, [state.language])
return (
<Spin
className="h-full pb-[20px]"
wrapperClassName="h-full min-h-[150px]"
indicator={
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ transform: 'scale(1.5)' }}>
<LoadingOutlined style={{ fontSize: 30 }} spin />
</div>
</div>
}
spinning={dashboardLoading}
>
<div className="mr-[30px]">
<Indicator indicatorInfo={indicatorInfo} />
<div className="mt-[20px]">
<DateSelectFilter selectCallback={selectCallback} defaultTime={defaultTime} />
</div>
<div className="mt-[20px] flex mb-[10px]">
{barChartInfo?.map((item: BarChartInfo, index: number) => (
<Card
key={index}
className={`flex-1 min-w-[430px] rounded-[10px] ${index > 0 ? 'ml-[10px]' : ''}`}
classNames={{
body: 'py-[15px] px-[0px]'
}}
>
<ServiceBarChar
showLegendIndicator={true}
key={index}
height={400}
dataInfo={item}
customClassNames="flex-1"
></ServiceBarChar>
</Card>
))}
</div>
<div className="flex mb-[10px]">
{perBarChartInfo?.map((item: any, index: number) => (
<Card
key={index}
className={`flex-1 rounded-[10px] min-w-[284px] ${index > 0 ? 'ml-[10px]' : ''}`}
classNames={{
body: 'py-[15px] px-[0px]'
}}
>
{item.type === 'area' ? (
<>
<ServiceAreaChart
key={index}
height={270}
dataInfo={item}
showAvgLine={true}
customClassNames="flex-1 relative"
></ServiceAreaChart>
</>
) : (
<ServiceBarChar
key={index}
height={270}
dataInfo={item}
hideIndicatorValue={true}
customClassNames="flex-1"
></ServiceBarChar>
)}
</Card>
))}
</div>
<RankingList topRankingList={topRankingList} serviceType={serviceType} />
</div>
</Spin>
)
}
export default ServiceOverview
@@ -1,55 +0,0 @@
export type BarData = {
title: string
value?: string
date: string[]
data: any[]
showXAxis?: boolean
}
export const setBarChartInfoData = ({ title, value, data, date, showXAxis }: BarData) => {
// 首先获取所有的键名(假设所有对象的键名都一样)
if (data.length === 0) {
return {
title,
value,
date,
data: [],
showXAxis: !!showXAxis
}
}
if (typeof data[0] !== 'object') {
return {
title,
value,
date,
data,
showXAxis: !!showXAxis
}
}
// 从第一个对象中获取所有键名
const keys = Object.keys(data[0])
// 定义颜色映射
const colorMap: Record<string, string> = {
'2xx': '#3ba272',
'4xx': '#ffc404',
'5xx': '#b92325'
}
// 为每个键创建一个数据集
const transformedData = keys.map((key) => {
// 为没有映射颜色的键生成随机颜色
const color = colorMap[key]
return {
name: key,
color: color,
value: data.map((item) => item[key])
}
})
return {
title,
value,
date,
data: transformedData,
showXAxis: !!showXAxis
}
}
@@ -2,6 +2,7 @@ import { LoadingOutlined } from '@ant-design/icons'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { BasicResponse, DELETE_TIPS, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { EntityItem, MemberItem, SimpleTeamItem } from '@common/const/type.ts'
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'
@@ -10,26 +11,14 @@ 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 { MCP_OPTIONS, SERVICE_APPROVAL_OPTIONS } from '@core/const/system/const.tsx'
import { 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,
RadioChangeEvent,
Row,
Select,
Tooltip,
TreeSelect,
Upload
} from 'antd'
import { App, Button, Form, Input, Radio, 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, useOutletContext, useParams } from 'react-router-dom'
import { Link, useLocation, useNavigate, 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'
@@ -48,13 +37,12 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
const { fetchData } = useFetch()
const [teamOptionList, setTeamOptionList] = useState<DefaultOptionType[]>()
const navigate = useNavigate()
const { setBreadcrumb } = useBreadcrumb()
const { setSystemInfo } = useSystemContext()
const [showClassify, setShowClassify] = useState<boolean>(true)
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 } =
@@ -286,7 +274,6 @@ 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))
@@ -353,6 +340,14 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_, ref) => {
if (serviceId !== undefined) {
setOnEdit(true)
getSystemInfo()
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title: $t('设置')
}
])
} else {
getProviderOptionList()
setOnEdit(false)
@@ -364,32 +359,10 @@ 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('删除'),
@@ -414,7 +387,6 @@ 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 (
<>
@@ -468,13 +440,6 @@ 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>
@@ -512,14 +477,10 @@ 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>
</>
@@ -540,8 +501,6 @@ 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)}
@@ -618,8 +577,6 @@ 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)}
@@ -18,6 +18,7 @@ const ServiceInsideDocument = () => {
const [doc, setDoc] = useState<string>()
const { fetchData } = useFetch()
const { serviceId, teamId } = useParams<RouterParams>()
const save = () => {
fetchData<
BasicResponse<{
@@ -14,8 +14,6 @@ import { FC, useEffect, useMemo, useState } from 'react'
import { Link, Outlet, useLocation, useNavigate, useParams } from 'react-router-dom'
import { SystemConfigFieldType } from '../../const/system/type.ts'
import { useSystemContext } from '../../contexts/SystemContext.tsx'
import ServiceInfoCard from '@common/components/aoplatform/serviceInfoCard.tsx'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
const SystemInsidePage: FC = () => {
const { message } = App.useApp()
@@ -28,13 +26,12 @@ const SystemInsidePage: FC = () => {
const [activeMenu, setActiveMenu] = useState<string>()
const navigateTo = useNavigate()
const [showMenu, setShowMenu] = useState<boolean>(false)
const { setBreadcrumb } = useBreadcrumb()
const getSystemInfo = () => {
fetchData<BasicResponse<{ service: SystemConfigFieldType }>>('service/info', {
method: 'GET',
eoParams: { team: teamId, service: serviceId }
}).then((response) => {
}).then(response => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setSystemInfo(data.service)
@@ -50,7 +47,7 @@ const SystemInsidePage: FC = () => {
fetchData<BasicResponse<{ prefix: string; force: boolean }>>('service/router/define', {
method: 'GET',
eoParams: { service: serviceId, team: teamId }
}).then((response) => {
}).then(response => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
setApiPrefix(data.prefix)
@@ -68,7 +65,6 @@ const SystemInsidePage: FC = () => {
'assets',
null,
[
getItem(<Link to="./overview">{$t('总览')}</Link>, 'overview', undefined, undefined, undefined, ''),
getItem(
<Link to="./route">{$t('API 路由')}</Link>,
'route',
@@ -150,10 +146,9 @@ const SystemInsidePage: FC = () => {
null,
[
// APP_MODE === 'pro' ? getItem(<Link to="./topology">{$t('调用拓扑图')}</Link>, 'topology',undefined,undefined,undefined,'project.mySystem.topology.view'):null,
getItem(<Link to="./setting">{$t('设置')}</Link>, 'setting', undefined, undefined, undefined, ''),
getItem(
<Link to="./logs">{$t('日志')}</Link>,
'logs',
<Link to="./setting">{$t('设置')}</Link>,
'setting',
undefined,
undefined,
undefined,
@@ -171,11 +166,12 @@ const SystemInsidePage: FC = () => {
const newMenu = cloneDeep(menu)
return newMenu!.filter((m: MenuItemGroupType) => {
if (m && m.children && m.children.length > 0) {
m.children = m.children.filter((c) => {
m.children = m.children.filter(c => {
if (!c) return false
return (c as MenuItemType & { access: string }).access
? checkPermission(
(c as MenuItemType & { access: string }).access as keyof (typeof PERMISSION_DEFINITION)[0]
(c as MenuItemType & { access: string })
.access as keyof (typeof PERMISSION_DEFINITION)[0]
)
: true
})
@@ -184,8 +180,12 @@ const SystemInsidePage: FC = () => {
})
}
const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType<MenuItemType>[])
const menu = (activeMenu ?? filteredMenu[0]?.children) ? filteredMenu[0]?.children?.[0]?.key : filteredMenu[0]?.key
if (menu && currentUrl.split('/')[-1] !== menu) navigateTo(`/service/${teamId}/inside/${serviceId}/${menu}`)
const menu =
(activeMenu ?? filteredMenu[0]?.children)
? filteredMenu[0]?.children?.[0]?.key
: filteredMenu[0]?.key
if (menu && currentUrl.split('/')[-1] !== menu)
navigateTo(`/service/${teamId}/inside/${serviceId}/${menu}`)
return filteredMenu || []
}, [accessData, accessInit, SYSTEM_PAGE_MENU_ITEMS])
@@ -208,7 +208,7 @@ const SystemInsidePage: FC = () => {
} else if (serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]) {
setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1])
} else {
setActiveMenu('overview')
setActiveMenu('route')
}
}, [currentUrl])
@@ -219,19 +219,10 @@ const SystemInsidePage: FC = () => {
}, [accessData])
useEffect(() => {
setBreadcrumb([
{
title: $t('服务'),
onClick: () => navigateTo('/service/list')
},
{
title: systemInfo?.name || ''
}
])
if (activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]) {
navigateTo(`/service/${teamId}/inside/${serviceId}/${activeMenu}`)
}
}, [activeMenu, systemInfo, state.language])
}, [activeMenu])
useEffect(() => {
serviceId && getSystemInfo()
@@ -242,7 +233,15 @@ const SystemInsidePage: FC = () => {
{showMenu ? (
<InsidePage
pageTitle={systemInfo?.name || '-'}
customBanner={<ServiceInfoCard serviceId={serviceId} teamId={teamId} />}
tagList={[
{
label: (
<Paragraph className="mb-0" copyable={serviceId ? { text: serviceId } : false}>
{$t('服务 ID')}{serviceId || '-'}
</Paragraph>
)
}
]}
backUrl="/service/list"
>
<div className="flex flex-1 h-full">
@@ -11,6 +11,7 @@ import {
STATUS_CODE
} from '@common/const/const.tsx'
import { SimpleMemberItem } from '@common/const/type.ts'
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'
@@ -19,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 { useParams } from 'react-router-dom'
import { Link, useParams } from 'react-router-dom'
import { SYSTEM_SUBSCRIBER_TABLE_COLUMNS } from '../../const/system/const.tsx'
import {
SimpleSystemItem,
@@ -30,6 +31,7 @@ import {
} from '../../const/system/type.ts'
const SystemInsideSubscriber: FC = () => {
const { setBreadcrumb } = useBreadcrumb()
const { modal, message } = App.useApp()
const { fetchData } = useFetch()
const { serviceId, teamId } = useParams<RouterParams>()
@@ -159,6 +161,14 @@ const SystemInsideSubscriber: FC = () => {
]
useEffect(() => {
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title: $t('订阅方管理')
}
])
getMemberList()
manualReloadTable()
}, [serviceId])
@@ -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, Tag } from 'antd'
import { App } 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,30 +176,10 @@ const SystemList: FC = () => {
x.valueEnum = teamList
}
if ((x.dataIndex as string) === 'service_kind') {
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>
)
x.valueEnum = {}
SERVICE_KIND_OPTIONS.forEach((option) => {
;(x.valueEnum as any)[option.value] = { text: $t(option.label) }
})
}
if ((x.dataIndex as string) === 'state') {
x.render = (dom: React.ReactNode, record: any) => (
@@ -2,6 +2,7 @@ import { ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons'
import G6, { EdgeConfig, Graph, NodeConfig } from '@antv/g6'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { EntityItem } from '@common/const/type'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext'
import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import { getNodeSpacing } from '@common/utils/systemRunning'
@@ -9,7 +10,7 @@ import { RouterParams } from '@core/components/aoplatform/RenderRoutes'
import { App, Button } from 'antd'
import { debounce } from 'lodash-es'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useParams } from 'react-router-dom'
import { Link, useParams } from 'react-router-dom'
import { RELATIVE_PICTURE_NODE_FONTSIZE } from '../../const/system-running/const'
import { GraphData } from '../../const/system-running/type'
import { SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP } from '../../const/system/const'
@@ -25,9 +26,9 @@ export default function SystemTopology() {
const [graph, setGraph] = useState<Graph | null>(null)
const { fetchData } = useFetch()
const { systemInfo } = useSystemContext()
const { setBreadcrumb } = useBreadcrumb()
const [zoomNum, setZoomNum] = useState<number>(1)
const getNodeData = () => {
fetchData<BasicResponse<SystemTopologyResponse>>('service/topology', {
method: 'GET',
@@ -102,6 +103,14 @@ export default function SystemTopology() {
useEffect(() => {
getNodeData()
setBreadcrumb([
{
title: <Link to={`/service/list`}>{$t('服务')}</Link>
},
{
title: $t('调用拓扑图')
}
])
}, [serviceId])
useEffect(() => {

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