Compare commits

...

93 Commits

Author SHA1 Message Date
maggieyyy b216556867 fix: Modify service inside access 2024-11-04 10:44:30 +08:00
maggieyyy c9ae05b22e fix: Modify link access 2024-11-01 18:41:16 +08:00
maggieyyy e31d41a276 fix: Modify consumer list reload and subscriber option 2024-11-01 16:42:34 +08:00
maggieyyy 0e20987fb8 fix: Add team selector to consumer 2024-11-01 15:48:51 +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
maggieyyy fa2607e9b8 fix: consumer menu access bug 2024-11-01 14:45:32 +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
maggieyyy 64fdf59905 fix: Add empty to member transfer 2024-11-01 13:54:33 +08:00
maggieyyy 2dcb7ebd74 fix: Modify subscribe options 2024-10-31 14:14:44 +08:00
maggieyyy d6bf3139ff fix: delete log 2024-10-31 09:14:24 +08:00
maggieyyy d5e6062ec9 fix: Modify access 2024-10-30 18:38:39 +08:00
maggieyyy 9030cff8ba fix: Modify local path 2024-10-29 18:32:45 +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
maggieyyy 2b7c1ded15 fix: Add psw to account 2024-10-29 16:44:31 +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
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
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
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
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
Maggie 0d737bad57 Merge pull request #111 from APIParkLab/feature/v1.2
Feature/v1.2
2024-10-28 16:22:58 +08:00
maggieyyy e5d85bb3df fix: Modify access fields 2024-10-28 16:15:38 +08:00
maggieyyy 0f0204b647 fix: cosumer list bug 2024-10-28 16:00:15 +08:00
maggieyyy 44f0b70461 fix: Consumer list bugs 2024-10-28 15:44:10 +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
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
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
Liujian 9592a0ddda Merge remote-tracking branch 'origin/main' into feature/ai-service 2024-10-23 18:41:14 +08:00
122 changed files with 1366 additions and 1280 deletions
+3 -3
View File
@@ -25,7 +25,7 @@ jobs:
echo "Build frontend..."
cd ./frontend && pnpm run build
- name: upload frontend release
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: frontend-package
path: frontend/dist
@@ -41,7 +41,7 @@ jobs:
- name: Checkout #Checkout代码
uses: actions/checkout@v3
- name: download frontend release
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: frontend-package
path: frontend/dist
@@ -71,7 +71,7 @@ jobs:
- uses: actions/checkout@v3
- name: download frontend release
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: frontend-package
path: frontend/dist
-1
View File
@@ -3,4 +3,3 @@
/config.yml
/build/
/apipark
/aoplatform
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
<![CDATA[
.st0{fill:#000000;}
]]>
</style>
<g>
<path class="st0" d="M485.016,220.691c12.422-8.422,22.188-57.266,7.797-87.016c-26.859,28.125-80.109,49.859-142,72.922
c-64.656,24.078-71.531,41.859-94.813,42.172c-23.297-0.313-30.156-18.094-94.813-42.172c-61.891-23.063-115.141-44.797-142-72.922
c-14.406,29.75-4.625,78.594,7.781,87.016C13.484,214.332,0,210.051,0,210.051s3.813,68.172,33.25,106.563
c24.953,32.547,86.984,72.906,145.828,58.828c62.219-14.875,62.344-41.406,76.922-41.266c14.563-0.141,14.688,26.391,76.906,41.266
c58.844,14.078,120.875-26.281,145.844-58.828C508.156,278.223,512,210.051,512,210.051S498.5,214.332,485.016,220.691z
M131.438,318.848c-25.109-11.641-46.063-37.422-43.188-73.891c12.813,5.078,48.844,9.406,69.094,17.281
c23,8.953,46.031,23.984,48.922,41.25C205.313,317.879,170.75,337.066,131.438,318.848z M380.563,318.848
c-39.344,18.219-73.875-0.969-74.828-15.359c2.891-17.266,25.891-32.297,48.922-41.25c20.25-7.875,56.281-12.203,69.094-17.281
C426.625,281.426,405.656,307.207,380.563,318.848z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
<![CDATA[
.st0{fill:#000000;}
]]>
</style>
<g>
<path class="st0" d="M485.016,220.691c12.422-8.422,22.188-57.266,7.797-87.016c-26.859,28.125-80.109,49.859-142,72.922
c-64.656,24.078-71.531,41.859-94.813,42.172c-23.297-0.313-30.156-18.094-94.813-42.172c-61.891-23.063-115.141-44.797-142-72.922
c-14.406,29.75-4.625,78.594,7.781,87.016C13.484,214.332,0,210.051,0,210.051s3.813,68.172,33.25,106.563
c24.953,32.547,86.984,72.906,145.828,58.828c62.219-14.875,62.344-41.406,76.922-41.266c14.563-0.141,14.688,26.391,76.906,41.266
c58.844,14.078,120.875-26.281,145.844-58.828C508.156,278.223,512,210.051,512,210.051S498.5,214.332,485.016,220.691z
M131.438,318.848c-25.109-11.641-46.063-37.422-43.188-73.891c12.813,5.078,48.844,9.406,69.094,17.281
c23,8.953,46.031,23.984,48.922,41.25C205.313,317.879,170.75,337.066,131.438,318.848z M380.563,318.848
c-39.344,18.219-73.875-0.969-74.828-15.359c2.891-17.266,25.891-32.297,48.922-41.25c20.25-7.875,56.281-12.203,69.094-17.281
C426.625,281.426,405.656,307.207,380.563,318.848z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,30 @@
provider: fakegpt
label:
en_US: FakeGPT
description:
en_US: FakeGPT is a fake model provider that does not actually connect to any model service. It is useful for testing and development purposes.
icon_small:
en_US: icon_s_en.svg
icon_large:
en_US: icon_l_en.svg
background: "#FCFDFF"
help:
title:
en_US: Get your Access Details from Google
url:
en_US: https://apipark.com
supported_model_types:
- llm
- text-embedding
configurate_methods:
- predefined-model
provider_credential_schema:
credential_form_schemas:
- variable: apikey
label:
en_US: API Key
type: secret-input
required: true
placeholder:
en_US: Enter your API key
address: https://apipark.com
@@ -0,0 +1,51 @@
model: fakegpt-1.0
label:
en_US: FakeGPT 1.0
model_type: llm
features:
- agent-thought
- vision
model_properties:
mode: chat
context_size: 200000
parameter_rules:
- name: max_tokens
use_template: max_tokens
required: true
type: int
default: 4096
min: 1
max: 4096
help:
zh_Hans: 停止前生成的最大令牌数。
en_US: The maximum number of tokens to generate before stopping.
- name: temperature
use_template: temperature
required: false
type: float
default: 1
min: 0.0
max: 1.0
help:
zh_Hans: 生成内容的随机性。
en_US: The amount of randomness injected into the response.
- name: top_p
required: false
type: float
default: 0.999
min: 0.000
max: 1.000
help:
zh_Hans: 在核采样中,按概率递减顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。您应该更改温度或top_p,但不能同时更改两者。
en_US: In nucleus sampling, computes the cumulative distribution over all the options for each subsequent token in decreasing probability order and cuts it off once it reaches a particular probability specified by top_p. You should alter either temperature or top_p, but not both.
- name: top_k
required: false
type: int
default: 0
min: 0
# tip docs from aws has error, max value is 500
max: 500
help:
zh_Hans: 对于每个后续标记,仅从前 K 个选项中进行采样。使用 top_k 删除长尾低概率响应。
en_US: Only sample from the top K options for each subsequent token. Use top_k to remove long tail low probability responses.
@@ -69,15 +69,6 @@ provider_credential_schema:
placeholder:
zh_Hans: 在此输入您的 API Key
en_US: Enter your API Key
- variable: openai_organization
label:
zh_Hans: 组织 ID
en_US: Organization
type: text-input
required: false
placeholder:
zh_Hans: 在此输入您的组织 ID
en_US: Enter your Organization ID
- variable: openai_api_base
label:
zh_Hans: API Base
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 2048
@@ -23,7 +23,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
@@ -24,7 +24,7 @@ parameter_rules:
use_template: presence_penalty
- name: frequency_penalty
use_template: frequency_penalty
- name: max_output_tokens
- name: max_tokens
use_template: max_tokens
required: true
default: 8192
+3 -2
View File
@@ -151,8 +151,9 @@ func (i *imlServiceController) createAIService(ctx *gin.Context, teamID string,
Prompt: "You need to translate {{source_lang}} into {{target_lang}}, and the following is the content that needs to be translated.\n---\n{{text}}",
}
aiModel := &ai_api_dto.AiModel{
Id: m.ID(),
Config: m.DefaultConfig(),
Id: m.ID(),
Config: m.DefaultConfig(),
Provider: *input.Provider,
}
name := "Demo Translation API"
description := "A demo that shows you how to use a prompt to create a Translation API."
+7 -6
View File
@@ -319,12 +319,12 @@ func (i *imlInitController) OnInit() {
}
func (i *imlInitController) createAIService(ctx context.Context, teamID string, input *service_dto.CreateService) error {
providerId := "openai"
err := i.providerModule.UpdateProviderConfig(ctx, "openai", &ai_dto.UpdateConfig{
Config: "{\n \"openai_api_base\": \"API Base\",\n \"openai_api_key\": \"API Key\",\n \"openai_organization\": \"Organization\"\n}",
providerId := "fakegpt"
err := i.providerModule.UpdateProviderConfig(ctx, providerId, &ai_dto.UpdateConfig{
Config: "{\n \"apikey\": \"xxx\" \n}",
})
if err != nil {
return fmt.Errorf("update openai config error: %v", err)
return fmt.Errorf("update %s config error: %v", providerId, err)
}
input.Provider = &providerId
if input.Id == "" {
@@ -381,8 +381,9 @@ func (i *imlInitController) createAIService(ctx context.Context, teamID string,
Prompt: "You need to translate {{source_lang}} into {{target_lang}}, and the following is the content that needs to be translated.\n---\n{{text}}",
}
aiModel := &ai_api_dto.AiModel{
Id: m.ID(),
Config: m.DefaultConfig(),
Id: m.ID(),
Config: m.DefaultConfig(),
Provider: providerId,
}
name := "Demo Translation API"
description := "A demo that shows you how to use a prompt to create a Translation API."
+1
View File
@@ -27,4 +27,5 @@ packages/core/public/tinymce/
*.sln
*.sw?
/pnpm-lock.yaml
+12 -5
View File
@@ -1,10 +1,17 @@
# 部署
## 安装依赖
建议使用pnpm
`npm install -g pnpm`
使用pnpm安装依赖
`pnpm install`
建议使用 pnpm
```
npm install -g pnpm
```
使用pnpm安装依赖
```
pnpm install
```
## 编译
`pnpm run build`
```
pnpm run build
```
+1 -8
View File
@@ -1,10 +1,3 @@
/*
* @Date: 2024-05-10 14:19:56
* @LastEditors: maggieyyy
* @LastEditTime: 2024-05-10 15:55:29
* @FilePath: \frontend\jest.config.js
*/
module.exports = {
roots: ['<rootDir>/packages'],
testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'],
@@ -15,4 +8,4 @@ module.exports = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};
};
+1 -7
View File
@@ -1,7 +1 @@
/*
* @Date: 2024-05-10 14:22:41
* @LastEditors: maggieyyy
* @LastEditTime: 2024-05-10 15:49:31
* @FilePath: \frontend\jest.setup.js
*/
// import '@testing-library/jest-dom/extend-expect';
// import '@testing-library/jest-dom/extend-expect';
+1
View File
@@ -3,4 +3,5 @@
"packages/*"
],
"version": "independent"
}
@@ -6,7 +6,6 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/frontend/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>APIPark - 企业API数据开放平台</title>
<title>2APIPark</title>
</head>
<body>
<div id="root"></div>
+1 -1
View File
@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": " vite --port 5000 --strictPort",
"dev": " vite --port 5000 --strictPort",
"build": "vite build ",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview --port 5000 --strictPort",
@@ -1,9 +1,3 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:42:18
* @FilePath: \frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,9 +1,4 @@
/*
* @Date: 2024-06-05 09:35:25
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:50:12
* @FilePath: \frontend\packages\core\start-vite.js
*/
// start-vite.js// start-vite.js
import { exec } from 'child_process';
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2023-11-29 15:49:05
* @FilePath: \applatform\frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
@@ -1,19 +1,15 @@
import {
ConfigProvider,
Dropdown,
MenuProps,
App,
Button} from 'antd';
Button,
ConfigProvider,
Dropdown} from 'antd';
import { Outlet, useLocation, useNavigate} from "react-router-dom";
import Logo from '@common/assets/layout-logo.png';
import AvatarPic from '@common/assets/default-avatar.png'
import {Outlet, useLocation, useNavigate} from "react-router-dom";
import { useEffect, useMemo, useState} from "react";
import { useEffect, useMemo, useState} from "react";
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx';
import { PERMISSION_DEFINITION } from '@common/const/permissions.ts';
import {
ProConfigProvider,
ProLayout,
} from '@ant-design/pro-components';
import { BasicResponse, RESPONSE_TIPS, routerKeyMap, STATUS_CODE } from '@common/const/const.tsx';
import { UserInfoType } from '@common/const/type.ts';
import { useFetch } from '@common/hooks/http.ts';
@@ -21,6 +17,7 @@ import { ProjectFilled } from '@ant-design/icons';
import { getNavItem } from '@common/utils/navigation';
import { Icon } from '@iconify/react';
import { $t } from '@common/locales';
import { ProConfigProvider, ProLayout } from '@ant-design/pro-components';
import LanguageSetting from './LanguageSetting';
const APP_MODE = import.meta.env.VITE_APP_MODE;
@@ -41,9 +38,8 @@ const themeToken = {
const navigator = useNavigate()
const location = useLocation()
const currentUrl = location.pathname
const { state,accessData,checkPermission,accessInit} = useGlobalContext()
const [pathname, setPathname] = useState(currentUrl);
const mainPage = project === 'core' ?'/service/list':'/serviceHub/list'
const { state,accessData,checkPermission,accessInit,dispatch,resetAccess,getGlobalAccessData} = useGlobalContext()
const [pathname, setPathname] = useState(currentUrl); const mainPage = project === 'core' ?'/service/list':'/serviceHub/list'
const TOTAL_MENU_ITEMS:MenuProps['items'] = useMemo(() => [
getNavItem($t('工作空间'), 'workspace','/guide/page',<Icon icon="ic:baseline-space-dashboard" width="18" height="18"/>, [
@@ -52,27 +48,27 @@ const themeToken = {
getNavItem(<a>{$t('消费者')}</a>, 'consumer','/consumer',<Icon icon="ic:baseline-apps" width="18" height="18"/>,undefined,undefined,'all'),
getNavItem(<a>{$t('团队')}</a>, 'team','/team',<Icon icon="ic:baseline-people-alt" width="18" height="18"/>,undefined,undefined,'all'),
]),
getNavItem($t('API 市场'), 'serviceHub','/serviceHub',<Icon icon="ic:baseline-hub" width="18" height="18"/>,undefined,undefined,'system.workspace.api_market.view'),
getNavItem($t('API 市场'), 'serviceHub','/serviceHub',<Icon icon="ic:baseline-hub" width="18" height="18"/>,undefined,undefined,'system.api_portal.api_portal.view'),
getNavItem($t('仪表盘'), 'mainPage', APP_MODE === 'pro' ? '/analytics' : '/analytics/total',<Icon icon="ic:baseline-bar-chart" width="18" height="18"/>,[
getNavItem(<a >{$t('运行视图')}</a>, 'analytics',APP_MODE === 'pro' ? '/analytics' : '/analytics/total' ,<ProjectFilled />,undefined,undefined,'system.dashboard.run_view.view'),
getNavItem(<a >{$t('运行视图')}</a>, 'analytics',APP_MODE === 'pro' ? '/analytics' : '/analytics/total' ,<ProjectFilled />,undefined,undefined,'system.analysis.run_view.view'),
APP_MODE === 'pro' ? getNavItem(<a >{$t('系统拓扑图')}</a>, 'systemrunning','/systemrunning',<ProjectFilled />,undefined,undefined,'system.dashboard.systemrunning.view') : null,
],undefined,'system.dashboard.run_view.view'),
],undefined,'system.analysis.run_view.view'),
getNavItem($t('系统设置'), 'operationCenter','/commonsetting',<Icon icon="ic:baseline-settings" width="18" height="18"/>, [
getNavItem($t('系统'), 'serviceHubSetting','/commonsetting',null,[
getNavItem(<a>{$t('常规')}</a>, 'commonsetting','/commonsetting',<Icon icon="ic:baseline-hub" width="18" height="18"/>,undefined,undefined,'system.api_market.service_classification.view'),
getNavItem(<a>{$t('API 网关')}</a>, 'cluster','/cluster',<Icon icon="ic:baseline-device-hub" width="18" height="18"/>,undefined,undefined,'system.devops.cluster.view'),
getNavItem(<a>{$t('AI 模型')}</a>, 'aisetting','/aisetting',<Icon icon="hugeicons:ai-network" width="18" height="18"/>,undefined,undefined,'system.devops.cluster.view'),
getNavItem(<a>{$t('API 网关')}</a>, 'cluster','/cluster',<Icon icon="ic:baseline-device-hub" width="18" height="18"/>,undefined,undefined,'system.settings.api_gateway.view'),
getNavItem(<a>{$t('AI 模型')}</a>, 'aisetting','/aisetting',<Icon icon="hugeicons:ai-network" width="18" height="18"/>,undefined,undefined,'system.settings.api_gateway.view'),
],undefined,'system.api_market.service_classification.view'),
getNavItem($t('用户'), 'organization','/member',null,[
getNavItem(<a>{$t('账号')}</a>, 'member','/member',<Icon icon="ic:baseline-people-alt" width="18" height="18"/>,undefined,undefined,'system.organization.member.view'),
getNavItem(<a>{$t('账号')}</a>, 'member','/member',<Icon icon="ic:baseline-people-alt" width="18" height="18"/>,undefined,undefined,'system.settings.account.view'),
getNavItem(<a>{$t('角色')}</a>, 'role','/role',<Icon icon="ic:baseline-verified-user" width="18" height="18"/>,undefined,undefined,'system.organization.role.view'),
],undefined,''),
getNavItem($t('集成'), 'maintenanceCenter','/datasourcing', null, [
getNavItem(<a>{$t('数据源')}</a>, 'datasourcing','/datasourcing',<Icon icon="ic:baseline-monitor-heart" width="18" height="18"/>,undefined,undefined,'system.devops.data_source.view'),
getNavItem(<a>{$t('证书')}</a>, 'cert','/cert',<Icon icon="ic:baseline-security" width="18" height="18"/>,undefined,undefined,'system.devops.ssl_certificate.view'),
getNavItem(<a>{$t('日志')}</a>, 'logsettings','/logsettings',<Icon icon="ic:baseline-sticky-note-2" width="18" height="18"/>,undefined,undefined,'system.devops.log_configuration.view'),
getNavItem(<a>{$t('数据源')}</a>, 'datasourcing','/datasourcing',<Icon icon="ic:baseline-monitor-heart" width="18" height="18"/>,undefined,undefined,'system.settings.data_source.view'),
getNavItem(<a>{$t('证书')}</a>, 'cert','/cert',<Icon icon="ic:baseline-security" width="18" height="18"/>,undefined,undefined,'system.settings.ssl_certificate.view'),
getNavItem(<a>{$t('日志')}</a>, 'logsettings','/logsettings',<Icon icon="ic:baseline-sticky-note-2" width="18" height="18"/>,undefined,undefined,'system.settings.log_configuration.view'),
APP_MODE === 'pro' ? getNavItem(<a>{$t('资源')}</a>, 'resourcesettings','/resourcesettings',null,undefined,undefined,'system.partition.self.view'):null,
APP_MODE === 'pro' ? getNavItem(<a>{$t('Open API')}</a>, 'openapi','/openapi',null,undefined,undefined,'system.openapi.self.view'):null,
]),
@@ -126,7 +122,6 @@ const themeToken = {
const { message } = App.useApp()
const { dispatch,resetAccess,getGlobalAccessData} = useGlobalContext()
const [userInfo,setUserInfo] = useState<UserInfoType>()
const {fetchData} = useFetch()
const navigate = useNavigate();
@@ -163,8 +158,8 @@ const themeToken = {
})
}
const items: MenuProps['items'] = [
{
const items: MenuProps['items'] = useMemo(() => [
userInfo?.type !== 'guest' && {
key: '2',
label: (
<Button key="changePsw" type="text" className="flex items-center p-0 bg-transparent border-none " onClick={()=>navigator('/userProfile/changepsw')}>
@@ -178,7 +173,7 @@ const themeToken = {
{$t('退出登录')}
</Button>)
},
];
].filter(Boolean), [userInfo]);
@@ -248,7 +243,7 @@ const themeToken = {
</div>
)}
logo={Logo}
pageTitleRender={()=>$t('APIPark - 企业API数据开放平台')}
pageTitleRender={()=>$t('APIPark')}
menuFooterRender={(props) => {
if (props?.collapsed) return undefined;
}}
@@ -1,27 +1,23 @@
import { GetProp, TransferProps, TreeDataNode, theme, Transfer, Tree, Spin } from "antd";
import { DataNode, TreeProps } from "antd/es/tree";
import { TransferProps, TreeDataNode, Tree, Spin, Input, Empty } from "antd";
import { DataNode } from "antd/es/tree";
import { Ref, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
import { ApartmentOutlined, LoadingOutlined, UserOutlined } from "@ant-design/icons";
import { cloneDeep, debounce } from "lodash-es";
import { ColumnsType } from "antd/es/table";
import { $t } from "@common/locales";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
type TransferItem = GetProp<TransferProps, 'dataSource'>[number];
export type TransferTableProps<T> = {
request?:(k?:string)=>Promise<{data:T[],success:boolean}>
columns: ColumnsType<T>
primaryKey:string
onSelect:(selectedData:T[])=>void
onSelect:(selectedData:string[])=>void
tableType?:'member'|'api'
disabledData:string[]
searchPlaceholder?:string
}
export type TransferTableHandle<T> = {
selectedData: () => T[];
selectedRowKeys: () => React.Key[];
}
@@ -31,10 +27,6 @@ interface TreeTransferProps {
onChange: TransferProps['onChange'];
}
// Customize Table Transfer
const isChecked = (selectedKeys: React.Key[], eventKey: React.Key) =>
selectedKeys.includes(eventKey);
const generateTree = (
treeNodes: TreeDataNode[] = [],
checkedKeys: TreeTransferProps['targetKeys'] = [],
@@ -73,200 +65,104 @@ const generateTree = (
)
};
const TransferTree = (props)=>{
const { direction, token, tableHeight, dataSource, targetKeys, onItemSelect, onItemSelectAll,checkedKey,selectedKeys, filteredItems ,disabledData} = props;
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
const getExpandedKeys = (newData:TreeDataNode[], expandedSet:Set<string> = new Set())=>{
newData.forEach((item)=>{
if(item.children && item.children.length > 0){
expandedSet.add(item.key)
getExpandedKeys(item.children,expandedSet)
}
})
return expandedSet
}
const treeData:TreeDataNode[] = useMemo(()=>{
const filteredSet = filteredItems && filteredItems.length > 0 ? new Set(filteredItems.map((x)=>x.id)) : new Set()
const res = dataSource && dataSource.length > 0 ? generateTree(dataSource, targetKeys,direction === 'right',disabledData,filteredSet) : []
setExpandedKeys(Array.from(getExpandedKeys(res)))
return res
},[
dataSource, targetKeys,direction ,disabledData,filteredItems
])
const onExpand: TreeProps['onExpand'] = (expandedKeysValue) => {
setExpandedKeys(expandedKeysValue as string[]);
};
return (
<div style={{ padding: token.paddingXS }}>
<Tree
className="icon-tree"
blockNode
checkable
showIcon
checkedKeys={direction === 'left' ? Array.from(new Set([...checkedKey,...disabledData])) : selectedKeys }
defaultExpandAll
expandedKeys={expandedKeys}
onExpand={onExpand}
height={tableHeight}
icon={(props)=> { return (props.type === 'member' ? <UserOutlined /> :<ApartmentOutlined /> )} }
treeData={treeData}
onCheck={(_checkedKeys, e:{checked: boolean, checkedNodes, node, event, halfCheckedKeys}) => {
if(e.checked){
onItemSelectAll( _checkedKeys, e.checked);
}else{
const checkedKeyArrFromTree = e.checkedNodes.map(node => node.key)
onItemSelectAll((checkedKey as string[]).filter(key => checkedKeyArrFromTree.indexOf(key) === -1),e.checked)
}
}}
onSelect={(_, { node: { key } }) => {
onItemSelect(key as string, !isChecked(checkedKey, key));
}}
/>
</div>
)
}
const MemberTransfer= forwardRef<TransferTableHandle<{[k:string]:unknown}>, TransferTableProps<{[k:string]:unknown}>>(
<T extends {[k:string]:unknown}>(props: TransferTableProps<T>, ref:Ref<TransferTableHandle<T>>) => {
const {request,columns,primaryKey,onSelect,tableType,disabledData = [],searchPlaceholder} = props
const [tableHeight, setTableHeight] = useState(window.innerHeight * 80 / 100 - 64 - 72 - 56 - 16 -3);
const [targetKeys, setTargetKeys] = useState<TreeTransferProps['targetKeys']>([]);
const [dataSource, setDataSource] = useState<DataNode[] >([])
const parentRef = useRef<HTMLDivElement>(null);
const [loading, setLoading] = useState<boolean>(false)
const {state} = useGlobalContext()
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
const [searchWord, setSearchWord] = useState<string>('')
useEffect(()=>{
setTargetKeys(disabledData)
},[disabledData])
useImperativeHandle(ref, () =>({
selectedData: () => dataSource,
selectedRowKeys: () => targetKeys,}))
const onChange: TreeTransferProps['onChange'] = (keys) => {
onSelect?.(new Set(keys))
setTargetKeys(Array.from(new Set(keys)));
};
const translatedDataSource = useMemo(()=>{
const loop = (data: DataNode[]): DataNode[] =>
data?.map((item) => {
const strTitle:string = item.name === '所有成员' ? $t(item.name) as string : item.name as string;
const index = strTitle.indexOf(searchWord);
const beforeStr = strTitle.substring(0, index);
const afterStr = strTitle.slice(index + searchWord.length);
const title =
index > -1 ? (
<span className='w-[calc(100%-16px)] truncate' title={strTitle}>
{beforeStr}
<span className="text-theme">{searchWord}</span>
{afterStr}
</span>
) : (
<span className='w-[calc(100%-16px)] truncate' title={`${strTitle}`}>{strTitle}</span>
)
if (item.children) {
return {
...item,
title,
disableCheckbox:disabledData.indexOf(item.key as string) !== -1,
icon:<ApartmentOutlined />,
children: loop(item.children as T[]) };
}
const { token } = theme.useToken();
const transferDataSource: TransferItem[] = useMemo(()=>{
function flatten(list: TreeDataNode[] = [], res:TransferItem[]) {
list.forEach((item) => {
res.push({...item, title:item.title === '所有成员' ? $t((item as unknown as {title:string}).title):item.title }as TransferItem);
flatten(item.children,res);
});
}
const res:TransferItem[] =[]
flatten(dataSource,res);
return res
},[
dataSource, state.language
])
const translatedDataSource = useMemo(()=>dataSource.map((item)=>({
...item,
name:item.name === '所有成员' ? $t((item as unknown as {name:string}).name):item.name,
})),[dataSource, state.language])
let memo: Record<string, boolean> = {};
const handlerFilterOption = (inputValue: string, item: any, parentResult: boolean = false, childrenSet: Set<string> = new Set()): boolean => {
const cacheKey = `${inputValue}_${item.key}`;
if (memo[cacheKey]) {
return memo[cacheKey];
}
childrenSet.add(item.key);
let result = item.title.includes(inputValue) || parentResult
if (item.children) {
for (const child of item.children) {
if (handlerFilterOption(inputValue, child, result,childrenSet)) {
result = true;
}
}
}
if (result) {
memo[cacheKey] = result;
childrenSet.forEach((key) => {
memo[`${inputValue}_${key}`] = result;
return {
...item,
title,
icon:<UserOutlined />,
isLeaf:true,
disableCheckbox:disabledData.indexOf(item.key as string) !== -1
};
});
}
return result;
};
return loop(dataSource);
},[dataSource, state.language, searchWord])
const getInitExpandKeys = (data:T[], expandKeys:string[] = [])=>{
data.forEach((item)=>{
if(item.children?.length){
expandKeys.push(item.key as string)
getInitExpandKeys(item.children,expandKeys)
}
})
return expandKeys
}
const getDataSource = ()=>{
setLoading(true)
request && request().then((res)=>{
const {data,success} = res
setDataSource(success? data : [])
setExpandedKeys(getInitExpandKeys(success? data:[]))
}).finally(()=>{setLoading(false)})
}
}
useEffect(() => {
getDataSource()
const handleResize = () => {
setTableHeight(window.innerHeight * 80 / 100 - 64 - 72 - 56 - 16 -3)
};
const debouncedHandleResize = debounce(handleResize, 200);
// 监听窗口大小变化
window.addEventListener('resize', debouncedHandleResize);
handleResize();
return () => {
window.removeEventListener('resize', debouncedHandleResize);
};
}, []);
useEffect(() => {
getDataSource()
}, []);
return (
<div ref={parentRef}>
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading} className=''>
<Transfer
showSearch
onSearch={(dir)=>{
memo = {};
}}
listStyle={{width:'408px'}}
disabledData={disabledData}
filterOption={(inputValue: string, item: any) => handlerFilterOption(inputValue, item)}
targetKeys={targetKeys}
dataSource={transferDataSource}
className="tree-transfer"
render={(item) => item.title!}
showSelectAll={false}
onChange={onChange}
titles={['','']}
>
{({ direction, onItemSelect, selectedKeys,onItemSelectAll ,filteredItems}) => {
const treeProps = {
dataSource:translatedDataSource, direction, onItemSelect, selectedKeys,onItemSelectAll ,filteredItems,token,tableHeight,targetKeys,disabledData
}
if (direction === 'left') {
const checkedKey = [...selectedKeys, ...targetKeys as string[]];
return (
<TransferTree {...treeProps} checkedKey={checkedKey} />
);
}
if(direction === 'right'){
const checkedKey = [...selectedKeys,...targetKeys as string[]];
return (
<TransferTree {...treeProps} checkedKey={checkedKey} />
);
}
}}
</Transfer>
<Input className="mb-[10px]" placeholder={searchPlaceholder} onChange={(e)=>setSearchWord(e.target.value)} value={searchWord} />
<>{ translatedDataSource && translatedDataSource.length > 0 ? <Tree
checkable
expandedKeys={expandedKeys}
checkedKeys={targetKeys}
selectable={false}
onCheck={(e)=>{setTargetKeys(e);
onSelect(((e as string[])?.filter(x=>disabledData.indexOf(x as string) === -1))||[])}}
onExpand={setExpandedKeys}
treeData={translatedDataSource}
blockNode
showIcon
/>
: <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/> }</>
</Spin>
</div>
);
@@ -219,12 +219,12 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
/></Row>
</>
}
<Form.Item
{/* <Form.Item
label={$t("备注")}
name="remark"
>
<Input.TextArea className="w-INPUT_NORMAL" disabled={type !== 'add' && type !== 'publish'} placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
</Form.Item> */}
{/*
{type !== 'add' && type !== 'publish' && <Form.Item
label={$t("审核意见"
@@ -137,6 +137,28 @@ export const TranslateWord = ()=>{
{$t('鉴权数量')}
{$t('列表')}
{$t('块')}
{$t('HTTP 请求头')}
{$t('全等匹配')}
{$t('前缀匹配')}
{$t('后缀匹配')}
{$t('子串匹配')}
{$t('非等匹配')}
{$t('空值匹配')}
{$t('存在匹配')}
{$t('不存在匹配')}
{$t('区分大小写的正则匹配')}
{$t('不区分大小写的正则匹配')}
{$t('任意匹配')}
{$t('驳回')}
{$t('已订阅')}
{$t('取消申请')}
{$t('透传客户端请求 Host')}
{$t('使用上游服务 Host')}
{$t('重写 Host')}
{$t('动态服务发现')}
{$t('地址')}
{$t('新增')}
{$t('申请方消费者')}
</>
)
@@ -39,7 +39,7 @@ const WithPermission = ({access, tooltip, children,disabled, showDisabled = true
{ cloneElement(children, {disabled:true})}
</Tooltip>}
{!editAccess && (children?.type !== Button && children?.type !== Upload && showDisabled) && <Tooltip title={tooltip ?? $t("暂无操作权限,请联系管理员分配。")}>
{ cloneElement(children, {disabled:true,okButtonProps:{disabled:true}})}
{ cloneElement(children, {disabled:true, onClick:(e)=>e.preventDefault(),okButtonProps:{disabled:true}})}
</Tooltip>}
</>
@@ -343,11 +343,6 @@ export const PUBLISH_APPROVAL_RECORD_INNER_TABLE_COLUMN : PageProColumns<Publish
dataIndex: 'status',
ellipsis:true,
},
{
title:('备注'),
dataIndex: 'comments',
ellipsis:true
},
{
title:('申请人'),
dataIndex: ['applicant','name'],
+119 -99
View File
@@ -4,84 +4,84 @@
export const PERMISSION_DEFINITION = [
{
"system.organization.member.view": {
"system.settings.account.view": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.view"] }]
"anyOf": [{ "backend": ["system.settings.account.view"] }]
}
},
"system.organization.member.add": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.edit": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.remove": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.delete": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.block": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.department.add": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.department.edit": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.member.department.delete": {
"granted": {
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
}
},
"system.organization.team.view": {
"system.workspace.team.view_all": {
"granted": {
"anyOf": [{ "backend": ["system.organization.team.view"] }]
"anyOf": [{ "backend": ["system.workspace.team.view_all"] }]
}
},
"system.organization.team.add": {
"granted": {
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.create"] }]
}
},
"system.organization.team.edit": {
"granted": {
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
}
},
"system.organization.team.delete": {
"granted": {
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
}
},
"system.organization.team.running": {
"granted": {
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
}
},
"system.organization.role.view": {
"granted": {
"anyOf": [{ "backend": ["system.organization.role.view_system_role","system.organization.role.view_team_role"] }]
"anyOf": [{ "backend": ["system.settings.role.view"] }]
}
},
"system.organization.role.system.view": {
"granted": {
"anyOf": [{ "backend": ["system.organization.role.view_system_role"] }]
"anyOf": [{ "backend": ["system.settings.role.view"] }]
}
},
"system.organization.role.system.add": {
@@ -101,7 +101,7 @@ export const PERMISSION_DEFINITION = [
},
"system.organization.role.team.view": {
"granted": {
"anyOf": [{ "backend": ["system.organization.role.view_team_role"] }]
"anyOf": [{ "backend": ["system.settings.role.view"] }]
}
},
"system.organization.role.team.add": {
@@ -121,22 +121,22 @@ export const PERMISSION_DEFINITION = [
},
"system.api_market.service_classification.view": {
"granted": {
"anyOf": [{ "backend": ["system.settings.service_classification.view"] }]
"anyOf": [{ "backend": ["system.settings.general.view"] }]
}
},
"system.api_market.service_classification.add": {
"granted": {
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
}
},
"system.api_market.service_classification.edit": {
"granted": {
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
}
},
"system.api_market.service_classification.delete": {
"granted": {
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
}
},
"system.devops.system_setting.view": {
@@ -149,94 +149,94 @@ export const PERMISSION_DEFINITION = [
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
}
},
"system.dashboard.run_view.view":{
"system.analysis.run_view.view":{
"granted": {
"anyOf": [{ "backend": ['system.dashboard.run_view.view'] }]
"anyOf": [{ "backend": ['system.analysis.run_view.view'] }]
}
},
"system.devops.data_source.view":{
"system.settings.data_source.view":{
"granted":{
"anyOf":[{"backend":['system.devops.data_source.view']}]
"anyOf":[{"backend":['system.settings.data_source.view']}]
}
},
"system.devops.data_source.edit":{
"granted":{
"anyOf":[{"backend":['system.devops.data_source.manager']}]
"anyOf":[{"backend":['system.settings.data_source.manager']}]
}
},
"system.devops.cluster.view": {
"system.settings.api_gateway.view": {
"granted": {
"anyOf": [{ "backend": ["system.devops.cluster.view"] }]
"anyOf": [{ "backend": ["system.settings.api_gateway.view"] }]
}
},
"system.devops.cluster.add": {
"granted": {
"anyOf": [{ "backend": ["system.devops.cluster.manager"] }]
"anyOf": [{ "backend": ["system.settings.api_gateway.manager"] }]
}
},
"system.devops.cluster.edit": {
"granted": {
"anyOf": [{ "backend": ["system.devops.cluster.manager"] }]
"anyOf": [{ "backend": ["system.settings.api_gateway.manager"] }]
}
},
"system.devops.cluster.delete": {
"granted": {
"anyOf": [{ "backend": ["system.devops.cluster.manager"] }]
"anyOf": [{ "backend": ["system.settings.api_gateway.manager"] }]
}
},
"system.devops.ai_provider.view": {
"system.settings.ai_provider.view": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ai_provider.view"] }]
"anyOf": [{ "backend": ["system.settings.ai_provider.view"] }]
}
},
"system.devops.ai_provider.edit": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ai_provider.manager"] }]
"anyOf": [{ "backend": ["system.settings.ai_provider.manager"] }]
}
},
"system.devops.ssl_certificate.view": {
"system.settings.ssl_certificate.view": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ssl_certificate.view"] }]
"anyOf": [{ "backend": ["system.settings.ssl_certificate.view"] }]
}
},
"system.devops.ssl_certificate.add": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ssl_certificate.manager"] }]
"anyOf": [{ "backend": ["system.settings.ssl_certificate.manager"] }]
}
},
"system.devops.ssl_certificate.edit": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ssl_certificate.manager"] }]
"anyOf": [{ "backend": ["system.settings.ssl_certificate.manager"] }]
}
},
"system.devops.ssl_certificate.delete": {
"granted": {
"anyOf": [{ "backend": ["system.devops.ssl_certificate.manager"] }]
"anyOf": [{ "backend": ["system.settings.ssl_certificate.manager"] }]
}
},
"system.devops.log_configuration.view": {
"system.settings.log_configuration.view": {
"granted": {
"anyOf": [{ "backend": ["system.devops.log_configuration.view"] }]
"anyOf": [{ "backend": ["system.settings.log_configuration.view"] }]
}
},
"system.devops.log_configuration.add": {
"granted": {
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
}
},
"system.devops.log_configuration.edit": {
"granted": {
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
}
},
"system.devops.log_configuration.publish": {
"granted": {
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
}
},
"system.devops.log_configuration.delete": {
"granted": {
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
}
},
"system.workspace.application.view_all": {
@@ -244,19 +244,24 @@ export const PERMISSION_DEFINITION = [
"anyOf": [{ "backend": ["system.workspace.application.view_all"] }]
}
},
"system.workspace.application.edit": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.application.manager_all"] }]
}
},
"system.workspace.service.view_all": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.service.view_all"] }]
}
},
"system.workspace.team.view_all": {
"system.workspace.service.edit": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.team.view_all"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all"] }]
}
},
"system.workspace.api_market.view": {
"system.api_portal.api_portal.view": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.api_market.view"] }]
"anyOf": [{ "backend": ["system.api_portal.api_portal.view"] }]
}
},
"system.dashboard.dashboard.view": {
@@ -271,237 +276,252 @@ export const PERMISSION_DEFINITION = [
},
"team.service.api_doc.view": {
"granted": {
"anyOf": [{ "backend": ["team.service.api_doc.view"] }]
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.api_doc.view"] }]
}
},
"team.service.api_doc.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.api_doc.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api_doc.manager"] }]
}
},
"team.service.api_doc.edit": {
"granted": {
"anyOf": [{ "backend": ["team.service.api_doc.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api_doc.manager"] }]
}
},
"team.service.service_intro.view": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.service_intro.view"] }]
}
},
"team.service.service_intro.add": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.service_intro.manager"] }]
}
},
"team.service.service_intro.edit": {
"granted": {
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.service_intro.manager"] }]
}
},
"team.service.api_doc.import": {
"granted": {
"anyOf": [{ "backend": ["team.service.api_doc.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api_doc.manager"] }]
}
},
"team.service.router.view": {
"granted": {
"anyOf": [{ "backend": ["team.service.router.view"] }]
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.api.view"] }]
}
},
"team.service.router.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.router.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
}
},
"team.service.router.edit": {
"granted": {
"anyOf": [{ "backend": ["team.service.router.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
}
},
"team.service.router.delete": {
"granted": {
"anyOf": [{ "backend": ["team.service.router.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
}
},
"team.service.upstream.view": {
"granted": {
"anyOf": [{ "backend": ["team.service.upstream.view"] }]
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.upstream.view"] }]
}
},
"team.service.upstream.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
}
},
"team.service.upstream.edit": {
"granted": {
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
}
},
"team.service.upstream.delete": {
"granted": {
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
}
},
"team.service.release.view": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.view"] }]
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.release.view"] }]
}
},
"team.service.release.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.online": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.stop": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.cancel": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.rollback": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.delete": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.release.approval": {
"granted": {
"anyOf": [{ "backend": ["team.service.release.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
}
},
"team.service.subscription.view": {
"granted": {
"anyOf": [{ "backend": ["team.service.subscription.view"] }]
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.subscription.view"] }]
}
},
"team.service.subscription.approval": {
"granted": {
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
}
},
"team.service.subscription.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
}
},
"team.service.subscription.delete": {
"granted": {
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
}
},
"team.service.service.view": {
"granted": {
"anyOf": [{ "backend": [""] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","system.workspace.service.view_all","team.team.service.view"] }]
}
},
"team.service.service.add": {
"granted": {
"anyOf": [{ "backend": ["team.service.service.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.team.service.manager","team.service.service.manager"] }]
}
},
"team.service.service.edit": {
"granted": {
"anyOf": [{ "backend": ["team.service.service.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.team.service.manager","team.service.service.manager"] }]
}
},
"team.service.service.delete": {
"granted": {
"anyOf": [{ "backend": ["team.service.service.manager"] }]
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.team.service.manager","team.service.service.manager"] }]
}
},
"team.application.subscription.view": {
"granted": {
"anyOf": [{ "backend": ["team.application.subscription.view"] }]
"anyOf": [{ "backend": ["system.workspace.application.view_all","team.consumer.subscription.view_subscribed_service"] }]
}
},
"team.application.subscription.add": {
"granted": {
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.subscription.subscribe"] }]
}
},
"team.application.subscription.edit": {
"granted": {
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.subscription.manager_subscribed_services"] }]
}
},
"team.application.subscription.delete": {
"granted": {
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.team.consumer.subscription.manager_subscribed_services"] }]
}
},
"team.application.application.view": {
"granted": {
"anyOf": [{ "backend": ["team.application.application.view"] }]
"anyOf": [{ "backend": ["system.workspace.application.view_all","team.team.consumer.view"] }]
}
},
"team.application.application.add": {
"granted": {
"anyOf": [{ "backend": ["team.application.application.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al",'team.team.consumer.manager',"team.consumer.application.manager"] }]
}
},
"team.application.application.edit": {
"granted": {
"anyOf": [{ "backend": ["team.application.application.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al",'team.team.consumer.manager',"team.consumer.application.manager"] }]
}
},
"team.application.application.delete": {
"granted": {
"anyOf": [{ "backend": ["team.application.application.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al",'team.team.consumer.manager',"team.consumer.application.manager"] }]
}
},
"team.application.authorization.view": {
"team.consumer.authorization.view": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.view"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","system.workspace.application.view_all","team.consumer.authorization.view"] }]
}
},
"team.application.authorization.add": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.authorization.manager"] }]
}
},
"team.application.authorization.edit": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.authorization.manager"] }]
}
},
"team.application.authorization.delete": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.authorization.manager"] }]
}
},
"team.application.authorization.cancelSubApply": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.authorization.manager"] }]
}
},
"team.application.authorization.cancelSub": {
"granted": {
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
"anyOf": [{ "backend": ["system.workspace.application.manager_al","team.consumer.authorization.manager"] }]
}
},
"team.team.team.view": {
"granted": {
"anyOf": [{ "backend": ["team.team.team.view"] }]
"anyOf": [{ "backend": ["system.workspace.team.view_all","team.team.team.view"] }]
}
},
"team.team.team.edit": {
"granted": {
"anyOf": [{ "backend": ["team.team.team.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.team.manager"] }]
}
},
"team.team.member.view": {
"granted": {
"anyOf": [{ "backend": ["team.team.member.view"] }]
"anyOf": [{ "backend": ["system.workspace.team.view_all","team.team.member.view"] }]
}
},
"team.team.member.add": {
"granted": {
"anyOf": [{ "backend": ["team.team.member.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.member.manager"] }]
}
},
"team.team.member.edit": {
"granted": {
"anyOf": [{ "backend": ["team.team.member.manager"] }]
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.member.manager"] }]
}
},
"project.mySystem.topology.view": {
@@ -7,7 +7,7 @@ system:
cname: '成员'
value: 'member'
access:
- system.organization.member.view
- system.settings.account.view
- system.organization.member.add
- system.organization.member.edit
- system.organization.member.delete
@@ -18,7 +18,7 @@ system:
- name: team_manager
cname: '团队管理'
desc: '团队管理'
- system.organization.team.view
- system.workspace.team.view_all
- system.organization.team.add
- system.organization.team.edit
- system.organization.team.delete
@@ -55,7 +55,7 @@ system:
cname: 集群
value: 'cluster'
children:
- system.devops.cluster.view
- system.settings.api_gateway.view
- system.devops.cluster.add
- system.devops.cluster.edit
- system.devops.cluster.delete
@@ -63,7 +63,7 @@ system:
cname: 证书
value: 'ssl_certificate'
children:
- system.devops.ssl_certificate.view
- system.settings.ssl_certificate.view
- system.devops.ssl_certificate.add
- system.devops.ssl_certificate.edit
- system.devops.ssl_certificate.delete
@@ -71,7 +71,7 @@ system:
cname: 日志
value: 'log_configuration'
children:
- system.devops.log_configuration.view
- system.settings.log_configuration.view
- system.devops.log_configuration.add
- system.devops.log_configuration.edit
- system.devops.log_configuration.publish
@@ -99,7 +99,7 @@ system:
cname: API市场
value: 'api_market'
children:
- system.workspace.api_market.view
- system.api_portal.api_portal.view
team:
- name: service
cname: 服务
@@ -172,8 +172,8 @@ team:
cname: 访问授权
value: 'authorization'
children:
- team.application.authorization.view
- team.application.authorization.manager
- team.consumer.authorization.view
- team.consumer.authorization.manager
- team.application.authorization.add
- team.application.authorization.edit
- team.application.authorization.delete
@@ -7,6 +7,8 @@ export type UserInfoType = {
email: string
phone: string
avatar: string
type:string
}
export type UserProfileProps = {
@@ -1,26 +0,0 @@
/*
* @Date: 2024-01-31 15:00:11
* @LastEditors: maggieyyy
* @LastEditTime: 2024-05-10 17:03:03
* @FilePath: \frontend\packages\core\src\hooks\crypto.ts
*/
// import CryptoJS from 'crypto-js';
// export const useCrypto = () => {
// const key = '1e42=7838a1vfc6n';
// const encryptByEnAES = (secretKey: string, data: string, initializationVector?: string): string => {
// const iv = CryptoJS.enc.Latin1.parse(initializationVector || key);
// const keyForEncryption = CryptoJS.enc.Latin1.parse(CryptoJS.MD5(secretKey).toString());
// const cipher = CryptoJS.AES.encrypt(data, keyForEncryption, {
// iv,
// mode: CryptoJS.mode.CBC,
// padding: CryptoJS.pad.Pkcs7,
// });
// return CryptoJS.enc.Base64.stringify(cipher.ciphertext);
// };
// return { encryptByEnAES };
// };
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2024-06-04 14:58:33
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-04 15:39:24
* @FilePath: \frontend\packages\common\src\index.css
*/
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -212,6 +212,28 @@
"鉴权数量": "Ka701316",
"列表": "K9eaa2eb6",
"块": "Kfaec39e9",
"HTTP 请求头": "K76036e25",
"全等匹配": "K44607e3f",
"前缀匹配": "Kc287500a",
"后缀匹配": "Kfc0b1147",
"子串匹配": "Ka4a92043",
"非等匹配": "K30b2e44f",
"空值匹配": "Kb1587991",
"存在匹配": "K1e97dbd8",
"不存在匹配": "Kc8ee3e62",
"区分大小写的正则匹配": "K87c5a801",
"不区分大小写的正则匹配": "K95f062f1",
"任意匹配": "Kfbd230a5",
"驳回": "Kd85208a3",
"已订阅": "Kad6aa439",
"取消申请": "K9a68443b",
"透传客户端请求 Host": "Kaeba0229",
"使用上游服务 Host": "K6d7e2fd0",
"重写 Host": "K31332633",
"动态服务发现": "K2c2bc64f",
"地址": "K78b1ca25",
"新增": "K1644b775",
"申请方消费者": "Kec91f0db",
"暂无操作权限,请联系管理员分配。": "K23fda291",
"微信小程序": "K4618cb0a",
"获取文件,需填路径": "Ka854f511",
@@ -524,7 +546,7 @@
"移除成员": "K395acc14",
"添加成员": "Kec46a57f",
"输入姓名查找": "K48724410",
"搜索用户名、邮箱": "Kb9052305",
"输入名称查找用户": "Kf5fd27ed",
"设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。": "K4c72fb6f",
"添加团队": "K510cdd27",
"输入名称、ID、负责人查找团队": "K9244ae14",
@@ -627,10 +649,10 @@
"搜索服务": "K66ea2f0",
"审核中": "K8adf7f8b",
"添加消费者": "K84c4dc71",
"暂无服务描述": "Ka4b45550",
"暂无消费者描述": "Kc3b7bfa8",
"创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务": "K5c4e2865",
"订阅的服务数量:已通过 (0) 个,申请中 (1) 个": "K3c7b175f",
"输入名称、ID 查找服务": "K40a89bd8",
"输入名称、ID 查找消费者": "K3a6f905d",
"退出测试": "Kbe3e9335",
"服务市场": "K370a3eb2",
"服务详情": "Kf7ec36d",
@@ -645,6 +667,7 @@
"版本": "K81634069",
"更新时间": "Keefda53d",
"无标签": "K96a2f1c8",
"暂无服务描述": "Ka4b45550",
"API 数量": "K72b0c0b3",
"接入消费者数量": "K70b79760",
"关联标签": "K96059c69",
@@ -319,7 +319,7 @@
"Ka46b9b24": "Data Source Type",
"Kbb0cdcd0": "Data Source Address",
"Kd9dfb884": "Organization",
"K3e770a75": "Authentication Token",
"K3e770a75": "Credentials Token",
"K8ef69ee2": "Key",
"Kba3507d6": "Upload Key",
"K93ac0f23": "Key file suffix is usually .key",
@@ -365,7 +365,7 @@
"Kcef64f4d": "Default AI Provider",
"Kcab588a9": "No AI model provider set,",
"Kb9b56111": "Set Now",
"Kcf756b7a": "API Call Prefix",
"Kcf756b7a": "API Request Prefix",
"K13edc043": "As a prefix for all APIs in the service, e.g., host/{service_name}/{api_path}, cannot be modified once saved.",
"Kf52a584d": "Service Category",
"K72b21be5": "Set the category in which the service will be displayed in the service marketplace",
@@ -391,8 +391,8 @@
"K813e1c0a": "Team Name",
"K692f5aa6": "Team ID",
"K5de0bc2": "Team ID can be used to retrieve the team, cannot be modified once saved.",
"Ka63dd985": "Team Leader",
"Ka6bcd272": "The leader has management authority over the team, services, and members within the team",
"Ka63dd985": "Team Administrator",
"Ka6bcd272": "The Administrator has management authority over the team, services, and members within the team",
"Ka2012bdd": "Delete Team",
"Kbde1f3d": "Service data must be cleared before deletion",
"K395acc14": "Remove",
@@ -463,7 +463,7 @@
"Kd59290a2": "Search Category or Tag",
"K6b75bdbc": "No API Data",
"K4b15d6f5": "Application Reason",
"Kb71b5a13": "Authentication Type",
"Kb71b5a13": "Credentials Type",
"K4d1465ee": "ISS",
"K5dcd7ed8": "Signature Algorithm",
"K5b0eedd3": "Secret",
@@ -475,10 +475,10 @@
"K31418470": "SK",
"Kbfeb5297": "API Key",
"K1a78e6f0": "Expiration Time",
"Ke64e43a": "Hide Authentication Info",
"K217cb125": "Authentication Details",
"K2bb63eca": "Add Authentication",
"Kd74d69b7": "Edit Authentication",
"Ke64e43a": "Hide Credentials Info",
"K217cb125": "Credentials Details",
"K2bb63eca": "Add Credentials",
"Kd74d69b7": "Edit Credentials",
"K9cbe1e0": "Modify",
"Kb6e9328f": "Authorization",
"Kd23d1716": "Add Authorization",
@@ -580,8 +580,8 @@
"Kd7d84192": "Name",
"Kc88e03b6": "Team Roles",
"Ke08ff808": "Addition Date",
"K19a3ebe0": "Successful Requests",
"Kcaa8259": "Successful Forwards",
"K19a3ebe0": "Success",
"Kcaa8259": "Success",
"K17f93984": "API",
"K888f038f": "Failed Status Code Count",
"Ke792d01c": "Service Association",
@@ -607,7 +607,7 @@
"Ke108c369": "Success",
"K9168d3e": "Redirecting to Login Page",
"K2f8a7ab7": "Review Comments Not Provided",
"Kb858d78a": "Copy Successful",
"Kb858d78a": "Copied",
"K26e85d15": "Copy Failed, Please Copy Manually",
"Kd60d204": "Service Team",
"K823bfe63": "Online",
@@ -654,5 +654,30 @@
"K6e32a344": "Number of Services",
"Ka701316": "Number of Auths",
"K9eaa2eb6": "List",
"Kfaec39e9": "Block"
"Kfaec39e9": "Block",
"Kc3b7bfa8": "No Consumer Description",
"K3a6f905d": "Enter Name, ID to Search Consumer",
"K76036e25": "HTTP Request Header",
"K44607e3f": "Exact Match",
"Kc287500a": "Prefix Match",
"Kfc0b1147": "Suffix Match",
"Ka4a92043": "Substring Match",
"K30b2e44f": "Non-Exact Match",
"Kb1587991": "Null Match",
"K87c5a801": "Case-Sensitive Regex Match",
"K95f062f1": "Case-Insensitive Regex Match",
"Kfbd230a5": "Any Match",
"Kd85208a3": "Reject",
"Kad6aa439": "Subscribed",
"K9a68443b": "Cancel Request",
"Kaeba0229": "Pass-through Client Request Host",
"K6d7e2fd0": "Use Upstream Service Host",
"K31332633": "Rewrite Host",
"K2c2bc64f": "Dynamic Service Discovery",
"K78b1ca25": "Address",
"K1644b775": "Add",
"Kc8ee3e62": "Non-Existence",
"K1e97dbd8": "Existence",
"Kec91f0db": "Applicant Consumer",
"Kf5fd27ed": "Enter Name to Search User"
}
@@ -672,8 +672,34 @@
"K67b530f": "コンシューマー名",
"K11f34de": "コンシューマー ID",
"Kc01002": "コンシューマーを削除",
"K84c4dc71": "コンシューマーエンティティを作成および管理し、各コンシューマーは複数の API サービスにサブスクライブできます。呼び出し前に適切な権限が付与されていることを確認してください。コンシューマー用に API キーなどの認証方法を生成して、安全に API サービスを呼び出せます。",
"K40a89bd8": "名前または ID を入力してサービスを検索",
"Kba74f26d": "コンシューマーを接続",
"K70b79760": "接続コンシューマー数"
"K70b79760": "接続コンシューマー数",
"K5c4e2865": "コンシューマーエンティティを作成および管理し、各コンシューマーは複数の API サービスにサブスクライブできます。呼び出し前に適切な権限が付与されていることを確認してください。コンシューマー用に API キーなどの認証方法を生成して、安全に API サービスを呼び出せます。",
"K84c4dc71": "コンシューマーを追加",
"Kc3b7bfa8": "コンシューマーの説明がありません",
"K3a6f905d": "名前、IDを入力してコンシューマーを検索",
"K76036e25": "HTTPリクエストヘッダー",
"K44607e3f": "完全一致",
"Kc287500a": "プレフィックス一致",
"Kfc0b1147": "サフィックス一致",
"Ka4a92043": "部分一致",
"K30b2e44f": "非完全一致",
"Kb1587991": "ヌル一致",
"K87c5a801": "大文字小文字を区別する正規表現一致",
"K95f062f1": "大文字小文字を区別しない正規表現一致",
"Kfbd230a5": "任意一致",
"Kd85208a3": "拒否",
"Kad6aa439": "申し込み済み",
"K9a68443b": "申し込み取消",
"Kaeba0229": "クライアントリクエストホストのパススルー",
"K6d7e2fd0": "上位サービスホストの使用",
"K31332633": "ホストの書き換え",
"K2c2bc64f": "動的サービス発見",
"K78b1ca25": "アドレス",
"K1644b775": "追加",
"Kc8ee3e62": "存在しない",
"K1e97dbd8": "存在する",
"Kec91f0db": "申請側コンシューマー",
"Kf5fd27ed": "名前を入力してユーザーを検索"
}
@@ -1 +1,3 @@
{}
{
"Kf5fd27ed": "输入名称查找用户"
}
@@ -1,32 +1,3 @@
{
"K7acfcfad": "消费者",
"Kc8054dba": "消费者开发者",
"Keb1673a6": "消费者管理员",
"K1fc2cc28": "无需审核:允许任何消费者调用该服务",
"K8dabb98e": "人工审核:仅允许通过人工审核的消费者调用该服务",
"K7c1fb123": "申请方-消费者",
"K93c2696e": "上线结果",
"K6e32a344": "订阅服务数量",
"Ka701316": "鉴权数量",
"K9eaa2eb6": "列表",
"Kfaec39e9": "块",
"Kdea9a418": "为了安全地调用 API,你需要创建一个消费者以及Token。",
"Keee27105": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
"Kaa717866": "提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。",
"Kd2c34e2c": "AI 服务",
"K62840d62": "REST 服务",
"K4c72fb6f": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。",
"K61cca533": "消费者调用统计",
"Kdfff59d4": "请选择消费者",
"K386857bd": "消费者调用量 Top10",
"Kb684c806": "搜索或选择消费者",
"Ke0fbd1c8": "消费者管理",
"K67b530f": "消费者名称",
"K11f34de": "消费者 ID",
"Kc01002": "删除消费者",
"K84c4dc71": "添加消费者",
"K5c4e2865": "创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务",
"K40a89bd8": "输入名称、ID 查找服务",
"Kba74f26d": "接入消费者",
"K70b79760": "接入消费者数量"
"Kf5fd27ed": "输入名称查找用户"
}
@@ -1,7 +1,27 @@
{
"K93c2696e": "上线结果",
"K6e32a344": "订阅服务数量",
"Ka701316": "鉴权数量",
"K9eaa2eb6": "列表",
"Kfaec39e9": "块"
"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": "申请方消费者",
"Kf5fd27ed": "输入名称查找用户",
"Kc3b7bfa8": "暂无消费者描述",
"K3a6f905d": "输入名称、ID 查找消费者"
}
@@ -1,32 +1,3 @@
{
"K7acfcfad": "消费者",
"Kc8054dba": "消费者开发者",
"Keb1673a6": "消费者管理员",
"K1fc2cc28": "无需审核:允许任何消费者调用该服务",
"K8dabb98e": "人工审核:仅允许通过人工审核的消费者调用该服务",
"K7c1fb123": "申请方-消费者",
"K93c2696e": "上线结果",
"K6e32a344": "订阅服务数量",
"Ka701316": "鉴权数量",
"K9eaa2eb6": "列表",
"Kfaec39e9": "块",
"Kdea9a418": "为了安全地调用 API,你需要创建一个消费者以及Token。",
"Keee27105": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
"Kaa717866": "提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。",
"Kd2c34e2c": "AI 服务",
"K62840d62": "REST 服务",
"K4c72fb6f": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。",
"K61cca533": "消费者调用统计",
"Kdfff59d4": "请选择消费者",
"K386857bd": "消费者调用量 Top10",
"Kb684c806": "搜索或选择消费者",
"Ke0fbd1c8": "消费者管理",
"K67b530f": "消费者名称",
"K11f34de": "消费者 ID",
"Kc01002": "删除消费者",
"K84c4dc71": "添加消费者",
"K5c4e2865": "创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务",
"K40a89bd8": "输入名称、ID 查找服务",
"Kba74f26d": "接入消费者",
"K70b79760": "接入消费者数量"
"Kf5fd27ed": "输入名称查找用户"
}
@@ -1,24 +1,4 @@
{
"Kfe93ef35": "Application",
"Kffd7e274": "No Review: All applications are allowed to subscribe to this service",
"K8a8b13e4": "Manual Review: Only reviewed and approved applications can subscribe to this service",
"K9bdd8403": "To securely call APIs, you need to create an application and a token.",
"Kc8239422": "Teams include personnel, applications, and services. Data between different teams is isolated, and can be used to manage different departments/project teams/teams within the enterprise.",
"Ka0a8840a": "Review subscription requests from other applications. Only approved requests can initiate API calls.",
"K5ece3bac": "Set up teams and members. You can then create services and applications, subscribe to APIs within the team. Members can only see services and applications within their team.",
"K1512e983": "Application Call Statistics",
"Kb4d2007f": "Please Select Application",
"Kc0915603": "Application Top 10",
"Kd8a7a689": "Search or Select Application",
"Kb7e869a4": "Application Settings",
"K5168eb63": "Application Name",
"K546e46f": "Application ID",
"K95764d1d": "Delete Application",
"K667bbbe7": "Add Application",
"K8723422e": "Access Application",
"K93d5a66e": "Number of Access Applications",
"K216a1ac7": "Application Developer",
"K27924db": "Application Administrator",
"Kd55c6887": "Review",
"K831aa6c0": "Applicant - Application"
"Kb9052305": "Search Username, Email",
"K40a89bd8": "Enter Name, ID to Search Member"
}
@@ -5,6 +5,7 @@
"K9bdd8403": "API を安全に呼び出すためには、アプリケーションとトークンを作成する必要があります。",
"Kc8239422": "チームにはユーザー、アプリケーション、サービスが含まれ、異なるチームのアプリケーションとサービスのデータは分離されています。企業内の部門/プロジェクトグループ/チームの管理に使用できます。",
"Ka0a8840a": "他のアプリケーションのサブスクリプション申請をレビューし、承認後に API リクエストが発行できます。",
"Kb9052305": "ユーザー名またはメールを検索",
"K5ece3bac": "チームとメンバーを設定してから、チーム内でサービスとアプリケーションを作成し、API をサブスクライブできます。メンバーは所属チーム内のサービスとアプリケーションのみを表示できます。",
"K1512e983": "アプリケーション呼び出し統計",
"Kb4d2007f": "Application を選択",
@@ -20,5 +21,6 @@
"K216a1ac7": "アプリケーション開発者",
"K27924db": "アプリケーション管理者",
"Kd55c6887": "レビュー",
"K831aa6c0": "申請元-アプリケーション"
"K831aa6c0": "申請元-アプリケーション",
"K40a89bd8": "名前または ID を入力してサービスを検索"
}
@@ -5,6 +5,7 @@
"K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。",
"Kc8239422": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。",
"Ka0a8840a": "审核其他消费者的订阅申请,审核通过后的才可发起 API 请求。",
"Kb9052305": "搜索用户名、邮箱",
"K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。",
"K1512e983": "消费者调用统计",
"Kb4d2007f": "请选择消费者",
@@ -20,5 +21,6 @@
"K216a1ac7": "消费者开发者",
"K27924db": "消费者管理员",
"Kd55c6887": "审核",
"K831aa6c0": "申请方-消费者"
"K831aa6c0": "申请方-消费者",
"K40a89bd8": "输入名称、ID 查找服务"
}
@@ -5,6 +5,7 @@
"K9bdd8403": "為了安全地調用 API,你需要創建一個應用以及Token。",
"Kc8239422": "團隊中包含了人員、應用程式和服務,不同團隊之間的應用程式和服務數據是隔離的,可用於管理企業內部不同的部門/項目組/團隊。",
"Ka0a8840a": "審核其他應用程式的訂閱申請,審核通過後的才可發起 API 請求。",
"Kb9052305": "搜索用戶名、電郵",
"K5ece3bac": "設置團隊和成員,然後你可以在團隊內創建服務和應用程式、訂閱API,成員只能看到所屬團隊內的服務和應用程式。",
"K1512e983": "應用程式調用統計",
"Kb4d2007f": "請選擇應用程式",
@@ -20,5 +21,6 @@
"K216a1ac7": "應用程式開發者",
"K27924db": "應用程式管理員",
"Kd55c6887": "審核",
"K831aa6c0": "申請方-應用程式"
"K831aa6c0": "申請方-應用程式",
"K40a89bd8": "輸入名稱、ID 查找服務"
}
@@ -676,5 +676,7 @@
"K6e32a344": "订阅服务数量",
"Ka701316": "鉴权数量",
"K9eaa2eb6": "列表",
"Kfaec39e9": "块"
"Kfaec39e9": "块",
"Kc3b7bfa8": "暂无消费者描述",
"K3a6f905d": "输入名称、ID 查找消费者"
}
@@ -676,5 +676,30 @@
"K5c4e2865": "創建並管理自己的消費者實體,每個消費者可以訂閱多個API服務,確保在調用之前已獲得相應權限。你可以為消費者生成 API 密鑰等鑒權方式,用於安全地調用 API 服務",
"K40a89bd8": "輸入名稱、ID 查找服務",
"Kba74f26d": "接入消費者",
"K70b79760": "接入消費者數量"
"K70b79760": "接入消費者數量",
"Kc3b7bfa8": "暫無消費者描述",
"K3a6f905d": "輸入名稱、ID 查找消費者",
"K76036e25": "HTTP請求頭",
"K44607e3f": "全等匹配",
"Kc287500a": "前綴匹配",
"Kfc0b1147": "後綴匹配",
"Ka4a92043": "子串匹配",
"K30b2e44f": "非等匹配",
"Kb1587991": "空值匹配",
"K87c5a801": "區分大小寫的正則匹配",
"K95f062f1": "不區分大小寫的正則匹配",
"Kfbd230a5": "任意匹配",
"Kd85208a3": "駁回",
"Kad6aa439": "已訂閱",
"K9a68443b": "取消申請",
"Kaeba0229": "透傳客戶端請求Host",
"K6d7e2fd0": "使用上游服務Host",
"K31332633": "重寫Host",
"K2c2bc64f": "動態服務發現",
"K78b1ca25": "位址",
"K1644b775": "新增",
"Kc8ee3e62": "不存在匹配",
"K1e97dbd8": "存在匹配",
"Kec91f0db": "申請方消費者",
"Kf5fd27ed": "輸入名稱查找使用者"
}
@@ -13,10 +13,15 @@ export const checkAccess:(access:AccessDataType, accessData:Map<string,string[]>
return false
}
const neededBackendAccessArr = PERMISSION_DEFINITION[0]?.[access]?.granted?.anyOf[0].backend || []
return accessData?.has(accLevel)&& accessData.get(accLevel)!.length > 0 ? hasIntersection(neededBackendAccessArr, accessData.get(accLevel)!) : false
let accessSet = new Set(accessData.get('system'))
if(accLevel === 'team'){
accessSet = new Set(Array.from(accessSet).concat(accessData?.get('team') || []))
}
return accessSet!.size > 0 ? hasIntersection(neededBackendAccessArr, accessSet) : false
}
const hasIntersection = (arr1:string[], arr2:string[])=> {
const hasIntersection = (arr1:string[], set1:Set<string>)=> {
const arr2 = Array.from(set1)
const set = new Set(arr1.length > arr2.length ? arr2:arr1)
const arr = arr1.length > arr2.length ? arr1:arr2
for (const item of arr) {
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2024-06-04 15:05:05
* @LastEditors: maggieyyy
* @LastEditTime: 2024-08-01 17:59:56
* @FilePath: \frontend\packages\common\tailwind.config.js
*/
/** @type {import('tailwindcss').Config} */
module.exports = {
important:true,
+26 -6
View File
@@ -1,16 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<head id="head">
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/frontend/favicon.ico" />
<link id="favicon" rel="icon" type="image/svg+xml" href="/frontend/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>APIPark - 企业API数据开放平台</title>
</head>
<body>
<body id="eo-body">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script async src="/frontend/iconpark_eolink.js"></script>
<script async src="/frontend/iconpark_apinto.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const eoBody = document.getElementById('eo-body');
const favicon = document.getElementById('favicon');
const createScript = (id, src) => {
const script = document.createElement('script');
script.id = id;
script.async = true;
script.src = src;
return script;
};
const iconparkApintoSrc = window.location.hostname === 'localhost' ? '/iconpark_apinto.js' : '/frontend/iconpark_apinto.js';
const iconparkEolinkSrc = window.location.hostname === 'localhost' ? '/iconpark_eolink.js' : '/frontend/iconpark_eolink.js';
const faviconSrc = window.location.hostname === 'localhost' ? '/favicon.ico' : '/frontend/favicon.ico';
favicon.href = faviconSrc;
eoBody.appendChild(createScript('iconpark_apinto', iconparkApintoSrc));
eoBody.appendChild(createScript('iconpark_eolink', iconparkEolinkSrc));
});
</script>
</body>
</html>
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:42:18
* @FilePath: \frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
View File
@@ -290,3 +290,13 @@ a{
transition: background-color 0s 600000s, color 0s 600000s !important;
}
}
.ant-select-selection-overflow-item:first-child {
max-width: calc(100% - 60px);
margin-right: 4px;
}
a[disabled]:hover {
color: #BBB;
cursor: not-allowed;
}
@@ -35,6 +35,7 @@ export type MemberDropdownModalFieldType = {
parent?:string
email?:string
departmentIds?:string[]
password:string
};
export type MemberDropdownModalProps = {
@@ -137,7 +137,7 @@ const ServiceInsideDocument = ()=>{
<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.edit"><Button type="primary" className="mr-btnbase" onClick={save}>{$t('保存')}</Button></WithPermission>
<WithPermission access="team.service.service_intro.edit"><Button type="primary" className="mr-btnbase" onClick={save}>{$t('保存')}</Button></WithPermission>
</div>
</div>
</div>)
@@ -42,6 +42,7 @@ const AiServiceInsidePage:FC = ()=> {
const getApiDefine = ()=>{
console.log('@@@@@@@')
setApiPrefix('')
setPrefixForce(false)
fetchData<BasicResponse<{ prefix:string, force:boolean }>>('service/router/define',{method:'GET',eoParams:{service:serviceId,team:teamId}}).then(response=>{
@@ -62,7 +63,7 @@ const AiServiceInsidePage:FC = ()=> {
[
getItem(<Link to="./route">{$t('API 路由')}</Link>, 'route',undefined,undefined,undefined,'team.service.router.view'),
getItem(<Link to="./api">{$t('API 文档')}</Link>, 'api',undefined,undefined,undefined,'team.service.api_doc.view'),
getItem(<Link to="./document">{$t('使用说明')}</Link>, 'document',undefined,undefined,undefined,''),
getItem(<Link to="./document">{$t('使用说明')}</Link>, 'document',undefined,undefined,undefined,'team.service.service_intro.view'),
getItem(<Link to="./publish">{$t('发布')}</Link>, 'publish',undefined,undefined,undefined,'team.service.release.view'),
],
'group'),
@@ -84,19 +85,22 @@ const AiServiceInsidePage:FC = ()=> {
const filterMenu = (menu:MenuItemGroupType<MenuItemType>[])=>{
const newMenu = cloneDeep(menu)
return newMenu!.filter((m:MenuItemGroupType )=>{
if(m.children && m.children.length > 0){
if(m&&m.children && m.children.length > 0){
m.children = m.children.filter(
(c)=>(c&&(c as MenuItemType&{access:string} ).access ?
(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]):
true))
true))})
}
return m.children && m.children.length > 0
})
}
const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType<MenuItemType>[])
setActiveMenu((pre)=>{
return pre ?? 'route'
})
const menu = activeMenu ?? filteredMenu[0]?.children ? filteredMenu[0]?.children?.[0]?.key : filteredMenu[0]?.key
if(menu && currentUrl.split('/')[-1] !== menu){
navigateTo(`/service/${teamId}/aiInside/${serviceId}/${menu}`)
}
return filteredMenu || []
},[accessData,accessInit, SYSTEM_PAGE_MENU_ITEMS])
@@ -116,7 +120,7 @@ const AiServiceInsidePage:FC = ()=> {
}, [currentUrl]);
useEffect(()=>{
if(accessData && accessData.get('team') && accessData.get('team')?.indexOf('team.service.router.view') !== -1){
if(accessData && checkPermission('team.service.router.view')){
getApiDefine()
}
},[accessData])
@@ -256,7 +256,7 @@ const AiServiceInsideRouterCreate = () => {
</Form.Item>
<Form.Item label={$t("请求路径")}>
<Form.Item className="flex-1" label={$t("请求路径")}>
<Space.Compact block>
<Form.Item
name="pathMatch"
@@ -276,7 +276,7 @@ const AiServiceInsideRouterCreate = () => {
}]}
noStyle
>
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")} className="w-INPUT_NORMAL"
<Input prefix={(prefixForce ? `${apiPrefix}/` :"/")}
placeholder={$t(PLACEHOLDER.input)} onChange={(e)=>{
if((e.target.value as string).endsWith('/*')){
form.setFieldValue('path',e.target.value.slice(0,-2))
@@ -18,6 +18,7 @@ export type AiServiceRouterModelConfigProps = {
}
type AiServiceRouterModelConfigField = {
provider:string
id:string
config:string
}
@@ -70,6 +71,10 @@ const AiServiceRouterModelConfig = forwardRef<AiServiceRouterModelConfigHandle,
getLlmList(provider)
}
useEffect(()=>{
getLlmList(entity.provider)
},[])
return (
<Form
layout='vertical'
@@ -146,7 +146,7 @@ const AiSettingList = ()=>{
}
</div>
<WithPermission access="system.devops.ai_provider.view">
<WithPermission access="system.settings.ai_provider.view">
<Button block icon={<Icon icon="ic:outline-settings" width={18} height={18}/>} onClick={()=>openModal(provider)} classNames={{icon:'h-[18px]'}}>{$t('设置')}</Button>
</WithPermission>
</div>
@@ -106,10 +106,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle,AiSettingMo
label:<div className="flex items-center gap-[10px]">
<span>{x.id}</span>
{x?.scopes?.map(s=><Tag >{s?.toLocaleUpperCase()}</Tag>)}
</div>}))}
onChange={(e)=>{
form.setFieldValue('config',llmList?.find(x=>x.id===e)?.config)
}}>
</div>}))}>
</Select>
</Form.Item>
@@ -21,22 +21,22 @@ export default function Guide(){
{
title: $t("配置你的 AI 模型"),
description: $t('通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。'),
link: 'https://docs.apipark.com/docs/quick/pre-work/team'
link: 'https://docs.apipark.com/docs/system_setting/ai_model_providers'
},
{
title: $t("创建 AI 服务和 API"),
description: $t('创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。'),
link: 'https://docs.apipark.com/docs/quick/provider/service'
link: 'https://docs.apipark.com/docs/services/ai_services'
},
{
title: $t("创建调用 Token"),
description: $t('为了安全地调用 API,你需要创建一个消费者以及Token。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/application'
link: 'https://docs.apipark.com/docs/consumers'
},
{
title: $t("调用"),
description: $t('现在你可以通过 Token 来调用这些 API。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/application'
link: 'https://docs.apipark.com/docs/call_api'
}
]
},
@@ -46,17 +46,17 @@ export default function Guide(){
{
title: $t("创建 REST 服务和 API"),
description: $t('创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。'),
link: 'https://docs.apipark.com/docs/tutorials/api-market/service'
link: 'https://docs.apipark.com/docs/services/rest_services'
},
{
title: $t("创建调用 Token"),
description: $t('为了安全地调用 API,你需要创建一个消费者以及Token。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe'
link: 'https://docs.apipark.com/docs/consumers'
},
{
title: $t("调用"),
description: $t('现在你可以通过 Token 来调用这些 API。'),
link: 'https://docs.apipark.com/docs/quick/provider/approve'
link: 'https://docs.apipark.com/docs/call_api'
}
]
},
@@ -66,7 +66,7 @@ export default function Guide(){
{
title: $t("统计 API 调用情况"),
description: $t('仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。'),
link: 'https://docs.apipark.com/docs/quick/pre-work/monitor'
link: 'https://docs.apipark.com/docs/analysis'
}
]
}
@@ -78,17 +78,17 @@ export default function Guide(){
{
title: $t("账号与角色"),
description: $t('邀请你的团队成员加入 APIPark,共同管理和调用 API。'),
link: 'https://docs.apipark.com/docs/quick/pre-work/team'
link: 'https://docs.apipark.com/docs/system_setting/account_role'
},
{
title: $t("团队"),
description: $t('团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。'),
link: 'https://docs.apipark.com/docs/quick/provider/service'
link: 'https://docs.apipark.com/docs/teams'
},
{
title: $t("服务"),
description: $t('服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/application'
link: 'https://docs.apipark.com/docs/category/-%E6%9C%8D%E5%8A%A1'
}
]
},
@@ -98,12 +98,12 @@ export default function Guide(){
{
title: $t("订阅服务"),
description: $t('如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。'),
link: 'https://docs.apipark.com/docs/tutorials/api-market/service'
link: 'https://docs.apipark.com/docs/developer_portal'
},
{
title: $t("审核订阅申请"),
description: $t('提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。'),
link: 'https://docs.apipark.com/docs/quick/suberscriber/subscribe'
link: 'https://docs.apipark.com/docs/services/review_consumers'
}
]
},
@@ -113,7 +113,7 @@ export default function Guide(){
{
title: $t("日志"),
description: $t('APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。'),
link: 'https://docs.apipark.com/docs/quick/pre-work/monitor'
link: 'https://docs.apipark.com/docs/system_setting/log/'
}
]
}
@@ -45,7 +45,7 @@ const LogSettings = ()=>{
undefined,
undefined,
undefined,
'system.devops.log_configuration.view')
'system.settings.log_configuration.view')
})
return newMenu
},[state.language,menuItems])
@@ -1,4 +1,5 @@
import WithPermission from "@common/components/aoplatform/WithPermission";
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
import { $t } from "@common/locales";
import { useEffect } from "react";
@@ -24,7 +25,7 @@ export default function LogSettingsInstruction() {
<div className="h-[208px] w-[384px] flex flex-col items-center py-[32px] px-[24px] gap-[16px] rounded-DEFAULT bg-MENU_BG mr-[24px]">
<p className="text-[20px] font-medium leading-[32px] text-MAIN_TEXT"></p>
<p className="text-[12px] font-normal leading-[20px] text-DESC_TEXT"></p>
<p><Link to="/cluster"></Link></p>
<p><WithPermission access="system.settings.api_gateway.view" ><Link to="/cluster"></Link></WithPermission></p>
</div>
</div>
</div></div>
@@ -1,10 +1,11 @@
import {App, Form, Input, TreeSelect} from "antd";
import {forwardRef, useEffect, useImperativeHandle, useState} from "react";
import {forwardRef, useEffect, useImperativeHandle, useMemo, useState} from "react";
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
import {useFetch} from "@common/hooks/http.ts";
import { MemberDropdownModalHandle, MemberDropdownModalProps, DepartmentListItem, MemberDropdownModalFieldType, MemberTableListItem } from "../../const/member/type.ts";
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { $t } from "@common/locales/index.ts";
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDropdownModalProps>((props,ref)=>{
const { message} = App.useApp()
@@ -12,6 +13,7 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
const {type,entity,selectedMemberGroupId} = props
const {fetchData} = useFetch()
const [departmentList, setDepartmentList] = useState<DepartmentListItem[]>([])
const { state } = useGlobalContext()
const save:()=>Promise<boolean | string> = ()=>{
let url:string
@@ -78,6 +80,15 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
})
}
const generateRandomString = () =>{
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 8; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
useEffect(() => {
switch(type){
case 'addChild':
@@ -87,7 +98,7 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
form.setFieldsValue({id:entity!.id,name:entity!.name})
break
case 'addMember':
form.setFieldsValue('-1' === selectedMemberGroupId ? {} : {departmentIds:selectedMemberGroupId})
form.setFieldsValue({...('-1' === selectedMemberGroupId ? {} : {departmentIds:selectedMemberGroupId}), password:generateRandomString()})
break
case 'editMember':
form.setFieldsValue({...entity,departmentIds:(entity as MemberTableListItem )?.department?.map(x=>x.id)})
@@ -97,6 +108,23 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
}, []);
const treeData = useMemo(() => {
const loop = (data: DepartmentListItem[]): unknown[] =>
data?.map((item) => {
const title = ['unknown','disable'].indexOf(item.id) === -1 ?item.name : $t(item.name) as string;
if (item.children) {
return {...item,name:title, children:loop(item.children)}
}
return {
...item,
name: title
};
});
return loop(departmentList);
}, [departmentList,state.language]);
return (<WithPermission access="">
<Form
@@ -163,6 +191,13 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<MemberDropdownModalFieldType>
label={$t("密码")}
name="password"
rules={[{required: type === 'addMember',whitespace:true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)}/>
</Form.Item>
<Form.Item<MemberDropdownModalFieldType>
label={$t("部门")}
name="departmentIds"
@@ -175,7 +210,7 @@ export const MemberDropdownModal = forwardRef<MemberDropdownModalHandle,MemberDr
placeholder={$t(PLACEHOLDER.select)}
allowClear
treeDefaultExpandAll
treeData={departmentList}
treeData={treeData}
multiple
/>
</Form.Item>
@@ -346,7 +346,7 @@ const MemberList = ()=>{
<WithPermission access="system.organization.member.edit">
<Select
className="w-full"
mode="multiple"
mode="multiple"
value={entity.roles?.map((x:EntityItem)=>x.id)}
options={roleSelectableList?.map((x:{id:string,name:string})=>({label:(x.name), value:x.id}))}
onChange={(value)=>{
@@ -47,7 +47,7 @@ const LogSettings = ()=>{
undefined,
undefined,
undefined,
'system.devops.log_configuration.view')
'system.settings.log_configuration.view')
})
return newMenu
},[state.language,menuItems])
@@ -1,3 +1,4 @@
import WithPermission from "@common/components/aoplatform/WithPermission";
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
import { useEffect } from "react";
import { Link } from "react-router-dom";
@@ -24,7 +25,7 @@ export default function ResourceSettingsInstruction() {
<div className="h-[208px] w-[384px] flex flex-col items-center py-[32px] px-[24px] gap-[16px] rounded-DEFAULT bg-MENU_BG mr-[24px]">
<p className="text-[20px] font-medium leading-[32px] text-MAIN_TEXT"></p>
<p className="text-[12px] font-normal leading-[20px] text-DESC_TEXT"></p>
<p><Link to="/cluster"></Link></p>
<p><WithPermission access="system.settings.data_source.view" ><Link to="/cluster"></Link></WithPermission></p>
</div>
</div>
</div></div>
@@ -176,13 +176,17 @@ const RoleConfig = ()=>{
},[permissionInfo, state.language])
useEffect(() => {
getPermissionTemplate()
form.setFieldsValue({name:'',permits:[]})
if(roleId){
getPermissionInfo()
}
}, []);
useEffect(()=>{
getPermissionTemplate()
},[state.language])
const onFinish =async() => {
const body = await form.validateFields()
@@ -292,7 +292,7 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_,ref) => {
return (
<>
<WithPermission access={onEdit ? 'team.service.service.edit' :''}>
<WithPermission access={onEdit ? ['team.service.service.edit'] :''}>
<Form
layout='vertical'
labelAlign='left'
@@ -460,7 +460,7 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_,ref) => {
<Row className="mb-[10px]"
// wrapperCol={{ offset: 5, span: 19 }}
>
<WithPermission access={onEdit ? 'team.service.service.edit' :''}>
<WithPermission access={onEdit ? ['team.service.service.edit'] :''}>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
@@ -468,11 +468,11 @@ const SystemConfig = forwardRef<SystemConfigHandle>((_,ref) => {
</Row></>}
</div>
{onEdit && <>
<WithPermission access="team.service.service.delete" showDisabled={false}>
<WithPermission access={["team.service.service.delete"]} showDisabled={false}>
<div className="bg-[rgb(255_120_117_/_5%)] rounded-[10px] mt-[50px] p-btnrbase pb-0">
<p className="text-left"><span className="font-bold">{$t('删除服务')}</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
<div className="text-left">
<WithPermission access="team.service.service.delete">
<WithPermission access={["team.service.service.delete"]}>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger={true} onClick={deleteSystemModal}>{$t('删除服务')}</Button>
</WithPermission>
</div>
@@ -137,7 +137,7 @@ const ServiceInsideDocument = ()=>{
<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.edit"><Button type="primary" className="mr-btnbase" onClick={save}>{$t('保存')}</Button></WithPermission>
<WithPermission access="team.service.service_intro.edit"><Button type="primary" className="mr-btnbase" onClick={save}>{$t('保存')}</Button></WithPermission>
</div>
</div>
</div>)
@@ -62,7 +62,7 @@ const SystemInsidePage:FC = ()=> {
getItem(<Link to="./route">{$t('API 路由')}</Link>, 'route',undefined,undefined,undefined,'team.service.router.view'),
getItem(<Link to="./api">{$t('API 文档')}</Link>, 'api',undefined,undefined,undefined,'team.service.api_doc.view'),
getItem(<Link to="./upstream">{$t('上游')}</Link>, 'upstream',undefined,undefined,undefined,'team.service.upstream.view'),
getItem(<Link to="./document">{$t('使用说明')}</Link>, 'document',undefined,undefined,undefined,''),
getItem(<Link to="./document">{$t('使用说明')}</Link>, 'document',undefined,undefined,undefined,'team.service.service_intro.view'),
getItem(<Link to="./publish">{$t('发布')}</Link>, 'publish',undefined,undefined,undefined,'team.service.release.view'),
],
'group'),
@@ -84,19 +84,20 @@ const SystemInsidePage:FC = ()=> {
const filterMenu = (menu:MenuItemGroupType<MenuItemType>[])=>{
const newMenu = cloneDeep(menu)
return newMenu!.filter((m:MenuItemGroupType )=>{
if(m.children && m.children.length > 0){
if(m&&m.children && m.children.length > 0){
m.children = m.children.filter(
(c)=>(c&&(c as MenuItemType&{access:string} ).access ?
(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]):
true))
true))})
}
return m.children && m.children.length > 0
})
}
const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType<MenuItemType>[])
setActiveMenu((pre)=>{
return pre ?? 'route'
})
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])
@@ -116,7 +117,7 @@ const SystemInsidePage:FC = ()=> {
}, [currentUrl]);
useEffect(()=>{
if(accessData && accessData.get('team') && accessData.get('team')?.indexOf('team.service.router.view') !== -1){
if(accessData && checkPermission('team.service.router.view')){
getApiDefine()
}
},[accessData])
@@ -153,7 +153,7 @@ const SystemList:FC = ()=>{
<InsidePage
pageTitle={$t('服务')}
description={'APIPark '+$t("服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。")}
description={$t("服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。")}
showBorder={false}
contentClassName=" pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B"
>
@@ -3,7 +3,7 @@ import {App, Button, Form, Input, Row, Select} from "antd";
import {Link, useLocation, useNavigate, useParams} from "react-router-dom";
import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx";
import { v4 as uuidv4 } from 'uuid'
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {MemberItem} from "@common/const/type.ts";
import {useFetch} from "@common/hooks/http.ts";
import {DefaultOptionType} from "antd/es/cascader";
@@ -34,10 +34,10 @@ const TeamConfig= forwardRef<TeamConfigHandle,TeamConfigProps>((props,ref) => {
const [managerOption, setManagerOption] = useState<DefaultOptionType[]>([])
const { setBreadcrumb} = useBreadcrumb()
const { setTeamInfo } =useTeamContext()
const {checkPermission,accessInit} = useGlobalContext()
const {checkPermission,accessInit,state} = useGlobalContext()
const pageType= useMemo(()=>{
if(!accessInit) return 'myteam'
return checkPermission('system.organization.team.view') ? 'manage' : 'myteam'
return checkPermission('system.workspace.team.view_all') ? 'manage' : 'myteam'
},[checkPermission,accessInit])
const [canDelete, setCanDelete] = useState<boolean>(false)
@@ -128,7 +128,10 @@ const TeamConfig= forwardRef<TeamConfigHandle,TeamConfigProps>((props,ref) => {
getTeamInfo();
} else {
setOnEdit(false);
form.setFieldsValue({id:uuidv4()}); // 清空 initialValues
form.setFieldsValue(
{id:uuidv4(),
master:state?.userData?.uid
}); // 清空 initialValues
}
return (form.setFieldsValue({}))
}, [teamId]);
@@ -197,7 +200,7 @@ const TeamConfig= forwardRef<TeamConfigHandle,TeamConfigProps>((props,ref) => {
<p className="text-left"><span className="font-bold">{$t('删除团队')}</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
<div className="text-left">
<WithPermission access="system.organization.team.delete" disabled={!canDelete} tooltip={canDelete ? '':$t('服务数据清除后,方可删除')}>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger onClick={()=>deleteTeam(entity!)}>{$t('删除')}</Button>
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger onClick={()=>deleteTeam()}>{$t('删除')}</Button>
</WithPermission>
</div>
</div>
@@ -20,7 +20,7 @@ import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import { $t } from "@common/locales/index.ts";
export const getDepartmentWithMember = (department:(DepartmentListItem & {type?:'department'|'member'})[],departmentMap:Map<string, (MemberItem & {type:'department'|'member'})[]>) : (DepartmentWithMemberItem | undefined)[] =>{
return department.map((x:DepartmentListItem & {type?:'department'|'member'})=>{
return department?.map((x:DepartmentListItem & {type?:'department'|'member'})=>{
const res = ({
...x,
key:x.id,
@@ -28,7 +28,7 @@ export const getDepartmentWithMember = (department:(DepartmentListItem & {type?:
type: x.type || 'department',
children:((x.type === 'member' || (!x.children||x.children.length === 0 )&& (!departmentMap.get(x.id) || departmentMap.get(x.id)!.length === 0))? undefined : [...(x.children && x.children.length > 0 ? getDepartmentWithMember(x.children,departmentMap) : []),...departmentMap.get(x.id) || []])
});
return res}).filter(node=>node.type === 'member' ||( node.children && node.children.length > 0))
return res})?.filter(node=>node.type === 'member' ||( node.children && node.children.length > 0)) || []
}
export const addMemberToDepartment = (departmentMap: Map<string, (MemberItem & {type:'department'|'member'})[]>, departmentId: string, member: MemberItem) => {
@@ -84,6 +84,7 @@ const TeamInsideMember:FC = ()=>{
addMemberToDepartment(departmentMap, '_withoutDepartment', member);
}
});
const finalData = departmentResponse.data.department
? [
@@ -93,30 +94,33 @@ const TeamInsideMember:FC = ()=>{
name: departmentResponse.data.department.name,
title:departmentResponse.data.department.name,
children: [
...getDepartmentWithMember(departmentResponse.data.department.children, departmentMap),
...getDepartmentWithMember(departmentResponse.data.department?.children || [], departmentMap),
...departmentMap.get('_withoutDepartment') || []
]
}
]
: [...departmentMap.get('_withoutDepartment') || []];
let allMemberSelectedFlag:boolean = true
for(const [k,v] of departmentMap){
if(k !== '_withoutDepartment' && allMemberIds.length > 0 ){
// 筛选出部门内没被勾选的用户,如果不存在没勾选用户,需要将部门id放入ids中
if(v.filter(m => allMemberIds.indexOf(m.id) === -1).length === 0){
setAllMemberSelectedDepartIds((pre)=>[...pre, k])
}else if(['unknown','disable'].indexOf(k) === -1){
allMemberSelectedFlag = false
}
}
}
if(!finalData[0].children || finalData[0].children.filter(m => allMemberIds.indexOf(m.id) === -1).length === 0){
setAllMemberSelectedDepartIds((pre)=>[...pre, topDepartmentId])
if(departmentMap.get('_withoutDepartment')?.filter(x=>allMemberIds.indexOf(x)!==-1).length === 0 && allMemberSelectedFlag){
setAllMemberSelectedDepartIds((pre)=>[...pre, topDepartmentId])
}
return {data:finalData, success: true}
}).catch(()=>({data:[], success:false}))
}
const getMemberList = ()=>{
return fetchData<BasicResponse<{members:TeamMemberTableListItem}>>('team/members',{method:'GET',eoParams:{keyword:searchWord, team:teamId},eoTransformKeys:['attach_time','is_delete']}).then(response=>{
@@ -214,7 +218,6 @@ const TeamInsideMember:FC = ()=>{
const changeMemberInfo = (value:string[],entity:TeamMemberTableListItem )=>{
//console.log(value)
return new Promise((resolve, reject) => {
fetchData<BasicResponse<null>>(`team/member/role`, {method: 'PUT',eoBody:({roles:value, users:[entity.user.id]}), eoParams: {team:teamId}}).then(response => {
const {code, msg} = response
@@ -252,6 +255,7 @@ const TeamInsideMember:FC = ()=>{
<Select
className="w-full"
mode="multiple"
maxTagCount="responsive"
value={entity.roles?.map((x:EntityItem)=>x.id)}
options={roleList?.map((x:{id:string,name:string})=>({label:(x.name), value:x.id}))}
onChange={(value)=>{
@@ -272,7 +276,6 @@ const TeamInsideMember:FC = ()=>{
},[ state.language,roleList])
useEffect(() => {
getRoleList()
setBreadcrumb([
{title:<Link to="/team/list">{$t('团队')}</Link>},
{title:$t('成员')}
@@ -280,6 +283,11 @@ const TeamInsideMember:FC = ()=>{
manualReloadTable()
}, [teamId]);
useEffect(()=>{
getRoleList()
},[state.language])
const treeDisabledData = useMemo(()=>{ return [...allMemberIds,...allMemberSelectedDepartIds]},[allMemberIds,allMemberSelectedDepartIds])
return (
@@ -302,7 +310,7 @@ const TeamInsideMember:FC = ()=>{
title={$t("添加成员")}
open={modalVisible}
destroyOnClose={true}
width={900}
width={600}
onCancel={() => cleanModalData()}
maskClosable={false}
footer={[
@@ -329,7 +337,7 @@ const TeamInsideMember:FC = ()=>{
const memberKeyFromModal = Array.from(selectedData)?.filter(x => allMemberIds.indexOf(x) === -1 &&selectableMemberIds.has(x)) || [];
setAddMemberBtnDisabled((memberKeyFromModal.length === 0));
}}
searchPlaceholder={$t("搜索用户名、邮箱")}
searchPlaceholder={$t("输入名称查找用户")}
/>
</Modal>
</>
@@ -1,16 +1,15 @@
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx"
import PageList from "@common/components/aoplatform/PageList.tsx"
import {ActionType} from "@ant-design/pro-components";
import {FC, useEffect, useMemo, useRef, useState} from "react";
import {useLocation, useNavigate} from "react-router-dom";
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
import {App, Divider, Modal} from "antd";
import {BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import {App, Modal} from "antd";
import {BasicResponse, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
import { SimpleMemberItem } from "@common/const/type.ts";
import {useFetch} from "@common/hooks/http.ts";
import { TEAM_TABLE_COLUMNS } from "../../const/team/const.tsx";
import { TeamConfigFieldType, TeamConfigHandle, TeamTableListItem } from "../../const/team/type.ts";
import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx";
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
import { checkAccess } from "@common/utils/permission.ts";
import TeamConfig from "./TeamConfig.tsx";
@@ -131,21 +130,6 @@ const TeamList:FC = ()=>{
})
}
const operation:PageProColumns<TeamTableListItem>[] =[
{
title: COLUMNS_TITLE.operate,
key: 'option',
fixed:'right',
btnNums:2,
valueType: 'option',
render: (_: React.ReactNode, entity: TeamTableListItem) => [
<TableBtnWithPermission access="" key="view" btnType="view" navigateTo={`../inside/${entity.id}/setting`} btnTitle="查看"/>,
<Divider type="vertical" className="mx-0" key="div2"/>,
<TableBtnWithPermission access="system.organization.team.delete" key="delete" btnType="delete" disabled={!entity.canDelete} tooltip="服务数据清除后,方可删除" onClick={()=>{openModal('delete',entity)}} btnTitle="删除"/>,
],
}
]
useEffect(() => {
setBreadcrumb([
{title: $t('团队')}
@@ -173,7 +157,7 @@ const TeamList:FC = ()=>{
id="global_team"
className="pl-btnbase"
ref={pageListRef}
columns = {[...columns,...operation]}
columns = {[...columns]}
request = {()=>getTeamList()}
showPagination={false}
addNewBtnTitle={$t('添加团队')}
@@ -207,7 +191,7 @@ const TeamList:FC = ()=>{
}
return res})}
>
<TeamConfig ref={teamConfigRef} inModal entity={modalType === 'add' ? undefined : curTeam} />
<TeamConfig ref={teamConfigRef} entity={modalType === 'add' ? undefined : curTeam} />
</Modal>
</InsidePage>
)
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2024-06-05 09:35:25
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:50:12
* @FilePath: \frontend\packages\core\start-vite.js
*/
// start-vite.js// start-vite.js
import { exec } from 'child_process';
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:44
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:36:46
* @FilePath: \frontend\packages\core\tailwind.config.js
*/
/** @type {import('tailwindcss').Config} */
export default {
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2023-11-29 15:49:05
* @FilePath: \applatform\frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
@@ -231,9 +231,9 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
}
return (
<div className={`h-full overflow-hidden pb-btnybase flex flex-col bg-[#fff]`}>
<div className={`h-full overflow-hidden pb-btnybase flex flex-col bg-[#fff] `}>
<ScrollableSection>
<div className="flex items-center flex-wrap pb-[10px] px-btnbase content-before bg-MAIN_BG">
<div className="flex items-center flex-wrap pb-[10px] px-btnbase content-before bg-MAIN_BG pr-PAGE_INSIDE_X ">
<TimeRangeSelector
labelSize="small"
initialTimeButton={timeButton}
@@ -247,7 +247,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
</div>
<Spin wrapperClassName={`flex-1 ${totalEmpty ?'':'overflow-auto'}`} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={queryBtnLoading}>
{totalEmpty ?<Empty className="mt-[100px]" image={Empty.PRESENTED_IMAGE_SIMPLE} />:
<div className=" h-full scroll-area">
<div className=" h-full scroll-area pr-PAGE_INSIDE_X ">
{/* 图表区域 */}
<div className=" px-btnbase mt-[12px] mb-[16px] grid gap-[20px]" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(570px, 1fr))'}}>
{/* 请求统计饼图 */}
@@ -10,7 +10,6 @@ import { reject } from "lodash-es";
import { EntityItem } from "@common/const/type";
import { LoadingOutlined } from "@ant-design/icons";
import DashboardInstruction from "./DashboardInstruction";
import cluster from "cluster";
export default function Dashboard(){
const { setBreadcrumb } = useBreadcrumb()
@@ -47,7 +46,7 @@ export default function Dashboard(){
return (
<>
<Spin wrapperClassName="h-full w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B " indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={loading}>
<Spin wrapperClassName="h-full w-full pb-PAGE_INSIDE_B " indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={loading}>
{
!loading && <>
{
@@ -1,4 +1,5 @@
import WithPermission from "@common/components/aoplatform/WithPermission";
import { $t } from "@common/locales";
import { Link } from "react-router-dom";
@@ -15,13 +16,13 @@ export default function DashboardInstruction({showClusterIns, showMonitorIns}:{s
{showClusterIns && <div className="h-[208px] w-[50%] max-w-[384px] flex flex-col items-center py-[32px] px-[24px] gap-[16px] rounded-DEFAULT bg-MENU_BG mr-[24px] justify-around">
<p className="text-[20px] font-medium leading-[32px] text-MAIN_TEXT">{$t('集群配置')}</p>
<p className="text-[12px] font-normal leading-[20px] text-DESC_TEXT">{$t('配置集群地址,以确保监控系统能够正确识别和连接到集群')}</p>
<p><a href="/cluster" target="_blank">{$t('配置集群信息')}</a></p>
<p><WithPermission access="system.settings.api_gateway.view" ><a href="/cluster" target="_blank">{$t('配置集群信息')}</a></WithPermission></p>
</div>}
{showMonitorIns &&
<div className="h-[208px] w-[50%] max-w-[384px] flex flex-col items-center py-[32px] px-[24px] gap-[16px] rounded-DEFAULT bg-MENU_BG justify-around">
<p className="text-[20px] font-medium leading-[32px] text-MAIN_TEXT">{$t('监控设置')}</p>
<p className="text-[12px] font-normal leading-[20px] text-DESC_TEXT">{$t('设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。')}</p>
<p><a href="/datasourcing" target="_blank">{$t('配置监控信息')}</a></p>
<p><WithPermission access="system.settings.data_source.view" ><a href="/datasourcing" target="_blank">{$t('配置监控信息')}</a></WithPermission></p>
</div>
}
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:44
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:36:11
* @FilePath: \frontend\packages\market\tailwind.config.js
*/
/** @type {import('tailwindcss').Config} */
export default {
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:42:18
* @FilePath: \frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
@@ -25,7 +25,6 @@ export const SERVICE_HUB_TABLE_COLUMNS: PageProColumns<ServiceHubTableListItem>[
title:('团队'),
dataIndex: ['team','name'],
ellipsis:true,
renderText:(_,entity:ServiceHubTableListItem)=>entity.tags?.map(x=>x.name).join(',') || '-'
},
{
title:('订阅服务数量'),
@@ -89,10 +89,10 @@ const ServiceHubDetail = ()=>{
const getMySelectList = ()=>{
setMySystemOptionList([])
fetchData<BasicResponse<{ apps: SimpleSystemItem[] }>>('simple/apps/mine',{method:'GET'}).then(response=>{
fetchData<BasicResponse<{ app: EntityItem[] }>>('apps/can_subscribe',{method:'GET'}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setMySystemOptionList(data.apps?.map((x:SimpleSystemItem)=>{return {
setMySystemOptionList(data.app?.map((x:EntityItem)=>{return {
label:x.name, value:x.id
}}))
}else{
@@ -8,6 +8,9 @@ import { useFetch } from "@common/hooks/http";
import { useNavigate } from "react-router-dom";
import { useTenantManagementContext } from "@market/contexts/TenantManagementContext";
import { $t } from "@common/locales";
import Select, { DefaultOptionType } from "antd/es/select";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
import { SimpleTeamItem, MemberItem } from "@common/const/type";
export type ManagementConfigFieldType = {
name:string
@@ -21,6 +24,7 @@ type ManagementConfigProps = {
type:'add'|'edit'
teamId:string
appId?:string
dataShowType?:'block'|'list'
}
export type ManagementConfigHandle = {
@@ -30,16 +34,18 @@ export type ManagementConfigHandle = {
const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps>((props, ref) => {
const { message,modal } = App.useApp()
const {type,teamId,appId} = props
const {type,teamId,appId,dataShowType} = props
const [form] = Form.useForm();
const {fetchData} = useFetch()
const [delBtnLoading, setDelBtnLoading] = useState<boolean>(false)
const {setAppName} = type === 'edit' ? useTenantManagementContext():{setAppName:()=>{}}
const navigate = type === 'edit' ? useNavigate() : ()=>{}
const [teamOptionList, setTeamOptionList] = useState<DefaultOptionType[]>()
const {checkPermission,accessInit, getGlobalAccessData} = useGlobalContext()
const save:()=>Promise<boolean | string> = ()=>{
return new Promise((resolve, reject)=>{
form.validateFields().then((value)=>{
fetchData<BasicResponse<{apps:ManagementConfigFieldType}>>(type === 'add'? 'team/app' : 'app/info',{method:type === 'add'? 'POST' : 'PUT',eoBody:(value), eoParams:type === 'add' ? {team:teamId}:{app:appId,team:teamId}}).then(response=>{
fetchData<BasicResponse<{apps:ManagementConfigFieldType}>>(type === 'add'? 'team/app' : 'app/info',{method:type === 'add'? 'POST' : 'PUT',eoBody:(value), eoParams:type === 'add' ? {team:dataShowType === 'list' ? value.team : teamId}:{app:appId,team:teamId}}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || $t(RESPONSE_TIPS.success))
@@ -68,6 +74,24 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
})
};
const getTeamOptionList = ()=>{
setTeamOptionList([])
fetchData<BasicResponse<{ teams: SimpleTeamItem[] }>>(!checkPermission('system.workspace.team.view_all') ?'simple/teams/mine' :'simple/teams',{method:'GET',eoTransformKeys:[]}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setTeamOptionList(data.teams?.map((x:MemberItem)=>{return {...x,
label:x.name, value:x.id
}}))
if(form.getFieldValue('team') === undefined&&data.teams?.length){
form.setFieldValue('team',data.teams[0].id);
}
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
})
}
const deleteApplicationModal = async ()=>{
setDelBtnLoading(true)
modal.confirm({
@@ -112,7 +136,17 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
if(type === 'edit'){
appId && getApplicationInfo()
}else{
form.setFieldValue('id',uuidv4())
form.setFieldsValue({
'id':uuidv4()})
}
if(type !== 'edit' && dataShowType === 'list'){
if(accessInit){
getTeamOptionList()
}else{
getGlobalAccessData()?.then?.(()=>{
getTeamOptionList()
})
}
}
}, [appId]);
@@ -146,6 +180,16 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} disabled={type === 'edit'}/>
</Form.Item>
{dataShowType === 'list' && <Form.Item<ManagementConfigFieldType>
label={$t("所属团队")}
name="team"
rules={[{ required: true }]}
>
<Select className="w-INPUT_NORMAL" disabled={type === 'edit'} placeholder={$t(PLACEHOLDER.input)} options={teamOptionList} >
</Select>
</Form.Item>}
<Form.Item
label={$t("描述")}
name="description"
@@ -14,7 +14,9 @@ import { ManagementConfigFieldType } from "./ManagementConfig";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
import { $t } from "@common/locales";
import { getItem } from "@common/utils/navigation";
import { MenuItemType } from "antd/es/menu/interface";
import { MenuItemGroupType, MenuItemType } from "antd/es/menu/interface";
import { PERMISSION_DEFINITION } from "@common/const/permissions";
import { cloneDeep } from "lodash-es";
export default function ManagementInsidePage(){
const { message } = App.useApp()
@@ -27,17 +29,29 @@ export default function ManagementInsidePage(){
const [openKeys, setOpenKeys] = useState<string[]>([])
const [loading, setLoading] = useState<boolean>(false)
const {appName,setAppName} = useTenantManagementContext()
const {getTeamAccessData,cleanTeamAccessData,state} = useGlobalContext()
const {getTeamAccessData,cleanTeamAccessData,state,accessData,checkPermission,accessInit} = useGlobalContext()
const TENANT_MANAGEMENT_APP_MENU: MenuProps['items'] = useMemo(()=>[
getItem($t('订阅的服务'), 'service'),
getItem($t('访问授权'), 'authorization'),
getItem($t('消费者管理'), 'setting'),
getItem($t('订阅的服务'), 'service',undefined, undefined, undefined, 'team.application.subscription.view'),
getItem($t('访问授权'), 'authorization',undefined, undefined, undefined, 'team.consumer.authorization.view'),
getItem($t('消费者管理'), 'setting',undefined, undefined, undefined, 'team.application.application.view'),
],[state.language])
const menuData = useMemo(()=>{
return TENANT_MANAGEMENT_APP_MENU
},[])
const filterMenu = (menu:(MenuItemType&{access:string})[])=>{
const newMenu = cloneDeep(menu)
return newMenu!.filter((c:MenuItemType&{access:string} )=>{
if(!c) return false
return (((c as MenuItemType&{access:string} ).access ?
checkPermission((c as MenuItemType&{access:string} ).access as keyof typeof PERMISSION_DEFINITION[0]):
true))
})}
const filteredMenu = filterMenu(TENANT_MANAGEMENT_APP_MENU as (MenuItemType&{access:string})[])
const menu = activeMenu ?? filteredMenu[0]?.children ? filteredMenu[0]?.children?.[0]?.key : filteredMenu[0]?.key
if(menu && currentUrl.split('/')[-1] !== menu) navigateTo(`/consumer/${teamId}/inside/${appId}/${menu}`)
return filteredMenu || []
},[accessData,accessInit, TENANT_MANAGEMENT_APP_MENU])
useEffect(()=>{
setActiveMenu(currentUrl.split('/').pop() || 'service')
@@ -1,5 +1,5 @@
import { MenuProps, Menu, App, Avatar, Card, Tooltip, Empty, Button, Radio } from "antd";
import { useState, forwardRef, useEffect, useRef, useMemo, memo } from "react";
import { useState, forwardRef, useEffect, useRef, useMemo, memo, Ref, useImperativeHandle } from "react";
import { VirtuosoGrid } from "react-virtuoso";
import { BasicResponse, DATA_SHOW_TYPE_OPTIONS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { ServiceHubAppListItem } from "../../../const/serviceHub/type";
@@ -17,6 +17,7 @@ import WithPermission from "@common/components/aoplatform/WithPermission";
import InsidePage from "@common/components/aoplatform/InsidePage";
import PageList from "@common/components/aoplatform/PageList";
import { SERVICE_HUB_TABLE_COLUMNS } from "@market/const/serviceHub/const";
import { ActionType } from "@ant-design/pro-components";
export default function ServiceHubManagement() {
const { message ,modal} = App.useApp()
@@ -36,23 +37,25 @@ export default function ServiceHubManagement() {
const [tableHttpReload, setTableHttpReload] = useState(true);
const [tableListDataSource, setTableListDataSource] = useState<ServiceHubAppListItem[]>([]);
const [tableSearchWord, setTableSearchWord] = useState<string>('')
const tableRef = useRef<TableAreaHandle>(null)
const getServiceList = ()=>{
if(!accessInit){
getGlobalAccessData()?.then?.(()=>{getServiceList()})
return Promise.resolve({data:[], success:false})
}
const getServiceList = (dataType?:'block'|'list')=>{
dataType = dataType ?? dataShowType
if(!accessInit){
getGlobalAccessData()?.then?.(()=>{getServiceList(dataType)})
return Promise.resolve({data:[], success:false})
}
if(dataType === 'list' && !tableHttpReload){
setTableHttpReload(true)
return Promise.resolve({
data: tableListDataSource,
success: true,
});
}
if(dataShowType === 'list' && !tableHttpReload){
setTableHttpReload(true)
return Promise.resolve({
data: tableListDataSource,
success: true,
});
}
setServiceLoading(true)
return fetchData<BasicResponse<{apps:ServiceHubAppListItem}>>(!checkPermission('system.workspace.application.view_all') ? 'my_apps':'apps',{method:'GET',eoParams:{ team:teamId,keyword:tableSearchWord},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num','auth_num']}).then(response=>{
setServiceLoading(true)
return fetchData<BasicResponse<{apps:ServiceHubAppListItem}>>(!checkPermission('system.workspace.application.view_all') ? 'my_apps':'apps',{method:'GET',eoParams:{ team: dataType === 'list' ? undefined : teamId,keyword:tableSearchWord},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num','auth_num','create_time','can_delete']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setServiceList([...data.apps,{type:'addNewItem'}])
@@ -75,36 +78,78 @@ const getServiceList = ()=>{
};
const getTeamsList = ()=>{
if(!accessInit){
getGlobalAccessData()?.then?.(()=>{getTeamsList()})
return
}
setPageLoading(true)
fetchData<BasicResponse<{ teams: SimpleTeamItem[] }>>(!checkPermission('system.workspace.team.view_all') ?'simple/teams/mine' :'simple/teams',{method:'GET',eoTransformKeys:['app_num','subscribe_num']}).then(response=>{
const {code,data,msg} = response
if(code === STATUS_CODE.SUCCESS){
setTeamList(data.teams.map((x:SimpleTeamItem)=>({label:<div className="flex items-center justify-between "><span className="w-[calc(100%-42px)] truncate" title={x.name}>{x.name}</span><span className="bg-[#fff] rounded-[5px] h-[20px] w-[30px] flex items-center justify-center">{x.appNum || 0}</span></div>, key:x.id})))
if(!teamId && data.teams?.[0]?.id){
navigateTo(data.teams[0].id)
const getTeamsList = () => {
setPageLoading(true);
const fetchTeams = () => {
fetchData<BasicResponse<{ teams: SimpleTeamItem[] }>>(
!checkPermission('system.workspace.team.view_all')
? 'simple/teams/mine'
: 'simple/teams',
{
method: 'GET',
eoTransformKeys: ['app_num', 'subscribe_num'],
}
}else{
message.error(msg || $t(RESPONSE_TIPS.error))
}
}).finally(()=>{
setPageLoading(false)
})
}
)
.then(response => {
const { code, data, msg } = response;
if (code === STATUS_CODE.SUCCESS) {
setTeamList(
data.teams.map((x: SimpleTeamItem) => ({
label: (
<div className="flex items-center justify-between">
<span className="w-[calc(100%-42px)] truncate" title={x.name}>
{x.name}
</span>
<span className="bg-[#fff] rounded-[5px] h-[20px] w-[30px] flex items-center justify-center">
{x.appNum || 0}
</span>
</div>
),
key: x.id,
}))
);
if (!teamId && data.teams?.[0]?.id) {
navigateTo(data.teams[0].id);
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error));
}
})
.finally(() => {
setPageLoading(false);
});
};
if (!accessInit) {
const checkAccessData = () => {
const accessInitd = getGlobalAccessData();
if (!accessInitd) {
setTimeout(checkAccessData, 100);
return;
}
if (typeof accessInitd.then === 'function') {
accessInitd.then(fetchTeams);
} else {
fetchTeams();
}
};
checkAccessData();
} else {
fetchTeams();
}
};
const openModal = async (type:'add'|'edit'|'delete')=>{
let title:string = ''
let content:string|React.ReactNode = ''
switch (type){
case 'add':
title=$t('添加消费者')
content=<ManagementConfig ref={addManagementRef} type={type} teamId={teamId!} />
content=<ManagementConfig ref={addManagementRef} dataShowType={dataShowType} type={type} teamId={teamId!} />
break;
// case 'edit':{
// title='配置 Open Api'
@@ -130,7 +175,15 @@ const getServiceList = ()=>{
onOk:()=> {
switch (type){
case 'add':
return addManagementRef.current?.save().then((res)=>{if(res === true) getTeamsList();getServiceList()})
return addManagementRef.current?.save().then((res)=>{if(res === true) {
getTeamsList();
if(dataShowType === 'list'){
setTableHttpReload(true)
tableRef.current?.manualReloadTable()
}else{
getServiceList()
}
}})
// case 'edit':
// return editManagementRef.current?.save().then((res)=>{if(res === true) manualReloadTable()})
// case 'delete':
@@ -196,7 +249,7 @@ useEffect(() => {
item.type === 'addNewItem' ?<WithPermission access="team.application.application.add" showDisabled={false}><Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{body:'h-[180px] flex items-center justify-center cursor-pointer'}} onClick={()=>{openModal('add')}}>
<div className="flex items-center"><Icon icon="ic:baseline-add" width="18" height="18"/><span>{$t('添加消费者')}</span></div>
</Card></WithPermission> : <Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>{setAppName(item.name);navigateTo(`/consumer/${teamId}/inside/${item.id}/service`)}}>
<span className="line-clamp-3 break-all">{item.description || $t('暂无服务描述')}</span>
<span className="line-clamp-3 break-all">{item.description || $t('暂无消费者描述')}</span>
</Card>}</div>
);
@@ -241,13 +294,13 @@ useEffect(() => {
customBtn={
<Radio.Group
options={dataShowTypeOptions}
onChange={(e)=>setDataShowType(e.target.value)}
onChange={(e)=>{setDataShowType(e.target.value); setTableHttpReload(true); if(e.target.value === 'block'){getServiceList(e.target.value)}}}
value={dataShowType}
optionType="button"
buttonStyle="solid"
/>}
>{
dataShowType === 'block' ? <BlockArea /> : <TableArea language={state.language} getServiceList={getServiceList} addNewApp={()=>openModal('add')} setTableHttpReload={setTableHttpReload} setTableSearchWord={setTableSearchWord} editApp={(row:ServiceHubAppListItem)=>{setAppName(row.name);navigateTo(`/consumer/${row.team.id}/inside/${row.id}/service`)}}/>
dataShowType === 'block' ? <BlockArea /> : <TableArea language={state.language} getServiceList={()=>getServiceList('list')} ref={tableRef} addNewApp={()=>openModal('add')} setTableHttpReload={setTableHttpReload} setTableSearchWord={setTableSearchWord} editApp={(row:ServiceHubAppListItem)=>{setAppName(row.name);navigateTo(`/consumer/${row.team.id}/inside/${row.id}/service`)}}/>
}
</InsidePage> :
<Empty className="mt-[100px]" image={Empty.PRESENTED_IMAGE_SIMPLE} />
@@ -281,20 +334,35 @@ type TableAreaProps = {
editApp:(item:ServiceHubAppListItem)=>void
}
const TableArea = memo(({language, getServiceList, addNewApp, setTableHttpReload, setTableSearchWord, editApp}:TableAreaProps)=>{
type TableAreaHandle = {
manualReloadTable:()=>void
}
const TableArea = memo(forwardRef((props:TableAreaProps, ref:Ref<TableAreaHandle>)=>{
const {language, getServiceList, addNewApp, setTableHttpReload, setTableSearchWord, editApp} = props
const pageListRef = useRef<ActionType>(null);
const columns = useMemo(()=>{
const res = SERVICE_HUB_TABLE_COLUMNS.map(x=>{
return {...x,title:typeof x.title === 'string' ? $t(x.title as string) : x.title}})
return res
},[language])
const manualReloadTable = ()=>{
pageListRef.current?.reload()
}
useImperativeHandle(ref, () =>({
manualReloadTable}))
return (
<PageList
id="service_hub_list"
ref={pageListRef}
columns={[...columns]}
request={()=>getServiceList()}
addNewBtnTitle={$t("添加服务")}
searchPlaceholder={$t("输入名称、ID 查找服务")}
addNewBtnTitle={$t("添加消费者")}
searchPlaceholder={$t("输入名称、ID 查找消费者")}
onAddNewBtnClick={addNewApp}
onChange={() => {
setTableHttpReload(false)
@@ -304,4 +372,4 @@ const TableArea = memo(({language, getServiceList, addNewApp, setTableHttpReload
}}
onRowClick={(row:ServiceHubAppListItem)=>editApp(row)}
/>
)})
)}))
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2023-11-29 15:49:05
* @FilePath: \applatform\frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
+1 -6
View File
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:44
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:36:11
* @FilePath: \frontend\packages\market\tailwind.config.js
*/
/** @type {import('tailwindcss').Config} */
export default {
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:54
* @LastEditors: maggieyyy
* @LastEditTime: 2023-11-29 15:49:05
* @FilePath: \applatform\frontend\packages\core\postcss.config.js
*/
export default {
plugins: {
'postcss-import': {},
@@ -1,9 +1,4 @@
/*
* @Date: 2023-11-27 17:31:44
* @LastEditors: maggieyyy
* @LastEditTime: 2024-06-05 10:36:11
* @FilePath: \frontend\packages\market\tailwind.config.js
*/
/** @type {import('tailwindcss').Config} */
export default {

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