diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..90f9de1 --- /dev/null +++ b/.env.development @@ -0,0 +1,2 @@ +VITE_API_BASE_URL=http://localhost:3000/api +VUE_APP_ENV=development \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..e72f72b --- /dev/null +++ b/.env.production @@ -0,0 +1,2 @@ +VITE_API_BASE_URL=http://localhost:3000/api # 替换为自己的生产环境域名 +VUE_APP_ENV=production \ No newline at end of file diff --git a/package.json b/package.json index 882ec1f..140e4c5 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "type-check": "vue-tsc --build" }, "dependencies": { + "axios": "^1.13.2", "echarts": "^6.0.0", "neoeasytierweb": "link:", "tailwindcss": "^4.1.17", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfcc848..184d080 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + axios: + specifier: ^1.13.2 + version: 1.13.2 echarts: specifier: ^6.0.0 version: 6.0.0 @@ -415,67 +418,56 @@ packages: resolution: {integrity: sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.53.1': resolution: {integrity: sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.53.1': resolution: {integrity: sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.53.1': resolution: {integrity: sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.53.1': resolution: {integrity: sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.53.1': resolution: {integrity: sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.53.1': resolution: {integrity: sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.53.1': resolution: {integrity: sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.53.1': resolution: {integrity: sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.53.1': resolution: {integrity: sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.53.1': resolution: {integrity: sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openharmony-arm64@4.53.1': resolution: {integrity: sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==} @@ -540,28 +532,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.1.17': resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.1.17': resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.1.17': resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.1.17': resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} @@ -710,6 +698,12 @@ packages: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + baseline-browser-mapping@2.8.25: resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==} hasBin: true @@ -726,9 +720,17 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + caniuse-lite@1.0.30001754: resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -767,10 +769,18 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + echarts@6.0.0: resolution: {integrity: sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==} @@ -788,6 +798,22 @@ packages: error-stack-parser-es@1.0.5: resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -809,18 +835,58 @@ packages: picomatch: optional: true + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -908,28 +974,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} @@ -953,10 +1015,22 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} @@ -1028,6 +1102,9 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + read-package-json-fast@4.0.0: resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==} engines: {node: ^18.17.0 || >=20.5.0} @@ -1819,6 +1896,16 @@ snapshots: ansis@4.2.0: {} + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + baseline-browser-mapping@2.8.25: {} birpc@2.8.0: {} @@ -1835,8 +1922,17 @@ snapshots: dependencies: run-applescript: 7.1.0 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + caniuse-lite@1.0.30001754: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + convert-source-map@2.0.0: {} copy-anything@4.0.5: @@ -1866,8 +1962,16 @@ snapshots: define-lazy-prop@3.0.0: {} + delayed-stream@1.0.0: {} + detect-libc@2.1.2: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + echarts@6.0.0: dependencies: tslib: 2.3.0 @@ -1884,6 +1988,21 @@ snapshots: error-stack-parser-es@1.0.5: {} + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -1921,13 +2040,55 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + follow-redirects@1.15.11: {} + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + gopd@1.2.0: {} + graceful-fs@4.2.11: {} + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + hookable@5.5.3: {} is-docker@3.0.0: {} @@ -2015,8 +2176,16 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} + memorystream@0.3.1: {} + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mitt@3.0.1: {} mrmime@2.0.1: {} @@ -2073,6 +2242,8 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + proxy-from-env@1.1.0: {} + read-package-json-fast@4.0.0: dependencies: json-parse-even-better-errors: 4.0.0 diff --git a/src/App.vue b/src/App.vue index a1b64b2..6840c91 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,33 +1,36 @@ - - - - - - - - 主页 - 节点监控 - 提交节点 - - EasyTierMC Uptime - + 主页 节点监控 提交节点 + 管理控制台 + 登录 diff --git a/src/router/index.ts b/src/router/index.ts index 2efc3c1..e8738af 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -19,6 +19,16 @@ const router = createRouter({ name: 'submit', component: () => import('../views/SubmitView.vue'), }, + { + path: '/login', + name: 'login', + component: () => import('../views/LoginView.vue'), + }, + { + path: '/dashboard', + name: 'dashboard', + component: () => import('../views/DashboardView.vue'), + }, ], }) diff --git a/src/utils/request/api.ts b/src/utils/request/api.ts new file mode 100644 index 0000000..e26a758 --- /dev/null +++ b/src/utils/request/api.ts @@ -0,0 +1,88 @@ +import Api from './index' + +export interface HealthResponse { + status?: string + uptime?: number + [key: string]: any +} + +export function getHealth() { + const path = import.meta.env.VITE_HEALTH_PATH || '/health' + return Api.get(path) +} + +export function getApiDocsUrl() { + return import.meta.env.VITE_API_DOCS_URL || `${import.meta.env.VITE_API_BASE_URL}/api` +} + +export interface LoginResponse { + token: string + [key: string]: any +} + +export async function login(username: string, password: string) { + const res = (await Api.post('/auth/login', { username, password })) as unknown as LoginResponse + const token = (res as any)?.data.token + if (token) { + localStorage.setItem('auth_token', token) + } + return res +} + +export function logout() { + localStorage.removeItem('auth_token') +} + +export function isAuthenticated() { + return !!localStorage.getItem('auth_token') +} + +export function getMe() { + return (Api.get('/auth/me') as Promise) +} + +// Admin list (requires admin role) +export function listAdmins() { + return Api.get('/admins') as Promise +} + +export function deleteAdmin(id: string | number) { + return Api.delete(`/admins/${id}`) +} + +export function createApiKey(data: any) { + return Api.post('/api-keys', data) +} + +export function listApiKeys() { + return Api.get('/api-keys') as Promise +} + +export function toggleApiKeyStatus(id: string | number, status: string) { + return Api.patch(`/api-keys/${id}/status`, { status }) +} + +export function deleteApiKey(id: string | number) { + return Api.delete(`/api-keys/${id}`) +} + +export function createNode(data: any) { + return Api.post('/nodes', data) +} + +export function listNodes() { + return Api.get('/nodes') as Promise +} + +export function deleteNode(id: string | number) { + return Api.delete(`/nodes/${id}`) +} + +export function updateNodeStatus(id: string | number, status: string) { + return Api.put(`/nodes/${id}/status`, { status }) +} + +// Public peers (optional API key) +export function getPeers() { + return Api.get('/peers') as Promise +} \ No newline at end of file diff --git a/src/utils/request/index.ts b/src/utils/request/index.ts new file mode 100644 index 0000000..be852f9 --- /dev/null +++ b/src/utils/request/index.ts @@ -0,0 +1,39 @@ +import axios from 'axios' + +const Api = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL, + headers: { + 'Content-Type': 'application/json' + }, + withCredentials: false, + timeout: 30000 +}) + +Api.interceptors.request.use( + (config) => { + const token = localStorage.getItem('auth_token') + if (token) { + config.headers = config.headers || {} + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error) => Promise.reject(error) +) + +Api.interceptors.response.use( + (response) => response.data, + (error) => { + if (error.response) { + const { status, data } = error.response + const message = data?.message || `Request failed with status ${status}` + return Promise.reject(new Error(message)) + } + if (error.request) { + return Promise.reject(new Error('Network error or no response from server')) + } + return Promise.reject(error) + } +) + +export default Api \ No newline at end of file diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue new file mode 100644 index 0000000..be9c086 --- /dev/null +++ b/src/views/DashboardView.vue @@ -0,0 +1,433 @@ + + + + + 加载中... + {{ error }} + + + + + 管理控制台 + + 欢迎,{{ currentUser?.username }} + {{ currentUser.role }} + + + 退出登录 + + + + + + 节点管理 + + + API Keys + + + 管理员 + + + + + + + 节点列表 + + + + + + + + ID + 名称 + 地址 + 协议 + 最大连接 + 中继 + 区域 + 运营商 + 状态 + 响应时间 + 操作 + + + + + 加载中... + + + 暂无节点 + + + {{ node.id }} + + {{ node.name }} + {{ node.description }} + + + {{ node.host }}:{{ node.port }} + 网络: {{ node.network_name }} + + + {{ node.protocol?.toUpperCase() }} + + {{ node.max_connections }} + + 允许 + 禁止 + + {{ node.region || '-' }} + {{ node.ISP || '-' }} + + + {{ node.status || 'Unknown' }} + + + {{ new Date(node.last_status_update).toLocaleString() }} + + + + {{ node.response_time }}ms + - + + + + + 切换 + + + 删除 + + + + QQ: {{ node.qq_number }} + {{ node.mail }} + + + + + + + + + + + + API Key 列表 + + {{ showApiKeyForm ? '取消' : '+ 创建 API Key' }} + + + + + + + 创建新 API Key + + + + 创建 + + + + + + + + + + ID + Key + 描述 + 速率限制 + 状态 + 操作 + + + + + 加载中... + + + 暂无 API Key + + + {{ key.id }} + {{ key.key }} + {{ key.description }} + {{ key.rate_limit}} + + + {{ key.is_active }} + + + + + 切换状态 + + + 删除 + + + + + + + + + + + + 管理员列表 + + + + + + + ID + 用户名 + Email + 创建时间 + 更新时间 + 操作 + + + + + 加载中... + + + 暂无管理员 + + + {{ user.id }} + {{ user.username }} + {{ user.email }} + {{ new Date(user.created_at).toLocaleDateString()}} + {{ new Date(user.updated_at).toLocaleDateString()}} + + + 删除 + + 当前用户 + + + + + + + + + + + + + diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue new file mode 100644 index 0000000..a11153f --- /dev/null +++ b/src/views/LoginView.vue @@ -0,0 +1,70 @@ + + + + + + + + 登录 + + + + + 用户账户 + + + + + + 登陆密码 + + + + + + {{ error }} + + + {{loading ? '登录中...' : '登录' }} + + + + + + + + + diff --git a/src/views/SubmitView.vue b/src/views/SubmitView.vue index 1ae18b2..276304f 100644 --- a/src/views/SubmitView.vue +++ b/src/views/SubmitView.vue @@ -1,10 +1,211 @@ - - 提交节点 - 这里是提交节点页面。 + + + 提交节点 + 填写以下信息提交新的 EasyTier 节点 + + + + 节点信息 + + + + + + + 节点名称 * + + + + + + + 主机地址 * + + + + + + + + + 端口 * + + + + + + + 最大连接数 * + + + + + + + + + 协议 * + + + + + HTTP + + + + HTTPS + + + + WS + + + + WSS + + + + + + + + + 允许中继连接 + + + + + 网络配置 + + + + + 网络名称 + + + + + + + 网络密钥 + + + + + + + 地理位置 + + + + + 区域位置 + + + + + + + 运营商 + + + + + + + 联系方式 + + + + + QQ 号码 + + + + + + + 邮箱地址 + + + + + + + + + 节点描述 + + + + + + + 重置 + + + {{ submitting ? '提交中...' : '提交节点' }} + + + + + +
+ 欢迎,{{ currentUser?.username }} + {{ currentUser.role }} +
这里是提交节点页面。
填写以下信息提交新的 EasyTier 节点