基本功能实现

This commit is contained in:
cnwhy
2023-11-10 15:14:11 +08:00
parent b24efcbb62
commit 7cca1e7d6a
21 changed files with 993 additions and 82 deletions
+3
View File
@@ -14,5 +14,8 @@ module.exports = {
'warn',
{ allowConstantExport: true },
],
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": 0,
"prefer-rest-params": 0,
},
}
+22
View File
@@ -0,0 +1,22 @@
name: CI
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
uses: actions/setup-node@v3
with:
node-version: "18.x"
- run: node -v
- run: npm install
- run: npm run build
- name: Deploy # 部署
uses: JamesIves/github-pages-deploy-action@v4.3.3
with:
branch: gh-pages # 部署后提交到那个分支
folder: dist # 这里填打包好的目录名称
+1 -1
View File
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
+419 -3
View File
@@ -14,14 +14,19 @@
"axios": "^1.6.0",
"events": "^3.3.0",
"i": "^0.3.7",
"jsonc": "^2.0.0",
"npm": "^10.2.3",
"qs": "^6.11.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/events": "^3.0.3",
"@types/qs": "^6.9.10",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react": "^4.0.3",
@@ -1519,6 +1524,12 @@
"@babel/types": "^7.20.7"
}
},
"node_modules/@types/events": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz",
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
"dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -1531,6 +1542,12 @@
"integrity": "sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==",
"dev": true
},
"node_modules/@types/qs": {
"version": "6.9.10",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz",
"integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.2.36",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-18.2.36.tgz",
@@ -1563,6 +1580,12 @@
"integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
"dev": true
},
"node_modules/@types/uuid": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz",
"integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.10.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz",
@@ -1969,6 +1992,16 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/call-bind": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.5.tgz",
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
"dependencies": {
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.1",
"set-function-length": "^1.1.1"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
@@ -2106,6 +2139,19 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/define-data-property": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.1.tgz",
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
"dependencies": {
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -2144,6 +2190,14 @@
"integrity": "sha512-/5xHPH6f00SxhHw6052r+5S1xO7gHNc89hV7tqlvnStvKbSrDqc/u6AlwPvVWWNj+s4/KL6T6y8ih+nOY0qYNA==",
"dev": true
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/esbuild": {
"version": "0.18.20",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz",
@@ -2489,6 +2543,11 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"node_modules/fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
},
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz",
@@ -2601,6 +2660,11 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -2610,6 +2674,17 @@
"node": ">=6.9.0"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
"dependencies": {
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
@@ -2665,6 +2740,19 @@
"node": ">=10"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dependencies": {
"get-intrinsic": "^1.1.3"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz",
@@ -2680,6 +2768,41 @@
"node": ">=4"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
"dependencies": {
"get-intrinsic": "^1.2.2"
}
},
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.0.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/i": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
@@ -2735,6 +2858,11 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2815,6 +2943,11 @@
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true
},
"node_modules/json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -2847,6 +2980,22 @@
"node": ">=6"
}
},
"node_modules/jsonc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz",
"integrity": "sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw==",
"dependencies": {
"fast-safe-stringify": "^2.0.6",
"graceful-fs": "^4.1.15",
"mkdirp": "^0.5.1",
"parse-json": "^4.0.0",
"strip-bom": "^4.0.0",
"strip-json-comments": "^3.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -2969,6 +3118,25 @@
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
@@ -5651,6 +5819,11 @@
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
},
"node_modules/omit.js": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz",
@@ -5718,6 +5891,18 @@
"node": ">=6"
}
},
"node_modules/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
"dependencies": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
@@ -5834,6 +6019,17 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/qs": {
"version": "6.11.2",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.2.tgz",
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -6583,6 +6779,20 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/set-function-length": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.1.1.tgz",
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
"dependencies": {
"define-data-property": "^1.1.1",
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
@@ -6609,6 +6819,16 @@
"node": ">=8"
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
@@ -6644,11 +6864,18 @@
"node": ">=8"
}
},
"node_modules/strip-bom": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
"integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"engines": {
"node": ">=8"
}
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
"engines": {
"node": ">=8"
}
@@ -7938,6 +8165,12 @@
"@babel/types": "^7.20.7"
}
},
"@types/events": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz",
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
"dev": true
},
"@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -7950,6 +8183,12 @@
"integrity": "sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==",
"dev": true
},
"@types/qs": {
"version": "6.9.10",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz",
"integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==",
"dev": true
},
"@types/react": {
"version": "18.2.36",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-18.2.36.tgz",
@@ -7982,6 +8221,12 @@
"integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
"dev": true
},
"@types/uuid": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz",
"integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "6.10.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz",
@@ -8289,6 +8534,16 @@
"update-browserslist-db": "^1.0.13"
}
},
"call-bind": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.5.tgz",
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
"requires": {
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.1",
"set-function-length": "^1.1.1"
}
},
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
@@ -8406,6 +8661,16 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"define-data-property": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.1.tgz",
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
"requires": {
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -8435,6 +8700,14 @@
"integrity": "sha512-/5xHPH6f00SxhHw6052r+5S1xO7gHNc89hV7tqlvnStvKbSrDqc/u6AlwPvVWWNj+s4/KL6T6y8ih+nOY0qYNA==",
"dev": true
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"requires": {
"is-arrayish": "^0.2.1"
}
},
"esbuild": {
"version": "0.18.20",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz",
@@ -8707,6 +8980,11 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
},
"fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz",
@@ -8789,12 +9067,28 @@
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
},
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true
},
"get-intrinsic": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
"requires": {
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
}
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
@@ -8838,6 +9132,19 @@
"slash": "^3.0.0"
}
},
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"requires": {
"get-intrinsic": "^1.1.3"
}
},
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz",
@@ -8850,6 +9157,32 @@
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"has-property-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
"requires": {
"get-intrinsic": "^1.2.2"
}
},
"has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
"hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.0.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
"requires": {
"function-bind": "^1.1.2"
}
},
"i": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
@@ -8893,6 +9226,11 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -8952,6 +9290,11 @@
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -8978,6 +9321,19 @@
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"jsonc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz",
"integrity": "sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw==",
"requires": {
"fast-safe-stringify": "^2.0.6",
"graceful-fs": "^4.1.15",
"mkdirp": "^0.5.1",
"parse-json": "^4.0.0",
"strip-bom": "^4.0.0",
"strip-json-comments": "^3.0.1"
}
},
"keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -9076,6 +9432,19 @@
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
},
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"requires": {
"minimist": "^1.2.6"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
@@ -10777,6 +11146,11 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
},
"omit.js": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz",
@@ -10832,6 +11206,15 @@
"callsites": "^3.0.0"
}
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
}
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
@@ -10924,6 +11307,14 @@
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
"requires": {}
},
"qs": {
"version": "6.11.2",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.2.tgz",
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
"requires": {
"side-channel": "^1.0.4"
}
},
"queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -11450,6 +11841,17 @@
}
}
},
"set-function-length": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.1.1.tgz",
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
"requires": {
"define-data-property": "^1.1.1",
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
}
},
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
@@ -11470,6 +11872,16 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
@@ -11496,11 +11908,15 @@
"ansi-regex": "^5.0.1"
}
},
"strip-bom": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
"integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="
},
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
},
"stylis": {
"version": "4.3.0",
+5
View File
@@ -16,14 +16,19 @@
"axios": "^1.6.0",
"events": "^3.3.0",
"i": "^0.3.7",
"jsonc": "^2.0.0",
"npm": "^10.2.3",
"qs": "^6.11.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/events": "^3.0.3",
"@types/qs": "^6.9.10",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react": "^4.0.3",
+1 -40
View File
@@ -1,42 +1,3 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
width: 100%;
}
+58 -13
View File
@@ -1,25 +1,28 @@
import { useState, useEffect, useCallback } from "react";
import { Col, Row } from "antd";
import { ProCard } from "@ant-design/pro-components";
import Ctx from "./uitls/ctx";
import { ProLayout } from "@ant-design/pro-components";
import { init, logout, useGolstCofnig } from "./uitls/server";
import { getConfig } from "./api";
import Home from './Pages/Home';
import Home from "./Pages/Home";
import Services from "./Pages/Services";
import Chains from "./Pages/Chains";
import "./App.css";
import { configEvent } from "./uitls/events";
const colSpan = {
xs: 24,
sm: 24,
md: 12,
lg: 12,
xl: 12,
xxl: 8,
};
function App() {
const gostInfo = useGolstCofnig();
const [gostConfig, setGostConfig] = useState<any>(null);
useEffect(() => {
init();
}, []);
useEffect(() => {
if (gostInfo) {
updateConfig();
}
}, [gostInfo]);
const updateConfig = useCallback(() => {
return getConfig().then((data) => {
setGostConfig(data);
@@ -27,6 +30,26 @@ function App() {
});
}, []);
useEffect(() => {
init();
const updateConfig = () => {
return getConfig().then((data) => {
setGostConfig(data);
return data;
});
};
configEvent.on("apiUpdate", updateConfig);
return () => {
configEvent.off("apiUpdate", updateConfig);
};
}, []);
useEffect(() => {
if (gostInfo) {
updateConfig();
}
}, [gostInfo]);
return (
<Ctx.Provider
value={{
@@ -35,7 +58,29 @@ function App() {
logout,
}}
>
{gostInfo ? <ProLayout></ProLayout> : <Home></Home>}
{gostInfo ? (
<Row style={{ padding: 16, overflow: "hidden" }}>
<Row gutter={[16, 16]}>
<Col {...colSpan}>
<ProCard boxShadow title="Services">
<Services></Services>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="Chains">
<Chains></Chains>
</ProCard>
</Col>
<Col span={24}>
<ProCard boxShadow title="All Config JSON">
<pre>{JSON.stringify(gostConfig, null, 4)}</pre>
</ProCard>
</Col>
</Row>
</Row>
) : (
<Home></Home>
)}
</Ctx.Provider>
);
}
+125
View File
@@ -0,0 +1,125 @@
import { useContext, useEffect, useState } from "react";
import { Button, Popconfirm, Space, Table } from "antd";
import Ctx from "../uitls/ctx";
import * as API from "../api";
import JsonForm from "../components/Forms/Json";
import { ChainConfig } from "../api/types";
const Chains: React.FC = () => {
const { gostConfig, updateConfig } = useContext(Ctx);
const { chains } = gostConfig || {};
const [json, setJson] = useState<any>(null);
const [config, setConfig] = useState("");
useEffect(() => {
if (json) {
setConfig(JSON.stringify(json));
}
}, [json]);
const submit = async (v?: string) => {
const data = JSON.parse(v || config);
if (json) {
await API.chains.put(data.name, data);
} else {
await API.chains.post(data);
}
};
const addService = async (servic: any) => {
const data = JSON.parse(servic);
await API.chains.post(data);
};
const updateService = async (id: string, servic: any) => {
const data = JSON.parse(servic);
await API.chains.put(id, data);
};
const deleteService = async (servic: any) => {
if (json === servic) {
setJson(null);
}
await API.chains.delete(servic.name);
};
return (
<div>
<Table
size="small"
dataSource={chains}
columns={[
{ title: "Name", dataIndex: "name", width: 100 },
{
title: "详情",
ellipsis: true,
render: (value, record: ChainConfig, index) => {
const { hops } = record;
const _hops = hops.map((hop) => {
const { nodes } = hop;
const _nodes = nodes.map((node) => {
const {
addr,
connector: { type: connectorType },
dialer: { type: dialerType },
} = node;
return `${connectorType}${
dialerType ? "+" + dialerType : ""
}://${addr}`;
});
return _nodes.join(",");
});
return _hops.join(" -> ");
},
},
{
title: "操作",
width: 120,
render: (value, record, index) => {
return (
<Space size={"small"}>
<JsonForm
layoutType="ModalForm"
trigger={
<Button type="link" size={"small"}>
</Button>
}
initialValues={{ value: JSON.stringify(record, null, 4) }}
onFinish={async (values: any) => {
const { value } = values;
await updateService(record.name, value);
return true;
}}
></JsonForm>
<Popconfirm
title="警告"
description="确定要删除吗?"
onConfirm={() => deleteService(record)}
>
<Button type="link" size={"small"}>
</Button>
</Popconfirm>
</Space>
);
},
},
]}
></Table>
<div>
<JsonForm
title="添加 Chains"
layoutType="ModalForm"
trigger={<Button></Button>}
onFinish={async (values: any) => {
const { value } = values;
await addService(value);
return true;
}}
></JsonForm>
</div>
</div>
);
};
export default Chains;
+74 -5
View File
@@ -1,9 +1,18 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from "react";
import { BetaSchemaForm } from "@ant-design/pro-components";
import {
BetaSchemaForm,
ProForm,
LoginForm,
ProFormText,
} from "@ant-design/pro-components";
import type {
ProFormColumnsType,
ProFormLayoutType,
} from "@ant-design/pro-components";
import { GlobalOutlined, LockOutlined, UserOutlined } from "@ant-design/icons";
import { Space } from "antd";
import { login } from "../uitls/server";
type DataItem = { name: string; state: string };
const columns: ProFormColumnsType<DataItem>[] = [
@@ -26,11 +35,71 @@ const columns: ProFormColumnsType<DataItem>[] = [
const Home: React.FC = () => {
return (
<div>
<BetaSchemaForm<DataItem>
layoutType="Form"
<div style={{ height: "100%" }}>
{/* <BetaSchemaForm<DataItem>
layoutType=""
layout="horizontal"
// grid
columns={columns}
></BetaSchemaForm>
></BetaSchemaForm> */}
<LoginForm
title="GOST(v3) 动态配制客户端"
subTitle="首先连接API服务"
layout="horizontal"
submitter={{
searchConfig: { submitText: "连接" },
}}
onFinish={(value) => {
return login({
addr: value.baseURL,
auth: {
username: value.username,
password: value.passowrd,
},
});
}}
>
<ProFormText
name="baseURL"
fieldProps={{
size: "large",
prefix: <GlobalOutlined className={"prefixIcon"} />,
}}
placeholder={"API baseURL"}
rules={[
{
required: true,
message: "请输入API地址",
},
]}
/>
<ProFormText
name="username"
fieldProps={{
size: "large",
prefix: <UserOutlined className={"prefixIcon"} />,
}}
placeholder={"username"}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: "large",
prefix: <LockOutlined className={"prefixIcon"} />,
}}
placeholder={"password"}
/>
</LoginForm>
<div>
<table>
<tr>
<th></th>
<th></th>
</tr>
<tbody></tbody>
</table>
</div>
</div>
);
};
+153
View File
@@ -0,0 +1,153 @@
import { useContext, useEffect, useState } from "react";
import { Button, Popconfirm, Space, Table } from "antd";
import qs from 'qs';
// import { ProTable, ProCard } from "@ant-design/pro-components";
import Ctx from "../uitls/ctx";
import * as API from "../api";
import JsonForm from "../components/Forms/Json";
import { ServiceConfig } from "../api/types";
const Services: React.FC = () => {
const { gostConfig, updateConfig } = useContext(Ctx);
const { services } = gostConfig || {};
const [json, setJson] = useState<any>(null);
const [config, setConfig] = useState("");
useEffect(() => {
if (json) {
setConfig(JSON.stringify(json));
}
}, [json]);
const submit = async (v?: string) => {
const data = JSON.parse(v || config);
if (json) {
await API.services.put(data.name, data);
} else {
await API.services.post(data);
}
};
const addService = async (servic: any) => {
const data = JSON.parse(servic);
await API.services.post(data);
};
const updateService = async (id: string, servic: any) => {
const data = JSON.parse(servic);
await API.services.put(id, data);
};
const deleteService = async (servic: any) => {
if (json === servic) {
setJson(null);
}
await API.services.delete(servic.name);
};
return (
<div>
<Table
size="small"
dataSource={services}
columns={[
{ title: "Name", dataIndex: "name", width: 100 },
{
title: "详情",
ellipsis: true,
render: (value, record: ServiceConfig, index) => {
const {handler,listener, addr} = record;
const xy = handler.type === listener.type ? handler.type : handler.type + '+' + listener.type;
const auth = handler.auth ? handler.auth.username + ':' + handler.auth.password + '@' : '';
const metadata = handler.metadata ? qs.stringify(handler.metadata) : '';
return `${xy}://${auth}${addr}?${metadata}` ;
},
},
{
title: "操作",
width: 120,
render: (value, record, index) => {
return (
<Space size={"small"}>
{/* <Button
type="link"
size={"small"}
onClick={() => setJson(record)}
>
修改
</Button> */}
<JsonForm
layoutType="ModalForm"
trigger={
<Button type="link" size={"small"}>
</Button>
}
initialValues={{ value: JSON.stringify(record, null, 4) }}
onFinish={async (values: any) => {
const { value } = values;
await updateService(record.name, value);
return true;
}}
></JsonForm>
<Popconfirm
title="警告"
description="确定要删除吗?"
onConfirm={() => deleteService(record)}
// okText="Yes"
// cancelText="No"
>
<Button type="link" size={"small"}>
</Button>
</Popconfirm>
</Space>
);
},
},
]}
>
{/* {services?.length ? (
services.map((servic) => (
<ProCard
key={servic.name}
colSpan={colSpan}
title={servic.name}
extra={
<Space>
<span onClick={() => setJson(servic)}>查看</span>
<Popconfirm
title="警告"
description="确定要删除吗?"
onConfirm={() => deleteService(servic)}
// okText="Yes"
// cancelText="No"
>
<span>删除</span>
</Popconfirm>
</Space>
}
>
<pre>{JSON.stringify(servic)}</pre>
</ProCard>
))
) : (
<ProCard>无数据</ProCard>
)} */}
</Table>
<div>
<JsonForm
title="添加 Services"
layoutType="ModalForm"
trigger={<Button>{"添加服务"}</Button>}
onFinish={async (values: any) => {
const { value } = values;
await addService(value);
return true;
}}
></JsonForm>
</div>
</div>
);
};
export default Services;
+2
View File
@@ -1,3 +1,5 @@
// 从 swagger.yaml 提取;
export type APIConfig = {
accesslog: boolean;
addr: string;
+57
View File
@@ -0,0 +1,57 @@
import React from "react";
import {
BetaSchemaForm,
ProForm,
ProFormTextArea,
type ProFormColumnsType,
ModalForm,
} from "@ant-design/pro-components";
import { FormSchema } from "@ant-design/pro-form/es/components/SchemaForm/typing";
type Data = { value: string };
const columns: ProFormColumnsType<Data>[] = [
{
// width: 'xs',
dataIndex: "value",
title: "config",
valueType: "textarea",
initialValue: "112233",
},
{
// width: 'xs',
dataIndex: "value1",
title: "config",
valueType: "textarea",
initialValue: "112233",
},
// {
// width: 'xs',
// title: '标题',
// dataIndex: 'groupTitle',
// tip: '标题过长会自动收缩',
// formItemProps: {
// rules: [
// {
// required: true,
// message: '此项为必填项',
// },
// ],
// },
// },
];
type Props = Omit<FormSchema, "columns">;
const JsonForm: React.FC<any> = (props) => {
return (
// <BetaSchemaForm<Data, "text">
// {...(props as any)}
// columns={columns}
// ></BetaSchemaForm>
<ModalForm {...props}>
<ProFormTextArea fieldProps={{rows: 16}} name="value" label="JSON"></ProFormTextArea>
</ModalForm>
);
};
export default JsonForm;
+29
View File
@@ -0,0 +1,29 @@
import {
BetaSchemaForm,
type ProFormColumnsType,
} from "@ant-design/pro-components";
import { ServiceConfig } from "../../api/types";
const columns: ProFormColumnsType<ServiceConfig>[] = [
{
dataIndex:'name',
title: "服务名",
valueType: 'text',
},
{
dataIndex:'addr',
title: "地址端口",
valueType: 'text',
},
{
dataIndex:'addr',
title: "地址端口",
valueType: 'text',
}
];
const ServiceForm: React.FC<any> = (props) => {
return <BetaSchemaForm<ServiceConfig> columns={columns}></BetaSchemaForm>;
};
export default ServiceForm;
View File
+1
View File
@@ -29,6 +29,7 @@ body {
place-items: center;
min-width: 320px;
min-height: 100vh;
align-items: stretch;
}
h1 {
+3
View File
@@ -0,0 +1,3 @@
import { EventEmitter as Events } from "events";
export const configEvent = new Events();
+1 -1
View File
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import Events from "events";
import { EventEmitter as Events } from "events";
type userObject<T = any> = {
(v?: T): T;
+31 -9
View File
@@ -1,11 +1,33 @@
import axios from "axios";
import {getGost} from './server';
import { getGost } from "./server";
import { message } from "antd";
import { configEvent } from "./events";
const require = axios.create()
require.interceptors.request.use((config)=>{
const gost = getGost();
config.baseURL = gost?.addr
config.auth = gost?.auth;
return config;
})
export default require;
const require = axios.create();
require.interceptors.request.use((config) => {
const gost = getGost();
config.baseURL = gost?.addr;
config.auth = gost?.auth;
return config;
});
require.interceptors.response.use(
(res) => {
if (res.config.method !== "get") {
configEvent.emit("apiUpdate", res.config);
}
if (res.data) {
return res.data;
}
return res;
},
(error) => {
const { response } = error || {};
let msg = error.message || "出现未知错误!";
if (response?.data?.msg) {
msg = response?.data?.msg;
}
message.error(msg);
throw error;
}
);
export default require;
+6 -5
View File
@@ -42,7 +42,8 @@ export const init = async () => {
};
const verify = async (arg: GostApiConfig) => {
return axios.head(arg.addr + "/config");
const baseUrl = arg.addr.replace(/\/+$/, "");
return axios.get(baseUrl + "/config");
};
export const login = async (arg: GostApiConfig, saveLocal?: false) => {
@@ -62,9 +63,9 @@ export const logout = async () => {
export const save2Local = async (arg: GostApiConfig, id: string) => {
let servers: any = {};
try {
let serversJson = localStorage.getItem(localServersKey);
const serversJson = localStorage.getItem(localServersKey);
servers = serversJson ? JSON.parse(serversJson) : [];
} catch (e) {}
} catch (e) { /* empty */ }
servers[id] = arg;
localStorage.setItem(localServersKey, JSON.stringify(servers));
};
@@ -72,9 +73,9 @@ export const save2Local = async (arg: GostApiConfig, id: string) => {
export const getLocalServer = async (id: string): Promise<GostApiConfig> => {
let servers: any = {};
try {
let serversJson = localStorage.getItem(localServersKey);
const serversJson = localStorage.getItem(localServersKey);
servers = serversJson ? JSON.parse(serversJson) : [];
} catch (e) {}
} catch (e) { /* empty */ }
return servers[id];
};
-3
View File
@@ -1,8 +1,5 @@
/// <reference types="vite/client" />
declare module 'uuid';
declare module 'events';
interface Window {
__GOST_SERVER__: any;
__USE_SERVER__: any;
+2 -2
View File
@@ -16,8 +16,8 @@
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],