mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Compare commits
295 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e449f86c01 | |||
| a1bdc048a7 | |||
| 0a1b08157d | |||
| d36c66371f | |||
| b7bb409e96 | |||
| 517007c941 | |||
| 4c685a9ec6 | |||
| 1aca2099de | |||
| a93e5b4ff8 | |||
| 85d25bebe2 | |||
| 9fa43ccc00 | |||
| c2a11050dd | |||
| 080bfc3a44 | |||
| f6956ddeca | |||
| 9f56fa5e14 | |||
| ccc39b95de | |||
| 9a2782e54b | |||
| 22455e2301 | |||
| 8ed2c84b68 | |||
| ccd2a209e2 | |||
| baf8ed4830 | |||
| dedb586daf | |||
| 21cd823791 | |||
| c8ab65ef1b | |||
| f1c16fd992 | |||
| 52035341f6 | |||
| aa62d44717 | |||
| a072d1fc8d | |||
| 38a00570d0 | |||
| 43283b9da3 | |||
| ef82cdbed6 | |||
| 2bafe6f31f | |||
| 3eb4f98fd8 | |||
| bb5acad033 | |||
| b8308a446b | |||
| c86f99ce45 | |||
| 952c519e45 | |||
| 07d97fa0bf | |||
| b0defedf04 | |||
| edc2fccdeb | |||
| a75b8a3f13 | |||
| 5aab5f7913 | |||
| 9ab7989c8b | |||
| e3e11d740a | |||
| 4bae2edc49 | |||
| 4eaa47ca25 | |||
| e01f596525 | |||
| 912e8d0d04 | |||
| 570c80af91 | |||
| 7aa0ec0d67 | |||
| 2fea6cb622 | |||
| 2195ff900f | |||
| 836c7699b8 | |||
| 72ed6c814e | |||
| c33b070509 | |||
| de12d5686c | |||
| c55a8ac805 | |||
| df3626f3f0 | |||
| 28bef97faa | |||
| 9897b6e9dc | |||
| 9af6963901 | |||
| c2d3ebecda | |||
| ba543311fc | |||
| 87b8dda97b | |||
| e7facf5686 | |||
| 4dd57837c5 | |||
| d4ebc68e30 | |||
| 1f8e089e51 | |||
| ce6f463fe8 | |||
| a37fe1d794 | |||
| 818d1ec6bf | |||
| fc4a5f7e28 | |||
| 0e3568b584 | |||
| 3617e4fe29 | |||
| f2fddc1727 | |||
| 3b7204f1a6 | |||
| 6646bb1e56 | |||
| c27533f802 | |||
| 613a47c181 | |||
| 90138a142b | |||
| 4bf8db4898 | |||
| 4f887f7204 | |||
| 14e17ccf2c | |||
| 5975670b8c | |||
| dbc4bc3343 | |||
| ada7635703 | |||
| 943a77f718 | |||
| ef02c11efa | |||
| 8c166dae9b | |||
| b23da78c26 | |||
| 93ac7310e8 | |||
| 9376acc456 | |||
| b70a1f9a51 | |||
| ac90a134b4 | |||
| 96bd1cf9f6 | |||
| 960e37a81a | |||
| 044bd550c9 | |||
| 0a9a903d1b | |||
| 84d7606e12 | |||
| febb64b8bb | |||
| 932e433c46 | |||
| b7307cd36d | |||
| 7a0f3efd83 | |||
| 28af1f691c | |||
| 796bc7bc15 | |||
| 8f06073783 | |||
| 7d6251b191 | |||
| e13fff633e | |||
| d984be4b85 | |||
| 213bdbd9d5 | |||
| 6a59d27b84 | |||
| ad45ab2e82 | |||
| 8982a63283 | |||
| 1b1515a8bd | |||
| df50e13db0 | |||
| 89d91c14c9 | |||
| 3a57c609f7 | |||
| 2cd331ec50 | |||
| 3fa02ec65c | |||
| f33f1965b4 | |||
| a70ecea02b | |||
| 8e68eb35f3 | |||
| 2893331ff5 | |||
| 1a3d14cdd6 | |||
| dce9a7addb | |||
| f3e7487482 | |||
| 86c39237dc | |||
| b5ad739b93 | |||
| 0b7f0405d5 | |||
| 1ab56708a5 | |||
| 522489c9e9 | |||
| a9eb2a790f | |||
| a092ed1108 | |||
| 503515281d | |||
| 2326d4dfb5 | |||
| 42e8030cf7 | |||
| 17b4ede566 | |||
| bbc3fea848 | |||
| 82e46b872b | |||
| 0f6a091c73 | |||
| 4e87adb4b3 | |||
| 320a2b6cf8 | |||
| b216556867 | |||
| 7fbb98a2a9 | |||
| 461a8edbea | |||
| cdef179bed | |||
| a067388d79 | |||
| 2d5e541593 | |||
| be40186ad3 | |||
| c9ae05b22e | |||
| 2b874fe59f | |||
| 9da5e5d6c0 | |||
| a6bfce2a5f | |||
| 8cbeabe917 | |||
| 1db354077f | |||
| e31d41a276 | |||
| 21d2abf716 | |||
| 3a86a88870 | |||
| 6117a840e1 | |||
| 0e20987fb8 | |||
| 65e7cab772 | |||
| 935f2ac766 | |||
| 3e12d7eb9c | |||
| d6095269b7 | |||
| 0c415b4e32 | |||
| bc1819b368 | |||
| a9be016c87 | |||
| 11da5e9d26 | |||
| 2c6c194821 | |||
| aedd8b4cc6 | |||
| fa2607e9b8 | |||
| 3783e5ee5d | |||
| fd56b8ffed | |||
| 07e288be16 | |||
| 46143c3fe0 | |||
| 83e3cc85f2 | |||
| a4b50ae60a | |||
| a30d0c37eb | |||
| 64fdf59905 | |||
| 1aa3f2fb05 | |||
| 68e8cb72d3 | |||
| a86d3cd65a | |||
| a4b4cbf60f | |||
| 2dcb7ebd74 | |||
| ad6b64ca74 | |||
| d27a2b8cf3 | |||
| 8fa1985feb | |||
| 451efb8d3e | |||
| d6bf3139ff | |||
| 309b9ea937 | |||
| 554bff38c6 | |||
| d5e6062ec9 | |||
| bcb68d552f | |||
| 3de87723ae | |||
| 535d70ac5a | |||
| d588d43aa1 | |||
| f455cecb54 | |||
| b88c0a9305 | |||
| 9030cff8ba | |||
| 98f73f799a | |||
| d2e428ada8 | |||
| 74156ec84c | |||
| f9e6bc92d7 | |||
| 9884586cc9 | |||
| ac717a6efb | |||
| 2b7c1ded15 | |||
| daac27712d | |||
| 1080f33282 | |||
| cc5c0a0a89 | |||
| 85971447e1 | |||
| 256e8ef275 | |||
| c07e54ec03 | |||
| 70f834e1cf | |||
| c320c6f2a2 | |||
| 256eb60df8 | |||
| 5f03973bf2 | |||
| ab2a0d8ae2 | |||
| 7e48402591 | |||
| aa85f6fcd1 | |||
| cd441ccfe7 | |||
| 47f6519006 | |||
| 9679376cb2 | |||
| efa97c3bbc | |||
| 087e598be0 | |||
| 31aa8243ee | |||
| d3d05ef539 | |||
| d6062ea4e7 | |||
| 7949748951 | |||
| 94f7392060 | |||
| 0d737bad57 | |||
| 1225db50c9 | |||
| e5d85bb3df | |||
| 0f09e5c236 | |||
| 0f0204b647 | |||
| 94421d2622 | |||
| 44f0b70461 | |||
| f58768237b | |||
| 588cf839e3 | |||
| 76872b3a97 | |||
| d253d68a12 | |||
| 4de0d29f30 | |||
| 0f0480db63 | |||
| aa40b62e0a | |||
| 68309ac582 | |||
| 522183eb4d | |||
| 4f6fee4d73 | |||
| c5fecf73c8 | |||
| ee8e93d1e8 | |||
| 9d0fa5ea4a | |||
| b0b9affbe7 | |||
| 1d1c7c78e8 | |||
| d7f5b87e70 | |||
| 1048666972 | |||
| 217f5d61c7 | |||
| 2f1677f581 | |||
| afd7ea6a1c | |||
| 7155e14e64 | |||
| 68e5b49f46 | |||
| c01e95c716 | |||
| ffa7e5130e | |||
| 7ce33bfd4c | |||
| 0c64fa9986 | |||
| 07e8b347e1 | |||
| 38a402adef | |||
| 7ab2e29101 | |||
| b96796793b | |||
| baa073b05d | |||
| c944f9de52 | |||
| 5567a65e4b | |||
| c6c775f436 | |||
| c0c43be6b9 | |||
| 9b6074318a | |||
| ada121015d | |||
| 9d7b6c4bc6 | |||
| c262fc4f4d | |||
| 335317bd86 | |||
| 396464c573 | |||
| d93c76ca36 | |||
| 60ad6007e5 | |||
| ceee520102 | |||
| a053557000 | |||
| e7c14b0817 | |||
| 727fd0bd36 | |||
| 4ba2b0c9ab | |||
| b3672b8c66 | |||
| b33dda4a32 | |||
| 450e565718 | |||
| 00bd72c1e4 | |||
| 81da1f45f1 | |||
| fd3d6433e2 | |||
| 9592a0ddda | |||
| bf2aefe2da | |||
| 540a31f237 | |||
| 0505045c81 | |||
| 1a18d79d94 |
@@ -25,7 +25,7 @@ jobs:
|
|||||||
echo "Build frontend..."
|
echo "Build frontend..."
|
||||||
cd ./frontend && pnpm run build
|
cd ./frontend && pnpm run build
|
||||||
- name: upload frontend release
|
- name: upload frontend release
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: frontend-package
|
name: frontend-package
|
||||||
path: frontend/dist
|
path: frontend/dist
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
- name: Checkout #Checkout代码
|
- name: Checkout #Checkout代码
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: download frontend release
|
- name: download frontend release
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: frontend-package
|
name: frontend-package
|
||||||
path: frontend/dist
|
path: frontend/dist
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: download frontend release
|
- name: download frontend release
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: frontend-package
|
name: frontend-package
|
||||||
path: frontend/dist
|
path: frontend/dist
|
||||||
|
|||||||
+1
-1
@@ -3,4 +3,4 @@
|
|||||||
/config.yml
|
/config.yml
|
||||||
/build/
|
/build/
|
||||||
/apipark
|
/apipark
|
||||||
/aoplatform
|
.gitlab-ci.yml
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
variables:
|
|
||||||
PATH: /opt/go-1.21/go/bin/:/opt/node/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
|
|
||||||
GOROOT: /opt/go-1.21/go
|
|
||||||
GOPROXY: https://goproxy.cn
|
|
||||||
VERSION: $CI_COMMIT_SHORT_SHA
|
|
||||||
APP: apipark
|
|
||||||
APP_PRE: ${APP}_${VERSION}
|
|
||||||
BUILD_DIR: ${APP}-build
|
|
||||||
DEPLOY_DESC: "DEV 环境"
|
|
||||||
VIEW_ADDR: http://172.18.166.219:8288
|
|
||||||
SAVE_DIR: /opt/${APP}
|
|
||||||
NODE_OPTIONS: --max_old_space_size=8192
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- notice
|
|
||||||
- prefix
|
|
||||||
- build
|
|
||||||
- deploy
|
|
||||||
- webhook
|
|
||||||
|
|
||||||
feishu-informer: # 飞书回调
|
|
||||||
stage: notice
|
|
||||||
variables:
|
|
||||||
DIFF_URL: "$CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID/diffs"
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE=="merge_request_event" && $CI_COMMIT_BRANCH =~ "main"
|
|
||||||
script:
|
|
||||||
- echo "merge request"
|
|
||||||
- |
|
|
||||||
curl -X POST -H "Content-Type: application/json" \
|
|
||||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"项目:${CI_PROJECT_NAME}\\n提交人:${GITLAB_USER_NAME}\\n提交信息:${CI_MERGE_REQUEST_TITLE}\\n合并分支信息:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} -> ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}\\n差异性地址:${DIFF_URL}\\n请及时review代码\"}}" \
|
|
||||||
https://open.feishu.cn/open-apis/bot/v2/hook/1c334752-2874-41a1-8f1b-3060f2d46b6c
|
|
||||||
|
|
||||||
prebuild:
|
|
||||||
stage: prefix
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == "main"
|
|
||||||
script:
|
|
||||||
- echo "prebuild"
|
|
||||||
- chmod +x ./scripts/prefix.sh
|
|
||||||
- ./scripts/prefix.sh
|
|
||||||
|
|
||||||
builder:
|
|
||||||
stage: build
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == "main"
|
|
||||||
script:
|
|
||||||
- set -e
|
|
||||||
- |
|
|
||||||
if [ ! -d "../artifacts" ]; then
|
|
||||||
mkdir -p ../artifacts
|
|
||||||
fi
|
|
||||||
if [ -d "../artifacts/dist" ]; then
|
|
||||||
cp -r ../artifacts/dist frontend/dist
|
|
||||||
fi
|
|
||||||
- |
|
|
||||||
if [ -n "$(git diff --name-status HEAD~1 HEAD -- frontend)" ]; then
|
|
||||||
./scripts/build.sh $BUILD_DIR ${VERSION} all ""
|
|
||||||
else
|
|
||||||
./scripts/build.sh $BUILD_DIR ${VERSION}
|
|
||||||
fi
|
|
||||||
if [ -d "frontend/dist" ]; then
|
|
||||||
echo "copy frontend/dist to artifacts/dist"
|
|
||||||
rm -fr ../artifacts/dist
|
|
||||||
cp -r frontend/dist ../artifacts/dist
|
|
||||||
fi
|
|
||||||
cp $BUILD_DIR/${APP_PRE}_linux_amd64.tar.gz ${SAVE_DIR}
|
|
||||||
|
|
||||||
deployer:
|
|
||||||
stage: deploy
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == "main"
|
|
||||||
variables:
|
|
||||||
APIPARK_GUEST_MODE: allow
|
|
||||||
APIPARK_GUEST_ID: dklejrfbhjqwdh
|
|
||||||
script:
|
|
||||||
- cd ${SAVE_DIR};mkdir -p ${APP_PRE};tar -zxvf ${APP_PRE}_linux_amd64.tar.gz -C ${APP_PRE};cd ${APP_PRE};./install.sh ${SAVE_DIR};./run.sh restart;cd ${SAVE_DIR} && ./clean.sh ${APP_PRE}
|
|
||||||
when: on_success
|
|
||||||
success:
|
|
||||||
stage: webhook
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == "main"
|
|
||||||
script:
|
|
||||||
- |
|
|
||||||
curl -X POST -H "Content-Type: application/json" \
|
|
||||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署完成.\\n访问地址:${VIEW_ADDR}\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
|
|
||||||
https://open.feishu.cn/open-apis/bot/v2/hook/c3672932-4dfa-4989-8023-0128bae59338
|
|
||||||
when: on_success
|
|
||||||
failure:
|
|
||||||
stage: webhook
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == "main"
|
|
||||||
script:
|
|
||||||
- |
|
|
||||||
curl -X POST -H "Content-Type: application/json" \
|
|
||||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署失败,请及时到gitlab上查看\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
|
|
||||||
https://open.feishu.cn/open-apis/bot/v2/hook/c3672932-4dfa-4989-8023-0128bae59338
|
|
||||||
when: on_failure
|
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Antd",
|
||||||
|
"apinto",
|
||||||
|
"Apipark",
|
||||||
|
"logsettings",
|
||||||
|
"resourcesettings"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -197,7 +197,7 @@ To achieve this goal, we plan to add new features to APIPark, including:
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
# 📕 Documentation
|
# 📕 Documentation
|
||||||
Visit [APIPark Documentation](https://docs.apipark.com/docs/install) for detailed installation guides, API references, and usage instructions.
|
Visit [APIPark Documentation](https://docs.apipark.com/docs/deploy) for detailed installation guides, API references, and usage instructions.
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
placeholder:
|
||||||
zh_Hans: 在此输入您的 API Key
|
zh_Hans: 在此输入您的 API Key
|
||||||
en_US: Enter your 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
|
- variable: openai_api_base
|
||||||
label:
|
label:
|
||||||
zh_Hans: API Base
|
zh_Hans: API Base
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 2048
|
default: 2048
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ parameter_rules:
|
|||||||
use_template: presence_penalty
|
use_template: presence_penalty
|
||||||
- name: frequency_penalty
|
- name: frequency_penalty
|
||||||
use_template: frequency_penalty
|
use_template: frequency_penalty
|
||||||
- name: max_output_tokens
|
- name: max_tokens
|
||||||
use_template: max_tokens
|
use_template: max_tokens
|
||||||
required: true
|
required: true
|
||||||
default: 8192
|
default: 8192
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type imlAPIController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error) {
|
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error) {
|
||||||
info, err := i.serviceModule.Get(ctx, serviceId)
|
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
plugins["ai_formatter"] = api.PluginSetting{
|
plugins["ai_formatter"] = api.PluginSetting{
|
||||||
Config: plugin_model.ConfigType{
|
Config: plugin_model.ConfigType{
|
||||||
"model": input.AiModel.Id,
|
"model": input.AiModel.Id,
|
||||||
"provider": fmt.Sprintf("%s@ai-provider", info.Provider.Id),
|
"provider": fmt.Sprintf("%s@ai-provider", input.AiModel.Provider),
|
||||||
"config": input.AiModel.Config,
|
"config": input.AiModel.Config,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
Retry: input.Retry,
|
Retry: input.Retry,
|
||||||
Plugins: plugins,
|
Plugins: plugins,
|
||||||
},
|
},
|
||||||
Upstream: info.Provider.Id,
|
Upstream: input.AiModel.Provider,
|
||||||
Disable: false,
|
Disable: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error) {
|
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error) {
|
||||||
info, err := i.serviceModule.Get(ctx, serviceId)
|
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -106,11 +106,11 @@ func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string
|
|||||||
proxy.Plugins["ai_formatter"] = api.PluginSetting{
|
proxy.Plugins["ai_formatter"] = api.PluginSetting{
|
||||||
Config: plugin_model.ConfigType{
|
Config: plugin_model.ConfigType{
|
||||||
"model": input.AiModel.Id,
|
"model": input.AiModel.Id,
|
||||||
"provider": fmt.Sprintf("%s@ai-provider", info.Provider.Id),
|
"provider": fmt.Sprintf("%s@ai-provider", input.AiModel.Provider),
|
||||||
"config": input.AiModel.Config,
|
"config": input.AiModel.Config,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
upstream = &info.Provider.Id
|
upstream = &input.AiModel.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.AiPrompt != nil {
|
if input.AiPrompt != nil {
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ func (p *imlCluster) Check(ctx *gin.Context, input *cluster_dto.CheckCluster) ([
|
|||||||
// return id, nil
|
// return id, nil
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//func (p *imlCluster) Search(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
//func (p *imlCluster) SearchByDriver(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
||||||
// return p.module.Search(ctx, keyword)
|
// return p.module.SearchByDriver(ctx, keyword)
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//func (p *imlCluster) Simple(ctx *gin.Context) ([]*parition_dto.Simple, error) {
|
//func (p *imlCluster) Simple(ctx *gin.Context) ([]*parition_dto.Simple, error) {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||||
|
"github.com/eolinker/go-common/autowire"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ILogController interface {
|
||||||
|
Save(ctx *gin.Context, driver string, input *log_dto.Save) error
|
||||||
|
Get(ctx *gin.Context, driver string) (*log_dto.LogSource, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logController := &imlLogController{}
|
||||||
|
autowire.Auto[ILogController](func() reflect.Value {
|
||||||
|
return reflect.ValueOf(logController)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/APIParkLab/APIPark/module/log"
|
||||||
|
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type imlLogController struct {
|
||||||
|
module log.ILogModule `autowired:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *imlLogController) Save(ctx *gin.Context, driver string, input *log_dto.Save) error {
|
||||||
|
return c.module.Save(ctx, driver, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *imlLogController) Get(ctx *gin.Context, driver string) (*log_dto.LogSource, error) {
|
||||||
|
return c.module.Get(ctx, driver)
|
||||||
|
}
|
||||||
@@ -17,6 +17,70 @@ type imlMonitorStatisticController struct {
|
|||||||
module monitor.IMonitorStatisticModule `autowired:""`
|
module monitor.IMonitorStatisticModule `autowired:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *imlMonitorStatisticController) Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error) {
|
||||||
|
switch dataType {
|
||||||
|
case monitor_dto.DataTypeApi:
|
||||||
|
return i.module.ApiStatistics(ctx, input)
|
||||||
|
case monitor_dto.DataTypeProvider:
|
||||||
|
return i.module.ProviderStatistics(ctx, input)
|
||||||
|
case monitor_dto.DataTypeSubscriber:
|
||||||
|
return i.module.SubscriberStatistics(ctx, input)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported data type: %s", dataType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlMonitorStatisticController) InvokeTrend(ctx *gin.Context, dataType string, id string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||||
|
switch dataType {
|
||||||
|
case monitor_dto.DataTypeApi:
|
||||||
|
return i.module.APITrend(ctx, id, input)
|
||||||
|
case monitor_dto.DataTypeProvider:
|
||||||
|
return i.module.ProviderTrend(ctx, id, input)
|
||||||
|
case monitor_dto.DataTypeSubscriber:
|
||||||
|
return i.module.SubscriberTrend(ctx, id, input)
|
||||||
|
default:
|
||||||
|
return nil, "", fmt.Errorf("unsupported data type: %s", dataType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlMonitorStatisticController) InvokeTrendInner(ctx *gin.Context, dataType string, typ string, api string, provider string, subscriber string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||||
|
if dataType == monitor_dto.DataTypeApi && typ == monitor_dto.DataTypeSubscriber || dataType == monitor_dto.DataTypeSubscriber && typ == monitor_dto.DataTypeApi {
|
||||||
|
return i.module.InvokeTrendWithSubscriberAndApi(ctx, api, subscriber, input)
|
||||||
|
} else if dataType == monitor_dto.DataTypeApi && typ == monitor_dto.DataTypeProvider || dataType == monitor_dto.DataTypeProvider && typ == monitor_dto.DataTypeApi {
|
||||||
|
return i.module.InvokeTrendWithProviderAndApi(ctx, provider, api, input)
|
||||||
|
}
|
||||||
|
return nil, "", fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlMonitorStatisticController) StatisticsInner(ctx *gin.Context, dataType string, typ string, id string, input *monitor_dto.StatisticInput) (interface{}, error) {
|
||||||
|
switch dataType {
|
||||||
|
case monitor_dto.DataTypeApi:
|
||||||
|
switch typ {
|
||||||
|
case monitor_dto.DataTypeProvider:
|
||||||
|
return i.module.ProviderStatisticsOnApi(ctx, id, input)
|
||||||
|
case monitor_dto.DataTypeSubscriber:
|
||||||
|
return i.module.SubscriberStatisticsOnApi(ctx, id, input)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||||
|
}
|
||||||
|
case monitor_dto.DataTypeProvider:
|
||||||
|
switch typ {
|
||||||
|
case monitor_dto.DataTypeApi:
|
||||||
|
return i.module.ApiStatisticsOnProvider(ctx, id, input)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||||
|
}
|
||||||
|
case monitor_dto.DataTypeSubscriber:
|
||||||
|
switch typ {
|
||||||
|
case monitor_dto.DataTypeApi:
|
||||||
|
return i.module.ApiStatisticsOnSubscriber(ctx, id, input)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unsupported data type: %s", dataType)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *imlMonitorStatisticController) OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error) {
|
func (i *imlMonitorStatisticController) OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error) {
|
||||||
trend, timeInterval, err := i.module.MessageTrend(ctx, input)
|
trend, timeInterval, err := i.module.MessageTrend(ctx, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ type IMonitorStatisticController interface {
|
|||||||
OverviewInvokeTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []int64, []int64, []int64, []int64, []float64, []float64, string, error)
|
OverviewInvokeTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []int64, []int64, []int64, []int64, []float64, []float64, string, error)
|
||||||
OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error)
|
OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error)
|
||||||
|
|
||||||
//Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error)
|
Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error)
|
||||||
|
|
||||||
|
InvokeTrend(ctx *gin.Context, dataType string, id string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||||
|
|
||||||
|
InvokeTrendInner(ctx *gin.Context, dataType string, typ string, api string, provider string, subscriber string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||||
|
StatisticsInner(ctx *gin.Context, dataType string, typ string, id string, input *monitor_dto.StatisticInput) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IMonitorConfigController interface {
|
type IMonitorConfigController interface {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
||||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||||
"github.com/APIParkLab/APIPark/module/router"
|
"github.com/APIParkLab/APIPark/module/router"
|
||||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ IRouterController = (*imlAPIController)(nil)
|
var _ IRouterController = (*imlAPIController)(nil)
|
||||||
@@ -15,6 +16,10 @@ type imlAPIController struct {
|
|||||||
module router.IRouterModule `autowired:""`
|
module router.IRouterModule `autowired:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *imlAPIController) Simple(ctx *gin.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error) {
|
||||||
|
return i.module.SimpleAPIs(ctx, input)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) {
|
func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) {
|
||||||
return i.module.Detail(ctx, serviceId, apiId)
|
return i.module.Detail(ctx, serviceId, apiId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/eolinker/go-common/autowire"
|
"github.com/eolinker/go-common/autowire"
|
||||||
@@ -24,6 +25,7 @@ type IRouterController interface {
|
|||||||
Delete(ctx *gin.Context, serviceId string, apiId string) error
|
Delete(ctx *gin.Context, serviceId string, apiId string) error
|
||||||
// Prefix 获取API前缀
|
// Prefix 获取API前缀
|
||||||
Prefix(ctx *gin.Context, serviceId string) (string, bool, error)
|
Prefix(ctx *gin.Context, serviceId string) (string, bool, error)
|
||||||
|
Simple(ctx *gin.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IAPIDocController interface {
|
type IAPIDocController interface {
|
||||||
|
|||||||
+162
-33
@@ -5,6 +5,19 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eolinker/go-common/pm3"
|
||||||
|
|
||||||
|
"github.com/APIParkLab/APIPark/module/system"
|
||||||
|
|
||||||
|
"github.com/getkin/kin-openapi/openapi3"
|
||||||
|
|
||||||
|
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
||||||
|
|
||||||
|
upstream_dto "github.com/APIParkLab/APIPark/module/upstream/dto"
|
||||||
|
|
||||||
|
"github.com/eolinker/eosc/log"
|
||||||
|
|
||||||
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
|
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
|
||||||
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
|
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
|
||||||
@@ -22,7 +35,6 @@ import (
|
|||||||
"github.com/APIParkLab/APIPark/module/service"
|
"github.com/APIParkLab/APIPark/module/service"
|
||||||
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
||||||
"github.com/APIParkLab/APIPark/module/upstream"
|
"github.com/APIParkLab/APIPark/module/upstream"
|
||||||
upstream_dto "github.com/APIParkLab/APIPark/module/upstream/dto"
|
|
||||||
"github.com/eolinker/go-common/store"
|
"github.com/eolinker/go-common/store"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -39,29 +51,102 @@ type imlServiceController struct {
|
|||||||
docModule service.IServiceDocModule `autowired:""`
|
docModule service.IServiceDocModule `autowired:""`
|
||||||
aiAPIModule ai_api.IAPIModule `autowired:""`
|
aiAPIModule ai_api.IAPIModule `autowired:""`
|
||||||
routerModule router.IRouterModule `autowired:""`
|
routerModule router.IRouterModule `autowired:""`
|
||||||
|
apiDocModule api_doc.IAPIDocModule `autowired:""`
|
||||||
providerModule ai.IProviderModule `autowired:""`
|
providerModule ai.IProviderModule `autowired:""`
|
||||||
upstreamModule upstream.IUpstreamModule `autowired:""`
|
upstreamModule upstream.IUpstreamModule `autowired:""`
|
||||||
|
settingModule system.ISettingModule `autowired:""`
|
||||||
transaction store.ITransaction `autowired:""`
|
transaction store.ITransaction `autowired:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAIUpstream(id string, provider string, uri model_runtime.IProviderURI) *upstream_dto.Upstream {
|
var (
|
||||||
return &upstream_dto.Upstream{
|
loader = openapi3.NewLoader()
|
||||||
Type: "http",
|
)
|
||||||
Balance: "round-robin",
|
|
||||||
Timeout: 300000,
|
func (i *imlServiceController) swagger(ctx *gin.Context, id string) (*openapi3.T, error) {
|
||||||
Retry: 0,
|
doc, err := i.apiDocModule.GetDoc(ctx, id)
|
||||||
Remark: fmt.Sprintf("auto create by ai service %s,provider is %s", id, provider),
|
if err != nil {
|
||||||
LimitPeerSecond: 0,
|
return nil, err
|
||||||
ProxyHeaders: nil,
|
|
||||||
Scheme: uri.Scheme(),
|
|
||||||
PassHost: "node",
|
|
||||||
Nodes: []*upstream_dto.NodeConfig{
|
|
||||||
{
|
|
||||||
Address: uri.Host(),
|
|
||||||
Weight: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
tmp, err := loader.LoadFromData([]byte(doc.Content))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cfg := i.settingModule.Get(ctx)
|
||||||
|
|
||||||
|
tmp.AddServer(&openapi3.Server{
|
||||||
|
URL: cfg.InvokeAddress,
|
||||||
|
})
|
||||||
|
return tmp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlServiceController) ExportSwagger(ctx *gin.Context) {
|
||||||
|
id, has := ctx.Params.Get("id")
|
||||||
|
if !has {
|
||||||
|
ctx.JSON(200, &pm3.Response{
|
||||||
|
Code: -1,
|
||||||
|
Success: "fail",
|
||||||
|
Message: fmt.Sprintf("id is required"),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s, err := i.module.Get(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(200, &pm3.Response{
|
||||||
|
Code: -1,
|
||||||
|
Success: "fail",
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmp, err := i.swagger(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(200, &pm3.Response{
|
||||||
|
Code: -1,
|
||||||
|
Success: "fail",
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _ := tmp.MarshalJSON()
|
||||||
|
ctx.Status(200)
|
||||||
|
// 设置响应头
|
||||||
|
ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.json", strings.Replace(s.Name, " ", "_", -1)))
|
||||||
|
ctx.Header("Content-Type", "application/octet-stream")
|
||||||
|
ctx.Header("Content-Transfer-Encoding", "binary")
|
||||||
|
ctx.Writer.Write(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlServiceController) Swagger(ctx *gin.Context) {
|
||||||
|
id, has := ctx.Params.Get("id")
|
||||||
|
if !has {
|
||||||
|
ctx.JSON(200, &pm3.Response{
|
||||||
|
Code: -1,
|
||||||
|
Success: "fail",
|
||||||
|
Message: fmt.Sprintf("id is required"),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmp, err := i.swagger(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(200, &pm3.Response{
|
||||||
|
Code: -1,
|
||||||
|
Success: "fail",
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(200, tmp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlServiceController) Simple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||||
|
return i.module.Simple(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlServiceController) MySimple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||||
|
return i.module.MySimple(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlServiceController) editAIService(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
func (i *imlServiceController) editAIService(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
||||||
@@ -151,8 +236,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}}",
|
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{
|
aiModel := &ai_api_dto.AiModel{
|
||||||
Id: m.ID(),
|
Id: m.ID(),
|
||||||
Config: m.DefaultConfig(),
|
Config: m.DefaultConfig(),
|
||||||
|
Provider: *input.Provider,
|
||||||
}
|
}
|
||||||
name := "Demo Translation API"
|
name := "Demo Translation API"
|
||||||
description := "A demo that shows you how to use a prompt to create a Translation API."
|
description := "A demo that shows you how to use a prompt to create a Translation API."
|
||||||
@@ -211,10 +297,7 @@ func (i *imlServiceController) createAIService(ctx *gin.Context, teamID string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//_, err = i.upstreamModule.Save(ctx, info.Id, newAIUpstream(info.Id, *input.Provider, p.URI()))
|
|
||||||
//if err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
return i.docModule.SaveServiceDoc(ctx, info.Id, &service_dto.SaveServiceDoc{
|
return i.docModule.SaveServiceDoc(ctx, info.Id, &service_dto.SaveServiceDoc{
|
||||||
Doc: "The Translation API allows developers to translate text from one language to another. It supports multiple languages and enables easy integration of high-quality translation features into applications. With simple API requests, you can quickly translate content into different target languages.",
|
Doc: "The Translation API allows developers to translate text from one language to another. It supports multiple languages and enables easy integration of high-quality translation features into applications. With simple API requests, you can quickly translate content into different target languages.",
|
||||||
})
|
})
|
||||||
@@ -227,15 +310,11 @@ func (i *imlServiceController) SearchMyServices(ctx *gin.Context, teamId string,
|
|||||||
return i.module.SearchMyServices(ctx, teamId, keyword)
|
return i.module.SearchMyServices(ctx, teamId, keyword)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (i *imlServiceController) Simple(ctx *gin.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
|
||||||
// return i.module.Simple(ctx, keyword)
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (i *imlServiceController) MySimple(ctx *gin.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
|
||||||
// return i.module.MySimple(ctx, keyword)
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (i *imlServiceController) Get(ctx *gin.Context, id string) (*service_dto.Service, error) {
|
func (i *imlServiceController) Get(ctx *gin.Context, id string) (*service_dto.Service, error) {
|
||||||
|
now := time.Now()
|
||||||
|
defer func() {
|
||||||
|
log.Infof("get service %s cost %d ms", id, time.Since(now).Milliseconds())
|
||||||
|
}()
|
||||||
return i.module.Get(ctx, id)
|
return i.module.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +326,33 @@ func (i *imlServiceController) Create(ctx *gin.Context, teamID string, input *se
|
|||||||
if input.Kind == "ai" {
|
if input.Kind == "ai" {
|
||||||
return i.createAIService(ctx, teamID, input)
|
return i.createAIService(ctx, teamID, input)
|
||||||
}
|
}
|
||||||
return i.module.Create(ctx, teamID, input)
|
var err error
|
||||||
|
var info *service_dto.Service
|
||||||
|
err = i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||||
|
info, err = i.module.Create(txCtx, teamID, input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
path := fmt.Sprintf("/%s/", strings.Trim(input.Prefix, "/"))
|
||||||
|
_, err = i.routerModule.Create(txCtx, info.Id, &router_dto.Create{
|
||||||
|
Id: uuid.New().String(),
|
||||||
|
Name: "",
|
||||||
|
Path: path + "*",
|
||||||
|
Methods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodOptions},
|
||||||
|
Description: "auto create by create service",
|
||||||
|
Protocols: []string{"http", "https"},
|
||||||
|
MatchRules: nil,
|
||||||
|
Upstream: "",
|
||||||
|
Proxy: &router_dto.InputProxy{
|
||||||
|
Path: path,
|
||||||
|
Timeout: 30000,
|
||||||
|
Retry: 0,
|
||||||
|
},
|
||||||
|
Disable: false,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlServiceController) Edit(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
func (i *imlServiceController) Edit(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
||||||
@@ -278,6 +383,10 @@ type imlAppController struct {
|
|||||||
authModule application_authorization.IAuthorizationModule `autowired:""`
|
authModule application_authorization.IAuthorizationModule `autowired:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *imlAppController) SearchCanSubscribe(ctx *gin.Context, serviceId string) ([]*service_dto.SimpleAppItem, error) {
|
||||||
|
return i.module.SearchCanSubscribe(ctx, serviceId)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *imlAppController) Search(ctx *gin.Context, teamId string, keyword string) ([]*service_dto.AppItem, error) {
|
func (i *imlAppController) Search(ctx *gin.Context, teamId string, keyword string) ([]*service_dto.AppItem, error) {
|
||||||
return i.module.Search(ctx, teamId, keyword)
|
return i.module.Search(ctx, teamId, keyword)
|
||||||
}
|
}
|
||||||
@@ -326,3 +435,23 @@ func (i *imlAppController) GetApp(ctx *gin.Context, appId string) (*service_dto.
|
|||||||
func (i *imlAppController) DeleteApp(ctx *gin.Context, appId string) error {
|
func (i *imlAppController) DeleteApp(ctx *gin.Context, appId string) error {
|
||||||
return i.module.DeleteApp(ctx, appId)
|
return i.module.DeleteApp(ctx, appId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newAIUpstream(id string, provider string, uri model_runtime.IProviderURI) *upstream_dto.Upstream {
|
||||||
|
return &upstream_dto.Upstream{
|
||||||
|
Type: "http",
|
||||||
|
Balance: "round-robin",
|
||||||
|
Timeout: 300000,
|
||||||
|
Retry: 0,
|
||||||
|
Remark: fmt.Sprintf("auto create by ai service %s,provider is %s", id, provider),
|
||||||
|
LimitPeerSecond: 0,
|
||||||
|
ProxyHeaders: nil,
|
||||||
|
Scheme: uri.Scheme(),
|
||||||
|
PassHost: "node",
|
||||||
|
Nodes: []*upstream_dto.NodeConfig{
|
||||||
|
{
|
||||||
|
Address: uri.Host(),
|
||||||
|
Weight: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,12 +24,11 @@ type IServiceController interface {
|
|||||||
Delete(ctx *gin.Context, id string) error
|
Delete(ctx *gin.Context, id string) error
|
||||||
ServiceDoc(ctx *gin.Context, id string) (*service_dto.ServiceDoc, error)
|
ServiceDoc(ctx *gin.Context, id string) (*service_dto.ServiceDoc, error)
|
||||||
SaveServiceDoc(ctx *gin.Context, id string, input *service_dto.SaveServiceDoc) error
|
SaveServiceDoc(ctx *gin.Context, id string, input *service_dto.SaveServiceDoc) error
|
||||||
|
Simple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||||
|
MySimple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||||
|
|
||||||
//createAIService(ctx *gin.Context, teamID string, input *service_dto.CreateService) (*service_dto.Service, error)
|
Swagger(ctx *gin.Context)
|
||||||
//editAIService(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error)
|
ExportSwagger(ctx *gin.Context)
|
||||||
//DeleteAIService(ctx *gin.Context, id string) error
|
|
||||||
//SearchMyAIServices(ctx *gin.Context, teamID string, keyword string) ([]*service_dto.ServiceItem, error)
|
|
||||||
//SearchAIServices(ctx *gin.Context, teamID string, keyword string) ([]*service_dto.ServiceItem, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type IAppController interface {
|
type IAppController interface {
|
||||||
@@ -42,6 +41,7 @@ type IAppController interface {
|
|||||||
// SimpleApps 获取简易项目列表
|
// SimpleApps 获取简易项目列表
|
||||||
SimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
|
SimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
|
||||||
MySimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
|
MySimpleApps(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
|
||||||
|
SearchCanSubscribe(ctx *gin.Context, keyword string) ([]*service_dto.SimpleAppItem, error)
|
||||||
GetApp(ctx *gin.Context, appId string) (*service_dto.App, error)
|
GetApp(ctx *gin.Context, appId string) (*service_dto.App, error)
|
||||||
DeleteApp(ctx *gin.Context, appId string) error
|
DeleteApp(ctx *gin.Context, appId string) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,263 @@
|
|||||||
|
package strategy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eolinker/go-common/utils"
|
||||||
|
|
||||||
|
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||||
|
|
||||||
|
"github.com/APIParkLab/APIPark/module/service"
|
||||||
|
"github.com/APIParkLab/APIPark/module/strategy"
|
||||||
|
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ IStrategyController = (*imlStrategyController)(nil)
|
||||||
|
|
||||||
|
type imlStrategyController struct {
|
||||||
|
strategyModule strategy.IStrategyModule `autowired:""`
|
||||||
|
serviceModule service.IServiceModule `autowired:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) Restore(ctx *gin.Context, id string) error {
|
||||||
|
return i.strategyModule.Restore(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) DeleteServiceStrategy(ctx *gin.Context, serviceId string, id string) error {
|
||||||
|
return i.strategyModule.DeleteServiceStrategy(ctx, serviceId, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) ToPublish(ctx *gin.Context, driver string) ([]*strategy_dto.ToPublishItem, string, string, bool, error) {
|
||||||
|
list, err := i.strategyModule.ToPublish(ctx, driver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", false, err
|
||||||
|
}
|
||||||
|
data, _ := json.Marshal(list)
|
||||||
|
source := base64.StdEncoding.EncodeToString(data)
|
||||||
|
return list, source, time.Now().Format("20060102150405") + "-release", len(list) > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) FilterGlobalRemote(ctx *gin.Context, name string) ([]*strategy_dto.Title, []any, int64, string, string, error) {
|
||||||
|
f, has := strategy_filter.RemoteFilter(name)
|
||||||
|
if !has {
|
||||||
|
return nil, nil, 0, "", "", fmt.Errorf("filter not found: %s", name)
|
||||||
|
}
|
||||||
|
scopeAllow := false
|
||||||
|
for _, s := range f.Scopes() {
|
||||||
|
if s == strategy_filter.ScopeGlobal {
|
||||||
|
scopeAllow = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !scopeAllow {
|
||||||
|
return nil, nil, 0, "", "", fmt.Errorf("scope not allowed: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
list, total, err := f.RemoteList(ctx, "", nil, -1, -1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, 0, "", "", err
|
||||||
|
}
|
||||||
|
return utils.SliceToSlice(f.Titles(), func(l strategy_filter.OptionTitle) *strategy_dto.Title {
|
||||||
|
return &strategy_dto.Title{
|
||||||
|
Field: l.Field,
|
||||||
|
Title: l.Title,
|
||||||
|
}
|
||||||
|
}), list, total, f.Key(), f.Key(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) FilterServiceRemote(ctx *gin.Context, serviceId string, name string) ([]*strategy_dto.Title, []any, int64, string, string, error) {
|
||||||
|
f, has := strategy_filter.RemoteFilter(name)
|
||||||
|
if !has {
|
||||||
|
return nil, nil, 0, "", "", fmt.Errorf("filter not found: %s", name)
|
||||||
|
}
|
||||||
|
scopeAllow := false
|
||||||
|
for _, s := range f.Scopes() {
|
||||||
|
if s == strategy_filter.ScopeService {
|
||||||
|
scopeAllow = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !scopeAllow {
|
||||||
|
return nil, nil, 0, "", "", fmt.Errorf("scope not allowed: %s", name)
|
||||||
|
}
|
||||||
|
list, total, err := f.RemoteList(ctx, "", map[string]interface{}{"service": serviceId}, -1, -1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, 0, "", "", err
|
||||||
|
}
|
||||||
|
return utils.SliceToSlice(f.Titles(), func(l strategy_filter.OptionTitle) *strategy_dto.Title {
|
||||||
|
return &strategy_dto.Title{
|
||||||
|
Field: l.Field,
|
||||||
|
Title: l.Title,
|
||||||
|
}
|
||||||
|
}), list, total, f.Key(), "list", nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) filterOptions(ctx *gin.Context, scope string) ([]*strategy_dto.FilterOption, error) {
|
||||||
|
m, has := strategy_filter.Options(scope)
|
||||||
|
if !has {
|
||||||
|
return nil, fmt.Errorf("scope not found: %s", scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
list := utils.MapToSlice(m, func(key string, value *strategy_filter.Option) *strategy_dto.FilterOption {
|
||||||
|
pattern := ""
|
||||||
|
if value.Pattern != nil {
|
||||||
|
pattern = value.Pattern.String()
|
||||||
|
}
|
||||||
|
return &strategy_dto.FilterOption{
|
||||||
|
Name: value.Name,
|
||||||
|
Title: value.Title,
|
||||||
|
Type: value.Type,
|
||||||
|
Pattern: pattern,
|
||||||
|
Options: value.Options,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sort.Slice(list, func(i, j int) bool {
|
||||||
|
return list[i].Name < list[j].Name
|
||||||
|
})
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) FilterServiceOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error) {
|
||||||
|
return i.filterOptions(ctx, strategy_filter.ScopeService)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) FilterGlobalOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error) {
|
||||||
|
return i.filterOptions(ctx, strategy_filter.ScopeGlobal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) GetStrategy(ctx *gin.Context, id string) (*strategy_dto.Strategy, error) {
|
||||||
|
return i.strategyModule.Get(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) search(ctx *gin.Context, keyword string, scope strategy_dto.Scope, target string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||||
|
p, err := strconv.Atoi(page)
|
||||||
|
if err != nil {
|
||||||
|
if page != "" {
|
||||||
|
return nil, 0, fmt.Errorf("page error: %s", err)
|
||||||
|
}
|
||||||
|
p = 1
|
||||||
|
}
|
||||||
|
ps, err := strconv.Atoi(pageSize)
|
||||||
|
if err != nil {
|
||||||
|
if pageSize != "" {
|
||||||
|
return nil, 0, fmt.Errorf("page size error: %s", err)
|
||||||
|
}
|
||||||
|
ps = 20
|
||||||
|
}
|
||||||
|
ss := make([]string, 0)
|
||||||
|
json.Unmarshal([]byte(sort), &ss)
|
||||||
|
fs := make([]string, 0)
|
||||||
|
json.Unmarshal([]byte(filters), &fs)
|
||||||
|
list, total, err := i.strategyModule.Search(ctx, keyword, driver, scope, target, p, ps, fs, ss...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) GlobalStrategyList(ctx *gin.Context, keyword string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||||
|
|
||||||
|
return i.search(ctx, keyword, strategy_dto.ToScope(strategy_dto.ScopeGlobal), "", driver, page, pageSize, order, sort, filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) CreateGlobalStrategy(ctx *gin.Context, driver string, input *strategy_dto.Create) error {
|
||||||
|
input.Driver = driver
|
||||||
|
input.Scope = strategy_dto.ToScope(strategy_dto.ScopeGlobal)
|
||||||
|
|
||||||
|
return i.strategyModule.Create(ctx, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) PublishGlobalStrategy(ctx *gin.Context, driver string) error {
|
||||||
|
return i.strategyModule.Publish(ctx, driver, strategy_dto.ScopeGlobal, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) ServiceStrategyList(ctx *gin.Context, keyword string, serviceId string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||||
|
|
||||||
|
return i.search(ctx, keyword, strategy_dto.ToScope(strategy_dto.ScopeService), serviceId, driver, page, pageSize, order, sort, filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) CreateServiceStrategy(ctx *gin.Context, serviceId string, driver string, input *strategy_dto.Create) error {
|
||||||
|
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create service strategy error: %s", err)
|
||||||
|
}
|
||||||
|
input.Driver = driver
|
||||||
|
input.Scope = strategy_dto.ToScope(strategy_dto.ScopeService)
|
||||||
|
input.Target = serviceId
|
||||||
|
|
||||||
|
return i.strategyModule.Create(ctx, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) EditStrategy(ctx *gin.Context, id string, input *strategy_dto.Edit) error {
|
||||||
|
return i.strategyModule.Edit(ctx, id, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) EnableStrategy(ctx *gin.Context, id string) error {
|
||||||
|
return i.strategyModule.Enable(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) DisableStrategy(ctx *gin.Context, id string) error {
|
||||||
|
return i.strategyModule.Disable(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) DeleteStrategy(ctx *gin.Context, id string) error {
|
||||||
|
return i.strategyModule.Delete(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genTime(t string, defaultValue time.Time) (time.Time, error) {
|
||||||
|
if t == "" {
|
||||||
|
return defaultValue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := strconv.ParseInt(t, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return time.Unix(s, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) GetStrategyLogs(ctx *gin.Context, keyword string, strategyId string, start string, end string, limit string, offset string) ([]*strategy_dto.LogItem, int64, error) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
s, err := genTime(start, now.Add(-time.Hour*24*30))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("start time error: %s", err)
|
||||||
|
}
|
||||||
|
e, err := genTime(end, now)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
return nil, 0, fmt.Errorf("end time error: %s", err)
|
||||||
|
}
|
||||||
|
if s.After(e) {
|
||||||
|
return nil, 0, fmt.Errorf("start time must be less than end time")
|
||||||
|
}
|
||||||
|
l, err := strconv.ParseInt(limit, 10, 64)
|
||||||
|
if err != nil && limit != "" {
|
||||||
|
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
o, err := strconv.ParseInt(offset, 10, 64)
|
||||||
|
if err != nil && offset != "" {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if l < 1 {
|
||||||
|
l = 15
|
||||||
|
}
|
||||||
|
if o < 1 {
|
||||||
|
o = 1
|
||||||
|
}
|
||||||
|
return i.strategyModule.GetStrategyLogs(ctx, keyword, strategyId, s, e, l, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyController) LogInfo(ctx *gin.Context, id string) (*strategy_dto.LogInfo, error) {
|
||||||
|
|
||||||
|
return i.strategyModule.StrategyLogInfo(ctx, id)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package strategy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||||
|
"github.com/eolinker/go-common/autowire"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IStrategyController interface {
|
||||||
|
GlobalStrategyList(ctx *gin.Context, keyword string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error)
|
||||||
|
CreateGlobalStrategy(ctx *gin.Context, driver string, input *strategy_dto.Create) error
|
||||||
|
PublishGlobalStrategy(ctx *gin.Context, driver string) error
|
||||||
|
|
||||||
|
ServiceStrategyList(ctx *gin.Context, keyword string, serviceId string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error)
|
||||||
|
CreateServiceStrategy(ctx *gin.Context, serviceId string, driver string, input *strategy_dto.Create) error
|
||||||
|
|
||||||
|
EditStrategy(ctx *gin.Context, id string, input *strategy_dto.Edit) error
|
||||||
|
GetStrategy(ctx *gin.Context, id string) (*strategy_dto.Strategy, error)
|
||||||
|
EnableStrategy(ctx *gin.Context, id string) error
|
||||||
|
DisableStrategy(ctx *gin.Context, id string) error
|
||||||
|
|
||||||
|
DeleteStrategy(ctx *gin.Context, id string) error
|
||||||
|
DeleteServiceStrategy(ctx *gin.Context, serviceId string, id string) error
|
||||||
|
|
||||||
|
Restore(ctx *gin.Context, id string) error
|
||||||
|
|
||||||
|
FilterGlobalOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error)
|
||||||
|
FilterServiceOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error)
|
||||||
|
|
||||||
|
FilterGlobalRemote(ctx *gin.Context, name string) ([]*strategy_dto.Title, []any, int64, string, string, error)
|
||||||
|
FilterServiceRemote(ctx *gin.Context, serviceId string, name string) ([]*strategy_dto.Title, []any, int64, string, string, error)
|
||||||
|
|
||||||
|
ToPublish(ctx *gin.Context, driver string) ([]*strategy_dto.ToPublishItem, string, string, bool, error)
|
||||||
|
|
||||||
|
GetStrategyLogs(ctx *gin.Context, keyword string, strategyId string, start string, end string, limit string, offset string) ([]*strategy_dto.LogItem, int64, error)
|
||||||
|
LogInfo(ctx *gin.Context, id string) (*strategy_dto.LogInfo, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type IStrategyCommonController interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
autowire.Auto[IStrategyController](func() reflect.Value {
|
||||||
|
return reflect.ValueOf(&imlStrategyController{})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -265,7 +265,8 @@ func (i *imlInitController) OnInit() {
|
|||||||
return fmt.Errorf("create default team error: %v", err)
|
return fmt.Errorf("create default team error: %v", err)
|
||||||
}
|
}
|
||||||
// 创建Rest服务
|
// 创建Rest服务
|
||||||
_, err = i.serviceModule.Create(ctx, info.Id, &service_dto.CreateService{
|
restPath := "/rest-demo"
|
||||||
|
serviceInfo, err := i.serviceModule.Create(ctx, info.Id, &service_dto.CreateService{
|
||||||
Name: "REST Demo Service",
|
Name: "REST Demo Service",
|
||||||
Prefix: "/rest-demo",
|
Prefix: "/rest-demo",
|
||||||
Description: "Auto created By APIPark",
|
Description: "Auto created By APIPark",
|
||||||
@@ -277,6 +278,26 @@ func (i *imlInitController) OnInit() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create default service error: %v", err)
|
return fmt.Errorf("create default service error: %v", err)
|
||||||
}
|
}
|
||||||
|
path := fmt.Sprintf("/%s/", strings.Trim(restPath, "/"))
|
||||||
|
_, err = i.routerModule.Create(ctx, serviceInfo.Id, &router_dto.Create{
|
||||||
|
Id: uuid.NewString(),
|
||||||
|
Name: "",
|
||||||
|
Path: path + "*",
|
||||||
|
Methods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodOptions},
|
||||||
|
Description: "auto create by create service",
|
||||||
|
Protocols: []string{"http", "https"},
|
||||||
|
MatchRules: nil,
|
||||||
|
Upstream: "",
|
||||||
|
Proxy: &router_dto.InputProxy{
|
||||||
|
Path: path,
|
||||||
|
Timeout: 30000,
|
||||||
|
Retry: 0,
|
||||||
|
},
|
||||||
|
Disable: false,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create default router error: %v", err)
|
||||||
|
}
|
||||||
// 创建AI服务
|
// 创建AI服务
|
||||||
err = i.createAIService(ctx, info.Id, &service_dto.CreateService{
|
err = i.createAIService(ctx, info.Id, &service_dto.CreateService{
|
||||||
Name: "AI Demo Service",
|
Name: "AI Demo Service",
|
||||||
@@ -319,12 +340,12 @@ func (i *imlInitController) OnInit() {
|
|||||||
}
|
}
|
||||||
func (i *imlInitController) createAIService(ctx context.Context, teamID string, input *service_dto.CreateService) error {
|
func (i *imlInitController) createAIService(ctx context.Context, teamID string, input *service_dto.CreateService) error {
|
||||||
|
|
||||||
providerId := "openai"
|
providerId := "fakegpt"
|
||||||
err := i.providerModule.UpdateProviderConfig(ctx, "openai", &ai_dto.UpdateConfig{
|
err := i.providerModule.UpdateProviderConfig(ctx, providerId, &ai_dto.UpdateConfig{
|
||||||
Config: "{\n \"openai_api_base\": \"API Base\",\n \"openai_api_key\": \"API Key\",\n \"openai_organization\": \"Organization\"\n}",
|
Config: "{\n \"apikey\": \"xxx\" \n}",
|
||||||
})
|
})
|
||||||
if err != nil {
|
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
|
input.Provider = &providerId
|
||||||
if input.Id == "" {
|
if input.Id == "" {
|
||||||
@@ -381,8 +402,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}}",
|
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{
|
aiModel := &ai_api_dto.AiModel{
|
||||||
Id: m.ID(),
|
Id: m.ID(),
|
||||||
Config: m.DefaultConfig(),
|
Config: m.DefaultConfig(),
|
||||||
|
Provider: providerId,
|
||||||
}
|
}
|
||||||
name := "Demo Translation API"
|
name := "Demo Translation API"
|
||||||
description := "A demo that shows you how to use a prompt to create a Translation API."
|
description := "A demo that shows you how to use a prompt to create a Translation API."
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["react", "@typescript-eslint", "prettier"],
|
||||||
|
"rules": {
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["warn"]
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,4 +27,5 @@ packages/core/public/tinymce/
|
|||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
|
||||||
/pnpm-lock.yaml
|
/pnpm-lock.yaml
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"jsxSingleQuote": false
|
||||||
|
}
|
||||||
+12
-5
@@ -1,10 +1,17 @@
|
|||||||
# 部署
|
# 部署
|
||||||
|
|
||||||
## 安装依赖
|
## 安装依赖
|
||||||
建议使用pnpm
|
建议使用 pnpm
|
||||||
`npm install -g pnpm`
|
```
|
||||||
使用pnpm安装依赖
|
npm install -g pnpm
|
||||||
`pnpm install`
|
```
|
||||||
|
|
||||||
|
使用pnpm安装依赖
|
||||||
|
```
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
## 编译
|
## 编译
|
||||||
`pnpm run build`
|
```
|
||||||
|
pnpm run build
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# 部署
|
|
||||||
|
|
||||||
## 代码同步
|
|
||||||
packages目录下,部分子项目为企业版独有,不要同步到开源版:
|
|
||||||
packages/businessEntry, packages/openApi, packages/systemRunning, README.pro.md
|
|
||||||
|
|
||||||
## 安装依赖
|
|
||||||
建议使用pnpm
|
|
||||||
`npm install -g pnpm`
|
|
||||||
使用pnpm安装依赖
|
|
||||||
`pnpm install`
|
|
||||||
|
|
||||||
## 编译
|
|
||||||
### 开源版本
|
|
||||||
`pnpm run build`
|
|
||||||
### 企业版本
|
|
||||||
`pnpm run build:pro`
|
|
||||||
@@ -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 = {
|
module.exports = {
|
||||||
roots: ['<rootDir>/packages'],
|
roots: ['<rootDir>/packages'],
|
||||||
testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'],
|
testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'],
|
||||||
@@ -15,4 +8,4 @@ module.exports = {
|
|||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||||
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
||||||
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
/*
|
// import '@testing-library/jest-dom/extend-expect';
|
||||||
* @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';
|
|
||||||
|
|||||||
@@ -3,4 +3,5 @@
|
|||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"version": "independent"
|
"version": "independent"
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"build": "set NODE_OPTIONS=--max-old-space-size=4096 && lerna run build --scope=core --stream --verbose ",
|
"build": "set NODE_OPTIONS=--max-old-space-size=4096 && lerna run build --scope=core --stream --verbose ",
|
||||||
"build:pro": "set NODE_OPTIONS=--max-old-space-size=4096 && lerna run build --scope=business-entry --stream --verbose ",
|
|
||||||
"serve": "lerna run preview --parallel",
|
"serve": "lerna run preview --parallel",
|
||||||
"serve:remotes": "lerna run serve --scope=remote --parallel",
|
"serve:remotes": "lerna run serve --scope=remote --parallel",
|
||||||
"dev": "lerna run dev --scope=core --stream",
|
"dev": "lerna run dev --scope=core --stream",
|
||||||
"dev:pro": "lerna run dev --scope=business-entry --stream",
|
|
||||||
"stop": "kill-port --port 5000",
|
"stop": "kill-port --port 5000",
|
||||||
"scan": "i18next-scanner --config i18next-scanner.config.js"
|
"scan": "i18next-scanner --config i18next-scanner.config.js"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
// .env.pro
|
|
||||||
VITE_APP_MODE=pro
|
|
||||||
VITE_APP_TITLE=My Production App
|
|
||||||
VITE_API_BASE_URL=https://api.production.example.com
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: { browser: true, es2020: true },
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
],
|
|
||||||
ignorePatterns: ['dist', '.eslintrc.cjs','public','code-snippet','ace-editor'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: ['react-refresh'],
|
|
||||||
rules: {
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
public/tinymce
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# `businessEntry`
|
|
||||||
|
|
||||||
> TODO: description
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
const businessEntry = require('businessEntry');
|
|
||||||
|
|
||||||
// TODO: DEMONSTRATE API
|
|
||||||
```
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const businessEntry = require('..');
|
|
||||||
const assert = require('assert').strict;
|
|
||||||
|
|
||||||
assert.strictEqual(businessEntry(), 'Hello from businessEntry');
|
|
||||||
console.info('businessEntry tests passed');
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<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>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
<script src="/frontend/iconpark_eolink.js"></script>
|
|
||||||
<script src="/frontend/iconpark_apinto.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "business-entry",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"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",
|
|
||||||
"serve": "vite preview --port 5000 --strictPort"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* @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': {},
|
|
||||||
'tailwindcss/nesting': {},
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,158 +0,0 @@
|
|||||||
import '@core/App.css'
|
|
||||||
import { ConfigProvider } from 'antd';
|
|
||||||
import RenderRoutes from '@businessEntry/components/aoplatform/RenderRoutes';
|
|
||||||
import {BreadcrumbProvider} from "@common/contexts/BreadcrumbContext.tsx";
|
|
||||||
import { StyleProvider } from '@ant-design/cssinjs';
|
|
||||||
import zhCN from 'antd/locale/zh_CN';
|
|
||||||
import useInitializeMonaco from "@common/hooks/useInitializeMonaco";
|
|
||||||
import ThemeSwitcher from '@common/components/aoplatform/ThemeSwitcher'
|
|
||||||
|
|
||||||
const antdComponentThemeToken = {
|
|
||||||
token: {
|
|
||||||
// Seed Token,影响范围大
|
|
||||||
colorPrimary: '#3D46F2',
|
|
||||||
colorLink:'#3D46F2',
|
|
||||||
colorBorder:'#ededed',
|
|
||||||
colorText:'#333',
|
|
||||||
borderRadius: 4,
|
|
||||||
// 派生变量,影响范围小
|
|
||||||
colorBgContainer: '#fff',
|
|
||||||
colorPrimaryBg:'#EBEEF2',
|
|
||||||
colorTextQuaternary:'#BBB',
|
|
||||||
colorTextTertiary:'#999'
|
|
||||||
},
|
|
||||||
components:{
|
|
||||||
// 派生变量,影响范围小
|
|
||||||
Input:{
|
|
||||||
activeShadow:'none'
|
|
||||||
},
|
|
||||||
Select:{
|
|
||||||
activeShadow:'none'
|
|
||||||
},
|
|
||||||
Checkbox:{
|
|
||||||
activeShadow:'none'
|
|
||||||
},
|
|
||||||
Cascader:{
|
|
||||||
activeShadow:'none',
|
|
||||||
optionSelectedBg:'#EBEEF2',
|
|
||||||
optionHoverBg:'#EBEEF2'
|
|
||||||
},
|
|
||||||
Layout: {
|
|
||||||
bodyBg: '#17163E',
|
|
||||||
headerBg: 'transparent',
|
|
||||||
headerColor: '#333',
|
|
||||||
headerPadding: '10 20px',
|
|
||||||
lightSiderBg: 'transparent',
|
|
||||||
siderBg: 'transparent',
|
|
||||||
},
|
|
||||||
Breadcrumb:{
|
|
||||||
itemColor:'#666',
|
|
||||||
linkColor:'#666',
|
|
||||||
lastItemColor:'#333',
|
|
||||||
},
|
|
||||||
Table:{
|
|
||||||
headerBorderRadius:0,
|
|
||||||
headerSplitColor:'#ededed',
|
|
||||||
borderColor:'#ededed',
|
|
||||||
cellPaddingBlockMD:'10px',
|
|
||||||
cellPaddingInlineMD:'12px',
|
|
||||||
cellPaddingBlockSM:'8px',
|
|
||||||
cellPaddingInlineSM:'12px',
|
|
||||||
headerFilterHoverBg:'#EBEEF2',
|
|
||||||
headerSortActiveBg:'#F7F8FA',
|
|
||||||
headerSortHoverBg:'#F7F8FA',
|
|
||||||
fixedHeaderSortActiveBg:'#F7F8FA',
|
|
||||||
headerBg:'#F7F8FA',
|
|
||||||
rowHoverBg:'#EBEEF2'
|
|
||||||
|
|
||||||
},
|
|
||||||
Segmented:{
|
|
||||||
itemColor:'#333',
|
|
||||||
itemSelectedColor:'#333',
|
|
||||||
trackBg:'#f7f8fa',
|
|
||||||
trackPadding:0,
|
|
||||||
// itemHoverColor:'#EBEEF2',
|
|
||||||
itemActiveBg:'#EBEEF2',
|
|
||||||
itemHoverBg:'#EBEEF2',
|
|
||||||
itemSelectedBg:'#EBEEF2',
|
|
||||||
},
|
|
||||||
Tree:{
|
|
||||||
// titleHeight:30,
|
|
||||||
// fontSize:12,
|
|
||||||
directoryNodeSelectedBg:'#EBEEF2',
|
|
||||||
directoryNodeSelectedColor:'#333',
|
|
||||||
nodeSelectedBg:'#EBEEF2',
|
|
||||||
nodeHoverBg:'#EBEEF2'
|
|
||||||
},
|
|
||||||
Collapse:{
|
|
||||||
headerBg:'#f7f8fa',
|
|
||||||
headerPadding:"12px",
|
|
||||||
contentPadding:"0 10px 12px 10px"
|
|
||||||
},
|
|
||||||
Button:{
|
|
||||||
// paddingInline:8,
|
|
||||||
dangerShadow:'none',
|
|
||||||
defaultShadow:'none',
|
|
||||||
primaryShadow:'none'
|
|
||||||
},
|
|
||||||
Tabs:{
|
|
||||||
cardBg:'#EBEEF2',
|
|
||||||
cardHeight:42,
|
|
||||||
horizontalItemGutter:8,
|
|
||||||
horizontalItemPaddingSM:'12px 8px 8px 8px',
|
|
||||||
horizontalItemPadding:'12px 8px 8px 8px',
|
|
||||||
},
|
|
||||||
Menu:{
|
|
||||||
// itemBg:'#F7F8FA',
|
|
||||||
// subMenuItemBg:'#F7F8FA',
|
|
||||||
// itemMarginBlock:0,
|
|
||||||
// activeBarBorderWidth:0,
|
|
||||||
// itemSelectedColor:'#333',
|
|
||||||
// itemSelectedBg:'#EBEEF2',
|
|
||||||
// itemHoverBg:'#EBEEF2'
|
|
||||||
// itemHeight:'72px',
|
|
||||||
// darkItemBg:'transparent',
|
|
||||||
// itemBg:'transparent',
|
|
||||||
// itemSelectedBg:'transparent',
|
|
||||||
// darkItemSelectedBg:'transparent',
|
|
||||||
// subMenuItemBg:'transparent',
|
|
||||||
// itemActiveBg:'transparent',
|
|
||||||
// darkSubMenuItemBg:'transparent',
|
|
||||||
// activeBarHeight:'2px',
|
|
||||||
// activeBarBorderWidth:2
|
|
||||||
},
|
|
||||||
List:{
|
|
||||||
itemPadding:'8px 0'
|
|
||||||
},
|
|
||||||
Form:{
|
|
||||||
itemMarginBottom:10,
|
|
||||||
|
|
||||||
},
|
|
||||||
Alert:{
|
|
||||||
defaultPadding:'12px 16px'
|
|
||||||
},
|
|
||||||
Tag:{
|
|
||||||
defaultBg:"#f7f8fa"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
useInitializeMonaco()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyleProvider hashPriority={"high"}>
|
|
||||||
<ConfigProvider
|
|
||||||
locale={zhCN}
|
|
||||||
wave={{disabled:true}}
|
|
||||||
theme={antdComponentThemeToken}>
|
|
||||||
<ThemeSwitcher />
|
|
||||||
<BreadcrumbProvider>
|
|
||||||
<RenderRoutes />
|
|
||||||
</BreadcrumbProvider>
|
|
||||||
</ConfigProvider>
|
|
||||||
</StyleProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App
|
|
||||||
@@ -1,484 +0,0 @@
|
|||||||
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom';
|
|
||||||
import Login from "@core/pages/Login.tsx"
|
|
||||||
import BasicLayout from '@common/components/aoplatform/BasicLayout';
|
|
||||||
import {createElement, ReactElement,ReactNode,Suspense} from 'react';
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import {App, Skeleton} from "antd";
|
|
||||||
import ApprovalPage from "@core/pages/approval/ApprovalPage.tsx";
|
|
||||||
import {SystemProvider} from "@core/contexts/SystemContext.tsx";
|
|
||||||
import {useGlobalContext} from "@common/contexts/GlobalStateContext.tsx";
|
|
||||||
import {FC,lazy} from 'react';
|
|
||||||
import { TeamProvider } from '@core/contexts/TeamContext.tsx';
|
|
||||||
import SystemOutlet from '@core/pages/system/SystemOutlet.tsx';
|
|
||||||
import { DashboardProvider } from '@core/contexts/DashboardContext.tsx';
|
|
||||||
import { TenantManagementProvider } from '@market/contexts/TenantManagementContext.tsx';
|
|
||||||
|
|
||||||
type RouteConfig = {
|
|
||||||
path:string
|
|
||||||
component?:ReactElement
|
|
||||||
children?:(RouteConfig|false)[]
|
|
||||||
key:string
|
|
||||||
provider?:FC<{ children: ReactNode; }>
|
|
||||||
lazy?:unknown
|
|
||||||
}
|
|
||||||
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
|
||||||
export type RouterParams = {
|
|
||||||
teamId:string
|
|
||||||
apiId:string
|
|
||||||
serviceId:string
|
|
||||||
clusterId:string;
|
|
||||||
memberGroupId:string
|
|
||||||
userGroupId:string
|
|
||||||
pluginName:string
|
|
||||||
moduleId:string
|
|
||||||
accessType:'project'|'team'|'service'
|
|
||||||
categoryId:string
|
|
||||||
tagId:string
|
|
||||||
dashboardType:string
|
|
||||||
dashboardDetailId:string
|
|
||||||
topologyId:string
|
|
||||||
appId:string
|
|
||||||
roleType:string
|
|
||||||
roleId:string
|
|
||||||
}
|
|
||||||
|
|
||||||
const PUBLIC_ROUTES:RouteConfig[] = [
|
|
||||||
{
|
|
||||||
path:'/',
|
|
||||||
component:<Login/>,
|
|
||||||
key: uuidv4(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'/login',
|
|
||||||
component:<Login/>,
|
|
||||||
key: uuidv4()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'/',
|
|
||||||
component:<ProtectedRoute/>,
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'approval/*',
|
|
||||||
component:<ApprovalPage />,
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'team',
|
|
||||||
component:<Outlet/>,
|
|
||||||
key: uuidv4(),
|
|
||||||
provider: TeamProvider,
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key: uuidv4(),
|
|
||||||
component: <Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamList.tsx'))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'inside/:teamId',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsidePage.tsx')),
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'member',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsideMember.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'setting',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamConfig.tsx')),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'service',
|
|
||||||
component:<SystemOutlet />,
|
|
||||||
key: uuidv4(),
|
|
||||||
provider: SystemProvider,
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key:uuidv4(),
|
|
||||||
component:<Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list/:teamId',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:':teamId',
|
|
||||||
component:<Outlet/>,
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'inside/:serviceId',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsidePage.tsx')),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'api',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideApiDocument.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'router',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterList')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'upstream',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/upstream/SystemInsideUpstreamContent.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'document',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideDocument.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'subscriber',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideSubscriber.tsx')),
|
|
||||||
children:[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'approval',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApproval.tsx')),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApprovalList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'*',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApprovalList.tsx')),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'topology',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemTopology.tsx')),
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'publish',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublish.tsx')),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublishList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'*',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublishList.tsx')),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'setting',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemConfig.tsx')),
|
|
||||||
children:[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},{
|
|
||||||
path:'datasourcing',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideDashboardSetting.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'cluster',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCluster.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'cert',
|
|
||||||
key: uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCert.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'serviceHub',
|
|
||||||
component:<Outlet />,
|
|
||||||
key:uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key: uuidv4(),
|
|
||||||
component: <Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/ServiceHubList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'detail/:serviceId',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/ServiceHubDetail.tsx')),
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'commonsetting',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/common/CommonPage.tsx')),
|
|
||||||
key:uuidv4(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'consumer',
|
|
||||||
component:<Outlet />,
|
|
||||||
provider:TenantManagementProvider,
|
|
||||||
key:uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key:uuidv4(),
|
|
||||||
component:<Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:':teamId/inside/:appId',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsidePage.tsx')),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'service',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsideService.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'authorization',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsideAuth.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'setting',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementAppSetting.tsx')),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ServiceHubManagement.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list/:teamId',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ServiceHubManagement.tsx')),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'member',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberPage.tsx')),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'',
|
|
||||||
key:uuidv4(),
|
|
||||||
component:<Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list/:memberGroupId',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberList.tsx')),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'role',
|
|
||||||
key:uuidv4(),
|
|
||||||
component:<Outlet></Outlet>,
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
key: uuidv4(),
|
|
||||||
component: <Navigate to="list" />
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleList.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:':roleType/config',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:':roleType/config/:roleId',
|
|
||||||
key:uuidv4(),
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
APP_MODE === 'pro' &&{
|
|
||||||
path:'openapi',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@openApi/pages/OpenApiList.tsx')),
|
|
||||||
key:uuidv4(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'assets',
|
|
||||||
component:<p>设计中</p>,
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
APP_MODE === 'pro' &&{
|
|
||||||
path:'analytics',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/Dashboard.tsx')),
|
|
||||||
key:uuidv4(),
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:':dashboardType',
|
|
||||||
component:<Outlet/>,
|
|
||||||
key:uuidv4(),
|
|
||||||
provider:DashboardProvider,
|
|
||||||
children:[
|
|
||||||
{
|
|
||||||
path:'list',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardList.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'detail/:dashboardDetailId',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardDetail.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'systemrunning',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@systemRunning/pages/SystemRunning.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'template/:moduleId',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '../../../../common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'logsettings/*',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/logsettings/LogSettings.tsx')),
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[{
|
|
||||||
path:'template/:moduleId',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
}]
|
|
||||||
|
|
||||||
},
|
|
||||||
APP_MODE ==='pro' && {
|
|
||||||
path:'resourcesettings/*',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/resourcesettings/ResourceSettings.tsx')),
|
|
||||||
key: uuidv4(),
|
|
||||||
children:[{
|
|
||||||
path:'template/:moduleId',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
}]
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path:'userProfile/*',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/UserProfile.tsx')),
|
|
||||||
key:uuidv4(),
|
|
||||||
children:[{
|
|
||||||
path:'changepsw',
|
|
||||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/ChangePsw.tsx')),
|
|
||||||
key:uuidv4()
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const RenderRoutes = ()=> {
|
|
||||||
return (
|
|
||||||
<App className="h-full" message={{ maxCount: 1 }}>
|
|
||||||
<Router>
|
|
||||||
<Routes>
|
|
||||||
{generateRoutes(PUBLIC_ROUTES)}
|
|
||||||
</Routes>
|
|
||||||
</Router>
|
|
||||||
</App>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateRoutes = (routerConfig: RouteConfig[]) => {
|
|
||||||
return routerConfig?.map((route: RouteConfig) => {
|
|
||||||
let routeElement;
|
|
||||||
if (route.lazy) {
|
|
||||||
const LazyComponent = route.lazy as React.ExoticComponent<unknown>;
|
|
||||||
|
|
||||||
routeElement = (
|
|
||||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active /></div>}>
|
|
||||||
{route.provider ? (
|
|
||||||
createElement(route.provider, {}, <LazyComponent />)
|
|
||||||
) : (
|
|
||||||
<LazyComponent />
|
|
||||||
)}
|
|
||||||
</Suspense>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
routeElement = route.provider ? (
|
|
||||||
createElement(route.provider, {}, route.component)
|
|
||||||
) : (
|
|
||||||
route.component
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Route
|
|
||||||
key={route.key}
|
|
||||||
path={route.path}
|
|
||||||
element={routeElement}
|
|
||||||
>
|
|
||||||
{route.children && generateRoutes(route.children as RouteConfig[])}
|
|
||||||
</Route>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保护的路由组件
|
|
||||||
function ProtectedRoute() {
|
|
||||||
const {state} = useGlobalContext()
|
|
||||||
return state.isAuthenticated? <BasicLayout project="core" /> : <Navigate to="/login" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RenderRoutes
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import {StrictMode} from 'react'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
|
||||||
import App from './App.tsx'
|
|
||||||
import '@core/index.css'
|
|
||||||
import {GlobalProvider} from "@common/contexts/GlobalStateContext.tsx";
|
|
||||||
|
|
||||||
async function initializeApp() {
|
|
||||||
try {
|
|
||||||
// 初始化行为
|
|
||||||
// await fetchInitialConfig(); // 示例:获取初始配置
|
|
||||||
|
|
||||||
// 异步操作完成后,渲染React应用
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
||||||
<StrictMode>
|
|
||||||
<GlobalProvider>
|
|
||||||
<App />
|
|
||||||
</GlobalProvider>
|
|
||||||
</StrictMode>,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Initialization failed:', error);
|
|
||||||
// 处理初始化失败的情况,比如渲染一个错误界面
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行初始化
|
|
||||||
initializeApp();
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* @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';
|
|
||||||
|
|
||||||
const viteProcess = exec('pnpm run build');
|
|
||||||
|
|
||||||
viteProcess.stdout.on('data', (data) => {
|
|
||||||
console.log(data.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
viteProcess.stderr.on('data', (data) => {
|
|
||||||
console.error(data.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
viteProcess.on('close', (code) => {
|
|
||||||
console.log(`Vite process exited with code ${code}`);
|
|
||||||
});
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2020",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": false,
|
|
||||||
"noUnusedParameters": false,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"paths": {
|
|
||||||
"@core/*": ["../core/src/*"],
|
|
||||||
"@common/*": ["../common/src/*"],
|
|
||||||
"@market/*": ["../market/src/*"],
|
|
||||||
"@dashboard/*": ["../dashboard/src/*"],
|
|
||||||
"@openApi/*": ["../openApi/src/*"],
|
|
||||||
"@systemRunning/*": ["../systemRunning/src/*"],
|
|
||||||
"@businessEntry/*": ["./src/*"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../common/src/components/aoplatform/ScrollableSection.tsx", "../common/src/utils/postcat.tsx", "../common/src/utils/curl.ts", "../common/src/components/aoplatform/ResetPsw.tsx", "../common/src/components/aoplatform/SubscribeApprovalModalContent.tsx", "src/components/aoplatform/RenderRoutes.tsx", "../common/src/components/aoplatform/PublishApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePage.tsx", "../common/src/const/type.ts", "../common/src/components/aoplatform/intelligent-plugin", "../common/src/const/domain"],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
import { defineConfig } from 'vite'
|
|
||||||
import react from '@vitejs/plugin-react'
|
|
||||||
import path from 'path'
|
|
||||||
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';
|
|
||||||
import tailwindcss from 'tailwindcss';
|
|
||||||
import autoprefixer from 'autoprefixer';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
cacheDir: './node_modules/.vite',
|
|
||||||
build:{
|
|
||||||
outDir:'../../dist',
|
|
||||||
sourcemap: false,
|
|
||||||
chunkSizeWarningLimit: 50000,
|
|
||||||
cacheDir: './node_modules/.vite',
|
|
||||||
output: {
|
|
||||||
manualChunks(id) {
|
|
||||||
if (id.includes('node_modules')) {
|
|
||||||
return id.toString().split('node_modules/')[1].split('/')[0].toString();
|
|
||||||
}
|
|
||||||
// 针对 pnpm 和 Monorepo 特殊处理
|
|
||||||
if (id.includes('.pnpm')) {
|
|
||||||
const segments = id.split(path.sep);
|
|
||||||
const packageName = segments[segments.indexOf('.pnpm') + 1].split('@')[0];
|
|
||||||
return packageName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
css: {
|
|
||||||
postcss: {
|
|
||||||
plugins: [
|
|
||||||
tailwindcss(path.resolve(__dirname, '../common/tailwind.config.js')),
|
|
||||||
autoprefixer
|
|
||||||
],
|
|
||||||
},
|
|
||||||
preprocessorOptions: {
|
|
||||||
less: {
|
|
||||||
javascriptEnabled: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
modules:{
|
|
||||||
localsConvention:"camelCase",
|
|
||||||
generateScopedName:"[local]_[hash:base64:2]"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: [react(),
|
|
||||||
dynamicImportVars({
|
|
||||||
include:["src"],
|
|
||||||
exclude:[],
|
|
||||||
warnOnError:false
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: [
|
|
||||||
{ find: /^~/, replacement: '' },
|
|
||||||
{ find: '@common', replacement: path.resolve(__dirname, '../common/src') },
|
|
||||||
{ find: '@market', replacement: path.resolve(__dirname, '../market/src') },
|
|
||||||
{ find: '@core', replacement: path.resolve(__dirname, '../core/src') },
|
|
||||||
{ find: '@dashboard', replacement: path.resolve(__dirname, '../dashboard/src') },
|
|
||||||
{ find: '@openApi', replacement: path.resolve(__dirname, '../openApi/src') },
|
|
||||||
{ find: '@systemRunning', replacement: path.resolve(__dirname, '../systemRunning/src') },
|
|
||||||
{ find: '@businessEntry', replacement: path.resolve(__dirname, './src') },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
'/api/v1': {
|
|
||||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
|
||||||
target: 'http://172.18.166.219:8288/',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/api2/v1': {
|
|
||||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
|
||||||
target: 'http://172.18.166.219:8288/',
|
|
||||||
changeOrigin: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
logLevel:'info'
|
|
||||||
})
|
|
||||||
-85
File diff suppressed because one or more lines are too long
@@ -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 {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
'postcss-import': {},
|
'postcss-import': {},
|
||||||
|
|||||||
@@ -1,185 +1,162 @@
|
|||||||
import {
|
import {
|
||||||
ConfigProvider,
|
MenuProps,
|
||||||
Dropdown,
|
App,
|
||||||
MenuProps,
|
Button,
|
||||||
App,
|
ConfigProvider,
|
||||||
Button} from 'antd';
|
Dropdown
|
||||||
|
} from 'antd';
|
||||||
|
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||||
import Logo from '@common/assets/layout-logo.png';
|
import Logo from '@common/assets/layout-logo.png';
|
||||||
import AvatarPic from '@common/assets/default-avatar.png'
|
import AvatarPic from '@common/assets/default-avatar.png'
|
||||||
import {Outlet, useLocation, useNavigate} from "react-router-dom";
|
import { useCallback, useEffect, useMemo, useState} from "react";
|
||||||
import { useEffect, useMemo, useState} from "react";
|
|
||||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx';
|
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx';
|
||||||
import { PERMISSION_DEFINITION } from '@common/const/permissions.ts';
|
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 { BasicResponse, RESPONSE_TIPS, routerKeyMap, STATUS_CODE } from '@common/const/const.tsx';
|
||||||
import { UserInfoType } from '@common/const/type.ts';
|
import { UserInfoType } from '@common/const/type.ts';
|
||||||
import { useFetch } from '@common/hooks/http.ts';
|
import { useFetch } from '@common/hooks/http.ts';
|
||||||
import { ProjectFilled } from '@ant-design/icons';
|
import { ProjectFilled } from '@ant-design/icons';
|
||||||
import { getNavItem } from '@common/utils/navigation';
|
import { getNavItem, transformMenuData } from '@common/utils/navigation';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { $t } from '@common/locales';
|
import { $t } from '@common/locales';
|
||||||
|
import { ProConfigProvider, ProLayout } from '@ant-design/pro-components';
|
||||||
import LanguageSetting from './LanguageSetting';
|
import LanguageSetting from './LanguageSetting';
|
||||||
|
import { usePluginSlotHub } from '@common/contexts/PluginSlotHubContext';
|
||||||
|
|
||||||
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
||||||
export type MenuItem = Required<MenuProps>['items'][number];
|
export type MenuItem = Required<MenuProps>['items'][number];
|
||||||
|
|
||||||
const themeToken = {
|
const themeToken = {
|
||||||
bgLayout:'#17163E;',
|
bgLayout: '#17163E;',
|
||||||
header: {
|
header: {
|
||||||
heightLayoutHeader:72
|
heightLayoutHeader: 72
|
||||||
},
|
},
|
||||||
pageContainer:{
|
pageContainer: {
|
||||||
paddingBlockPageContainerContent:0,
|
paddingBlockPageContainerContent: 0,
|
||||||
paddingInlinePageContainerContent:0,
|
paddingInlinePageContainerContent: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function BasicLayout({project = 'core'}:{project:string}){
|
function BasicLayout({project = 'core'}:{project:string}){
|
||||||
const navigator = useNavigate()
|
const navigator = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const currentUrl = location.pathname
|
const currentUrl = location.pathname
|
||||||
const { state,accessData,checkPermission,accessInit} = useGlobalContext()
|
const { state,accessData,checkPermission,accessInit,dispatch,resetAccess,getGlobalAccessData, menuList} = useGlobalContext()
|
||||||
const [pathname, setPathname] = useState(currentUrl);
|
const [pathname, setPathname] = useState(currentUrl);
|
||||||
const mainPage = project === 'core' ?'/service/list':'/serviceHub/list'
|
const mainPage = project === 'core' ?'/service/list':'/serviceHub/list'
|
||||||
|
const [menuItems, setMenuItems] = useState<MenuProps['items']>();
|
||||||
|
const pluginSlotHub = usePluginSlotHub()
|
||||||
|
|
||||||
const TOTAL_MENU_ITEMS:MenuProps['items'] = useMemo(() => [
|
useEffect(()=>{
|
||||||
getNavItem($t('工作空间'), 'workspace','/guide/page',<Icon icon="ic:baseline-space-dashboard" width="18" height="18"/>, [
|
const newMenu = transformMenuData(menuList)
|
||||||
getNavItem(<a>{$t('首页')}</a>, 'guide','/guide/page',<Icon icon="ic:baseline-home" width="18" height="18"/>,undefined,undefined,'all'),
|
setMenuItems(newMenu);
|
||||||
getNavItem(<a>{$t('服务')}</a>, 'service','/service',<Icon icon="ic:baseline-blinds-closed" width="18" height="18"/>,undefined,undefined,'all'),
|
},[menuList, state.language,accessInit])
|
||||||
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('仪表盘'), 'mainPage', APP_MODE === 'pro' ? '/analytics' : '/analytics/total',<Icon icon="ic:baseline-bar-chart" width="18" height="18"/>,[
|
useEffect(() => {
|
||||||
getNavItem(<a >{$t('运行视图')}</a>, 'analytics',APP_MODE === 'pro' ? '/analytics' : '/analytics/total' ,<ProjectFilled />,undefined,undefined,'system.dashboard.run_view.view'),
|
if (currentUrl === '/') {
|
||||||
APP_MODE === 'pro' ? getNavItem(<a >{$t('系统拓扑图')}</a>, 'systemrunning','/systemrunning',<ProjectFilled />,undefined,undefined,'system.dashboard.systemrunning.view') : null,
|
navigator(mainPage)
|
||||||
],undefined,'system.dashboard.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'),
|
|
||||||
],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>, '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'),
|
|
||||||
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,
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
],[state.language,accessInit])
|
|
||||||
|
|
||||||
|
}, [currentUrl]);
|
||||||
|
|
||||||
useEffect(() => {
|
const headerMenuData = useMemo(() => {
|
||||||
if(currentUrl === '/'){
|
// 判断权限
|
||||||
navigator(mainPage)
|
const hasAccess = (access: unknown) => checkPermission(access as keyof typeof PERMISSION_DEFINITION[0]);
|
||||||
}
|
|
||||||
|
|
||||||
}, [currentUrl]);
|
|
||||||
|
|
||||||
const headerMenuData = useMemo(() => {
|
// 过滤菜单项
|
||||||
// 判断权限
|
const filterMenu = (menu: Array<{ [k: string]: unknown }>) => {
|
||||||
const hasAccess = (access: unknown) => checkPermission(access as keyof typeof PERMISSION_DEFINITION[0]);
|
return [...menu]
|
||||||
|
.filter(x => x) // 过滤掉空数据
|
||||||
// 过滤菜单项
|
.map((item: any) => {
|
||||||
const filterMenu = (menu: Array<{ [k: string]: unknown }>) => {
|
if (item.routes && item.routes.length > 0) {
|
||||||
return [...menu]
|
// 递归处理子菜单
|
||||||
.filter(x => x) // 过滤掉空数据
|
const filteredRoutes: Array<{ [k: string]: unknown }> = filterMenu(item.routes);
|
||||||
.map((item: any) => {
|
|
||||||
if (item.routes && item.routes.length > 0) {
|
|
||||||
// 递归处理子菜单
|
|
||||||
const filteredRoutes: Array<{ [k: string]: unknown }> = filterMenu(item.routes);
|
|
||||||
|
|
||||||
if(filteredRoutes.length === 0){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return {...item, routes: filteredRoutes};
|
|
||||||
}
|
|
||||||
// 处理没有 routes 的菜单项
|
|
||||||
if (item.access) {
|
|
||||||
return (item.access === 'all' || hasAccess(item.access)) ? item : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (filteredRoutes.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return { ...item,routes: filteredRoutes,name:$t(item.name) };
|
||||||
|
}
|
||||||
|
// 处理没有 routes 的菜单项
|
||||||
|
if (item.access) {
|
||||||
|
return (item.access === 'all' || hasAccess(item.access)) ? {...item,name:$t(item.name)} : null;
|
||||||
|
}
|
||||||
// 如果没有 access 和 routes,则保留
|
// 如果没有 access 和 routes,则保留
|
||||||
return item;
|
return {...item,name:$t(item.name) };
|
||||||
})
|
})
|
||||||
.filter(x => x); // 过滤掉处理后为 null 的项
|
.filter(x => x); // 过滤掉处理后为 null 的项
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始过滤操作
|
// 初始过滤操作
|
||||||
const res = [...TOTAL_MENU_ITEMS]!.filter(x => x).map((x: any) => (x.routes ? { ...x, routes: filterMenu(x.routes) } : x));
|
const res = [...(menuItems || [])]!.filter(x => x).map((x: any) => (x.routes ? { ...x,name:$t(x.name), routes: filterMenu(x.routes) } : {...x,name:$t(x.name)}));
|
||||||
// 返回处理后的数据
|
// 返回处理后的数据
|
||||||
return { path: '/', routes: res.map(x=> ({...x, routes: x.routes?.filter(x=> (x.access || x.routes?.length > 0))})).filter(x=> (x.access || x.routes?.length > 0)) };
|
return { path: '/', routes: res.map(x=> ({...x, routes: x.routes?.filter(x=> (x.access || x.routes?.length > 0))})).filter(x=> (x.access || x.routes?.length > 0)) };
|
||||||
}, [accessData, state.language]);
|
}, [accessData, state.language,menuItems]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { message } = App.useApp()
|
const { message } = App.useApp()
|
||||||
const { dispatch,resetAccess,getGlobalAccessData} = useGlobalContext()
|
|
||||||
const [userInfo,setUserInfo] = useState<UserInfoType>()
|
const [userInfo,setUserInfo] = useState<UserInfoType>()
|
||||||
const {fetchData} = useFetch()
|
const {fetchData} = useFetch()
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const getUserInfo = ()=>{
|
const getUserInfo = () => {
|
||||||
fetchData<BasicResponse<{profile:UserInfoType}>>('account/profile',{method:'GET'})
|
fetchData<BasicResponse<{ profile: UserInfoType }>>('account/profile', { method: 'GET' })
|
||||||
.then(response=>{
|
.then(response => {
|
||||||
const {code,data,msg} = response
|
const { code, data, msg } = response
|
||||||
if(code === STATUS_CODE.SUCCESS){
|
if (code === STATUS_CODE.SUCCESS) {
|
||||||
setUserInfo(data.profile)
|
setUserInfo(data.profile)
|
||||||
dispatch({type:'UPDATE_USERDATA',userData:data.profile})
|
dispatch({ type: 'UPDATE_USERDATA', userData: data.profile })
|
||||||
}else{
|
} else {
|
||||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUserInfo()
|
getUserInfo()
|
||||||
getGlobalAccessData()
|
getGlobalAccessData()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const logOut = ()=>{
|
|
||||||
fetchData<BasicResponse<null>>('account/logout',{method:'GET'}).then(response=>{
|
|
||||||
const {code,msg} = response
|
|
||||||
if(code === STATUS_CODE.SUCCESS){
|
|
||||||
dispatch({type:'LOGOUT'})
|
|
||||||
resetAccess()
|
|
||||||
// message.success(msg || $t(RESPONSE_TIPS.logoutSuccess))
|
|
||||||
navigate('/login')
|
|
||||||
}else{
|
|
||||||
message.error(msg ||$t(RESPONSE_TIPS.error))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
const logOut = () => {
|
||||||
{
|
fetchData<BasicResponse<null>>('account/logout', { method: 'GET' }).then(response => {
|
||||||
key: '2',
|
const { code, msg } = response
|
||||||
label: (
|
if (code === STATUS_CODE.SUCCESS) {
|
||||||
<Button key="changePsw" type="text" className="flex items-center p-0 bg-transparent border-none " onClick={()=>navigator('/userProfile/changepsw')}>
|
dispatch({ type: 'LOGOUT' })
|
||||||
{$t('账号设置')}
|
resetAccess()
|
||||||
</Button>)
|
// message.success(msg || $t(RESPONSE_TIPS.logoutSuccess))
|
||||||
},
|
navigate('/login')
|
||||||
{
|
} else {
|
||||||
key: '3',
|
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||||
label: (
|
}
|
||||||
<Button key="logout" type="text" className="flex items-center p-0 bg-transparent border-none " onClick={logOut}>
|
})
|
||||||
{$t('退出登录')}
|
}
|
||||||
</Button>)
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
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')}>
|
||||||
|
{$t('账号设置')}
|
||||||
|
</Button>)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: (
|
||||||
|
<Button key="logout" type="text" className="flex items-center p-0 bg-transparent border-none " onClick={logOut}>
|
||||||
|
{$t('退出登录')}
|
||||||
|
</Button>)
|
||||||
|
},
|
||||||
|
].filter(Boolean), [userInfo]);
|
||||||
|
|
||||||
|
|
||||||
|
const actionRender =useMemo( ()=>{
|
||||||
|
return [
|
||||||
|
<LanguageSetting />,
|
||||||
|
<Button className=" text-[#ffffffb3] hover:text-[#fff] border-none" type="default" ghost onClick={()=>{window.open('https://docs.apipark.com','_blank')}}>
|
||||||
|
<span className='flex items-center gap-[8px]'> <Icon icon="ic:baseline-help" width="14" height="14"/>{$t('文档')}</span>
|
||||||
|
</Button> ,
|
||||||
|
...((pluginSlotHub.getSlot('basicLayoutAfterBtns') as unknown[] )||[] )
|
||||||
|
]
|
||||||
|
},[pluginSlotHub.getSlot('basicLayoutAfterBtns') ])
|
||||||
|
|
||||||
|
|
||||||
return(
|
return(
|
||||||
@@ -231,12 +208,7 @@ const themeToken = {
|
|||||||
actionsRender={(props) => {
|
actionsRender={(props) => {
|
||||||
if (props.isMobile) return [];
|
if (props.isMobile) return [];
|
||||||
if (typeof window === 'undefined') return [];
|
if (typeof window === 'undefined') return [];
|
||||||
return [
|
return actionRender;
|
||||||
<LanguageSetting />,
|
|
||||||
<Button className=" text-[#ffffffb3] hover:text-[#fff] border-none" type="default" ghost onClick={()=>{window.open('https://docs.apipark.com','_blank')}}>
|
|
||||||
<span className='flex items-center gap-[8px]'> <Icon icon="ic:baseline-help" width="14" height="14"/>{$t('文档')}</span>
|
|
||||||
</Button>
|
|
||||||
];
|
|
||||||
}}
|
}}
|
||||||
headerTitleRender={() => (
|
headerTitleRender={() => (
|
||||||
<div className="w-[192px] flex items-center">
|
<div className="w-[192px] flex items-center">
|
||||||
@@ -248,7 +220,7 @@ const themeToken = {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
logo={Logo}
|
logo={Logo}
|
||||||
pageTitleRender={()=>$t('APIPark - 企业API数据开放平台')}
|
pageTitleRender={()=>$t('APIPark')}
|
||||||
menuFooterRender={(props) => {
|
menuFooterRender={(props) => {
|
||||||
if (props?.collapsed) return undefined;
|
if (props?.collapsed) return undefined;
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ const InsidePage:FC<InsidePageProps> = ({showBanner=true,pageTitle,tagList,showB
|
|||||||
// <div className="h-full flex flex-col flex-1 overflow-hidden bg-[#f7f8fa]">
|
// <div className="h-full flex flex-col flex-1 overflow-hidden bg-[#f7f8fa]">
|
||||||
<div className={`h-full flex flex-col flex-1 overflow-hidden ${className}`}>
|
<div className={`h-full flex flex-col flex-1 overflow-hidden ${className}`}>
|
||||||
{ showBanner && <div className={`border-[0px] mr-PAGE_INSIDE_X ${showBorder ? 'border-b-[1px] border-solid border-BORDER' : ''} ${headerClassName}`}>
|
{ showBanner && <div className={`border-[0px] mr-PAGE_INSIDE_X ${showBorder ? 'border-b-[1px] border-solid border-BORDER' : ''} ${headerClassName}`}>
|
||||||
<div className="mb-[30px]">
|
{!pageTitle && !description && !backUrl &&!customBtn ? <></>: <div className="mb-[30px]">
|
||||||
{backUrl &&<div className="text-[18px] leading-[25px] mb-[12px]">
|
{backUrl &&<div className="text-[18px] leading-[25px] mb-[12px]">
|
||||||
<Button type="text" onClick={goBack}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
|
<Button type="text" onClick={goBack}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
|
||||||
</div>}
|
</div>}
|
||||||
<div className="flex justify-between mb-[20px] items-center ">
|
<div className="flex justify-between mb-[20px] items-center ">
|
||||||
<div className="flex items-center gap-TAG_LEFT ">
|
<div className="flex items-center gap-TAG_LEFT ">
|
||||||
<p className="text-theme text-[26px] ">{pageTitle}</p>
|
<div className="text-theme text-[26px] ">{pageTitle}</div>
|
||||||
{tagList && tagList?.length > 0 && tagList?.map((tag)=>{
|
{tagList && tagList?.length > 0 && tagList?.map((tag)=>{
|
||||||
return ( <Tag key={tag.label as string} bordered={false} >{tag.label}</Tag>)
|
return ( <Tag key={tag.label as string} bordered={false} >{tag.label}</Tag>)
|
||||||
})}
|
})}
|
||||||
@@ -53,10 +53,10 @@ const InsidePage:FC<InsidePageProps> = ({showBanner=true,pageTitle,tagList,showB
|
|||||||
}}>{btnTitle}</Button></WithPermission>}
|
}}>{btnTitle}</Button></WithPermission>}
|
||||||
{customBtn}
|
{customBtn}
|
||||||
</div>
|
</div>
|
||||||
<p >
|
<div >
|
||||||
{description}
|
{description}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>}
|
||||||
</div>}
|
</div>}
|
||||||
<div className={`h-full ${scrollPage ? 'overflow-hidden' : 'overflow-auto'} ${contentClassName || ''}`}>{children}</div>
|
<div className={`h-full ${scrollPage ? 'overflow-hidden' : 'overflow-auto'} ${contentClassName || ''}`}>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,69 +4,88 @@ import { memo, useEffect, useMemo } from 'react';
|
|||||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
||||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||||
|
|
||||||
const LanguageSetting = ({mode = 'light'}:{mode?:'dark'|'light'}) => {
|
const LanguageSetting = ({ mode = 'light' }: { mode?: 'dark' | 'light' }) => {
|
||||||
const { dispatch,state} = useGlobalContext()
|
const { dispatch, state } = useGlobalContext();
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
key: 'en-US',
|
key: 'en-US',
|
||||||
label:<Button key="en" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
label: (
|
||||||
English
|
<Button key="en" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
</Button>,
|
English
|
||||||
title:'English'
|
</Button>
|
||||||
},
|
),
|
||||||
{
|
title: 'English',
|
||||||
key: 'ja-JP',
|
},
|
||||||
label: <Button key="jp" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
{
|
||||||
|
key: 'ja-JP',
|
||||||
|
label: (
|
||||||
|
<Button key="jp" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
日本語
|
日本語
|
||||||
</Button>,
|
</Button>
|
||||||
title: '日本語',
|
),
|
||||||
},
|
title: '日本語',
|
||||||
{
|
},
|
||||||
key: 'zh-TW',
|
{
|
||||||
label: <Button key="tw" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
key: 'zh-TW',
|
||||||
繁體中文
|
label: (
|
||||||
</Button>,
|
<Button key="tw" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
title: '繁體中文',
|
繁體中文
|
||||||
},
|
</Button>
|
||||||
{
|
),
|
||||||
key: 'zh-CN',
|
title: '繁體中文',
|
||||||
label: <Button key="cn" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
},
|
||||||
简体中文
|
{
|
||||||
</Button>,
|
key: 'zh-CN',
|
||||||
title: '简体中文',
|
label: (
|
||||||
},
|
<Button key="cn" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
|
简体中文
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
title: '简体中文',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const langLabel = useMemo(()=>items.find((item) => item?.key === state.language)?.title,[state.language])
|
const langLabel = useMemo(
|
||||||
|
() => items.find(item => item?.key === state.language)?.title,
|
||||||
|
[state.language]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
const savedLang = sessionStorage.getItem('i18nextLng')
|
const savedLang = sessionStorage.getItem('i18nextLng');
|
||||||
const browserLang = navigator.language || navigator.userLanguage
|
const browserLang = navigator.language || navigator.userLanguage;
|
||||||
if(savedLang){
|
if (savedLang) return;
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: savedLang });
|
|
||||||
}else{
|
dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang });
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang });
|
}, []);
|
||||||
}
|
|
||||||
},[
|
|
||||||
])
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
trigger={['hover']}
|
trigger={['hover']}
|
||||||
menu={{
|
menu={{
|
||||||
items,
|
items,
|
||||||
style:{minWidth:'80px'},
|
style: { minWidth: '80px' },
|
||||||
onClick: (e) => {
|
onClick: e => {
|
||||||
const { key } = e;
|
const { key } = e;
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: key });
|
dispatch({ type: 'UPDATE_LANGUAGE', language: key });
|
||||||
i18n.changeLanguage(key);
|
i18n.changeLanguage(key);
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button className={`border-none ${mode==='dark' ? "text-[#333] hover:text-[#333333b3]" : "text-[#ffffffb3] hover:text-[#fff] "}`} type="default" ghost >
|
<Button
|
||||||
<span className='flex items-center gap-[8px]'> <Icon icon="ic:baseline-language" width="14" height="14"/>{langLabel}</span>
|
className={`border-none ${
|
||||||
</Button>
|
mode === 'dark'
|
||||||
|
? 'text-[#333] hover:text-[#333333b3]'
|
||||||
|
: 'text-[#ffffffb3] hover:text-[#fff] '
|
||||||
|
}`}
|
||||||
|
type="default"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-[8px]">
|
||||||
|
{' '}
|
||||||
|
<Icon icon="ic:baseline-language" width="14" height="14" />
|
||||||
|
{langLabel}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default memo(LanguageSetting);
|
export default memo(LanguageSetting);
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,23 @@
|
|||||||
|
|
||||||
import { GetProp, TransferProps, TreeDataNode, theme, Transfer, Tree, Spin } from "antd";
|
import { TransferProps, TreeDataNode, Tree, Spin, Input, Empty } from "antd";
|
||||||
import { DataNode, TreeProps } from "antd/es/tree";
|
import { DataNode } from "antd/es/tree";
|
||||||
import { Ref, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
import { Ref, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
||||||
import { ApartmentOutlined, LoadingOutlined, UserOutlined } from "@ant-design/icons";
|
import { ApartmentOutlined, LoadingOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
import { cloneDeep, debounce } from "lodash-es";
|
|
||||||
import { ColumnsType } from "antd/es/table";
|
import { ColumnsType } from "antd/es/table";
|
||||||
import { $t } from "@common/locales";
|
import { $t } from "@common/locales";
|
||||||
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
||||||
|
|
||||||
type TransferItem = GetProp<TransferProps, 'dataSource'>[number];
|
|
||||||
|
|
||||||
export type TransferTableProps<T> = {
|
export type TransferTableProps<T> = {
|
||||||
request?:(k?:string)=>Promise<{data:T[],success:boolean}>
|
request?:(k?:string)=>Promise<{data:T[],success:boolean}>
|
||||||
columns: ColumnsType<T>
|
columns: ColumnsType<T>
|
||||||
primaryKey:string
|
primaryKey:string
|
||||||
onSelect:(selectedData:T[])=>void
|
onSelect:(selectedData:string[])=>void
|
||||||
tableType?:'member'|'api'
|
tableType?:'member'|'api'
|
||||||
disabledData:string[]
|
disabledData:string[]
|
||||||
searchPlaceholder?:string
|
searchPlaceholder?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TransferTableHandle<T> = {
|
export type TransferTableHandle<T> = {
|
||||||
selectedData: () => T[];
|
|
||||||
selectedRowKeys: () => React.Key[];
|
selectedRowKeys: () => React.Key[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,10 +27,6 @@ interface TreeTransferProps {
|
|||||||
onChange: TransferProps['onChange'];
|
onChange: TransferProps['onChange'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Customize Table Transfer
|
|
||||||
const isChecked = (selectedKeys: React.Key[], eventKey: React.Key) =>
|
|
||||||
selectedKeys.includes(eventKey);
|
|
||||||
|
|
||||||
const generateTree = (
|
const generateTree = (
|
||||||
treeNodes: TreeDataNode[] = [],
|
treeNodes: TreeDataNode[] = [],
|
||||||
checkedKeys: TreeTransferProps['targetKeys'] = [],
|
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}>>(
|
const MemberTransfer= forwardRef<TransferTableHandle<{[k:string]:unknown}>, TransferTableProps<{[k:string]:unknown}>>(
|
||||||
<T extends {[k:string]:unknown}>(props: TransferTableProps<T>, ref:Ref<TransferTableHandle<T>>) => {
|
<T extends {[k:string]:unknown}>(props: TransferTableProps<T>, ref:Ref<TransferTableHandle<T>>) => {
|
||||||
const {request,columns,primaryKey,onSelect,tableType,disabledData = [],searchPlaceholder} = props
|
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 [targetKeys, setTargetKeys] = useState<TreeTransferProps['targetKeys']>([]);
|
||||||
const [dataSource, setDataSource] = useState<DataNode[] >([])
|
const [dataSource, setDataSource] = useState<DataNode[] >([])
|
||||||
const parentRef = useRef<HTMLDivElement>(null);
|
const parentRef = useRef<HTMLDivElement>(null);
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const {state} = useGlobalContext()
|
const {state} = useGlobalContext()
|
||||||
|
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
|
||||||
|
const [searchWord, setSearchWord] = useState<string>('')
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setTargetKeys(disabledData)
|
setTargetKeys(disabledData)
|
||||||
},[disabledData])
|
},[disabledData])
|
||||||
|
|
||||||
useImperativeHandle(ref, () =>({
|
useImperativeHandle(ref, () =>({
|
||||||
selectedData: () => dataSource,
|
|
||||||
selectedRowKeys: () => targetKeys,}))
|
selectedRowKeys: () => targetKeys,}))
|
||||||
|
|
||||||
const onChange: TreeTransferProps['onChange'] = (keys) => {
|
const translatedDataSource = useMemo(()=>{
|
||||||
onSelect?.(new Set(keys))
|
|
||||||
setTargetKeys(Array.from(new Set(keys)));
|
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();
|
return {
|
||||||
|
...item,
|
||||||
const transferDataSource: TransferItem[] = useMemo(()=>{
|
title,
|
||||||
function flatten(list: TreeDataNode[] = [], res:TransferItem[]) {
|
icon:<UserOutlined />,
|
||||||
list.forEach((item) => {
|
isLeaf:true,
|
||||||
res.push({...item, title:item.title === '所有成员' ? $t((item as unknown as {title:string}).title):item.title }as TransferItem);
|
disableCheckbox:disabledData.indexOf(item.key as string) !== -1
|
||||||
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 loop(dataSource);
|
||||||
return result;
|
},[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 = ()=>{
|
const getDataSource = ()=>{
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
request && request().then((res)=>{
|
request && request().then((res)=>{
|
||||||
const {data,success} = res
|
const {data,success} = res
|
||||||
setDataSource(success? data : [])
|
setDataSource(success? data : [])
|
||||||
|
setExpandedKeys(getInitExpandKeys(success? data:[]))
|
||||||
}).finally(()=>{setLoading(false)})
|
}).finally(()=>{setLoading(false)})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getDataSource()
|
|
||||||
const handleResize = () => {
|
|
||||||
setTableHeight(window.innerHeight * 80 / 100 - 64 - 72 - 56 - 16 -3)
|
|
||||||
};
|
|
||||||
|
|
||||||
const debouncedHandleResize = debounce(handleResize, 200);
|
useEffect(() => {
|
||||||
|
getDataSource()
|
||||||
// 监听窗口大小变化
|
}, []);
|
||||||
window.addEventListener('resize', debouncedHandleResize);
|
|
||||||
handleResize();
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('resize', debouncedHandleResize);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={parentRef}>
|
<div ref={parentRef}>
|
||||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading} className=''>
|
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading} className=''>
|
||||||
<Transfer
|
<Input className="mb-[10px]" placeholder={searchPlaceholder} onChange={(e)=>setSearchWord(e.target.value)} value={searchWord} />
|
||||||
showSearch
|
<>{ translatedDataSource && translatedDataSource.length > 0 ? <Tree
|
||||||
onSearch={(dir)=>{
|
checkable
|
||||||
memo = {};
|
expandedKeys={expandedKeys}
|
||||||
}}
|
checkedKeys={targetKeys}
|
||||||
listStyle={{width:'408px'}}
|
selectable={false}
|
||||||
disabledData={disabledData}
|
onCheck={(e)=>{setTargetKeys(e);
|
||||||
filterOption={(inputValue: string, item: any) => handlerFilterOption(inputValue, item)}
|
onSelect(((e as string[])?.filter(x=>disabledData.indexOf(x as string) === -1))||[])}}
|
||||||
targetKeys={targetKeys}
|
onExpand={setExpandedKeys}
|
||||||
dataSource={transferDataSource}
|
treeData={translatedDataSource}
|
||||||
className="tree-transfer"
|
blockNode
|
||||||
render={(item) => item.title!}
|
showIcon
|
||||||
showSelectAll={false}
|
/>
|
||||||
onChange={onChange}
|
: <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/> }</>
|
||||||
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>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Result, Skeleton } from 'antd';
|
||||||
|
|
||||||
|
const NotFound: React.FC = () => {
|
||||||
|
const [showPage, setShowPage] = useState<boolean>(false)
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setTimeout(()=>setShowPage(true), 1000)
|
||||||
|
},[])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`h-full w-full flex flex-1 align-middle ${showPage ? 'items-center' : ''}`}>
|
||||||
|
{ showPage ? <Result
|
||||||
|
className='w-full'
|
||||||
|
status="404"
|
||||||
|
title="404"
|
||||||
|
subTitle="Sorry, the page you visited does not exist."
|
||||||
|
/> : <Skeleton active /> }
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
export default NotFound;
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import {App, Form, Input, Row, Table} from "antd";
|
||||||
|
import {forwardRef, useEffect, useImperativeHandle, useMemo} from "react";
|
||||||
|
import {useFetch} from "@common/hooks/http.ts";
|
||||||
|
import {BasicResponse, PLACEHOLDER, PolicyPublishColumns, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||||
|
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||||
|
import { $t } from "@common/locales";
|
||||||
|
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
||||||
|
import { PolicyPublishModalHandle, PolicyPublishModalProps } from "@common/const/type";
|
||||||
|
|
||||||
|
|
||||||
|
export const PolicyPublishModalContent = forwardRef<PolicyPublishModalHandle,PolicyPublishModalProps>((props, ref) => {
|
||||||
|
const { message } = App.useApp()
|
||||||
|
const { data} = props
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const {fetchData} = useFetch()
|
||||||
|
const {state} = useGlobalContext()
|
||||||
|
|
||||||
|
const publish:()=>Promise<boolean | string | Record<string, unknown>> = ()=>{
|
||||||
|
return new Promise((resolve, reject)=>{
|
||||||
|
form.validateFields().then((value)=>{
|
||||||
|
const body = {...value, source:data.source}
|
||||||
|
fetchData<BasicResponse<null>>('strategy/global/data-masking/publish',{method: 'POST',eoBody:body,eoTransformKeys:['versionName']}).then(response=>{
|
||||||
|
const {code,msg} = response
|
||||||
|
if(code === STATUS_CODE.SUCCESS){
|
||||||
|
message.success(msg || $t(RESPONSE_TIPS.success))
|
||||||
|
resolve(response)
|
||||||
|
}else{
|
||||||
|
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||||
|
reject(msg || $t(RESPONSE_TIPS.error))
|
||||||
|
}
|
||||||
|
}).catch((errorInfo)=> reject(errorInfo))
|
||||||
|
}).catch((errorInfo)=> reject(errorInfo))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useImperativeHandle(ref, ()=>({
|
||||||
|
publish,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
form.setFieldsValue(data)
|
||||||
|
},[data])
|
||||||
|
|
||||||
|
const translatedPolicyColumns = useMemo(()=>PolicyPublishColumns.map((x)=>({
|
||||||
|
...x,
|
||||||
|
title: typeof x.title === 'string' ? $t(x.title) : x.title,
|
||||||
|
})),[state.language])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<WithPermission access=""><Form
|
||||||
|
className=" mx-auto"
|
||||||
|
form={form}
|
||||||
|
labelAlign='left'
|
||||||
|
layout='vertical'
|
||||||
|
scrollToFirstError
|
||||||
|
name="publishApprovalModalContent"
|
||||||
|
// labelCol={{span: 3}}
|
||||||
|
// wrapperCol={{span: 21}}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label={$t("发布名称")}
|
||||||
|
name='versionName'
|
||||||
|
rules={[{required: true,whitespace:true }]}
|
||||||
|
>
|
||||||
|
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label={$t("描述")}
|
||||||
|
name="desc"
|
||||||
|
>
|
||||||
|
<Input.TextArea className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
|
||||||
|
</Form.Item>
|
||||||
|
<Row className="mt-mbase pb-[8px] h-[32px] font-bold" ><span >{$t('策略列表')}:</span></Row>
|
||||||
|
<Row className="mb-mbase ">
|
||||||
|
<Table
|
||||||
|
columns={translatedPolicyColumns}
|
||||||
|
bordered={true}
|
||||||
|
rowKey="name"
|
||||||
|
size="small"
|
||||||
|
dataSource={data.strategies || []}
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
{!data?.isPublish&& data?.unpublishMsg&& <p className="text-status_fail mt-[4px]">{data.unpublishMsg}</p>}
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
</Form>
|
||||||
|
</WithPermission>
|
||||||
|
</>)
|
||||||
|
})
|
||||||
@@ -6,7 +6,7 @@ import {BasicResponse, FORM_ERROR_TIPS, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE,
|
|||||||
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||||
import { SYSTEM_PUBLISH_ONLINE_COLUMNS } from "@core/const/system/const.tsx";
|
import { SYSTEM_PUBLISH_ONLINE_COLUMNS } from "@core/const/system/const.tsx";
|
||||||
import { $t } from "@common/locales";
|
import { $t } from "@common/locales";
|
||||||
import { ApprovalRouteColumns, ApprovalStatusColorClass, ApprovalUpstreamColumns, ChangeTypeEnum } from "@common/const/approval/const";
|
import { ApprovalPolicyColumns, ApprovalRouteColumns, ApprovalStatusColorClass, ApprovalUpstreamColumns, ChangeTypeEnum } from "@common/const/approval/const";
|
||||||
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
||||||
import { LoadingOutlined } from "@ant-design/icons";
|
import { LoadingOutlined } from "@ant-design/icons";
|
||||||
import { SystemInsidePublishOnlineItems } from "@core/pages/system/publish/SystemInsidePublishOnline";
|
import { SystemInsidePublishOnlineItems } from "@core/pages/system/publish/SystemInsidePublishOnline";
|
||||||
@@ -140,6 +140,22 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
|
|||||||
}
|
}
|
||||||
}),[state.language])
|
}),[state.language])
|
||||||
|
|
||||||
|
|
||||||
|
const translatedPolicyColumns = useMemo(()=>ApprovalPolicyColumns.map((x)=>{
|
||||||
|
return {
|
||||||
|
...x,
|
||||||
|
title: typeof x.title === 'string' ? $t(x.title) : x.title,
|
||||||
|
...(x.dataIndex === 'status' ? {
|
||||||
|
render:(_,entity)=> (
|
||||||
|
<span className={`${ApprovalStatusColorClass[entity.change as keyof typeof ApprovalStatusColorClass]} truncate block`}>
|
||||||
|
{$t(ChangeTypeEnum[entity.change as (keyof typeof ChangeTypeEnum)] || '-')}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}:{})
|
||||||
|
}
|
||||||
|
}),[state.language])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!insidePage && <>
|
{!insidePage && <>
|
||||||
@@ -219,12 +235,22 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
|
|||||||
/></Row>
|
/></Row>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
<Form.Item
|
<Row className="mt-mbase pb-[8px] h-[32px] font-bold" ><span >{$t('策略列表')}:</span></Row>
|
||||||
|
<Row className="mb-mbase ">
|
||||||
|
<Table
|
||||||
|
bordered={true}
|
||||||
|
columns={translatedPolicyColumns}
|
||||||
|
size="small"
|
||||||
|
rowKey="id"
|
||||||
|
dataSource={data.diffs?.strategies || []}
|
||||||
|
pagination={false}
|
||||||
|
/></Row>
|
||||||
|
{/* <Form.Item
|
||||||
label={$t("备注")}
|
label={$t("备注")}
|
||||||
name="remark"
|
name="remark"
|
||||||
>
|
>
|
||||||
<Input.TextArea className="w-INPUT_NORMAL" disabled={type !== 'add' && type !== 'publish'} placeholder={$t(PLACEHOLDER.input)} />
|
<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
|
{type !== 'add' && type !== 'publish' && <Form.Item
|
||||||
label={$t("审核意见"
|
label={$t("审核意见"
|
||||||
|
|||||||
@@ -8,64 +8,78 @@ import { Icon } from "@iconify/react/dist/iconify.js"
|
|||||||
import { $t } from "@common/locales"
|
import { $t } from "@common/locales"
|
||||||
|
|
||||||
type TableBtnWithPermissionProps = {
|
type TableBtnWithPermissionProps = {
|
||||||
btnTitle:string
|
btnTitle: string
|
||||||
access?:keyof typeof PERMISSION_DEFINITION[0],
|
access?: keyof typeof PERMISSION_DEFINITION[0],
|
||||||
tooltip?:string,
|
tooltip?: string,
|
||||||
disabled?:boolean,
|
disabled?: boolean,
|
||||||
navigateTo?:string,
|
navigateTo?: string,
|
||||||
onClick?:(args?:unknown)=>void
|
onClick?: (args?: unknown) => void
|
||||||
className?:string
|
className?: string
|
||||||
btnType:string
|
btnType: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const TableIconName={
|
const TableIconName = {
|
||||||
'add':'ic:baseline-add',
|
'add': 'ic:baseline-add',
|
||||||
'edit':'ic:baseline-edit',
|
'edit': 'ic:baseline-edit',
|
||||||
'delete':'ic:baseline-delete',
|
'delete': 'ic:baseline-delete',
|
||||||
'remove':'ic:baseline-minus',
|
'remove': 'ic:baseline-minus',
|
||||||
'copy':'ic:baseline-file-copy',
|
'copy': 'ic:baseline-file-copy',
|
||||||
'view':'ic:baseline-remove-red-eye',
|
'view': 'ic:baseline-remove-red-eye',
|
||||||
'publish':'ic:baseline-publish',
|
'publish': 'ic:baseline-publish',
|
||||||
'approval':'ic:baseline-approval',
|
'approval': 'ic:baseline-approval',
|
||||||
'stop':'ic:baseline-stop-circle',
|
'stop': 'ic:baseline-stop-circle',
|
||||||
'online':'ic:baseline-check-circle',
|
'online': 'ic:baseline-check-circle',
|
||||||
'cancel':'ic:baseline-cancel-schedule-send',
|
'cancel': 'ic:baseline-cancel-schedule-send',
|
||||||
'refresh':'ic:baseline-refresh'
|
'refresh': 'ic:baseline-refresh',
|
||||||
|
'logs': 'hugeicons:google-doc'
|
||||||
}
|
}
|
||||||
// 表格操作栏按钮,受权限控制
|
// 表格操作栏按钮,受权限控制
|
||||||
const TableBtnWithPermission = ({btnTitle, access, tooltip, disabled, navigateTo, onClick,className,btnType}:TableBtnWithPermissionProps) => {
|
const TableBtnWithPermission = ({ btnTitle, access, tooltip, disabled, navigateTo, onClick, className, btnType }: TableBtnWithPermissionProps) => {
|
||||||
|
|
||||||
const [btnAccess, setBtnAccess] = useState<boolean>(false)
|
|
||||||
const {accessData,checkPermission,accessInit} = useGlobalContext()
|
|
||||||
const navigate = useNavigate()
|
|
||||||
const lastAccess = useMemo(()=>{
|
|
||||||
if(!accessInit) return false
|
|
||||||
if(!access) return true
|
|
||||||
return checkPermission(access)
|
|
||||||
},[access, accessData,checkPermission,accessInit])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
const [btnAccess, setBtnAccess] = useState<boolean>(false)
|
||||||
access ? setBtnAccess(lastAccess) : setBtnAccess(true)
|
const [btnStatus, setBtnStatus] = useState<boolean>(false)
|
||||||
},[access, lastAccess])
|
const [closeToolTip, setCloseToolTip] = useState<boolean>(false)
|
||||||
|
const { accessData, checkPermission, accessInit } = useGlobalContext()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const lastAccess = useMemo(() => {
|
||||||
|
if (!accessInit) return false
|
||||||
|
if (!access) return true
|
||||||
|
return checkPermission(access)
|
||||||
|
}, [access, accessData, checkPermission, accessInit])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
access ? setBtnAccess(lastAccess) : setBtnAccess(true)
|
||||||
|
}, [access, lastAccess])
|
||||||
|
|
||||||
|
|
||||||
|
const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setTimeout(() => {
|
||||||
|
setBtnStatus(false)
|
||||||
|
setCloseToolTip(true)
|
||||||
|
})
|
||||||
|
|
||||||
const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
navigateTo ? navigate(navigateTo) : onClick?.()
|
||||||
e.stopPropagation()
|
}, [navigateTo, navigate, onClick])
|
||||||
navigateTo ? navigate(navigateTo) : onClick?.()
|
const changeTooltipStatus = (open: boolean) => {
|
||||||
}, [navigateTo, navigate, onClick])
|
setBtnStatus(open)
|
||||||
|
if (closeToolTip) {
|
||||||
return (<>{
|
setBtnStatus(false)
|
||||||
!btnAccess || (disabled&&tooltip) ?
|
setCloseToolTip(false)
|
||||||
<Tooltip placement="top" title={tooltip ?? $t('暂无(0)权限,请联系管理员分配。',[$t(btnTitle).toLowerCase()])}>
|
|
||||||
<Button type="text" disabled={true} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className}`} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18"/>} >{}</Button>
|
|
||||||
</Tooltip>
|
|
||||||
:
|
|
||||||
<Tooltip placement="top" title={$t(btnTitle)}>
|
|
||||||
<Button type="text" disabled={disabled} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className} `} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18"/>} onClick={handleClick}>{}</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
}</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return (<>{
|
||||||
|
!btnAccess || (disabled && tooltip) ?
|
||||||
|
<Tooltip placement="top" title={tooltip ?? $t('暂无(0)权限,请联系管理员分配。', [$t(btnTitle).toLowerCase()])}>
|
||||||
|
<Button type="text" disabled={true} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className}`} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18" />} >{ }</Button>
|
||||||
|
</Tooltip>
|
||||||
|
:
|
||||||
|
<Tooltip placement="top" title={$t(btnTitle)} trigger='hover' open={btnStatus} onOpenChange={changeTooltipStatus}>
|
||||||
|
<Button type="text" disabled={disabled} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className} `} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18" />} onClick={handleClick}>{ }</Button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
}</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default TableBtnWithPermission
|
export default TableBtnWithPermission
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Radio, DatePicker, GetProps, RadioChangeEvent } from 'antd';
|
import { Radio, DatePicker, GetProps, RadioChangeEvent } from 'antd';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||||
@@ -12,69 +12,80 @@ export type RangeValue = [Dayjs | null, Dayjs | null] | null;
|
|||||||
dayjs.extend(customParseFormat);
|
dayjs.extend(customParseFormat);
|
||||||
|
|
||||||
export type TimeRange = {
|
export type TimeRange = {
|
||||||
start:number|null
|
start: number | null
|
||||||
end:number|null
|
end: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TimeRangeButton = ''| 'hour' | 'day' | 'threeDays' | 'sevenDays';
|
export type TimeRangeButton = '' | 'hour' | 'day' | 'threeDays' | 'sevenDays';
|
||||||
|
|
||||||
type TimeRangeSelectorProps = {
|
type TimeRangeSelectorProps = {
|
||||||
initialTimeButton?:TimeRangeButton,
|
initialTimeButton?: TimeRangeButton,
|
||||||
initialDatePickerValue?:RangeValue
|
initialDatePickerValue?: RangeValue
|
||||||
onTimeRangeChange?:(timeRange:TimeRange) =>void
|
onTimeRangeChange?: (timeRange: TimeRange) => void
|
||||||
hideTitle?:boolean
|
hideTitle?: boolean
|
||||||
onTimeButtonChange:(time:TimeRangeButton) =>void
|
onTimeButtonChange: (time: TimeRangeButton) => void
|
||||||
labelSize?:'small'|'default'
|
labelSize?: 'small' | 'default'
|
||||||
}
|
bindRef?: any
|
||||||
const TimeRangeSelector = (props:TimeRangeSelectorProps) => {
|
hideBtns?: TimeRangeButton[]
|
||||||
const {initialTimeButton,initialDatePickerValue,onTimeRangeChange,hideTitle,onTimeButtonChange,labelSize='default'} = props
|
defaultTimeButton?: TimeRangeButton
|
||||||
|
}
|
||||||
|
const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
|
||||||
|
const { initialTimeButton, initialDatePickerValue, onTimeRangeChange, hideTitle, onTimeButtonChange, labelSize = 'default', bindRef, hideBtns = [], defaultTimeButton = 'hour' } = props
|
||||||
const [timeButton, setTimeButton] = useState(initialTimeButton || '');
|
const [timeButton, setTimeButton] = useState(initialTimeButton || '');
|
||||||
const [datePickerValue, setDatePickerValue] = useState<RangeValue>(initialDatePickerValue || [null,null]);
|
const [datePickerValue, setDatePickerValue] = useState<RangeValue>(initialDatePickerValue || [null, null]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (bindRef) {
|
||||||
|
bindRef({ reset });
|
||||||
|
}
|
||||||
|
}, [bindRef])
|
||||||
// 根据选择的时间范围计算开始和结束时间
|
// 根据选择的时间范围计算开始和结束时间
|
||||||
const calculateTimeRange = (curBtn:'hour'|'day'|'threeDays'|'sevenDays') => {
|
const calculateTimeRange = (curBtn: TimeRangeButton) => {
|
||||||
const currentSecond = new Date().getTime() // 当前毫秒数时间戳
|
const currentSecond = Math.floor(Date.now() / 1000); // 当前秒级时间戳
|
||||||
const currentMin = currentSecond - (currentSecond % (60 * 1000)) // 当前分钟数时间戳
|
let startMin = currentSecond - 60 * 60
|
||||||
let startMin = currentMin - 60 * 60 * 1000
|
|
||||||
switch (curBtn) {
|
switch (curBtn) {
|
||||||
case 'hour': {
|
case 'hour': {
|
||||||
startMin = currentMin - 60 * 60 * 1000
|
startMin = currentSecond - 60 * 60
|
||||||
break
|
break
|
||||||
}
|
|
||||||
case 'day': {
|
|
||||||
startMin = currentMin - 24 * 60 * 60 * 1000
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'threeDays': {
|
|
||||||
startMin =
|
|
||||||
new Date(new Date().setHours(0, 0, 0, 0)).getTime() -
|
|
||||||
2 * 24 * 60 * 60 * 1000
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'sevenDays': {
|
|
||||||
startMin =
|
|
||||||
new Date(new Date().setHours(0, 0, 0, 0)).getTime() -
|
|
||||||
6 * 24 * 60 * 60 * 1000
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
case 'day': {
|
||||||
|
startMin = currentSecond - 24 * 60 * 60
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'threeDays': {
|
||||||
|
startMin =
|
||||||
|
Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) -
|
||||||
|
2 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'sevenDays': {
|
||||||
|
startMin =
|
||||||
|
Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) -
|
||||||
|
6 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if (onTimeRangeChange) {
|
if (onTimeRangeChange) {
|
||||||
onTimeRangeChange({ start: startMin / 1000, end: currentMin / 1000 });
|
onTimeRangeChange({ start: startMin, end: currentSecond });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理单选按钮的变化
|
// 处理单选按钮的变化
|
||||||
const handleRadioChange = (e:RadioChangeEvent) => {
|
const handleRadioChange = (e: RadioChangeEvent) => {
|
||||||
setTimeButton(e.target.value);
|
setTimeButton(e.target.value);
|
||||||
onTimeButtonChange?.(e.target.value)
|
onTimeButtonChange?.(e.target.value)
|
||||||
setDatePickerValue(null)
|
setDatePickerValue(null)
|
||||||
calculateTimeRange(e.target.value);
|
calculateTimeRange(e.target.value);
|
||||||
};
|
};
|
||||||
|
const reset = () => {
|
||||||
|
setTimeButton(defaultTimeButton)
|
||||||
|
calculateTimeRange(defaultTimeButton)
|
||||||
|
setDatePickerValue(null)
|
||||||
|
}
|
||||||
|
|
||||||
// 处理日期选择器的变化
|
// 处理日期选择器的变化
|
||||||
const handleDatePickerChange = (dates: RangeValue) => {
|
const handleDatePickerChange = (dates: RangeValue) => {
|
||||||
setTimeButton(dates ? '' : 'hour')
|
setTimeButton(dates ? '' : defaultTimeButton)
|
||||||
onTimeButtonChange?.(dates ? '' : 'hour')
|
onTimeButtonChange?.(dates ? '' : defaultTimeButton)
|
||||||
setDatePickerValue(dates);
|
setDatePickerValue(dates);
|
||||||
if (dates && Array.isArray(dates) && dates.length === 2) {
|
if (dates && Array.isArray(dates) && dates.length === 2) {
|
||||||
const [startDate, endDate] = dates;
|
const [startDate, endDate] = dates;
|
||||||
@@ -84,34 +95,37 @@ const TimeRangeSelector = (props:TimeRangeSelectorProps) => {
|
|||||||
onTimeRangeChange({ start, end });
|
onTimeRangeChange({ start, end });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!dates) {
|
||||||
|
calculateTimeRange(defaultTimeButton)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
||||||
// Can not select days before today and today
|
// Can not select days before today and today
|
||||||
return current && current.valueOf() > dayjs().startOf('day').valueOf();
|
return current && current.valueOf() > dayjs().startOf('day').valueOf();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
|
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
|
||||||
{!hideTitle && <label className={`whitespace-nowrap `}>{$t('时间')}:</label>}
|
{!hideTitle && <label className={`whitespace-nowrap `}>{$t('时间')}:</label>}
|
||||||
<Radio.Group className="whitespace-nowrap" value={timeButton} onChange={handleRadioChange} buttonStyle="solid">
|
<Radio.Group className="whitespace-nowrap" value={timeButton} onChange={handleRadioChange} buttonStyle="solid">
|
||||||
<Radio.Button value="hour">{$t('近1小时')}</Radio.Button>
|
{hideBtns?.length && hideBtns.includes('hour') ? null : <Radio.Button value="hour">{$t('近1小时')}</Radio.Button>}
|
||||||
<Radio.Button value="day">{$t('近24小时')}</Radio.Button>
|
{hideBtns?.length && hideBtns.includes('day') ? null : <Radio.Button value="day">{$t('近24小时')}</Radio.Button>}
|
||||||
<Radio.Button value="threeDays">{$t('近3天')}</Radio.Button>
|
{hideBtns?.length && hideBtns.includes('threeDays') ? null : <Radio.Button value="threeDays">{$t('近3天')}</Radio.Button>}
|
||||||
<Radio.Button className="rounded-e-none" value="sevenDays">{$t('近7天')}</Radio.Button>
|
{hideBtns?.length && hideBtns.includes('sevenDays') ? null : <Radio.Button className="rounded-e-none" value="sevenDays">{$t('近7天')}</Radio.Button>}
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
value={datePickerValue}
|
value={datePickerValue}
|
||||||
className="rounded-s-none ml-[-1px]"
|
className="rounded-s-none ml-[-1px]"
|
||||||
disabledDate={disabledDate}
|
disabledDate={disabledDate}
|
||||||
onChange={handleDatePickerChange}
|
onChange={handleDatePickerChange}
|
||||||
onOpenChange={(open)=>{
|
onOpenChange={(open) => {
|
||||||
if(!open && datePickerValue && datePickerValue.length > 2){
|
if (!open && datePickerValue && datePickerValue.length > 2) {
|
||||||
setTimeButton('')
|
setTimeButton('')
|
||||||
onTimeButtonChange?.('')
|
onTimeButtonChange?.('')
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -137,7 +137,54 @@ export const TranslateWord = ()=>{
|
|||||||
{$t('鉴权数量')}
|
{$t('鉴权数量')}
|
||||||
{$t('列表')}
|
{$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('申请方消费者')}
|
||||||
|
{$t('策略名称')}
|
||||||
|
{$t('优先级')}
|
||||||
|
{$t('筛选条件')}
|
||||||
|
{$t('处理数')}
|
||||||
|
{$t('数据格式')}
|
||||||
|
{$t('关键字')}
|
||||||
|
{$t('正则表达式')}
|
||||||
|
{$t('手机号')}
|
||||||
|
{$t('身份证号')}
|
||||||
|
{$t('银行卡号')}
|
||||||
|
{$t('金额')}
|
||||||
|
{$t('日期')}
|
||||||
|
{$t('局部显示')}
|
||||||
|
{$t('局部遮蔽')}
|
||||||
|
{$t('截取')}
|
||||||
|
{$t('替换')}
|
||||||
|
{$t('乱序')}
|
||||||
|
{$t('随机字符串')}
|
||||||
|
{$t('自定义字符串')}
|
||||||
|
{$t('请输入IP地址或CIDR范围,每条以换行分割')}
|
||||||
|
{$t('待更新')}
|
||||||
|
{$t('待删除')}
|
||||||
|
{$t('内容')}
|
||||||
|
{$t('调用地址')}
|
||||||
|
{$t('消费者 IP')}
|
||||||
|
{$t('鉴权名称')}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ const WithPermission = ({access, tooltip, children,disabled, showDisabled = true
|
|||||||
{ cloneElement(children, {disabled:true})}
|
{ cloneElement(children, {disabled:true})}
|
||||||
</Tooltip>}
|
</Tooltip>}
|
||||||
{!editAccess && (children?.type !== Button && children?.type !== Upload && showDisabled) && <Tooltip title={tooltip ?? $t("暂无操作权限,请联系管理员分配。")}>
|
{!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>}
|
</Tooltip>}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { set } from 'lodash-es';
|
||||||
|
import { ExoticComponent, JSXElementConstructor, ReactElement, useEffect, useState } from 'react';
|
||||||
|
import { useBlocker, useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import { JSX } from 'react/jsx-runtime';
|
||||||
|
|
||||||
|
const withRouteGuard = (WrappedComponent: ExoticComponent<any> | JSXElementConstructor<any>, {
|
||||||
|
canActivate,
|
||||||
|
canLoad ,
|
||||||
|
canDeactivate,
|
||||||
|
deactivated,
|
||||||
|
pathPrefix
|
||||||
|
}: { pathPrefix?:string, canActivate?: () => Promise<boolean>; canLoad?: () => Promise<boolean>; canDeactivate?: () => Promise<boolean>; deactivated?: () => Promise<void>; } = {}) => {
|
||||||
|
return function RouteGuard(props: JSX.IntrinsicAttributes) {
|
||||||
|
const [isActivated, setIsActivated] = useState<boolean>(false);
|
||||||
|
const location = useLocation();
|
||||||
|
// check canActivate
|
||||||
|
const startLifecycle = async ()=>{
|
||||||
|
if(canActivate){
|
||||||
|
const activateRes = await canActivate();
|
||||||
|
setIsActivated(activateRes);
|
||||||
|
}else{
|
||||||
|
setIsActivated(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check canDeactivate
|
||||||
|
const handleBeforeUnload =async (event: { preventDefault: () => void; returnValue: string; }) => {
|
||||||
|
const deactivateRes = canDeactivate? await canDeactivate():true;
|
||||||
|
if (!deactivateRes) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 激活组件时的检查
|
||||||
|
useEffect(() => {
|
||||||
|
startLifecycle();
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
deactivated?.();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
const blocker = useBlocker((tx) => {
|
||||||
|
const currentPath = location.pathname;
|
||||||
|
const targetPath = tx.nextLocation.pathname;
|
||||||
|
|
||||||
|
if (pathPrefix && currentPath.startsWith(pathPrefix) && !targetPath.startsWith(pathPrefix) && canDeactivate) {
|
||||||
|
canDeactivate().then((res) => {
|
||||||
|
if(res){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const checkCanLoad = async()=>{
|
||||||
|
const loadRes = await canLoad!();
|
||||||
|
!loadRes && setIsActivated(false);
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
if (isActivated && canLoad) {
|
||||||
|
checkCanLoad()
|
||||||
|
}
|
||||||
|
}, [isActivated]);
|
||||||
|
|
||||||
|
return isActivated ? <WrappedComponent {...props}/> : null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouteGuard;
|
||||||
@@ -58,7 +58,7 @@ import {
|
|||||||
UPDATE_DATASETS_EVENT_EMITTER,
|
UPDATE_DATASETS_EVENT_EMITTER,
|
||||||
UPDATE_HISTORY_EVENT_EMITTER,
|
UPDATE_HISTORY_EVENT_EMITTER,
|
||||||
} from './constants'
|
} from './constants'
|
||||||
import { useEventEmitterContextContext } from '@common/contexts/event-emitter'
|
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'
|
||||||
|
|
||||||
export type PromptEditorProps = {
|
export type PromptEditorProps = {
|
||||||
instanceId?: string
|
instanceId?: string
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ import { $splitNodeContainingQuery } from '../../utils'
|
|||||||
import { useOptions } from './hooks'
|
import { useOptions } from './hooks'
|
||||||
import type { PickerBlockMenuOption } from './menu'
|
import type { PickerBlockMenuOption } from './menu'
|
||||||
// import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars'
|
// import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars'
|
||||||
import { useEventEmitterContextContext } from '@common/contexts/event-emitter'
|
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'
|
||||||
|
|
||||||
type ComponentPickerProps = {
|
type ComponentPickerProps = {
|
||||||
triggerString: string
|
triggerString: string
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ import { DELETE_CONTEXT_BLOCK_COMMAND } from './index'
|
|||||||
// PortalToFollowElemContent,
|
// PortalToFollowElemContent,
|
||||||
// PortalToFollowElemTrigger,
|
// PortalToFollowElemTrigger,
|
||||||
// } from '@/app/components/base/portal-to-follow-elem'
|
// } from '@/app/components/base/portal-to-follow-elem'
|
||||||
import { useEventEmitterContextContext } from '@common/contexts/event-emitter'
|
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'
|
||||||
import { $t } from '@common/locales'
|
import { $t } from '@common/locales'
|
||||||
|
|
||||||
type ContextBlockComponentProps = {
|
type ContextBlockComponentProps = {
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ import { DELETE_HISTORY_BLOCK_COMMAND } from './index'
|
|||||||
// PortalToFollowElemContent,
|
// PortalToFollowElemContent,
|
||||||
// PortalToFollowElemTrigger,
|
// PortalToFollowElemTrigger,
|
||||||
// } from '@/app/components/base/portal-to-follow-elem'
|
// } from '@/app/components/base/portal-to-follow-elem'
|
||||||
import { useEventEmitterContextContext } from '@common/contexts/event-emitter'
|
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'
|
||||||
import { $t } from '@common/locales'
|
import { $t } from '@common/locales'
|
||||||
|
|
||||||
type HistoryBlockComponentProps = {
|
type HistoryBlockComponentProps = {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
|
|||||||
import { textToEditorState } from '../utils'
|
import { textToEditorState } from '../utils'
|
||||||
import { CustomTextNode } from './custom-text/node'
|
import { CustomTextNode } from './custom-text/node'
|
||||||
import { CLEAR_HIDE_MENU_TIMEOUT } from './workflow-variable-block'
|
import { CLEAR_HIDE_MENU_TIMEOUT } from './workflow-variable-block'
|
||||||
import { useEventEmitterContextContext } from '@common/contexts/event-emitter'
|
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'
|
||||||
|
|
||||||
export const PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER = 'PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER'
|
export const PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER = 'PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER'
|
||||||
export const PROMPT_EDITOR_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY'
|
export const PROMPT_EDITOR_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY'
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export interface CodeboxApiRef {
|
|||||||
formatCode: () => void
|
formatCode: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type codeBoxLanguagesType = 'html' | 'json' | 'xml' | 'javascript' | 'css' | 'plaintext'|'yaml'
|
||||||
interface CodeboxProps {
|
interface CodeboxProps {
|
||||||
options?: MonacoEditor.IStandaloneEditorConstructionOptions
|
options?: MonacoEditor.IStandaloneEditorConstructionOptions
|
||||||
value?: string
|
value?: string
|
||||||
@@ -22,7 +23,7 @@ interface CodeboxProps {
|
|||||||
height?: string | null
|
height?: string | null
|
||||||
readOnly?: boolean
|
readOnly?: boolean
|
||||||
apiRef?: RefObject<CodeboxApiRef>
|
apiRef?: RefObject<CodeboxApiRef>
|
||||||
language?: 'html' | 'json' | 'xml' | 'javascript' | 'css' | 'plaintext'|'yaml'
|
language?: codeBoxLanguagesType
|
||||||
extraContent?:React.ReactNode
|
extraContent?:React.ReactNode
|
||||||
sx?:Record<string,unknown>
|
sx?:Record<string,unknown>
|
||||||
editorTheme?:'vs' | 'vs-dark' | 'hc-black'
|
editorTheme?:'vs' | 'vs-dark' | 'hc-black'
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ export interface IconParkIconElement extends HTMLElement {
|
|||||||
| 'apispace'
|
| 'apispace'
|
||||||
| 'auto-generate-api'
|
| 'auto-generate-api'
|
||||||
| 'compare-api'
|
| 'compare-api'
|
||||||
| 'multi-protocal'
|
| 'multi-protocol'
|
||||||
| 'read-good'
|
| 'read-good'
|
||||||
| 'richdoc'
|
| 'richdoc'
|
||||||
| 'mockapi'
|
| 'mockapi'
|
||||||
|
|||||||
@@ -241,6 +241,26 @@ export const ApprovalRouteColumns = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const ApprovalPolicyColumns = [
|
||||||
|
{
|
||||||
|
title:('名称'),
|
||||||
|
dataIndex:'name',
|
||||||
|
ellipsis:true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:('优先级'),
|
||||||
|
dataIndex:'priority',
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:('状态'),
|
||||||
|
dataIndex:'status',
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
export const ApprovalUpstreamColumns = [
|
export const ApprovalUpstreamColumns = [
|
||||||
{
|
{
|
||||||
title:('上游类型'),
|
title:('上游类型'),
|
||||||
@@ -343,11 +363,6 @@ export const PUBLISH_APPROVAL_RECORD_INNER_TABLE_COLUMN : PageProColumns<Publish
|
|||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
ellipsis:true,
|
ellipsis:true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title:('备注'),
|
|
||||||
dataIndex: 'comments',
|
|
||||||
ellipsis:true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title:('申请人'),
|
title:('申请人'),
|
||||||
dataIndex: ['applicant','name'],
|
dataIndex: ['applicant','name'],
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export type PublishApprovalInfoType = {
|
|||||||
diffs:{
|
diffs:{
|
||||||
apis:PublishApprovalApiItem[]
|
apis:PublishApprovalApiItem[]
|
||||||
upstreams:PublishApprovalUpstreamItem[]
|
upstreams:PublishApprovalUpstreamItem[]
|
||||||
|
strategies:Array<{name:string, priority:number,statues:0|1}>
|
||||||
}
|
}
|
||||||
clusterPublishStatus?:SystemInsidePublishOnlineItems[],
|
clusterPublishStatus?:SystemInsidePublishOnlineItems[],
|
||||||
error:string
|
error:string
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { $t } from '@common/locales'
|
||||||
|
import { StrategyStatusColorClass, StrategyStatusEnum } from './policy/consts'
|
||||||
|
|
||||||
export type BasicResponse<T> = {
|
export type BasicResponse<T> = {
|
||||||
code:number
|
code:number
|
||||||
@@ -5,7 +7,6 @@ export type BasicResponse<T> = {
|
|||||||
msg:string
|
msg:string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const STATUS_CODE = {
|
export const STATUS_CODE = {
|
||||||
SUCCESS:0,
|
SUCCESS:0,
|
||||||
UNANTHORIZED:401,
|
UNANTHORIZED:401,
|
||||||
@@ -18,7 +19,7 @@ export const STATUS_COLOR = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// avoid changing route within ths same category
|
// TODO should be generated dynamically
|
||||||
export const routerKeyMap = new Map<string, string[]|string>([
|
export const routerKeyMap = new Map<string, string[]|string>([
|
||||||
['workspace',['consumer','service','team','guide']],
|
['workspace',['consumer','service','team','guide']],
|
||||||
['my',['consumer','service','team']],
|
['my',['consumer','service','team']],
|
||||||
@@ -29,6 +30,7 @@ export const routerKeyMap = new Map<string, string[]|string>([
|
|||||||
['maintenanceCenter',['aisetting','datasourcing','cluster','cert','logsettings','resourcesettings','openapi']
|
['maintenanceCenter',['aisetting','datasourcing','cluster','cert','logsettings','resourcesettings','openapi']
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const COLUMNS_TITLE = {
|
export const COLUMNS_TITLE = {
|
||||||
operate : ''
|
operate : ''
|
||||||
@@ -45,6 +47,7 @@ export const routerKeyMap = new Map<string, string[]|string>([
|
|||||||
startWithAlphabet:('英文数字下划线任意一种,首字母必须为英文'),
|
startWithAlphabet:('英文数字下划线任意一种,首字母必须为英文'),
|
||||||
specialStartWithAlphabet:('支持字母开头、英文数字中横线下划线组合'),
|
specialStartWithAlphabet:('支持字母开头、英文数字中横线下划线组合'),
|
||||||
onlyAlphabet:('字符非法,仅支持英文'),
|
onlyAlphabet:('字符非法,仅支持英文'),
|
||||||
|
ipAndCidr:'请输入IP地址或CIDR范围,每条以换行分割'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FORM_ERROR_TIPS = {
|
export const FORM_ERROR_TIPS = {
|
||||||
@@ -73,4 +76,33 @@ export const routerKeyMap = new Map<string, string[]|string>([
|
|||||||
export const DATA_SHOW_TYPE_OPTIONS = [
|
export const DATA_SHOW_TYPE_OPTIONS = [
|
||||||
{label:'列表', value:'list'},
|
{label:'列表', value:'list'},
|
||||||
{label:'块', value:'block'},
|
{label:'块', value:'block'},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const PolicyPublishColumns = [
|
||||||
|
|
||||||
|
{
|
||||||
|
title: ('策略名称'),
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: ('优先级'),
|
||||||
|
dataIndex: 'priority',
|
||||||
|
width: 140,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: ('状态'),
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 140,
|
||||||
|
render:(text:string)=> <span className={StrategyStatusColorClass[text as keyof typeof StrategyStatusColorClass]}>{$t(StrategyStatusEnum[text as keyof typeof StrategyStatusEnum])}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: ('更新时间'),
|
||||||
|
dataIndex: 'optTime',
|
||||||
|
width: 182,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -4,84 +4,84 @@
|
|||||||
|
|
||||||
export const PERMISSION_DEFINITION = [
|
export const PERMISSION_DEFINITION = [
|
||||||
{
|
{
|
||||||
"system.organization.member.view": {
|
"system.settings.account.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.view"] }]
|
"anyOf": [{ "backend": ["system.settings.account.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.add": {
|
"system.organization.member.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.edit": {
|
"system.organization.member.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.remove": {
|
"system.organization.member.remove": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.delete": {
|
"system.organization.member.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.block": {
|
"system.organization.member.block": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.department.add": {
|
"system.organization.member.department.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.department.edit": {
|
"system.organization.member.department.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.member.department.delete": {
|
"system.organization.member.department.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.member.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.account.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.team.view": {
|
"system.workspace.team.view_all": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.team.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.view_all"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.team.add": {
|
"system.organization.team.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.create"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.team.edit": {
|
"system.organization.team.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.team.delete": {
|
"system.organization.team.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.team.running": {
|
"system.organization.team.running": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.team.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.role.view": {
|
"system.organization.role.view": {
|
||||||
"granted": {
|
"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": {
|
"system.organization.role.system.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.role.view_system_role"] }]
|
"anyOf": [{ "backend": ["system.settings.role.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.role.system.add": {
|
"system.organization.role.system.add": {
|
||||||
@@ -101,7 +101,7 @@ export const PERMISSION_DEFINITION = [
|
|||||||
},
|
},
|
||||||
"system.organization.role.team.view": {
|
"system.organization.role.team.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.organization.role.view_team_role"] }]
|
"anyOf": [{ "backend": ["system.settings.role.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.organization.role.team.add": {
|
"system.organization.role.team.add": {
|
||||||
@@ -121,22 +121,22 @@ export const PERMISSION_DEFINITION = [
|
|||||||
},
|
},
|
||||||
"system.api_market.service_classification.view": {
|
"system.api_market.service_classification.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.settings.service_classification.view"] }]
|
"anyOf": [{ "backend": ["system.settings.general.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.api_market.service_classification.add": {
|
"system.api_market.service_classification.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.api_market.service_classification.edit": {
|
"system.api_market.service_classification.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.api_market.service_classification.delete": {
|
"system.api_market.service_classification.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.settings.service_classification.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.system_setting.view": {
|
"system.devops.system_setting.view": {
|
||||||
@@ -149,94 +149,119 @@ export const PERMISSION_DEFINITION = [
|
|||||||
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.general.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.dashboard.run_view.view":{
|
"system.analysis.run_view.view":{
|
||||||
"granted": {
|
"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":{
|
"granted":{
|
||||||
"anyOf":[{"backend":['system.devops.data_source.view']}]
|
"anyOf":[{"backend":['system.settings.data_source.view']}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.data_source.edit":{
|
"system.devops.data_source.edit":{
|
||||||
"granted":{
|
"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": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.cluster.view"] }]
|
"anyOf": [{ "backend": ["system.settings.api_gateway.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.cluster.add": {
|
"system.devops.cluster.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.cluster.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.api_gateway.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.cluster.edit": {
|
"system.devops.cluster.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.cluster.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.api_gateway.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.cluster.delete": {
|
"system.devops.cluster.delete": {
|
||||||
"granted": {
|
"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": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.ai_provider.view"] }]
|
"anyOf": [{ "backend": ["system.settings.ai_provider.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.ai_provider.edit": {
|
"system.devops.ai_provider.edit": {
|
||||||
"granted": {
|
"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": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.ssl_certificate.view"] }]
|
"anyOf": [{ "backend": ["system.settings.ssl_certificate.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.ssl_certificate.add": {
|
"system.devops.ssl_certificate.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.ssl_certificate.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.ssl_certificate.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.ssl_certificate.edit": {
|
"system.devops.ssl_certificate.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.ssl_certificate.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.ssl_certificate.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.ssl_certificate.delete": {
|
"system.devops.ssl_certificate.delete": {
|
||||||
"granted": {
|
"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": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.log_configuration.view"] }]
|
"anyOf": [{ "backend": ["system.settings.log_configuration.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.log_configuration.add": {
|
"system.devops.log_configuration.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.log_configuration.edit": {
|
"system.devops.log_configuration.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.log_configuration.publish": {
|
"system.devops.log_configuration.publish": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.devops.log_configuration.delete": {
|
"system.devops.log_configuration.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.devops.log_configuration.manager"] }]
|
"anyOf": [{ "backend": ["system.settings.log_configuration.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system.devops.policy.view": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.settings.strategy.view"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system.devops.policy.add": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.settings.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system.devops.policy.edit": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.settings.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system.devops.policy.publish": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.settings.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system.devops.policy.delete": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.settings.strategy.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.workspace.application.view_all": {
|
"system.workspace.application.view_all": {
|
||||||
@@ -244,19 +269,24 @@ export const PERMISSION_DEFINITION = [
|
|||||||
"anyOf": [{ "backend": ["system.workspace.application.view_all"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.view_all"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"system.workspace.application.edit": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
"system.workspace.service.view_all": {
|
"system.workspace.service.view_all": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.workspace.service.view_all"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.view_all"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.workspace.team.view_all": {
|
"system.workspace.service.edit": {
|
||||||
"granted": {
|
"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": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["system.workspace.api_market.view"] }]
|
"anyOf": [{ "backend": ["system.api_portal.api_portal.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system.dashboard.dashboard.view": {
|
"system.dashboard.dashboard.view": {
|
||||||
@@ -271,237 +301,277 @@ export const PERMISSION_DEFINITION = [
|
|||||||
},
|
},
|
||||||
"team.service.api_doc.view": {
|
"team.service.api_doc.view": {
|
||||||
"granted": {
|
"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": {
|
"team.service.api_doc.add": {
|
||||||
"granted": {
|
"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": {
|
"team.service.api_doc.edit": {
|
||||||
"granted": {
|
"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": {
|
"team.service.api_doc.import": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.api_doc.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api_doc.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.router.view": {
|
"team.service.router.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.router.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.api.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.router.add": {
|
"team.service.router.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.router.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.router.edit": {
|
"team.service.router.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.router.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.router.delete": {
|
"team.service.router.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.router.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.api.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.upstream.view": {
|
"team.service.upstream.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.upstream.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.upstream.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.upstream.add": {
|
"team.service.upstream.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.upstream.edit": {
|
"team.service.upstream.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.upstream.delete": {
|
"team.service.upstream.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.upstream.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.upstream.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.view": {
|
"team.service.release.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.release.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.add": {
|
"team.service.release.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.online": {
|
"team.service.release.online": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.stop": {
|
"team.service.release.stop": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.cancel": {
|
"team.service.release.cancel": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.rollback": {
|
"team.service.release.rollback": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.delete": {
|
"team.service.release.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.release.approval": {
|
"team.service.release.approval": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.release.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.release.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.subscription.view": {
|
"team.service.subscription.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.subscription.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.view_all","team.service.subscription.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.subscription.approval": {
|
"team.service.subscription.approval": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.subscription.add": {
|
"team.service.subscription.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.subscription.delete": {
|
"team.service.subscription.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.service.subscription.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.service.view": {
|
"team.service.service.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": [""] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","system.workspace.service.view_all","team.team.service.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.service.service.add": {
|
"team.service.service.add": {
|
||||||
"granted": {
|
"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": {
|
"team.service.service.edit": {
|
||||||
"granted": {
|
"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": {
|
"team.service.service.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.service.service.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.service.manager_all","team.team.service.manager","team.service.service.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team.service.policy.view": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["team.service.strategy.view"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team.service.policy.add": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["team.service.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team.service.policy.edit": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["team.service.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team.service.policy.publish": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["team.service.strategy.manager"] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team.service.policy.delete": {
|
||||||
|
"granted": {
|
||||||
|
"anyOf": [{ "backend": ["team.service.strategy.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.subscription.view": {
|
"team.application.subscription.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.subscription.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.view_all","team.consumer.subscription.view_subscribed_service"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.subscription.add": {
|
"team.application.subscription.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.subscription.subscribe"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.subscription.edit": {
|
"team.application.subscription.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.subscription.manager_subscribed_services"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.subscription.delete": {
|
"team.application.subscription.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.subscription.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.team.consumer.subscription.manager_subscribed_services"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.application.view": {
|
"team.application.application.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.application.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.view_all","team.team.consumer.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.application.add": {
|
"team.application.application.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.application.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all",'team.team.consumer.manager',"team.consumer.application.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.application.edit": {
|
"team.application.application.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.application.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all",'team.team.consumer.manager',"team.consumer.application.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.application.delete": {
|
"team.application.application.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.application.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all",'team.team.consumer.manager',"team.consumer.application.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.view": {
|
"team.consumer.authorization.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","system.workspace.application.view_all","team.consumer.authorization.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.add": {
|
"team.application.authorization.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.authorization.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.edit": {
|
"team.application.authorization.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.authorization.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.delete": {
|
"team.application.authorization.delete": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.authorization.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.cancelSubApply": {
|
"team.application.authorization.cancelSubApply": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.authorization.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.application.authorization.cancelSub": {
|
"team.application.authorization.cancelSub": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.application.authorization.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.application.manager_all","team.consumer.authorization.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.team.team.view": {
|
"team.team.team.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.team.team.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.view_all","team.team.team.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.team.team.edit": {
|
"team.team.team.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.team.team.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.team.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.team.member.view": {
|
"team.team.member.view": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.team.member.view"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.view_all","team.team.member.view"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.team.member.add": {
|
"team.team.member.add": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.team.member.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.member.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"team.team.member.edit": {
|
"team.team.member.edit": {
|
||||||
"granted": {
|
"granted": {
|
||||||
"anyOf": [{ "backend": ["team.team.member.manager"] }]
|
"anyOf": [{ "backend": ["system.workspace.team.manager","team.team.member.manager"] }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"project.mySystem.topology.view": {
|
"project.mySystem.topology.view": {
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
system:
|
|
||||||
- name: organization
|
|
||||||
cname: '组织管理'
|
|
||||||
value: 'organization'
|
|
||||||
children:
|
|
||||||
- name: member
|
|
||||||
cname: '成员'
|
|
||||||
value: 'member'
|
|
||||||
access:
|
|
||||||
- system.organization.member.view
|
|
||||||
- system.organization.member.add
|
|
||||||
- system.organization.member.edit
|
|
||||||
- system.organization.member.delete
|
|
||||||
- system.organization.member.block
|
|
||||||
- system.organization.member.department.add
|
|
||||||
- system.organization.member.department.edit
|
|
||||||
- system.organization.member.department.delete
|
|
||||||
- name: team_manager
|
|
||||||
cname: '团队管理'
|
|
||||||
desc: '团队管理'
|
|
||||||
- system.organization.team.view
|
|
||||||
- system.organization.team.add
|
|
||||||
- system.organization.team.edit
|
|
||||||
- system.organization.team.delete
|
|
||||||
- system.organization.team.running
|
|
||||||
- name: role_manager
|
|
||||||
cname: '角色管理'
|
|
||||||
desc: '角色管理'
|
|
||||||
- system.organization.role.view
|
|
||||||
- system.organization.role.system.view
|
|
||||||
- system.organization.role.system.add
|
|
||||||
- system.organization.role.system.edit
|
|
||||||
- system.organization.role.system.delete
|
|
||||||
- system.organization.role.team.view
|
|
||||||
- system.organization.role.team.add
|
|
||||||
- system.organization.role.team.edit
|
|
||||||
- system.organization.role.team.delete
|
|
||||||
- name: API Market
|
|
||||||
cname: 'API市场'
|
|
||||||
value: 'api_market'
|
|
||||||
children:
|
|
||||||
- name: service classification
|
|
||||||
cname: '服务分类'
|
|
||||||
value: 'service_classification'
|
|
||||||
children:
|
|
||||||
- system.api_market.service_classification.view
|
|
||||||
- system.api_market.service_classification.add
|
|
||||||
- system.api_market.service_classification.edit
|
|
||||||
- system.api_market.service_classification.delete
|
|
||||||
- name: devops
|
|
||||||
cname: 运维
|
|
||||||
value: 'devops'
|
|
||||||
children:
|
|
||||||
- name: cluster
|
|
||||||
cname: 集群
|
|
||||||
value: 'cluster'
|
|
||||||
children:
|
|
||||||
- system.devops.cluster.view
|
|
||||||
- system.devops.cluster.add
|
|
||||||
- system.devops.cluster.edit
|
|
||||||
- system.devops.cluster.delete
|
|
||||||
- name: ssl certificate
|
|
||||||
cname: 证书
|
|
||||||
value: 'ssl_certificate'
|
|
||||||
children:
|
|
||||||
- system.devops.ssl_certificate.view
|
|
||||||
- system.devops.ssl_certificate.add
|
|
||||||
- system.devops.ssl_certificate.edit
|
|
||||||
- system.devops.ssl_certificate.delete
|
|
||||||
- name: log configuration
|
|
||||||
cname: 日志
|
|
||||||
value: 'log_configuration'
|
|
||||||
children:
|
|
||||||
- system.devops.log_configuration.view
|
|
||||||
- system.devops.log_configuration.add
|
|
||||||
- system.devops.log_configuration.edit
|
|
||||||
- system.devops.log_configuration.publish
|
|
||||||
- system.devops.log_configuration.delete
|
|
||||||
- name: workspace
|
|
||||||
cname: 工作空间
|
|
||||||
value: 'workspace'
|
|
||||||
children:
|
|
||||||
- name: application
|
|
||||||
cname: 应用
|
|
||||||
value: 'application'
|
|
||||||
children:
|
|
||||||
- system.workspace.application.view_all
|
|
||||||
- name: service
|
|
||||||
cname: 服务
|
|
||||||
value: 'service'
|
|
||||||
children:
|
|
||||||
- system.workspace.service.view_all
|
|
||||||
- name: team
|
|
||||||
cname: 团队
|
|
||||||
value: 'team'
|
|
||||||
children:
|
|
||||||
- system.workspace.team.view_all
|
|
||||||
- name: api market
|
|
||||||
cname: API市场
|
|
||||||
value: 'api_market'
|
|
||||||
children:
|
|
||||||
- system.workspace.api_market.view
|
|
||||||
team:
|
|
||||||
- name: service
|
|
||||||
cname: 服务
|
|
||||||
value: 'service'
|
|
||||||
children:
|
|
||||||
- name: api
|
|
||||||
cname: API
|
|
||||||
value: 'api'
|
|
||||||
children:
|
|
||||||
- team.service.api_doc.view
|
|
||||||
- team.service.api_doc.add
|
|
||||||
- team.service.api_doc.edit
|
|
||||||
- name: route
|
|
||||||
cname: route
|
|
||||||
value: 'route'
|
|
||||||
children:
|
|
||||||
- team.service.router.view
|
|
||||||
- team.service.router.add
|
|
||||||
- team.service.router.edit
|
|
||||||
- team.service.router.delete
|
|
||||||
- name: upstream
|
|
||||||
cname: 上游
|
|
||||||
value: 'upstream'
|
|
||||||
children:
|
|
||||||
- team.service.upstream.view
|
|
||||||
- team.service.upstream.add
|
|
||||||
- team.service.upstream.edit
|
|
||||||
- team.service.upstream.delete
|
|
||||||
- name: release
|
|
||||||
cname: 发布
|
|
||||||
value: 'release'
|
|
||||||
children:
|
|
||||||
- team.service.release.view
|
|
||||||
- team.service.release.add
|
|
||||||
- team.service.release.rollback
|
|
||||||
- team.service.release.delete
|
|
||||||
- team.service.release.approval
|
|
||||||
- team.service.release.online
|
|
||||||
- team.service.release.cancel
|
|
||||||
- team.service.release.stop
|
|
||||||
- name: subscription management
|
|
||||||
cname: 订阅方管理
|
|
||||||
value: 'subscription'
|
|
||||||
children:
|
|
||||||
- team.service.subscription.view
|
|
||||||
- team.service.subscription.approval
|
|
||||||
- team.service.subscription.add
|
|
||||||
- team.service.subscription.delete
|
|
||||||
- name: service
|
|
||||||
cname: 服务管理
|
|
||||||
value: 'service'
|
|
||||||
children:
|
|
||||||
- team.service.service.view
|
|
||||||
- team.service.service.add
|
|
||||||
- team.service.service.edit
|
|
||||||
- team.service.service.delete
|
|
||||||
- name: application
|
|
||||||
cname: 应用
|
|
||||||
value: 'application'
|
|
||||||
children:
|
|
||||||
- name: subscription Service
|
|
||||||
cname: 订阅服务
|
|
||||||
value: 'subscription'
|
|
||||||
children:
|
|
||||||
- team.application.subscription.view
|
|
||||||
- team.application.subscription.add
|
|
||||||
- team.application.subscription.edit
|
|
||||||
- team.application.subscription.delete
|
|
||||||
- name: authorization
|
|
||||||
cname: 访问授权
|
|
||||||
value: 'authorization'
|
|
||||||
children:
|
|
||||||
- team.application.authorization.view
|
|
||||||
- team.application.authorization.manager
|
|
||||||
- team.application.authorization.add
|
|
||||||
- team.application.authorization.edit
|
|
||||||
- team.application.authorization.delete
|
|
||||||
- name: application
|
|
||||||
cname: 应用
|
|
||||||
value: 'application'
|
|
||||||
children:
|
|
||||||
- team.application.application.view
|
|
||||||
- team.application.application.add
|
|
||||||
- team.application.application.edit
|
|
||||||
- team.application.application.delete
|
|
||||||
- name: team
|
|
||||||
cname: 团队
|
|
||||||
value: 'team'
|
|
||||||
children:
|
|
||||||
- name: member
|
|
||||||
cname: 成员
|
|
||||||
value: 'member'
|
|
||||||
children:
|
|
||||||
- team.team.member.view
|
|
||||||
- team.team.member.add
|
|
||||||
- team.team.member.edit
|
|
||||||
- name: team
|
|
||||||
cname: 团队管理
|
|
||||||
value: 'team'
|
|
||||||
children:
|
|
||||||
- team.team.team.view
|
|
||||||
- team.team.team.edit
|
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { codeBoxLanguagesType } from "@common/components/postcat/api/Codebox";
|
||||||
|
|
||||||
|
export const MatchRules = [
|
||||||
|
{ value: 'inner', label: '数据格式' },
|
||||||
|
{ value: 'keyword', label: '关键字' },
|
||||||
|
{ value: 'regex', label: '正则表达式' },
|
||||||
|
{ value: 'json_path', label: 'JSON Path' }
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const DataFormatOptions = [
|
||||||
|
{ label: '姓名', value: 'name' },
|
||||||
|
{ label: '手机号', value: 'phone' },
|
||||||
|
{ label: '身份证号', value: 'id-card' },
|
||||||
|
{ label: '银行卡号', value: 'bank-card' },
|
||||||
|
{ label: '日期', value: 'date' },
|
||||||
|
{ label: '金额', value: 'amount' }
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const DataMaskBaseOptionOptions = [
|
||||||
|
{ value: 'partial-display', label: '局部显示' },
|
||||||
|
{ value: 'partial-masking', label: '局部遮蔽' },
|
||||||
|
{ value: 'truncation', label: '截取' },
|
||||||
|
{ value: 'replacement', label: '替换' },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const DataMaskOrderOptions = [
|
||||||
|
...DataMaskBaseOptionOptions,
|
||||||
|
{ label: '乱序', value: 'shuffling' }
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const DataMaskReplaceStrOptions = [
|
||||||
|
{ value: 'random', label: '随机字符串' },
|
||||||
|
{ value: 'custom', label: '自定义字符串' }
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const PolicyOptions = [
|
||||||
|
{label:'数据脱敏',value:'data-masking'},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const StrategyStatusEnum = {
|
||||||
|
'update':'待更新',
|
||||||
|
'online':'已发布',
|
||||||
|
'offline':'未发布',
|
||||||
|
"delete":'待删除',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StrategyStatusColorClass = {
|
||||||
|
"online":'text-status_success',
|
||||||
|
"update":'text-status_pending',
|
||||||
|
"offline":'text-status_fail',
|
||||||
|
"delete":'text-status_offline',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const contentTypeToLanguageMap: Record<string, codeBoxLanguagesType> = {
|
||||||
|
// JSON
|
||||||
|
"application/json": "json",
|
||||||
|
|
||||||
|
// XML
|
||||||
|
"application/xml": "xml",
|
||||||
|
"text/xml": "xml",
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
"text/html": "html",
|
||||||
|
|
||||||
|
// Plain text
|
||||||
|
"text/plain": "plaintext",
|
||||||
|
|
||||||
|
// JavaScript
|
||||||
|
"application/javascript": "javascript",
|
||||||
|
"text/javascript": "javascript",
|
||||||
|
|
||||||
|
// CSS
|
||||||
|
"text/css": "css",
|
||||||
|
|
||||||
|
// YAML
|
||||||
|
"application/x-yaml": "yaml",
|
||||||
|
"text/yaml": "yaml",
|
||||||
|
|
||||||
|
// Others (fallback)
|
||||||
|
"*/*": "plaintext", // 任意类型默认处理为普通文本
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
import { DefaultOptionType } from "antd/es/select";
|
||||||
|
import { StrategyStatusEnum } from "./consts";
|
||||||
|
import { EntityItem } from "../type";
|
||||||
|
|
||||||
|
export type DataMaskRuleTableProps = {
|
||||||
|
disabled?: boolean;
|
||||||
|
value?: MaskRuleData[];
|
||||||
|
onChange?: (value: MaskRuleData[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type MaskRuleData = {
|
||||||
|
match: {
|
||||||
|
type: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
mask: {
|
||||||
|
type: string;
|
||||||
|
begin?: number;
|
||||||
|
length?: number;
|
||||||
|
replace?: {
|
||||||
|
type: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
eoKey?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataMaskRuleFormProps = {
|
||||||
|
editData?: MaskRuleData;
|
||||||
|
ruleList: MaskRuleData[];
|
||||||
|
onSave: (ruleList: MaskRuleData[]) => void;
|
||||||
|
onClose: () => void;
|
||||||
|
modalVisible:boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type DataMaskingConfigHandle = {
|
||||||
|
save: (values: any) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PolicyMatchType = {name:string, values:string[], label?:string, title?:string, type?:string}
|
||||||
|
|
||||||
|
export type DataMaskingRulesType = {}
|
||||||
|
|
||||||
|
export type DataMaskingConfigFieldType = {
|
||||||
|
id:string
|
||||||
|
name:string
|
||||||
|
priority:number
|
||||||
|
description:string
|
||||||
|
filters:PolicyMatchType[]
|
||||||
|
config:{
|
||||||
|
rules:DataMaskingRulesType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataMaskStrategyItem = {
|
||||||
|
id:string
|
||||||
|
name:string
|
||||||
|
priority:number
|
||||||
|
isStop:boolean
|
||||||
|
isDelete:boolean
|
||||||
|
publishStatus:keyof typeof StrategyStatusEnum
|
||||||
|
filters:string
|
||||||
|
conf:string
|
||||||
|
updater:EntityItem
|
||||||
|
updateTime:string
|
||||||
|
}
|
||||||
|
export type DataMaskLogItem = {
|
||||||
|
id:string
|
||||||
|
service: {
|
||||||
|
id:string
|
||||||
|
name:string
|
||||||
|
}
|
||||||
|
method:string
|
||||||
|
url:string
|
||||||
|
remote_ip:string
|
||||||
|
consumer: {
|
||||||
|
id:string
|
||||||
|
name:string
|
||||||
|
}
|
||||||
|
authorization:string
|
||||||
|
record_time:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type FilterFormField= {
|
||||||
|
name: string;
|
||||||
|
values:string[] |string;
|
||||||
|
label:string
|
||||||
|
title:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterOptionType = {
|
||||||
|
name:string
|
||||||
|
pattern:string
|
||||||
|
title:string
|
||||||
|
type:'remote'|'pattern'|'static'
|
||||||
|
options:string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type FilterTableProps = {
|
||||||
|
disabled?: boolean;
|
||||||
|
drawerTitle?: string;
|
||||||
|
value?:FilterFormField[];
|
||||||
|
onChange?:(val:FilterFormField[])=>void
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterFormType = {
|
||||||
|
name:string
|
||||||
|
values:unknown
|
||||||
|
type?:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterFormProps = {
|
||||||
|
filterForm: FilterFormType;
|
||||||
|
filterOptions:DefaultOptionType[];
|
||||||
|
selectedOptionNameSet: Set<string>;
|
||||||
|
disabled: boolean;
|
||||||
|
onFilterFormChange: (form: FilterFormType) => void;
|
||||||
|
setFormCanSubmit:(canSubmit:boolean)=>void
|
||||||
|
serviceId?:string
|
||||||
|
teamId?:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterFormHandle = {
|
||||||
|
clear:()=>void
|
||||||
|
save:()=>Promise<FilterFormField>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FilterFormItemProps = {
|
||||||
|
value?: string[];
|
||||||
|
onChange?: (value: string[]) => void;
|
||||||
|
disabled:boolean
|
||||||
|
option:unknown
|
||||||
|
onShowValueChange?:(value:string)=>void
|
||||||
|
serviceId?:string
|
||||||
|
teamId?:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RemoteTitleType = {
|
||||||
|
title:string
|
||||||
|
field:string
|
||||||
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import { FC, ReactElement, ReactNode } from "react"
|
||||||
import { PERMISSION_DEFINITION } from "./permissions"
|
import { PERMISSION_DEFINITION } from "./permissions"
|
||||||
import { MatchPositionEnum, MatchTypeEnum } from "@core/const/system/const"
|
import { MatchPositionEnum, MatchTypeEnum } from "@core/const/system/const"
|
||||||
|
import usePluginLoader from "@common/hooks/pluginLoader"
|
||||||
|
import { useGlobalContext } from "@common/contexts/GlobalStateContext"
|
||||||
|
import { StrategyStatusEnum } from "./policy/consts"
|
||||||
|
|
||||||
export type UserInfoType = {
|
export type UserInfoType = {
|
||||||
username: string
|
username: string
|
||||||
@@ -7,6 +11,7 @@ export type UserInfoType = {
|
|||||||
email: string
|
email: string
|
||||||
phone: string
|
phone: string
|
||||||
avatar: string
|
avatar: string
|
||||||
|
type:string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserProfileProps = {
|
export type UserProfileProps = {
|
||||||
@@ -98,4 +103,112 @@ export type SimpleMemberItem = {
|
|||||||
email:string
|
email:string
|
||||||
department:string
|
department:string
|
||||||
avatar:string
|
avatar:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type RouteConfig = {
|
||||||
|
path:string
|
||||||
|
pathPrefix?:string
|
||||||
|
component?:ReactElement
|
||||||
|
children?:(RouteConfig|false)[]
|
||||||
|
key:string
|
||||||
|
provider?:FC<{ children: ReactNode; }>
|
||||||
|
lazy?:unknown
|
||||||
|
data?:Record<string, string>
|
||||||
|
lifecycle?:{
|
||||||
|
canActivate?:()=>Promise<boolean>
|
||||||
|
canLoad?:()=>Promise<boolean>
|
||||||
|
canDeactivate?:()=>Promise<boolean>
|
||||||
|
deactivated?:()=>Promise<boolean>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RouterParams = {
|
||||||
|
teamId:string
|
||||||
|
apiId:string
|
||||||
|
serviceId:string
|
||||||
|
clusterId:string;
|
||||||
|
memberGroupId:string
|
||||||
|
userGroupId:string
|
||||||
|
pluginName:string
|
||||||
|
moduleId:string
|
||||||
|
accessType:'project'|'team'|'service'
|
||||||
|
categoryId:string
|
||||||
|
tagId:string
|
||||||
|
dashboardType:string
|
||||||
|
dashboardDetailId:string
|
||||||
|
topologyId:string
|
||||||
|
appId:string
|
||||||
|
roleType:string
|
||||||
|
roleId:string
|
||||||
|
routeId:string
|
||||||
|
policyId:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type PluginRouterConfig = {
|
||||||
|
name:string
|
||||||
|
path:string;
|
||||||
|
type:string;
|
||||||
|
expose?:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CoreObj = {
|
||||||
|
routerConfig: RouteConfig[];
|
||||||
|
setExecuteList: (param:unknown[])=>void;
|
||||||
|
pluginLoader: {
|
||||||
|
loadModule: (path: string, name: string, expose: string, pluginPath: string) => Promise<any>;
|
||||||
|
};
|
||||||
|
pluginProvider: ReturnType<typeof useGlobalContext>
|
||||||
|
// pluginLifecycleGuard: PluginLifecycleGuard;
|
||||||
|
builtInPluginLoader: (name: string) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PluginConfigType = {
|
||||||
|
name: string;
|
||||||
|
router: Array<PluginRouterConfig>;
|
||||||
|
path?: string;
|
||||||
|
driver:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type ApiparkPluginDriverType = {
|
||||||
|
[key:string]:{[key:string]:(coreObj?:CoreObj, pluginConfig?:PluginConfigType)=>(CoreObj|undefined)}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type RouterMapConfig = {
|
||||||
|
type: 'component' | 'module',
|
||||||
|
component: ReactElement,
|
||||||
|
provider?: FC,
|
||||||
|
lazy?: FC
|
||||||
|
key?: string
|
||||||
|
children?: RouteConfig[]
|
||||||
|
data?:Record<string, string>
|
||||||
|
pathMatch?:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type PolichPublishItemType = {
|
||||||
|
name:string
|
||||||
|
priority:number
|
||||||
|
status:keyof typeof StrategyStatusEnum
|
||||||
|
optTime:string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发布详情(版本)
|
||||||
|
export type PolicyPublishInfoType = {
|
||||||
|
source:string
|
||||||
|
strategies:Array<PolichPublishItemType>
|
||||||
|
isPublish:boolean
|
||||||
|
versionName:string
|
||||||
|
unpublishMsg:string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PolicyPublishModalProps = {
|
||||||
|
data:PolicyPublishInfoType
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PolicyPublishModalHandle = {
|
||||||
|
publish:()=>Promise<boolean|string|Record<string, unknown>>
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
import {createContext, Dispatch, FC, ReactNode, useContext, useReducer, useState} from "react";
|
import {createContext, Dispatch, FC, ReactNode, useContext, useEffect, useReducer, useState} from "react";
|
||||||
import { useFetch } from "@common/hooks/http";
|
import { useFetch } from "@common/hooks/http";
|
||||||
import { App } from "antd";
|
import { App } from "antd";
|
||||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||||
import { checkAccess } from "@common/utils/permission";
|
import { checkAccess } from "@common/utils/permission";
|
||||||
import { PERMISSION_DEFINITION } from "@common/const/permissions";
|
import { PERMISSION_DEFINITION } from "@common/const/permissions";
|
||||||
import { $t } from "@common/locales";
|
import { $t } from "@common/locales";
|
||||||
|
import { MenuItem } from "@common/utils/navigation";
|
||||||
|
import { ErrorBoundary } from "@ant-design/pro-components";
|
||||||
|
import NotFound from "@common/components/aoplatform/NotFound";
|
||||||
|
import { RouteConfig } from "@common/const/type";
|
||||||
|
import { ProtectedRoute } from "@core/components/aoplatform/RenderRoutes";
|
||||||
|
import Login from "@core/pages/Login";
|
||||||
|
import { useLocaleContext } from "./LocaleContext";
|
||||||
|
import Root from "@core/pages/Root"
|
||||||
|
import DataMaskingCompare from "@core/pages/policy/dataMasking/DataMaskingCompare";
|
||||||
interface GlobalState {
|
interface GlobalState {
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
userData: UserData | null;
|
userData: UserData | null;
|
||||||
@@ -14,6 +22,7 @@ interface GlobalState {
|
|||||||
powered:string;
|
powered:string;
|
||||||
mainPage:string;
|
mainPage:string;
|
||||||
language:string;
|
language:string;
|
||||||
|
pluginsLoaded:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserData {
|
interface UserData {
|
||||||
@@ -29,8 +38,171 @@ export type GlobalAction =
|
|||||||
| { type: 'UPDATE_POWER'; powered: string }
|
| { type: 'UPDATE_POWER'; powered: string }
|
||||||
| { type: 'UPDATE_MAIN_PAGE'; mainPage: string }
|
| { type: 'UPDATE_MAIN_PAGE'; mainPage: string }
|
||||||
| { type: 'UPDATE_LANGUAGE'; language: string }
|
| { type: 'UPDATE_LANGUAGE'; language: string }
|
||||||
|
| { type: 'SET_PLUGINS_LOADED'; pluginsLoaded: boolean }
|
||||||
|
|
||||||
|
|
||||||
|
const mockData = [
|
||||||
|
{
|
||||||
|
"name": "工作空间",
|
||||||
|
"key": "workspace",
|
||||||
|
"path": "/guide",
|
||||||
|
"icon": "ic:baseline-space-dashboard",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "首页",
|
||||||
|
"key": "guide",
|
||||||
|
"path": "/guide",
|
||||||
|
"icon": "ic:baseline-home",
|
||||||
|
"access": "all"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "服务",
|
||||||
|
"key": "service",
|
||||||
|
"path": "/service",
|
||||||
|
"icon": "ic:baseline-blinds-closed",
|
||||||
|
"access": "all"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "消费者",
|
||||||
|
"key": "consumer",
|
||||||
|
"path": "/consumer",
|
||||||
|
"icon": "ic:baseline-apps",
|
||||||
|
"access": "all"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "团队",
|
||||||
|
"key": "team",
|
||||||
|
"path": "/team",
|
||||||
|
"icon": "ic:baseline-people-alt",
|
||||||
|
"access": "all"
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// "name": "路由组件",
|
||||||
|
// "key": "router",
|
||||||
|
// "path": "/router1",
|
||||||
|
// "icon": "ic:baseline-people-alt",
|
||||||
|
// "access": "all"
|
||||||
|
// }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "API 市场",
|
||||||
|
"key": "serviceHub",
|
||||||
|
"path": "/serviceHub",
|
||||||
|
"icon": "ic:baseline-hub",
|
||||||
|
"access": "system.api_portal.api_portal.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "仪表盘",
|
||||||
|
"key": "analytics",
|
||||||
|
"path": "/analytics",
|
||||||
|
"icon": "ic:baseline-bar-chart",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "运行视图",
|
||||||
|
"key": "analytics",
|
||||||
|
"path": "/analytics",
|
||||||
|
"icon": "ic:baseline-bar-chart",
|
||||||
|
"access": "system.analysis.run_view.view"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"access": "system.analysis.run_view.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "系统设置",
|
||||||
|
"key": "operationCenter",
|
||||||
|
"path": "/commonsetting",
|
||||||
|
"icon": "ic:baseline-settings",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "系统",
|
||||||
|
"key": "serviceHubSetting",
|
||||||
|
"path": "/commonsetting",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "常规",
|
||||||
|
"key": "commonsetting",
|
||||||
|
"path": "/commonsetting",
|
||||||
|
"icon": "ic:baseline-hub",
|
||||||
|
"access": "system.api_market.service_classification.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "API 网关",
|
||||||
|
"key": "cluster",
|
||||||
|
"path": "/cluster",
|
||||||
|
"icon": "ic:baseline-device-hub",
|
||||||
|
"access": "system.settings.api_gateway.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AI 模型",
|
||||||
|
"key": "aisetting",
|
||||||
|
"path": "/aisetting",
|
||||||
|
"icon": "hugeicons:ai-network",
|
||||||
|
"access": "system.settings.ai_provider.view"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "用户",
|
||||||
|
"key": "organization",
|
||||||
|
"path": "/member",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "账号",
|
||||||
|
"key": "member",
|
||||||
|
"path": "/member",
|
||||||
|
"icon": "ic:baseline-people-alt",
|
||||||
|
"access": "system.settings.account.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "角色",
|
||||||
|
"key": "role",
|
||||||
|
"path": "/role",
|
||||||
|
"icon": "ic:baseline-verified-user",
|
||||||
|
"access": "system.organization.role.view"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "集成",
|
||||||
|
"key": "maintenanceCenter",
|
||||||
|
"path": "/datasourcing",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "数据源",
|
||||||
|
"key": "datasourcing",
|
||||||
|
"path": "/datasourcing",
|
||||||
|
"icon": "ic:baseline-monitor-heart",
|
||||||
|
"access": "system.settings.data_source.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "全局策略",
|
||||||
|
"key": "globalpolicy",
|
||||||
|
"path": "/globalpolicy",
|
||||||
|
"icon": "icon-park-solid:exchange-three",
|
||||||
|
"access": "system.settings.data_source.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "证书",
|
||||||
|
"key": "cert",
|
||||||
|
"path": "/cert",
|
||||||
|
"icon": "ic:baseline-security",
|
||||||
|
"access": "system.settings.ssl_certificate.view"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "日志",
|
||||||
|
"key": "logsettings",
|
||||||
|
"path": "/logsettings",
|
||||||
|
"icon": "ic:baseline-sticky-note-2",
|
||||||
|
"access": "system.settings.log_configuration.view"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
存储用户登录、信息、权限等数据
|
存储用户登录、信息、权限等数据
|
||||||
*/
|
*/
|
||||||
@@ -39,9 +211,11 @@ export const GlobalContext = createContext<{
|
|||||||
dispatch: Dispatch<GlobalAction>;
|
dispatch: Dispatch<GlobalAction>;
|
||||||
accessData:Map<string,string[]>;
|
accessData:Map<string,string[]>;
|
||||||
pluginAccessDictionary:{[k:string]:string};
|
pluginAccessDictionary:{[k:string]:string};
|
||||||
|
menuList:MenuItem[];
|
||||||
getGlobalAccessData:()=>Promise<{ access:string[]}>;
|
getGlobalAccessData:()=>Promise<{ access:string[]}>;
|
||||||
getTeamAccessData:(teamId:string)=>void;
|
getTeamAccessData:(teamId:string)=>void;
|
||||||
getPluginAccessDictionary:(pluginData:{[k:string]:string})=>void
|
getPluginAccessDictionary:(pluginData:{[k:string]:string})=>void
|
||||||
|
getMenuList:()=>void
|
||||||
resetAccess:()=>void
|
resetAccess:()=>void
|
||||||
cleanTeamAccessData:()=>void
|
cleanTeamAccessData:()=>void
|
||||||
checkPermission:(access:keyof typeof PERMISSION_DEFINITION[0] | Array<keyof typeof PERMISSION_DEFINITION[0]>)=>boolean
|
checkPermission:(access:keyof typeof PERMISSION_DEFINITION[0] | Array<keyof typeof PERMISSION_DEFINITION[0]>)=>boolean
|
||||||
@@ -49,6 +223,11 @@ export const GlobalContext = createContext<{
|
|||||||
accessInit:boolean
|
accessInit:boolean
|
||||||
aiConfigFlushed:boolean
|
aiConfigFlushed:boolean
|
||||||
setAiConfigFlushed:(flush:boolean)=>void
|
setAiConfigFlushed:(flush:boolean)=>void
|
||||||
|
routeConfig: RouteConfig[];
|
||||||
|
setRouterConfig: (isRoot: boolean, config: RouteConfig) => void;
|
||||||
|
addRouteConfig: (parentRoute: RouteConfig, config: RouteConfig) => void;
|
||||||
|
fetchData: ReturnType<typeof useFetch>['fetchData'];
|
||||||
|
$t: typeof $t;
|
||||||
} | undefined>(undefined);
|
} | undefined>(undefined);
|
||||||
|
|
||||||
const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState => {
|
const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState => {
|
||||||
@@ -94,23 +273,38 @@ const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState =>
|
|||||||
...state,
|
...state,
|
||||||
language: action.language,
|
language: action.language,
|
||||||
};
|
};
|
||||||
|
case 'SET_PLUGINS_LOADED':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pluginsLoaded: action.pluginsLoaded,
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const DefaultRouteConfig = [
|
||||||
|
{ path: '/', pathMatch: 'full', component: <Root /> ,key:'root',},
|
||||||
|
{ path: '/login', component: <Login /> ,key:'login'},
|
||||||
|
{ path: '/dataMaskCompare/:logId/:serviceId?/:teamId?', component: <DataMaskingCompare /> ,key:'dataMaskCompare'},
|
||||||
|
{ path: '/', pathMatch:'prefix',component:<ProtectedRoute /> ,key:'basciLayout',children:[
|
||||||
|
{ path: '*', component: <ErrorBoundary><NotFound/></ErrorBoundary>, key: 'errorBoundary' }
|
||||||
|
]}
|
||||||
|
]
|
||||||
// Create a context provider component
|
// Create a context provider component
|
||||||
export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
||||||
const {fetchData} = useFetch()
|
|
||||||
const { message } = App.useApp()
|
const { message } = App.useApp()
|
||||||
|
const { setLocale } = useLocaleContext();
|
||||||
const [state, dispatch] = useReducer(globalReducer, {
|
const [state, dispatch] = useReducer(globalReducer, {
|
||||||
isAuthenticated: true, //mock用
|
isAuthenticated: false, //mock用
|
||||||
userData: null,
|
userData: null,
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
updateDate: '2024-07-01',
|
updateDate: '2024-07-01',
|
||||||
powered:'Powered by https://apipark.com',
|
powered:'Powered by https://apipark.com',
|
||||||
mainPage:'/guide/page',
|
mainPage:'/guide/page',
|
||||||
language:'en-US'
|
language:'en-US',
|
||||||
|
pluginsLoaded:false
|
||||||
});
|
});
|
||||||
const [accessData,setAccessData] = useState<Map<string,string[]>>(new Map())
|
const [accessData,setAccessData] = useState<Map<string,string[]>>(new Map())
|
||||||
const [pluginAccessDictionary, setPluginAccessDictionary] = useState<{[k:string]:string}>({})
|
const [pluginAccessDictionary, setPluginAccessDictionary] = useState<{[k:string]:string}>({})
|
||||||
@@ -118,6 +312,43 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
|||||||
const [accessInit, setAccessInit] = useState<boolean>(false)
|
const [accessInit, setAccessInit] = useState<boolean>(false)
|
||||||
const [aiConfigFlushed, setAiConfigFlushed] = useState<boolean>(false)
|
const [aiConfigFlushed, setAiConfigFlushed] = useState<boolean>(false)
|
||||||
let getGlobalAccessPromise: Promise<BasicResponse<{ access:string[] }>> | null = null
|
let getGlobalAccessPromise: Promise<BasicResponse<{ access:string[] }>> | null = null
|
||||||
|
const [menuList, setMenuList] = useState<MenuItem[]>(mockData);
|
||||||
|
const [routeConfig, setRouteConfigState] = useState<RouteConfig[]>(DefaultRouteConfig)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLocale(state.language);
|
||||||
|
}, [state.language, setLocale]);
|
||||||
|
|
||||||
|
const { fetchData } = useFetch();
|
||||||
|
|
||||||
|
const setRouterConfig = (isRoot: boolean, config: RouteConfig) => {
|
||||||
|
setRouteConfigState(prevConfig => {
|
||||||
|
if (isRoot) {
|
||||||
|
return [config,...prevConfig];
|
||||||
|
} else {
|
||||||
|
const rootRoute = prevConfig.find(route => route.path === '/' && route?.pathMatch === 'prefix') ;
|
||||||
|
if (rootRoute ) {
|
||||||
|
rootRoute.children = rootRoute.children ? [config, ...rootRoute.children] : [config];
|
||||||
|
}
|
||||||
|
return [...prevConfig];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRouteConfig = (parentRoute: RouteConfig, config: RouteConfig) => {
|
||||||
|
const addConfigToParent = (routes: RouteConfig[]): RouteConfig[] => {
|
||||||
|
return routes.map(route => {
|
||||||
|
if (route.key === parentRoute.key) {
|
||||||
|
route.children = route.children ? [...route.children, config] : [config];
|
||||||
|
} else if (route.children) {
|
||||||
|
route.children = addConfigToParent(route.children);
|
||||||
|
}
|
||||||
|
return route;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
setRouteConfigState(prevConfig => addConfigToParent(prevConfig));
|
||||||
|
};
|
||||||
|
|
||||||
const getGlobalAccessData = ()=>{
|
const getGlobalAccessData = ()=>{
|
||||||
if(getGlobalAccessPromise){
|
if(getGlobalAccessPromise){
|
||||||
@@ -151,6 +382,18 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getMenuList = ()=>{
|
||||||
|
// TODO 等待对接后端接口
|
||||||
|
// fetchData<BasicResponse<{ access:string[]}>>('profile/permission/team',{method:'GET',eoParams:{team:teamId}},).then(response=>{
|
||||||
|
// const {code,data,msg} = response
|
||||||
|
// if(code === STATUS_CODE.SUCCESS){
|
||||||
|
// setMenuList(data.menus)
|
||||||
|
// }else{
|
||||||
|
// message.error(msg || $t(RESPONSE_TIPS.error))
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
const cleanTeamAccessData = ()=>{
|
const cleanTeamAccessData = ()=>{
|
||||||
setTeamDataFlushed(false)
|
setTeamDataFlushed(false)
|
||||||
setAccessData(prevData => prevData.set('team',[]))
|
setAccessData(prevData => prevData.set('team',[]))
|
||||||
@@ -176,15 +419,26 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
|||||||
return revs
|
return revs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GlobalContext.Provider value={
|
<GlobalContext.Provider value={
|
||||||
{ state, dispatch,accessData,pluginAccessDictionary,
|
{ state, dispatch,
|
||||||
|
accessData,
|
||||||
|
pluginAccessDictionary,
|
||||||
getGlobalAccessData,
|
getGlobalAccessData,
|
||||||
getPluginAccessDictionary,
|
getPluginAccessDictionary,
|
||||||
getTeamAccessData,teamDataFlushed,
|
getTeamAccessData,teamDataFlushed,getMenuList,menuList,
|
||||||
cleanTeamAccessData,
|
cleanTeamAccessData,
|
||||||
resetAccess ,checkPermission,accessInit,
|
resetAccess ,checkPermission,
|
||||||
aiConfigFlushed, setAiConfigFlushed}}>
|
accessInit,
|
||||||
|
aiConfigFlushed,
|
||||||
|
setAiConfigFlushed,
|
||||||
|
routeConfig,
|
||||||
|
setRouterConfig,
|
||||||
|
addRouteConfig,
|
||||||
|
fetchData,
|
||||||
|
$t:$t,}}>
|
||||||
{children}
|
{children}
|
||||||
</GlobalContext.Provider>
|
</GlobalContext.Provider>
|
||||||
);
|
);
|
||||||
@@ -194,7 +448,40 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => {
|
|||||||
export const useGlobalContext = () => {
|
export const useGlobalContext = () => {
|
||||||
const context = useContext(GlobalContext);
|
const context = useContext(GlobalContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error('useGlobalContext must be used within a GlobalProvider');
|
|
||||||
|
console.warn('useGlobalContext must be used within a GlobalProvider. Returning default context.');
|
||||||
|
return {
|
||||||
|
state: {
|
||||||
|
isAuthenticated: false,
|
||||||
|
userData: null,
|
||||||
|
version: '1.0.0',
|
||||||
|
updateDate: '',
|
||||||
|
powered: '',
|
||||||
|
mainPage: '',
|
||||||
|
language: 'en-US',
|
||||||
|
pluginsLoaded: false,
|
||||||
|
},
|
||||||
|
dispatch: () => {},
|
||||||
|
accessData: new Map(),
|
||||||
|
pluginAccessDictionary: {},
|
||||||
|
menuList: [],
|
||||||
|
getGlobalAccessData: async () => ({ access: [] }),
|
||||||
|
getTeamAccessData: () => {},
|
||||||
|
getPluginAccessDictionary: () => {},
|
||||||
|
getMenuList: () => {},
|
||||||
|
resetAccess: () => {},
|
||||||
|
cleanTeamAccessData: () => {},
|
||||||
|
checkPermission: () => false,
|
||||||
|
teamDataFlushed: false,
|
||||||
|
accessInit: false,
|
||||||
|
aiConfigFlushed: false,
|
||||||
|
setAiConfigFlushed: () => {},
|
||||||
|
routeConfig: [],
|
||||||
|
setRouterConfig: () => {},
|
||||||
|
addRouteConfig: () => {},
|
||||||
|
fetchData: async () => ({}),
|
||||||
|
$t: (key: string) => key,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import React, { createContext, useContext, useState, useEffect, useMemo, FC, ReactNode } from 'react';
|
||||||
|
import { ConfigProviderProps } from 'antd';
|
||||||
|
import zhCN from 'antd/locale/zh_CN';
|
||||||
|
import enUS from 'antd/locale/en_US';
|
||||||
|
import zhTW from 'antd/locale/zh_TW';
|
||||||
|
import jaJP from 'antd/locale/ja_JP';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import 'dayjs/locale/zh-cn';
|
||||||
|
import 'dayjs/locale/zh-tw';
|
||||||
|
import 'dayjs/locale/ja';
|
||||||
|
|
||||||
|
type Locale = ConfigProviderProps['locale'];
|
||||||
|
|
||||||
|
const languageMap: Record<string, Locale> = {
|
||||||
|
'zh-CN': zhCN,
|
||||||
|
'en-US': enUS,
|
||||||
|
'zh-TW': zhTW,
|
||||||
|
'ja-JP': jaJP,
|
||||||
|
};
|
||||||
|
|
||||||
|
const LocaleContext = createContext<{
|
||||||
|
locale: Locale;
|
||||||
|
setLocale: (locale: string) => void;
|
||||||
|
}|undefined>(undefined);
|
||||||
|
|
||||||
|
export const LocaleProvider: FC<{children:ReactNode}> = ({ children }) => {
|
||||||
|
const [locale, setLocaleState] = useState<Locale>(zhCN);
|
||||||
|
|
||||||
|
const setLocale = (language: string) => {
|
||||||
|
dayjs.locale(language);
|
||||||
|
setLocaleState(languageMap[language]);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LocaleContext.Provider value={{ locale, setLocale }}>
|
||||||
|
{children}
|
||||||
|
</LocaleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useLocaleContext = () => {
|
||||||
|
const context = useContext(LocaleContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useLocaleContext must be used within a LocaleContext');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { createContext, FC, ReactNode, useContext, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
class EventEmitter {
|
||||||
|
// 用来存放注册的事件与回调
|
||||||
|
_events:any
|
||||||
|
constructor () {
|
||||||
|
this._events = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
on (eventName:string, callback:Function) {
|
||||||
|
// 由于一个事件可能注册多个回调函数,所以使用数组来存储事件队列
|
||||||
|
const callbacks = this._events[eventName] || []
|
||||||
|
callbacks.push(callback)
|
||||||
|
this._events[eventName] = callbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
// 此处需要处理,emit时需要按顺序执行监听的函数,每个函数都会返回是否中止的参数,如果中止则不执行后续的函数
|
||||||
|
// emit传入eventName 和 event, 返回 event
|
||||||
|
emit (eventName:string, event:any) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const callbacks = this._events[eventName] || []
|
||||||
|
for (const cb of callbacks) {
|
||||||
|
const cbRes = cb(event.data)
|
||||||
|
if (cbRes.continue === false) {
|
||||||
|
resolve(cbRes)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
event = cbRes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(event.data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消订阅
|
||||||
|
off (eventName:string, callback:Function) {
|
||||||
|
const callbacks = this._events[eventName] || []
|
||||||
|
const newCallbacks = callbacks.filter((fn:any) => fn !== callback && fn.initialCallback !== callback /* 用于once的取消订阅 */)
|
||||||
|
this._events[eventName] = newCallbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单次订阅,后台插件可以自行决定取消对事件的订阅
|
||||||
|
once (eventName:string, callback:Function) {
|
||||||
|
// 由于需要在回调函数执行后,取消订阅当前事件,所以需要对传入的回调函数做一层包装,然后绑定包装后的函数
|
||||||
|
const one = (...args:any) => {
|
||||||
|
callback(...args)
|
||||||
|
this.off(eventName, one)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 由于:我们订阅事件的时候,修改了原回调函数的引用,所以,用户触发 off 的时候不能找到对应的回调函数
|
||||||
|
// 所以,我们需要在当前函数与用户传入的回调函数做一个绑定,我们通过自定义属性来实现
|
||||||
|
one.initialCallback = callback
|
||||||
|
this.on(eventName, one)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PluginEventHubContext = createContext<EventEmitter | undefined>(undefined);
|
||||||
|
|
||||||
|
export const PluginEventHubProvider: FC<{ children: ReactNode }> = ({ children }) => {
|
||||||
|
const [pluginEventHub] = useState<EventEmitter>(new EventEmitter());
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PluginEventHubContext.Provider value={pluginEventHub}>
|
||||||
|
{children}
|
||||||
|
</PluginEventHubContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePluginEventHub = () => {
|
||||||
|
const context = useContext(PluginEventHubContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('usePluginEventHub must be used within a PluginEventHubProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { createContext, FC, ReactNode, useContext, useState } from "react";
|
||||||
|
|
||||||
|
export const PluginSlotHubContext = createContext<{
|
||||||
|
addSlot: (name: string, content: unknown) => void;
|
||||||
|
addSlotArr: (name: string, content: unknown[]) => void;
|
||||||
|
removeSlot: (name: string) => void;
|
||||||
|
getSlot: (name: string) => unknown;
|
||||||
|
} | undefined>(undefined);
|
||||||
|
|
||||||
|
export const PluginSlotHubProvider: FC<{ children: ReactNode }> = ({ children }) => {
|
||||||
|
const [pluginSlotHub] = useState<Map<string, unknown>>(new Map());
|
||||||
|
|
||||||
|
const pluginSlotHubService = {
|
||||||
|
addSlot: (name: string, content: any) => {
|
||||||
|
pluginSlotHub.set(name, pluginSlotHub.get(name) ? [...(pluginSlotHub.get(name) as Array<unknown>), content] : [content] ); },
|
||||||
|
addSlotArr: (name: string, content: any[]) => { pluginSlotHub.get(name) ? pluginSlotHub.set(name, (pluginSlotHub.get(name) as Array<unknown>).push(content)) : pluginSlotHub.set(name, content); },
|
||||||
|
removeSlot: (name: string) => { pluginSlotHub.delete(name); },
|
||||||
|
getSlot: (name: string) => {
|
||||||
|
|
||||||
|
return pluginSlotHub.get(name) ; }
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PluginSlotHubContext.Provider value={pluginSlotHubService}>
|
||||||
|
{children}
|
||||||
|
</PluginSlotHubContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePluginSlotHub = () => {
|
||||||
|
const context = useContext(PluginSlotHubContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('usePluginSlotHub must be used within a PluginSlotHubProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import { RESPONSE_TIPS } from '@common/const/const';
|
import { RESPONSE_TIPS } from '@common/const/const';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
|
import { $t } from "@common/locales"
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
const useCopyToClipboard = () => {
|
const useCopyToClipboard = () => {
|
||||||
|
|||||||
@@ -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,4 +1,6 @@
|
|||||||
import { STATUS_CODE } from "@common/const/const";
|
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||||
|
import { usePluginEventHub } from "@common/contexts/PluginEventHubContext";
|
||||||
|
import EventEmitter from "events";
|
||||||
|
|
||||||
const urlWhiteList = [/api.example.com\/users/, /api.example2.com\/products/]; // 正则白名单
|
const urlWhiteList = [/api.example.com\/users/, /api.example2.com\/products/]; // 正则白名单
|
||||||
|
|
||||||
@@ -137,7 +139,10 @@ type EoRequest = RequestInit & {eoParams?:{[k:string]:unknown},eoTransformKeys?:
|
|||||||
|
|
||||||
type EoHeaders = Headers | {[k:string]:string}
|
type EoHeaders = Headers | {[k:string]:string}
|
||||||
|
|
||||||
export function useFetch(){
|
export function useFetch() {
|
||||||
|
// plugin cannot use usePluginEventHub directly, so we need to pass it as a parameter
|
||||||
|
const pluginEventHub = usePluginEventHub()
|
||||||
|
|
||||||
function fetchData<T>(url:string, options: EoRequest ) {
|
function fetchData<T>(url:string, options: EoRequest ) {
|
||||||
// 合并传入的headers与默认headers
|
// 合并传入的headers与默认headers
|
||||||
const headers = { ...(options.body ? {}:DEFAULT_HEADERS), ...options.headers };
|
const headers = { ...(options.body ? {}:DEFAULT_HEADERS), ...options.headers };
|
||||||
@@ -184,9 +189,11 @@ export function useFetch(){
|
|||||||
// 如果响应体为JSON且指定了转换键,则转换响应数据
|
// 如果响应体为JSON且指定了转换键,则转换响应数据
|
||||||
if ( isJsonHttp(response.headers)) {
|
if ( isJsonHttp(response.headers)) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return shouldTransformKeys ? keysToCamel(data,options.eoTransformKeys as string[]) as T:data
|
const newData = await pluginEventHub.emit('httpResponse', {data,continue:true}) as Response;
|
||||||
|
return shouldTransformKeys ? keysToCamel(newData,options.eoTransformKeys as string[]) as T:data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@@ -0,0 +1,449 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
||||||
|
import { DEFAULT_LOCAL_PLUGIN_PATH, generateRemoteModuleTemplate, loadRemoteModule, validateExportLifecycle } from "@common/utils/plugin.tsx";
|
||||||
|
import { useFetch } from "@common/hooks/http";
|
||||||
|
import { PluginConfigType, RouteConfig } from "@common/const/type.ts";
|
||||||
|
import { ApiparkPluginDriverType ,RouterMapConfig} from "@common/const/type";
|
||||||
|
import { usePluginEventHub } from "@common/contexts/PluginEventHubContext";
|
||||||
|
import { usePluginSlotHub } from "@common/contexts/PluginSlotHubContext";
|
||||||
|
import { App } from "antd";
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
buildAt:'2024-09-13T03:51:25Z',
|
||||||
|
build_user:'gitlab-runner',
|
||||||
|
git_commint:'6438d5aaff146dc560ed0d8563788e64a49640a5',
|
||||||
|
goversion:'go version go1.21.4 linux/amd64',
|
||||||
|
guide:true,
|
||||||
|
plugins:[
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'guide',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'guide/*',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'team',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'team',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'service',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'service',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'datasourcing',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'datasourcing',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'cluster',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'cluster',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'aisetting',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'aisetting',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'cert',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'cert',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'serviceHub',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'serviceHub',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'commonsetting',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'commonsetting',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'consumer',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'consumer',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'member',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'member',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'role',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'role',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'analytics',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'analytics',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'template',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'template/:moduleId',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'logsettings',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'logsettings/*',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'resourcesettings',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'resourcesettings/*',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'userProfile',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'userProfile',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver:'apipark.builtIn.component',
|
||||||
|
name:'globalPolicy',
|
||||||
|
router:[
|
||||||
|
{
|
||||||
|
path:'globalPolicy',
|
||||||
|
type:'normal'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.remote.normal",
|
||||||
|
// "name": "remote",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "path": "remote",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.local.preload",
|
||||||
|
// "name": "auth",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "expose": "AppModule",
|
||||||
|
// "path": "auth",
|
||||||
|
// "type": "root"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "expose": "AuthInfoModule",
|
||||||
|
// "path": "auth-info",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.builtIn.component",
|
||||||
|
// "name": "email",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "path": "system/email",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.builtIn.module",
|
||||||
|
// "name": "open-api",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "path": "system/ext-app",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.local.preload",
|
||||||
|
// "name": "remote",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "expose": "App",
|
||||||
|
// "path": "router1/*",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "driver": "apipark.remote.normal",
|
||||||
|
// "name": "apispace",
|
||||||
|
// "router": [
|
||||||
|
// {
|
||||||
|
// "path": "remote/apispace",
|
||||||
|
// "type": "normal"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
powered:'Powered by https://eolink.com',
|
||||||
|
product:'apipark',
|
||||||
|
version:'6438d5aa'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecutePluginType = PluginConfigType & {
|
||||||
|
expose:string,
|
||||||
|
bootstrap:string
|
||||||
|
}
|
||||||
|
|
||||||
|
const usePluginLoader = (apipark:ApiparkPluginDriverType,routerMap:Map<string, RouterMapConfig>) => {
|
||||||
|
const [modules, setModules] = useState(new Map());
|
||||||
|
const [executeList, setExecuteList] = useState<ExecutePluginType[]>([]);
|
||||||
|
const [baseHref, setBaseHref] = useState('');
|
||||||
|
const [pendingTasks, setPendingTasks] = useState(0);
|
||||||
|
const {fetchData} = useFetch();
|
||||||
|
const pluginProvider = useGlobalContext();
|
||||||
|
const pluginEventHub = usePluginEventHub();
|
||||||
|
const pluginSlotHub = usePluginSlotHub();
|
||||||
|
const { getMenuList,dispatch} = pluginProvider
|
||||||
|
const { modal,message } = App.useApp()
|
||||||
|
const [startLoadExecutePlugin, setStartLoadExecutePlugin] = useState<boolean>(false)
|
||||||
|
const messageService = message;
|
||||||
|
const modalService = modal;
|
||||||
|
let startInstallPlugin = false
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if (startLoadExecutePlugin && pendingTasks === 0 && executeList.length > 0) {
|
||||||
|
loadExecutedPlugin();
|
||||||
|
}
|
||||||
|
},[pendingTasks, executeList])
|
||||||
|
|
||||||
|
|
||||||
|
const getModule = (routerPrefix:string, specific = false) => {
|
||||||
|
if (routerPrefix.startsWith('/')) {
|
||||||
|
routerPrefix = routerPrefix.substring(1);
|
||||||
|
}
|
||||||
|
if (specific) {
|
||||||
|
return modules.get(routerPrefix);
|
||||||
|
}
|
||||||
|
let matchedModule = null;
|
||||||
|
let matchedLength = 0;
|
||||||
|
|
||||||
|
modules.forEach((value, key) => {
|
||||||
|
if (routerPrefix.startsWith(key) && key.length > matchedLength) {
|
||||||
|
matchedModule = value;
|
||||||
|
matchedLength = key.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return matchedModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadModule = async (routerPrefix: string, pluginName: any, exposedModule: string , pluginPath: any) => {
|
||||||
|
if (!modules.get(routerPrefix)) {
|
||||||
|
try {
|
||||||
|
const loadedModule = await loadRemoteModule(generateRemoteModuleTemplate(pluginName, exposedModule, pluginPath));
|
||||||
|
const Module = loadedModule.default ?? loadedModule
|
||||||
|
let ModuleBootstrap;
|
||||||
|
try {
|
||||||
|
ModuleBootstrap = await loadRemoteModule(generateRemoteModuleTemplate(pluginName, 'Bootstrap', pluginPath));
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Bootstrap module not found:', error);
|
||||||
|
}
|
||||||
|
setModules(prevModules => new Map(prevModules).set(routerPrefix,Module[exposedModule] ));
|
||||||
|
if (!validateExportLifecycle(Module)) {
|
||||||
|
console.error('需要导出插件生命周期函数');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await Module.bootstrap?.({
|
||||||
|
pluginProvider,
|
||||||
|
pluginEventHub,
|
||||||
|
pluginSlotHub
|
||||||
|
});
|
||||||
|
return Module;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('导入插件失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getModule(routerPrefix, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadExecutedPlugin = async () => {
|
||||||
|
setStartLoadExecutePlugin(true)
|
||||||
|
for (const plugin of executeList) {
|
||||||
|
try {
|
||||||
|
const Module = await loadRemoteModule(generateRemoteModuleTemplate(plugin.name, plugin?.expose || 'Bootstrap', plugin.path || `${DEFAULT_LOCAL_PLUGIN_PATH}${plugin.name}/apipark.js`));
|
||||||
|
const bootstrap = Module.bootstrap;
|
||||||
|
if (!bootstrap) {
|
||||||
|
console.warn('立即执行插件未导出Bootstrap模块或bootstrap函数');
|
||||||
|
} else {
|
||||||
|
await bootstrap({
|
||||||
|
pluginEventHub,
|
||||||
|
pluginSlotHub,
|
||||||
|
pluginProvider,
|
||||||
|
platformProvider:null,
|
||||||
|
messageService,
|
||||||
|
modalService,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('执行插件失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const loadPlugins = () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if(startInstallPlugin) {
|
||||||
|
return resolve(true)
|
||||||
|
}
|
||||||
|
startInstallPlugin = true
|
||||||
|
installPlugin().then(async (res)=>{
|
||||||
|
// reset route after loading executed plugins
|
||||||
|
await loadExecutedPlugin();
|
||||||
|
return resolve(res)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const installPlugin = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// fetchData('system/plugins',{method:'GET'}).then((resp) => {
|
||||||
|
// if (resp.code === 0){
|
||||||
|
const resp = {data:mockData}
|
||||||
|
dispatch({type:'UPDATE_VERSION',version:resp.data.version})
|
||||||
|
dispatch({type:'UPDATE_DATE',updateDate:resp.data.buildAt})
|
||||||
|
dispatch({type:'UPDATE_POWER',powered:resp.data.powered})
|
||||||
|
const driverMethod = { apipark: apipark };
|
||||||
|
const pluginConfigList = resp.data.plugins;
|
||||||
|
const pluginLoader = { loadModule };
|
||||||
|
const pluginLifecycleGuard ={};
|
||||||
|
const builtInPluginLoader = loadBuiltInModule;
|
||||||
|
pluginSlotHub.addSlot('renewMenu', () => {
|
||||||
|
getMenuList()
|
||||||
|
});
|
||||||
|
for (const plugin of pluginConfigList) {
|
||||||
|
try {
|
||||||
|
const driverName = plugin.driver;
|
||||||
|
if (!driverName) {
|
||||||
|
console.error('no driver name');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const driver = driverName.split('.').reduce((driverMethod: { [x: string]: any; }, driverName: string | number) => driverMethod[driverName], driverMethod);
|
||||||
|
if(driverName.split('.')[2] === 'preload'){
|
||||||
|
setPendingTasks(prev => prev + 1);
|
||||||
|
}
|
||||||
|
;(driver as Function )?.({ setExecuteList:(callback:ExecutePluginType[]) => {
|
||||||
|
setExecuteList(callback);
|
||||||
|
setPendingTasks(prev => prev - 1);
|
||||||
|
}, pluginLoader, pluginProvider, pluginLifecycleGuard, builtInPluginLoader }, plugin);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('安装插件出错:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
// } else {
|
||||||
|
// messageService.error(resp.msg || '获取插件配置列表失败,请重试!');
|
||||||
|
// reject(new Error(resp.msg || '获取插件配置列表失败'));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadBuiltInModule = (pluginName: any) => {
|
||||||
|
try {
|
||||||
|
const { module } = routerMap.get(pluginName)!;
|
||||||
|
return module;
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`安装内置插件[${pluginName}]出错:`, err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadPlugins,
|
||||||
|
loadModule,
|
||||||
|
loadExecutedPlugin,
|
||||||
|
setBaseHref,
|
||||||
|
getModule
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default usePluginLoader;
|
||||||
@@ -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 base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user