diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e605da20 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "cSpell.words": [ + "Antd", + "apinto", + "Apipark", + "logsettings", + "resourcesettings" + ] +} \ No newline at end of file diff --git a/frontend/README.pro.md b/frontend/README.pro.md deleted file mode 100644 index b95b1e79..00000000 --- a/frontend/README.pro.md +++ /dev/null @@ -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` \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 41e27f69..5fa0b6c5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,11 +9,9 @@ "scripts": { "test": "jest", "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:remotes": "lerna run serve --scope=remote --parallel", "dev": "lerna run dev --scope=core --stream", - "dev:pro": "lerna run dev --scope=business-entry --stream", "stop": "kill-port --port 5000", "scan": "i18next-scanner --config i18next-scanner.config.js" }, diff --git a/frontend/packages/businessEntry/.env b/frontend/packages/businessEntry/.env deleted file mode 100644 index ef729214..00000000 --- a/frontend/packages/businessEntry/.env +++ /dev/null @@ -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 \ No newline at end of file diff --git a/frontend/packages/businessEntry/.eslintrc.cjs b/frontend/packages/businessEntry/.eslintrc.cjs deleted file mode 100644 index 87e6dac6..00000000 --- a/frontend/packages/businessEntry/.eslintrc.cjs +++ /dev/null @@ -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 }, - ], - }, -} diff --git a/frontend/packages/businessEntry/.gitignore b/frontend/packages/businessEntry/.gitignore deleted file mode 100644 index b5e526e8..00000000 --- a/frontend/packages/businessEntry/.gitignore +++ /dev/null @@ -1,25 +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? - diff --git a/frontend/packages/businessEntry/README.md b/frontend/packages/businessEntry/README.md deleted file mode 100644 index 38866cff..00000000 --- a/frontend/packages/businessEntry/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# `businessEntry` - -> TODO: description - -## Usage - -``` -const businessEntry = require('businessEntry'); - -// TODO: DEMONSTRATE API -``` diff --git a/frontend/packages/businessEntry/__tests__/businessEntry.test.js b/frontend/packages/businessEntry/__tests__/businessEntry.test.js deleted file mode 100644 index 46213a5b..00000000 --- a/frontend/packages/businessEntry/__tests__/businessEntry.test.js +++ /dev/null @@ -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'); diff --git a/frontend/packages/businessEntry/index.html b/frontend/packages/businessEntry/index.html deleted file mode 100644 index aa5cad3d..00000000 --- a/frontend/packages/businessEntry/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - 2APIPark - - -
- - - - - diff --git a/frontend/packages/businessEntry/package.json b/frontend/packages/businessEntry/package.json deleted file mode 100644 index 98766f5c..00000000 --- a/frontend/packages/businessEntry/package.json +++ /dev/null @@ -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": { - } -} diff --git a/frontend/packages/businessEntry/postcss.config.js b/frontend/packages/businessEntry/postcss.config.js deleted file mode 100644 index 494471a0..00000000 --- a/frontend/packages/businessEntry/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -export default { - plugins: { - 'postcss-import': {}, - 'tailwindcss/nesting': {}, - tailwindcss: {}, - autoprefixer: {} - }, - } - \ No newline at end of file diff --git a/frontend/packages/businessEntry/public/favicon.ico b/frontend/packages/businessEntry/public/favicon.ico deleted file mode 100644 index 2c1de84c..00000000 Binary files a/frontend/packages/businessEntry/public/favicon.ico and /dev/null differ diff --git a/frontend/packages/businessEntry/public/iconpark_apinto.js b/frontend/packages/businessEntry/public/iconpark_apinto.js deleted file mode 100644 index 93caf0e3..00000000 --- a/frontend/packages/businessEntry/public/iconpark_apinto.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(){window.__iconpark__=window.__iconpark__||{};var obj=JSON.parse("{\"680840\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"},\"680856\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680857\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680858\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680859\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680860\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680861\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680862\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680863\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680864\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680865\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680866\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680867\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680868\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680869\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680870\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680871\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680872\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680873\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680874\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680875\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680876\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680877\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680878\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680879\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680880\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680881\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680882\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680883\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680884\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680885\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680886\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680887\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680888\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680889\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680890\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680891\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680892\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680893\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680894\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680895\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680896\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680897\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680898\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680899\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680900\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680901\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680902\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680903\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680904\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680905\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680906\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680907\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680908\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680909\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680910\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680911\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680912\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680913\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680914\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680915\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680916\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680917\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680918\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680919\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680920\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680921\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680922\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680923\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680924\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680925\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680926\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680927\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680928\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680929\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680930\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680931\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680932\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680933\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680934\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680935\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680936\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680937\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680938\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"680939\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681014\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681015\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681016\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681017\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681018\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681019\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"content\":\"\"},\"681787\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"},\"694557\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"694558\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707431\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707736\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707739\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707741\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707742\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707743\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707744\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"707749\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708142\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708144\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708145\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708146\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708147\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"708181\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"709715\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"808898\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"808900\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"808916\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"810363\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"810396\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"818250\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"818340\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"}}");for(var _k in obj){window.__iconpark__[_k] = obj[_k]};var nm={"fuzhi1":680840,"bianji":680856,"tishi":680857,"xinkaibiaoqian":680858,"bianjiyoujian":680859,"suoyou":680860,"fuzhi":680861,"shijian":680862,"gundongxuanze":680863,"guanbi":680864,"zanting":680865,"chenggong":680866,"chakanyinyong":680867,"guidang":680868,"tihuan":680869,"zhankai":680870,"duankailianjie":680871,"Cookieguanli":680872,"riqi":680873,"zhongwen":680874,"yingwen":680875,"shuaxinjiankongzhuangtai":680876,"rili":680877,"genmulu":680878,"shangxianguanli":680879,"daimashili":680880,"yingyong":680881,"tianjia-2":680882,"qingchu":680883,"daoru":680884,"xiala":680885,"kuaisuceshi-2":680886,"saoyisao":680887,"shiyongjiaocheng":680888,"tianjiafujian":680889,"xiazai":680890,"jinzhidengji":680891,"fasongyoujian":680892,"bug":680893,"chaping":680894,"kuaisuceshi":680895,"yunshangchuan":680896,"yunxiazai":680897,"sousuo":680898,"peizhi":680899,"xinchuangkoudakai":680900,"shanchu-2":680901,"quanjusuoxiao":680902,"qiehuan":680903,"jianshao":680904,"chakanAPIlishi":680905,"lianjie":680906,"dunpaibaoxianrenzheng":680907,"shaixuan":680908,"zhihang":680909,"congmobanzhongchuangjianyongli":680910,"zhengligeshi":680911,"haoping":680912,"shouqi-2":680913,"gouwuche":680914,"lishi":680915,"tianjiaziji":680916,"tianjia":680917,"shouqi":680918,"gailan":680919,"paixu":680920,"gengduo":680921,"guanliyuanrenzheng":680922,"fenxiang":680923,"shanchu":680924,"yidong":680925,"chakan":680926,"shujuku":680927,"shangyoufuwu-":680928,"huanyuangeshi":680929,"jiangxu":680930,"shengxu":680931,"quanjufangda":680932,"xuanzhong":680933,"riqiqujian":680934,"ditu-1":680935,"qunzu":680936,"daochu":680937,"zhankai-":680938,"ditu-2":680939,"Eolink":681014,"APISpace":681015,"Apinto":681016,"json":681017,"webhook":681018,"linux":681019,"xinzengfenzu":681787,"circle-right-up":694557,"circle-right-down":694558,"APIjiekou-7mme3dcg":707431,"connection-box":707736,"system":707739,"form-one":707741,"yingyong-7mmhj11e":707742,"jiankongshexiangtou":707743,"file-cabinet":707744,"network-tree":707749,"search":708142,"find":708144,"circle-right-up-7mnlo5g9":708145,"circle-right-down-7mnlphn2":708146,"reduce-one":708147,"tool":708181,"shangxianguanli-new":709715,"hamburger-button":808898,"puzzle":808900,"keyline":808916,"daohang":810363,"lanjieqiguanli":810396,"shop":818250,"xiangmu":818340};for(var _i in nm){window.__iconpark__[_i] = obj[nm[_i]]}})();"object"!=typeof globalThis&&(Object.prototype.__defineGetter__("__magic__",function(){return this}),__magic__.globalThis=__magic__,delete Object.prototype.__magic__);(()=>{"use strict";var t={816:(t,e,i)=>{var s,r,o,n;i.d(e,{Vm:()=>z,dy:()=>P,Jb:()=>x,Ld:()=>$,sY:()=>T,YP:()=>A});const l=globalThis.trustedTypes,a=l?l.createPolicy("lit-html",{createHTML:t=>t}):void 0,h=`lit$${(Math.random()+"").slice(9)}$`,c="?"+h,d=`<${c}>`,u=document,p=(t="")=>u.createComment(t),v=t=>null===t||"object"!=typeof t&&"function"!=typeof t,f=Array.isArray,y=t=>{var e;return f(t)||"function"==typeof(null===(e=t)||void 0===e?void 0:e[Symbol.iterator])},m=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,g=/-->/g,b=/>/g,S=/>|[ \n \r](?:([^\s"'>=/]+)([ \n \r]*=[ \n \r]*(?:[^ \n \r"'`<>=]|("|')|))|$)/g,w=/'/g,k=/"/g,E=/^(?:script|style|textarea)$/i,C=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),P=C(1),A=C(2),x=Symbol.for("lit-noChange"),$=Symbol.for("lit-nothing"),O=new WeakMap,T=(t,e,i)=>{var s,r;const o=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let n=o._$litPart$;if(void 0===n){const t=null!==(r=null==i?void 0:i.renderBefore)&&void 0!==r?r:null;o._$litPart$=n=new H(e.insertBefore(p(),t),t,void 0,i)}return n.I(t),n},R=u.createTreeWalker(u,129,null,!1),_=(t,e)=>{const i=t.length-1,s=[];let r,o=2===e?"":"",n=m;for(let e=0;e"===a[0]?(n=null!=r?r:m,c=-1):void 0===a[1]?c=-2:(c=n.lastIndex-a[2].length,l=a[1],n=void 0===a[3]?S:'"'===a[3]?k:w):n===k||n===w?n=S:n===g||n===b?n=m:(n=S,r=void 0);const p=n===S&&t[e+1].startsWith("/>")?" ":"";o+=n===m?i+d:c>=0?(s.push(l),i.slice(0,c)+"$lit$"+i.slice(c)+h+p):i+h+(-2===c?(s.push(void 0),e):p)}const l=o+(t[i]||"")+(2===e?"":"");return[void 0!==a?a.createHTML(l):l,s]};class N{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let r=0,o=0;const n=t.length-1,a=this.parts,[d,u]=_(t,e);if(this.el=N.createElement(d,i),R.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(s=R.nextNode())&&a.length0){s.textContent=l?l.emptyScript:"";for(let i=0;i2||""!==i[0]||""!==i[1]?(this.H=Array(i.length-1).fill($),this.strings=i):this.H=$}get tagName(){return this.element.tagName}I(t,e=this,i,s){const r=this.strings;let o=!1;if(void 0===r)t=U(this,t,e,0),o=!v(t)||t!==this.H&&t!==x,o&&(this.H=t);else{const s=t;let n,l;for(t=r[0],n=0;n{i.r(e),i.d(e,{customElement:()=>s,eventOptions:()=>a,property:()=>o,query:()=>h,queryAll:()=>c,queryAssignedNodes:()=>v,queryAsync:()=>d,state:()=>n});const s=t=>e=>"function"==typeof e?((t,e)=>(window.customElements.define(t,e),e))(t,e):((t,e)=>{const{kind:i,elements:s}=e;return{kind:i,elements:s,finisher(e){window.customElements.define(t,e)}}})(t,e),r=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function o(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):r(t,e)}function n(t){return o({...t,state:!0,attribute:!1})}const l=({finisher:t,descriptor:e})=>(i,s)=>{var r;if(void 0===s){const s=null!==(r=i.originalKey)&&void 0!==r?r:i.key,o=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(o.finisher=function(e){t(e,s)}),o}{const r=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(r,s)}};function a(t){return l({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})}function h(t,e){return l({descriptor:i=>{const s={get(){var e;return null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0};if(e){const e="symbol"==typeof i?Symbol():"__"+i;s.get=function(){var i;return void 0===this[e]&&(this[e]=null===(i=this.renderRoot)||void 0===i?void 0:i.querySelector(t)),this[e]}}return s}})}function c(t){return l({descriptor:e=>({get(){var e;return null===(e=this.renderRoot)||void 0===e?void 0:e.querySelectorAll(t)},enumerable:!0,configurable:!0})})}function d(t){return l({descriptor:e=>({async get(){var e;return await this.updateComplete,null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0})})}const u=Element.prototype,p=u.msMatchesSelector||u.webkitMatchesSelector;function v(t="",e=!1,i=""){return l({descriptor:s=>({get(){var s,r;const o="slot"+(t?`[name=${t}]`:":not([name])");let n=null===(r=null===(s=this.renderRoot)||void 0===s?void 0:s.querySelector(o))||void 0===r?void 0:r.assignedNodes({flatten:e});return n&&i&&(n=n.filter((t=>t.nodeType===Node.ELEMENT_NODE&&(t.matches?t.matches(i):p.call(t,i))))),n},enumerable:!0,configurable:!0})})}},23:(t,e,i)=>{i.r(e),i.d(e,{unsafeSVG:()=>l});const s=t=>(...e)=>({_$litDirective$:t,values:e});var r=i(816);class o extends class{constructor(t){}T(t,e,i){this.Σdt=t,this.M=e,this.Σct=i}S(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}{constructor(t){if(super(t),this.vt=r.Ld,2!==t.type)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===r.Ld)return this.Vt=void 0,this.vt=t;if(t===r.Jb)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.vt)return this.Vt;this.vt=t;const e=[t];return e.raw=e,this.Vt={_$litType$:this.constructor.resultType,strings:e,values:[]}}}o.directiveName="unsafeHTML",o.resultType=1,s(o);class n extends o{}n.directiveName="unsafeSVG",n.resultType=2;const l=s(n)},249:(t,e,i)=>{i.r(e),i.d(e,{CSSResult:()=>n,LitElement:()=>x,ReactiveElement:()=>b,UpdatingElement:()=>A,_Σ:()=>s.Vm,_Φ:()=>$,adoptStyles:()=>c,css:()=>h,defaultConverter:()=>y,getCompatibleStyle:()=>d,html:()=>s.dy,noChange:()=>s.Jb,notEqual:()=>m,nothing:()=>s.Ld,render:()=>s.sY,supportsAdoptingStyleSheets:()=>r,svg:()=>s.YP,unsafeCSS:()=>l});var s=i(816);const r=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol();class n{constructor(t,e){if(e!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t}get styleSheet(){return r&&void 0===this.t&&(this.t=new CSSStyleSheet,this.t.replaceSync(this.cssText)),this.t}toString(){return this.cssText}}const l=t=>new n(t+"",o),a=new Map,h=(t,...e)=>{const i=e.reduce(((e,i,s)=>e+(t=>{if(t instanceof n)return t.cssText;if("number"==typeof t)return t;throw Error(`Value passed to 'css' function must be a 'css' function result: ${t}. Use 'unsafeCSS' to pass non-literal values, but\n take care to ensure page security.`)})(i)+t[s+1]),t[0]);let s=a.get(i);return void 0===s&&a.set(i,s=new n(i,o)),s},c=(t,e)=>{r?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style");i.textContent=e.cssText,t.appendChild(i)}))},d=r?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return l(e)})(t):t;var u,p,v,f;const y={toAttribute(t,e){switch(e){case Boolean:t=t?"":null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},m=(t,e)=>e!==t&&(e==e||t==t),g={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:m};class b extends HTMLElement{constructor(){super(),this.Πi=new Map,this.Πo=void 0,this.Πl=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this.Πh=null,this.u()}static addInitializer(t){var e;null!==(e=this.v)&&void 0!==e||(this.v=[]),this.v.push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const s=this.Πp(i,e);void 0!==s&&(this.Πm.set(s,i),t.push(s))})),t}static createProperty(t,e=g){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const r=this[t];this[e]=s,this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||g}static finalize(){if(this.hasOwnProperty("finalized"))return!1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this.Πm=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(d(t))}else void 0!==t&&e.push(d(t));return e}static Πp(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this.Πg=new Promise((t=>this.enableUpdating=t)),this.L=new Map,this.Π_(),this.requestUpdate(),null===(t=this.constructor.v)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this.ΠU)&&void 0!==e?e:this.ΠU=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this.ΠU)||void 0===e||e.splice(this.ΠU.indexOf(t)>>>0,1)}Π_(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this.Πi.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return c(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})),this.Πl&&(this.Πl(),this.Πo=this.Πl=void 0)}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})),this.Πo=new Promise((t=>this.Πl=t))}attributeChangedCallback(t,e,i){this.K(t,i)}Πj(t,e,i=g){var s,r;const o=this.constructor.Πp(t,i);if(void 0!==o&&!0===i.reflect){const n=(null!==(r=null===(s=i.converter)||void 0===s?void 0:s.toAttribute)&&void 0!==r?r:y.toAttribute)(e,i.type);this.Πh=t,null==n?this.removeAttribute(o):this.setAttribute(o,n),this.Πh=null}}K(t,e){var i,s,r;const o=this.constructor,n=o.Πm.get(t);if(void 0!==n&&this.Πh!==n){const t=o.getPropertyOptions(n),l=t.converter,a=null!==(r=null!==(s=null===(i=l)||void 0===i?void 0:i.fromAttribute)&&void 0!==s?s:"function"==typeof l?l:null)&&void 0!==r?r:y.fromAttribute;this.Πh=n,this[n]=a(e,t.type),this.Πh=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||m)(this[t],e)?(this.L.has(t)||this.L.set(t,e),!0===i.reflect&&this.Πh!==t&&(void 0===this.Πk&&(this.Πk=new Map),this.Πk.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this.Πg=this.Πq())}async Πq(){this.isUpdatePending=!0;try{for(await this.Πg;this.Πo;)await this.Πo}catch(t){Promise.reject(t)}const t=this.performUpdate();return null!=t&&await t,!this.isUpdatePending}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this.Πi&&(this.Πi.forEach(((t,e)=>this[e]=t)),this.Πi=void 0);let e=!1;const i=this.L;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this.Π$()}catch(t){throw e=!1,this.Π$(),t}e&&this.E(i)}willUpdate(t){}E(t){var e;null===(e=this.ΠU)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}Π$(){this.L=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this.Πg}shouldUpdate(t){return!0}update(t){void 0!==this.Πk&&(this.Πk.forEach(((t,e)=>this.Πj(e,this[e],t))),this.Πk=void 0),this.Π$()}updated(t){}firstUpdated(t){}}var S,w,k,E,C,P;b.finalized=!0,b.shadowRootOptions={mode:"open"},null===(p=(u=globalThis).reactiveElementPlatformSupport)||void 0===p||p.call(u,{ReactiveElement:b}),(null!==(v=(f=globalThis).reactiveElementVersions)&&void 0!==v?v:f.reactiveElementVersions=[]).push("1.0.0-rc.1");const A=b;(null!==(S=(P=globalThis).litElementVersions)&&void 0!==S?S:P.litElementVersions=[]).push("3.0.0-rc.1");class x extends b{constructor(){super(...arguments),this.renderOptions={host:this},this.Φt=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();super.update(t),this.Φt=(0,s.sY)(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this.Φt)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.Φt)||void 0===t||t.setConnected(!1)}render(){return s.Jb}}x.finalized=!0,x._$litElement$=!0,null===(k=(w=globalThis).litElementHydrateSupport)||void 0===k||k.call(w,{LitElement:x}),null===(C=(E=globalThis).litElementPlatformSupport)||void 0===C||C.call(E,{LitElement:x});const $={K:(t,e,i)=>{t.K(e,i)},L:t=>t.L}},409:function(t,e,i){var s=this&&this.__decorate||function(t,e,i,s){var r,o=arguments.length,n=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(t,e,i,s);else for(var l=t.length-1;l>=0;l--)(r=t[l])&&(n=(o<3?r(n):o>3?r(e,i,n):r(e,i))||n);return o>3&&n&&Object.defineProperty(e,i,n),n};Object.defineProperty(e,"__esModule",{value:!0}),e.IconparkIconElement=void 0;const r=i(249),o=i(26),n=i(23),l={color:1,fill:1,stroke:1},a={STROKE:{trackAttr:"data-follow-stroke",rawAttr:"stroke"},FILL:{trackAttr:"data-follow-fill",rawAttr:"fill"}};class h extends r.LitElement{constructor(){super(...arguments),this.name="",this.identifyer="",this.size="1em"}get _width(){return this.width||this.size}get _height(){return this.height||this.size}get _stroke(){return this.stroke||this.color}get _fill(){return this.fill||this.color}get SVGConfig(){return(window.__iconpark__||{})[this.identifyer]||(window.__iconpark__||{})[this.name]||{viewBox:"0 0 0 0",content:""}}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.monkeyPatch("STROKE",!0),this.monkeyPatch("FILL",!0)}))}monkeyPatch(t,e){switch(t){case"STROKE":this.updateDOMByHand(this.strokeAppliedNodes,"STROKE",this._stroke,!!e);break;case"FILL":this.updateDOMByHand(this.fillAppliedNodes,"FILL",this._fill,!!e)}}updateDOMByHand(t,e,i,s){!i&&s||t&&t.forEach((t=>{i&&i===t.getAttribute(a[e].rawAttr)||t.setAttribute(a[e].rawAttr,i||t.getAttribute(a[e].trackAttr))}))}attributeChangedCallback(t,e,i){super.attributeChangedCallback(t,e,i),"name"===t||"identifyer"===t?setTimeout((()=>{this.monkeyPatch("STROKE"),this.monkeyPatch("FILL")})):l[t]&&(this.monkeyPatch("STROKE"),this.monkeyPatch("FILL"))}render(){return r.svg`${n.unsafeSVG(this.SVGConfig.content)}`}}h.styles=r.css`:host {display: inline-flex; align-items: center; justify-content: center;} :host([spin]) svg {animation: iconpark-spin 1s infinite linear;} :host([spin][rtl]) svg {animation: iconpark-spin-rtl 1s infinite linear;} :host([rtl]) svg {transform: scaleX(-1);} @keyframes iconpark-spin {0% { -webkit-transform: rotate(0); transform: rotate(0);} 100% {-webkit-transform: rotate(360deg); transform: rotate(360deg);}} @keyframes iconpark-spin-rtl {0% {-webkit-transform: scaleX(-1) rotate(0); transform: scaleX(-1) rotate(0);} 100% {-webkit-transform: scaleX(-1) rotate(360deg); transform: scaleX(-1) rotate(360deg);}}`,s([o.property({reflect:!0})],h.prototype,"name",void 0),s([o.property({reflect:!0,attribute:"icon-id"})],h.prototype,"identifyer",void 0),s([o.property({reflect:!0})],h.prototype,"color",void 0),s([o.property({reflect:!0})],h.prototype,"stroke",void 0),s([o.property({reflect:!0})],h.prototype,"fill",void 0),s([o.property({reflect:!0})],h.prototype,"size",void 0),s([o.property({reflect:!0})],h.prototype,"width",void 0),s([o.property({reflect:!0})],h.prototype,"height",void 0),s([o.queryAll(`[${a.STROKE.trackAttr}]`)],h.prototype,"strokeAppliedNodes",void 0),s([o.queryAll(`[${a.FILL.trackAttr}]`)],h.prototype,"fillAppliedNodes",void 0),e.IconparkIconElement=h,customElements.get("iconpark-icon")||customElements.define("iconpark-icon",h)}},e={};function i(s){var r=e[s];if(void 0!==r)return r.exports;var o=e[s]={exports:{}};return t[s].call(o.exports,o,o.exports,i),o.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i(409)})(); - \ No newline at end of file diff --git a/frontend/packages/businessEntry/public/iconpark_eolink.js b/frontend/packages/businessEntry/public/iconpark_eolink.js deleted file mode 100644 index 8cc587d7..00000000 --- a/frontend/packages/businessEntry/public/iconpark_eolink.js +++ /dev/null @@ -1 +0,0 @@ -(function(){window.__iconpark__=window.__iconpark__||{};var obj=JSON.parse("{\"647367\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"684408\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"684409\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"684411\":{\"viewBox\":\"0 0 119.19 102.5\",\"content\":\"\"},\"684412\":{\"viewBox\":\"0 0 108.55 93.99\",\"fill\":\"currentColor\",\"content\":\"\"},\"684413\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"684414\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"686740\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686741\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686742\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686743\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686744\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686745\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686746\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686747\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686748\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686749\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686750\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686751\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686752\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686753\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686754\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"686993\":{\"viewBox\":\"0 0 38.22 22.18\",\"fill\":\"currentColor\",\"content\":\"\"},\"687741\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"687742\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"691262\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"691537\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"691538\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"691806\":{\"viewBox\":\"0 0 194 194\",\"content\":\"\"},\"695738\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695739\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695740\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695741\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695742\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695743\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695746\":{\"viewBox\":\"0 0 1185 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695747\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695748\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695750\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695751\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695752\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695754\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695755\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695756\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"695758\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695759\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695760\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695761\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695762\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695763\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695764\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695801\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695802\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695803\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695804\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695805\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695806\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695807\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695810\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695811\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695812\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695817\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695818\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695819\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695820\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695821\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695822\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695828\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695829\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695830\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695831\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695833\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695834\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695835\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695836\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695837\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695838\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695839\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695840\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695841\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695842\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695844\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695845\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695846\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695865\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695867\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695868\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695869\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695870\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695876\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695877\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695878\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695883\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695884\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695886\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695887\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695888\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695889\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695890\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695891\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695892\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695893\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695896\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695899\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695900\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695901\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695902\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695903\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695904\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695905\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695906\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695907\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695908\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695909\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695913\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695914\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695915\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695916\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695933\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695934\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695935\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695936\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695938\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695940\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695941\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695942\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695944\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695945\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695946\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695947\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695948\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695950\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695951\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695953\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695954\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695955\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695956\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695957\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695958\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695959\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695960\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695961\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695962\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695963\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695964\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695966\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695967\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695968\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695969\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695971\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695972\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695973\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695975\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695978\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695979\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695980\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695981\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695982\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695984\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695985\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695986\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695987\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695988\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695990\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695993\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695995\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695997\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"695999\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696002\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696003\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696004\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696005\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696007\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696009\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696010\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696011\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696012\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696013\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696014\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696015\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696016\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696017\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696018\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696019\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696020\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696021\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696022\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696023\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696024\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696025\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696027\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696028\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696029\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696030\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696031\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696032\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696033\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696034\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696035\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696036\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696037\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696038\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696039\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696040\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696041\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696042\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696043\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696044\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696045\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696046\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696048\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696049\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696660\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"696661\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"744163\":{\"viewBox\":\"0 0 1024 1024\",\"fill\":\"currentColor\",\"content\":\"\"},\"744173\":{\"viewBox\":\"0 0 128 128\",\"fill\":\"none\",\"content\":\"\"},\"744175\":{\"viewBox\":\"0 0 128 128\",\"fill\":\"none\",\"content\":\"\"},\"750656\":{\"viewBox\":\"0 0 61 61\",\"fill\":\"none\",\"content\":\"\"},\"752737\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"756392\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757321\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757499\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757504\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757518\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757519\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757520\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757521\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757616\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"757650\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"767277\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"767278\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"775549\":{\"viewBox\":\"0 0 18 14\",\"fill\":\"none\",\"content\":\"\"},\"779333\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"},\"779418\":{\"viewBox\":\"0 0 1024 1024\",\"content\":\"\"},\"779705\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"779706\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"},\"787702\":{\"viewBox\":\"0 0 1024 1024\",\"content\":\"\"},\"788577\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"802334\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"804269\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"804612\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"804614\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"806103\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"813707\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"815901\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"820089\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"826687\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"854318\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"855246\":{\"viewBox\":\"0 0 16 16\",\"fill\":\"none\",\"content\":\"\"},\"855247\":{\"viewBox\":\"0 0 16 16\",\"fill\":\"none\",\"content\":\"\"},\"855248\":{\"viewBox\":\"0 0 16 16\",\"fill\":\"none\",\"content\":\"\"},\"855927\":{\"viewBox\":\"0 0 83 20\",\"fill\":\"none\",\"content\":\"\"},\"855928\":{\"viewBox\":\"0 0 68 24\",\"fill\":\"none\",\"content\":\"\"},\"855929\":{\"viewBox\":\"0 0 66 24\",\"fill\":\"none\",\"content\":\"\"},\"855938\":{\"viewBox\":\"0 0 198 72\",\"fill\":\"none\",\"content\":\"\"},\"857931\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"857985\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"861388\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"876705\":{\"viewBox\":\"0 0 16 16\",\"fill\":\"none\",\"content\":\"\"},\"884011\":{\"viewBox\":\"0 0 20 20\",\"fill\":\"none\",\"content\":\"\"},\"885387\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"897026\":{\"viewBox\":\"0 0 250 250\",\"fill\":\"none\",\"content\":\"\"},\"915485\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"929257\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"932197\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"949128\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"970590\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"973801\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"985435\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1002903\":{\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"content\":\"\"},\"1021623\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1021686\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1035721\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1035737\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1037074\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1037815\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1037816\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1037817\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1039918\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1042170\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"},\"1042171\":{\"viewBox\":\"0 0 48 48\",\"fill\":\"none\",\"content\":\"\"}}");for(var _k in obj){window.__iconpark__[_k] = obj[_k]};var nm={"round-fill":647367,"apinto-pro-icon":684408,"apinto-icon":684409,"apinto-pro":684411,"apinto":684412,"check-circle":684413,"apispace":684414,"auto-generate-api":686740,"compare-api":686741,"multi-protocal":686742,"read-good":686743,"richdoc":686744,"mockapi":686745,"script-support":686746,"diy-test":686747,"send":686748,"stereo-perspective":686749,"automatic-robot":686750,"switch-env":686751,"flash":686752,"chart-pie":686753,"date-drive":686754,"apistudio":686993,"postcat-icon":687741,"postcat":687742,"apistudio-icon":691262,"update-rotation":691537,"page":691538,"apispace-icon":691806,"avatar":695738,"people":695739,"people-minus":695740,"people-plus":695741,"peoples":695742,"user-business":695743,"folder-close-fill":695746,"windows":695747,"github":695748,"qq":695750,"browser-chrome":695751,"linux":695752,"edge":695754,"wechat":695755,"browser":695756,"gitlab":695758,"apple":695759,"alipay":695760,"facebook":695761,"twitter":695762,"paypal":695763,"new-lark":695764,"delete":695801,"return":695802,"search":695803,"import":695804,"export":695805,"add":695806,"add-child":695807,"file-addition":695810,"add-circle":695811,"minus":695812,"close":695817,"close-small":695818,"check-small":695819,"check":695820,"code-terminal":695821,"code":695822,"preview-open":695828,"preview-close":695829,"folder-close":695830,"folder-open":695831,"upload":695833,"download":695834,"copy":695835,"upload-file":695836,"compare":695837,"edit":695838,"share":695839,"share-all":695840,"share-url-fill":695841,"share-url":695842,"back":695844,"back-fill":695845,"share-fill":695846,"sort":695865,"filter":695867,"reduce":695868,"done-all":695869,"full-selection":695870,"right-bar":695876,"left-bar":695877,"direction-adjustment":695878,"down-small":695883,"left-small":695884,"right-small":695886,"right-one":695887,"right":695888,"up":695889,"up-one":695890,"up-small":695891,"up-two":695892,"down-two":695893,"enter":695896,"down":695899,"left":695900,"down-one":695901,"left-two":695902,"right-two":695903,"left-one":695904,"more":695905,"expand-left":695906,"expand-right":695907,"column":695908,"center-alignment":695909,"list-add":695913,"sort-amount-down":695914,"sort-amount-up":695915,"list":695916,"remind":695933,"close-remind":695934,"api":695935,"rocket":695936,"monitor":695938,"robot":695940,"plan":695941,"application":695942,"chart-proportion":695944,"data":695945,"chart-line":695946,"pie-10":695947,"pie":695948,"chart-bubble":695950,"cube":695951,"application-menu":695953,"crown":695954,"crown-fill":695955,"market":695956,"file-word":695957,"file-excel":695958,"hashtag-key":695959,"file-hash":695960,"refresh":695961,"order":695962,"command":695963,"branch":695964,"page-template":695966,"smart-optimization":695967,"assembly-line":695968,"stopwatch":695969,"checklist":695971,"menu-fold":695972,"menu-unfold":695973,"alarm":695975,"protection":695978,"caution":695979,"openapi":695980,"webhook":695981,"holding-hands":695982,"support":695984,"agreement":695985,"community":695986,"roadmap":695987,"family-7knl2ae1":695988,"smiling-face":695990,"play-fill":695993,"play":695995,"pause":695997,"magic":695999,"whole-site-accelerator":696002,"link-cloud-faild":696003,"link-cloud-sucess":696004,"translate":696005,"funds":696007,"unhappy-face":696009,"message":696010,"connection-arrow":696011,"loading":696012,"fork":696013,"quote":696014,"headset":696015,"attention":696016,"theme":696017,"keyboard":696018,"briefcase":696019,"star":696020,"star-7knmka28":696021,"protect":696022,"finance":696023,"setting":696024,"link":696025,"undo":696027,"inbox-success":696028,"home":696029,"local":696030,"laptop":696031,"view-list":696032,"lock":696033,"unlock":696034,"lightning":696035,"file-text":696036,"cooperative-handshake":696037,"navigation":696038,"view-grid-detail":696039,"help":696040,"history":696041,"logout-7knnioon":696042,"chinese":696043,"calendar":696044,"play-cycle":696045,"world":696046,"plugins":696048,"link-cloud":696049,"book":696660,"table-report":696661,"qiyeweixin":744163,"Oauth":744173,"dingding":744175,"eolink":750656,"tool":752737,"category-management":756392,"folder-code-one":757321,"link-three-8ah7lifn":757499,"download-two-8ah85008":757504,"quanjusuoxiao1":757518,"quanjufangda21":757519,"quanjusuoxiao211":757520,"quanjufangda1":757521,"wenjianshezhi":757616,"key":757650,"zidingyijiaoben":767277,"tiqubianliang":767278,"mock":775549,"tongzhishezhi":779333,"csdn":779418,"ceshibaogao":779705,"biangengtongzhi":779706,"icon-api":787702,"youjian":788577,"pushpin":802334,"announcement":804269,"collapse-text-input":804612,"zhankai":804614,"replay-music":806103,"download-web":813707,"permissions":815901,"file-editing":820089,"wallet":826687,"file-focus":854318,"pingpu-9a913n0n":855246,"zuoyoufenping-9a913n1f":855247,"shangxiafenping-9a913n1i":855248,"Paypal11":855927,"zhifubaozhifu1":855928,"weixinzhifu11":855929,"weixinzhifu":855938,"update-rotation-9and40f5":857931,"terminal":857985,"switch":861388,"zhinengrucan":876705,"biaoqian-banbenleixinzeng":884011,"book-open":885387,"morentouxiang-2":897026,"xiajia":915485,"drag":929257,"new-up":932197,"rss":949128,"yewuchangjing":970590,"newlybuild":973801,"bianji":985435,"jiekoushouquan":1002903,"interfacefenzutubiao":1021623,"yidong":1021686,"link-one":1035721,"canshugouzaoqi":1035737,"bianliang":1037074,"tars":1037815,"if":1037816,"tars-2":1037817,"yingyongguanxi":1039918,"save-one":1042170,"save":1042171};for(var _i in nm){window.__iconpark__[_i] = obj[nm[_i]]}})();"object"!=typeof globalThis&&(Object.prototype.__defineGetter__("__magic__",function(){return this}),__magic__.globalThis=__magic__,delete Object.prototype.__magic__);(()=>{"use strict";var t={816:(t,e,i)=>{var s,r,o,n;i.d(e,{Vm:()=>z,dy:()=>P,Jb:()=>x,Ld:()=>$,sY:()=>T,YP:()=>A});const l=globalThis.trustedTypes,a=l?l.createPolicy("lit-html",{createHTML:t=>t}):void 0,h=`lit$${(Math.random()+"").slice(9)}$`,c="?"+h,d=`<${c}>`,u=document,p=(t="")=>u.createComment(t),v=t=>null===t||"object"!=typeof t&&"function"!=typeof t,f=Array.isArray,y=t=>{var e;return f(t)||"function"==typeof(null===(e=t)||void 0===e?void 0:e[Symbol.iterator])},m=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,g=/-->/g,b=/>/g,S=/>|[ \n \r](?:([^\s"'>=/]+)([ \n \r]*=[ \n \r]*(?:[^ \n \r"'`<>=]|("|')|))|$)/g,w=/'/g,k=/"/g,E=/^(?:script|style|textarea)$/i,C=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),P=C(1),A=C(2),x=Symbol.for("lit-noChange"),$=Symbol.for("lit-nothing"),O=new WeakMap,T=(t,e,i)=>{var s,r;const o=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let n=o._$litPart$;if(void 0===n){const t=null!==(r=null==i?void 0:i.renderBefore)&&void 0!==r?r:null;o._$litPart$=n=new H(e.insertBefore(p(),t),t,void 0,i)}return n.I(t),n},R=u.createTreeWalker(u,129,null,!1),_=(t,e)=>{const i=t.length-1,s=[];let r,o=2===e?"":"",n=m;for(let e=0;e"===a[0]?(n=null!=r?r:m,c=-1):void 0===a[1]?c=-2:(c=n.lastIndex-a[2].length,l=a[1],n=void 0===a[3]?S:'"'===a[3]?k:w):n===k||n===w?n=S:n===g||n===b?n=m:(n=S,r=void 0);const p=n===S&&t[e+1].startsWith("/>")?" ":"";o+=n===m?i+d:c>=0?(s.push(l),i.slice(0,c)+"$lit$"+i.slice(c)+h+p):i+h+(-2===c?(s.push(void 0),e):p)}const l=o+(t[i]||"")+(2===e?"":"");return[void 0!==a?a.createHTML(l):l,s]};class N{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let r=0,o=0;const n=t.length-1,a=this.parts,[d,u]=_(t,e);if(this.el=N.createElement(d,i),R.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(s=R.nextNode())&&a.length0){s.textContent=l?l.emptyScript:"";for(let i=0;i2||""!==i[0]||""!==i[1]?(this.H=Array(i.length-1).fill($),this.strings=i):this.H=$}get tagName(){return this.element.tagName}I(t,e=this,i,s){const r=this.strings;let o=!1;if(void 0===r)t=U(this,t,e,0),o=!v(t)||t!==this.H&&t!==x,o&&(this.H=t);else{const s=t;let n,l;for(t=r[0],n=0;n{i.r(e),i.d(e,{customElement:()=>s,eventOptions:()=>a,property:()=>o,query:()=>h,queryAll:()=>c,queryAssignedNodes:()=>v,queryAsync:()=>d,state:()=>n});const s=t=>e=>"function"==typeof e?((t,e)=>(window.customElements.define(t,e),e))(t,e):((t,e)=>{const{kind:i,elements:s}=e;return{kind:i,elements:s,finisher(e){window.customElements.define(t,e)}}})(t,e),r=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function o(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):r(t,e)}function n(t){return o({...t,state:!0,attribute:!1})}const l=({finisher:t,descriptor:e})=>(i,s)=>{var r;if(void 0===s){const s=null!==(r=i.originalKey)&&void 0!==r?r:i.key,o=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(o.finisher=function(e){t(e,s)}),o}{const r=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(r,s)}};function a(t){return l({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})}function h(t,e){return l({descriptor:i=>{const s={get(){var e;return null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0};if(e){const e="symbol"==typeof i?Symbol():"__"+i;s.get=function(){var i;return void 0===this[e]&&(this[e]=null===(i=this.renderRoot)||void 0===i?void 0:i.querySelector(t)),this[e]}}return s}})}function c(t){return l({descriptor:e=>({get(){var e;return null===(e=this.renderRoot)||void 0===e?void 0:e.querySelectorAll(t)},enumerable:!0,configurable:!0})})}function d(t){return l({descriptor:e=>({async get(){var e;return await this.updateComplete,null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0})})}const u=Element.prototype,p=u.msMatchesSelector||u.webkitMatchesSelector;function v(t="",e=!1,i=""){return l({descriptor:s=>({get(){var s,r;const o="slot"+(t?`[name=${t}]`:":not([name])");let n=null===(r=null===(s=this.renderRoot)||void 0===s?void 0:s.querySelector(o))||void 0===r?void 0:r.assignedNodes({flatten:e});return n&&i&&(n=n.filter((t=>t.nodeType===Node.ELEMENT_NODE&&(t.matches?t.matches(i):p.call(t,i))))),n},enumerable:!0,configurable:!0})})}},23:(t,e,i)=>{i.r(e),i.d(e,{unsafeSVG:()=>l});const s=t=>(...e)=>({_$litDirective$:t,values:e});var r=i(816);class o extends class{constructor(t){}T(t,e,i){this.Σdt=t,this.M=e,this.Σct=i}S(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}{constructor(t){if(super(t),this.vt=r.Ld,2!==t.type)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===r.Ld)return this.Vt=void 0,this.vt=t;if(t===r.Jb)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.vt)return this.Vt;this.vt=t;const e=[t];return e.raw=e,this.Vt={_$litType$:this.constructor.resultType,strings:e,values:[]}}}o.directiveName="unsafeHTML",o.resultType=1,s(o);class n extends o{}n.directiveName="unsafeSVG",n.resultType=2;const l=s(n)},249:(t,e,i)=>{i.r(e),i.d(e,{CSSResult:()=>n,LitElement:()=>x,ReactiveElement:()=>b,UpdatingElement:()=>A,_Σ:()=>s.Vm,_Φ:()=>$,adoptStyles:()=>c,css:()=>h,defaultConverter:()=>y,getCompatibleStyle:()=>d,html:()=>s.dy,noChange:()=>s.Jb,notEqual:()=>m,nothing:()=>s.Ld,render:()=>s.sY,supportsAdoptingStyleSheets:()=>r,svg:()=>s.YP,unsafeCSS:()=>l});var s=i(816);const r=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol();class n{constructor(t,e){if(e!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t}get styleSheet(){return r&&void 0===this.t&&(this.t=new CSSStyleSheet,this.t.replaceSync(this.cssText)),this.t}toString(){return this.cssText}}const l=t=>new n(t+"",o),a=new Map,h=(t,...e)=>{const i=e.reduce(((e,i,s)=>e+(t=>{if(t instanceof n)return t.cssText;if("number"==typeof t)return t;throw Error(`Value passed to 'css' function must be a 'css' function result: ${t}. Use 'unsafeCSS' to pass non-literal values, but\n take care to ensure page security.`)})(i)+t[s+1]),t[0]);let s=a.get(i);return void 0===s&&a.set(i,s=new n(i,o)),s},c=(t,e)=>{r?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style");i.textContent=e.cssText,t.appendChild(i)}))},d=r?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return l(e)})(t):t;var u,p,v,f;const y={toAttribute(t,e){switch(e){case Boolean:t=t?"":null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},m=(t,e)=>e!==t&&(e==e||t==t),g={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:m};class b extends HTMLElement{constructor(){super(),this.Πi=new Map,this.Πo=void 0,this.Πl=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this.Πh=null,this.u()}static addInitializer(t){var e;null!==(e=this.v)&&void 0!==e||(this.v=[]),this.v.push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const s=this.Πp(i,e);void 0!==s&&(this.Πm.set(s,i),t.push(s))})),t}static createProperty(t,e=g){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const r=this[t];this[e]=s,this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||g}static finalize(){if(this.hasOwnProperty("finalized"))return!1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this.Πm=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(d(t))}else void 0!==t&&e.push(d(t));return e}static Πp(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this.Πg=new Promise((t=>this.enableUpdating=t)),this.L=new Map,this.Π_(),this.requestUpdate(),null===(t=this.constructor.v)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this.ΠU)&&void 0!==e?e:this.ΠU=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this.ΠU)||void 0===e||e.splice(this.ΠU.indexOf(t)>>>0,1)}Π_(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this.Πi.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return c(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})),this.Πl&&(this.Πl(),this.Πo=this.Πl=void 0)}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})),this.Πo=new Promise((t=>this.Πl=t))}attributeChangedCallback(t,e,i){this.K(t,i)}Πj(t,e,i=g){var s,r;const o=this.constructor.Πp(t,i);if(void 0!==o&&!0===i.reflect){const n=(null!==(r=null===(s=i.converter)||void 0===s?void 0:s.toAttribute)&&void 0!==r?r:y.toAttribute)(e,i.type);this.Πh=t,null==n?this.removeAttribute(o):this.setAttribute(o,n),this.Πh=null}}K(t,e){var i,s,r;const o=this.constructor,n=o.Πm.get(t);if(void 0!==n&&this.Πh!==n){const t=o.getPropertyOptions(n),l=t.converter,a=null!==(r=null!==(s=null===(i=l)||void 0===i?void 0:i.fromAttribute)&&void 0!==s?s:"function"==typeof l?l:null)&&void 0!==r?r:y.fromAttribute;this.Πh=n,this[n]=a(e,t.type),this.Πh=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||m)(this[t],e)?(this.L.has(t)||this.L.set(t,e),!0===i.reflect&&this.Πh!==t&&(void 0===this.Πk&&(this.Πk=new Map),this.Πk.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this.Πg=this.Πq())}async Πq(){this.isUpdatePending=!0;try{for(await this.Πg;this.Πo;)await this.Πo}catch(t){Promise.reject(t)}const t=this.performUpdate();return null!=t&&await t,!this.isUpdatePending}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this.Πi&&(this.Πi.forEach(((t,e)=>this[e]=t)),this.Πi=void 0);let e=!1;const i=this.L;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this.ΠU)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this.Π$()}catch(t){throw e=!1,this.Π$(),t}e&&this.E(i)}willUpdate(t){}E(t){var e;null===(e=this.ΠU)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}Π$(){this.L=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this.Πg}shouldUpdate(t){return!0}update(t){void 0!==this.Πk&&(this.Πk.forEach(((t,e)=>this.Πj(e,this[e],t))),this.Πk=void 0),this.Π$()}updated(t){}firstUpdated(t){}}var S,w,k,E,C,P;b.finalized=!0,b.shadowRootOptions={mode:"open"},null===(p=(u=globalThis).reactiveElementPlatformSupport)||void 0===p||p.call(u,{ReactiveElement:b}),(null!==(v=(f=globalThis).reactiveElementVersions)&&void 0!==v?v:f.reactiveElementVersions=[]).push("1.0.0-rc.1");const A=b;(null!==(S=(P=globalThis).litElementVersions)&&void 0!==S?S:P.litElementVersions=[]).push("3.0.0-rc.1");class x extends b{constructor(){super(...arguments),this.renderOptions={host:this},this.Φt=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();super.update(t),this.Φt=(0,s.sY)(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this.Φt)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.Φt)||void 0===t||t.setConnected(!1)}render(){return s.Jb}}x.finalized=!0,x._$litElement$=!0,null===(k=(w=globalThis).litElementHydrateSupport)||void 0===k||k.call(w,{LitElement:x}),null===(C=(E=globalThis).litElementPlatformSupport)||void 0===C||C.call(E,{LitElement:x});const $={K:(t,e,i)=>{t.K(e,i)},L:t=>t.L}},409:function(t,e,i){var s=this&&this.__decorate||function(t,e,i,s){var r,o=arguments.length,n=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(t,e,i,s);else for(var l=t.length-1;l>=0;l--)(r=t[l])&&(n=(o<3?r(n):o>3?r(e,i,n):r(e,i))||n);return o>3&&n&&Object.defineProperty(e,i,n),n};Object.defineProperty(e,"__esModule",{value:!0}),e.IconparkIconElement=void 0;const r=i(249),o=i(26),n=i(23),l={color:1,fill:1,stroke:1},a={STROKE:{trackAttr:"data-follow-stroke",rawAttr:"stroke"},FILL:{trackAttr:"data-follow-fill",rawAttr:"fill"}};class h extends r.LitElement{constructor(){super(...arguments),this.name="",this.identifyer="",this.size="1em"}get _width(){return this.width||this.size}get _height(){return this.height||this.size}get _stroke(){return this.stroke||this.color}get _fill(){return this.fill||this.color}get SVGConfig(){return(window.__iconpark__||{})[this.identifyer]||(window.__iconpark__||{})[this.name]||{viewBox:"0 0 0 0",content:""}}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.monkeyPatch("STROKE",!0),this.monkeyPatch("FILL",!0)}))}monkeyPatch(t,e){switch(t){case"STROKE":this.updateDOMByHand(this.strokeAppliedNodes,"STROKE",this._stroke,!!e);break;case"FILL":this.updateDOMByHand(this.fillAppliedNodes,"FILL",this._fill,!!e)}}updateDOMByHand(t,e,i,s){!i&&s||t&&t.forEach((t=>{i&&i===t.getAttribute(a[e].rawAttr)||t.setAttribute(a[e].rawAttr,i||t.getAttribute(a[e].trackAttr))}))}attributeChangedCallback(t,e,i){super.attributeChangedCallback(t,e,i),"name"===t||"identifyer"===t?setTimeout((()=>{this.monkeyPatch("STROKE"),this.monkeyPatch("FILL")})):l[t]&&(this.monkeyPatch("STROKE"),this.monkeyPatch("FILL"))}render(){return r.svg`${n.unsafeSVG(this.SVGConfig.content)}`}}h.styles=r.css`:host {display: inline-flex; align-items: center; justify-content: center;} :host([spin]) svg {animation: iconpark-spin 1s infinite linear;} :host([spin][rtl]) svg {animation: iconpark-spin-rtl 1s infinite linear;} :host([rtl]) svg {transform: scaleX(-1);} @keyframes iconpark-spin {0% { -webkit-transform: rotate(0); transform: rotate(0);} 100% {-webkit-transform: rotate(360deg); transform: rotate(360deg);}} @keyframes iconpark-spin-rtl {0% {-webkit-transform: scaleX(-1) rotate(0); transform: scaleX(-1) rotate(0);} 100% {-webkit-transform: scaleX(-1) rotate(360deg); transform: scaleX(-1) rotate(360deg);}}`,s([o.property({reflect:!0})],h.prototype,"name",void 0),s([o.property({reflect:!0,attribute:"icon-id"})],h.prototype,"identifyer",void 0),s([o.property({reflect:!0})],h.prototype,"color",void 0),s([o.property({reflect:!0})],h.prototype,"stroke",void 0),s([o.property({reflect:!0})],h.prototype,"fill",void 0),s([o.property({reflect:!0})],h.prototype,"size",void 0),s([o.property({reflect:!0})],h.prototype,"width",void 0),s([o.property({reflect:!0})],h.prototype,"height",void 0),s([o.queryAll(`[${a.STROKE.trackAttr}]`)],h.prototype,"strokeAppliedNodes",void 0),s([o.queryAll(`[${a.FILL.trackAttr}]`)],h.prototype,"fillAppliedNodes",void 0),e.IconparkIconElement=h,customElements.get("iconpark-icon")||customElements.define("iconpark-icon",h)}},e={};function i(s){var r=e[s];if(void 0!==r)return r.exports;var o=e[s]={exports:{}};return t[s].call(o.exports,o,o.exports,i),o.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i(409)})(); \ No newline at end of file diff --git a/frontend/packages/businessEntry/public/vite.svg b/frontend/packages/businessEntry/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/frontend/packages/businessEntry/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/packages/businessEntry/src/App.tsx b/frontend/packages/businessEntry/src/App.tsx deleted file mode 100644 index 52dac839..00000000 --- a/frontend/packages/businessEntry/src/App.tsx +++ /dev/null @@ -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 ( - - - - - - - - - ); -} - -export default App diff --git a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx b/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx deleted file mode 100644 index dea284a8..00000000 --- a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx +++ /dev/null @@ -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:, - key: uuidv4(), - }, - { - path:'/login', - component:, - key: uuidv4() - }, - { - path:'/', - component:, - key: uuidv4(), - children:[ - { - path:'approval/*', - component:, - key:uuidv4() - }, - { - path:'team', - component:, - key: uuidv4(), - provider: TeamProvider, - children:[ - { - path:'', - key: uuidv4(), - component: - }, - { - 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:, - key: uuidv4(), - provider: SystemProvider, - children:[ - { - path:'', - key:uuidv4(), - component: - }, - { - 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:, - 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:, - key:uuidv4(), - children:[ - { - path:'', - key: uuidv4(), - component: - }, - { - 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:, - provider:TenantManagementProvider, - key:uuidv4(), - children:[ - { - path:'', - key:uuidv4(), - component: - }, - { - 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: - }, - { - 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:, - children:[ - { - path: '', - key: uuidv4(), - component: - }, - { - 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:

设计中

, - key:uuidv4() - }, - APP_MODE === 'pro' &&{ - path:'analytics', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/Dashboard.tsx')), - key:uuidv4(), - children:[ - { - path:':dashboardType', - component:, - 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 ( - - - - {generateRoutes(PUBLIC_ROUTES)} - - - - ) -} - -const generateRoutes = (routerConfig: RouteConfig[]) => { - return routerConfig?.map((route: RouteConfig) => { - let routeElement; - if (route.lazy) { - const LazyComponent = route.lazy as React.ExoticComponent; - - routeElement = ( - }> - {route.provider ? ( - createElement(route.provider, {}, ) - ) : ( - - )} - - ); - } else { - routeElement = route.provider ? ( - createElement(route.provider, {}, route.component) - ) : ( - route.component - ); - } - - return ( - - {route.children && generateRoutes(route.children as RouteConfig[])} - - ); - } - ) -} - -// 保护的路由组件 -function ProtectedRoute() { - const {state} = useGlobalContext() - return state.isAuthenticated? : ; - } - -export default RenderRoutes \ No newline at end of file diff --git a/frontend/packages/businessEntry/src/main.tsx b/frontend/packages/businessEntry/src/main.tsx deleted file mode 100644 index cfb7d8ef..00000000 --- a/frontend/packages/businessEntry/src/main.tsx +++ /dev/null @@ -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( - - - - - , - ); - } catch (error) { - console.error('Initialization failed:', error); - // 处理初始化失败的情况,比如渲染一个错误界面 - } -} - -// 执行初始化 -initializeApp(); \ No newline at end of file diff --git a/frontend/packages/businessEntry/src/vite-env.d.ts b/frontend/packages/businessEntry/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/frontend/packages/businessEntry/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/frontend/packages/businessEntry/start-vite.js b/frontend/packages/businessEntry/start-vite.js deleted file mode 100644 index 224115dc..00000000 --- a/frontend/packages/businessEntry/start-vite.js +++ /dev/null @@ -1,17 +0,0 @@ - -// 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}`); -}); diff --git a/frontend/packages/businessEntry/tsconfig.json b/frontend/packages/businessEntry/tsconfig.json deleted file mode 100644 index 92776632..00000000 --- a/frontend/packages/businessEntry/tsconfig.json +++ /dev/null @@ -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" }] -} diff --git a/frontend/packages/businessEntry/tsconfig.node.json b/frontend/packages/businessEntry/tsconfig.node.json deleted file mode 100644 index 42872c59..00000000 --- a/frontend/packages/businessEntry/tsconfig.node.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/frontend/packages/businessEntry/vite.config.ts b/frontend/packages/businessEntry/vite.config.ts deleted file mode 100644 index 895d5197..00000000 --- a/frontend/packages/businessEntry/vite.config.ts +++ /dev/null @@ -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' -}) diff --git a/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs b/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs deleted file mode 100644 index b2f55614..00000000 --- a/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs +++ /dev/null @@ -1,85 +0,0 @@ -// vite.config.ts -import { defineConfig } from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/vite@5.2.12_@types+node@20.14.2_less@4.2.0/node_modules/vite/dist/node/index.js"; -import react from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/@vitejs+plugin-react@4.3.0_vite@5.2.12_@types+node@20.14.2_less@4.2.0_/node_modules/@vitejs/plugin-react/dist/index.mjs"; -import path from "path"; -import dynamicImportVars from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/@rollup+plugin-dynamic-import-vars@2.1.2_rollup@4.18.0/node_modules/@rollup/plugin-dynamic-import-vars/dist/es/index.js"; -import tailwindcss from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/tailwindcss@3.4.4/node_modules/tailwindcss/lib/index.js"; -import autoprefixer from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/autoprefixer@10.4.19_postcss@8.4.38/node_modules/autoprefixer/lib/autoprefixer.js"; -var __vite_injected_original_dirname = "D:\\eolink\\applatform\\frontend\\packages\\businessEntry"; -var vite_config_default = defineConfig({ - cacheDir: "./node_modules/.vite", - build: { - outDir: "../../dist", - sourcemap: false, - chunkSizeWarningLimit: 5e4, - cacheDir: "./node_modules/.vite", - output: { - manualChunks(id) { - if (id.includes("node_modules")) { - return id.toString().split("node_modules/")[1].split("/")[0].toString(); - } - 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(__vite_injected_original_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(__vite_injected_original_dirname, "../common/src") }, - { find: "@market", replacement: path.resolve(__vite_injected_original_dirname, "../market/src") }, - { find: "@core", replacement: path.resolve(__vite_injected_original_dirname, "../core/src") }, - { find: "@dashboard", replacement: path.resolve(__vite_injected_original_dirname, "../dashboard/src") }, - { find: "@openApi", replacement: path.resolve(__vite_injected_original_dirname, "../openApi/src") }, - { find: "@systemRunning", replacement: path.resolve(__vite_injected_original_dirname, "../systemRunning/src") }, - { find: "@businessEntry", replacement: path.resolve(__vite_injected_original_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" -}); -export { - vite_config_default as default -}; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxlb2xpbmtcXFxcYXBwbGF0Zm9ybVxcXFxmcm9udGVuZFxcXFxwYWNrYWdlc1xcXFxidXNpbmVzc0VudHJ5XCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJEOlxcXFxlb2xpbmtcXFxcYXBwbGF0Zm9ybVxcXFxmcm9udGVuZFxcXFxwYWNrYWdlc1xcXFxidXNpbmVzc0VudHJ5XFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9EOi9lb2xpbmsvYXBwbGF0Zm9ybS9mcm9udGVuZC9wYWNrYWdlcy9idXNpbmVzc0VudHJ5L3ZpdGUuY29uZmlnLnRzXCI7LypcclxuICogQERhdGU6IDIwMjQtMDEtMzEgMTU6MDA6MzlcclxuICogQExhc3RFZGl0b3JzOiBtYWdnaWV5eXlcclxuICogQExhc3RFZGl0VGltZTogMjAyNC0wOC0wMSAxMDo1MDoxMlxyXG4gKiBARmlsZVBhdGg6IFxcZnJvbnRlbmRcXHBhY2thZ2VzXFxidXNpbmVzc0VudHJ5XFx2aXRlLmNvbmZpZy50c1xyXG4gKi9cclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJ1xyXG5pbXBvcnQgZHluYW1pY0ltcG9ydFZhcnMgZnJvbSAnQHJvbGx1cC9wbHVnaW4tZHluYW1pYy1pbXBvcnQtdmFycyc7XHJcbmltcG9ydCB0YWlsd2luZGNzcyBmcm9tICd0YWlsd2luZGNzcyc7XHJcbmltcG9ydCBhdXRvcHJlZml4ZXIgZnJvbSAnYXV0b3ByZWZpeGVyJztcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XHJcbiAgY2FjaGVEaXI6ICcuL25vZGVfbW9kdWxlcy8udml0ZScsXHJcbiAgYnVpbGQ6e1xyXG4gICAgb3V0RGlyOicuLi8uLi9kaXN0JyxcclxuICAgIHNvdXJjZW1hcDogZmFsc2UsXHJcbiAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IDUwMDAwLFxyXG4gICAgY2FjaGVEaXI6ICcuL25vZGVfbW9kdWxlcy8udml0ZScsIFxyXG4gICAgICBvdXRwdXQ6IHtcclxuICAgICAgICBtYW51YWxDaHVua3MoaWQpIHtcclxuICAgICAgICAgIGlmIChpZC5pbmNsdWRlcygnbm9kZV9tb2R1bGVzJykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGlkLnRvU3RyaW5nKCkuc3BsaXQoJ25vZGVfbW9kdWxlcy8nKVsxXS5zcGxpdCgnLycpWzBdLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICAvLyBcdTk0ODhcdTVCRjkgcG5wbSBcdTU0OEMgTW9ub3JlcG8gXHU3Mjc5XHU2QjhBXHU1OTA0XHU3NDA2XHJcbiAgICAgICAgICBpZiAoaWQuaW5jbHVkZXMoJy5wbnBtJykpIHtcclxuICAgICAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBpZC5zcGxpdChwYXRoLnNlcCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VOYW1lID0gc2VnbWVudHNbc2VnbWVudHMuaW5kZXhPZignLnBucG0nKSArIDFdLnNwbGl0KCdAJylbMF07XHJcbiAgICAgICAgICAgIHJldHVybiBwYWNrYWdlTmFtZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gIGNzczoge1xyXG4gICAgcG9zdGNzczoge1xyXG4gICAgICBwbHVnaW5zOiBbXHJcbiAgICAgICAgdGFpbHdpbmRjc3MocGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvbW1vbi90YWlsd2luZC5jb25maWcuanMnKSksIFxyXG4gICAgICAgIGF1dG9wcmVmaXhlclxyXG4gICAgICBdLFxyXG4gICAgfSxcclxuICAgIHByZXByb2Nlc3Nvck9wdGlvbnM6IHtcclxuICAgICAgbGVzczoge1xyXG4gICAgICAgIGphdmFzY3JpcHRFbmFibGVkOiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgfSxcclxuICAgIG1vZHVsZXM6e1xyXG4gICAgICBsb2NhbHNDb252ZW50aW9uOlwiY2FtZWxDYXNlXCIsXHJcbiAgICAgIGdlbmVyYXRlU2NvcGVkTmFtZTpcIltsb2NhbF1fW2hhc2g6YmFzZTY0OjJdXCJcclxuICAgIH1cclxuICB9LFxyXG4gIHBsdWdpbnM6IFtyZWFjdCgpLFxyXG4gICAgICBkeW5hbWljSW1wb3J0VmFycyh7XHJcbiAgICAgICAgaW5jbHVkZTpbXCJzcmNcIl0sXHJcbiAgICAgICAgZXhjbHVkZTpbXSxcclxuICAgICAgICB3YXJuT25FcnJvcjpmYWxzZVxyXG4gICAgICAgfSksXHJcbiAgICBdLFxyXG4gIHJlc29sdmU6IHtcclxuICAgIGFsaWFzOiBbXHJcbiAgICAgIHsgZmluZDogL15+LywgcmVwbGFjZW1lbnQ6ICcnIH0sXHJcbiAgICAgIHsgZmluZDogJ0Bjb21tb24nLCByZXBsYWNlbWVudDogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvbW1vbi9zcmMnKSB9LFxyXG4gICAgICB7IGZpbmQ6ICdAbWFya2V0JywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9tYXJrZXQvc3JjJykgfSxcclxuICAgICAgeyBmaW5kOiAnQGNvcmUnLCByZXBsYWNlbWVudDogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvcmUvc3JjJykgfSxcclxuICAgICAgeyBmaW5kOiAnQGRhc2hib2FyZCcsIHJlcGxhY2VtZW50OiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4vZGFzaGJvYXJkL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BvcGVuQXBpJywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9vcGVuQXBpL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BzeXN0ZW1SdW5uaW5nJywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9zeXN0ZW1SdW5uaW5nL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BidXNpbmVzc0VudHJ5JywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuL3NyYycpIH0sXHJcbiAgICBdXHJcbiAgfSxcclxuICBzZXJ2ZXI6IHtcclxuICAgIHByb3h5OiB7XHJcbiAgICAgICcvYXBpL3YxJzoge1xyXG4gICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly91YXQuYXBpa2l0LmNvbToxMTIwNC9tb2NrQXBpL2FvcGxhdGZvcm0vJyxcclxuICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTcyLjE4LjE2Ni4yMTk6ODI4OC8nLFxyXG4gICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgICAgJy9hcGkyL3YxJzoge1xyXG4gICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly91YXQuYXBpa2l0LmNvbToxMTIwNC9tb2NrQXBpL2FvcGxhdGZvcm0vJyxcclxuICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTcyLjE4LjE2Ni4yMTk6ODI4OC8nLFxyXG4gICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0sXHJcbiAgbG9nTGV2ZWw6J2luZm8nXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFNQSxTQUFTLG9CQUFvQjtBQUM3QixPQUFPLFdBQVc7QUFDbEIsT0FBTyxVQUFVO0FBQ2pCLE9BQU8sdUJBQXVCO0FBQzlCLE9BQU8saUJBQWlCO0FBQ3hCLE9BQU8sa0JBQWtCO0FBWHpCLElBQU0sbUNBQW1DO0FBYXpDLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFVBQVU7QUFBQSxFQUNWLE9BQU07QUFBQSxJQUNKLFFBQU87QUFBQSxJQUNQLFdBQVc7QUFBQSxJQUNYLHVCQUF1QjtBQUFBLElBQ3ZCLFVBQVU7QUFBQSxJQUNSLFFBQVE7QUFBQSxNQUNOLGFBQWEsSUFBSTtBQUNmLFlBQUksR0FBRyxTQUFTLGNBQWMsR0FBRztBQUMvQixpQkFBTyxHQUFHLFNBQVMsRUFBRSxNQUFNLGVBQWUsRUFBRSxDQUFDLEVBQUUsTUFBTSxHQUFHLEVBQUUsQ0FBQyxFQUFFLFNBQVM7QUFBQSxRQUN4RTtBQUVBLFlBQUksR0FBRyxTQUFTLE9BQU8sR0FBRztBQUN4QixnQkFBTSxXQUFXLEdBQUcsTUFBTSxLQUFLLEdBQUc7QUFDbEMsZ0JBQU0sY0FBYyxTQUFTLFNBQVMsUUFBUSxPQUFPLElBQUksQ0FBQyxFQUFFLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDeEUsaUJBQU87QUFBQSxRQUNUO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDRixLQUFLO0FBQUEsSUFDSCxTQUFTO0FBQUEsTUFDUCxTQUFTO0FBQUEsUUFDUCxZQUFZLEtBQUssUUFBUSxrQ0FBVyw4QkFBOEIsQ0FBQztBQUFBLFFBQ25FO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUNBLHFCQUFxQjtBQUFBLE1BQ25CLE1BQU07QUFBQSxRQUNKLG1CQUFtQjtBQUFBLE1BQ3JCO0FBQUEsSUFDRjtBQUFBLElBQ0EsU0FBUTtBQUFBLE1BQ04sa0JBQWlCO0FBQUEsTUFDakIsb0JBQW1CO0FBQUEsSUFDckI7QUFBQSxFQUNGO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFBQyxNQUFNO0FBQUEsSUFDWixrQkFBa0I7QUFBQSxNQUNoQixTQUFRLENBQUMsS0FBSztBQUFBLE1BQ2QsU0FBUSxDQUFDO0FBQUEsTUFDVCxhQUFZO0FBQUEsSUFDYixDQUFDO0FBQUEsRUFDSjtBQUFBLEVBQ0YsU0FBUztBQUFBLElBQ1AsT0FBTztBQUFBLE1BQ0wsRUFBRSxNQUFNLE1BQU0sYUFBYSxHQUFHO0FBQUEsTUFDOUIsRUFBRSxNQUFNLFdBQVcsYUFBYSxLQUFLLFFBQVEsa0NBQVcsZUFBZSxFQUFFO0FBQUEsTUFDekUsRUFBRSxNQUFNLFdBQVcsYUFBYSxLQUFLLFFBQVEsa0NBQVcsZUFBZSxFQUFFO0FBQUEsTUFDekUsRUFBRSxNQUFNLFNBQVMsYUFBYSxLQUFLLFFBQVEsa0NBQVcsYUFBYSxFQUFFO0FBQUEsTUFDckUsRUFBRSxNQUFNLGNBQWMsYUFBYSxLQUFLLFFBQVEsa0NBQVcsa0JBQWtCLEVBQUU7QUFBQSxNQUMvRSxFQUFFLE1BQU0sWUFBWSxhQUFhLEtBQUssUUFBUSxrQ0FBVyxnQkFBZ0IsRUFBRTtBQUFBLE1BQzNFLEVBQUUsTUFBTSxrQkFBa0IsYUFBYSxLQUFLLFFBQVEsa0NBQVcsc0JBQXNCLEVBQUU7QUFBQSxNQUN2RixFQUFFLE1BQU0sa0JBQWtCLGFBQWEsS0FBSyxRQUFRLGtDQUFXLE9BQU8sRUFBRTtBQUFBLElBQzFFO0FBQUEsRUFDRjtBQUFBLEVBQ0EsUUFBUTtBQUFBLElBQ04sT0FBTztBQUFBLE1BQ0wsV0FBVztBQUFBO0FBQUEsUUFFVCxRQUFRO0FBQUEsUUFDUixjQUFjO0FBQUEsTUFDaEI7QUFBQSxNQUNBLFlBQVk7QUFBQTtBQUFBLFFBRVYsUUFBUTtBQUFBLFFBQ1IsY0FBYztBQUFBLE1BQ2hCO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFBQSxFQUNBLFVBQVM7QUFDWCxDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo= diff --git a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx index d0c80a86..b46732a7 100644 --- a/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx +++ b/frontend/packages/common/src/components/aoplatform/BasicLayout.tsx @@ -1,180 +1,162 @@ -import { - MenuProps, - App, - Button, - ConfigProvider, - Dropdown} from 'antd'; -import { Outlet, useLocation, useNavigate} from "react-router-dom"; +import { + MenuProps, + App, + Button, + ConfigProvider, + Dropdown +} from 'antd'; +import { Outlet, useLocation, useNavigate } from "react-router-dom"; import Logo from '@common/assets/layout-logo.png'; import AvatarPic from '@common/assets/default-avatar.png' -import { useEffect, useMemo, useState} from "react"; +import { useCallback, useEffect, useMemo, useState} from "react"; import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'; import { PERMISSION_DEFINITION } from '@common/const/permissions.ts'; import { BasicResponse, RESPONSE_TIPS, routerKeyMap, STATUS_CODE } from '@common/const/const.tsx'; import { UserInfoType } from '@common/const/type.ts'; import { useFetch } from '@common/hooks/http.ts'; 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 { $t } from '@common/locales'; import { ProConfigProvider, ProLayout } from '@ant-design/pro-components'; import LanguageSetting from './LanguageSetting'; +import { usePluginSlotHub } from '@common/contexts/PluginSlotHubContext'; const APP_MODE = import.meta.env.VITE_APP_MODE; export type MenuItem = Required['items'][number]; const themeToken = { - bgLayout:'#17163E;', - header: { - heightLayoutHeader:72 - }, - pageContainer:{ - paddingBlockPageContainerContent:0, - paddingInlinePageContainerContent:0, - } + bgLayout: '#17163E;', + header: { + heightLayoutHeader: 72 + }, + pageContainer: { + paddingBlockPageContainerContent: 0, + paddingInlinePageContainerContent: 0, + } } - + + function BasicLayout({project = 'core'}:{project:string}){ - const navigator = useNavigate() - const location = useLocation() - const currentUrl = location.pathname - const { state,accessData,checkPermission,accessInit,dispatch,resetAccess,getGlobalAccessData} = useGlobalContext() - const [pathname, setPathname] = useState(currentUrl); const mainPage = project === 'core' ?'/service/list':'/serviceHub/list' + const navigator = useNavigate() + const location = useLocation() + const currentUrl = location.pathname + const { state,accessData,checkPermission,accessInit,dispatch,resetAccess,getGlobalAccessData, menuList} = useGlobalContext() + const [pathname, setPathname] = useState(currentUrl); + const mainPage = project === 'core' ?'/service/list':'/serviceHub/list' + const [menuItems, setMenuItems] = useState(); + const pluginSlotHub = usePluginSlotHub() - const TOTAL_MENU_ITEMS:MenuProps['items'] = useMemo(() => [ - getNavItem($t('工作空间'), 'workspace','/guide/page',, [ - getNavItem({$t('首页')}, 'guide','/guide/page',,undefined,undefined,'all'), - getNavItem({$t('服务')}, 'service','/service',,undefined,undefined,'all'), - getNavItem({$t('消费者')}, 'consumer','/consumer',,undefined,undefined,'all'), - getNavItem({$t('团队')}, 'team','/team',,undefined,undefined,'all'), - ]), - getNavItem($t('API 市场'), 'serviceHub','/serviceHub',,undefined,undefined,'system.api_portal.api_portal.view'), + useEffect(()=>{ + const newMenu = transformMenuData(menuList) + setMenuItems(newMenu); + },[menuList, state.language,accessInit]) - getNavItem($t('仪表盘'), 'mainPage', APP_MODE === 'pro' ? '/analytics' : '/analytics/total',,[ - getNavItem({$t('运行视图')}, 'analytics',APP_MODE === 'pro' ? '/analytics' : '/analytics/total' ,,undefined,undefined,'system.analysis.run_view.view'), - APP_MODE === 'pro' ? getNavItem({$t('系统拓扑图')}, 'systemrunning','/systemrunning',,undefined,undefined,'system.dashboard.systemrunning.view') : null, - ],undefined,'system.analysis.run_view.view'), - - getNavItem($t('系统设置'), 'operationCenter','/commonsetting',, [ - getNavItem($t('系统'), 'serviceHubSetting','/commonsetting',null,[ - getNavItem({$t('常规')}, 'commonsetting','/commonsetting',,undefined,undefined,'system.api_market.service_classification.view'), - getNavItem({$t('API 网关')}, 'cluster','/cluster',,undefined,undefined,'system.settings.api_gateway.view'), - getNavItem({$t('AI 模型')}, 'aisetting','/aisetting',,undefined,undefined,'system.settings.api_gateway.view'), - ],undefined,'system.api_market.service_classification.view'), - getNavItem($t('用户'), 'organization','/member',null,[ - getNavItem({$t('账号')}, 'member','/member',,undefined,undefined,'system.settings.account.view'), - getNavItem({$t('角色')}, 'role','/role',,undefined,undefined,'system.organization.role.view'), - ],undefined,''), - getNavItem($t('集成'), 'maintenanceCenter','/datasourcing', null, [ - getNavItem({$t('数据源')}, 'datasourcing','/datasourcing',,undefined,undefined,'system.settings.data_source.view'), - getNavItem({$t('证书')}, 'cert','/cert',,undefined,undefined,'system.settings.ssl_certificate.view'), - getNavItem({$t('日志')}, 'logsettings','/logsettings',,undefined,undefined,'system.settings.log_configuration.view'), - APP_MODE === 'pro' ? getNavItem({$t('资源')}, 'resourcesettings','/resourcesettings',null,undefined,undefined,'system.partition.self.view'):null, - APP_MODE === 'pro' ? getNavItem({$t('Open API')}, 'openapi','/openapi',null,undefined,undefined,'system.openapi.self.view'):null, - ]), - ]), - ],[state.language,accessInit]) + useEffect(() => { + if (currentUrl === '/') { + navigator(mainPage) + } + }, [currentUrl]); - useEffect(() => { - if(currentUrl === '/'){ - navigator(mainPage) - } - - }, [currentUrl]); + const headerMenuData = useMemo(() => { + // 判断权限 + const hasAccess = (access: unknown) => checkPermission(access as keyof typeof PERMISSION_DEFINITION[0]); - const headerMenuData = useMemo(() => { - // 判断权限 - const hasAccess = (access: unknown) => checkPermission(access as keyof typeof PERMISSION_DEFINITION[0]); - - // 过滤菜单项 - const filterMenu = (menu: Array<{ [k: string]: unknown }>) => { - return [...menu] - .filter(x => x) // 过滤掉空数据 - .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; - } + // 过滤菜单项 + const filterMenu = (menu: Array<{ [k: string]: unknown }>) => { + return [...menu] + .filter(x => x) // 过滤掉空数据 + .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,name:$t(item.name) }; + } + // 处理没有 routes 的菜单项 + if (item.access) { + return (item.access === 'all' || hasAccess(item.access)) ? {...item,name:$t(item.name)} : null; + } // 如果没有 access 和 routes,则保留 - return item; + return {...item,name:$t(item.name) }; }) .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)) }; - }, [accessData, state.language]); - - - + }, [accessData, state.language,menuItems]); const { message } = App.useApp() const [userInfo,setUserInfo] = useState() const {fetchData} = useFetch() const navigate = useNavigate(); - const getUserInfo = ()=>{ - fetchData>('account/profile',{method:'GET'}) - .then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setUserInfo(data.profile) - dispatch({type:'UPDATE_USERDATA',userData:data.profile}) - }else{ - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) - } + const getUserInfo = () => { + fetchData>('account/profile', { method: 'GET' }) + .then(response => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setUserInfo(data.profile) + dispatch({ type: 'UPDATE_USERDATA', userData: data.profile }) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } - useEffect(() => { - getUserInfo() - getGlobalAccessData() - }, []); - - const logOut = ()=>{ - fetchData>('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)) - } - }) - } + useEffect(() => { + getUserInfo() + getGlobalAccessData() + }, []); - const items: MenuProps['items'] = useMemo(() => [ - userInfo?.type !== 'guest' && { - key: '2', - label: ( - ) - }, - { - key: '3', - label: ( - ) - }, - ].filter(Boolean), [userInfo]); + const logOut = () => { + fetchData>('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'] = useMemo(() => [ + userInfo?.type !== 'guest' && { + key: '2', + label: ( + ) + }, + { + key: '3', + label: ( + ) + }, + ].filter(Boolean), [userInfo]); + + + const actionRender =useMemo( ()=>{ + return [ + , + , + ...((pluginSlotHub.getSlot('basicLayoutAfterBtns') as unknown[] )||[] ) + ] + },[pluginSlotHub.getSlot('basicLayoutAfterBtns') ]) return( @@ -226,12 +208,7 @@ const themeToken = { actionsRender={(props) => { if (props.isMobile) return []; if (typeof window === 'undefined') return []; - return [ - , - - ]; + return actionRender; }} headerTitleRender={() => (
diff --git a/frontend/packages/common/src/components/aoplatform/NotFound.tsx b/frontend/packages/common/src/components/aoplatform/NotFound.tsx new file mode 100644 index 00000000..fc30bb0d --- /dev/null +++ b/frontend/packages/common/src/components/aoplatform/NotFound.tsx @@ -0,0 +1,22 @@ +import React, { useEffect, useState } from 'react'; +import { Result, Skeleton } from 'antd'; + +const NotFound: React.FC = () => { + const [showPage, setShowPage] = useState(false) + + useEffect(()=>{ + setTimeout(()=>setShowPage(true), 1000) + },[]) + + return ( +
+ { showPage ? : } +
+)} + +export default NotFound; \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/PolicyPublishModalContent.tsx b/frontend/packages/common/src/components/aoplatform/PolicyPublishModalContent.tsx new file mode 100644 index 00000000..c8df5598 --- /dev/null +++ b/frontend/packages/common/src/components/aoplatform/PolicyPublishModalContent.tsx @@ -0,0 +1,96 @@ +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((props, ref) => { + const { message } = App.useApp() + const { data} = props + const [form] = Form.useForm(); + const {fetchData} = useFetch() + const {state} = useGlobalContext() + + const publish:()=>Promise> = ()=>{ + return new Promise((resolve, reject)=>{ + form.validateFields().then((value)=>{ + const body = {...value, source:data.source} + fetchData>('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]) + +console.log(translatedPolicyColumns,data.strategies) + + return ( + <> +
+ + + + + + + + + {$t('策略列表')}: + + + {!data?.isPublish&& data?.unpublishMsg&&

{data.unpublishMsg}

} + + + + + ) +}) \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/RemotePlugin.tsx b/frontend/packages/common/src/components/aoplatform/RemotePlugin.tsx new file mode 100644 index 00000000..e69de29b diff --git a/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx b/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx index 5c493d92..f84b21bb 100644 --- a/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx +++ b/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx @@ -8,64 +8,65 @@ import { Icon } from "@iconify/react/dist/iconify.js" import { $t } from "@common/locales" type TableBtnWithPermissionProps = { - btnTitle:string - access?:keyof typeof PERMISSION_DEFINITION[0], - tooltip?:string, - disabled?:boolean, - navigateTo?:string, - onClick?:(args?:unknown)=>void - className?:string - btnType:string + btnTitle: string + access?: keyof typeof PERMISSION_DEFINITION[0], + tooltip?: string, + disabled?: boolean, + navigateTo?: string, + onClick?: (args?: unknown) => void + className?: string + btnType: string } -const TableIconName={ - 'add':'ic:baseline-add', - 'edit':'ic:baseline-edit', - 'delete':'ic:baseline-delete', - 'remove':'ic:baseline-minus', - 'copy':'ic:baseline-file-copy', - 'view':'ic:baseline-remove-red-eye', - 'publish':'ic:baseline-publish', - 'approval':'ic:baseline-approval', - 'stop':'ic:baseline-stop-circle', - 'online':'ic:baseline-check-circle', - 'cancel':'ic:baseline-cancel-schedule-send', - 'refresh':'ic:baseline-refresh' +const TableIconName = { + 'add': 'ic:baseline-add', + 'edit': 'ic:baseline-edit', + 'delete': 'ic:baseline-delete', + 'remove': 'ic:baseline-minus', + 'copy': 'ic:baseline-file-copy', + 'view': 'ic:baseline-remove-red-eye', + 'publish': 'ic:baseline-publish', + 'approval': 'ic:baseline-approval', + 'stop': 'ic:baseline-stop-circle', + 'online': 'ic:baseline-check-circle', + 'cancel': 'ic:baseline-cancel-schedule-send', + 'refresh': 'ic:baseline-refresh', + 'logs': 'hugeicons:google-doc' } // 表格操作栏按钮,受权限控制 -const TableBtnWithPermission = ({btnTitle, access, tooltip, disabled, navigateTo, onClick,className,btnType}:TableBtnWithPermissionProps) => { - - const [btnAccess, setBtnAccess] = useState(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]) +const TableBtnWithPermission = ({ btnTitle, access, tooltip, disabled, navigateTo, onClick, className, btnType }: TableBtnWithPermissionProps) => { - useEffect(()=>{ - access ? setBtnAccess(lastAccess) : setBtnAccess(true) - },[access, lastAccess]) + const [btnAccess, setBtnAccess] = useState(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]) - - const handleClick = useCallback((e: React.MouseEvent) => { - e.stopPropagation() - navigateTo ? navigate(navigateTo) : onClick?.() - }, [navigateTo, navigate, onClick]) - - return (<>{ - !btnAccess || (disabled&&tooltip) ? - - - - : - - - + useEffect(() => { + access ? setBtnAccess(lastAccess) : setBtnAccess(true) + }, [access, lastAccess]) + + + const handleClick = useCallback((e: React.MouseEvent) => { + e.stopPropagation() + navigateTo ? navigate(navigateTo) : onClick?.() + }, [navigateTo, navigate, onClick]) + + return (<>{ + !btnAccess || (disabled && tooltip) ? + + + + : + + + + + } + ); +} - } - ); - } - export default TableBtnWithPermission \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx index 02b3e24c..4cba7f4a 100644 --- a/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx +++ b/frontend/packages/common/src/components/aoplatform/UnUsedWordForTranslate.tsx @@ -159,7 +159,26 @@ export const TranslateWord = ()=>{ {$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范围,每条以换行分割')} ) } \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/WithRouteGuard.tsx b/frontend/packages/common/src/components/aoplatform/WithRouteGuard.tsx new file mode 100644 index 00000000..242ad144 --- /dev/null +++ b/frontend/packages/common/src/components/aoplatform/WithRouteGuard.tsx @@ -0,0 +1,82 @@ +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 | JSXElementConstructor, { + canActivate, + canLoad , + canDeactivate, + deactivated, + pathPrefix +}: { pathPrefix?:string, canActivate?: () => Promise; canLoad?: () => Promise; canDeactivate?: () => Promise; deactivated?: () => Promise; } = {}) => { + return function RouteGuard(props: JSX.IntrinsicAttributes) { + const [isActivated, setIsActivated] = useState(false); + const location = useLocation(); + useEffect(()=>{ + console.log('路由守卫') + },[]) + // 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 ? : null; + }; +} + +export default withRouteGuard; \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/prompt-editor/PromptEditor.tsx b/frontend/packages/common/src/components/aoplatform/prompt-editor/PromptEditor.tsx index 20320bb3..fcf85646 100644 --- a/frontend/packages/common/src/components/aoplatform/prompt-editor/PromptEditor.tsx +++ b/frontend/packages/common/src/components/aoplatform/prompt-editor/PromptEditor.tsx @@ -58,7 +58,7 @@ import { UPDATE_DATASETS_EVENT_EMITTER, UPDATE_HISTORY_EVENT_EMITTER, } from './constants' -import { useEventEmitterContextContext } from '@common/contexts/event-emitter' +import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext' export type PromptEditorProps = { instanceId?: string diff --git a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/component-picker-block/index.tsx b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/component-picker-block/index.tsx index bfece5ba..8b137349 100644 --- a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/component-picker-block/index.tsx +++ b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/component-picker-block/index.tsx @@ -30,7 +30,7 @@ import { $splitNodeContainingQuery } from '../../utils' import { useOptions } from './hooks' import type { PickerBlockMenuOption } from './menu' // 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 = { triggerString: string diff --git a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/context-block/component.tsx b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/context-block/component.tsx index 60346493..7a8db454 100644 --- a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/context-block/component.tsx +++ b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/context-block/component.tsx @@ -14,7 +14,7 @@ import { DELETE_CONTEXT_BLOCK_COMMAND } from './index' // PortalToFollowElemContent, // PortalToFollowElemTrigger, // } 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' type ContextBlockComponentProps = { diff --git a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/history-block/component.tsx b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/history-block/component.tsx index 54e0cc5a..d333b712 100644 --- a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/history-block/component.tsx +++ b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/history-block/component.tsx @@ -14,7 +14,7 @@ import { DELETE_HISTORY_BLOCK_COMMAND } from './index' // PortalToFollowElemContent, // PortalToFollowElemTrigger, // } 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' type HistoryBlockComponentProps = { diff --git a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/update-block.tsx b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/update-block.tsx index ad5c50dd..e17a493b 100644 --- a/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/update-block.tsx +++ b/frontend/packages/common/src/components/aoplatform/prompt-editor/plugins/update-block.tsx @@ -3,7 +3,7 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext import { textToEditorState } from '../utils' import { CustomTextNode } from './custom-text/node' 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_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY' diff --git a/frontend/packages/common/src/const/const.tsx b/frontend/packages/common/src/const/const.tsx index b4d1de95..092671f6 100644 --- a/frontend/packages/common/src/const/const.tsx +++ b/frontend/packages/common/src/const/const.tsx @@ -1,3 +1,5 @@ +import { $t } from '@common/locales' +import { StrategyStatusColorClass, StrategyStatusEnum } from './policy/consts' export type BasicResponse = { code:number @@ -5,7 +7,6 @@ export type BasicResponse = { msg:string } - export const STATUS_CODE = { SUCCESS:0, 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([ ['workspace',['consumer','service','team','guide']], ['my',['consumer','service','team']], @@ -29,6 +30,7 @@ export const routerKeyMap = new Map([ ['maintenanceCenter',['aisetting','datasourcing','cluster','cert','logsettings','resourcesettings','openapi'] ]]) + export const COLUMNS_TITLE = { operate : '' @@ -45,6 +47,7 @@ export const routerKeyMap = new Map([ startWithAlphabet:('英文数字下划线任意一种,首字母必须为英文'), specialStartWithAlphabet:('支持字母开头、英文数字中横线下划线组合'), onlyAlphabet:('字符非法,仅支持英文'), + ipAndCidr:'请输入IP地址或CIDR范围,每条以换行分割' } export const FORM_ERROR_TIPS = { @@ -73,4 +76,33 @@ export const routerKeyMap = new Map([ export const DATA_SHOW_TYPE_OPTIONS = [ {label:'列表', value:'list'}, {label:'块', value:'block'}, - ] \ No newline at end of file + ] + + +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)=> {$t(StrategyStatusEnum[text as keyof typeof StrategyStatusEnum])}, + }, + { + title: ('更新时间'), + dataIndex: 'optTime', + width: 182, + ellipsis: true, + }, +] \ No newline at end of file diff --git a/frontend/packages/common/src/const/policy/consts.tsx b/frontend/packages/common/src/const/policy/consts.tsx new file mode 100644 index 00000000..d9897596 --- /dev/null +++ b/frontend/packages/common/src/const/policy/consts.tsx @@ -0,0 +1,57 @@ + +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', + } + \ No newline at end of file diff --git a/frontend/packages/common/src/const/policy/type.ts b/frontend/packages/common/src/const/policy/type.ts new file mode 100644 index 00000000..f91403aa --- /dev/null +++ b/frontend/packages/common/src/const/policy/type.ts @@ -0,0 +1,123 @@ +import { DefaultOptionType } from "antd/es/select"; +import { StrategyStatusEnum } from "./consts"; + +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 + isDeleted:boolean + publishStatus:keyof typeof StrategyStatusEnum + filters:string + conf:string + operator:string + updateTime:string + } + + +export type FilterFormField= { + name: string; + value: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 + value:unknown + } + + export type FilterFormProps = { + filterForm: FilterFormType; + filterOptions:DefaultOptionType[]; + selectedOptionNameSet: Set; + disabled: boolean; + onFilterFormChange: (form: FilterFormType) => void; + setFormCanSubmit:(canSubmit:boolean)=>void + } + + export type FilterFormHandle = { + clear:()=>void + save:()=>Promise + } + + export type FilterFormItemProps = { + value?: string[]; + onChange?: (value: string[]) => void; + disabled:boolean + option:unknown + onShowValueChange?:(value:string)=>void + } + + export type RemoteTitleType = { + title:string + field:string + } \ No newline at end of file diff --git a/frontend/packages/common/src/const/type.ts b/frontend/packages/common/src/const/type.ts index 094d858e..e0cfe1bf 100644 --- a/frontend/packages/common/src/const/type.ts +++ b/frontend/packages/common/src/const/type.ts @@ -1,5 +1,9 @@ +import { FC, ReactElement, ReactNode } from "react" import { PERMISSION_DEFINITION } from "./permissions" 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 = { username: string @@ -8,7 +12,6 @@ export type UserInfoType = { phone: string avatar: string type:string - } export type UserProfileProps = { @@ -100,4 +103,112 @@ export type SimpleMemberItem = { email:string department: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 + lifecycle?:{ + canActivate?:()=>Promise + canLoad?:()=>Promise + canDeactivate?:()=>Promise + deactivated?:()=>Promise + } +} + +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; +}; +pluginProvider: ReturnType +// pluginLifecycleGuard: PluginLifecycleGuard; +builtInPluginLoader: (name: string) => any; +} + +export type PluginConfigType = { + name: string; + router: Array; + 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 + pathMatch?:string +} + + +export type PolichPublishItemType = { + name:string + priority:number + status:keyof typeof StrategyStatusEnum + optTime:string +} + +// 发布详情(版本) +export type PolicyPublishInfoType = { + source:string + strategies:Array + isPublish:boolean + versionName:string + unpublishMsg:string +}; + +export type PolicyPublishModalProps = { + data:PolicyPublishInfoType +} + +export type PolicyPublishModalHandle = { + publish:()=>Promise> } \ No newline at end of file diff --git a/frontend/packages/common/src/contexts/event-emitter.tsx b/frontend/packages/common/src/contexts/EventEmitterContext.tsx similarity index 100% rename from frontend/packages/common/src/contexts/event-emitter.tsx rename to frontend/packages/common/src/contexts/EventEmitterContext.tsx diff --git a/frontend/packages/common/src/contexts/GlobalStateContext.tsx b/frontend/packages/common/src/contexts/GlobalStateContext.tsx index b338b76a..8fa8215e 100644 --- a/frontend/packages/common/src/contexts/GlobalStateContext.tsx +++ b/frontend/packages/common/src/contexts/GlobalStateContext.tsx @@ -1,10 +1,17 @@ -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 { App } from "antd"; import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"; import { checkAccess } from "@common/utils/permission"; import { PERMISSION_DEFINITION } from "@common/const/permissions"; 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"; interface GlobalState { isAuthenticated: boolean; @@ -31,6 +38,168 @@ export type GlobalAction = | { type: 'UPDATE_LANGUAGE'; language: string } + const mockData = [ + { + "name": "工作空间", + "key": "workspace", + "path": "/guide/page", + "icon": "ic:baseline-space-dashboard", + "children": [ + { + "name": "首页", + "key": "guide", + "path": "/guide/page", + "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": "uil:comment-shield", + "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 +208,11 @@ export const GlobalContext = createContext<{ dispatch: Dispatch; accessData:Map; pluginAccessDictionary:{[k:string]:string}; + menuList:MenuItem[]; getGlobalAccessData:()=>Promise<{ access:string[]}>; getTeamAccessData:(teamId:string)=>void; getPluginAccessDictionary:(pluginData:{[k:string]:string})=>void + getMenuList:()=>void resetAccess:()=>void cleanTeamAccessData:()=>void checkPermission:(access:keyof typeof PERMISSION_DEFINITION[0] | Array)=>boolean @@ -49,6 +220,11 @@ export const GlobalContext = createContext<{ accessInit:boolean aiConfigFlushed:boolean setAiConfigFlushed:(flush:boolean)=>void + routeConfig: RouteConfig[]; + setRouterConfig: (isRoot: boolean, config: RouteConfig) => void; + addRouteConfig: (parentRoute: RouteConfig, config: RouteConfig) => void; + fetchData: ReturnType['fetchData']; + $t: typeof $t; } | undefined>(undefined); const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState => { @@ -99,10 +275,18 @@ const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState => } }; + +export const DefaultRouteConfig = [ + { path: '/', pathMatch: 'full', component: ,key:'root',}, + { path: '/login', component: ,key:'login'}, + { path: '/', pathMatch:'prefix',component: ,key:'basciLayout',children:[ + { path: '*', component: , key: 'errorBoundary' } + ]} +] // Create a context provider component export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => { - const {fetchData} = useFetch() const { message } = App.useApp() + const { setLocale } = useLocaleContext(); const [state, dispatch] = useReducer(globalReducer, { isAuthenticated: true, //mock用 userData: null, @@ -118,6 +302,43 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => { const [accessInit, setAccessInit] = useState(false) const [aiConfigFlushed, setAiConfigFlushed] = useState(false) let getGlobalAccessPromise: Promise> | null = null + const [menuList, setMenuList] = useState(mockData); + const [routeConfig, setRouteConfigState] = useState(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 = ()=>{ if(getGlobalAccessPromise){ @@ -151,6 +372,18 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => { }) } + const getMenuList = ()=>{ + // TODO 等待对接后端接口 + // fetchData>('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 = ()=>{ setTeamDataFlushed(false) setAccessData(prevData => prevData.set('team',[])) @@ -176,15 +409,26 @@ export const GlobalProvider: FC<{children:ReactNode}> = ({ children }) => { return revs } + + return ( + resetAccess ,checkPermission, + accessInit, + aiConfigFlushed, + setAiConfigFlushed, + routeConfig, + setRouterConfig, + addRouteConfig, + fetchData, + $t:$t,}}> {children} ); diff --git a/frontend/packages/common/src/contexts/LocaleContext.tsx b/frontend/packages/common/src/contexts/LocaleContext.tsx new file mode 100644 index 00000000..497e1a79 --- /dev/null +++ b/frontend/packages/common/src/contexts/LocaleContext.tsx @@ -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 = { + '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(zhCN); + + const setLocale = (language: string) => { + dayjs.locale(language); + setLocaleState(languageMap[language]); + }; + + return ( + + {children} + + ); +}; + +export const useLocaleContext = () => { + const context = useContext(LocaleContext); + if (!context) { + throw new Error('useLocaleContext must be used within a LocaleContext'); + } + return context; +}; \ No newline at end of file diff --git a/frontend/packages/common/src/contexts/PluginEventHubContext.tsx b/frontend/packages/common/src/contexts/PluginEventHubContext.tsx new file mode 100644 index 00000000..407b5993 --- /dev/null +++ b/frontend/packages/common/src/contexts/PluginEventHubContext.tsx @@ -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(undefined); + +export const PluginEventHubProvider: FC<{ children: ReactNode }> = ({ children }) => { + const [pluginEventHub] = useState(new EventEmitter()); + + return ( + + {children} + + ); +}; + +export const usePluginEventHub = () => { + const context = useContext(PluginEventHubContext); + if (!context) { + throw new Error('usePluginEventHub must be used within a PluginEventHubProvider'); + } + return context; +}; \ No newline at end of file diff --git a/frontend/packages/common/src/contexts/PluginSlotHubContext.tsx b/frontend/packages/common/src/contexts/PluginSlotHubContext.tsx new file mode 100644 index 00000000..7cdd47ac --- /dev/null +++ b/frontend/packages/common/src/contexts/PluginSlotHubContext.tsx @@ -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>(new Map()); + + const pluginSlotHubService = { + addSlot: (name: string, content: any) => { + pluginSlotHub.set(name, pluginSlotHub.get(name) ? [...(pluginSlotHub.get(name) as Array), content] : [content] ); }, + addSlotArr: (name: string, content: any[]) => { pluginSlotHub.get(name) ? pluginSlotHub.set(name, (pluginSlotHub.get(name) as Array).push(content)) : pluginSlotHub.set(name, content); }, + removeSlot: (name: string) => { pluginSlotHub.delete(name); }, + getSlot: (name: string) => { + + return pluginSlotHub.get(name) ; } + }; + + return ( + + {children} + + ); +}; + +export const usePluginSlotHub = () => { + const context = useContext(PluginSlotHubContext); + if (!context) { + throw new Error('usePluginSlotHub must be used within a PluginSlotHubProvider'); + } + return context; +}; \ No newline at end of file diff --git a/frontend/packages/common/src/hooks/http.ts b/frontend/packages/common/src/hooks/http.ts index 13886e0e..05fe42cf 100644 --- a/frontend/packages/common/src/hooks/http.ts +++ b/frontend/packages/common/src/hooks/http.ts @@ -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/]; // 正则白名单 @@ -137,7 +139,10 @@ type EoRequest = RequestInit & {eoParams?:{[k:string]:unknown},eoTransformKeys?: 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(url:string, options: EoRequest ) { // 合并传入的headers与默认headers const headers = { ...(options.body ? {}:DEFAULT_HEADERS), ...options.headers }; @@ -184,9 +189,11 @@ export function useFetch(){ // 如果响应体为JSON且指定了转换键,则转换响应数据 if ( isJsonHttp(response.headers)) { 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; }) .catch(error => { diff --git a/frontend/packages/common/src/hooks/pluginLoader.ts b/frontend/packages/common/src/hooks/pluginLoader.ts new file mode 100644 index 00000000..375fe664 --- /dev/null +++ b/frontend/packages/common/src/hooks/pluginLoader.ts @@ -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) => { + const [modules, setModules] = useState(new Map()); + const [executeList, setExecuteList] = useState([]); + 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(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; \ No newline at end of file diff --git a/frontend/packages/common/src/locales/keyHashMap.json b/frontend/packages/common/src/locales/keyHashMap.json index 16b77da7..6fd4a111 100644 --- a/frontend/packages/common/src/locales/keyHashMap.json +++ b/frontend/packages/common/src/locales/keyHashMap.json @@ -1,31 +1,8 @@ { - "工作空间": "Kc0e5ef9f", - "首页": "K4de11e23", - "服务": "Kb58e0c3f", - "消费者": "K7acfcfad", - "团队": "Kc9e489f5", - "API 市场": "K61c89f5f", - "仪表盘": "K16d71239", - "运行视图": "K714c192d", - "系统拓扑图": "Kd57dfe97", - "系统设置": "K3fe97dcc", - "系统": "Kecbb0e45", - "常规": "Ka358e23d", - "API 网关": "K449058e9", - "AI 模型": "K99935e6f", - "用户": "K1deaa2dd", - "账号": "K80a560a1", - "角色": "Kf644225f", - "集成": "K4057391a", - "数据源": "K8fa58214", - "证书": "K481e8a05", - "日志": "Kca53edd0", - "资源": "Kb283e720", - "Open API": "K631d646f", "账号设置": "K6535ff9c", "退出登录": "Kf15499b4", "文档": "Kabbd6e6", - "APIPark - 企业API数据开放平台": "K1196b104", + "APIPark": "K630c9e6d", "HTTP 状态码": "K1f42de3", "系统状态码": "K4770dff4", "描述": "Kf89e58f1", @@ -43,6 +20,8 @@ "ID": "K11d3633a", "名称": "Kbff43de3", "Driver": "K16ca79ef", + "资源": "Kb283e720", + "日志": "Kca53edd0", "已发布": "K7a369eef", "下线": "Kcfa1a4d2", "上线": "K771dc3b7", @@ -50,6 +29,8 @@ "删除": "Kecbd7449", "确认": "K1cbe2507", "搜索(0)名称": "K48325b6", + "发布名称": "Ka3e9f580", + "策略列表": "Kb2480682", "上下文": "Kc6340091", "查询内容": "K74ecb1fa", "会话历史": "K79f2e2f9", @@ -234,6 +215,26 @@ "地址": "K78b1ca25", "新增": "K1644b775", "申请方消费者": "Kec91f0db", + "策略名称": "K931615d7", + "优先级": "K31faa2a1", + "筛选条件": "Kbdec9fa", + "处理数": "Kbcbb7391", + "数据格式": "K118d8d74", + "关键字": "Kfe7c7d2d", + "正则表达式": "K2f57a694", + "手机号": "K8953e0a6", + "身份证号": "K6f86a038", + "银行卡号": "K7954e7c8", + "金额": "K320fdb17", + "日期": "K7867acda", + "局部显示": "K7d327ae8", + "局部遮蔽": "Kfbf38e3c", + "截取": "Kd8c1fbb0", + "替换": "K89829921", + "乱序": "K480a7165", + "随机字符串": "Kea0d69df", + "自定义字符串": "Ke7c84d1d", + "请输入IP地址或CIDR范围,每条以换行分割": "K49731763", "暂无操作权限,请联系管理员分配。": "K23fda291", "微信小程序": "K4618cb0a", "获取文件,需填路径": "Ka854f511", @@ -321,11 +322,14 @@ "至": "K7e1ab4b0", "详情": "Kf1b166e7", "暂不支持带有双斜杠//的url": "K28555332", + "输入的IP或CIDR不符合格式": "K83237c89", + "请正确输入路径,如/usr/*或*/usr/*": "K5ae2c87a", "必填项": "K71661ee8", "不是有效邮箱地址": "Kcbee3f8", "最近一次更新者": "K617f34f1", "最近一次更新时间": "K6ebca204", "保存": "Kabfe9512", + "服务": "Kb58e0c3f", "API 路由": "K51d1eb5d", "API 文档": "Ka2b6d281", "使用说明": "Kdefa9caa", @@ -401,11 +405,13 @@ "现在你可以通过 Token 来调用这些 API。": "Kd6d7ca1f", "快速接入 REST API": "K86cf95f", "创建 REST 服务和 API": "K7a3a8417", + "仪表盘": "K16d71239", "统计 API 调用情况": "K4a84214e", "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。": "K297d8563", "核心功能": "K2cdbb773", "账号与角色": "K3378c50d", "邀请你的团队成员加入 APIPark,共同管理和调用 API。": "Kda5bb930", + "团队": "Kc9e489f5", "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。": "Keee27105", "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。": "Kd5be0cd7", "权限管理": "K62e89ee7", @@ -413,6 +419,7 @@ "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。": "Kf2410413", "审核订阅申请": "K6c2e44b8", "提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。": "Kaa717866", + "集成": "K4057391a", "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。": "K3453272", "Hello!欢迎使用 APIPark": "Kd518ba3e", "你能通过 APIPark 快速在企业内部构建 API 开放门户/市场,享受极致的转发性能、API 可观测、服务治理、多租户管理、订阅审核流程等诸多好处。": "K7e04ea16", @@ -424,6 +431,7 @@ "了解更多功能": "K48f7e21f", "隐藏该教程": "K698296e2", "请输入账号": "Kf076f63c", + "账号": "K80a560a1", "请输入密码": "K25c895d5", "密码": "K551b0348", "登录": "Kd2c1a316", @@ -466,6 +474,7 @@ "密钥": "K8ef69ee2", "上传密钥": "Kba3507d6", "密钥文件的后缀名一般为 .key 的文件内容": "K93ac0f23", + "证书": "K481e8a05", "上传证书": "K7cdd1331", "证书文件的后缀名一般为 .crt 或 .pem 的文件内容": "K6d91905d", "添加证书": "Kd0f6ded7", @@ -484,11 +493,39 @@ "同步地址": "K2a49373f", "集群地址": "K5878440c", "下一步": "K5e9022f8", + "数据源": "K8fa58214", "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。": "Kdbafd6f9", "统计图表": "K1358acf", "地址(IP:端口)": "K62dabdf6", "组织(Organization)": "K2db12335", + "添加策略": "K34d0d409", + "输入名称、筛选条件查找": "Kbb4298ac", + "编辑策略": "Kc82b8374", + "策略类型": "K4b34a5e5", + "匹配条件": "K57f0fee8", + "数据脱敏规则": "K10650c58", + "配置脱敏规则": "K1b34a9ab", + "匹配值": "K26d22405", + "脱敏类型": "K1546e1fe", + "起始位置": "K9b9b0629", + "长度": "K52c84fe1", + "替换类型": "Kde84409c", + "替换值": "K338653b4", + "JSON Path": "Kbaeed3b7", + "脱敏规则": "K4cd91d61", + "自定义字符串; 值:": "K8dcad979", + "起始位置:(0)位;长度:(1)位": "K82e3f7b7", + "编辑": "Kad207008", + "已选择(0)项(1)数据": "K49dfc123", + "所有(0)": "K8457ea34", + "属性名称": "K7ca9a795", + "属性值": "Kc4391744", + "配置(0)": "K678e13fc", + "数据脱敏": "Kabac9caf", + "全局策略": "Ke8cbb878", + "支持对系统全局进行统一的策略配置,从而简化管理并确保一致性。全局策略的优先级比服务策略略低。": "Kc975cd5a", "资源配置": "K8e7a0f80", + "角色": "Kf644225f", "设置角色的权限范围。": "K95c3fd8b", "系统级别角色": "K138facd3", "添加角色": "K6eac768d", @@ -523,6 +560,7 @@ "删除服务": "Kde6bae17", "删除操作不可恢复,请谨慎操作!": "K885ea699", "上游": "Kda8d5ea1", + "服务策略": "K52f72551", "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。": "K12f58863", "添加服务": "K2d6658ed", "输入名称、ID、所属团队、负责人查找服务": "K7b8f623f", @@ -568,6 +606,7 @@ "退出全屏": "Kaf70c3b", "(0)调用详情": "Kd22841a4", "消费者调用统计": "K61cca533", + "消费者": "K7acfcfad", "请选择消费者": "Kdfff59d4", "调用趋势": "K8c7f2d2e", "(0)-(1)调用趋势": "K657c3452", @@ -600,6 +639,7 @@ "暂无调用量统计数据": "Kcd125e4d", "暂无报文量统计数据": "Kaa114e8b", "报文量统计": "K3ad84406", + "运行视图": "K714c192d", "集群配置并开启监控": "Kfa088d49", "监控功能用于辅助管理集群内信息,请配置集群、设置监控信息后查看当前集群监控情况;": "K3da3b9a0", "集群配置": "Kaddacfb", @@ -616,6 +656,19 @@ "暂无API数据": "K6b75bdbc", "搜索或选择消费者": "Kb684c806", "申请理由": "K4b15d6f5", + "支持把当前服务对接主流的 AI Agent平台,实现在 Agent 平台上快速、安全和合规地使用企业开放的 API 能力。": "K2ec0fa56", + "可按以下步骤进行对接:": "K35f23b64", + "步骤一:Agent 平台上创建自定义插件": "Kf5cd608b", + "不同 Agent 平台的操作细节可查看": "K4c81c7b6", + "《 Agent 对接手册》": "K275f7ffa", + "步骤二:导入 API 文档数据": "K49b81d06", + "可通过以下 URL 或 下载 Json 文件,导入 API 文档数据到 Agent 平台中。": "K4a3b62be", + "复制 URL": "K42697e11", + "下载 Json 文件": "K27a809c5", + "步骤三:配置 API 密钥": "K1e61fdee", + "在": "K55912595", + "菜单中,选择已通过本 API 服务申请的消费者,": "K33b1bc3", + "把 \"访问权限\" 菜单下的密钥填入到 Agent 平台对应的插件密钥配置中。": "K62adc41e", "消费者管理": "Ke0fbd1c8", "鉴权类型": "Kb71b5a13", "Iss": "K4d1465ee", @@ -676,6 +729,7 @@ "配置 Open Api": "K7829bb78", "Open Api": "Kcdf76005", "调用服务": "Ke2601944", + "系统拓扑图": "Kd57dfe97", "放大": "K8504bca8", "缩小": "K693c1b41" } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/en-US.json b/frontend/packages/common/src/locales/scan/en-US.json index ed2e807f..a693bcda 100644 --- a/frontend/packages/common/src/locales/scan/en-US.json +++ b/frontend/packages/common/src/locales/scan/en-US.json @@ -679,5 +679,70 @@ "Kc8ee3e62": "Non-Existence", "K1e97dbd8": "Existence", "Kec91f0db": "Applicant Consumer", - "Kf5fd27ed": "Enter Name to Search User" + "Kf5fd27ed": "Enter Name to Search User", + "K2ec0fa56": "Support integration with mainstream AI Agent platforms to enable the use of enterprise APIs in a fast, secure, and compliant manner on the Agent platform.", + "K35f23b64": "Follow these steps for integration:", + "Kf5cd608b": "Step 1: Create a custom plugin on the Agent platform", + "K4c81c7b6": "For details on the operations of different Agent platforms, refer to", + "K275f7ffa": "the 'Agent Integration Manual'", + "K49b81d06": "Step 2: Import API documentation data", + "K4a3b62be": "You can import API documentation data to the Agent platform via the following URL or by downloading the JSON file.", + "K42697e11": "Copy URL", + "K27a809c5": "Download JSON file", + "K1e61fdee": "Step 3: Configure API keys", + "K55912595": "In the", + "K33b1bc3": "menu, select the consumer that has applied for the API service,", + "K62adc41e": "and fill in the key from the 'Access Permission' menu into the corresponding plugin key configuration on the Agent platform.", + "Ke8cbb878": "Global Policy", + "K34d0d409": "Add Policy", + "Kbb4298ac": "Enter name, filter criteria to search", + "Kabac9caf": "Data Masking", + "Kc975cd5a": "Supports unified policy configuration for the system globally, simplifying management and ensuring consistency. The priority of global policies is slightly lower than that of service policies.", + "K52f72551": "Service Policy", + "K931615d7": "Policy Name", + "K31faa2a1": "Priority", + "Kbdec9fa": "Filter Criteria", + "Kbcbb7391": "Processed Count", + "Kad207008": "Edit", + "K630c9e6d": "APIPark", + "Ka3e9f580": "Release Name", + "Kb2480682": "Policy List", + "K118d8d74": "Data Format", + "Kfe7c7d2d": "Keyword", + "K2f57a694": "Regular Expression", + "K8953e0a6": "Mobile Number", + "K6f86a038": "ID Card Number", + "K7954e7c8": "Bank Card Number", + "K320fdb17": "Amount", + "K7867acda": "Date", + "K7d327ae8": "Partial Display", + "Kfbf38e3c": "Partial Masking", + "Kd8c1fbb0": "Truncate", + "K89829921": "Replace", + "K480a7165": "Shuffle", + "Kea0d69df": "Random String", + "Ke7c84d1d": "Custom String", + "K49731763": "Please enter IP address or CIDR range, each separated by a newline.", + "K83237c89": "The entered IP or CIDR does not meet the format.", + "K5ae2c87a": "Please enter the correct path, such as /usr/* or */usr/*.", + "Kc82b8374": "Edit Policy", + "K4b34a5e5": "Policy Type", + "K57f0fee8": "Match Conditions", + "K10650c58": "Data Masking Rules", + "K1b34a9ab": "Configure Masking Rules", + "K26d22405": "Match Value", + "K1546e1fe": "Masking Type", + "K9b9b0629": "Starting Position", + "K52c84fe1": "Length", + "Kde84409c": "Replace Type", + "K338653b4": "Replace Value", + "Kbaeed3b7": "JSON Path", + "K4cd91d61": "Masking Rules", + "K8dcad979": "Custom String; Value:", + "K82e3f7b7": "Starting Position: (0); Length: (1)", + "K49dfc123": "Selected (0) items (1) data", + "K8457ea34": "All (0)", + "K7ca9a795": "Attribute Name", + "Kc4391744": "Attribute Value", + "K678e13fc": "Configure (0)" } diff --git a/frontend/packages/common/src/locales/scan/ja-JP.json b/frontend/packages/common/src/locales/scan/ja-JP.json index 4e0e0b0f..8559a6bb 100644 --- a/frontend/packages/common/src/locales/scan/ja-JP.json +++ b/frontend/packages/common/src/locales/scan/ja-JP.json @@ -701,5 +701,70 @@ "Kc8ee3e62": "存在しない", "K1e97dbd8": "存在する", "Kec91f0db": "申請側コンシューマー", - "Kf5fd27ed": "名前を入力してユーザーを検索" + "Kf5fd27ed": "名前を入力してユーザーを検索", + "K2ec0fa56": "主要なAIエージェントプラットフォームと連携し、エージェントプラットフォーム上で企業のAPIを迅速、安全、かつコンプライアンスに準拠して使用できるようサポートします。", + "K35f23b64": "以下の手順で統合を行います:", + "Kf5cd608b": "ステップ1:エージェントプラットフォームでカスタムプラグインを作成", + "K4c81c7b6": "異なるエージェントプラットフォームの操作詳細については、", + "K275f7ffa": "「エージェント統合マニュアル」を参照してください。", + "K49b81d06": "ステップ2:APIドキュメントデータのインポート", + "K4a3b62be": "以下のURLを使用するか、JSONファイルをダウンロードして、APIドキュメントデータをエージェントプラットフォームにインポートできます。", + "K42697e11": "URLをコピー", + "K27a809c5": "JSONファイルをダウンロード", + "K1e61fdee": "ステップ3:APIキーの設定", + "K55912595": "「", + "K33b1bc3": "メニュー」から、APIサービスを申し込んだ消費者を選択し、", + "K62adc41e": "「アクセス権限」メニューのキーをエージェントプラットフォームのプラグインキー設定に入力します。", + "Ke8cbb878": "グローバルポリシー", + "K34d0d409": "ポリシーを追加", + "Kbb4298ac": "名前、フィルタ条件を入力して検索", + "Kabac9caf": "データマスキング", + "Kc975cd5a": "システム全体で統一されたポリシー設定をサポートし、管理の簡素化と一貫性の確保を実現します。グローバルポリシーの優先度はサービスポリシーより少し低いです。", + "K52f72551": "サービスポリシー", + "K931615d7": "ポリシー名", + "K31faa2a1": "優先度", + "Kbdec9fa": "フィルタ条件", + "Kbcbb7391": "処理数", + "Kad207008": "編集", + "K630c9e6d": "APIPark", + "Ka3e9f580": "リリース名", + "Kb2480682": "ポリシーリスト", + "K118d8d74": "データフォーマット", + "Kfe7c7d2d": "キーワード", + "K2f57a694": "正規表現", + "K8953e0a6": "携帯番号", + "K6f86a038": "IDカード番号", + "K7954e7c8": "銀行カード番号", + "K320fdb17": "金額", + "K7867acda": "日付", + "K7d327ae8": "部分表示", + "Kfbf38e3c": "部分マスキング", + "Kd8c1fbb0": "切り取り", + "K89829921": "置換", + "K480a7165": "シャッフル", + "Kea0d69df": "ランダム文字列", + "Ke7c84d1d": "カスタム文字列", + "K49731763": "IPアドレスまたはCIDR範囲を入力してください。各行で改行してください。", + "K83237c89": "入力されたIPまたはCIDRがフォーマットに一致しません。", + "K5ae2c87a": "正しいパスを入力してください。例: /usr/* または */usr/*。", + "Kc82b8374": "ポリシーを編集", + "K4b34a5e5": "ポリシータイプ", + "K57f0fee8": "一致条件", + "K10650c58": "データマスキングルール", + "K1b34a9ab": "マスキングルールを設定", + "K26d22405": "一致値", + "K1546e1fe": "マスキングタイプ", + "K9b9b0629": "開始位置", + "K52c84fe1": "長さ", + "Kde84409c": "置換タイプ", + "K338653b4": "置換値", + "Kbaeed3b7": "JSON パス", + "K4cd91d61": "マスキングルール", + "K8dcad979": "カスタム文字列; 値:", + "K82e3f7b7": "開始位置: (0); 長さ: (1)", + "K49dfc123": "選択された (0) アイテム (1) データ", + "K8457ea34": "すべて (0)", + "K7ca9a795": "属性名", + "Kc4391744": "属性値", + "K678e13fc": "設定 (0)" } diff --git a/frontend/packages/common/src/locales/scan/newJson/en-US.json b/frontend/packages/common/src/locales/scan/newJson/en-US.json index ddcaee31..9e26dfee 100644 --- a/frontend/packages/common/src/locales/scan/newJson/en-US.json +++ b/frontend/packages/common/src/locales/scan/newJson/en-US.json @@ -1,3 +1 @@ -{ - "Kf5fd27ed": "输入名称查找用户" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/ja-JP.json b/frontend/packages/common/src/locales/scan/newJson/ja-JP.json index ddcaee31..9e26dfee 100644 --- a/frontend/packages/common/src/locales/scan/newJson/ja-JP.json +++ b/frontend/packages/common/src/locales/scan/newJson/ja-JP.json @@ -1,3 +1 @@ -{ - "Kf5fd27ed": "输入名称查找用户" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/zh-CN.json b/frontend/packages/common/src/locales/scan/newJson/zh-CN.json index 44f232eb..878c5a8e 100644 --- a/frontend/packages/common/src/locales/scan/newJson/zh-CN.json +++ b/frontend/packages/common/src/locales/scan/newJson/zh-CN.json @@ -1,4 +1,7 @@ { + "K630c9e6d": "APIPark", + "Ka3e9f580": "发布名称", + "Kb2480682": "策略列表", "K76036e25": "HTTP 请求头", "K44607e3f": "全等匹配", "Kc287500a": "前缀匹配", @@ -21,7 +24,43 @@ "K78b1ca25": "地址", "K1644b775": "新增", "Kec91f0db": "申请方消费者", - "Kf5fd27ed": "输入名称查找用户", - "Kc3b7bfa8": "暂无消费者描述", - "K3a6f905d": "输入名称、ID 查找消费者" + "K118d8d74": "数据格式", + "Kfe7c7d2d": "关键字", + "K2f57a694": "正则表达式", + "K8953e0a6": "手机号", + "K6f86a038": "身份证号", + "K7954e7c8": "银行卡号", + "K320fdb17": "金额", + "K7867acda": "日期", + "K7d327ae8": "局部显示", + "Kfbf38e3c": "局部遮蔽", + "Kd8c1fbb0": "截取", + "K89829921": "替换", + "K480a7165": "乱序", + "Kea0d69df": "随机字符串", + "Ke7c84d1d": "自定义字符串", + "K49731763": "请输入IP地址或CIDR范围,每条以换行分割", + "K83237c89": "输入的IP或CIDR不符合格式", + "K5ae2c87a": "请正确输入路径,如/usr/*或*/usr/*", + "Kc82b8374": "编辑策略", + "K4b34a5e5": "策略类型", + "K57f0fee8": "匹配条件", + "K10650c58": "数据脱敏规则", + "K1b34a9ab": "配置脱敏规则", + "K26d22405": "匹配值", + "K1546e1fe": "脱敏类型", + "K9b9b0629": "起始位置", + "K52c84fe1": "长度", + "Kde84409c": "替换类型", + "K338653b4": "替换值", + "Kbaeed3b7": "JSON Path", + "K4cd91d61": "脱敏规则", + "K8dcad979": "自定义字符串; 值:", + "K82e3f7b7": "起始位置:(0)位;长度:(1)位", + "K49dfc123": "已选择(0)项(1)数据", + "K8457ea34": "所有(0)", + "K7ca9a795": "属性名称", + "Kc4391744": "属性值", + "K678e13fc": "配置(0)", + "Kf5fd27ed": "输入名称查找用户" } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/newJson/zh-TW.json b/frontend/packages/common/src/locales/scan/newJson/zh-TW.json index ddcaee31..9e26dfee 100644 --- a/frontend/packages/common/src/locales/scan/newJson/zh-TW.json +++ b/frontend/packages/common/src/locales/scan/newJson/zh-TW.json @@ -1,3 +1 @@ -{ - "Kf5fd27ed": "输入名称查找用户" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/oldJson/en-US.json b/frontend/packages/common/src/locales/scan/oldJson/en-US.json index 8b7a4c95..f4755dd7 100644 --- a/frontend/packages/common/src/locales/scan/oldJson/en-US.json +++ b/frontend/packages/common/src/locales/scan/oldJson/en-US.json @@ -1,4 +1,15 @@ { + "Kc0e5ef9f": "Workspace", + "K4de11e23": "Home", + "K61c89f5f": "API Portal", + "K3fe97dcc": "System Settings", + "Kecbb0e45": "System", + "Ka358e23d": "General", + "K449058e9": "API Gateway", + "K99935e6f": "AI Model", + "K1deaa2dd": "User", + "K631d646f": "Open API", + "K1196b104": "APIPark", "Kb9052305": "Search Username, Email", "K40a89bd8": "Enter Name, ID to Search Member" } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/oldJson/ja-JP.json b/frontend/packages/common/src/locales/scan/oldJson/ja-JP.json index 552991b2..56a74a5c 100644 --- a/frontend/packages/common/src/locales/scan/oldJson/ja-JP.json +++ b/frontend/packages/common/src/locales/scan/oldJson/ja-JP.json @@ -1,5 +1,16 @@ { + "Kc0e5ef9f": "Workspace", + "K4de11e23": "Home", "Kfe93ef35": "Application", + "K61c89f5f": "API Portal", + "K3fe97dcc": "設定", + "Kecbb0e45": "システム", + "Ka358e23d": "一般", + "K449058e9": "API ゲートウェイ", + "K99935e6f": "AI モデル", + "K1deaa2dd": "ユーザー", + "K631d646f": "Open API", + "K1196b104": "APIPark", "Kffd7e274": "無審査:すべてのアプリケーションがこのサービスにサブスクライブできます", "K8a8b13e4": "手動審査:承認されたアプリケーションのみがこのサービスにサブスクライブできます", "K9bdd8403": "API を安全に呼び出すためには、アプリケーションとトークンを作成する必要があります。", diff --git a/frontend/packages/common/src/locales/scan/oldJson/zh-CN.json b/frontend/packages/common/src/locales/scan/oldJson/zh-CN.json index d2364570..502e8f18 100644 --- a/frontend/packages/common/src/locales/scan/oldJson/zh-CN.json +++ b/frontend/packages/common/src/locales/scan/oldJson/zh-CN.json @@ -1,5 +1,16 @@ { + "Kc0e5ef9f": "工作空间", + "K4de11e23": "首页", "Kfe93ef35": "消费者", + "K61c89f5f": "API 门户", + "K3fe97dcc": "系统设置", + "Kecbb0e45": "系统", + "Ka358e23d": "常规", + "K449058e9": "API 网关", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用户", + "K631d646f": "Open API", + "K1196b104": "APIPark", "Kffd7e274": "无审核:允许所有消费者订阅该服务", "K8a8b13e4": "人工审核:仅允许审核通过的消费者订阅该服务", "K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。", diff --git a/frontend/packages/common/src/locales/scan/oldJson/zh-TW.json b/frontend/packages/common/src/locales/scan/oldJson/zh-TW.json index 7ac8fd66..46e9364a 100644 --- a/frontend/packages/common/src/locales/scan/oldJson/zh-TW.json +++ b/frontend/packages/common/src/locales/scan/oldJson/zh-TW.json @@ -1,5 +1,16 @@ { + "Kc0e5ef9f": "工作區", + "K4de11e23": "主頁", "Kfe93ef35": "應用程式", + "K61c89f5f": "API 門戶", + "K3fe97dcc": "系統設置", + "Kecbb0e45": "系統", + "Ka358e23d": "常規", + "K449058e9": "API 網關", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用戶", + "K631d646f": "Open API", + "K1196b104": "APIPark", "Kffd7e274": "無審核:允許所有應用程式訂閱該服務", "K8a8b13e4": "人工審核:僅允許審核通過的應用程式訂閱該服務", "K9bdd8403": "為了安全地調用 API,你需要創建一個應用以及Token。", diff --git a/frontend/packages/common/src/locales/scan/zh-CN.json b/frontend/packages/common/src/locales/scan/zh-CN.json index 52fc73e6..5dc5f509 100644 --- a/frontend/packages/common/src/locales/scan/zh-CN.json +++ b/frontend/packages/common/src/locales/scan/zh-CN.json @@ -1,682 +1,706 @@ { - "Kc0e5ef9f": "工作空间", - "K4de11e23": "首页", - "Kfe93ef35": "消费者", - "Kb58e0c3f": "服务", - "Kc9e489f5": "团队", - "K61c89f5f": "API 门户", - "K16d71239": "分析报告", - "K714c192d": "调用统计", - "Kd57dfe97": "拓扑图", - "K3fe97dcc": "系统设置", - "Kecbb0e45": "系统", - "Ka358e23d": "常规", - "K449058e9": "API 网关", - "K99935e6f": "AI 模型", - "K1deaa2dd": "用户", - "K80a560a1": "账号", - "Kf644225f": "角色", - "K4057391a": "集成", - "K8fa58214": "数据源", - "K481e8a05": "SSL 证书", - "Kca53edd0": "日志", - "Kb283e720": "资源", - "K631d646f": "Open API", - "K6535ff9c": "账号设置", - "Kf15499b4": "退出登录", - "Kabbd6e6": "文档", - "K1196b104": "APIPark", - "K1f42de3": "HTTP 状态码", - "K4770dff4": "系统状态码", - "Kf89e58f1": "描述", - "K9e53c664": "保存", - "Kf8e7294c": "上一步", - "Ka0451c97": "取消", - "Kb1dedda3": "关闭", - "Kb2fc7600": "添加设置", - "K4e07217d": "编辑设置", - "K4ea968fe": "编辑(0)", - "Ka7aaaeb": "添加(0)", - "Kaff78ecf": "请输入Key", - "K65d46535": "请输入Value", - "Kc14b2ea3": "返回", - "K11d3633a": "ID", - "Kbff43de3": "名称", - "K16ca79ef": "驱动", - "K7a369eef": "已发布", - "Kcfa1a4d2": "下线", - "K771dc3b7": "上线", - "K530f5951": "查看", - "Kecbd7449": "删除", - "K1cbe2507": "确认", - "K48325b6": "搜索(0)名称", - "Kc6340091": "上下文", - "K74ecb1fa": "查询内容", - "K79f2e2f9": "会话历史", - "K3a8912ee": "添加变量", - "Kb291a19": "添加工具", - "K27ece71d": "AI 模型调用默认仅使用 Query 变量,可输入 “{key}” 增加新变量。", - "Kdeed8399": "固定的上游服务器", - "K4ee62e8": "该 API 缺失(0)(1)(2)请先补充", - "K385591f3": "转发信息,", - "K68415c14": "文档信息,", - "K133b75e9": "上游信息,", - "K43fcaf94": "成功", - "Kc71c6a9": "上线失败", - "K56c686f8": "失败", - "K1ff96ff": "申请系统", - "K9bf855d6": "所属团队", - "K11b994ed": "申请人", - "K939baba7": "申请时间", - "Kdab2e63b": "版本号", - "K8b29c460": "版本说明", - "K4758140d": "路由列表", - "K54e44357": "上游列表", - "Kb8e8e6f5": "备注", - "K7e52ffa3": "上线情况", - "K1ab0ae5b": "申请原因", - "K53c00c3c": "审核意见", - "Kfd50704d": "无(0)权限,请联系管理员分配。", - "K7edf331d": "时间", - "Kef45b208": "1小时", - "K9dbf22b8": "24小时", - "K820fbfab": "3天", - "Kd6d28fc": "7天", - "Ke00c858c": "上传文件", - "K6d9dd1f5": "替换文件", - "K71753476": "是否放行", - "K597435c5": "监控", - "Ke66a17dd": "必填", - "K28b68036": "字符非法,仅支持英文", - "K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)", - "Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)", - "Kdac8ce7e": "打开 OpenAPI YAML 编辑器", - "Kffd7e274": "无审核:允许所有消费者订阅该服务", - "K8a8b13e4": "人工审核:仅允许审核通过的消费者订阅该服务", - "Kbfe02d7f": "永久", - "K1e9c479e": "否", - "Kaddfcb6b": "是", - "K23fda291": "无操作权限,请联系管理员分配。", - "K4618cb0a": "微信小程序", - "Ka854f511": "获取文件,需填路径", - "Kaa11a695": "暂不支持生成非 HTTP/HTTPS 代码示例", - "Kbe46924e": "搜索编程语言...", - "Ke8e4f258": "编程语言", - "K29c07a47": "成功示例", - "K1f5c814d": "失败示例", - "K4ef022d7": "默认 text/html;charset=UTF-8", - "Kd061b5bf": "暂未填写示例", - "Kc14cec33": "Binary", - "K48b4d9e3": "请求 Header", - "Kcd347eaf": "请求 Body", - "K9e100bfe": "请求 Query", - "K3e9f12fd": "请求 REST", - "K2bfa290c": "API 请求编辑器", - "Kb36d111a": "响应 Header", - "K980bde79": "响应 Body", - "Kb04d201a": "更多设置", - "Kee74f5b4": "添加子参数", - "Kc7d3106c": "添加行", - "Keaabd222": "标签", - "K8ad2c50e": "参数名", - "K67d68dd1": "类型", - "K29245f47": "必需", - "Ke32cbcd3": "示例", - "Kc13936c6": "输入 URL 或 cURL", - "Ka1ede006": "HTTP", - "K152ac44e": "参数位置", - "K1660ae72": "匹配类型", - "K91ced765": "参数值", - "K5b265628": "操作类型", - "K1826982d": "新增或修改", - "Kd65b55f5": "匹配参数值", - "K15f35bf2": "转发上游路径", - "K79dec0dd": "请求超时时间", - "K7d465645": "绑定上游服务", - "K63a6404d": "重试时间", - "K47740727": "转发上游请求头", - "K2b605d42": "更多", - "K1df9fbd5": "导入", - "K5e85df18": "导入格式", - "K9eaf7885": "全部替换", - "Kf8c3a80b": "在最后插入", - "Kd96b2d7d": "增量更新", - "Kf2fc08eb": "请求 Header", - "Ka45f1d8": "请求 Rest 参数", - "K94bb113a": "大小", - "K359919b5": "另存为文件", - "K38bf1b90": "响应", - "K59f4186e": "响应 Header", - "K5f1e23fd": "正文", - "Kf404ef7d": "发送(Enter)", - "K2dbfd648": "中止", - "Kacabc771": "秒", - "K13ae6a93": "复制", - "Ke54a14a3": "格式化", - "K43934f6d": "搜索", - "K741decac": "替代", - "Kd507abff": "确认", - "Kca2d1624": "(0) 不能为负数.", - "K792b255a": "(0) 必须大于或等于 (1).", - "Kf0bed26d": "枚举值", - "K633a03ca": "枚举", - "Kd2766caf": "最小长度", - "Kd6d52485": "最大长度", - "Kea15f66c": "最小值", - "K1af340ff": "最大值", - "K68691e16": "拖拽文件至此处,或选择文件上传", - "Kcec46ae": "上传文件", - "K760fb044": "已选择文件", - "Kea2bdee0": "请填写接口名称", - "K49053438": "详细说明", - "K148f6fa4": "高级匹配", - "K3ae4c789": "转发设置", - "K2f4d0a37": "请求参数", - "Kde2d6dbd": "返回示例", - "K70e6069c": "测试 API", - "Ke4603448": "请求 Header", - "K89fd86b3": "请求 Body", - "K8747e3c4": "请求示例代码", - "K8613e6e7": "响应示例", - "Kab1c2159": "响应 Header", - "Kd2be51d1": "响应 Body", - "K2a3f24ac": "默认工作表", - "K7e1ab4b0": "至", - "Kf1b166e7": "详情", - "K28555332": "不支持带有双斜杠 // 的 URL", - "K71661ee8": "必填项", - "Kcbee3f8": "不是有效邮箱地址", - "K617f34f1": "更新者", - "K6ebca204": "更新时间", - "Kabfe9512": "保存", - "K51d1eb5d": "API", - "Ka2b6d281": "API 文档", - "Kdefa9caa": "说明文档", - "K36856e71": "发布", - "K6382bbfd": "订阅管理", - "K31af5b99": "审核", - "Ka97bd9e5": "订阅方", - "K5974bf24": "管理", - "K3fa5c4c3": "调用拓扑图", - "Kb5c7b82d": "设置", - "K1e84ad04": "服务 ID", - "K39ab0358": "新增订阅方", - "K18307d56": "手动添加", - "K705fe9f5": "订阅申请", - "K3a67ea90": "订阅方", - "Kefa2a4cf": "API 设置", - "K66060758": "API 名称", - "K5582ac8": "请求路径", - "K2bb86fb4": "提示词", - "K13ffbe88": "变量", - "K79c8cfaf": "接口描述", - "K469e475a": "最大重试次数", - "K8a35059b": "模型设置", - "Kf9dcef3a": "API", - "K6134bbe8": "添加 API", - "Kf85b83a0": "输入 URL 查找", - "Kcf9f90b8": "模型供应商", - "Kfede1c7c": "模型", - "Ke99513a0": "参数", - "Kb595f40": "审核", - "K54e27f57": "通过", - "K8582af3f": "拒绝", - "Kd568e15c": "发布结果", - "K35f990b0": "查看详情", - "Kdbc1f6cb": "申请发布", - "Kb6860a3f": "回滚发布", - "Ka3494f4b": "是否回滚发布?", - "Kb397a99f": "撤销申请", - "K7d401c0f": "是否撤销申请?", - "Ke1b79b93": "终止发布", - "Ka2449180": "是否终止发布?", - "K2cb02f38": "新建版本", - "Kb3e34847": "从 (0) 获取 API KEY", - "K66a7d24c": "已设置", - "Kaf074220": "未设置", - "Kd9a46c29": "默认", - "K7ac2be34": "AI 模型管理", - "K2260837a": "设置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务", - "K18dccc1a": "同步最新模型", - "K35612f29": "待审核", - "K47eaafde": "已审核", - "K56b4254f": "发布申请", - "Kea2f9279": "API 调用地址", - "K7fc496a1": "API Base URL 一般设置为 API 网关的外部网络访问地址,或者是API网关绑定的域名。", - "K8ab0fc95": "常规设置", - "Kb66fec9d": "API 请求设置", - "K4de0af74": "服务分类", - "Kb4ceecea": "添加子分类", - "K67479e88": "修改分类名称", - "K2bc75e2c": "添加分类", - "Kab4aab44": "重命名分类", - "Ke595a20a": "分类名称", - "K9679728f": "父分类 ID", - "K9b2d08fd": "子分类名称", - "K71671763": "快速接入 AI", - "Ka8a5ec5": "设置你的 AI 模型", - "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", - "Kc057704a": "创建 AI 服务和 API", - "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", - "K71b2c70f": "创建调用 Token", - "K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。", - "Kc5738b6c": "调用", - "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", - "K86cf95f": "快速接入 REST API", - "K7a3a8417": "创建 REST 服务和 API", - "K4a84214e": "统计 API 调用情况", - "K297d8563": "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。", - "K2cdbb773": "核心功能", - "K3378c50d": "账号与角色", - "Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。", - "Kc8239422": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", - "Kd5be0cd7": "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。", - "K62e89ee7": "权限管理", - "K8f7808e6": "订阅服务", - "Kf2410413": "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。", - "K6c2e44b8": "审核订阅", - "Ka0a8840a": "审核其他消费者的订阅申请,审核通过后的才可发起 API 请求。", - "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", - "Kd518ba3e": "Hello!欢迎使用 APIPark", - "K7e04ea16": "🦄 APIPark 是开源的一站式 AI 网关和 API 开发者门户,帮助企业和开发者快速接入 100+ AI 模型,将 AI 模型和 Prompt 提示词组合成新的 API,并且统一所有 AI 的请求数据格式,避免切换 AI 模型或调整提示词时影响你的 APP 消费者或者微服务。你还可以通过 APIPark 的开发者门户在团队内共享 API,管理调用的消费者并保障你的 API 安全,通过清晰的图表来监控你的 AI API 使用情况。", - "Kedd41c18": "✨ 如果你喜欢 APIPark,欢迎在 Github 为我们 Star 或提供产品反馈意见。", - "Kef02fd87": "快速入门", - "K43a3b38d": "我们提供了一些任务来帮你快速了解 APIPark", - "K408bfcf1": "进阶教程", - "K1afaf20e": "了解 APIPark 如何更好地管理 API 和 AI", - "K48f7e21f": "了解更多功能", - "K698296e2": "隐藏该教程", - "Kd2c1a316": "登录", - "Kf076f63c": "请输入账号", - "K25c895d5": "请输入密码", - "K551b0348": "密码", - "K192b3e38": "访客模式", - "K91aa4801": "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。", - "K480045ce": "Version (0)-(1)", - "Kadee8e49": "日志设置", - "K2724314b": "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", - "K33c76dbc": "部门名称", - "K84829ca9": "父部门 ID", - "K4d7fc74b": "子部门名称", - "Keb9fcdad": "用户名", - "Kc654b275": "邮箱", - "Kbe2ecc69": "部门", - "Ka16e6c44": "未激活或禁用的成员无法加入部门", - "Ked03ba97": "请选择成员需要新加入的部门", - "K184d3473": "添加账号", - "K1ecb35f2": "编辑成员信息", - "Ke6f00b44": "加入部门", - "K501cb1e7": "此操作无法恢复,确认删除成员?", - "Kf20863b5": "成员与部门", - "K52c8a730": "启用", - "K718c9310": "禁用", - "K5f27a546": "输入用户名、邮箱查找成员", - "K7c97c5df": "移出", - "K1362a512": "禁用", - "K6e1289b1": "启用", - "K1f4b5385": "删除", - "K26c698bb": "添加部门", - "Kb9cf2a7d": "添加子部门", - "Kc83551f5": "重命名", - "K5cfdd950": "该数据删除后将无法找回,是否删除?", - "K74aef1ad": "账号", - "K3f1077c9": "设置成员的角色,成员只能够看到角色权限范围内的功能和数据。", - "Kdce62a6": "搜索部门", - "Ka46b9b24": "数据源类型", - "Kbb0cdcd0": "数据源地址", - "Kd9dfb884": "Organization", - "K3e770a75": "鉴权 Token", - "K8ef69ee2": "密钥", - "Kba3507d6": "上传密钥", - "K93ac0f23": "密钥文件的后缀名一般是 .key", - "K7cdd1331": "上传证书", - "K6d91905d": "证书文件的后缀名一般是 .crt 或 .pem ", - "Kd0f6ded7": "添加证书", - "Ke5732d60": "修改证书", - "K3ca07a70": "证书管理", - "Kdb927f83": "通过为 API 服务设置和管理 SSL 证书,企业可以加密数据传输,防止敏感信息泄露。", - "Ke93d36ed": "集群", - "K877985b7": "修改设置", - "Kdf66a675": "设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。", - "Ke039b9b5": "正常", - "K23a3bd72": "异常", - "Kf12b3034": "管理地址", - "K867e6faf": "服务地址", - "K2a49373f": "同步地址", - "K5878440c": "集群地址", - "K5e9022f8": "下一步", - "Kdbafd6f9": "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。", - "K1358acf": "统计图表", - "K62dabdf6": "地址(IP:端口)", - "K2db12335": "组织", - "K8e7a0f80": "资源设置", - "K95c3fd8b": "设置角色的权限范围。", - "K138facd3": "系统角色", - "K6eac768d": "添加角色", - "Kb9c2cf02": "团队角色", - "K2a16c93b": "单位:ms,最小值:1", - "Ka945cfb1": "API 设置", - "K2e050340": "API 基础信息", - "Kba92c499": "拦截接口", - "Kde9d6e8e": "开启拦截后,网关会拦截所有该路径的请求。", - "K6bc47edb": "请求协议", - "K1365fe45": "请求方式", - "K90f3c02f": "转发规则设置", - "Kb7df6ac1": "拦截", - "K5c1722fe": "放行", - "K28435c5c": "API 详情", - "Ka9c08390": "只允许上传PNG、JPG或SVG格式的图片", - "K413b9869": "服务名称", - "K9919285b": "服务类型", - "Kcef64f4d": "默认 AI 供应商", - "Kcab588a9": "未设置任何 AI 模型供应商,", - "Kb9b56111": "立即设置", - "Kcf756b7a": "API 调用前缀", - "K13edc043": "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改", - "Kf52a584d": "所属服务分类", - "K72b21be5": "设置服务展示在服务市场中的哪个分类下", - "Kdc840242": "图标", - "K427a5bd5": "仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩", - "K44bc352d": "Logo", - "Kde6bae17": "删除服务", - "K885ea699": "删除操作不可恢复,请谨慎操作!", - "Kda8d5ea1": "上游", - "K12f58863": "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。", - "K2d6658ed": "添加服务", - "K7b8f623f": "输入名称、ID、所属团队、负责人查找服务", - "Kad98e030": "上游类型", - "Kdd9b5008": "后端默认使用的IP地址", - "Kc9acdb25": "负载均衡", - "K632dba5c": "转发 Host", - "Kc1f08a63": "重写 Host", - "K628f6851": "超时时间", - "Kaff62621": "超时重试次数", - "Kf14d159b": "次", - "Kc41ca30e": "调用频率限制", - "K753e8aeb": "次/秒", - "K813e1c0a": "团队名称", - "K692f5aa6": "团队 ID", - "K5de0bc2": "团队 ID(team_id)可用于检索团队,一旦保存无法修改。", - "Ka63dd985": "团队负责人", - "Ka6bcd272": "负责人对团队内的团队、服务、成员有管理权限", - "Ka2012bdd": "删除团队", - "Kbde1f3d": "服务数据清除后,方可删除", - "K395acc14": "移除成员", - "Kec46a57f": "添加成员", - "K48724410": "输入姓名查找", - "Kb9052305": "搜索用户名、邮箱", - "K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。", - "K510cdd27": "添加团队", - "K9244ae14": "输入名称、ID、负责人查找团队", - "Kc7b24b4b": "设置团队", - "Kecb51e2c": "旧密码", - "K8266bcf2": "新密码", - "Ka9aef039": "确认密码", - "Kcf42dcda": "两次密码不一致", - "Kf876a42d": "修改密码", - "K8ed884f": "管理个人账号", - "K9be8e1d7": "API调用统计", - "K521ab28e": "选择服务", - "Kcc8265e1": "选择API", - "Kc380335f": "路径", - "K8aefc1e4": "请输入请求路径进行搜索", - "K50d471b2": "重置", - "Kee8ae330": "查询", - "Ka2c794a2": "导出", - "Kaf70c3b": "退出全屏", - "Kd22841a4": "(0)调用详情", - "K1512e983": "消费者调用统计", - "Kb4d2007f": "请选择消费者", - "K8c7f2d2e": "调用趋势", - "K657c3452": "(0)-(1)调用趋势", - "Kc04efb87": "调用量统计", - "Keb98266e": "加入总体数据对比", - "K18c2ed46": "(0)调用量", - "Kc3741830": "(0)成功率", - "Ka6aa5863": "请求数", - "K9eaef42": "成功率", - "K7082a4af": "转发数", - "K1ce386fb": "成功率", - "K87d6877e": "4xx", - "K4c8a54db": "5xx", - "Kd566283e": "趋势", - "K21ad4a6a": "(0)报文", - "Kd23a0be6": "请求报文", - "Kec3e8361": "响应报文", - "Ke6250744": "4XX数", - "K2d79d4e1": "5XX数", - "Kcf6553c6": "服务调用统计", - "Kffcfe375": "请选择服务", - "Ka65f739c": "调用详情", - "K89b7ac79": "API Top10", - "Kc0915603": "消费者 Top10", - "Kf90b54": "服务 Top10", - "Kfb26388": "无请求数据", - "Kc8cbd8f8": "请求统计", - "K8dece48": "无转发统计数据", - "K1ee32434": "转发统计", - "Kcd125e4d": "无调用量统计数据", - "Kaa114e8b": "无报文统计数据", - "K3ad84406": "报文统计", - "Kfa088d49": "集群设置并开启监控", - "K3da3b9a0": "监控功能用于辅助管理集群内信息,请设置集群、设置监控信息后查看当前集群监控情况;", - "Kaddacfb": "集群", - "K4ac33975": "设置集群地址,以确保监控系统能够正确识别和连接到集群", - "Ke5ed9810": "设置集群", - "K1a132228": "监控", - "K6af08c3c": "设置监控", - "K4a1a14": "监控总览", - "K69741ea7": "服务调用", - "K9c8d9933": "API 调用", - "K145e4941": "亿", - "Ke6a935d": "万", - "Kd59290a2": "搜索分类或标签", - "K6b75bdbc": "无API数据", - "Kd8a7a689": "搜索或选择消费者", - "K4b15d6f5": "申请理由", - "Kb7e869a4": "消费者管理", - "Kb71b5a13": "鉴权类型", - "K4d1465ee": "ISS", - "K5dcd7ed8": "签名算法", - "K5b0eedd3": "Secret", - "K44f4ffe1": "RSA 公钥", - "Kc5ecd7d9": "用户名 JSONPath", - "K417d85cf": "校验字段", - "K3b82fe1d": "是否 Base64 加密", - "K49b5f4a3": "AK", - "K31418470": "SK", - "Kbfeb5297": "API Key", - "K1a78e6f0": "过期时间", - "Ke64e43a": "隐藏认证信息", - "K5168eb63": "消费者名称", - "K546e46f": "消费者 ID", - "K95764d1d": "删除消费者", - "K217cb125": "鉴权详情", - "K2bb63eca": "添加鉴权", - "Kd74d69b7": "编辑鉴权", - "K9cbe1e0": "修改", - "Kb6e9328f": "访问授权", - "Kd23d1716": "添加授权", - "K9dfa2c97": "永不过期", - "Kfa920c0": "过期时间", - "Kcce1af60": "订阅的服务", - "Kfefa9b58": "审核详情", - "K3118fdb0": "取消订阅", - "Ked811bb1": "是否取消订阅?", - "K50c39a62": "取消订阅申请", - "K1856c229": "是否取消订阅申请?", - "K66ea2f0": "搜索服务", - "K8adf7f8b": "审核中", - "K667bbbe7": "添加消费者", - "Ka4b45550": "无服务描述", - "K3c7b175f": "订阅服务:已通过 (0) ,审核中 (1)", - "Kbe3e9335": "退出测试", - "K370a3eb2": "服务市场", - "Kf7ec36d": "服务详情", - "K58ca9485": "申请订阅", - "K59cdbec3": "服务介绍", - "K4aa9ed2c": "申请订阅", - "K6c060779": "服务信息", - "K8723422e": "接入消费者", - "Kb97544cb": "供应方", - "Kb32f0afe": "分类", - "K81634069": "版本", - "Keefda53d": "更新时间", - "K96a2f1c8": "无标签", - "K72b0c0b3": "API 数量", - "K93d5a66e": "接入消费者数量", - "K96059c69": "关联标签", - "K8b7c2592": "更新者", - "K32263abd": "添加 Open Api", - "K7829bb78": "设置 Open Api", - "Kcdf76005": "Open Api", - "Ke2601944": "调用服务", - "K8504bca8": "放大", - "K693c1b41": "缩小", - "K3d7465f7": "文件日志", - "Kc87167a0": "HTTP 日志", - "K54630fe8": "Kafka 日志", - "Kd5c3966e": "NSQ 日志", - "K2e3de2c1": "Syslog 日志", - "K48322168": "未分配", - "K98f247f9": "超级管理员", - "K9c8a571f": "团队管理员", - "K929b485b": "运维管理员", - "K82cc5ec2": "普通成员", - "Ke41d7451": "只读成员", - "Kf99e8b66": "服务管理员", - "Kda8db57a": "服务开发者", - "K216a1ac7": "消费者开发者", - "K27924db": "消费者管理员", - "K8dc5c723": "驱动名称", - "Kda249fe8": "失败", - "Kcf2df651": "失败", - "K7e6a859d": "作用范围", - "K3a008b34": "添加条目", - "Ke0599ef7": "添加地址", - "K48d3b5c4": "文件名称", - "Kafde0d2a": "存放目录", - "Kfb2926ac": "日志分割周期", - "Kd96c2c69": "单位:天", - "Kc2b776fa": "输出格式", - "K7b7cdac2": "格式化设置", - "K2f59807a": "服务器地址", - "Kb1cfa6e7": "Access 日志", - "K540488a8": "NSQD 地址列表", - "K8bc33a11": "鉴权 Secret", - "K1cd3002f": "网络协议", - "Kdfaa32c8": "日志等级", - "Kc0408d9c": "单行", - "Ke3db239d": "小时", - "K3509a9f8": "天", - "Kb3960e83": "未发布", - "K8bd1e18": "待发布", - "K225a6c43": "单位:s,最小值:1", - "K593e0c7e": "无需审核", - "Ke2d747d9": "需要审核", - "Kc29dabf2": "Base URL", - "Kd55c6887": "审核", - "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API", - "Kefaf9956": "创建时间", - "Kad1c674c": "协议", - "Kad01bc3e": "方法", - "Ka29b346f": "地址(IP 端口或域名)", - "K63b1e0dc": "权重(0-999)", - "Ka7f8266f": "带权轮询", - "K9d7e880a": "发布版本", - "Kea996156": "发布申请记录", - "K855135f": "创建版本时间", - "Kcbf39b82": "版本状态", - "K339d15b5": "创建人", - "K7194cea2": "审核时间", - "K831aa6c0": "申请方-消费者", - "K7ad449bc": "审核状态", - "K3b3a98ce": "审核人", - "K61b62ace": "来源", - "K442937c4": "订阅时间", - "K442cfba1": "请输入", - "K3bb646e4": "请选择", - "Ka9481f95": "创建者", - "K2472615e": "服务数量", - "Kf7200cd9": "负责人", - "Kd7d84192": "姓名", - "Kc88e03b6": "团队角色", - "Ke08ff808": "添加日期", - "K19a3ebe0": "请求成功", - "Kcaa8259": "转发成功", - "K17f93984": "API 名称", - "K888f038f": "失败状态码", - "Ke792d01c": "所属服务", - "K42d2bef2": "平均响应时间(ms)", - "K9197c994": "最大响应时间(ms)", - "K7c2f3fee": "最小响应时间(ms)", - "K3d85ea54": "平均请求流量(KB)", - "Keec09d32": "最大请求流量(KB)", - "K3786b48": "最小请求流量(KB)", - "Kdf35c48c": "所有成员", - "K759fb403": "状态", - "K5c123bad": "角色名称", - "K2c5882be": "绑定域名", - "K1cc07937": "过期日期", - "K39686a7f": "支持字母开头、英文数字中横线下划线组合", - "Ka4ecfa40": "英文数字下划线任意一种,首字母必须为英文", - "K37318b68": "无法连接集群,请检查集群地址是否正确或防火墙配置", - "Kac172626": "拒绝申请时,请填写拒绝理由", - "K7f0c746d": "成功", - "K6a365d01": "失败", - "K978062b6": "正在操作", - "Kca7bd6d4": "正在加载数据", - "K3c93b77e": "获取数据失败", - "Ke108c369": "登录成功", - "K9168d3e": "退出成功,将跳转至登录页", - "K2f8a7ab7": "未填写审核意见", - "Kb858d78a": "复制成功", - "K26e85d15": "复制失败,请手动复制", - "Kd60d204": "服务所属团队", - "K823bfe63": "在线", - "Kc9315fa1": "已拒绝", - "K3fbe7511": "发布异常", - "Ke64e695c": "发布中", - "K1f89176d": "申请方所属团队", - "K69827c60": "发布状态", - "K8f7abcab": "次", - "K28cf9613": "每分钟", - "K18f25019": "每5分钟", - "Kf00f01ca": "每小时", - "Kfcda87fc": "每天", - "K29ec75dc": "每周", - "Ke1b1865": "私有", - "K4786c57c": "公共", - "K7acfcfad": "消费者", - "Kc8054dba": "消费者开发者", - "Keb1673a6": "消费者管理员", - "K1fc2cc28": "无需审核:允许任何消费者调用该服务", - "K8dabb98e": "人工审核:仅允许通过人工审核的消费者调用该服务", - "K7c1fb123": "申请方-消费者", - "Kdea9a418": "为了安全地调用 API,你需要创建一个消费者以及Token。", - "Keee27105": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", - "Kaa717866": "提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。", - "Kd2c34e2c": "AI 服务", - "K62840d62": "REST 服务", - "K4c72fb6f": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。", - "K61cca533": "消费者调用统计", - "Kdfff59d4": "请选择消费者", - "K386857bd": "消费者调用量 Top10", - "Kb684c806": "搜索或选择消费者", - "Ke0fbd1c8": "消费者管理", - "K67b530f": "消费者名称", - "K11f34de": "消费者 ID", - "Kc01002": "删除消费者", - "K84c4dc71": "添加消费者", - "K5c4e2865": "创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务", - "K40a89bd8": "输入名称、ID 查找服务", - "Kba74f26d": "接入消费者", - "K70b79760": "接入消费者数量", + "Kc0e5ef9f": "工作空间", + "K4de11e23": "首页", + "Kfe93ef35": "消费者", + "Kb58e0c3f": "服务", + "Kc9e489f5": "团队", + "K61c89f5f": "API 门户", + "K16d71239": "分析报告", + "K714c192d": "调用统计", + "Kd57dfe97": "拓扑图", + "K3fe97dcc": "系统设置", + "Kecbb0e45": "系统", + "Ka358e23d": "常规", + "K449058e9": "API 网关", + "K99935e6f": "AI 模型", + "K1deaa2dd": "用户", + "K80a560a1": "账号", + "Kf644225f": "角色", + "K4057391a": "集成", + "K8fa58214": "数据源", + "K481e8a05": "SSL 证书", + "Kca53edd0": "日志", + "Kb283e720": "资源", + "K631d646f": "Open API", + "K6535ff9c": "账号设置", + "Kf15499b4": "退出登录", + "Kabbd6e6": "文档", + "K1196b104": "APIPark", + "K1f42de3": "HTTP 状态码", + "K4770dff4": "系统状态码", + "Kf89e58f1": "描述", + "K9e53c664": "保存", + "Kf8e7294c": "上一步", + "Ka0451c97": "取消", + "Kb1dedda3": "关闭", + "Kb2fc7600": "添加设置", + "K4e07217d": "编辑设置", + "K4ea968fe": "编辑(0)", + "Ka7aaaeb": "添加(0)", + "Kaff78ecf": "请输入Key", + "K65d46535": "请输入Value", + "Kc14b2ea3": "返回", + "K11d3633a": "ID", + "Kbff43de3": "名称", + "K16ca79ef": "驱动", + "K7a369eef": "已发布", + "Kcfa1a4d2": "下线", + "K771dc3b7": "上线", + "K530f5951": "查看", + "Kecbd7449": "删除", + "K1cbe2507": "确认", + "K48325b6": "搜索(0)名称", + "Kc6340091": "上下文", + "K74ecb1fa": "查询内容", + "K79f2e2f9": "会话历史", + "K3a8912ee": "添加变量", + "Kb291a19": "添加工具", + "K27ece71d": "AI 模型调用默认仅使用 Query 变量,可输入 “{key}” 增加新变量。", + "Kdeed8399": "固定的上游服务器", + "K4ee62e8": "该 API 缺失(0)(1)(2)请先补充", + "K385591f3": "转发信息,", + "K68415c14": "文档信息,", + "K133b75e9": "上游信息,", + "K43fcaf94": "成功", + "Kc71c6a9": "上线失败", + "K56c686f8": "失败", + "K1ff96ff": "申请系统", + "K9bf855d6": "所属团队", + "K11b994ed": "申请人", + "K939baba7": "申请时间", + "Kdab2e63b": "版本号", + "K8b29c460": "版本说明", + "K4758140d": "路由列表", + "K54e44357": "上游列表", + "Kb8e8e6f5": "备注", + "K7e52ffa3": "上线情况", + "K1ab0ae5b": "申请原因", + "K53c00c3c": "审核意见", + "Kfd50704d": "无(0)权限,请联系管理员分配。", + "K7edf331d": "时间", + "Kef45b208": "1小时", + "K9dbf22b8": "24小时", + "K820fbfab": "3天", + "Kd6d28fc": "7天", + "Ke00c858c": "上传文件", + "K6d9dd1f5": "替换文件", + "K71753476": "是否放行", + "K597435c5": "监控", + "Ke66a17dd": "必填", + "K28b68036": "字符非法,仅支持英文", + "K6206e4ad": "上传 OpenAPI 文档 (.json/.yaml)", + "Kfba46e6d": "替换 OpenAPI 文档 (.json/.yaml)", + "Kdac8ce7e": "打开 OpenAPI YAML 编辑器", + "Kffd7e274": "无审核:允许所有消费者订阅该服务", + "K8a8b13e4": "人工审核:仅允许审核通过的消费者订阅该服务", + "Kbfe02d7f": "永久", + "K1e9c479e": "否", + "Kaddfcb6b": "是", + "K23fda291": "无操作权限,请联系管理员分配。", + "K4618cb0a": "微信小程序", + "Ka854f511": "获取文件,需填路径", + "Kaa11a695": "暂不支持生成非 HTTP/HTTPS 代码示例", + "Kbe46924e": "搜索编程语言...", + "Ke8e4f258": "编程语言", + "K29c07a47": "成功示例", + "K1f5c814d": "失败示例", + "K4ef022d7": "默认 text/html;charset=UTF-8", + "Kd061b5bf": "暂未填写示例", + "Kc14cec33": "Binary", + "K48b4d9e3": "请求 Header", + "Kcd347eaf": "请求 Body", + "K9e100bfe": "请求 Query", + "K3e9f12fd": "请求 REST", + "K2bfa290c": "API 请求编辑器", + "Kb36d111a": "响应 Header", + "K980bde79": "响应 Body", + "Kb04d201a": "更多设置", + "Kee74f5b4": "添加子参数", + "Kc7d3106c": "添加行", + "Keaabd222": "标签", + "K8ad2c50e": "参数名", + "K67d68dd1": "类型", + "K29245f47": "必需", + "Ke32cbcd3": "示例", + "Kc13936c6": "输入 URL 或 cURL", + "Ka1ede006": "HTTP", + "K152ac44e": "参数位置", + "K1660ae72": "匹配类型", + "K91ced765": "参数值", + "K5b265628": "操作类型", + "K1826982d": "新增或修改", + "Kd65b55f5": "匹配参数值", + "K15f35bf2": "转发上游路径", + "K79dec0dd": "请求超时时间", + "K7d465645": "绑定上游服务", + "K63a6404d": "重试时间", + "K47740727": "转发上游请求头", + "K2b605d42": "更多", + "K1df9fbd5": "导入", + "K5e85df18": "导入格式", + "K9eaf7885": "全部替换", + "Kf8c3a80b": "在最后插入", + "Kd96b2d7d": "增量更新", + "Kf2fc08eb": "请求 Header", + "Ka45f1d8": "请求 Rest 参数", + "K94bb113a": "大小", + "K359919b5": "另存为文件", + "K38bf1b90": "响应", + "K59f4186e": "响应 Header", + "K5f1e23fd": "正文", + "Kf404ef7d": "发送(Enter)", + "K2dbfd648": "中止", + "Kacabc771": "秒", + "K13ae6a93": "复制", + "Ke54a14a3": "格式化", + "K43934f6d": "搜索", + "K741decac": "替代", + "Kd507abff": "确认", + "Kca2d1624": "(0) 不能为负数.", + "K792b255a": "(0) 必须大于或等于 (1).", + "Kf0bed26d": "枚举值", + "K633a03ca": "枚举", + "Kd2766caf": "最小长度", + "Kd6d52485": "最大长度", + "Kea15f66c": "最小值", + "K1af340ff": "最大值", + "K68691e16": "拖拽文件至此处,或选择文件上传", + "Kcec46ae": "上传文件", + "K760fb044": "已选择文件", + "Kea2bdee0": "请填写接口名称", + "K49053438": "详细说明", + "K148f6fa4": "高级匹配", + "K3ae4c789": "转发设置", + "K2f4d0a37": "请求参数", + "Kde2d6dbd": "返回示例", + "K70e6069c": "测试 API", + "Ke4603448": "请求 Header", + "K89fd86b3": "请求 Body", + "K8747e3c4": "请求示例代码", + "K8613e6e7": "响应示例", + "Kab1c2159": "响应 Header", + "Kd2be51d1": "响应 Body", + "K2a3f24ac": "默认工作表", + "K7e1ab4b0": "至", + "Kf1b166e7": "详情", + "K28555332": "不支持带有双斜杠 // 的 URL", + "K71661ee8": "必填项", + "Kcbee3f8": "不是有效邮箱地址", + "K617f34f1": "更新者", + "K6ebca204": "更新时间", + "Kabfe9512": "保存", + "K51d1eb5d": "API", + "Ka2b6d281": "API 文档", + "Kdefa9caa": "说明文档", + "K36856e71": "发布", + "K6382bbfd": "订阅管理", + "K31af5b99": "审核", + "Ka97bd9e5": "订阅方", + "K5974bf24": "管理", + "K3fa5c4c3": "调用拓扑图", + "Kb5c7b82d": "设置", + "K1e84ad04": "服务 ID", + "K39ab0358": "新增订阅方", + "K18307d56": "手动添加", + "K705fe9f5": "订阅申请", + "K3a67ea90": "订阅方", + "Kefa2a4cf": "API 设置", + "K66060758": "API 名称", + "K5582ac8": "请求路径", + "K2bb86fb4": "提示词", + "K13ffbe88": "变量", + "K79c8cfaf": "接口描述", + "K469e475a": "最大重试次数", + "K8a35059b": "模型设置", + "Kf9dcef3a": "API", + "K6134bbe8": "添加 API", + "Kf85b83a0": "输入 URL 查找", + "Kcf9f90b8": "模型供应商", + "Kfede1c7c": "模型", + "Ke99513a0": "参数", + "Kb595f40": "审核", + "K54e27f57": "通过", + "K8582af3f": "拒绝", + "Kd568e15c": "发布结果", + "K35f990b0": "查看详情", + "Kdbc1f6cb": "申请发布", + "Kb6860a3f": "回滚发布", + "Ka3494f4b": "是否回滚发布?", + "Kb397a99f": "撤销申请", + "K7d401c0f": "是否撤销申请?", + "Ke1b79b93": "终止发布", + "Ka2449180": "是否终止发布?", + "K2cb02f38": "新建版本", + "Kb3e34847": "从 (0) 获取 API KEY", + "K66a7d24c": "已设置", + "Kaf074220": "未设置", + "Kd9a46c29": "默认", + "K7ac2be34": "AI 模型管理", + "K2260837a": "设置好 AI 模型后,你可以使用对应的大模型来创建 AI 服务", + "K18dccc1a": "同步最新模型", + "K35612f29": "待审核", + "K47eaafde": "已审核", + "K56b4254f": "发布申请", + "Kea2f9279": "API 调用地址", + "K7fc496a1": "API Base URL 一般设置为 API 网关的外部网络访问地址,或者是API网关绑定的域名。", + "K8ab0fc95": "常规设置", + "Kb66fec9d": "API 请求设置", + "K4de0af74": "服务分类", + "Kb4ceecea": "添加子分类", + "K67479e88": "修改分类名称", + "K2bc75e2c": "添加分类", + "Kab4aab44": "重命名分类", + "Ke595a20a": "分类名称", + "K9679728f": "父分类 ID", + "K9b2d08fd": "子分类名称", + "K71671763": "快速接入 AI", + "Ka8a5ec5": "设置你的 AI 模型", + "K10d7e99f": "通过 APIPark 快速接入各种 AI 模型,使用统一的格式来调用API,并且可以随意切换模型。", + "Kc057704a": "创建 AI 服务和 API", + "K76bb4a09": "创建 AI 类型的服务,并且你可以将 Prompt 提示词设置为一个 API,简化使用 AI 的流程。", + "K71b2c70f": "创建调用 Token", + "K9bdd8403": "为了安全地调用 API,你需要创建一个消费者以及Token。", + "Kc5738b6c": "调用", + "Kd6d7ca1f": "现在你可以通过 Token 来调用这些 API。", + "K86cf95f": "快速接入 REST API", + "K7a3a8417": "创建 REST 服务和 API", + "K4a84214e": "统计 API 调用情况", + "K297d8563": "仪表盘中提供了多种统计图表,帮助我们了解 API 的运行情况。", + "K2cdbb773": "核心功能", + "K3378c50d": "账号与角色", + "Kda5bb930": "邀请你的团队成员加入 APIPark,共同管理和调用 API。", + "Kc8239422": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", + "Kd5be0cd7": "服务内包含一组 API,并且可以发布到 API 市场被其他团队使用。", + "K62e89ee7": "权限管理", + "K8f7808e6": "订阅服务", + "Kf2410413": "如果需要调用某个服务的 API,需要先订阅该服务,并且等待提供服务的团队审核后才可发起 API 请求。", + "K6c2e44b8": "审核订阅", + "Ka0a8840a": "审核其他消费者的订阅申请,审核通过后的才可发起 API 请求。", + "K3453272": "APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "Kd518ba3e": "Hello!欢迎使用 APIPark", + "K7e04ea16": "🦄 APIPark 是开源的一站式 AI 网关和 API 开发者门户,帮助企业和开发者快速接入 100+ AI 模型,将 AI 模型和 Prompt 提示词组合成新的 API,并且统一所有 AI 的请求数据格式,避免切换 AI 模型或调整提示词时影响你的 APP 消费者或者微服务。你还可以通过 APIPark 的开发者门户在团队内共享 API,管理调用的消费者并保障你的 API 安全,通过清晰的图表来监控你的 AI API 使用情况。", + "Kedd41c18": "✨ 如果你喜欢 APIPark,欢迎在 Github 为我们 Star 或提供产品反馈意见。", + "Kef02fd87": "快速入门", + "K43a3b38d": "我们提供了一些任务来帮你快速了解 APIPark", + "K408bfcf1": "进阶教程", + "K1afaf20e": "了解 APIPark 如何更好地管理 API 和 AI", + "K48f7e21f": "了解更多功能", + "K698296e2": "隐藏该教程", + "Kd2c1a316": "登录", + "Kf076f63c": "请输入账号", + "K25c895d5": "请输入密码", + "K551b0348": "密码", + "K192b3e38": "访客模式", + "K91aa4801": "您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。", + "K480045ce": "Version (0)-(1)", + "Kadee8e49": "日志设置", + "K2724314b": "提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。", + "K33c76dbc": "部门名称", + "K84829ca9": "父部门 ID", + "K4d7fc74b": "子部门名称", + "Keb9fcdad": "用户名", + "Kc654b275": "邮箱", + "Kbe2ecc69": "部门", + "Ka16e6c44": "未激活或禁用的成员无法加入部门", + "Ked03ba97": "请选择成员需要新加入的部门", + "K184d3473": "添加账号", + "K1ecb35f2": "编辑成员信息", + "Ke6f00b44": "加入部门", + "K501cb1e7": "此操作无法恢复,确认删除成员?", + "Kf20863b5": "成员与部门", + "K52c8a730": "启用", + "K718c9310": "禁用", + "K5f27a546": "输入用户名、邮箱查找成员", + "K7c97c5df": "移出", + "K1362a512": "禁用", + "K6e1289b1": "启用", + "K1f4b5385": "删除", + "K26c698bb": "添加部门", + "Kb9cf2a7d": "添加子部门", + "Kc83551f5": "重命名", + "K5cfdd950": "该数据删除后将无法找回,是否删除?", + "K74aef1ad": "账号", + "K3f1077c9": "设置成员的角色,成员只能够看到角色权限范围内的功能和数据。", + "Kdce62a6": "搜索部门", + "Ka46b9b24": "数据源类型", + "Kbb0cdcd0": "数据源地址", + "Kd9dfb884": "Organization", + "K3e770a75": "鉴权 Token", + "K8ef69ee2": "密钥", + "Kba3507d6": "上传密钥", + "K93ac0f23": "密钥文件的后缀名一般是 .key", + "K7cdd1331": "上传证书", + "K6d91905d": "证书文件的后缀名一般是 .crt 或 .pem ", + "Kd0f6ded7": "添加证书", + "Ke5732d60": "修改证书", + "K3ca07a70": "证书管理", + "Kdb927f83": "通过为 API 服务设置和管理 SSL 证书,企业可以加密数据传输,防止敏感信息泄露。", + "Ke93d36ed": "集群", + "K877985b7": "修改设置", + "Kdf66a675": "设置访问 API 的集群,让 API 在分布式环境中稳定运行,并且能够根据业务需求进行灵活扩展和优化。", + "Ke039b9b5": "正常", + "K23a3bd72": "异常", + "Kf12b3034": "管理地址", + "K867e6faf": "服务地址", + "K2a49373f": "同步地址", + "K5878440c": "集群地址", + "K5e9022f8": "下一步", + "Kdbafd6f9": "设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。", + "K1358acf": "统计图表", + "K62dabdf6": "地址(IP:端口)", + "K2db12335": "组织", + "K8e7a0f80": "资源设置", + "K95c3fd8b": "设置角色的权限范围。", + "K138facd3": "系统角色", + "K6eac768d": "添加角色", + "Kb9c2cf02": "团队角色", + "K2a16c93b": "单位:ms,最小值:1", + "Ka945cfb1": "API 设置", + "K2e050340": "API 基础信息", + "Kba92c499": "拦截接口", + "Kde9d6e8e": "开启拦截后,网关会拦截所有该路径的请求。", + "K6bc47edb": "请求协议", + "K1365fe45": "请求方式", + "K90f3c02f": "转发规则设置", + "Kb7df6ac1": "拦截", + "K5c1722fe": "放行", + "K28435c5c": "API 详情", + "Ka9c08390": "只允许上传PNG、JPG或SVG格式的图片", + "K413b9869": "服务名称", + "K9919285b": "服务类型", + "Kcef64f4d": "默认 AI 供应商", + "Kcab588a9": "未设置任何 AI 模型供应商,", + "Kb9b56111": "立即设置", + "Kcf756b7a": "API 调用前缀", + "K13edc043": "作为服务内所有API的前缀,比如host/{service_name}/{api_path},一旦保存无法修改", + "Kf52a584d": "所属服务分类", + "K72b21be5": "设置服务展示在服务市场中的哪个分类下", + "Kdc840242": "图标", + "K427a5bd5": "仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩", + "K44bc352d": "Logo", + "Kde6bae17": "删除服务", + "K885ea699": "删除操作不可恢复,请谨慎操作!", + "Kda8d5ea1": "上游", + "K12f58863": "服务提供了高性能 API 网关,并且可以无缝接入多种大型 AI 模型,并将这些 AI 能力打包成 API 进行调用,从而大幅简化了 AI 模型的使用门槛。同时,我们的平台提供了完善的 API 管理功能,支持 API 的创建、监控、访问控制等,保障开发者可以高效、安全地开发和管理 API 服务。", + "K2d6658ed": "添加服务", + "K7b8f623f": "输入名称、ID、所属团队、负责人查找服务", + "Kad98e030": "上游类型", + "Kdd9b5008": "后端默认使用的IP地址", + "Kc9acdb25": "负载均衡", + "K632dba5c": "转发 Host", + "Kc1f08a63": "重写 Host", + "K628f6851": "超时时间", + "Kaff62621": "超时重试次数", + "Kf14d159b": "次", + "Kc41ca30e": "调用频率限制", + "K753e8aeb": "次/秒", + "K813e1c0a": "团队名称", + "K692f5aa6": "团队 ID", + "K5de0bc2": "团队 ID(team_id)可用于检索团队,一旦保存无法修改。", + "Ka63dd985": "团队负责人", + "Ka6bcd272": "负责人对团队内的团队、服务、成员有管理权限", + "Ka2012bdd": "删除团队", + "Kbde1f3d": "服务数据清除后,方可删除", + "K395acc14": "移除成员", + "Kec46a57f": "添加成员", + "K48724410": "输入姓名查找", + "Kb9052305": "搜索用户名、邮箱", + "K5ece3bac": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。", + "K510cdd27": "添加团队", + "K9244ae14": "输入名称、ID、负责人查找团队", + "Kc7b24b4b": "设置团队", + "Kecb51e2c": "旧密码", + "K8266bcf2": "新密码", + "Ka9aef039": "确认密码", + "Kcf42dcda": "两次密码不一致", + "Kf876a42d": "修改密码", + "K8ed884f": "管理个人账号", + "K9be8e1d7": "API调用统计", + "K521ab28e": "选择服务", + "Kcc8265e1": "选择API", + "Kc380335f": "路径", + "K8aefc1e4": "请输入请求路径进行搜索", + "K50d471b2": "重置", + "Kee8ae330": "查询", + "Ka2c794a2": "导出", + "Kaf70c3b": "退出全屏", + "Kd22841a4": "(0)调用详情", + "K1512e983": "消费者调用统计", + "Kb4d2007f": "请选择消费者", + "K8c7f2d2e": "调用趋势", + "K657c3452": "(0)-(1)调用趋势", + "Kc04efb87": "调用量统计", + "Keb98266e": "加入总体数据对比", + "K18c2ed46": "(0)调用量", + "Kc3741830": "(0)成功率", + "Ka6aa5863": "请求数", + "K9eaef42": "成功率", + "K7082a4af": "转发数", + "K1ce386fb": "成功率", + "K87d6877e": "4xx", + "K4c8a54db": "5xx", + "Kd566283e": "趋势", + "K21ad4a6a": "(0)报文", + "Kd23a0be6": "请求报文", + "Kec3e8361": "响应报文", + "Ke6250744": "4XX数", + "K2d79d4e1": "5XX数", + "Kcf6553c6": "服务调用统计", + "Kffcfe375": "请选择服务", + "Ka65f739c": "调用详情", + "K89b7ac79": "API Top10", + "Kc0915603": "消费者 Top10", + "Kf90b54": "服务 Top10", + "Kfb26388": "无请求数据", + "Kc8cbd8f8": "请求统计", + "K8dece48": "无转发统计数据", + "K1ee32434": "转发统计", + "Kcd125e4d": "无调用量统计数据", + "Kaa114e8b": "无报文统计数据", + "K3ad84406": "报文统计", + "Kfa088d49": "集群设置并开启监控", + "K3da3b9a0": "监控功能用于辅助管理集群内信息,请设置集群、设置监控信息后查看当前集群监控情况;", + "Kaddacfb": "集群", + "K4ac33975": "设置集群地址,以确保监控系统能够正确识别和连接到集群", + "Ke5ed9810": "设置集群", + "K1a132228": "监控", + "K6af08c3c": "设置监控", + "K4a1a14": "监控总览", + "K69741ea7": "服务调用", + "K9c8d9933": "API 调用", + "K145e4941": "亿", + "Ke6a935d": "万", + "Kd59290a2": "搜索分类或标签", + "K6b75bdbc": "无API数据", + "Kd8a7a689": "搜索或选择消费者", + "K4b15d6f5": "申请理由", + "Kb7e869a4": "消费者管理", + "Kb71b5a13": "鉴权类型", + "K4d1465ee": "ISS", + "K5dcd7ed8": "签名算法", + "K5b0eedd3": "Secret", + "K44f4ffe1": "RSA 公钥", + "Kc5ecd7d9": "用户名 JSONPath", + "K417d85cf": "校验字段", + "K3b82fe1d": "是否 Base64 加密", + "K49b5f4a3": "AK", + "K31418470": "SK", + "Kbfeb5297": "API Key", + "K1a78e6f0": "过期时间", + "Ke64e43a": "隐藏认证信息", + "K5168eb63": "消费者名称", + "K546e46f": "消费者 ID", + "K95764d1d": "删除消费者", + "K217cb125": "鉴权详情", + "K2bb63eca": "添加鉴权", + "Kd74d69b7": "编辑鉴权", + "K9cbe1e0": "修改", + "Kb6e9328f": "访问授权", + "Kd23d1716": "添加授权", + "K9dfa2c97": "永不过期", + "Kfa920c0": "过期时间", + "Kcce1af60": "订阅的服务", + "Kfefa9b58": "审核详情", + "K3118fdb0": "取消订阅", + "Ked811bb1": "是否取消订阅?", + "K50c39a62": "取消订阅申请", + "K1856c229": "是否取消订阅申请?", + "K66ea2f0": "搜索服务", + "K8adf7f8b": "审核中", + "K667bbbe7": "添加消费者", + "Ka4b45550": "无服务描述", + "K3c7b175f": "订阅服务:已通过 (0) ,审核中 (1)", + "Kbe3e9335": "退出测试", + "K370a3eb2": "服务市场", + "Kf7ec36d": "服务详情", + "K58ca9485": "申请订阅", + "K59cdbec3": "服务介绍", + "K4aa9ed2c": "申请订阅", + "K6c060779": "服务信息", + "K8723422e": "接入消费者", + "Kb97544cb": "供应方", + "Kb32f0afe": "分类", + "K81634069": "版本", + "Keefda53d": "更新时间", + "K96a2f1c8": "无标签", + "K72b0c0b3": "API 数量", + "K93d5a66e": "接入消费者数量", + "K96059c69": "关联标签", + "K8b7c2592": "更新者", + "K32263abd": "添加 Open Api", + "K7829bb78": "设置 Open Api", + "Kcdf76005": "Open Api", + "Ke2601944": "调用服务", + "K8504bca8": "放大", + "K693c1b41": "缩小", + "K3d7465f7": "文件日志", + "Kc87167a0": "HTTP 日志", + "K54630fe8": "Kafka 日志", + "Kd5c3966e": "NSQ 日志", + "K2e3de2c1": "Syslog 日志", + "K48322168": "未分配", + "K98f247f9": "超级管理员", + "K9c8a571f": "团队管理员", + "K929b485b": "运维管理员", + "K82cc5ec2": "普通成员", + "Ke41d7451": "只读成员", + "Kf99e8b66": "服务管理员", + "Kda8db57a": "服务开发者", + "K216a1ac7": "消费者开发者", + "K27924db": "消费者管理员", + "K8dc5c723": "驱动名称", + "Kda249fe8": "失败", + "Kcf2df651": "失败", + "K7e6a859d": "作用范围", + "K3a008b34": "添加条目", + "Ke0599ef7": "添加地址", + "K48d3b5c4": "文件名称", + "Kafde0d2a": "存放目录", + "Kfb2926ac": "日志分割周期", + "Kd96c2c69": "单位:天", + "Kc2b776fa": "输出格式", + "K7b7cdac2": "格式化设置", + "K2f59807a": "服务器地址", + "Kb1cfa6e7": "Access 日志", + "K540488a8": "NSQD 地址列表", + "K8bc33a11": "鉴权 Secret", + "K1cd3002f": "网络协议", + "Kdfaa32c8": "日志等级", + "Kc0408d9c": "单行", + "Ke3db239d": "小时", + "K3509a9f8": "天", + "Kb3960e83": "未发布", + "K8bd1e18": "待发布", + "K225a6c43": "单位:s,最小值:1", + "K593e0c7e": "无需审核", + "Ke2d747d9": "需要审核", + "Kc29dabf2": "Base URL", + "Kd55c6887": "审核", + "K300c89d4": "创建 API 时会默认选择该供应商,修改默认供应商不会影响现有 API", + "Kefaf9956": "创建时间", + "Kad1c674c": "协议", + "Kad01bc3e": "方法", + "Ka29b346f": "地址(IP 端口或域名)", + "K63b1e0dc": "权重(0-999)", + "Ka7f8266f": "带权轮询", + "K9d7e880a": "发布版本", + "Kea996156": "发布申请记录", + "K855135f": "创建版本时间", + "Kcbf39b82": "版本状态", + "K339d15b5": "创建人", + "K7194cea2": "审核时间", + "K831aa6c0": "申请方-消费者", + "K7ad449bc": "审核状态", + "K3b3a98ce": "审核人", + "K61b62ace": "来源", + "K442937c4": "订阅时间", + "K442cfba1": "请输入", + "K3bb646e4": "请选择", + "Ka9481f95": "创建者", + "K2472615e": "服务数量", + "Kf7200cd9": "负责人", + "Kd7d84192": "姓名", + "Kc88e03b6": "团队角色", + "Ke08ff808": "添加日期", + "K19a3ebe0": "请求成功", + "Kcaa8259": "转发成功", + "K17f93984": "API 名称", + "K888f038f": "失败状态码", + "Ke792d01c": "所属服务", + "K42d2bef2": "平均响应时间(ms)", + "K9197c994": "最大响应时间(ms)", + "K7c2f3fee": "最小响应时间(ms)", + "K3d85ea54": "平均请求流量(KB)", + "Keec09d32": "最大请求流量(KB)", + "K3786b48": "最小请求流量(KB)", + "Kdf35c48c": "所有成员", + "K759fb403": "状态", + "K5c123bad": "角色名称", + "K2c5882be": "绑定域名", + "K1cc07937": "过期日期", + "K39686a7f": "支持字母开头、英文数字中横线下划线组合", + "Ka4ecfa40": "英文数字下划线任意一种,首字母必须为英文", + "K37318b68": "无法连接集群,请检查集群地址是否正确或防火墙配置", + "Kac172626": "拒绝申请时,请填写拒绝理由", + "K7f0c746d": "成功", + "K6a365d01": "失败", + "K978062b6": "正在操作", + "Kca7bd6d4": "正在加载数据", + "K3c93b77e": "获取数据失败", + "Ke108c369": "登录成功", + "K9168d3e": "退出成功,将跳转至登录页", + "K2f8a7ab7": "未填写审核意见", + "Kb858d78a": "复制成功", + "K26e85d15": "复制失败,请手动复制", + "Kd60d204": "服务所属团队", + "K823bfe63": "在线", + "Kc9315fa1": "已拒绝", + "K3fbe7511": "发布异常", + "Ke64e695c": "发布中", + "K1f89176d": "申请方所属团队", + "K69827c60": "发布状态", + "K8f7abcab": "次", + "K28cf9613": "每分钟", + "K18f25019": "每5分钟", + "Kf00f01ca": "每小时", + "Kfcda87fc": "每天", + "K29ec75dc": "每周", + "Ke1b1865": "私有", + "K4786c57c": "公共", + "K7acfcfad": "消费者", + "Kc8054dba": "消费者开发者", + "Keb1673a6": "消费者管理员", + "K1fc2cc28": "无需审核:允许任何消费者调用该服务", + "K8dabb98e": "人工审核:仅允许通过人工审核的消费者调用该服务", + "K7c1fb123": "申请方-消费者", + "Kdea9a418": "为了安全地调用 API,你需要创建一个消费者以及Token。", + "Keee27105": "团队中包含了人员、消费者和服务,不同团队之间的消费者和服务数据是隔离的,可用于管理企业内部不同的部门/项目组/团队。", + "Kaa717866": "提供服务的团队可以审核来自其他团队的订阅申请,审核通过后的消费者才可发起 API 请求。", + "Kd2c34e2c": "AI 服务", + "K62840d62": "REST 服务", + "K4c72fb6f": "设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。", + "K61cca533": "消费者调用统计", + "Kdfff59d4": "请选择消费者", + "K386857bd": "消费者调用量 Top10", + "Kb684c806": "搜索或选择消费者", + "Ke0fbd1c8": "消费者管理", + "K67b530f": "消费者名称", + "K11f34de": "消费者 ID", + "Kc01002": "删除消费者", + "K84c4dc71": "添加消费者", + "K5c4e2865": "创建并管理自己的消费者实体,每个消费者可以订阅多个API服务,确保在调用之前已获得相应权限。你可以为消费者生成 API 密钥等鉴权方式,用于安全地调用 API 服务", + "K40a89bd8": "输入名称、ID 查找服务", + "Kba74f26d": "接入消费者", + "K70b79760": "接入消费者数量", "K93c2696e": "上线结果", "K6e32a344": "订阅服务数量", "Ka701316": "鉴权数量", "K9eaa2eb6": "列表", "Kfaec39e9": "块", "Kc3b7bfa8": "暂无消费者描述", - "K3a6f905d": "输入名称、ID 查找消费者" + "K3a6f905d": "输入名称、ID 查找消费者", + "K2ec0fa56": "支持把当前服务对接主流的 AI Agent平台,实现在 Agent 平台上快速、安全和合规地使用企业开放的 API 能力。", + "K35f23b64": "可按以下步骤进行对接:", + "Kf5cd608b": "步骤一:Agent 平台上创建自定义插件", + "K4c81c7b6": "不同 Agent 平台的操作细节可查看", + "K275f7ffa": "《 Agent 对接手册》", + "K49b81d06": "步骤二:导入 API 文档数据", + "K4a3b62be": "可通过以下 URL 或 下载 Json 文件,导入 API 文档数据到 Agent 平台中。", + "K42697e11": "复制 URL", + "K27a809c5": "下载 Json 文件", + "K1e61fdee": "步骤三:配置 API 密钥", + "K55912595": "在", + "K33b1bc3": "菜单中,选择已通过本 API 服务申请的消费者,", + "K62adc41e": "把 \"访问权限\" 菜单下的密钥填入到 Agent 平台对应的插件密钥配置中。", + "Ke8cbb878": "全局策略", + "K34d0d409": "添加策略", + "Kbb4298ac": "输入名称、筛选条件查找", + "Kabac9caf": "数据脱敏", + "Kc975cd5a": "支持对系统全局进行统一的策略配置,从而简化管理并确保一致性。全局策略的优先级比服务策略略低。", + "K52f72551": "服务策略", + "K931615d7": "策略名称", + "K31faa2a1": "优先级", + "Kbdec9fa": "筛选条件", + "Kbcbb7391": "处理数", + "Kad207008": "编辑" } \ No newline at end of file diff --git a/frontend/packages/common/src/locales/scan/zh-TW.json b/frontend/packages/common/src/locales/scan/zh-TW.json index 72373d12..6c5787a9 100644 --- a/frontend/packages/common/src/locales/scan/zh-TW.json +++ b/frontend/packages/common/src/locales/scan/zh-TW.json @@ -701,5 +701,70 @@ "Kc8ee3e62": "不存在匹配", "K1e97dbd8": "存在匹配", "Kec91f0db": "申請方消費者", - "Kf5fd27ed": "輸入名稱查找使用者" + "Kf5fd27ed": "輸入名稱查找使用者", + "K2ec0fa56": "支援將當前服務對接主流的 AI Agent 平台,實現在 Agent 平台上快速、安全和合規地使用企業開放的 API 能力。", + "K35f23b64": "可按以下步驟進行對接:", + "Kf5cd608b": "步驟一:Agent 平台上創建自定義插件", + "K4c81c7b6": "不同 Agent 平台的操作細節可查看", + "K275f7ffa": "《 Agent 對接手冊》", + "K49b81d06": "步驟二:導入 API 文檔數據", + "K4a3b62be": "可通過以下 URL 或下載 json 文件,導入 API 文檔數據到 Agent 平台中。", + "K42697e11": "複製 URL", + "K27a809c5": "下載 Json 文件", + "K1e61fdee": "步驟三:配置 API 密鑰", + "K55912595": "在", + "K33b1bc3": "菜單中,選擇已通過本 API 服務申請的消費者,", + "K62adc41e": "把「訪問權限」菜單下的密鑰填入到 Agent 平台對應的插件密鑰配置中。", + "Ke8cbb878": "全域策略", + "K34d0d409": "新增策略", + "Kbb4298ac": "輸入名稱、篩選條件查找", + "Kabac9caf": "資料脫敏", + "Kc975cd5a": "支援對系統全域進行統一的策略配置,從而簡化管理並確保一致性。全域策略的優先級比服務策略略低。", + "K52f72551": "服務策略", + "K931615d7": "策略名稱", + "K31faa2a1": "優先級", + "Kbdec9fa": "篩選條件", + "Kbcbb7391": "處理數", + "Kad207008": "編輯", + "K630c9e6d": "APIPark", + "Ka3e9f580": "發布名稱", + "Kb2480682": "策略列表", + "K118d8d74": "數據格式", + "Kfe7c7d2d": "關鍵字", + "K2f57a694": "正則表達式", + "K8953e0a6": "手機號碼", + "K6f86a038": "身份證號碼", + "K7954e7c8": "銀行卡號碼", + "K320fdb17": "金額", + "K7867acda": "日期", + "K7d327ae8": "局部顯示", + "Kfbf38e3c": "局部遮蔽", + "Kd8c1fbb0": "截取", + "K89829921": "替換", + "K480a7165": "亂序", + "Kea0d69df": "隨機字串", + "Ke7c84d1d": "自訂字串", + "K49731763": "請輸入IP地址或CIDR範圍,每行以換行符分隔", + "K83237c89": "輸入的IP或CIDR格式不正確", + "K5ae2c87a": "請正確輸入路徑,例如/usr/*或*/usr/*", + "Kc82b8374": "編輯策略", + "K4b34a5e5": "策略類型", + "K57f0fee8": "匹配條件", + "K10650c58": "數據脫敏規則", + "K1b34a9ab": "配置脫敏規則", + "K26d22405": "匹配值", + "K1546e1fe": "脫敏類型", + "K9b9b0629": "起始位置", + "K52c84fe1": "長度", + "Kde84409c": "替換類型", + "K338653b4": "替換值", + "Kbaeed3b7": "JSON路徑", + "K4cd91d61": "脫敏規則", + "K8dcad979": "自訂字串; 值:", + "K82e3f7b7": "起始位置:(0)位;長度:(1)位", + "K49dfc123": "已選擇(0)項(1)數據", + "K8457ea34": "所有(0)", + "K7ca9a795": "屬性名稱", + "Kc4391744": "屬性值", + "K678e13fc": "配置(0)" } diff --git a/frontend/packages/common/src/utils/navigation.tsx b/frontend/packages/common/src/utils/navigation.tsx index 1e48c7c4..5c4df895 100644 --- a/frontend/packages/common/src/utils/navigation.tsx +++ b/frontend/packages/common/src/utils/navigation.tsx @@ -1,25 +1,34 @@ +import { Icon } from "@iconify/react/dist/iconify.js"; import { MenuProps } from "antd"; export type MenuItem = Required['items'][number]; -export function getNavItem( - label: React.ReactNode, - key: React.Key, - path:string, - icon?: React.ReactNode, - children?: MenuItem[], - type?: 'group', - access?:string[] | string -): MenuItem { +export function getNavItem({ + label, + key, + path, + icon, + children, + type, + access +}: { + label: React.ReactNode; + key: React.Key; + path?: string; + icon?: React.ReactNode; + children?: MenuItem[]; + type?: 'group'; + access?: string[] | string; +}): MenuItem { return { key, - icon :icon , - path, + icon, routes:children, name:label, type, - access + access, + path } as MenuItem; } @@ -53,4 +62,19 @@ export function getItem( label, access } - } \ No newline at end of file + } + + +export function transformMenuData(data: any[]): MenuItem[] { + return data.map(item => { + const { name, key, path, icon, children, access } = item; + return getNavItem({ + label:name, + key, + path, + icon: icon ? : undefined, + children:children ? transformMenuData(children) : undefined, + access} + ); + }); +} \ No newline at end of file diff --git a/frontend/packages/common/src/utils/plugin.tsx b/frontend/packages/common/src/utils/plugin.tsx new file mode 100644 index 00000000..db23aafc --- /dev/null +++ b/frontend/packages/common/src/utils/plugin.tsx @@ -0,0 +1,154 @@ +import { CoreObj, PluginConfigType, PluginRouterConfig, RouteConfig, RouterMapConfig } from '@common/const/type'; +import { isFunction } from 'lodash-es' +// @ts-expect-error module cannot find +import { __federation_method_setRemote,__federation_method_getRemote,__federation_method_unwrapDefault } from 'virtual:__federation__'; +import { ApiparkPluginDriverType } from '@common/const/type'; +import React from 'react'; + +interface RemoteModuleConfig{ + type:string + remoteEntry:string + exposedModule:string + remoteName:string +} + +export async function loadRemoteModule(remoteModuleConfig:RemoteModuleConfig){ + __federation_method_setRemote(remoteModuleConfig.remoteName, { + url: () => Promise.resolve(remoteModuleConfig.remoteEntry), + format: 'esm', + from: 'vite', + }); + return await __federation_method_getRemote( + remoteModuleConfig.remoteName, + `./${remoteModuleConfig.exposedModule}` + ) +} + +export function generateRemoteModuleTemplate( + pluginName: string, + exposedModule: string, + pluginPath: string +):RemoteModuleConfig { + return { + type: 'module', + remoteEntry: pluginPath, + exposedModule, + remoteName: pluginName + } +} + +/** check the lifecycle method of plugin */ +export function validateExportLifecycle(exports: unknown) { + const { bootstrap, mount, unmount } = exports ?? {} + return isFunction(bootstrap) && isFunction(mount) && isFunction(unmount) +} + +export const DEFAULT_LOCAL_PLUGIN_PATH = '/plugin-frontend/' + +export const ApiparkPluginDriver = (routerMap: Map): ApiparkPluginDriverType => { return { + builtIn: { + component: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => { + if(!coreObj || !pluginConfig) return coreObj + for (const pluginRouter of pluginConfig.router) { + routerMap.get(pluginConfig.name) && coreObj.pluginProvider.setRouterConfig(pluginRouter.type === 'root' , { + ...routerMap.get(pluginConfig.name)!, + key:pluginConfig.name, + path:pluginRouter.path}) + } + return coreObj + } + }, + remote: { + normal: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => { + if(!coreObj || !pluginConfig) return coreObj + const routerToChanged:RouteConfig[] = coreObj.routerConfig.find((router: RouteConfig) => router.path === '/' && router?.pathMatch !== 'full')!.children as RouteConfig[] + const remoteRouter:RouteConfig[] = routerToChanged.find((item:RouteConfig) => item?.data?.['type'] === 'remotePlugin') as RouteConfig[] + if (!remoteRouter) { + routerMap.get('remote') && coreObj.pluginProvider.setRouterConfig(false,{ + ...routerMap.get('remote')!, key:'remote', path:'remote',type:'remotePlugin',children:[{ + path:':moduleName', + component: routerMap.get('remote')!.component} + ] + }) + } + return coreObj + } + }, + intelligent: { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + normal: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => { + if(!coreObj || !pluginConfig) return coreObj + if(['logsettings','resourcesettings'].indexOf(pluginConfig.name) !== -1){ + const routerToChanged:RouteConfig[] = coreObj.routerConfig.find((router: RouteConfig) => router.path === '/' && router?.pathMatch !== 'full')!.children as RouteConfig[] + const remoteRouter:RouteConfig[] = routerToChanged.find((item:RouteConfig) => item?.data?.['key'] === pluginConfig.name) as RouteConfig[] + if(!remoteRouter){ + routerMap.get(pluginConfig.name) && routerToChanged.unshift({...routerMap.get(pluginConfig.name)!, key:pluginConfig.name, path:pluginConfig.path}) + } + return + } + const remoteRouter = coreObj.routerConfig.find((item:RouteConfig) => item?.data?.['type'] === 'intelligentPlugin') + if (!remoteRouter) { + // coreObj.pluginProvider.setRouterConfig(false, { + // path: 'template', + // loadChildren: coreObj.builtInPluginLoader('intelligent'), + // data: { + // type: 'intelligentPlugin' + // } + // }, coreObj.routerConfig) + } + return coreObj + } + }, + local: { + router: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => { + if(!coreObj || !pluginConfig) return coreObj + for (const pluginRouter of pluginConfig.router) { + if (pluginRouter.type === 'sub') { + continue + } + updateRouterConfigWithPlugin(coreObj, pluginRouter, pluginConfig) + } + return coreObj + }, + preload: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => { + if(!coreObj || !pluginConfig) return coreObj + coreObj.setExecuteList(prev=>[...prev,{ ...pluginConfig, expose: 'Bootstrap', bootstrap: 'BootstrapModule.bootstrap' }]) + for (const pluginRouter of pluginConfig.router) { + updateRouterConfigWithPlugin(coreObj, pluginRouter, pluginConfig) + } + return coreObj + } + // extender: (coreObj?:CoreObj, pluginConfig?:PluginConfigType) => {} + } +} +} +async function updateRouterConfigWithPlugin (coreObj: CoreObj, pluginRouter: PluginRouterConfig, pluginConfig: PluginConfigType) { + if (!pluginRouter.expose) { + throw new Error('pluginRouter.expose is required') + } else { + for (const pluginRouter of pluginConfig.router) { + const loadedModule = await coreObj.pluginLoader.loadModule( + pluginRouter.path, + pluginConfig.name, + pluginRouter.expose!, + pluginConfig.path || `${DEFAULT_LOCAL_PLUGIN_PATH}${pluginConfig.name}/apipark.js` + ) + const loadedModulePage = loadedModule[pluginRouter.expose!] + const LazyComponent = React.lazy(() => Promise.resolve({ default: loadedModulePage?.default || loadedModulePage })); + + const newRouter: RouteConfig = { + path: pluginRouter.path, + key: pluginConfig.name, + lazy: () => Promise.resolve({ default: (props: any) => }), + pathPrefix: pluginRouter.path.endsWith('/*') ? pluginRouter.path.slice(0, -2) : pluginRouter.path, + lifecycle:{ + canActivate: loadedModule?.beforeMount, + canLoad: loadedModule?.mount, + canDeactivate: loadedModule?.beforeUnmount, + deactivated: loadedModule?.unmount + } + }; + coreObj.pluginProvider.setRouterConfig(pluginRouter.type === 'root' , newRouter) + } + } +} diff --git a/frontend/packages/common/src/utils/validate.ts b/frontend/packages/common/src/utils/validate.ts index e0a63f5e..ca780fc4 100644 --- a/frontend/packages/common/src/utils/validate.ts +++ b/frontend/packages/common/src/utils/validate.ts @@ -4,5 +4,38 @@ export const validateUrlSlash = (_, value) => { if (value && value.includes('//')) { return Promise.reject(new Error($t('暂不支持带有双斜杠//的url'))); } + return Promise.resolve(); + }; + + export const validateIPorCIDR = (rule, value) => { + if (!value) { + return Promise.resolve(); + } + + const lines = value.split('\n'); + const ipCidrRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[1-2][0-9]|3[0-2]))?$/; + + for (const line of lines) { + if (line && !ipCidrRegex.test(line.trim())) { + return Promise.reject($t('输入的IP或CIDR不符合格式')); + } + } + + return Promise.resolve(); + }; + + + export const validateApiPath = (rule, value) => { + if (!value) { + return Promise.resolve(); + } + + const invalidCharsRegex = /[^a-zA-Z0-9\-\/\*]/; + const validPathRegex = /^(\/?\*?\/?[a-zA-Z0-9\-\/\*]*)$/; + + if (value && (invalidCharsRegex.test(value.trim()) || !validPathRegex.test(value.trim()))) { + return Promise.reject($t('请正确输入路径,如/usr/*或*/usr/*')); + } + return Promise.resolve(); }; \ No newline at end of file diff --git a/frontend/packages/core/src/App.css b/frontend/packages/core/src/App.css index dbc2b579..e5f6c0b2 100644 --- a/frontend/packages/core/src/App.css +++ b/frontend/packages/core/src/App.css @@ -299,4 +299,11 @@ a{ a[disabled]:hover { color: #BBB; cursor: not-allowed; + } + + .ant-input-group-addon{ + height:32px !important; + .ant-btn.ant-btn-default{ + height:32px !important; + } } \ No newline at end of file diff --git a/frontend/packages/core/src/App.tsx b/frontend/packages/core/src/App.tsx index 9e5f751b..34f176a8 100644 --- a/frontend/packages/core/src/App.tsx +++ b/frontend/packages/core/src/App.tsx @@ -1,30 +1,16 @@ import './App.css' -import { ConfigProvider, ConfigProviderProps, Radio, RadioChangeEvent } from 'antd'; +import { ConfigProvider, App as AppAntd } from 'antd'; import RenderRoutes from '@core/components/aoplatform/RenderRoutes'; import {BreadcrumbProvider} from "@common/contexts/BreadcrumbContext.tsx"; -import { StyleProvider } from '@ant-design/cssinjs'; -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 useInitializeMonaco from "@common/hooks/useInitializeMonaco"; -import { useEffect, useMemo, useState } from 'react'; -import 'dayjs/locale/zh-cn'; -import 'dayjs/locale/zh-tw'; -import 'dayjs/locale/ja'; -import dayjs from 'dayjs'; -import { useGlobalContext } from '@common/contexts/GlobalStateContext'; +import { useMemo } from 'react'; +import { GlobalProvider } from '@common/contexts/GlobalStateContext'; import { $t } from '@common/locales'; - -type Locale = ConfigProviderProps['locale']; - -const languageMap: Record = { - 'zh-CN':zhCN, - 'en-US':enUS, - 'zh-TW':zhTW, - 'ja-JP':jaJP -} +import { PluginEventHubProvider } from '@common/contexts/PluginEventHubContext'; +import { PluginSlotHubProvider } from '@common/contexts/PluginSlotHubContext'; +import { useLocaleContext } from '@common/contexts/LocaleContext'; +import { StyleProvider } from '@ant-design/cssinjs'; const antdComponentThemeToken = { @@ -150,33 +136,35 @@ const antdComponentThemeToken = { function App() { - const [locale, setLocal] = useState(); + const { locale } = useLocaleContext(); useInitializeMonaco() - const { state} = useGlobalContext() - - useEffect(() => { - dayjs.locale(state.language); - setLocal(languageMap[state.language]); - },[state.language]) const validateMessages = useMemo(()=>({ required: $t('必填项'), email:$t('不是有效邮箱地址')} - ),[state.language]) + ),[locale]) return ( - - - - - - - + + + + + + + + + + + + + + + ); } diff --git a/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx b/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx index ad5635b1..29ae48b1 100644 --- a/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx +++ b/frontend/packages/core/src/components/aoplatform/RenderRoutes.tsx @@ -1,572 +1,92 @@ -import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom'; -import Login from "@core/pages/Login.tsx" +import { Navigate, RouterProvider, createBrowserRouter, RouteObject } from 'react-router-dom'; 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 {createElement,Suspense, useEffect, useState} from 'react'; +import {Skeleton, Spin} from "antd"; import {useGlobalContext} from "@common/contexts/GlobalStateContext.tsx"; -import {FC,lazy} from 'react'; -import { TeamProvider } from '@core/contexts/TeamContext.tsx'; -import { TenantManagementProvider } from '@market/contexts/TenantManagementContext.tsx'; -import Guide from '@core/pages/guide/Guide'; -import { AiServiceProvider } from '@core/contexts/AiServiceContext'; -import AiServiceOutlet from '@core/pages/aiService/AiServiceOutlet'; -import SystemOutlet from '@core/pages/system/SystemOutlet'; -import { SystemProvider } from '@core/contexts/SystemContext'; - -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 - routeId:string -} - -const PUBLIC_ROUTES:RouteConfig[] = [ - { - path:'/', - component:, - key: uuidv4(), - }, - { - path:'/login', - component:, - key: uuidv4() - }, - { - path:'/', - component:, - key: uuidv4(), - children:[ - // { - // path:'approval/*', - // component:, - // key:uuidv4() - // }, - { - path:'guide/*', - component:, - key:uuidv4() - }, - { - path:'team', - component:, - key: uuidv4(), - provider: TeamProvider, - children:[ - { - path:'', - key: uuidv4(), - component: - }, - { - 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', - key: uuidv4(), - component:, - provider: SystemProvider, - children:[ - { - path:'', - key:uuidv4(), - component: - }, - { - 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:, - 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:'route/create', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), - }, - { - - path:'route/:routeId', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), - }, - { - path:'route', - 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:'aiInside/:serviceId', - component:, - provider: AiServiceProvider, - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsidePage.tsx')), - children:[ - { - path:'api', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideApiDocument')), - }, - { - - path:'route/create', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), - }, - { - - path:'route/:routeId', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), - }, - { - path:'route', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterList')), - }, - { - path:'document', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideDocument.tsx')), - }, - { - path:'subscriber', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideSubscriber.tsx')), - children:[ - - ] - }, - { - path:'approval', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApproval')), - children:[ - { - path:'', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), - }, - { - path:'*', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), - } - ] - }, - { - path:'publish', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublish')), - children:[ - { - path:'', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), - }, - { - path:'*', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), - } - ] - }, - { - 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:'aisetting', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiSetting/AiSettingList.tsx')), - }, - { - path:'cert', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCert.tsx')), - }, - { - path:'serviceHub', - component:, - key:uuidv4(), - children:[ - { - path:'', - key: uuidv4(), - component: - }, - { - 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:, - provider:TenantManagementProvider, - key:uuidv4(), - children:[ - { - path:'', - key:uuidv4(), - component: - }, - { - 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: - }, - { - 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:, - children:[ - { - path: '', - key: uuidv4(), - component: - }, - { - path:'list', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleList.tsx')), - },{ - path:':roleType/config/:roleId', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), - },{ - path:':roleType/config', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), - } - ] - }, - { - path:'assets', - component:

设计中

, - key:uuidv4() - }, - { - path:'analytics', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/Dashboard.tsx')), - key:uuidv4(), - children:[ - { - path:'total', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardTotal.tsx')), - }, - ] - }, - { - path:'template/:moduleId', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/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() - }] - } - ] - }, -] +import usePluginLoader from '@common/hooks/pluginLoader.ts'; +import { RouteConfig } from '@common/const/type.ts'; +import { ApiparkPluginDriver } from '@common/utils/plugin.tsx'; +import { routerMap } from '@core/const/const'; +import withRouteGuard from "@common/components/aoplatform/WithRouteGuard.tsx"; +import ErrorBoundary from "@common/components/aoplatform/ErrorBoundary"; +import React from 'react'; +import { LoadingOutlined } from '@ant-design/icons'; const RenderRoutes = ()=> { + const { loadPlugins,loadExecutedPlugin } = usePluginLoader(ApiparkPluginDriver(routerMap), routerMap) + const { routeConfig } = useGlobalContext(); + const [router, setRouter] = useState(null); + + useEffect(()=>{ + loadPlugins().then(()=>{ + loadExecutedPlugin() + }) + },[]) + + useEffect(() => { + if (routeConfig && routeConfig.length > 0) { + const routerInstance = createBrowserRouter(generateRoutes(routeConfig)); + setRouter(routerInstance); + } + }, [routeConfig]); + + if (!router) { + return } spinning={true} className='w-full h-full flex items-center justify-center'>; + } + return ( - - - - {generateRoutes(PUBLIC_ROUTES)} - - - - ) + + ); } -const generateRoutes = (routerConfig: RouteConfig[]) => { +const generateRoutes = (routerConfig: RouteConfig[]):RouteObject[] => { return routerConfig?.map((route: RouteConfig) => { let routeElement; if (route.lazy) { - const LazyComponent = route.lazy as React.ExoticComponent; - + let LazyComponent; + if (typeof route.lazy === 'function') { + const result = route.lazy(); + if (result instanceof Promise) { + LazyComponent = React.lazy(() => result.then(module => ({ default: module.default || module }))); + } else { + LazyComponent = result; + } + } else { + LazyComponent = route.lazy; + } + const GuardedComponent = route.lifecycle ? withRouteGuard(LazyComponent, {pathPrefix:`/${route.pathPrefix ?? route.path}`, ...route.lifecycle}): LazyComponent routeElement = ( }> {route.provider ? ( - createElement(route.provider, {}, ) + createElement(route.provider, {}, ) ) : ( - + )} ); } else { routeElement = route.provider ? ( - createElement(route.provider, {}, route.component) + createElement(route.provider, {}, route.component) ) : ( route.component ); } return ( - - {route.children && generateRoutes(route.children as RouteConfig[])} - + { + path: route.path, + element: {routeElement} , + children: route.children ? generateRoutes(route.children as RouteConfig[]) : undefined,} ); } ) } // 保护的路由组件 -function ProtectedRoute() { +export function ProtectedRoute() { const {state} = useGlobalContext() return state.isAuthenticated? : ; } -export default RenderRoutes \ No newline at end of file +export default RenderRoutes diff --git a/frontend/packages/core/src/const/const.tsx b/frontend/packages/core/src/const/const.tsx new file mode 100644 index 00000000..5a937d28 --- /dev/null +++ b/frontend/packages/core/src/const/const.tsx @@ -0,0 +1,493 @@ +import { RouterMapConfig } from '@common/const/type'; +import { ProtectedRoute } from '@core/components/aoplatform/RenderRoutes'; +import { AiServiceProvider } from '@core/contexts/AiServiceContext'; +import { SystemProvider } from '@core/contexts/SystemContext'; +import { TeamProvider } from '@core/contexts/TeamContext'; +import AiServiceOutlet from '@core/pages/aiService/AiServiceOutlet'; +import Guide from '@core/pages/guide/Guide'; +import Login from '@core/pages/Login'; +import SystemOutlet from '@core/pages/system/SystemOutlet'; +import { TenantManagementProvider } from '@market/contexts/TenantManagementContext'; +import { lazy } from 'react'; +import { Outlet, Navigate } from 'react-router-dom'; + + + // 内置插件与对应组件/模块 + export const routerMap:Map = new Map([ + ['basicLayout', { type: 'component', component: }], + ['navHidden', { type: 'component', component: }], + ['login', { type: 'component', component: }], + ['guide',{ + type:'component', + component: + }], + ['team', {type: 'module', + component:, + key: 'team', + provider: TeamProvider, + children:[ + { + path:'', + key: 'teamList', + component: + }, + { + path:'list', + key: 'teamList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamList.tsx')) + }, + { + path:'inside/:teamId', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsidePage.tsx')), + key: 'teamInside', + children:[ + { + path:'member', + key: 'teamMember', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsideMember.tsx')), + }, + { + path:'setting', + key: 'teamSetting', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamConfig.tsx')), + }, + ] + } + ] + }], + ['service', { + type: 'module', + path:'service', + component:, + key: 'service', + provider: SystemProvider, + children:[ + { + path:'', + key:'serviceList', + component: + }, + { + path:'list', + key: 'serviceList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')), + }, + { + path:'list/:teamId', + key: 'serviceList3', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')), + }, + { + path:':teamId', + component:, + key: 'serviceInside', + children:[ + { + path:'inside/:serviceId', + key: 'restServiceInside', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsidePage.tsx')), + children:[ + { + path:'api', + key: 'restServiceInsideApi', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideApiDocument.tsx')), + }, + { + + path:'route/create', + key: 'restServiceInsideRouteCreate', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), + }, + { + + path:'route/:routeId', + key: 'restServiceInsideRouteEdit', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterCreate')), + }, + { + path:'route', + key: 'restServiceInsideRoute', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/api/SystemInsideRouterList')), + }, + { + path:'upstream', + key: 'restServiceInsideUpstream', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/upstream/SystemInsideUpstreamContent.tsx')), + }, + { + path:'document', + key: 'restServiceInsideDocument', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideDocument.tsx')), + }, + { + path:'subscriber', + key: 'restServiceInsideSubscriber', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideSubscriber.tsx')), + children:[ + + ] + }, + { + path:'approval', + key: 'restServiceInsideApproval', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApproval.tsx')), + children:[ + { + path:'', + key: 'restServiceInsideApprovalList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApprovalList.tsx')), + }, + { + path:'*', + key: 'restServiceInsideApprovalList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApprovalList.tsx')), + } + ] + }, + { + path:'publish', + key: 'systemPublish', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublish.tsx')), + children:[ + { + path:'', + key: 'systemPublishList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublishList.tsx')), + }, + { + path:'*', + key: 'systemPublishList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublishList.tsx')), + } + ] + }, + { + path:'setting', + key: 'systemConfig', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemConfig.tsx')), + children:[ + + ] + }, + { + path:'servicepolicy', + key: 'servicePolicy', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/ServicePolicy')), + children:[ + + ] + }, + ] + }, + { + path:'aiInside/:serviceId', + component:, + provider: AiServiceProvider, + key: 'aiServiceInside', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsidePage.tsx')), + children:[ + { + path:'api', + key: 'aiServiceInsideApi', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideApiDocument')), + }, + { + + path:'route/create', + key: 'aiServiceInsideRouteCreate', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), + }, + { + + path:'route/:routeId', + key: 'aiServiceInsideRouteEdit', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterCreate')), + }, + { + path:'route', + key: 'aiServiceInsideRouteList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/api/AiServiceInsideRouterList')), + }, + { + path:'document', + key: 'aiServiceInsideDocument', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideDocument.tsx')), + }, + { + path:'subscriber', + key: 'aiServiceInsideSubscriber', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/AiServiceInsideSubscriber.tsx')), + children:[ + + ] + }, + { + path:'approval', + key: 'aiServiceInsideApproval', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApproval')), + children:[ + { + path:'', + key: 'aiServiceInsideApprovalList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), + }, + { + path:'*', + key: 'aiServiceInsideApprovalList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/approval/AiServiceInsideApprovalList')), + } + ] + }, + { + path:'publish', + key: 'aiServiceInsidePublish', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublish')), + children:[ + { + path:'', + key: 'aiServiceInsidePublishList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), + }, + { + path:'*', + key: 'aiServiceInsidePublishList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiService/publish/AiServiceInsidePublishList')), + } + ] + }, + { + path:'setting', + key: 'aiServiceInsideSetting', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemConfig.tsx')), + children:[ + + ] + }, + { + path:'servicepolicy', + key: 'servicePolicy', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/ServicePolicy')), + children:[ + + ] + }, + ] + } + ] + } + ] + }], + ['datasourcing', { type: 'component', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideDashboardSetting.tsx')) + }], + ['cluster', { type: 'component', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCluster.tsx')), + }], + ['aisetting', { type: 'component', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/aiSetting/AiSettingList.tsx')), + }], + ['cert', { type: 'component', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCert.tsx')), + }], + + ['serviceHub', { + type: 'module', + component:, + key:'serviceHub', + children:[ + { + path:'', + key: 'serviceHubList', + component: + }, + { + path:'list', + key:'serviceHubList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/ServiceHubList.tsx')), + }, + { + path:'detail/:serviceId', + key:'serviceHubDetail', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/ServiceHubDetail.tsx')), + }] + }], + + ['commonsetting', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/common/CommonPage.tsx')), + }], + + ['consumer', { type: 'module', + component:, + provider:TenantManagementProvider, + key:'consumer', + children:[ + { + path:'', + key:'consumerList', + component: + }, + { + path:':teamId/inside/:appId', + key:'consumerInside', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsidePage.tsx')), + children:[ + { + path:'service', + key:'consumerInsideService', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsideService.tsx')), + }, + { + path:'authorization', + key:'consumerInsideAuthorization', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsideAuth.tsx')), + }, + { + path:'setting', + key:'consumerSetting', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementAppSetting.tsx')), + }, + ] + }, + { + path:'list', + key:'serviceHubManagementList', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ServiceHubManagement.tsx')), + }, + { + path:'list/:teamId', + key:'serviceHubManagementList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ServiceHubManagement.tsx')), + }, + ]}], + ['member', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberPage.tsx')), + children:[ + { + path:'', + key:'memberList', + component: + }, + { + path:'list', + key:'memberList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberList.tsx')), + }, + { + path:'list/:memberGroupId', + key:'memberList3', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberList.tsx')), + } + ], + }], + ['role', { type: 'module', + component:, + children:[ + { + path: '', + key: 'roleList', + component: + }, + { + path:'list', + key:'roleList2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleList.tsx')), + }, + { + path:':roleType/config/:roleId', + key:'roleConfig', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), + }, + { + path:':roleType/config', + key:'roleConfig2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), + } + ] + }], + ['analytics', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/Dashboard.tsx')), + key:'analytics', + children:[ + { + path:'total', + key:'analytics2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardTotal.tsx')), + }, + { + path:':dashboardType', + key:'analytics3', + component:, + children:[ + { + path:'list', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardList.tsx')), + key:'analyticsList' + }, + { + path:'detail/:dashboardDetailId', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardDetail.tsx')), + key:'analyticsDetail' + }, + ] + } + ] + }], + ['template', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')), + }], + ['logsettings', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/logsettings/LogSettings.tsx')), + key:'logsettings', + children:[ + { + path:'template/:moduleId', + key:'logSettings2', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')), + }, + ] + }], + ['resourcesettings', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/resourcesettings/ResourceSettings.tsx')), + key:'resourcesettings', + children:[ + { + path:'template/:moduleId', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')), + key:'resourceSettings2' + }, + ] + }], + ['userProfile', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/UserProfile.tsx')), + key:'userProfile', + children:[{ + path:'changepsw', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/ChangePsw.tsx')), + key:'changePsw' + }]}], + ['globalPolicy', { type: 'module', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/GlobalPolicyLayout')), + key:'globalPolicy', + children:[{ + path:'datamasking', + component:, + key:'dataMasking', + children:[ + { + path:'list', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/GlobalPolicy')), + key:'dataMaskingList' + }, + { + path:'create', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/dataMasking/DataMaskingConfig')), + key:'dataMaskingAdd' + }, + { + path:':policyId', + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/policy/dataMasking/DataMaskingConfig')), + key:'dataMaskingAdd' + }] + }] + }], + ]) \ No newline at end of file diff --git a/frontend/packages/core/src/const/system/const.tsx b/frontend/packages/core/src/const/system/const.tsx index 19d329a2..36711421 100644 --- a/frontend/packages/core/src/const/system/const.tsx +++ b/frontend/packages/core/src/const/system/const.tsx @@ -3,9 +3,10 @@ import { Input, TabsProps } from "antd"; import { MatchItem } from "@common/const/type"; import { ConfigField } from "@common/components/aoplatform/EditableTableWithModal"; import { frontendTimeSorter } from "@common/utils/dataTransfer"; -import { COLUMNS_TITLE } from "@common/const/const"; +import { COLUMNS_TITLE, PLACEHOLDER } from "@common/const/const"; import { PageProColumns } from "@common/components/aoplatform/PageList"; +import { $t } from "@common/locales"; export enum SubscribeEnum{ Rejected = 0, @@ -222,7 +223,7 @@ export const MATCH_CONFIG:ConfigField[] = [ }, { title:('参数名'), key: 'key', - component: , + component: , renderText: (value: unknown) => value, required: true }, { @@ -236,7 +237,7 @@ export const MATCH_CONFIG:ConfigField[] = [ title:('参数值'), key: 'pattern', unRender:(formValue)=>{return formValue?.matchType === 'NULL' || formValue?.matchType==='EXIST' || formValue?.matchType === 'UNEXIST'}, - component: , + component: , renderText: (value: string) => { return value }, diff --git a/frontend/packages/core/src/contexts/PartitionContext.tsx b/frontend/packages/core/src/contexts/PartitionContext.tsx deleted file mode 100644 index 2782ae2b..00000000 --- a/frontend/packages/core/src/contexts/PartitionContext.tsx +++ /dev/null @@ -1,23 +0,0 @@ - -import {FC, createContext, useContext, useState, ReactNode } from 'react'; -import { PartitionConfigFieldType } from '../const/partitions/types.ts'; - -interface PartitionContextProps { - partitionInfo:PartitionConfigFieldType|undefined - setPartitionInfo:React.Dispatch>; -} - -const PartitionContext = createContext(undefined); - -export const usePartitionContext = () => { - const context = useContext(PartitionContext); - if (!context) { - throw new Error('useArray must be used within a ArrayProvider'); - } - return context; -}; - -export const PartitionProvider: FC<{ children: ReactNode }> = ({ children }) => { - const [partitionInfo, setPartitionInfo] = useState() - return {children}; -}; \ No newline at end of file diff --git a/frontend/packages/core/src/contexts/SystemMyServiceContext.tsx b/frontend/packages/core/src/contexts/SystemMyServiceContext.tsx deleted file mode 100644 index ffc4b34e..00000000 --- a/frontend/packages/core/src/contexts/SystemMyServiceContext.tsx +++ /dev/null @@ -1,23 +0,0 @@ - -import { createContext, useContext, useState, ReactNode, FC } from 'react'; -import { MyServiceFieldType } from '../const/system/type.ts'; - -interface SystemMyServiceContextProps { - serviceInfo:MyServiceFieldType|undefined - setServiceInfo:React.Dispatch>; -} - -const SystemMyServiceContext = createContext(undefined); - -export const useSystemMyServiceContext = () => { - const context = useContext(SystemMyServiceContext); - if (!context) { - throw new Error('useArray must be used within a ArrayProvider'); - } - return context; -}; - -export const SystemMyServiceProvider: FC<{ children: ReactNode }> = ({ children }) => { - const [serviceInfo, setServiceInfo] = useState() - return {children}; -}; \ No newline at end of file diff --git a/frontend/packages/core/src/index.css b/frontend/packages/core/src/index.css index acb3395d..dcfb7383 100644 --- a/frontend/packages/core/src/index.css +++ b/frontend/packages/core/src/index.css @@ -321,6 +321,11 @@ p{ } } +.ant-table-body { + scrollbar-width: auto; + scrollbar-color: auto; +} + ::-webkit-scrollbar { width: 10px; @@ -664,7 +669,7 @@ p{ .ant-pro-table-list-toolbar-setting-items{ position:absolute; top:18px; - right:16px; + right:22px; z-index:9; .ant-pro-table-list-toolbar-setting-item{ font-size:14px; @@ -1005,6 +1010,19 @@ p{ } } +.global-policy-tabs { + .ant-tabs-nav { + &::before { + border-bottom: none; + } + } + .ant-tabs-content { + height: 100%; + .ant-tabs-tabpane { + height: 100%; + } + } +} .ant-tooltip{ max-width: 280px !important; diff --git a/frontend/packages/core/src/main.tsx b/frontend/packages/core/src/main.tsx index 7d71bc81..6aa026a9 100644 --- a/frontend/packages/core/src/main.tsx +++ b/frontend/packages/core/src/main.tsx @@ -3,8 +3,7 @@ import {StrictMode} from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' -import {GlobalProvider} from "@common/contexts/GlobalStateContext.tsx"; - +import { LocaleProvider } from '@common/contexts/LocaleContext.tsx'; async function initializeApp() { try { // 初始化行为 @@ -13,9 +12,9 @@ async function initializeApp() { // 异步操作完成后,渲染React消费者 ReactDOM.createRoot(document.getElementById('root')!).render( - + - + , ); } catch (error) { diff --git a/frontend/packages/core/src/pages/Login.tsx b/frontend/packages/core/src/pages/Login.tsx index dc59c5d8..120b28f2 100644 --- a/frontend/packages/core/src/pages/Login.tsx +++ b/frontend/packages/core/src/pages/Login.tsx @@ -206,7 +206,7 @@ const Login:FC = ()=> {

- {$t('Version (0)-(1)',[state.version,state.updateDate])}, {$t(state.powered)} + {$t('Version (0)-(1)',[state?.version,state?.updateDate])}, {$t(state?.powered || '-')}

diff --git a/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx b/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx index e0eaad83..303ecadc 100644 --- a/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx +++ b/frontend/packages/core/src/pages/aiService/AiServiceInsidePage.tsx @@ -42,7 +42,6 @@ const AiServiceInsidePage:FC = ()=> { const getApiDefine = ()=>{ - console.log('@@@@@@@') setApiPrefix('') setPrefixForce(false) fetchData>('service/router/define',{method:'GET',eoParams:{service:serviceId,team:teamId}}).then(response=>{ diff --git a/frontend/packages/core/src/pages/policy/FilterForm.tsx b/frontend/packages/core/src/pages/policy/FilterForm.tsx new file mode 100644 index 00000000..5a082df3 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/FilterForm.tsx @@ -0,0 +1,256 @@ +import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'; +import { Form, Input, Select, Checkbox, Table, Spin, TableColumnsType, message } from 'antd'; +import { useFetch } from '@common/hooks/http'; +import { LoadingOutlined } from '@ant-design/icons'; +import { validateApiPath, validateIPorCIDR } from '@common/utils/validate'; +import { $t } from '@common/locales'; +import { FilterFormItemProps, RemoteTitleType, FilterFormHandle, FilterFormProps } from '@common/const/policy/type'; +import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'; + +const RemoteFormItem: React.FC = (props) =>{ + const {value, onChange, disabled,option, onShowValueChange} = props + const [remoteList, setRemoteList] = useState([]) + const [remoteTableColumns, setRemoteTableColumns] = useState([]) + const [loading, setLoading] = useState(false) + const [rowKey, setRowKey] = useState('') + const title = useMemo(()=>option?.title,[option]) + const [remoteCounts, setRemoteCounts] = useState(0) + const [originRemoteList, setOriginRemoteList] = useState([]) + const {fetchData} = useFetch() + + + const getRemoteDetail = (searchWord?:string)=>{ + setLoading(true) + fetchData[], + target:string, + titles:Array, + total:number + value:string + }>>(`strategy/filter-REMOTE/${option?.name}`,{method:'GET', eoParams:{keyword:searchWord}}).then(response=>{ + const {code,data, msg} = response + if(code === STATUS_CODE.SUCCESS){ + setRemoteList(data[data.target as string] as unknown[]) + setRowKey(data.key as string) + setRemoteTableColumns(data.titles.map((x:RemoteTitleType)=>({ + title: x.title,dataIndex:x.field,key:x.field,ellipsis:true + }))) + setRemoteCounts(data.total) + if(!searchWord){ + setOriginRemoteList(data[data.target as string]) + if(value?.length === 1 && value[0] === 'ALL'){ + const totalDataArr = data[data.target as string]?.map((x:Record)=>x[data.key as string]) + onChange?.(totalDataArr) + onShowValueChange?.(totalDataArr.join(',')) + } + } + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }).finally(()=>{ + setLoading(false) + }) + } + + useEffect(()=>{getRemoteDetail()},[option]) + return ( +
+ } spinning={loading}> +

+ {$t('已选择(0)项(1)数据', [value?.length || 0, title])} +

+
+
+ getRemoteDetail(value)} + disabled={disabled} + /> +
+
(disabled ? '' : 'clickable-row')} + rowKey={rowKey} + size='small' + rowSelection={{ + type: 'checkbox', + onChange: (selectedRowKeys: React.Key[]) => { + onChange?.(selectedRowKeys as string[]); + onShowValueChange?.(selectedRowKeys.length === remoteCounts? $t('所有(0)',[title]) : originRemoteList.filter(x=>selectedRowKeys?.indexOf(x[option.target]))?.map(x=>x.title).join(' , ')) + }, + selectedRowKeys: value, + // getCheckboxProps: (record: unknown) => ({ + // disabled: record.name === 'Disabled User', // Column configuration not to be checked + // name: record.name, + // }) + }} + onRow={(record)=>({ + onClick:()=>{ + if(value === undefined){ + onChange?.([record[rowKey]]) + onShowValueChange?.(record.title) + }else if(value?.indexOf(record[rowKey])!== -1){ + const newSelectedKeys = value?.filter(x=>x!==record[rowKey]) + onChange?.(newSelectedKeys!) + onShowValueChange?.(newSelectedKeys.length === remoteCounts? $t('所有(0)',[option?.title]) : originRemoteList.filter(x=>newSelectedKeys.indexOf(x[rowKey]) !== -1)?.map(x=>x.title)?.join(' , ')) + }else{ + const newSelectedKeys = [...value,record[rowKey]] + onChange?.(newSelectedKeys) + onShowValueChange?.(newSelectedKeys.length === remoteCounts? $t('所有(0)',[option?.title]) : originRemoteList.filter(x=>newSelectedKeys.indexOf(x[rowKey]) !== -1)?.map(x=>x.title)?.join(' , ')) + } + } + })} + /> + + ) +} + +const StaticFormItem: React.FC = (props) => { + const {value, onChange, disabled,option,onShowValueChange} = props + const showAll = useMemo(()=>option.options.indexOf('ALL') !== -1,[option]) + const allChecked = useMemo(()=>value?.filter(x=>x!== 'ALL').length === option.options.filter(x=>x!== 'ALL').length,[value,option]) + + useEffect(()=>{ + if(value?.length === 1 && value[0] === 'ALL'){ + onChange?.(option.options.filter(x=>x!== 'ALL')) + onShowValueChange?.($t('所有(0)',[option?.title])) + } + },[]) + + return ( +
+ {showAll && ( + { + onChange?.(e.target.checked ? option.options : []) + onShowValueChange?.(e.target.checked ? $t('所有(0)',[option?.title]) : '-') + }} + disabled={disabled} + indeterminate={!allChecked && value?.length > 0} + > + ALL + + )} + x!== 'ALL')} + onChange={(checkedValues) => { + onChange?.(checkedValues) + onShowValueChange?.(checkedValues.join(',')) + }} + disabled={disabled} + /> +
) +} + +const FilterForm = forwardRef(({ + filterForm, + filterOptions, + selectedOptionNameSet, + disabled, + setFormCanSubmit},ref)=> { + const [form] = Form.useForm(); + const [filterType, setFilterType] = useState<'remote'|'static'|'pattern'>(); + const [curOption, setCurOption] = useState() + const [label,setLabel] = useState('') + + useImperativeHandle(ref, ()=>({ + clear:()=>{ + form.resetFields() + }, + save:()=>form.validateFields().then((res)=>{ + const selectedOption = filterOptions.filter(x=>x.name === res.name)[0] + return Promise.resolve({ + ...res, + label:filterType === 'pattern' ? res.value : label, + title:selectedOption.label + }) + }).catch((errorInfo)=>Promise.reject(errorInfo)) + }) + ) + + const handleValuesChange = (changedValues: any, allValues: any) => { + if(!allValues){ + setFormCanSubmit(false) + return + } + if(allValues.value instanceof Array){ + setFormCanSubmit(allValues.value.length > 0) + return + } + setFormCanSubmit(true) + }; + + + const handleTypeChange = (value:string)=>{ + form.setFieldValue('value',filterForm?.name === value ? filterForm.value : undefined) + const selectedOption = filterOptions?.filter(item=>item.name === value)[0] + setFilterType(selectedOption?.type) + setCurOption(selectedOption) + setFormCanSubmit(filterForm?.name === value ) + } + + const handleIPChange = (e) => { + const inputValue = e.target.value; + const formattedValue = inputValue.replace(/,/g, '\n'); + form.setFieldsValue({ value: formattedValue }); + }; + + useEffect(()=>{ + if(filterForm?.name){ + form.setFieldsValue(filterForm) + const selectedOption = filterOptions.filter(x=>x.name === filterForm?.name)[0] + setFilterType(selectedOption?.type ) + setCurOption(selectedOption) + }else{ + const firstOption = filterOptions.filter(x=>!selectedOptionNameSet.has(x.name))[0] + form.setFieldValue('name',firstOption?.name) + setFilterType(firstOption?.type) + setCurOption(firstOption) + } + },[filterForm]) + + const filterOptionsList = useMemo(() => { + return filterOptions.filter(x=>{ + return !!(filterForm?.name && x.name === filterForm?.name )|| !selectedOptionNameSet.has(x.name)}).map((item) => ({label:item.title, value:item.name})); + }, [filterOptions,filterForm,selectedOptionNameSet]); + + return ( +
+ + + )} + + {filterType === 'pattern' && form.getFieldValue('name') === 'ip' && ( + + )} + + {filterType === 'static' && } + + + ); +}) + +export default FilterForm; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/FilterTable.tsx b/frontend/packages/core/src/pages/policy/FilterTable.tsx new file mode 100644 index 00000000..ccbcabfb --- /dev/null +++ b/frontend/packages/core/src/pages/policy/FilterTable.tsx @@ -0,0 +1,144 @@ +import React, { useState, useEffect, useRef, useMemo } from 'react'; +import { Button, Table, Modal, App, Divider } from 'antd'; +import { ColumnsType } from 'antd/es/table'; +import { $t } from '@common/locales'; +import { useFetch } from '@common/hooks/http'; +import { useGlobalContext } from '@common/contexts/GlobalStateContext'; +import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission'; +import { FilterFormField, FilterTableProps, FilterOptionType, FilterFormHandle } from '@common/const/policy/type.ts'; +import FilterForm from './FilterForm'; +import { BasicResponse, COLUMNS_TITLE, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'; + + +const FilterTable: React.FC = ({ + disabled = false, + drawerTitle = '筛选条件', + value, + onChange +}) => { + const [isModalVisible, setIsModalVisible] = useState(false); + const [filterForm, setFilterForm] = useState(); + const [filterOptions, setFilterOptions] = useState([]); + const {message} = App.useApp() + const {state} = useGlobalContext() + const {fetchData} = useFetch() + const formRef = useRef(null); + const [formCanSubmit,setFormCanSubmit] = useState(false) + const [selectedOptionNameSet, setSelectedOptionNameSet] = useState>(new Set()); + const openDrawer = (type: string, data?: FilterFormField) => { + switch (type) { + case 'addFilter': + setFilterForm(undefined) + break; + case 'editFilter': + console.log(data) + setFilterForm(data) + } + setIsModalVisible(true); + }; + + const closeDrawer = () => { + setIsModalVisible(false); + cleanFilterForm(); + }; + + const cleanFilterForm = () => { + setFilterForm(undefined); + }; + + const handleSaveFilter = () => { + const formPromise = formRef.current?.save(); + formPromise?.then?.((res)=>{ + const newFilterForm = { + name:res.name, + value:res.value instanceof Array ? res.value : [res.value], + label:res.label, + title:res.title + } + onChange?.([newFilterForm, ...(value?.filter(x=>!filterForm?.name|| x.name!==filterForm.name) || [])]) + setSelectedOptionNameSet(prev=>{filterForm?.name &&prev.delete(filterForm?.name); prev.add(res.name); return prev}) + closeDrawer() + }) + }; + + const handleDeleteFilter = (item: FilterFormField) => { + setSelectedOptionNameSet(prev=>{prev.delete(item?.name); return prev}) + const newFilterShowList = value.filter((filter) => filter !== item); + onChange?.(newFilterShowList); + }; + + const getFilterOptions = ()=>{ + fetchData>('strategy/filter-options',{method:'GET'}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setFilterOptions(data.options) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }).catch((errorInfo)=> console.error(errorInfo)) + } + + const columns: ColumnsType =useMemo(()=>[ + { + title: $t('属性名称'), + dataIndex: 'name', + key: 'name', + }, + { + title: $t('属性值'), + dataIndex: 'label', + key: 'label', + }, + { + title: COLUMNS_TITLE.operate, + key: 'action', + width:100, + render: (_, record) => ( +
+ {openDrawer('editFilter', record)}} btnTitle={$t("编辑")}/> + + {handleDeleteFilter(record)}} btnTitle={$t("删除")}/>
) + } + ],[state.language]) + + useEffect(()=>{ + getFilterOptions() + },[state.language]) + + return ( +
+ { + !disabled && + } + {value && value.length >0 &&
} +
+
+ handleSaveFilter()} + destroyOnClose={true} + > + + + + ); +}; + +export default FilterTable; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/GlobalPolicyLayout.tsx b/frontend/packages/core/src/pages/policy/GlobalPolicyLayout.tsx new file mode 100644 index 00000000..d072238b --- /dev/null +++ b/frontend/packages/core/src/pages/policy/GlobalPolicyLayout.tsx @@ -0,0 +1,14 @@ +import { useEffect } from "react"; +import { Outlet, useLocation, useNavigate } from "react-router-dom"; + +export default function GlobalPolicyLayout(){ + const location = useLocation() + const pathName = location.pathname + const navigator = useNavigate() + useEffect(()=>{ + if(pathName === '/globalpolicy'){ + navigator('/globalpolicy/datamasking/list') + } + },[pathName]) + return () +} \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/dataMasking/DataMasking.tsx b/frontend/packages/core/src/pages/policy/dataMasking/DataMasking.tsx new file mode 100644 index 00000000..23dc41b0 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/dataMasking/DataMasking.tsx @@ -0,0 +1,331 @@ +import { ActionType } from "@ant-design/pro-components"; +import { useMemo, useRef, useState } from "react"; +import { Button, message, Switch } from 'antd' +import PageList, { PageProColumns } from "@common/components/aoplatform/PageList"; +import { $t } from "@common/locales"; +import { useGlobalContext } from "@common/contexts/GlobalStateContext"; +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const.tsx"; +import { useFetch } from "@common/hooks/http"; +import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; +import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission"; +import { DATA_MASSKING_TABLE_COLUMNS } from "./DataMaskingColumn"; +import { useNavigate, useParams } from "react-router-dom"; +import { PolicyPublishInfoType, PolicyPublishModalHandle, RouterParams } from "@common/const/type"; +import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter"; +import { DataMaskStrategyItem } from "@common/const/policy/type"; +import {PolicyPublishModalContent} from '@common/components/aoplatform/PolicyPublishModalContent' + +const DataMasking = (props: any) => { + + const { + // 是否显示发布按钮 + publishBtn = false, + // 行操作 + rowOperation = [] + } = props; + const { serviceId, teamId } = useParams() + const { state } = useGlobalContext() + const navigator = useNavigate() + const [drawerVisible, setDrawerVisible] = useState(false) + const [drawerData, setDrawerData] = useState() + const [isOkToPublish, setIsOkToPublish] = useState(false) + const drawerRef = useRef(null) + /** + * 列表ref + */ + const pageListRef = useRef(null); + + /** + * 请求数据 + */ + const { fetchData } = useFetch() + + /** + * 搜索关键字 + */ + const [searchWord, setSearchWord] = useState('') + + /** + * 获取列数据,国际化变化时重新获取 + */ + const columns = useMemo(() => { + const res = DATA_MASSKING_TABLE_COLUMNS.map(x => { + // 启动列渲染 + if (x.dataIndex === 'isStop') { + x.render = (text: any, record: any) => { changeOpenApiStatus(e, record) }} /> + } + // 处理数列渲染 + if (x.dataIndex === 'treatmentNumber') { + x.render = (text: any, record: any) => { openLogsModal(record) }} >{ text } + } + return { + ...x, + title: typeof x.title === 'string' ? $t(x.title as string) : x.title + } + }) + return res + }, [ state.language]) + + /** + * 操作列 + */ + const operation: PageProColumns[] = rowOperation.length ? [ + { + title: '', + key: 'option', + btnNums: rowOperation.length, + fixed: 'right', + valueType: 'option', + render: (_: React.ReactNode, entity: any) => [ + ...(rowOperation.length && rowOperation.find((item: string) => item === 'edit') ? [ { openEditModal(entity) }} btnTitle="编辑" />] : []), + // ...(rowOperation.length && rowOperation.find((item: string) => item === 'logs') ? [ { openLogsModal(entity) }} btnTitle="详情" />] : []), + ...(rowOperation.length && rowOperation.find((item: string) => item === 'delete') ? [ + entity.isDeleted ? { restorePolicy(entity) }} btnTitle="恢复" /> : + { deletePolicy(entity) }} btnTitle="删除" /> + ] : []), + ], + } + ] : [] + + /** + * 手动刷新表格数据 + */ + const manualReloadTable = () => { + pageListRef.current?.reload() + }; + + /** + * 更改启动状态 + * @param enabled 状态 + * @param entity 行数据 + */ + const changeOpenApiStatus = (enabled: boolean, entity: any) => { + fetchData>( + `strategy/${serviceId === undefined? 'global':'service'}/data-masking/${enabled ? 'disable' : 'enable'}`, + { + method: 'PUT', + eoParams: { + service:serviceId, + team:teamId, + strategy: entity.id + } + } + ).then(response => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + manualReloadTable() + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + /** + * 获取列表数据 + * @param dataType + * @returns + */ + const getPolicyList = (params: DataMaskStrategyItem & { + pageSize: number; + current: number; + }, + sort:Record, + filter:Record) => { + let filters + if(filter){ + filters = [] + if(filter.isStop){ + if(filter.isStop.indexOf('true')!== -1){ + filters.push('enable') + } + if(filter.isStop.indexOf('false')!== -1){ + filters.push('disable') + } + if(filter.publishStatus?.length > 0){ + filters = [...filters, ...filter.publishStatus] + } + } + } + + return fetchData>( + `strategy/${serviceId === undefined? 'global':'service'}/data-masking/list`, + { + method: 'GET', + eoParams: { + order:Object.keys(sort)?.[0], + sort:Object.keys(sort)?.length > 0 ? Object.values(sort)?.[0] === 'descend' ? 'desc' : 'asc' : undefined, + filters:JSON.stringify(filters), + keyword: searchWord, + service:serviceId, + team:teamId,}, + eoTransformKeys: ['is_stop', 'is_deleted', 'update_time','publish_status','processed_total'] + } + ).then(response => { + const { code,data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + // 保存数据 + return { + data:data.strategies, + total:data.total, + success: true + } + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + return { data: [], success: false } + } + }).catch(() => { + return { data: [], success: false } + }) + + + } + + /** + * 添加策略 + * @param type + */ + const addPolicy = () => { + navigator('/globalpolicy/datamasking/create') + } + + /** + * 发布策略 + */ + const publish = async () => { + message.loading($t(RESPONSE_TIPS.loading)); + const { code, data, msg } = await fetchData>( + 'strategy/global/data-masking/to-publishs', + { method: 'GET',eoTransformKeys:['opt_time','is_publish','version_name','unpublish_msg'] } + ); + message.destroy(); + if (code === STATUS_CODE.SUCCESS) { + setDrawerVisible(true) + setDrawerData(data) + setIsOkToPublish(data.isPublish??true) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)); + return + } + } + + /** + * 编辑 + */ + const openEditModal = (entity: any) => { + navigator(`/globalpolicy/datamasking/${entity.id}`) + } + + /** + * 日志 + * @param entity + */ + const openLogsModal = (entity: any) => { + console.log('日志', entity); + } + + /** + * 删除 + * @param entity + */ + const deletePolicy = (entity: DataMaskStrategyItem) => { + fetchData>( + `strategy/${serviceId === undefined? 'global':'service'}/data-masking`, + { + method: 'DELETE', + eoParams: { + service:serviceId, + team:teamId, + strategy:entity.id}, + } + ).then(response => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + manualReloadTable() + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + /** + * 恢复 + * @param entity + */ + const restorePolicy = (entity: any) => { + fetchData>( + `strategy/${serviceId === undefined? 'global':'service'}/data-masking/restore`, + { + method: 'PATCH', + eoParams: { + service:serviceId, + team:teamId, + strategy:entity.id}, + } + ).then(response => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + manualReloadTable() + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + + const onSubmit = () => { + return drawerRef.current?.publish()?.then((res) => { + manualReloadTable(); + return res; + }); + } + + return ( + <> + + id="data_masking_list" + ref={pageListRef} + columns={[...columns, ...operation]} + request={async (params: DataMaskStrategyItem & { + pageSize: number; + current: number; + }, + sort:Record, + filter:Record) => getPolicyList(params,sort, filter)} + addNewBtnTitle={$t("添加策略")} + addNewBtnAccess="system.organization.member.edit" + onAddNewBtnClick={() => { addPolicy() }} + searchPlaceholder={$t("输入名称、筛选条件查找")} + afterNewBtn={ + publishBtn && [ + + ] + } + onSearchWordChange={(e) => { + setSearchWord(e.target.value) + }} + manualReloadTable={manualReloadTable} + /> + {setDrawerVisible(false)}} + okBtnTitle={$t('发布')} + open={drawerVisible} + submitDisabled={!isOkToPublish} + submitAccess={`team.service.release.add`} + onSubmit={onSubmit} + > + + + + ) +} + +export default DataMasking; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingColumn.tsx b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingColumn.tsx new file mode 100644 index 00000000..51cc8974 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingColumn.tsx @@ -0,0 +1,69 @@ + +import { PageProColumns } from "@common/components/aoplatform/PageList"; +import { frontendTimeSorter } from "@common/utils/dataTransfer"; +import { $t } from "@common/locales"; +import { StrategyStatusEnum, StrategyStatusColorClass } from "@common/const/policy/consts"; + + +export const DATA_MASSKING_TABLE_COLUMNS: PageProColumns[] = [ + { + title: ('策略名称'), + dataIndex: 'name', + ellipsis: true, + width: 160 + }, + { + title: ('优先级'), + dataIndex: 'priority', + width: 140, + ellipsis: true, + sorter: (a: any, b: any) => { + return (a.priority as number) - (b.priority as number) + } + }, + { + title: ('发布状态'), + dataIndex: 'publishStatus', + filters: true, + onFilter: false , + width: 140, + valueEnum: new Map( + Object.keys(StrategyStatusEnum).map(key=> + [key, + {$t(StrategyStatusEnum[key as keyof typeof StrategyStatusEnum])} + ])) + }, + { + title: ('启用'), + dataIndex: 'isStop', + filters: true, + onFilter: false , + valueEnum: { + false: { text: {$t('启用')} }, + true: { text: {$t('禁用')} } + } + }, + { + title: ('筛选条件'), + dataIndex: 'filters', + ellipsis: true + }, + { + title: ('处理数'), + dataIndex: 'processedTotal', + ellipsis: true + }, + { + title: ('更新者'), + dataIndex: 'operator', + width: 140, + ellipsis: true + }, + { + title: ('更新时间'), + dataIndex: 'updateTime', + width: 182, + ellipsis: true, + sorter: (a, b) => frontendTimeSorter(a, b, 'updateTime') + }, +]; diff --git a/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingConfig.tsx b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingConfig.tsx new file mode 100644 index 00000000..fdeb9416 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingConfig.tsx @@ -0,0 +1,171 @@ +import { LoadingOutlined } from "@ant-design/icons" +import InsidePage from "@common/components/aoplatform/InsidePage" +import WithPermission from "@common/components/aoplatform/WithPermission" +import { BasicResponse, STATUS_CODE, RESPONSE_TIPS, PLACEHOLDER } from "@common/const/const" +import { RouterParams } from "@common/const/type" +import { useGlobalContext } from "@common/contexts/GlobalStateContext" +import { useFetch } from "@common/hooks/http" +import { $t } from "@common/locales" +import { App, Button, Form, Input, InputNumber, Row, Select, Spin } from "antd" +import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react" +import { useParams, useNavigate } from "react-router-dom" +import DataMaskRuleTable from "./DataMaskingRuleTable" +import FilterTable from "../FilterTable" +import { DataMaskingConfigHandle ,DataMaskingConfigFieldType} from "@common/const/policy/type" +import {PolicyOptions} from '@common/const/policy/consts' + +const DataMaskingConfig = forwardRef((_,ref) => { + const { message,modal } = App.useApp() + const { teamId, serviceId, policyId } = useParams(); + const [onEdit, setOnEdit] = useState(!!teamId) + const [form] = Form.useForm(); + const {fetchData} = useFetch() + const { state } = useGlobalContext() + const [ loading, setLoading ] = useState(false) + const navigator = useNavigate() + + useImperativeHandle(ref, () => ({ + save:onFinish + })); + + // 获取表单默认值 + const getPolicyInfo = () => { + setLoading(true) + fetchData>( `strategy/${serviceId === undefined? 'global':'service'}/data-masking`,{method:'GET',eoParams:{team:teamId, service:serviceId, strategy:policyId}}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setTimeout(()=>{ + form.setFieldsValue({ + ...data.strategy, + type:'data-masking' + }) + },0) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }).finally(()=>setLoading(false)) + }; + + const onFinish:()=>Promise = () => { + return form.validateFields().then((value)=>{ + return fetchData>( + `strategy/${serviceId === undefined? 'global':'service'}/data-masking`, + { + method:policyId === undefined? 'POST' : 'PUT', + eoParams: {service:serviceId,team:teamId, policyId:policyId}, + eoBody:({...value}) + }).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || $t(RESPONSE_TIPS.success)) + return Promise.resolve(true) + }else{ + message.error(msg || $t(RESPONSE_TIPS.error)) + return Promise.reject(msg || $t(RESPONSE_TIPS.error)) + } + }).catch((errorInfo)=>{ + return Promise.reject(errorInfo) + }) + }) + }; + + useEffect(() => { + if (policyId !== undefined) { + setOnEdit(true); + getPolicyInfo(); + } else { + setOnEdit(false); + form.setFieldValue('type','data-masking') + } + return (form.setFieldsValue({})) + }, [policyId]); + + const policyOptions = useMemo(()=>PolicyOptions.map((x)=>({...x, label:$t(x.label)})),[state.language]) + + return ( + + + } spinning={loading} wrapperClassName=' pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X'> + + +
+
+ + label={$t("策略名称")} + name="name" + rules={[{ required: true ,whitespace:true }]} + > + + + + + label={$t("策略类型")} + name="type" + rules={[{ required: true }]} + > + + + + + + label={$t("优先级")} + name={'priority'} + rules={[{required: true}]} + > + + + + + label={$t("描述")} + name="description" + > + + + + + label={$t("匹配条件")} + name="filters" + > + + + + + label={$t("数据脱敏规则")} + name="rules" + rules={[{required: true}]} + > + + + + + + + + + +
+ +
+
+
+ ) +}) +export default DataMaskingConfig \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleForm.tsx b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleForm.tsx new file mode 100644 index 00000000..4ad2707a --- /dev/null +++ b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleForm.tsx @@ -0,0 +1,158 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { Form, Input, Select, Modal } from 'antd'; +import { useGlobalContext } from '@common/contexts/GlobalStateContext'; +import { $t } from '@common/locales'; +import { PLACEHOLDER } from '@common/const/const'; +import { v4 as uuidv4 } from 'uuid'; +import { DataMaskRuleFormProps } from '@common/const/policy/type'; +import { MatchRules, DataFormatOptions, DataMaskReplaceStrOptions, DataMaskBaseOptionOptions, DataMaskOrderOptions } from '@common/const/policy/consts'; +const DataMaskRuleForm: React.FC = ({ editData, ruleList, onSave, onClose,modalVisible }) => { + const [form] = Form.useForm(); + const [matchType, setMatchType] = useState(''); + const [matchValue, setMatchValue] = useState(''); + const [maskType, setMaskType] = useState(''); + const [replaceType, setReplaceType] = useState(''); + const {state} = useGlobalContext() + useEffect(() => { + if (editData) { + form.setFieldsValue(editData); + } + }, [editData, form]); + + const handleSave = () => { + form.validateFields().then((values) => { + const submitData = prepareSubmitData(values); + const newRuleList =ruleList ? [...ruleList] : []; + if (editData) { + const index = newRuleList.findIndex((rule) => rule.eoKey === editData.eoKey); + if (index !== -1) { + newRuleList.splice(index, 1); + } + } + newRuleList.unshift({ ...submitData, eoKey: editData?.eoKey || uuidv4() }); + onSave?.(newRuleList); + onClose?.(); + clearData() + }); + }; + + const clearData = ()=>{ + form.resetFields() + setMatchType(''); + setMaskType(''); + setMatchValue(''); + setReplaceType(''); + } + + useEffect(() => { + if (editData) { + form.setFieldsValue(editData); + editData?.match?.type && setMatchType(editData.match.type); + editData?.mask?.type && setMaskType(editData.mask.type); + editData?.match?.value && setMatchValue(editData.match.value); + editData?.mask?.replace?.type && setReplaceType(editData.mask.replace.type); + } + }, [editData, form]); + + const handleMatchTypeChange = (value: string) => { + setMatchType(value); + form.resetFields(['match.value','mask.begin', 'mask.length', 'mask.replace.type', 'mask.replace.value']); + }; + + const handleMatchValueChange = (value: string) => { + setMatchValue(value); + form.resetFields(['mask.begin', 'mask.length', 'mask.replace.type', 'mask.replace.value']); + }; + + const handleMaskTypeChange = (value: string) => { + setMaskType(value); + form.resetFields(['mask.begin', 'mask.length', 'mask.replace.type', 'mask.replace.value']); + }; + + const handleReplaceTypeChange = (value: string) => { + setReplaceType(value); + form.resetFields(['mask.replace.value']); + }; + + const prepareSubmitData = (formData: any) => { + const submitData: any = { + match: { + type: formData.match.type, + value: formData.match.value + }, + mask: { + type: formData.mask.type + } + }; + + switch (formData.mask.type) { + case 'replacement': + submitData.mask = { + ...submitData.mask, + replace: formData.mask.replace + }; + break; + case 'shuffling': + break; + default: + submitData.mask.begin = formData.mask.begin; + submitData.mask.length = formData.mask.length; + break; + } + return submitData; + }; + + const matchRuleOptions = useMemo(()=>MatchRules.map(rule => ({ label: $t(rule.label), value: rule.value })),[state.language]) + const dataFormatOptions = useMemo(()=>DataFormatOptions.map(rule => ({ label: $t(rule.label), value: rule.value })),[state.language]) + const dataMaskBaseOptions = useMemo(()=>DataMaskBaseOptionOptions.map(rule => ({ label: $t(rule.label), value: rule.value })),[state.language]) + const dataMaskOrderOptions = useMemo(()=>DataMaskOrderOptions.map(rule => ({ label: $t(rule.label), value: rule.value })),[state.language]) + const dataMaskReplaceStrOptions = useMemo(()=>DataMaskReplaceStrOptions.map(rule => ({ label: $t(rule.label), value: rule.value })),[state.language]) + + return ( + +
+ + + :} + + } + + + + + + + + + )} + + {maskType === 'replacement' && ( + <> + + + + )} + + )} + + +
+ ); +}; + +export default DataMaskRuleForm; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleTable.tsx b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleTable.tsx new file mode 100644 index 00000000..9043918f --- /dev/null +++ b/frontend/packages/core/src/pages/policy/dataMasking/DataMaskingRuleTable.tsx @@ -0,0 +1,152 @@ +import { useMemo, useState } from 'react'; +import { Button, Table, Tooltip } from 'antd'; +import DataMaskRuleForm from './DataMaskingRuleForm'; +import { $t } from '@common/locales'; +import {DataMaskRuleTableProps, MaskRuleData} from "@common/const/policy/type"; +import { useGlobalContext } from '@common/contexts/GlobalStateContext'; +import { COLUMNS_TITLE } from '@common/const/const'; +import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission'; + + +const DataMaskRuleTable: React.FC = ({ + disabled = false, + value, + onChange +}) => { + const [editData, setEditData] = useState(undefined); + const [isModalVisible, setIsModalVisible] = useState(false); + const {state} = useGlobalContext() + const openDrawer = (type:'add'|'edit',data?: MaskRuleData) => { + setEditData(data); + setIsModalVisible(true); + }; + + const closeDrawer = () => { + setIsModalVisible(false); + setEditData(undefined); + }; + + const handleSave = (newRuleList: MaskRuleData[]) => { + onChange?.(newRuleList); + }; + + const columns = useMemo(()=> [ + { + title: $t('匹配类型'), + dataIndex: ['match', 'type'], + key: 'matchType', + render: (text: string) => { + switch (text) { + case 'inner': + return $t('数据格式'); + case 'keyword': + return $t('关键字'); + case 'regex': + return $t('正则表达式'); + case 'json_path': + return $t('JSON Path'); + default: + return text; + } + }, + }, + { + title: $t('匹配值'), + dataIndex: ['match', 'value'], + key: 'matchValue', + render: (text: string) => { + switch (text) { + case 'name': + return $t('姓名'); + case 'phone': + return $t('手机号'); + case 'id-card': + return $t('身份证号'); + case 'bank-card': + return $t('银行卡号'); + case 'date': + return $t('日期'); + case 'amount': + return $t('金额'); + default: + return text; + } + }, + }, + { + title: $t('脱敏类型'), + dataIndex: ['mask', 'type'], + key: 'maskType', + render: (text: string) => { + switch (text) { + case 'partial-display': + return $t('局部显示'); + case 'partial-masking': + return $t('局部遮蔽'); + case 'truncation': + return $t('截取'); + case 'replacement': + return $t('替换'); + case 'shuffling': + return $t('乱序'); + default: + return text; + } + }, + }, + { + title: $t('脱敏规则'), + dataIndex: 'mask', + key: 'maskRule', + render: (mask: any) => { + switch (mask.type) { + case 'replacement': + return ( + + {$t('类型')}:{mask.replace.type === 'random' ? $t('随机字符串') : $t('自定义字符串; 值:')}{mask.replace.value} + + ); + case 'shuffling': + return '-'; + default: + return ( + + {$t('起始位置:(0)位;长度:(1)位',[mask.begin,mask.length])} + + ); + } + }, + }, + { + title: COLUMNS_TITLE.operate, + key: 'action', + render: (_: any, record: MaskRuleData) => ( + {openDrawer('edit', record)}} btnTitle={$t("编辑")}/> + ), + }, + ],[state.language]) + + return ( +
+ { + !disabled && + } + {value && value.length >0 &&
} + + + ); +}; + +export default DataMaskRuleTable; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/globalPolicy.tsx b/frontend/packages/core/src/pages/policy/globalPolicy.tsx new file mode 100644 index 00000000..3e5f7b5c --- /dev/null +++ b/frontend/packages/core/src/pages/policy/globalPolicy.tsx @@ -0,0 +1,36 @@ +import InsidePage from "@common/components/aoplatform/InsidePage.tsx"; +import { $t } from "@common/locales/index.ts"; +import PolicyTabContainer from "./PolicyTabContainer.tsx"; +import DataMasking from "./dataMasking/DataMasking.tsx"; +import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; +import { useMemo } from "react"; + + +const PartitionInsideGlobalPolicy = () => { + const {state} = useGlobalContext() + /** + * tab列表 + */ + const tabItems =useMemo(()=> [ + { + key: 'dataMasking', + label: $t('数据脱敏'), + children:
+ } + ],[state.language]) + + return ( + <> + + + + + ) +} + +export default PartitionInsideGlobalPolicy \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/policyTabContainer.tsx b/frontend/packages/core/src/pages/policy/policyTabContainer.tsx new file mode 100644 index 00000000..6cd174a6 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/policyTabContainer.tsx @@ -0,0 +1,19 @@ +import { Tabs } from "antd"; + +const PolicyTabContainer = (props: any) => { + /** + * 支持的tab + */ + const { tabs } = props; + + return ( + <> + + + ) +} + +export default PolicyTabContainer; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/policy/servicePolicy.tsx b/frontend/packages/core/src/pages/policy/servicePolicy.tsx new file mode 100644 index 00000000..32022c02 --- /dev/null +++ b/frontend/packages/core/src/pages/policy/servicePolicy.tsx @@ -0,0 +1,23 @@ +import { $t } from "@common/locales/index.ts"; +import DataMasking from "./dataMasking/DataMasking"; +import PolicyTabContainer from "./PolicyTabContainer"; + +const servicePolicy = () => { + /** + * tab列表 + */ + const tabItems = [ + { + key: 'dataMasking', + label: $t('数据脱敏'), + children:
+ } + ] + return ( + <> + + + ) +} + +export default servicePolicy; \ No newline at end of file diff --git a/frontend/packages/core/src/pages/system/SystemInsidePage.tsx b/frontend/packages/core/src/pages/system/SystemInsidePage.tsx index afa7b7c5..9dd929d9 100644 --- a/frontend/packages/core/src/pages/system/SystemInsidePage.tsx +++ b/frontend/packages/core/src/pages/system/SystemInsidePage.tsx @@ -1,11 +1,11 @@ -import {FC, useEffect, useMemo, useState} from "react"; -import {Link, Outlet, useLocation, useNavigate, useParams} from "react-router-dom"; -import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; -import {App, Menu, MenuProps} from "antd"; -import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx"; -import {useFetch} from "@common/hooks/http.ts"; -import { useSystemContext} from "../../contexts/SystemContext.tsx"; +import { FC, useEffect, useMemo, useState } from "react"; +import { Link, Outlet, useLocation, useNavigate, useParams } from "react-router-dom"; +import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx"; +import { App, Menu, MenuProps } from "antd"; +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const.tsx"; +import { useFetch } from "@common/hooks/http.ts"; +import { useSystemContext } from "../../contexts/SystemContext.tsx"; import { SystemConfigFieldType } from "../../const/system/type.ts"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; import { PERMISSION_DEFINITION } from "@common/const/permissions.ts"; @@ -17,144 +17,147 @@ import { $t } from "@common/locales/index.ts"; import { getItem } from "@common/utils/navigation.tsx"; const APP_MODE = import.meta.env.VITE_APP_MODE; -const SystemInsidePage:FC = ()=> { - const { message } = App.useApp() - const { teamId,serviceId,apiId,routeId} = useParams(); - const location = useLocation() - const currentUrl = location.pathname - const {fetchData} = useFetch() - const { setPrefixForce,setApiPrefix ,systemInfo,setSystemInfo} = useSystemContext() - const { accessData,checkPermission,accessInit,state} = useGlobalContext() - const [activeMenu, setActiveMenu] = useState() - const navigateTo = useNavigate() - const [showMenu, setShowMenu] = useState(false) +const SystemInsidePage: FC = () => { + const { message } = App.useApp() + const { teamId, serviceId, apiId, routeId } = useParams(); + const location = useLocation() + const currentUrl = location.pathname + const { fetchData } = useFetch() + const { setPrefixForce, setApiPrefix, systemInfo, setSystemInfo } = useSystemContext() + const { accessData, checkPermission, accessInit, state } = useGlobalContext() + const [activeMenu, setActiveMenu] = useState() + const navigateTo = useNavigate() + const [showMenu, setShowMenu] = useState(false) - const getSystemInfo = ()=>{ - fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId}}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setSystemInfo(data.service) - }else{ - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) - } + const getSystemInfo = () => { + fetchData>('service/info', { method: 'GET', eoParams: { team: teamId, service: serviceId } }).then(response => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setSystemInfo(data.service) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } - const getApiDefine = ()=>{ - setApiPrefix('') - setPrefixForce(false) - fetchData>('service/router/define',{method:'GET',eoParams:{service:serviceId,team:teamId}}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setApiPrefix(data.prefix) - setPrefixForce(data.force) - }else{ - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) - } + const getApiDefine = () => { + setApiPrefix('') + setPrefixForce(false) + fetchData>('service/router/define', { method: 'GET', eoParams: { service: serviceId, team: teamId } }).then(response => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setApiPrefix(data.prefix) + setPrefixForce(data.force) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } - - const SYSTEM_PAGE_MENU_ITEMS = useMemo(()=>[ + + const SYSTEM_PAGE_MENU_ITEMS = useMemo(() => [ getItem($t('服务'), 'assets', null, - [ - getItem({$t('API 路由')}, 'route',undefined,undefined,undefined,'team.service.router.view'), - getItem({$t('API 文档')}, 'api',undefined,undefined,undefined,'team.service.api_doc.view'), - getItem({$t('上游')}, 'upstream',undefined,undefined,undefined,'team.service.upstream.view'), - getItem({$t('使用说明')}, 'document',undefined,undefined,undefined,'team.service.service_intro.view'), - getItem({$t('发布')}, 'publish',undefined,undefined,undefined,'team.service.release.view'), - ], - 'group'), + [ + getItem({$t('API 路由')}, 'route', undefined, undefined, undefined, 'team.service.router.view'), + getItem({$t('API 文档')}, 'api', undefined, undefined, undefined, 'team.service.api_doc.view'), + getItem({$t('上游')}, 'upstream', undefined, undefined, undefined, 'team.service.upstream.view'), + getItem({$t('使用说明')}, 'document', undefined, undefined, undefined, 'team.service.service_intro.view'), + getItem({$t('服务策略')}, 'servicePolicy', undefined, undefined, undefined, 'team.service.service_intro.view'), + getItem({$t('发布')}, 'publish', undefined, undefined, undefined, 'team.service.release.view'), + ], + 'group'), getItem($t('订阅管理'), 'provideSer', null, - [ - getItem({$t('订阅审核')}, 'approval',undefined,undefined,undefined,'team.service.subscription.view'), - getItem({$t('订阅方管理')}, 'subscriber',undefined,undefined,undefined,'team.service.subscription.view'), - ], - 'group'), + [ + getItem({$t('订阅审核')}, 'approval', undefined, undefined, undefined, 'team.service.subscription.view'), + getItem({$t('订阅方管理')}, 'subscriber', undefined, undefined, undefined, 'team.service.subscription.view'), + ], + 'group'), getItem($t('管理'), 'mng', null, [ - APP_MODE === 'pro' ? getItem({$t('调用拓扑图')}, 'topology',undefined,undefined,undefined,'project.mySystem.topology.view'):null, + // APP_MODE === 'pro' ? getItem({$t('调用拓扑图')}, 'topology',undefined,undefined,undefined,'project.mySystem.topology.view'):null, getItem({$t('设置')}, 'setting',undefined,undefined,undefined,'')], 'group'), ],[state.language]) - const menuData = useMemo(()=>{ - const filterMenu = (menu:MenuItemGroupType[])=>{ - const newMenu = cloneDeep(menu) - return newMenu!.filter((m:MenuItemGroupType )=>{ - if(m&&m.children && m.children.length > 0){ - m.children = m.children.filter( - (c)=>{ - if(!c) return false - return (((c as MenuItemType&{access:string} ).access ? - checkPermission((c as MenuItemType&{access:string} ).access as keyof typeof PERMISSION_DEFINITION[0]): - true))}) - } - return m.children && m.children.length > 0 + const menuData = useMemo(() => { + const filterMenu = (menu: MenuItemGroupType[]) => { + const newMenu = cloneDeep(menu) + return newMenu!.filter((m: MenuItemGroupType) => { + if (m && m.children && m.children.length > 0) { + m.children = m.children.filter( + (c) => { + if (!c) return false + return (((c as MenuItemType & { access: string }).access ? + checkPermission((c as MenuItemType & { access: string }).access as keyof typeof PERMISSION_DEFINITION[0]) : + true)) }) } - const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType[]) - const menu = activeMenu ?? filteredMenu[0]?.children ? filteredMenu[0]?.children?.[0]?.key : filteredMenu[0]?.key - if(menu && currentUrl.split('/')[-1] !== menu) navigateTo(`/service/${teamId}/inside/${serviceId}/${menu}`) - return filteredMenu || [] - },[accessData,accessInit, SYSTEM_PAGE_MENU_ITEMS]) - - const onMenuClick: MenuProps['onClick'] = ({key}) => { - setActiveMenu(key) - }; - - useEffect(() => { - setShowMenu(!routeId && !currentUrl.includes('route/create')) - if(apiId !== undefined){ - setActiveMenu('api') - }else if(serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]){ - setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1]) - }else{ - setActiveMenu('route') - } - }, [currentUrl]); + return m.children && m.children.length > 0 + }) + } + const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType[]) + const menu = activeMenu ?? filteredMenu[0]?.children ? filteredMenu[0]?.children?.[0]?.key : filteredMenu[0]?.key + if (menu && currentUrl.split('/')[-1] !== menu) navigateTo(`/service/${teamId}/inside/${serviceId}/${menu}`) + return filteredMenu || [] + }, [accessData, accessInit, SYSTEM_PAGE_MENU_ITEMS]) - useEffect(()=>{ - if(accessData && checkPermission('team.service.router.view')){ - getApiDefine() - } - },[accessData]) + const onMenuClick: MenuProps['onClick'] = ({ key }) => { + setActiveMenu(key) + }; - useEffect(()=>{ - if( activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]){ - navigateTo(`/service/${teamId}/inside/${serviceId}/${activeMenu}`) - } - },[activeMenu]) + useEffect(() => { + setShowMenu(!routeId && !currentUrl.includes('route/create')) + if (apiId !== undefined) { + setActiveMenu('api') + } else if (serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]) { + setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1]) + } else { + setActiveMenu('route') + } + }, [currentUrl]); - useEffect(() => { - serviceId && getSystemInfo() - }, [serviceId]); + useEffect(() => { + if (accessData && checkPermission('team.service.router.view')) { + getApiDefine() + } + }, [accessData]) - return ( - <>{showMenu ? - {$t('服务 ID')}:{serviceId || '-'} - }]} - backUrl="/service/list"> -
- [] } - /> -
- -
-
-
: } + useEffect(() => { + if (activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]) { + navigateTo(`/service/${teamId}/inside/${serviceId}/${activeMenu}`) + } + }, [activeMenu]) - - ) + useEffect(() => { + serviceId && getSystemInfo() + }, [serviceId]); + + return ( + <>{showMenu ? + {$t('服务 ID')}:{serviceId || '-'} + }]} + backUrl="/service/list"> +
+ []} + /> +
+ +
+
+
: } + + + ) } export default SystemInsidePage \ No newline at end of file diff --git a/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx b/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx index 7721d564..a316ed40 100644 --- a/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx +++ b/frontend/packages/core/src/pages/system/api/SystemInsideRouterCreate.tsx @@ -1,18 +1,16 @@ import {App, Button, Col, Form, Input, Row, Select, Space, Spin, Switch} from "antd"; import {forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react"; import EditableTableWithModal from "@common/components/aoplatform/EditableTableWithModal.tsx"; -import styles from "./SystemInsideApi.module.css" import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx"; import {useFetch} from "@common/hooks/http.ts"; import { API_PATH_MATCH_RULES, API_PROTOCOL, HTTP_METHOD, MATCH_CONFIG, MatchPositionEnum, MatchTypeEnum } from "../../../const/system/const.tsx"; import { SystemInsideRouterCreateHandle, SystemInsideRouterCreateProps, SystemApiProxyFieldType, SystemInsideApiProxyHandle } from "../../../const/system/type.ts"; -import { MatchItem } from "@common/const/type.ts"; +import { MatchItem, RouterParams } from "@common/const/type.ts"; import { validateUrlSlash } from "@common/utils/validate.ts"; import { $t } from "@common/locales/index.ts"; import SystemInsideApiProxy from "@core/pages/system/api/SystemInsideApiProxy.tsx"; import { LoadingOutlined } from "@ant-design/icons"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; -import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx"; import { useNavigate, useParams } from "react-router-dom"; import { useSystemContext } from "@core/contexts/SystemContext.tsx"; import InsidePage from "@common/components/aoplatform/InsidePage.tsx"; @@ -236,8 +234,6 @@ const SystemInsideRouterCreate = forwardRef - {/* } */} -
{$t('转发规则设置')} diff --git a/frontend/packages/core/src/pages/system/publish/SystemInsidePublishList.tsx b/frontend/packages/core/src/pages/system/publish/SystemInsidePublishList.tsx index d02fec26..894a2682 100644 --- a/frontend/packages/core/src/pages/system/publish/SystemInsidePublishList.tsx +++ b/frontend/packages/core/src/pages/system/publish/SystemInsidePublishList.tsx @@ -4,10 +4,9 @@ import { useState, useRef, useEffect, useMemo, FC } from "react"; import { useParams, Link, useLocation } from "react-router-dom"; import PageList, { PageProColumns } from "@common/components/aoplatform/PageList"; import { PublishApprovalModalContent } from "@common/components/aoplatform/PublishApprovalModalContent"; -import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; import { PUBLISH_APPROVAL_RECORD_INNER_TABLE_COLUMN, PUBLISH_APPROVAL_VERSION_INNER_TABLE_COLUMN, PublishApplyStatusEnum, PublishStatusEnum, PublishTableStatusColorClass } from "@common/const/approval/const"; import { BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"; -import { SimpleMemberItem } from "@common/const/type.ts"; +import { RouterParams, SimpleMemberItem } from "@common/const/type.ts"; import { MemberTableListItem } from "../../../const/member/type"; import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; import { useFetch } from "@common/hooks/http"; diff --git a/frontend/packages/core/src/pages/system/upstream/SystemInsideUpstreamContent.tsx b/frontend/packages/core/src/pages/system/upstream/SystemInsideUpstreamContent.tsx index bec5c1d6..550bdbfd 100644 --- a/frontend/packages/core/src/pages/system/upstream/SystemInsideUpstreamContent.tsx +++ b/frontend/packages/core/src/pages/system/upstream/SystemInsideUpstreamContent.tsx @@ -79,7 +79,7 @@ const SystemInsideUpstreamContent= forwardRef if(code === STATUS_CODE.SUCCESS){ setTimeout(()=>{ form.setFieldsValue({...DEFAULT_FORM_VALUE,...data.upstream}) - setFormShowHost(data.upstream.passHost === 'rewrite') + setFormShowHost(data.upstream?.passHost === 'rewrite') },0) }else{ message.error(msg || $t(RESPONSE_TIPS.error)) diff --git a/frontend/packages/core/src/pages/team/TeamList.tsx b/frontend/packages/core/src/pages/team/TeamList.tsx index 075d753d..4efbf9f7 100644 --- a/frontend/packages/core/src/pages/team/TeamList.tsx +++ b/frontend/packages/core/src/pages/team/TeamList.tsx @@ -31,7 +31,6 @@ const TeamList:FC = ()=>{ const [curTeam, setCurTeam] = useState({} as TeamConfigFieldType) const [modalVisible, setModalVisible] = useState(false) const [modalType, setModalType] = useState<'add'|'edit'>('add') - const getTeamList = ()=>{ if(!accessInit){ getGlobalAccessData()?.then?.(()=>{getTeamList()}) diff --git a/frontend/packages/core/vite.config.ts b/frontend/packages/core/vite.config.ts index c4334d68..918a68a7 100644 --- a/frontend/packages/core/vite.config.ts +++ b/frontend/packages/core/vite.config.ts @@ -5,6 +5,7 @@ import path from 'path' import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'; import tailwindcss from 'tailwindcss'; import autoprefixer from 'autoprefixer'; +import federation from "@originjs/vite-plugin-federation"; export default defineConfig({ cacheDir: './node_modules/.vite', @@ -18,7 +19,7 @@ export default defineConfig({ chunkFileNames: 'assets/eo-[name]-[hash].js', }, }, - }, + }, css: { postcss: { plugins: [ @@ -42,6 +43,17 @@ export default defineConfig({ exclude:[], warnOnError:false }), + federation({ + name:"container", + remotes:{ + remoteApp: 'http://localhost:5001/assets/remoteEntry.js' // 远程项目的URL + }, + shared:[ + "react", + "react-dom", + ] + }) + ], resolve: { alias: [ diff --git a/frontend/packages/dashboard/src/component/MonitorTable.tsx b/frontend/packages/dashboard/src/component/MonitorTable.tsx index 66ffec60..fd46c0e1 100644 --- a/frontend/packages/dashboard/src/component/MonitorTable.tsx +++ b/frontend/packages/dashboard/src/component/MonitorTable.tsx @@ -16,8 +16,6 @@ const TableType = { provider :SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG, subscribers :APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG } -const APP_MODE = import.meta.env.VITE_APP_MODE; - type MonitorTableProps = { type:'api'|'subscribers'|'provider' @@ -77,13 +75,12 @@ const MonitorTable = forwardRef> { title: COLUMNS_TITLE.operate, key: 'option', - btnNums:2, + btnNums:1, fixed:'right', hideInSetting:true, valueType: 'option', render: (_: React.ReactNode, entity: unknown) => [ - // onRowClick(entity)} btnTitle="查看"/>, - APP_MODE === 'pro' ? onRowClick(entity)} btnTitle="查看"/> : null + onRowClick(entity)} btnTitle="查看"/> ], } ] diff --git a/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx b/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx index 3f7c18a7..aa87146d 100644 --- a/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx +++ b/frontend/packages/dashboard/src/component/MonitorTotalPage.tsx @@ -1,13 +1,11 @@ -import { App, Select, Button, Tabs, TabsProps, Empty, Drawer, Spin } from "antd"; +import { App, Button, Tabs, TabsProps, Empty, Drawer, Spin } from "antd"; import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; import { useState, useEffect, useRef, useReducer } from "react"; -import { useParams } from "react-router-dom"; import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"; import { SummaryPieData, SearchBody, PieData, MonitorApiData, MonitorSubscriberData, InvokeData, MessageData } from "@dashboard/const/type"; import { getTime, getTimeUnit, changeNumberUnit } from "../utils/dashboard"; -import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; import ScrollableSection from "@common/components/aoplatform/ScrollableSection"; import { RangeValue, TimeRange } from "@common/components/aoplatform/TimeRangeSelector"; import TimeRangeSelector from "@common/components/aoplatform/TimeRangeSelector"; @@ -19,7 +17,6 @@ import DashboardDetail from "@dashboard/pages/DashboardDetail"; import { $t } from "@common/locales"; dayjs.extend(customParseFormat); -const APP_MODE = import.meta.env.VITE_APP_MODE; export type MonitorTotalPageProps = { fetchPieData:(body:SearchBody)=>Promise> @@ -209,17 +206,17 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => { { label:$t('API 请求量 Top10'), key:'api', - children:{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorApiData,'api')}} request={()=>getTablesData(queryData||{},'api')}/> + children:{ getDetailData(record as MonitorApiData,'api')}} request={()=>getTablesData(queryData||{},'api')}/> }, { label:$t('消费者调用量 Top10'), key:'subscribers', - children:{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorSubscriberData,'subscriber')}} request={()=>getTablesData(queryData||{},'subscriber')} /> + children:{getDetailData(record as MonitorSubscriberData,'subscriber')}} request={()=>getTablesData(queryData||{},'subscriber')} /> }, { label:$t('服务被调用量 Top10'), key:'providers', - children:{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorSubscriberData,'provider')}} request={()=>getTablesData(queryData||{},'provider')} /> + children:{getDetailData(record as MonitorSubscriberData,'provider')}} request={()=>getTablesData(queryData||{},'provider')} /> } ] diff --git a/frontend/packages/dashboard/src/pages/DashboardTabPage.tsx b/frontend/packages/dashboard/src/pages/DashboardTabPage.tsx index a9cb2c07..ff005815 100644 --- a/frontend/packages/dashboard/src/pages/DashboardTabPage.tsx +++ b/frontend/packages/dashboard/src/pages/DashboardTabPage.tsx @@ -2,11 +2,10 @@ import { Tabs, TabsProps } from "antd"; import DashboardTotal from "./DashboardTotal"; import { Outlet, useNavigate, useParams } from "react-router-dom"; -import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; import { useEffect, useState } from "react"; import { $t } from "@common/locales"; +import { RouterParams } from "@common/const/type"; -const APP_MODE = import.meta.env.VITE_APP_MODE; export default function DashboardTabPage(){ const { dashboardType} = useParams() @@ -41,10 +40,10 @@ export default function DashboardTabPage(){ ] return (<> - {APP_MODE === 'pro' ? { + { setActiveKey(val); navigateTo(`/analytics/${val === 'total' ? val :`${val}/list`}`) }} - items={monitorTabItems} className="h-auto mt-[6px]" size="small" tabBarStyle={{paddingLeft:'10px',marginTop:'0px',marginBottom:'0px'}} /> - : } ) + items={monitorTabItems} className="h-full overflow-hidden mt-[6px] [&>.ant-tabs-content-holder]:overflow-auto" size="small" tabBarStyle={{paddingLeft:'10px',marginTop:'0px',marginBottom:'0px'}} /> + ) } \ No newline at end of file diff --git a/frontend/packages/market/src/const/serviceHub/type.ts b/frontend/packages/market/src/const/serviceHub/type.ts index a6b080f5..34e8f422 100644 --- a/frontend/packages/market/src/const/serviceHub/type.ts +++ b/frontend/packages/market/src/const/serviceHub/type.ts @@ -18,6 +18,7 @@ export type ServiceBasicInfoType = { invokeAddress:string approvalType:'auto'|'manual' serviceKind:'ai'|'rest' + sitePrefix?:string } export type ServiceDetailType = { diff --git a/frontend/packages/market/src/index.css b/frontend/packages/market/src/index.css index 9154cbf7..69e22726 100644 --- a/frontend/packages/market/src/index.css +++ b/frontend/packages/market/src/index.css @@ -335,6 +335,7 @@ p{ background-color:transparent } + /* .hidden-switcher .ant-tree-switcher { @apply hidden; } */ diff --git a/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx b/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx index d6d10f00..273b0b6d 100644 --- a/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx @@ -1,191 +1,198 @@ -import {Link, useNavigate, useParams} from "react-router-dom"; -import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; -import { App, Avatar, Button, Descriptions, Divider, Tabs} from "antd"; -import { useEffect, useMemo, useRef, useState} from "react"; -import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; -import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx"; -import {useFetch} from "@common/hooks/http.ts"; -import {DefaultOptionType} from "antd/es/cascader"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import { App, Avatar, Button, Descriptions, Divider, Tabs } from "antd"; +import { useEffect, useRef, useState } from "react"; +import { useBreadcrumb } from "@common/contexts/BreadcrumbContext.tsx"; +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const.tsx"; +import { useFetch } from "@common/hooks/http.ts"; +import { DefaultOptionType } from "antd/es/cascader"; import { ApplyServiceHandle, ServiceBasicInfoType, ServiceDetailType } from "../../const/serviceHub/type.ts"; -import { EntityItem } from "@common/const/type.ts"; +import { EntityItem, RouterParams } from "@common/const/type.ts"; import { ApplyServiceModal } from "./ApplyServiceModal.tsx"; import ServiceHubApiDocument from "./ServiceHubApiDocument.tsx"; -import { ApiFilled, ArrowLeftOutlined } from "@ant-design/icons"; -import { SimpleSystemItem } from "@core/const/system/type.ts"; +import Integrate from "./integrate.tsx"; +import { ApiFilled, ArrowLeftOutlined, BgColorsOutlined } from "@ant-design/icons"; import { Icon } from "@iconify/react/dist/iconify.js"; import DOMPurify from 'dompurify'; import { $t } from "@common/locales/index.ts"; import { approvalTypeTranslate } from "@market/const/serviceHub/const.tsx"; -const ServiceHubDetail = ()=>{ - const {serviceId} = useParams(); - const {setBreadcrumb} = useBreadcrumb() - const [serviceBasicInfo, setServiceBasicInfo] = useState() - const [serviceName, setServiceName] = useState() - const [serviceDesc, setServiceDesc] = useState() - const [serviceDoc, setServiceDoc] = useState() - const {fetchData} = useFetch() - const applyRef = useRef(null) - const { modal,message } = App.useApp() - const [mySystemOptionList, setMySystemOptionList] = useState() - // const [applied,setApplied] = useState(false) - // const [activeKey, setActiveKey] = useState([]) - const [service, setService] = useState() - const navigate = useNavigate(); +const ServiceHubDetail = () => { + const { serviceId } = useParams(); + const { setBreadcrumb } = useBreadcrumb() + const [serviceBasicInfo, setServiceBasicInfo] = useState() + const [serviceName, setServiceName] = useState() + const [serviceDesc, setServiceDesc] = useState() + const [serviceDoc, setServiceDoc] = useState() + const { fetchData } = useFetch() + const applyRef = useRef(null) + const { modal, message } = App.useApp() + const [mySystemOptionList, setMySystemOptionList] = useState() + // const [applied,setApplied] = useState(false) + // const [activeKey, setActiveKey] = useState([]) + const [service, setService] = useState() + const navigate = useNavigate(); - const modifyApiDoc = (apiDoc:string, apiPrefix:string)=>{ - if(!apiDoc) return '' - if(!apiPrefix) return apiDoc - try{ - const openApiSpec = JSON.parse(apiDoc); - // 遍历并修改 paths,给每个路径添加前缀 - const modifiedPaths:Record = {}; - for (const [path, pathItem] of Object.entries(openApiSpec.paths)) { - modifiedPaths[apiPrefix + path] = pathItem; - } - openApiSpec.paths = modifiedPaths; - return JSON.stringify(openApiSpec); - }catch(err){ - console.warn('拼接api前缀失败',err) - } - return apiDoc + const modifyApiDoc = (apiDoc: string, apiPrefix: string) => { + if (!apiDoc) return '' + if (!apiPrefix) return apiDoc + try { + const openApiSpec = JSON.parse(apiDoc); + // 遍历并修改 paths,给每个路径添加前缀 + const modifiedPaths: Record = {}; + for (const [path, pathItem] of Object.entries(openApiSpec.paths)) { + modifiedPaths[apiPrefix + path] = pathItem; + } + openApiSpec.paths = modifiedPaths; + return JSON.stringify(openApiSpec); + } catch (err) { + console.warn('拼接api前缀失败', err) } + return apiDoc + } - const getServiceBasicInfo = ()=>{ - fetchData>('catalogue/service',{method:'GET',eoParams:{service:serviceId}, eoTransformKeys:['app_num','api_num','update_time','api_doc','invoke_address','approval_type','service_kind']}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setService({...data.service,apiDoc:modifyApiDoc(data.service.apiDoc, data.service.basic?.invokeAddress)}) - setServiceBasicInfo(data.service.basic) - setServiceName(data.service.name) - setServiceDesc(data.service.description) - setServiceDoc(DOMPurify.sanitize(data.service.document)) - }else{ - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) + const getServiceBasicInfo = () => { + fetchData>('catalogue/service', { method: 'GET', eoParams: { service: serviceId }, eoTransformKeys: ['app_num', 'api_num', 'update_time', 'api_doc', 'invoke_address', 'approval_type', 'service_kind','site_prefix'] }).then(response => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setService({ ...data.service, apiDoc: modifyApiDoc(data.service.apiDoc, data.service.basic?.invokeAddress) }) + setServiceBasicInfo(data.service.basic) + setServiceName(data.service.name) + setServiceDesc(data.service.description) + setServiceDoc(DOMPurify.sanitize(data.service.document)) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + useEffect(() => { + if (!serviceId) { + console.warn('缺少serviceId') + return } + serviceId && getServiceBasicInfo() + }, [serviceId]); - useEffect(() => { - if(!serviceId){ - console.warn('缺少serviceId') - return - } - serviceId && getServiceBasicInfo() - }, [serviceId]); - - useEffect(() => { - getMySelectList() - setBreadcrumb( - [ - {title:{$t('服务市场')}}, - {title:$t('服务详情')} - ] - ) - - }, []); - - - const getMySelectList = ()=>{ - setMySystemOptionList([]) - fetchData>('apps/can_subscribe',{method:'GET'}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setMySystemOptionList(data.app?.map((x:EntityItem)=>{return { - label:x.name, value:x.id - }})) - }else{ - message.error(msg || $t(RESPONSE_TIPS.error)) - } - }) - } - - - const openModal = (type:'apply')=>{ - modal.confirm({ - title:$t('申请服务'), - content:, - onOk:()=>{ - return applyRef.current?.apply().then((res)=>{ - // if(res === true) setApplied(true) - }) - }, - okText:$t('确认'), - cancelText:$t('取消'), - closable:true, - icon:<>, - width:600 - }) - } - - const items = [ - { - key: 'introduction', - label: $t('介绍'), - children: <>
, - icon: , - }, - { - key: 'api-document', - label: $t('API 文档'), - children:
, - icon: - } - ] - - return ( -
-
-
- -
- -
-
- {/* {service?.name?.substring(0,1)} */} - : undefined} - icon={serviceBasicInfo?.logo ? '' :}> - -
-

