feat: 添加 eslint-plugin-unicorn 依赖,更新 ESLint 配置以支持新规则
All checks were successful
/ depcheck (push) Successful in 2m3s
/ build-and-deploy-to-vercel (push) Successful in 2m52s
/ lint-build-and-check (push) Successful in 2m57s
/ surge (push) Successful in 2m32s
/ playwright (push) Successful in 3m10s

This commit is contained in:
严浩
2025-03-14 12:50:54 +08:00
parent 8b12d3e3dd
commit 31909c906d
24 changed files with 520 additions and 294 deletions

View File

@ -3,13 +3,13 @@
import depcheck from 'depcheck';
depcheck(process.cwd(), {
const unused = await depcheck(process.cwd(), {
ignorePatterns: ['tsconfig.json'],
}).then((unused) => {
console.debug(`unused.dependencies :>> `, unused.dependencies); // an array containing the unused dependencies
console.debug(`unused.devDependencies :>> `, unused.devDependencies); // an array containing the unused devDependencies
console.debug(`unused.missing :>> `, unused.missing); // a lookup containing the dependencies missing in `package.json` and where they are used
console.debug(`unused.using :>> `, unused.using); // a lookup indicating each dependency is used by which files
console.debug(`unused.invalidFiles :>> `, unused.invalidFiles); // files that cannot access or parse
console.debug(`unused.invalidDirs :>> `, unused.invalidDirs); // directories that cannot access
});
console.debug(`unused.dependencies :>>`, unused.dependencies); // an array containing the unused dependencies
console.debug(`unused.devDependencies :>>`, unused.devDependencies); // an array containing the unused devDependencies
console.debug(`unused.missing :>>`, unused.missing); // a lookup containing the dependencies missing in `package.json` and where they are used
console.debug(`unused.using :>>`, unused.using); // a lookup indicating each dependency is used by which files
console.debug(`unused.invalidFiles :>>`, unused.invalidFiles); // files that cannot access or parse
console.debug(`unused.invalidDirs :>>`, unused.invalidDirs); // directories that cannot access

View File

@ -4,6 +4,7 @@ import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescri
import pluginImport from 'eslint-plugin-import-x';
import oxlint from 'eslint-plugin-oxlint';
import perfectionist from 'eslint-plugin-perfectionist';
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
import pluginVue from 'eslint-plugin-vue';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@ -20,6 +21,7 @@ configureVueProject({ scriptLangs: ['ts', 'tsx', 'js', 'jsx'] });
export default defineConfigWithVueTs(
includeIgnoreFile(gitignorePath), // oxlint . --fix -D correctness --ignore-path .gitignore
{ ignores: ['typed-router.d.ts'] },
{
files: ['**/*.{ts,mts,tsx,vue}'],
name: 'app/files-to-lint',
@ -33,6 +35,17 @@ export default defineConfigWithVueTs(
pluginVue.configs['flat/essential'],
vueTsConfigs.recommended,
eslintPluginUnicorn.configs.recommended,
{
rules: {
'unicorn/filename-case': 'off',
'unicorn/no-console-spaces': 'off',
'unicorn/no-null': 'off',
'unicorn/no-useless-spread': 'off',
'unicorn/prevent-abbreviations': 'off',
},
},
// {
// ...pluginVitest.configs.recommended,
// files: ['src/**/__tests__/*'],

View File

@ -101,6 +101,7 @@
"eslint-plugin-import-x": "^4.6.1",
"eslint-plugin-oxlint": "^0.15.13",
"eslint-plugin-perfectionist": "^4.8.0",
"eslint-plugin-unicorn": "^57.0.0",
"eslint-plugin-vue": "^9.32.0",
"husky": "^9.1.7",
"less": "^4.2.2",

249
pnpm-lock.yaml generated
View File

@ -197,6 +197,9 @@ importers:
eslint-plugin-perfectionist:
specifier: ^4.8.0
version: 4.8.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)
eslint-plugin-unicorn:
specifier: ^57.0.0
version: 57.0.0(eslint@9.20.1(jiti@2.4.2))
eslint-plugin-vue:
specifier: ^9.32.0
version: 9.32.0(eslint@9.20.1(jiti@2.4.2))
@ -1446,6 +1449,9 @@ packages:
'@types/node@22.13.1':
resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==}
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
'@types/nprogress@0.2.3':
resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
@ -2265,6 +2271,11 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
browserslist@4.24.4:
resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
@ -2280,6 +2291,10 @@ packages:
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
builtin-modules@4.0.0:
resolution: {integrity: sha512-p1n8zyCkt1BVrKNFymOHjcDSAl7oq/gUvfgULv2EblgpPVQlQr9yHnWjg9IJ2MhfwPqiYqMMrr01OY7yQoK2yA==}
engines: {node: '>=18.20'}
bundle-import@0.0.2:
resolution: {integrity: sha512-XB3T6xlgqJHThyr2luo3pNAVhfN/Y2qFEsblrzUO5QZLpJtesget8jmGDImSairScy80ZKBDVcRdFzTzWv3v8A==}
@ -2375,6 +2390,10 @@ packages:
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
engines: {node: '>=18'}
ci-info@4.2.0:
resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
engines: {node: '>=8'}
citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
@ -2385,6 +2404,10 @@ packages:
resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
engines: {node: '>= 10.0'}
clean-regexp@1.0.0:
resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
engines: {node: '>=4'}
cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'}
@ -2507,6 +2530,9 @@ packages:
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
engines: {node: '>=12.13'}
core-js-compat@3.41.0:
resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==}
core-js@3.40.0:
resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==}
@ -2951,6 +2977,12 @@ packages:
eslint-config-prettier:
optional: true
eslint-plugin-unicorn@57.0.0:
resolution: {integrity: sha512-zUYYa6zfNdTeG9BISWDlcLmz16c+2Ck2o5ZDHh0UzXJz3DEP7xjmlVDTzbyV0W+XksgZ0q37WEWzN2D2Ze+g9Q==}
engines: {node: '>=18.18'}
peerDependencies:
eslint: '>=9.20.0'
eslint-plugin-vue@9.32.0:
resolution: {integrity: sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==}
engines: {node: ^14.17.0 || >=16.0.0}
@ -3113,6 +3145,10 @@ packages:
find-root@1.1.0:
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
find-up-simple@1.0.1:
resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==}
engines: {node: '>=18'}
find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
@ -3281,6 +3317,10 @@ packages:
resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==}
engines: {node: '>=18'}
globals@15.15.0:
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'}
globby@14.0.2:
resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==}
engines: {node: '>=18'}
@ -3337,6 +3377,10 @@ packages:
hookified@1.6.0:
resolution: {integrity: sha512-se7cpwTA+iA/eY548Bu03JJqBiEZAqU2jnyKdj5B5qurtBg64CZGHTgqCv4Yh7NWu6FGI09W61MCq+NoPj9GXA==}
hosted-git-info@7.0.2:
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
engines: {node: ^16.14.0 || >=18.0.0}
html-tags@3.3.1:
resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
engines: {node: '>=8'}
@ -3417,6 +3461,14 @@ packages:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
indent-string@5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
index-to-position@0.1.2:
resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==}
engines: {node: '>=18'}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
@ -3445,6 +3497,10 @@ packages:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
is-builtin-module@4.0.0:
resolution: {integrity: sha512-rWP3AMAalQSesXO8gleROyL2iKU73SX5Er66losQn9rWOWL4Gef0a/xOEOVqjWGMuR2vHG3FJ8UUmT700O8oFg==}
engines: {node: '>=18.20'}
is-core-module@2.16.1:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
@ -3595,6 +3651,11 @@ packages:
resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==}
engines: {node: '>= 10.16.0'}
jsesc@3.0.2:
resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
engines: {node: '>=6'}
hasBin: true
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@ -3861,6 +3922,10 @@ packages:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
min-indent@1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@ -4043,6 +4108,10 @@ packages:
engines: {node: ^18.17.0 || >=20.5.0}
hasBin: true
normalize-package-data@6.0.2:
resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==}
engines: {node: ^16.14.0 || >=18.0.0}
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
@ -4178,6 +4247,10 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
parse-json@8.1.0:
resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==}
engines: {node: '>=18'}
parse-ms@2.1.0:
resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==}
engines: {node: '>=6'}
@ -4324,6 +4397,10 @@ packages:
please-upgrade-node@3.2.0:
resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==}
pluralize@8.0.0:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
@ -4434,6 +4511,14 @@ packages:
resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==}
engines: {node: ^18.17.0 || >=20.5.0}
read-package-up@11.0.0:
resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==}
engines: {node: '>=18'}
read-pkg@9.0.1:
resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==}
engines: {node: '>=18'}
read@1.0.5:
resolution: {integrity: sha512-hDLATrzYLoMu23c/69pMC6u3fO3Y0qLTIygJkEZHLOn+AO2gSapu6QgrgwX9ehyVtaRoZVZbF4IuiZPPRdGgdg==}
engines: {node: '>=0.8'}
@ -4453,6 +4538,14 @@ packages:
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
regexp-tree@0.1.27:
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
hasBin: true
regjsparser@0.12.0:
resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==}
hasBin: true
request@2.88.2:
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
engines: {node: '>= 6'}
@ -4708,6 +4801,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
semver@7.7.1:
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
engines: {node: '>=10'}
hasBin: true
setprototypeof@1.1.1:
resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==}
@ -4771,6 +4869,18 @@ packages:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
deprecated: Please use @jridgewell/sourcemap-codec instead
spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
spdx-exceptions@2.5.0:
resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
spdx-expression-parse@3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
spdx-license-ids@3.0.21:
resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==}
speakingurl@14.0.1:
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
engines: {node: '>=0.10.0'}
@ -4848,6 +4958,10 @@ packages:
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
engines: {node: '>=18'}
strip-indent@4.0.0:
resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==}
engines: {node: '>=12'}
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@ -5058,6 +5172,10 @@ packages:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
type-fest@4.37.0:
resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==}
engines: {node: '>=16'}
typescript-eslint@8.20.0:
resolution: {integrity: sha512-Kxz2QRFsgbWj6Xcftlw3Dd154b3cEPFqQC+qMZrMypSijPd4UanKKvoKDrJ4o8AIfZFKAF+7sMaEIR8mTElozA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -5323,6 +5441,9 @@ packages:
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
vant@4.9.16:
resolution: {integrity: sha512-QkcxoV7MOiV+fakCPF8z/czarW42BeR0k79U9KNuM2xZs8q3YhhPxBDdrcoQ64OWIkdf5alEYeDWCuDYfiyR3g==}
peerDependencies:
@ -6684,6 +6805,8 @@ snapshots:
dependencies:
undici-types: 6.20.0
'@types/normalize-package-data@2.4.4': {}
'@types/nprogress@0.2.3': {}
'@types/parse-json@4.0.2': {}
@ -7879,6 +8002,13 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.1(browserslist@4.24.3)
browserslist@4.24.4:
dependencies:
caniuse-lite: 1.0.30001690
electron-to-chromium: 1.5.79
node-releases: 2.0.19
update-browserslist-db: 1.1.1(browserslist@4.24.4)
buffer-builder@0.2.0: {}
buffer-crc32@0.2.13: {}
@ -7895,6 +8025,8 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
builtin-modules@4.0.0: {}
bundle-import@0.0.2:
dependencies:
get-tsconfig: 4.8.1
@ -7991,6 +8123,8 @@ snapshots:
chownr@3.0.0: {}
ci-info@4.2.0: {}
citty@0.1.6:
dependencies:
consola: 3.4.0
@ -8001,6 +8135,10 @@ snapshots:
dependencies:
source-map: 0.6.1
clean-regexp@1.0.0:
dependencies:
escape-string-regexp: 1.0.5
cli-cursor@3.1.0:
dependencies:
restore-cursor: 3.1.0
@ -8119,6 +8257,10 @@ snapshots:
dependencies:
is-what: 4.1.16
core-js-compat@3.41.0:
dependencies:
browserslist: 4.24.4
core-js@3.40.0: {}
core-util-is@1.0.2: {}
@ -8568,6 +8710,26 @@ snapshots:
optionalDependencies:
eslint-config-prettier: 10.0.1(eslint@9.20.1(jiti@2.4.2))
eslint-plugin-unicorn@57.0.0(eslint@9.20.1(jiti@2.4.2)):
dependencies:
'@babel/helper-validator-identifier': 7.25.9
'@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2))
ci-info: 4.2.0
clean-regexp: 1.0.0
core-js-compat: 3.41.0
eslint: 9.20.1(jiti@2.4.2)
esquery: 1.6.0
globals: 15.15.0
indent-string: 5.0.0
is-builtin-module: 4.0.0
jsesc: 3.1.0
pluralize: 8.0.0
read-package-up: 11.0.0
regexp-tree: 0.1.27
regjsparser: 0.12.0
semver: 7.7.1
strip-indent: 4.0.0
eslint-plugin-vue@9.32.0(eslint@9.20.1(jiti@2.4.2)):
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2))
@ -8776,6 +8938,8 @@ snapshots:
find-root@1.1.0: {}
find-up-simple@1.0.1: {}
find-up@5.0.0:
dependencies:
locate-path: 6.0.0
@ -8968,6 +9132,8 @@ snapshots:
globals@15.14.0: {}
globals@15.15.0: {}
globby@14.0.2:
dependencies:
'@sindresorhus/merge-streams': 2.3.0
@ -9019,6 +9185,10 @@ snapshots:
hookified@1.6.0: {}
hosted-git-info@7.0.2:
dependencies:
lru-cache: 10.4.3
html-tags@3.3.1: {}
http-errors@1.4.0:
@ -9100,6 +9270,10 @@ snapshots:
imurmurhash@0.1.4: {}
indent-string@5.0.0: {}
index-to-position@0.1.2: {}
inflight@1.0.6:
dependencies:
once: 1.4.0
@ -9138,6 +9312,10 @@ snapshots:
dependencies:
binary-extensions: 2.3.0
is-builtin-module@4.0.0:
dependencies:
builtin-modules: 4.0.0
is-core-module@2.16.1:
dependencies:
hasown: 2.0.2
@ -9245,6 +9423,8 @@ snapshots:
jsep@1.4.0: {}
jsesc@3.0.2: {}
jsesc@3.1.0: {}
json-buffer@3.0.1: {}
@ -9509,6 +9689,8 @@ snapshots:
mimic-function@5.0.1: {}
min-indent@1.0.1: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
@ -9654,6 +9836,12 @@ snapshots:
dependencies:
abbrev: 2.0.0
normalize-package-data@6.0.2:
dependencies:
hosted-git-info: 7.0.2
semver: 7.7.1
validate-npm-package-license: 3.0.4
normalize-path@3.0.0: {}
nosleep.js@0.12.0: {}
@ -9820,6 +10008,12 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
parse-json@8.1.0:
dependencies:
'@babel/code-frame': 7.26.2
index-to-position: 0.1.2
type-fest: 4.37.0
parse-ms@2.1.0: {}
parse-ms@4.0.0: {}
@ -9929,6 +10123,8 @@ snapshots:
dependencies:
semver-compare: 1.0.0
pluralize@8.0.0: {}
postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
@ -10046,6 +10242,20 @@ snapshots:
json-parse-even-better-errors: 4.0.0
npm-normalize-package-bin: 4.0.0
read-package-up@11.0.0:
dependencies:
find-up-simple: 1.0.1
read-pkg: 9.0.1
type-fest: 4.37.0
read-pkg@9.0.1:
dependencies:
'@types/normalize-package-data': 2.4.4
normalize-package-data: 6.0.2
parse-json: 8.1.0
type-fest: 4.37.0
unicorn-magic: 0.1.0
read@1.0.5:
dependencies:
mute-stream: 0.0.8
@ -10064,6 +10274,12 @@ snapshots:
regenerator-runtime@0.14.1: {}
regexp-tree@0.1.27: {}
regjsparser@0.12.0:
dependencies:
jsesc: 3.0.2
request@2.88.2:
dependencies:
aws-sign2: 0.7.0
@ -10304,6 +10520,8 @@ snapshots:
semver@7.6.3: {}
semver@7.7.1: {}
setprototypeof@1.1.1: {}
shallow-equal@1.2.1: {}
@ -10353,6 +10571,20 @@ snapshots:
sourcemap-codec@1.4.8: {}
spdx-correct@3.2.0:
dependencies:
spdx-expression-parse: 3.0.1
spdx-license-ids: 3.0.21
spdx-exceptions@2.5.0: {}
spdx-expression-parse@3.0.1:
dependencies:
spdx-exceptions: 2.5.0
spdx-license-ids: 3.0.21
spdx-license-ids@3.0.21: {}
speakingurl@14.0.1: {}
split@1.0.1:
@ -10431,6 +10663,10 @@ snapshots:
strip-final-newline@4.0.0: {}
strip-indent@4.0.0:
dependencies:
min-indent: 1.0.1
strip-json-comments@3.1.1: {}
strip-literal@2.1.1:
@ -10687,6 +10923,8 @@ snapshots:
type-fest@0.21.3: {}
type-fest@4.37.0: {}
typescript-eslint@8.20.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.20.0(@typescript-eslint/parser@8.20.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)
@ -10988,6 +11226,12 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
update-browserslist-db@1.1.1(browserslist@4.24.4):
dependencies:
browserslist: 4.24.4
escalade: 3.2.0
picocolors: 1.1.1
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@ -11014,6 +11258,11 @@ snapshots:
v8-compile-cache-lib@3.0.1: {}
validate-npm-package-license@3.0.4:
dependencies:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
vant@4.9.16(vue@3.5.13(typescript@5.7.3)):
dependencies:
'@vant/popperjs': 1.3.0

View File

@ -57,8 +57,8 @@ const onUploader = (event: FileUploadUploaderEvent) => {
item.url = res.data.url;
}
})
.catch((err) => {
console.error(`err :>> `, err);
.catch((error) => {
console.error(`err :>> `, error);
const item = fileUploadRef.value!.uploadedFiles.find((f) => f.rawFile === file);
if (item) {
item.status = 'failed';

View File

@ -430,91 +430,89 @@ function applyTheme(type: string, color: any) {
function getPresetExt() {
const color = primaryColors.value.find((c) => c.name === layoutConfig.primary)!;
if (color.name === 'noir') {
return {
semantic: {
colorScheme: {
dark: {
highlight: {
background: '{primary.50}',
color: '{primary.950}',
focusBackground: '{primary.300}',
focusColor: '{primary.950}',
return color.name === 'noir'
? {
semantic: {
colorScheme: {
dark: {
highlight: {
background: '{primary.50}',
color: '{primary.950}',
focusBackground: '{primary.300}',
focusColor: '{primary.950}',
},
primary: {
activeColor: '{primary.300}',
color: '{primary.50}',
contrastColor: '{primary.950}',
hoverColor: '{primary.200}',
},
},
primary: {
activeColor: '{primary.300}',
color: '{primary.50}',
contrastColor: '{primary.950}',
hoverColor: '{primary.200}',
light: {
highlight: {
background: '{primary.950}',
color: '#ffffff',
focusBackground: '{primary.700}',
focusColor: '#ffffff',
},
primary: {
activeColor: '{primary.700}',
color: '{primary.950}',
contrastColor: '#ffffff',
hoverColor: '{primary.800}',
},
},
},
light: {
highlight: {
background: '{primary.950}',
color: '#ffffff',
focusBackground: '{primary.700}',
focusColor: '#ffffff',
},
primary: {
activeColor: '{primary.700}',
color: '{primary.950}',
contrastColor: '#ffffff',
hoverColor: '{primary.800}',
},
primary: {
50: '{surface.50}',
100: '{surface.100}',
200: '{surface.200}',
300: '{surface.300}',
400: '{surface.400}',
500: '{surface.500}',
600: '{surface.600}',
700: '{surface.700}',
800: '{surface.800}',
900: '{surface.900}',
950: '{surface.950}',
},
},
primary: {
50: '{surface.50}',
100: '{surface.100}',
200: '{surface.200}',
300: '{surface.300}',
400: '{surface.400}',
500: '{surface.500}',
600: '{surface.600}',
700: '{surface.700}',
800: '{surface.800}',
900: '{surface.900}',
950: '{surface.950}',
},
},
};
} else {
return {
semantic: {
colorScheme: {
dark: {
highlight: {
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
color: 'rgba(255,255,255,.87)',
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
focusColor: 'rgba(255,255,255,.87)',
}
: {
semantic: {
colorScheme: {
dark: {
highlight: {
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
color: 'rgba(255,255,255,.87)',
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
focusColor: 'rgba(255,255,255,.87)',
},
primary: {
activeColor: '{primary.200}',
color: '{primary.400}',
contrastColor: '{surface.900}',
hoverColor: '{primary.300}',
},
},
primary: {
activeColor: '{primary.200}',
color: '{primary.400}',
contrastColor: '{surface.900}',
hoverColor: '{primary.300}',
},
},
light: {
highlight: {
background: '{primary.50}',
color: '{primary.700}',
focusBackground: '{primary.100}',
focusColor: '{primary.800}',
},
primary: {
activeColor: '{primary.700}',
color: '{primary.500}',
contrastColor: '#ffffff',
hoverColor: '{primary.600}',
light: {
highlight: {
background: '{primary.50}',
color: '{primary.700}',
focusBackground: '{primary.100}',
focusColor: '{primary.800}',
},
primary: {
activeColor: '{primary.700}',
color: '{primary.500}',
contrastColor: '#ffffff',
hoverColor: '{primary.600}',
},
},
},
primary: color.palette,
},
primary: color.palette,
},
};
}
};
}
function onMenuModeChange() {

View File

@ -12,8 +12,8 @@ const { isSidebarActive, layoutConfig, layoutState } = useLayout();
const outsideClickListener = ref(null as null | Parameters<typeof document.addEventListener>[1]);
watch(isSidebarActive, (newVal) => {
if (newVal) {
watch(isSidebarActive, (newValue) => {
if (newValue) {
bindOutsideClickListener();
} else {
unbindOutsideClickListener();

View File

@ -33,31 +33,28 @@ const menuItems = computed(() => {
parentId,
};
});
const groupItems = flatArray.reduce(
(acc, flatArrItem) => {
if (
!acc.some((item) => item.id === flatArrItem.parentId) && //
flatArrItem.parentId !== '_ROOT_'
) {
let groupItemParentId = flatArrItem.parentId.replace(/\/[^/]+$/, '');
if (groupItemParentId === flatArrItem.parentId) groupItemParentId = '_ROOT_';
acc.push({
id: flatArrItem.parentId,
label: `Group ${flatArrItem.parentId}`,
parentId: groupItemParentId,
});
}
return acc;
},
[] as Record<string, string>[],
);
console.debug(`groupItems :>> `, groupItems);
const tree = arrayToTree(flatArray.concat(groupItems), { id: 'id', parentId: 'parentId', rootId: '_ROOT_' });
const groupItems: Record<string, string>[] = [];
for (const flatArrayItem of flatArray) {
if (
!groupItems.some((item) => item.id === flatArrayItem.parentId) && //
flatArrayItem.parentId !== '_ROOT_'
) {
let groupItemParentId = flatArrayItem.parentId.replace(/\/[^/]+$/, '');
if (groupItemParentId === flatArrayItem.parentId) groupItemParentId = '_ROOT_';
groupItems.push({
id: flatArrayItem.parentId,
label: `Group ${flatArrayItem.parentId}`,
parentId: groupItemParentId,
});
}
}
console.debug(`groupItems :>>`, groupItems);
const tree = arrayToTree([...flatArray, ...groupItems], { id: 'id', parentId: 'parentId', rootId: '_ROOT_' });
// 递归把 children 改为 items
function _convertChildrenToItems(tree: MenuItemWithRoute[]) {
return tree.map((item) => {
if (item.children.length) {
if (item.children.length > 0) {
item.items = _convertChildrenToItems(item.children);
} else {
item.command = (/* event */) => {

View File

@ -2,30 +2,32 @@ import type { Viewer } from 'cesium';
import * as Cesium from 'cesium';
export const VIEWER_OPTIONS: Viewer.ConstructorOptions = {
animation: true, // .cesium-viewer-animationContainer https://cesium.com/learn/ion-sdk/ref-doc/Animation.html
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')),
),
baseLayerPicker: false,
fullscreenButton: !true, // 全屏按钮
geocoder: false, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false则不会创建Geocoder小部件。
export const VIEWER_OPTIONS = (): Viewer.ConstructorOptions => {
return {
animation: true, // .cesium-viewer-animationContainer https://cesium.com/learn/ion-sdk/ref-doc/Animation.html
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')),
),
baseLayerPicker: false,
fullscreenButton: !true, // 全屏按钮
geocoder: false, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false则不会创建Geocoder小部件。
// globe: false, // 地球
homeButton: true, // Home按钮
infoBox: false, // InfoBox小部件。
navigationHelpButton: false, // 是否显示导航帮助按钮
orderIndependentTranslucency: false, // 顺序无关透明度
projectionPicker: !true, // 投影选择器
requestRenderMode: !true, // 如果为真渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率并在移动设备上节省更多电量但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
selectionIndicator: true,
shadows: true, // Determines if shadows are cast by light sources.
// globe: false, // 地球
homeButton: true, // Home按钮
infoBox: false, // InfoBox小部件。
navigationHelpButton: false, // 是否显示导航帮助按钮
orderIndependentTranslucency: false, // 顺序无关透明度
projectionPicker: !true, // 投影选择器
requestRenderMode: !true, // 如果为真渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率并在移动设备上节省更多电量但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
selectionIndicator: true,
shadows: true, // Determines if shadows are cast by light sources.
/* animationContainer: !true, */
/* timelineContainer: true, */
/* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */
shouldAnimate: !true,
showRenderLoopErrors: true, // 如果为真当发生渲染循环错误时此小部件将自动向用户显示包含错误的HTML面板。
timeline: true,
/* animationContainer: !true, */
/* timelineContainer: true, */
/* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */
shouldAnimate: !true,
showRenderLoopErrors: true, // 如果为真当发生渲染循环错误时此小部件将自动向用户显示包含错误的HTML面板。
timeline: true,
};
};

View File

@ -6,12 +6,12 @@ import 'cesium/Build/Cesium/Widgets/widgets.css';
Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_ION_TOKEN; // 用了离线地图的情况是不需要的。
Object.assign(window, { Cesium });
Object.assign(globalThis, { Cesium });
_configureCesium();
export function cesium_init(container: Element) {
const viewer = new Cesium.Viewer(container, VIEWER_OPTIONS);
const viewer = new Cesium.Viewer(container, VIEWER_OPTIONS());
viewer.scene.debugShowFramesPerSecond = true;

View File

@ -13,8 +13,8 @@ class SatelliteEntity {
private totalSeconds!: number;
private trailTime!: number;
constructor(tle2LineStr = '' /* , options = {} */) {
const [name, tleLine1, tleLine2] = this._checkTle(tle2LineStr);
constructor(tle2LineString = '' /* , options = {} */) {
const [name, tleLine1, tleLine2] = this._checkTle(tle2LineString);
const circle = Number(tleLine2.slice(52, 64));
this.name = name.trim();
@ -28,8 +28,8 @@ class SatelliteEntity {
this.trailTime = 0;
}
_checkTle(tle2LineStr: string) {
const elements = tle2LineStr.split('\n');
_checkTle(tle2LineString: string) {
const elements = tle2LineString.split('\n');
if (elements.length !== 3) throw new Error('tle data error');
return elements as [string, string, string];
}
@ -40,11 +40,11 @@ class SatelliteEntity {
const positionProperty = new Cesium.SampledPositionProperty(Cesium.ReferenceFrame.INERTIAL);
const now = Date.now();
for (let i = 0; i < this.totalSeconds / this.stepSeconds; i++) {
const sateTime = new Date(now + i * this.stepSeconds * 1000);
for (let index = 0; index < this.totalSeconds / this.stepSeconds; index++) {
const sateTime = new Date(now + index * this.stepSeconds * 1000);
const sateCoord = this.getPositionEci(sateTime);
if (!sateCoord) continue;
const cesiumTime = Cesium.JulianDate.addSeconds(start, i * this.stepSeconds, new Cesium.JulianDate());
const cesiumTime = Cesium.JulianDate.addSeconds(start, index * this.stepSeconds, new Cesium.JulianDate());
const cesiumPosition = {
x: sateCoord.x * 1000,
y: sateCoord.y * 1000,

View File

@ -1,43 +1,46 @@
/* eslint-disable perfectionist/sort-objects */
// eslint-disable no-useless-spread
/* eslint-disable unicorn/numeric-separators-style */
// eslint-disable no-unused-vars
import { twoline2satrec } from 'satellite.js';
// https://en.wikipedia.org/wiki/Two-line_element_set#Format
const longstr1 = `1 62949U 25029B 25070.91668981 .00039463 00000+0 99294-3 0 9990`;
const longstr2 = `2 62949 53.1596 120.9032 0001355 101.1211 35.9659 15.39574303 5809`;
export const DEMO_DATA = {
// #############################
tleJson: {
ARG_OF_PERICENTER: 181.9338,
BSTAR: 0.00039937,
CLASSIFICATION_TYPE: 'U',
ECCENTRICITY: 0.7375486,
ELEMENT_SET_NO: 999,
EPHEMERIS_TYPE: 0,
EPOCH: '2025-03-12T15:49:04.420416',
INCLINATION: 19.0363,
MEAN_ANOMALY: 171.615,
MEAN_MOTION: 2.21786616,
MEAN_MOTION_DDOT: -5.0502e-7,
MEAN_MOTION_DOT: 0.00072212,
NORAD_CAT_ID: 63158,
OBJECT_ID: '2025-045B',
OBJECT_NAME: '2025-045B',
RA_OF_ASC_NODE: 63.0294,
REV_AT_EPOCH: 13,
},
tleString: `2025-045B
1 63158U 25045B 25071.65907894 .00072212 -50502-6 39937-3 0 9999
2 63158 19.0363 63.0294 7375486 181.9338 171.6150 2.21786616 127`,
};
export const TLE_LIST = [
`STARLINK-32857
${longstr1}
${longstr2}`,
`STARLINK-32915
DEMO_DATA.tleString,
...[
`STARLINK-32915
1 63152U 25043W 25070.91668981 .00451203 87802-4 12020-2 0 9994
2 63152 43.0011 279.4620 0003944 269.6759 119.1758 15.93738994 2341`,
`STARLINK-32915 [测修改1]
`STARLINK-32915 [测修改1]
1 00000U 00000W 25070.91668981 .00000000 00000-0 00000-0 0 0000
2 00000 43.0011 279.4620 0003944 269.6759 119.1758 15.93738994 0000`,
];
export const TLE_LIST_JSON = [
{
ARG_OF_PERICENTER: 179.7218, // 近地点角距Argument of Perigee单位是度表示近地点相对于升交点的角度。
BSTAR: 0, // 轨道模型类型0=SGP4模型
CLASSIFICATION_TYPE: 'U', // U 表示未分类(可能是临时编号)。
ECCENTRICITY: 0.732_766_1, // 偏心率Eccentricity无单位科学记数法为 0.7327661,表示轨道是一个高度椭圆的形状(接近 1 表示非常扁平)。
ELEMENT_SET_NO: 999, // 校验码或元素集编号,表示这是第 999 次更新的 TLE 数据。
EPHEMERIS_TYPE: 0, // 轨道模型类型(通常为 0表示 SGP4 模型)。
EPOCH: '2025-03-10T08:27:09.857952',
INCLINATION: 19.0062, // 轨道倾角Inclination单位是度表示轨道平面与地球赤道的夹角。此处为 19.0062°,属于低倾角轨道。
MEAN_ANOMALY: 141.4162, // 平近点角Mean Anomaly单位是度表示卫星在轨道上的位置。
MEAN_MOTION: 2.262_061_55, // 平均运动Mean Motion单位是圈/天,表示卫星每天绕地球运行的圈数,此处约为 2.26 圈(周期约 10.6 小时)。
MEAN_MOTION_DDOT: -6.5692e-7, // 平均运动的二阶导数(科学记数法:-6.5692 × 10⁻⁶表示轨道受摄动如大气阻力的加速度变化。
MEAN_MOTION_DOT: 5.45e-6, // 0.00000545 // 平均运动的一阶导数(每天的轨道变化率),单位是圈/天²,这里非常小,表示轨道衰减缓慢。
NORAD_CAT_ID: 63_157, // NORAD
OBJECT_ID: '2025-045A',
OBJECT_NAME: '2025-045A',
RA_OF_ASC_NODE: 64.6364, // 升交点赤经RAAN, Right Ascension of Ascending Node单位是度表示轨道平面在赤道上的交叉点位置。
REV_AT_EPOCH: 2, // Checksum 校验和
},
],
];
// 为了twoline2satrec函数需要哪些参数
@ -89,61 +92,6 @@ function twoline2satrecFake(longstr1: string, longstr2: string) {
console.groupEnd();
return satrec;
}
// if ($__DEV__)
// console.debug(
// `twoline2satrecFake(longstr1, longstr2) :>>`,
// twoline2satrecFake(longstr1, longstr2),
// );
const = twoline2satrec(
`1 63157 25069.35219743 .00000545 -65692-6 00000+0 `,
`2 19.0062 64.6364 7327661 179.7218 141.4162 2.26206155 `,
);
const item = {
gdzj: '7',
wxzj: '2025029F',
wxmc: 'STARLINK-32884',
wxbh: '62953',
lysj: '25070.91668981',
ysjbh: '999',
xllx: '0',
bstarqzxt: '-0.01591824',
pjyddyjds: '-0.01591824',
drry: null,
drsj: null,
xgry: null,
xgsj: null,
isFlag: 0,
pjyddejds: '0',
gdqj: '53.1597',
sjdcj: '125.942',
pxl: '0.0001413',
jddfj: '92.4266',
pjdj: '189.6779',
pjyd: '15.48632226',
fsyldgdqs: '556',
};
const r = {
ARG_OF_PERICENTER: 101.1211,
BSTAR: 0.00099294,
CLASSIFICATION_TYPE: 'U',
ECCENTRICITY: 0.0001355,
ELEMENT_SET_NO: 999,
EPHEMERIS_TYPE: 0,
EPOCH: '2025-03-11T22:00:01.999584',
INCLINATION: 53.1596,
MEAN_ANOMALY: 35.9659,
MEAN_MOTION: 15.39574303,
MEAN_MOTION_DDOT: 0,
MEAN_MOTION_DOT: 0.00039463,
NORAD_CAT_ID: 62949,
OBJECT_ID: '2025-029B',
OBJECT_NAME: 'STARLINK-32857',
RA_OF_ASC_NODE: 120.9032,
REV_AT_EPOCH: 580,
};
const satrec1 = twoline2satrec(longstr1, longstr2); // 正确结果
let line1 = '';
line1 += '1'; //
line1 += ' '; //
@ -194,13 +142,24 @@ line2 += '9';
// `${numbers}${numbers}${numbers}${numbers}${numbers}${numbers}`,
// '',
// );
const satrec2 = twoline2satrec(
`1 62949 25070.91668981 .00039463 00000+0 99294-3 `,
`2 53.1596 120.9032 0001355 101.1211 35.9659 15.39574303 `,
);
const satrec1_str = JSON.stringify(satrec1, null, 2);
const satrec2_str = JSON.stringify(satrec2, null, 2);
if ($__DEV__) console.debug(`satrec1_str === satrec2_str :>>`, satrec1_str === satrec2_str);
// if ($__DEV__) {
// const tle = TLE_LIST[0] as string;
// const line1 = tle.split('\n')[1] as string;
// const line2 = tle.split('\n')[2] as string;
// console.clear();
// twoline2satrecFake(line1, line2);
// }
// if ($__DEV__) {
// const satrec2 = twoline2satrec(
// `1 62949 25070.91668981 .00039463 00000+0 99294-3 `,
// `2 53.1596 120.9032 0001355 101.1211 35.9659 15.39574303 `,
// );
// const satrec1_str = JSON.stringify(satrec1, null, 2);
// const satrec2_str = JSON.stringify(satrec2, null, 2);
// console.debug(`satrec1_str === satrec2_str :>>`, satrec1_str === satrec2_str);
// }
// longstr1.substring(2, 7) :>> "63157"
// longstr1.substring(18, 20) :>> "25"

View File

@ -0,0 +1,20 @@
/* prettier-ignore */
export const TOOLTIP_MAP = {
ARG_OF_PERICENTER_近地点幅角: "8位数字如'181.9338'表示近地点相对升交点的角度范围0°-360°",
BSTAR_BSTAR拖曳项: "BSTAR参数。8位科学计数法如'39937-3'表示0.39937×10⁻³/地球半径,表示大气拖曳影响",
CLASSIFICATION_TYPE_卫星分类: "1个字母如'U',表示数据分类",
ECCENTRICITY_离心率: "7位数字无小数点如'7375486'表示0.7375486,小数点隐含在最前面",
ELEMENT_SET_NO_元素集编号: "4位数字如'9999'表示TLE版本号",
EPHEMERIS_TYPE_星历类型: "通常为'0'表示使用SGP4星历模型",
EPOCH_历元时间: "14位数字如'25071.65907894',表示轨道数据的参考时间(年份+年积日.一天中的小数部分)",
// CHECKSUM_校验和: "1位数字用于验证数据完整性可选项",
INCLINATION_轨道倾角: "8位数字如'19.0363'表示轨道与赤道平面的夹角范围0°-180°",
MEAN_ANOMALY_平近点角: "8位数字如'171.6150'表示历元时的平近点角范围0°-360°",
MEAN_MOTION_DDOT_平均运动二阶导数: "8位科学计数法如'-50502-6'表示-5.0502×10⁻⁶圈/天³,最后一位是指数",
MEAN_MOTION_DOT_平均运动一阶导数: "10位数字如'.00072212',表示平均运动变化率的一半,单位圈/天²,左侧补空格",
MEAN_MOTION_平均运动: "11位数字如'2.21786616',表示卫星每天绕地球的圈数(圈/天)",
NORAD_CAT_ID_卫星编号: "5位数字如'63158'表示NORAD卫星唯一目录编号",
OBJECT_ID_国际标识符: "8个字符如'25045B'(年份+发射编号+部件),不足时右侧补空格",
RA_OF_ASC_NODE_升交点赤经: "8位数字如'63.0294'表示轨道升交点的赤经范围0°-360°",
REV_AT_EPOCH_历元时的圈数: "5位数字如'13',表示卫星在历元时完成的轨道圈数",
};

View File

@ -28,9 +28,9 @@ export async function demo_01_OrbitGeneration(viewer: Viewer) {
await new Promise((resolve) => setTimeout(resolve, 500));
// 计算一条完整的轨道
for (let i = 0; i < totalMinutes; i += timeStepInMinutes) {
for (let index = 0; index < totalMinutes; index += timeStepInMinutes) {
// 创建时间点
const time = new Date(now.getTime() + i * 60_000);
const time = new Date(now.getTime() + index * 60_000);
// 获取卫星位置
const positionAndVelocity = propagate(satrec, time);

View File

@ -73,8 +73,8 @@ export async function demo_02_Track(viewer: Viewer) {
// const satelliteAltitude = 550_000; // 默认高度为550公里
// 计算轨道上的点
for (let i = 0; i <= totalSeconds; i += timeStepInSeconds) {
const time = Cesium.JulianDate.addSeconds(startTime, i, new Cesium.JulianDate());
for (let index = 0; index <= totalSeconds; index += timeStepInSeconds) {
const time = Cesium.JulianDate.addSeconds(startTime, index, new Cesium.JulianDate());
const jsDate = Cesium.JulianDate.toDate(time);
// 计算卫星位置

View File

@ -2,7 +2,7 @@
import type { Entity, Viewer } from 'cesium';
import { FilterOutlined, SearchOutlined } from '@ant-design/icons-vue';
import { computed, onBeforeUnmount, reactive, ref, watchEffect } from 'vue';
import { computed, reactive, ref, watchEffect } from 'vue';
import SatelliteEntity from '../cesium-helper/SatelliteEntity';
@ -17,7 +17,7 @@ const getSatelliteName = (tle: string) => {
};
// 将satellites改为计算属性响应tleList的变化
const satellites = computed(() => Array.from(new Set(tleList)));
const satellites = computed(() => [...new Set(tleList)]);
// 创建Map存储卫星实体
const satelliteEntities = ref<Map<string, Entity>>(new Map());
@ -66,8 +66,8 @@ const updateSatelliteEntity = (tle: string, selected: boolean) => {
if (selected) {
// 添加卫星到viewer
try {
const satelliteObj = new SatelliteEntity(tle);
const cesiumSateEntity = satelliteObj.createSatelliteEntity();
const satelliteObject = new SatelliteEntity(tle);
const cesiumSateEntity = satelliteObject.createSatelliteEntity();
const result = viewer.entities.add(cesiumSateEntity);
satelliteEntities.value.set(tle, result);
} catch (error) {
@ -100,7 +100,7 @@ const toggleSatellite = (tle: string) => {
const onCheckAllChange = (e: { target: { checked: boolean } }) => {
const checked = e.target.checked;
filteredSatellites.value.forEach((tle) => {
for (const tle of filteredSatellites.value) {
const isCurrentlySelected = isSatelliteSelected(tle);
if (isCurrentlySelected !== checked) {
@ -112,20 +112,8 @@ const onCheckAllChange = (e: { target: { checked: boolean } }) => {
updateSatelliteEntity(tle, checked);
}
});
};
// 组件卸载时清理所有卫星实体
onBeforeUnmount(() => {
if (viewer) {
// 移除所有实体
satelliteEntities.value.forEach((entity) => {
viewer?.entities.remove(entity);
});
satelliteEntities.value.clear();
selectedSatellites.value.clear();
}
});
};
</script>
<template>

View File

@ -19,7 +19,8 @@ declare global {
}
export async function demoOrbitGeneration(viewer: Viewer) {
window.spaceCatalog = new SpaceCatalogDataSource({ name: 'celestrak' });
// @ts-expect-error globalThis
globalThis.spaceCatalog = new SpaceCatalogDataSource({ name: 'celestrak' });
viewer.extend(viewerReferenceFrameMixin);
viewer.referenceFrame = 1;
@ -30,8 +31,8 @@ export async function demoOrbitGeneration(viewer: Viewer) {
backgroundColor: new Color(0.1, 0.1, 0.1, 0.9),
font: `1rem Helvetica`,
pixelOffset: new Cartesian2(10, 0),
pixelOffsetScaleByDistance: new NearFarScalar(1.5e2, 3.0, 1.5e7, 0.5),
scaleByDistance: new NearFarScalar(1.5e2, 1.5, 13.0e7, 0.0),
pixelOffsetScaleByDistance: new NearFarScalar(1.5e2, 3, 1.5e7, 0.5),
scaleByDistance: new NearFarScalar(1.5e2, 1.5, 13e7, 0),
show: false,
showBackground: true,
},
@ -39,13 +40,13 @@ export async function demoOrbitGeneration(viewer: Viewer) {
point: {
pixelSize: 1,
},
viewFrom: new Cartesian3(-1678500.7493507154, -17680994.63403464, 24667690.486357275),
viewFrom: new Cartesian3(-1_678_500.749_350_715_4, -17_680_994.634_034_64, 24_667_690.486_357_275),
});
ISS.position.loadOMM({
/* CCSDS OMM版本 */ ARG_OF_PERICENTER: 149.2285,
/* 创建日期(ISO 8601 UTC格式) */ BSTAR: 0.00028217,
/* 创建者 */ CCSDS_OMM_VERS: 0.0,
/* 创建日期(ISO 8601 UTC格式) */ BSTAR: 0.000_282_17,
/* 创建者 */ CCSDS_OMM_VERS: 0,
/* 卫星名称 */ CENTER_NAME: null,
/* 国际标识符(YYYY-NNNAAA) */ CLASSIFICATION_TYPE: 'U',
/* 中心名称(例如:EARTH, MARS) */ COMMENT: null,
@ -74,7 +75,7 @@ export async function demoOrbitGeneration(viewer: Viewer) {
/* 根数组编号 */ CZ_Z: 0,
/* 历元时的圈次 */ DRAG_AREA: 0,
/* 气阻系数(1/地球半径) */ DRAG_COEFF: 0,
/* 平均运动一阶导数(圈/天²) */ ECCENTRICITY: 0.0003349,
/* 平均运动一阶导数(圈/天²) */ ECCENTRICITY: 0.000_334_9,
/* 平均运动二阶导数(圈/天³) */ ELEMENT_SET_NO: 999,
/* 协方差矩阵参考坐标系 */ EPHEMERIS_TYPE: 0,
/* --- 位置/速度协方差矩阵(6x6下三角) --- */
@ -84,17 +85,17 @@ export async function demoOrbitGeneration(viewer: Viewer) {
/* 位置协方差矩阵元素(km²) */ MASS: 0,
/* 位置协方差矩阵元素(km²) */ MEAN_ANOMALY: 210.8902,
/* 位置协方差矩阵元素(km²) */ MEAN_ELEMENT_THEORY: 0,
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION: 15.51025615,
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION: 15.510_256_15,
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION_DDOT: 0,
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION_DOT: 0.00016275,
/* 速度协方差矩阵元素(km²/s²) */ NORAD_CAT_ID: 25544,
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION_DOT: 0.000_162_75,
/* 速度协方差矩阵元素(km²/s²) */ NORAD_CAT_ID: 25_544,
/* 速度-位置协方差矩阵元素(km²/s) */ OBJECT_ID: '1998-067A',
/* 速度-位置协方差矩阵元素(km²/s) */ OBJECT_NAME: 'ISS (ZARYA)',
/* 速度-位置协方差矩阵元素(km²/s) */ ORIGINATOR: null,
/* 速度协方差矩阵元素(km²/s²) */ RA_OF_ASC_NODE: 150.5366,
/* 速度协方差矩阵元素(km²/s²) */ REFERENCE_FRAME: 2,
/* 速度-位置协方差矩阵元素(km²/s) */ REFERENCE_FRAME_EPOCH: null,
/* 速度-位置协方差矩阵元素(km²/s) */ REV_AT_EPOCH: 45244,
/* 速度-位置协方差矩阵元素(km²/s) */ REV_AT_EPOCH: 45_244,
/* 速度-位置协方差矩阵元素(km²/s) */ SEMI_MAJOR_AXIS: 0,
/* 速度协方差矩阵元素(km²/s²) */ SOLAR_RAD_AREA: 0,
/* 速度协方差矩阵元素(km²/s²) */ SOLAR_RAD_COEFF: 0,
@ -118,7 +119,7 @@ export async function demoOrbitGeneration(viewer: Viewer) {
});
const issDataSource = new SpaceCatalogDataSource({ name: 'issSource' });
Object.assign(window, { issDataSource });
Object.assign(globalThis, { issDataSource });
issDataSource.entities.add(ISS); // FIXME: add后有问题。
await viewer.dataSources.add(issDataSource);

View File

@ -3,9 +3,11 @@ const baseURL = '/fake-api';
let fakeApiResult = $ref<null | Record<string, unknown>>(null);
fetch(`${baseURL}/mock/get-user-info`)
.then((response) => response.json())
.then((json) => (fakeApiResult = json));
onMounted(() => {
fetch(`${baseURL}/mock/get-user-info`)
.then((response) => response.json())
.then((json) => (fakeApiResult = json));
});
/* fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json())

View File

@ -1,5 +1,6 @@
<script lang="ts">
const structuredClone = window.structuredClone || ((obj) => JSON.parse(JSON.stringify(obj)));
// eslint-disable-next-line unicorn/prefer-structured-clone
const structuredClone = globalThis.structuredClone || ((object) => JSON.parse(JSON.stringify(object)));
const K_INITIAL_STATE = deepFreeze({
complete: false,
@ -51,7 +52,7 @@ async function loadMore() {
}
});
const data = await response.json();
state.list = state.list.concat(data);
state.list = [...state.list, ...data];
if ($__DEV__) await new Promise((resolve) => setTimeout(resolve, 500));
state.complete = state.list.length >= 5;
} catch (error) {

View File

@ -4,8 +4,8 @@ import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic';
export const usePageData = defineBasicLoader(
'DataLoadersId',
async (route, ...otherArgs) => {
console.log('[DefineLoaderFn]', 'otherArgs :>> ', otherArgs);
async (route, ...otherArguments) => {
console.log('[DefineLoaderFn]', 'otherArgs :>>', otherArguments);
await new Promise((resolve) => setTimeout(resolve, 777));
return { idFromPreviousPage: route.params.id, someOtherData: 'someOtherData' };
},

View File

@ -1,5 +1,5 @@
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders';
import { createGetRoutes, setupLayouts } from 'virtual:meta-layouts';
import { setupLayouts } from 'virtual:meta-layouts';
// import { createGetRoutes, setupLayouts } from 'virtual:generated-layouts';
import { createRouter, createWebHistory } from 'vue-router/auto';
import { handleHotUpdate, routes } from 'vue-router/auto-routes';
@ -9,21 +9,17 @@ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: /* routes ?? */ setupLayoutsResult,
scrollBehavior: (_to, _from, savedPosition) => {
if (savedPosition) {
return savedPosition;
} else {
return { left: 0, top: 0 };
}
return savedPosition ?? { left: 0, top: 0 };
},
strict: true,
});
if (import.meta.hot) handleHotUpdate(router);
if ($__DEV__) Object.assign(window, { router });
if ($__DEV__) Object.assign(globalThis, { router });
router.onError((error) => {
console.debug('🚨 [router error]: ', error);
console.debug('🚨 [router error]:', error);
});
export { createGetRoutes, router, setupLayoutsResult };
export { router, setupLayoutsResult };
export function install({ app }: { app: import('vue').App<Element> }) {
app
// Register the plugin before the router
@ -38,7 +34,7 @@ export function install({ app }: { app: import('vue').App<Element> }) {
// 警告:路由守卫的创建顺序会影响执行流程,请勿调整
createNProgressGuard(router);
createLogGuard(router);
Object.assign(window, { stack: createStackGuard(router) });
Object.assign(globalThis, { stack: createStackGuard(router) });
}
/*
@ -58,3 +54,5 @@ declare module 'vue-router' {
title?: string;
}
}
export { createGetRoutes } from 'virtual:meta-layouts';

View File

@ -13,6 +13,6 @@ test('页面加载正常', async ({ page }, testInfo) => {
// 查找包含"commit:"文本的元素
const commitElement = page.locator('text=commit:').first();
// 获取元素的文本内容
const innerText = await commitElement.innerText();
const innerText = await commitElement.textContent();
consola.debug(`Commit 文本内容: "${innerText}"`);
});

View File

@ -135,7 +135,7 @@ export function Plugins() {
VueI18n({
/* options */
// locale messages resource pre-compile option
include: [path.resolve(__dirname, './src/locales/**')],
include: [path.resolve(import.meta.dirname, './src/locales/**')],
// https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#transformi18nblock
// transformI18nBlock(src) {
@ -152,8 +152,8 @@ export function Plugins() {
return svg.replace(/^<svg /, '<svg fill="currentColor" ');
}),
},
iconCustomizer(collection, icon, props) {
props.class = 'unplugin-icons';
iconCustomizer(collection, icon, properties) {
properties.class = 'unplugin-icons';
},
}),
@ -187,9 +187,6 @@ export function Plugins() {
VueDevTools({
// launchEditor: env.LAUNCH_EDITOR,
}),
);
plugins.push(
// https://github.com/unplugin/unplugin-vue-components/issues/664$0
// https://github.com/VaJoy/vite-plugin-cdn-import-async$0
// https://github.com/mmf-fe/vite-plugin-cdn-import/blob/HEAD/README.zh-CN.md

View File

@ -48,7 +48,7 @@ export default defineConfig(({ command, mode }) => {
plugins: Plugins(),
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@': fileURLToPath(new URL('src', import.meta.url)),
},
},
server: {