{serviceName} -

-
-

{serviceDesc || '-'}

-

{$t('Base URL')}: {serviceBasicInfo?.invokeAddress || '-'}

-
- -
-
-
-
-
- - -
-
- - {serviceBasicInfo?.appNum ?? '-'} - {serviceBasicInfo?.team?.name || '-'} - {serviceBasicInfo?.approvalType ? $t((approvalTypeTranslate[serviceBasicInfo?.approvalType] || '-' )): '-'} - {serviceBasicInfo?.catalogue?.name || '-'} - {serviceBasicInfo?.tags?.map(x=>x.name)?.join(',') || '-'} - - - - { serviceBasicInfo?.version || '-'} - {serviceBasicInfo?.updateTime || '-'} - -
-
+ useEffect(() => { + getMySelectList() + setBreadcrumb( + [ + { title: {$t('服务市场')} }, + { title: $t('服务详情') } + ] ) + + }, []); + + + const getMySelectList = () => { + setMySystemOptionList([]) + fetchData>('apps/can_subscribe', { method: 'GET' }).then(response => { + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + setMySystemOptionList(data.app?.map((x: EntityItem) => { + return { + label: x.name, value: x.id + } + })) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + + + const openModal = (type: 'apply') => { + modal.confirm({ + title: $t('申请服务'), + content: , + onOk: () => { + return applyRef.current?.apply().then((res) => { + // if(res === true) setApplied(true) + }) + }, + okText: $t('确认'), + cancelText: $t('取消'), + closable: true, + icon: <>, + width: 600 + }) + } + + const items = [ + { + key: 'introduction', + label: $t('介绍'), + children: <>
, + icon: , + }, + { + key: 'api-document', + label: $t('API 文档'), + children:
, + icon: + }, + { + key: 'api-integrate', + label: $t('集成'), + children:
, + icon: + } + ] + + return ( +
+
+
+ +
+ +
+
+ {/* {service?.name?.substring(0,1)} */} + : undefined} + icon={serviceBasicInfo?.logo ? '' : }> + +
+

{serviceName} +

+
+

{serviceDesc || '-'}

+

{$t('Base URL')}: {serviceBasicInfo?.invokeAddress || '-'}

+
+ +
+
+
+
+
+ + +
+
+ + {serviceBasicInfo?.appNum ?? '-'} + {serviceBasicInfo?.team?.name || '-'} + {serviceBasicInfo?.approvalType ? $t((approvalTypeTranslate[serviceBasicInfo?.approvalType] || '-')) : '-'} + {serviceBasicInfo?.catalogue?.name || '-'} + {serviceBasicInfo?.tags?.map(x => x.name)?.join(',') || '-'} + + + + {serviceBasicInfo?.version || '-'} + {serviceBasicInfo?.updateTime || '-'} + +
+
+ ) } export default ServiceHubDetail \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/integrate.tsx b/frontend/packages/market/src/pages/serviceHub/integrate.tsx new file mode 100644 index 00000000..4eb553bb --- /dev/null +++ b/frontend/packages/market/src/pages/serviceHub/integrate.tsx @@ -0,0 +1,71 @@ +import { ServiceDetailType } from "@market/const/serviceHub/type" +import { Input, Button, Space, message } from 'antd' +import { $t } from "@common/locales" +import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { useParams } from "react-router-dom" +import { useState, useEffect } from "react" +import { RouterParams } from "@common/const/type" +import { useFetch } from "@common/hooks/http" + +const Integrate = ({ service }: { service: ServiceDetailType }) => { + const stepClass = "leading-[20px] truncate font-bold items-center gap-[4px] mt-[15px]"; + const [url, setUrl] = useState(''); + const { serviceId} = useParams() + const {fetchData} = useFetch() + + useEffect(()=>{ + setUrl(`${service?.basic?.sitePrefix || window.location?.origin}/${serviceId}/swagger` ) + },[service]) + /** + * Agent 平台地址 + */ + const agentAddress = '/cluster'; + /** + * 消费者地址 + */ + const consumerAddress = '/consumer/list'; + /** + * 复制代码 + */ + const copyURL = async (): Promise => { + await navigator.clipboard.writeText(url) + message.success($t(RESPONSE_TIPS.copySuccess)) + } + /** + * 下载文件 + */ + const onDownload = () => { + fetchData>(`export/openapi/${serviceId}`, { method: 'GET' ,headers:{ + 'Content-Type': 'application/octet-stream' + }}).then(response => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + } + }) + } + return ( +
+
{$t('支持把当前服务对接主流的 AI Agent平台,实现在 Agent 平台上快速、安全和合规地使用企业开放的 API 能力。')}
+
{$t('可按以下步骤进行对接:')}
+

{$t('步骤一:Agent 平台上创建自定义插件')}

+
{$t('不同 Agent 平台的操作细节可查看')} {$t('《 Agent 对接手册》')}
+

{$t('步骤二:导入 API 文档数据')}

+
{$t('可通过以下 URL 或 下载 Json 文件,导入 API 文档数据到 Agent 平台中。')}
+
+ + + + + OR + +
+

{$t('步骤三:配置 API 密钥')}

+
{$t('在')} {$t('消费者')} {$t('菜单中,选择已通过本 API 服务申请的消费者,')}
+
{$t('把 "访问权限" 菜单下的密钥填入到 Agent 平台对应的插件密钥配置中。')}
+
+ ); +} +export default Integrate; \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx index 29202f45..48aadf61 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx @@ -78,7 +78,6 @@ export const ManagementAuthorityConfig = forwardRef { - //console.log(data) if(type === 'edit' && data){ form.setFieldsValue({...data,expireTime:data.expireTime === 0 ? '' : dayjs(data.expireTime * 1000)}) forceUpdate({}) diff --git a/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx b/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx index 97473e64..59e99221 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx @@ -110,7 +110,7 @@ export default function ServiceHubManagement() { })) ); if (!teamId && data.teams?.[0]?.id) { - navigateTo(data.teams[0].id); + navigateTo(`/consumer/list/${data.teams[0].id}`); } } else { message.error(msg || $t(RESPONSE_TIPS.error)); diff --git a/frontend/packages/openApi/src/pages/OpenApiList.tsx b/frontend/packages/openApi/src/pages/OpenApiList.tsx index b4f16c71..e58233ef 100644 --- a/frontend/packages/openApi/src/pages/OpenApiList.tsx +++ b/frontend/packages/openApi/src/pages/OpenApiList.tsx @@ -10,8 +10,8 @@ import {OpenApiConfig, OpenApiConfigFieldType, OpenApiConfigHandle} from "./Open import { SimpleMemberItem } from "@common/const/type.ts"; import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx"; import { frontendTimeSorter } from "@common/utils/dataTransfer.ts"; -import { OPENAPI_LIST_COLUMNS } from "@market/consts/const.tsx"; -import { OpenApiTableListItem } from "@market/consts/type.ts"; +import { OPENAPI_LIST_COLUMNS } from "@openApi/consts/const.tsx"; +import { OpenApiTableListItem } from "@openApi/consts/type.ts"; import { $t } from "@common/locales/index.ts"; diff --git a/frontend/packages/openApi/tsconfig.json b/frontend/packages/openApi/tsconfig.json index 9549c6dc..9260fb6d 100644 --- a/frontend/packages/openApi/tsconfig.json +++ b/frontend/packages/openApi/tsconfig.json @@ -21,7 +21,7 @@ "paths": { "@common/*": ["../common/src/*"], "@core/*": ["../core/src/*"], - "@market/*": ["./src/*"] + "@openApi/*": ["./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/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],