Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
75f9985265 | |||
95d1352a2b | |||
0c9091f5e6 | |||
0a86b75454 | |||
b1c572903f | |||
521edd2a8f | |||
96425f7e70 | |||
de3cd7bb34 | |||
1c87705166 | |||
d2eb0fa284 | |||
4b1d0d2139 | |||
bcd8fc3963 | |||
b852159e39 | |||
a31ad98a9e | |||
10ab2fb670 | |||
0d30d6cb5a | |||
05f3fbc454 | |||
2365231986 | |||
68aec74c80 | |||
b2e4937c69 | |||
838856e53f | |||
9ad6d3bb9d | |||
c7a10c7e98 | |||
9aed3ec064 | |||
f1a7c74b93 | |||
d3a29eed91 | |||
ec35a111c7 | |||
171c8a404c |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,5 +1,22 @@
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
## V3.0.0
|
## [3.1.1] - 2024-09-08
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `配置文件` 解决打包异常。
|
||||||
|
|
||||||
|
## [3.1.0] - 2024-09-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `工具箱` 添加“工具箱”模块,包含“下载用时计算”“比例计算”“生成随机字符串”工具。
|
||||||
|
- `网址导航` 支持记录最后一次选中的链接分类。
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `功能` 修改页面跳转方式,支持返回。
|
||||||
|
|
||||||
|
## [3.0.0] - 2024-09-01
|
||||||
|
|
||||||
重构新版本,支持“搜索”功能和“网址导航”功能。
|
重构新版本,支持“搜索”功能和“网址导航”功能。
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
### 在线
|
### 在线
|
||||||
|
|
||||||
- [GitHub Pages](https://frost-zx.github.io/frost-navigation/)
|
- [GitHub Pages](https://frost-zx.github.io/frost-navigation/)
|
||||||
|
- [V1 版本](https://frost-zx.github.io/frost-navigation/v1/)(2020-09-10)
|
||||||
|
- [V2 版本](https://frost-zx.github.io/frost-navigation/v2/)(2024-08-31)
|
||||||
|
- [V3 版本](https://frost-zx.github.io/frost-navigation/v3/)(开发中)
|
||||||
- [Vercel](https://frost-navigation.vercel.app/)
|
- [Vercel](https://frost-navigation.vercel.app/)
|
||||||
|
|
||||||
### 离线(需要手动更新)
|
### 离线(需要手动更新)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "frost-navigation",
|
"name": "frost-navigation",
|
||||||
"description": "Frost Navigation",
|
"description": "Frost Navigation",
|
||||||
"version": "3.0.0",
|
"version": "3.1.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -14,7 +14,9 @@
|
|||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
"@vueuse/core": "^11.0.3",
|
"@vueuse/core": "^11.0.3",
|
||||||
"axios": "^1.7.5",
|
"axios": "^1.7.5",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"lunisolar": "^2.5.0",
|
"lunisolar": "^2.5.0",
|
||||||
|
"mathjs": "^13.1.1",
|
||||||
"naive-ui": "^2.39.0",
|
"naive-ui": "^2.39.0",
|
||||||
"radash": "^12.1.0",
|
"radash": "^12.1.0",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
|
69
pnpm-lock.yaml
generated
69
pnpm-lock.yaml
generated
@@ -20,9 +20,15 @@ importers:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.7.5
|
specifier: ^1.7.5
|
||||||
version: 1.7.5
|
version: 1.7.5
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.13
|
||||||
|
version: 1.11.13
|
||||||
lunisolar:
|
lunisolar:
|
||||||
specifier: ^2.5.0
|
specifier: ^2.5.0
|
||||||
version: 2.5.0
|
version: 2.5.0
|
||||||
|
mathjs:
|
||||||
|
specifier: ^13.1.1
|
||||||
|
version: 13.1.1
|
||||||
naive-ui:
|
naive-ui:
|
||||||
specifier: ^2.39.0
|
specifier: ^2.39.0
|
||||||
version: 2.39.0(vue@3.4.38)
|
version: 2.39.0(vue@3.4.38)
|
||||||
@@ -1231,6 +1237,9 @@ packages:
|
|||||||
commander@2.20.3:
|
commander@2.20.3:
|
||||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||||
|
|
||||||
|
complex.js@2.1.1:
|
||||||
|
resolution: {integrity: sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==}
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
|
|
||||||
@@ -1273,6 +1282,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
||||||
engines: {node: '>=0.11'}
|
engines: {node: '>=0.11'}
|
||||||
|
|
||||||
|
dayjs@1.11.13:
|
||||||
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -1282,6 +1294,9 @@ packages:
|
|||||||
supports-color:
|
supports-color:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
decimal.js@10.4.3:
|
||||||
|
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||||
|
|
||||||
deep-is@0.1.4:
|
deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
|
|
||||||
@@ -1313,6 +1328,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
|
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
escape-latex@1.2.0:
|
||||||
|
resolution: {integrity: sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==}
|
||||||
|
|
||||||
escape-string-regexp@1.0.5:
|
escape-string-regexp@1.0.5:
|
||||||
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
@@ -1406,6 +1424,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
fraction.js@4.3.7:
|
||||||
|
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||||
|
|
||||||
fs.realpath@1.0.0:
|
fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
|
|
||||||
@@ -1511,6 +1532,9 @@ packages:
|
|||||||
isexe@2.0.0:
|
isexe@2.0.0:
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||||
|
|
||||||
|
javascript-natural-sort@0.7.1:
|
||||||
|
resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
@@ -1582,6 +1606,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
|
resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
mathjs@13.1.1:
|
||||||
|
resolution: {integrity: sha512-duaSAy7m4F+QtP1Dyv8MX2XuxcqpNDDlGly0SdVTCqpAmwdOFWilDdQKbLdo9RfD6IDNMOdo9tIsEaTXkconlQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
meow@13.2.0:
|
meow@13.2.0:
|
||||||
resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
|
resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -1755,6 +1784,9 @@ packages:
|
|||||||
sax@1.4.1:
|
sax@1.4.1:
|
||||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
||||||
|
|
||||||
|
seedrandom@3.0.5:
|
||||||
|
resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==}
|
||||||
|
|
||||||
seemly@0.3.8:
|
seemly@0.3.8:
|
||||||
resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==}
|
resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==}
|
||||||
|
|
||||||
@@ -1824,6 +1856,9 @@ packages:
|
|||||||
text-table@0.2.0:
|
text-table@0.2.0:
|
||||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||||
|
|
||||||
|
tiny-emitter@2.1.0:
|
||||||
|
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
|
||||||
|
|
||||||
to-fast-properties@2.0.0:
|
to-fast-properties@2.0.0:
|
||||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -1842,6 +1877,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
typed-function@4.2.1:
|
||||||
|
resolution: {integrity: sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
undici-types@6.19.8:
|
undici-types@6.19.8:
|
||||||
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
||||||
|
|
||||||
@@ -3297,6 +3336,8 @@ snapshots:
|
|||||||
|
|
||||||
commander@2.20.3: {}
|
commander@2.20.3: {}
|
||||||
|
|
||||||
|
complex.js@2.1.1: {}
|
||||||
|
|
||||||
concat-map@0.0.1: {}
|
concat-map@0.0.1: {}
|
||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
@@ -3336,10 +3377,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.25.4
|
'@babel/runtime': 7.25.4
|
||||||
|
|
||||||
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.2
|
ms: 2.1.2
|
||||||
|
|
||||||
|
decimal.js@10.4.3: {}
|
||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
delayed-stream@1.0.0: {}
|
delayed-stream@1.0.0: {}
|
||||||
@@ -3385,6 +3430,8 @@ snapshots:
|
|||||||
|
|
||||||
escalade@3.1.2: {}
|
escalade@3.1.2: {}
|
||||||
|
|
||||||
|
escape-latex@1.2.0: {}
|
||||||
|
|
||||||
escape-string-regexp@1.0.5: {}
|
escape-string-regexp@1.0.5: {}
|
||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
@@ -3510,6 +3557,8 @@ snapshots:
|
|||||||
combined-stream: 1.0.8
|
combined-stream: 1.0.8
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
fraction.js@4.3.7: {}
|
||||||
|
|
||||||
fs.realpath@1.0.0: {}
|
fs.realpath@1.0.0: {}
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
@@ -3595,6 +3644,8 @@ snapshots:
|
|||||||
|
|
||||||
isexe@2.0.0: {}
|
isexe@2.0.0: {}
|
||||||
|
|
||||||
|
javascript-natural-sort@0.7.1: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-yaml@4.1.0:
|
js-yaml@4.1.0:
|
||||||
@@ -3664,6 +3715,18 @@ snapshots:
|
|||||||
semver: 5.7.2
|
semver: 5.7.2
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
mathjs@13.1.1:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.4
|
||||||
|
complex.js: 2.1.1
|
||||||
|
decimal.js: 10.4.3
|
||||||
|
escape-latex: 1.2.0
|
||||||
|
fraction.js: 4.3.7
|
||||||
|
javascript-natural-sort: 0.7.1
|
||||||
|
seedrandom: 3.0.5
|
||||||
|
tiny-emitter: 2.1.0
|
||||||
|
typed-function: 4.2.1
|
||||||
|
|
||||||
meow@13.2.0: {}
|
meow@13.2.0: {}
|
||||||
|
|
||||||
mime-db@1.52.0: {}
|
mime-db@1.52.0: {}
|
||||||
@@ -3855,6 +3918,8 @@ snapshots:
|
|||||||
sax@1.4.1:
|
sax@1.4.1:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
seedrandom@3.0.5: {}
|
||||||
|
|
||||||
seemly@0.3.8: {}
|
seemly@0.3.8: {}
|
||||||
|
|
||||||
semver@5.7.2:
|
semver@5.7.2:
|
||||||
@@ -3908,6 +3973,8 @@ snapshots:
|
|||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
|
||||||
|
tiny-emitter@2.1.0: {}
|
||||||
|
|
||||||
to-fast-properties@2.0.0: {}
|
to-fast-properties@2.0.0: {}
|
||||||
|
|
||||||
treemate@0.3.11: {}
|
treemate@0.3.11: {}
|
||||||
@@ -3920,6 +3987,8 @@ snapshots:
|
|||||||
|
|
||||||
type-fest@0.20.2: {}
|
type-fest@0.20.2: {}
|
||||||
|
|
||||||
|
typed-function@4.2.1: {}
|
||||||
|
|
||||||
undici-types@6.19.8: {}
|
undici-types@6.19.8: {}
|
||||||
|
|
||||||
unicode-canonical-property-names-ecmascript@2.0.0: {}
|
unicode-canonical-property-names-ecmascript@2.0.0: {}
|
||||||
|
@@ -188,6 +188,7 @@ html {
|
|||||||
.app-view-header {
|
.app-view-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
@@ -203,6 +204,7 @@ html {
|
|||||||
|
|
||||||
.app-view-content {
|
.app-view-content {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
268
src/assets/js/toolbox-data.js
Normal file
268
src/assets/js/toolbox-data.js
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
// 工具箱
|
||||||
|
|
||||||
|
const MODULES = import.meta.glob('../../views/ToolboxView/**/*.vue');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 工具列表
|
||||||
|
* @type {ToolboxCategory[]}
|
||||||
|
*/
|
||||||
|
export const toolList = [
|
||||||
|
{
|
||||||
|
id: 'calculation-tools',
|
||||||
|
title: '计算',
|
||||||
|
enabled: true,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'calc-download-time',
|
||||||
|
component: 'Calculation/CalcDownloadTime',
|
||||||
|
title: '下载用时计算',
|
||||||
|
iconClass: 'mdi mdi-calculator-variant-outline',
|
||||||
|
desc: '根据设定的文件大小和下载速度简单计算大约下载完成所需的时间。',
|
||||||
|
createdAt: '2024-09-08',
|
||||||
|
updatedAt: '2024-09-08',
|
||||||
|
version: '1',
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'calc-ratio',
|
||||||
|
component: 'Calculation/CalcRatio',
|
||||||
|
title: '比例计算',
|
||||||
|
iconClass: 'mdi mdi-calculator-variant-outline',
|
||||||
|
desc: '按设定的比例计算给出的数值所对应的数值。',
|
||||||
|
createdAt: '2024-09-08',
|
||||||
|
updatedAt: '2024-09-08',
|
||||||
|
version: '1',
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'conversion-tools',
|
||||||
|
title: '转换',
|
||||||
|
enabled: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'convert-html-entities',
|
||||||
|
component: 'Conversion/ConvertHtmlEntities',
|
||||||
|
title: '转换 HTML 实体',
|
||||||
|
iconClass: 'mdi mdi-swap-horizontal',
|
||||||
|
desc: '',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'url-encode-decode',
|
||||||
|
component: 'Conversion/UrlEncodeDecode',
|
||||||
|
title: 'URL 编码 / 解码',
|
||||||
|
iconClass: 'mdi mdi-swap-horizontal',
|
||||||
|
desc: '',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'convert-text-structure',
|
||||||
|
component: 'Conversion/ConvertTextStructure',
|
||||||
|
title: '文本结构转换',
|
||||||
|
iconClass: 'mdi mdi-swap-horizontal',
|
||||||
|
desc: '倒序、横竖互换等',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'convert-timestamp',
|
||||||
|
component: 'Conversion/ConvertTimestamp',
|
||||||
|
title: 'Unix 时间戳转换',
|
||||||
|
iconClass: 'mdi mdi-swap-horizontal',
|
||||||
|
desc: '时间戳转时间 / 时间转时间戳',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edit-tools',
|
||||||
|
title: '编辑',
|
||||||
|
enabled: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'csv-editor',
|
||||||
|
component: 'Edit/CsvEditor',
|
||||||
|
title: 'CSV 编辑工具',
|
||||||
|
iconClass: 'mdi mdi-table-edit',
|
||||||
|
desc: '查看或编辑 CSV 文件',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'generator-tools',
|
||||||
|
title: '生成',
|
||||||
|
enabled: true,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'generate-urls',
|
||||||
|
component: 'Generator/GenerateUrls',
|
||||||
|
title: '生成批量下载链接',
|
||||||
|
iconClass: 'mdi mdi-link-variant',
|
||||||
|
desc: '根据设置,生成有一定规律的用于批量下载的链接。',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'generate-random-string',
|
||||||
|
component: 'Generator/GenerateRandomString',
|
||||||
|
title: '生成随机字符串',
|
||||||
|
iconClass: 'mdi mdi-format-text',
|
||||||
|
desc: '生成随机组合的字符串,可用于密码。',
|
||||||
|
createdAt: '2024-09-08',
|
||||||
|
updatedAt: '2024-09-08',
|
||||||
|
version: '1',
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'minecraft-tools',
|
||||||
|
title: 'Minecraft',
|
||||||
|
enabled: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'calc-minecraft-chunk-location',
|
||||||
|
component: 'Minecraft/CalcChunkLocation',
|
||||||
|
title: 'Minecraft 区块位置计算',
|
||||||
|
iconClass: 'mdi mdi-calculator-variant-outline',
|
||||||
|
desc: '',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'generate-minecraft-dynmap-renderdata',
|
||||||
|
component: 'Minecraft/GenerateDynmapRenderdata',
|
||||||
|
title: '生成 Dynmap renderdata',
|
||||||
|
iconClass: 'mdi mdi-file-outline',
|
||||||
|
desc: '生成用于 Minecraft Dynmap 插件或模组的 renderdata 数据。',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'minecraft-uuid-converter',
|
||||||
|
component: 'Minecraft/UuidConverter',
|
||||||
|
title: 'Minecraft UUID 转换',
|
||||||
|
iconClass: 'mdi mdi-identifier',
|
||||||
|
desc: '随机生成或转换 Minecraft 的 UUID。',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'network-tools',
|
||||||
|
title: '网络',
|
||||||
|
enabled: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'websocket-test-tool',
|
||||||
|
component: 'Network/WebSocketTestTool',
|
||||||
|
title: 'WebSocket',
|
||||||
|
iconClass: 'mdi mdi-connection',
|
||||||
|
desc: 'WebSocket 测试工具',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'other-tools',
|
||||||
|
title: '其他',
|
||||||
|
enabled: false,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'open-new-window',
|
||||||
|
component: 'Other/OpenNewWindow',
|
||||||
|
title: '新窗口(小窗)中打开',
|
||||||
|
iconClass: 'mdi mdi-window-maximize',
|
||||||
|
desc: '从新的小窗口中打开指定的链接(仅支持 PC 端浏览器)',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'run-javascript',
|
||||||
|
component: 'Other/RunJavaScript',
|
||||||
|
title: '执行 JavaScript',
|
||||||
|
iconClass: 'mdi mdi-code-braces',
|
||||||
|
desc: '执行简单的 JavaScript 代码片段',
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
version: '0',
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取动态组件
|
||||||
|
* @param {string} path 工具页面相对路径
|
||||||
|
*/
|
||||||
|
function getDynamicComponent(path) {
|
||||||
|
|
||||||
|
let key = `../../views/ToolboxView/${path}.vue`;
|
||||||
|
let component = MODULES[key];
|
||||||
|
|
||||||
|
return component;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 生成工具箱页面路由 */
|
||||||
|
export function getToolboxRoutes() {
|
||||||
|
|
||||||
|
/** @type {VueRouteRecordRaw[]} */
|
||||||
|
let routes = [];
|
||||||
|
|
||||||
|
toolList.forEach((categoryItem) => {
|
||||||
|
categoryItem.items.forEach((toolItem) => {
|
||||||
|
|
||||||
|
// 跳过未启用的工具
|
||||||
|
if (!toolItem.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
routes.push({
|
||||||
|
path: `/toolbox-view/${toolItem.id}`,
|
||||||
|
name: `Toolbox/${toolItem.component}`,
|
||||||
|
component: getDynamicComponent(toolItem.component),
|
||||||
|
meta: {
|
||||||
|
isToolDetail: true,
|
||||||
|
title: toolItem.title,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return routes;
|
||||||
|
|
||||||
|
}
|
@@ -52,7 +52,7 @@ const router = useRouter();
|
|||||||
|
|
||||||
/** 切换页面 */
|
/** 切换页面 */
|
||||||
function changePage(routeName = '') {
|
function changePage(routeName = '') {
|
||||||
router.replace({ name: routeName });
|
router.push({ name: routeName });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化数据 */
|
/** 初始化数据 */
|
||||||
|
@@ -27,7 +27,7 @@ export const SEARCH_MODULE_ENABLED = true;
|
|||||||
export const SEARCH_MODULE_TITLE = '搜索';
|
export const SEARCH_MODULE_TITLE = '搜索';
|
||||||
|
|
||||||
/** 启用模块 */
|
/** 启用模块 */
|
||||||
export const TOOLBOX_MODULE_ENABLED = IS_DEV;
|
export const TOOLBOX_MODULE_ENABLED = true;
|
||||||
|
|
||||||
/** 模块标题 */
|
/** 模块标题 */
|
||||||
export const TOOLBOX_MODULE_TITLE = '工具箱';
|
export const TOOLBOX_MODULE_TITLE = '工具箱';
|
||||||
|
@@ -6,6 +6,9 @@ const PREFIX = 'frost-navigation/';
|
|||||||
/** 导航链接侧边栏折叠状态 */
|
/** 导航链接侧边栏折叠状态 */
|
||||||
export const SKEY_NAV_LINK_ASIDE_COLLAPSED = PREFIX + 'nav-link-aside-collapsed';
|
export const SKEY_NAV_LINK_ASIDE_COLLAPSED = PREFIX + 'nav-link-aside-collapsed';
|
||||||
|
|
||||||
|
/** 导航链接当前选中分类 */
|
||||||
|
export const SKEY_NAV_LINK_CATEGORY = PREFIX + 'nav-link-category';
|
||||||
|
|
||||||
/** 导航链接搜索类型 */
|
/** 导航链接搜索类型 */
|
||||||
export const SKEY_NAV_LINK_SEARCH_TYPE = PREFIX + 'nav-link-search-type';
|
export const SKEY_NAV_LINK_SEARCH_TYPE = PREFIX + 'nav-link-search-type';
|
||||||
|
|
||||||
|
12
src/main.js
12
src/main.js
@@ -4,6 +4,12 @@ import { router } from './router';
|
|||||||
import '@mdi/font/css/materialdesignicons.css';
|
import '@mdi/font/css/materialdesignicons.css';
|
||||||
import '@/assets/fonts/index.css';
|
import '@/assets/fonts/index.css';
|
||||||
|
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import dayjsDuration from 'dayjs/plugin/duration';
|
||||||
|
|
||||||
|
import 'dayjs/locale/zh-cn';
|
||||||
|
import 'dayjs/locale/zh-hk';
|
||||||
|
|
||||||
import lunisolar from 'lunisolar';
|
import lunisolar from 'lunisolar';
|
||||||
import lunisolarLang1 from 'lunisolar/locale/en';
|
import lunisolarLang1 from 'lunisolar/locale/en';
|
||||||
import lunisolarLang2 from 'lunisolar/locale/zh-cn';
|
import lunisolarLang2 from 'lunisolar/locale/zh-cn';
|
||||||
@@ -11,6 +17,12 @@ import lunisolarFestivals from 'lunisolar/markers/festivals.zh-cn';
|
|||||||
|
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
|
|
||||||
|
// 加载 Day.js Duration 插件
|
||||||
|
dayjs.extend(dayjsDuration);
|
||||||
|
|
||||||
|
// 配置 Day.js 默认语言
|
||||||
|
dayjs.locale('zh-cn');
|
||||||
|
|
||||||
// 加载 Lunisolar 语言包
|
// 加载 Lunisolar 语言包
|
||||||
lunisolar.locale([
|
lunisolar.locale([
|
||||||
lunisolarLang1,
|
lunisolarLang1,
|
||||||
|
@@ -3,6 +3,10 @@ import {
|
|||||||
createWebHashHistory,
|
createWebHashHistory,
|
||||||
} from 'vue-router';
|
} from 'vue-router';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getToolboxRoutes,
|
||||||
|
} from '@/assets/js/toolbox-data';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
updateAppTitle,
|
updateAppTitle,
|
||||||
} from '@/assets/js/utils';
|
} from '@/assets/js/utils';
|
||||||
@@ -62,9 +66,11 @@ export const router = createRouter({
|
|||||||
component: () => import('@/views/ToolboxView/ToolboxView.vue'),
|
component: () => import('@/views/ToolboxView/ToolboxView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
iconClass: 'mdi mdi-tools',
|
iconClass: 'mdi mdi-tools',
|
||||||
|
isToolDetail: false,
|
||||||
showInAside: TOOLBOX_MODULE_ENABLED,
|
showInAside: TOOLBOX_MODULE_ENABLED,
|
||||||
title: TOOLBOX_MODULE_TITLE,
|
title: TOOLBOX_MODULE_TITLE,
|
||||||
},
|
},
|
||||||
|
children: getToolboxRoutes(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/minecraft-ctrl-view',
|
path: '/minecraft-ctrl-view',
|
||||||
|
@@ -145,6 +145,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
SKEY_NAV_LINK_ASIDE_COLLAPSED,
|
SKEY_NAV_LINK_ASIDE_COLLAPSED,
|
||||||
|
SKEY_NAV_LINK_CATEGORY,
|
||||||
SKEY_NAV_LINK_SEARCH_TYPE,
|
SKEY_NAV_LINK_SEARCH_TYPE,
|
||||||
} from '@/config/storage';
|
} from '@/config/storage';
|
||||||
|
|
||||||
@@ -228,10 +229,36 @@ const searchTypes = [
|
|||||||
*/
|
*/
|
||||||
function changeList(data = null) {
|
function changeList(data = null) {
|
||||||
|
|
||||||
let useData = data || navLinksAll[0] || null;
|
let useData = null;
|
||||||
|
let storedKey = '';
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
useData = data;
|
||||||
|
} else {
|
||||||
|
storedKey = localStorage.getItem(SKEY_NAV_LINK_CATEGORY)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storedKey) {
|
||||||
|
useData = navLinksAll.find((item) => {
|
||||||
|
return item.title === storedKey;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useData) {
|
||||||
|
useData = navLinksAll[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useData) {
|
||||||
|
localStorage.setItem(SKEY_NAV_LINK_CATEGORY, useData.title);
|
||||||
|
navLinksCurr.value = useData.children;
|
||||||
|
navLinksTitle.value = useData.title;
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(SKEY_NAV_LINK_CATEGORY, '');
|
||||||
|
navLinksCurr.value = [];
|
||||||
|
navLinksTitle.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
navLinksCurr.value = useData ? useData.children : [];
|
|
||||||
navLinksTitle.value = useData ? useData.title : '';
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
209
src/views/ToolboxView/Calculation/CalcDownloadTime.vue
Normal file
209
src/views/ToolboxView/Calculation/CalcDownloadTime.vue
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page">
|
||||||
|
|
||||||
|
<!-- 参数 -->
|
||||||
|
<n-card size="small" title="参数">
|
||||||
|
<n-form
|
||||||
|
class="form-no-feedback"
|
||||||
|
label-align="right"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="auto"
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-form-item label="文件大小:">
|
||||||
|
<n-input-group>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="inputs.sizeValue"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:max="10000"
|
||||||
|
:step="1"
|
||||||
|
/>
|
||||||
|
<n-select
|
||||||
|
v-model:value="inputs.sizeUnit"
|
||||||
|
label-field="name"
|
||||||
|
value-field="name"
|
||||||
|
:options="units"
|
||||||
|
/>
|
||||||
|
</n-input-group>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="已下载大小:">
|
||||||
|
<n-input-group>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="inputs.downloadedValue"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:max="10000"
|
||||||
|
:step="1"
|
||||||
|
/>
|
||||||
|
<n-select
|
||||||
|
v-model:value="inputs.downloadedUnit"
|
||||||
|
label-field="name"
|
||||||
|
value-field="name"
|
||||||
|
:options="units"
|
||||||
|
/>
|
||||||
|
</n-input-group>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="下载速度:">
|
||||||
|
<n-input-group>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="inputs.speedValue"
|
||||||
|
:precision="2"
|
||||||
|
:min="0"
|
||||||
|
:max="10000"
|
||||||
|
:step="1"
|
||||||
|
/>
|
||||||
|
<n-select
|
||||||
|
v-model:value="inputs.speedUnit"
|
||||||
|
label-field="speed"
|
||||||
|
value-field="name"
|
||||||
|
:options="units"
|
||||||
|
/>
|
||||||
|
</n-input-group>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 计算结果 -->
|
||||||
|
<n-card size="small" title="计算结果">
|
||||||
|
<n-form
|
||||||
|
class="form-no-feedback"
|
||||||
|
label-align="right"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="auto"
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-form-item label="大约需要时长:">
|
||||||
|
<span>{{ outputs.duration || '未计算' }}</span>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="大约结束时间:">
|
||||||
|
<span>{{ outputs.time || '未计算' }}</span>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
NCard, NForm, NFormItem,
|
||||||
|
NInputGroup, NInputNumber, NSelect,
|
||||||
|
} from 'naive-ui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
reactive, ref,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
$message,
|
||||||
|
} from '@/assets/js/naive-ui';
|
||||||
|
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
/** 单位和比率(基于 KB) */
|
||||||
|
const units = [
|
||||||
|
{ name: 'KiB', speed: 'KiB/s', rate: 1 },
|
||||||
|
{ name: 'MiB', speed: 'MiB/s', rate: 1024 },
|
||||||
|
{ name: 'GiB', speed: 'GiB/s', rate: 1048576 },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 参数 */
|
||||||
|
const inputs = reactive({
|
||||||
|
downloadedUnit: 'KiB',
|
||||||
|
downloadedValue: 0,
|
||||||
|
sizeUnit: 'KiB',
|
||||||
|
sizeValue: 0,
|
||||||
|
speedUnit: 'KiB',
|
||||||
|
speedValue: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 计算结果 */
|
||||||
|
const outputs = reactive({
|
||||||
|
duration: '',
|
||||||
|
time: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 防抖定时器 */
|
||||||
|
const timer = ref(null);
|
||||||
|
|
||||||
|
/** 计算结果 */
|
||||||
|
function calc() {
|
||||||
|
|
||||||
|
let {
|
||||||
|
downloadedUnit, downloadedValue,
|
||||||
|
sizeUnit, sizeValue,
|
||||||
|
speedUnit, speedValue,
|
||||||
|
} = inputs;
|
||||||
|
|
||||||
|
if (sizeValue === 0 || speedValue === 0) {
|
||||||
|
outputs.duration = '';
|
||||||
|
outputs.time = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取转换比例
|
||||||
|
let downloadedRate = units[units.findIndex((obj) => {
|
||||||
|
return (obj.name === downloadedUnit);
|
||||||
|
})].rate;
|
||||||
|
let sizeRate = units[units.findIndex((obj) => {
|
||||||
|
return (obj.name === sizeUnit);
|
||||||
|
})].rate;
|
||||||
|
let speedRate = units[units.findIndex((obj) => {
|
||||||
|
return (obj.name === speedUnit);
|
||||||
|
})].rate;
|
||||||
|
|
||||||
|
// 转为 KB 单位
|
||||||
|
let realDownloaded = downloadedValue * downloadedRate;
|
||||||
|
let realSize = sizeValue * sizeRate - realDownloaded;
|
||||||
|
let realSpeed = speedValue * speedRate;
|
||||||
|
|
||||||
|
if (realSize < 0) {
|
||||||
|
$message.warning('参数有误,请检查');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时长(秒)
|
||||||
|
let dSeconds = (realSize / realSpeed).toFixed(0);
|
||||||
|
// 起始时间
|
||||||
|
let timeStart = dayjs();
|
||||||
|
// 结束时间
|
||||||
|
let timeEnd = timeStart.add(dSeconds, 'second');
|
||||||
|
// 时长(天,整数)
|
||||||
|
let dDays = timeEnd.diff(timeStart, 'day');
|
||||||
|
// 最后一天的起始时间
|
||||||
|
let timeLastDay = timeStart.add(dDays, 'day');
|
||||||
|
// 时长(格式化,最后一天剩余)
|
||||||
|
let dLastDay = dayjs.duration(timeEnd.diff(timeLastDay)).format('HH 时 mm 分 ss 秒');
|
||||||
|
|
||||||
|
outputs.duration = `${dDays} 天 ${dLastDay}`;
|
||||||
|
outputs.time = timeEnd.format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动计算
|
||||||
|
watch(inputs, () => {
|
||||||
|
clearTimeout(timer.value);
|
||||||
|
timer.value = setTimeout(() => {
|
||||||
|
calc();
|
||||||
|
}, 1000);
|
||||||
|
}, { deep: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.tool-detail-page {
|
||||||
|
:deep(.n-input-number) {
|
||||||
|
width: 12em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-select) {
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
183
src/views/ToolboxView/Calculation/CalcRatio.vue
Normal file
183
src/views/ToolboxView/Calculation/CalcRatio.vue
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page">
|
||||||
|
|
||||||
|
<!-- 计算模式 -->
|
||||||
|
<n-card size="small" title="计算模式">
|
||||||
|
<n-form-item
|
||||||
|
class="form-item-no-feedback"
|
||||||
|
:show-label="false"
|
||||||
|
>
|
||||||
|
<n-select
|
||||||
|
v-model:value="mode"
|
||||||
|
:options="[
|
||||||
|
{ label: '1 -> 2', value: '1-to-2' },
|
||||||
|
{ label: '2 -> 1', value: '2-to-1' },
|
||||||
|
]"
|
||||||
|
:on-blur="update"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 小数位数 -->
|
||||||
|
<n-card size="small" title="小数位数">
|
||||||
|
<n-form-item
|
||||||
|
class="form-item-no-feedback"
|
||||||
|
:show-label="false"
|
||||||
|
>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="decimals"
|
||||||
|
:min="0"
|
||||||
|
:max="10"
|
||||||
|
:precision="0"
|
||||||
|
:step="1"
|
||||||
|
:on-blur="update"
|
||||||
|
></n-input-number>
|
||||||
|
</n-form-item>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 基础比例 -->
|
||||||
|
<n-card size="small" title="基础比例">
|
||||||
|
<n-form-item
|
||||||
|
class="form-item-no-feedback"
|
||||||
|
:show-label="false"
|
||||||
|
>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="base.a"
|
||||||
|
:min="limit.min"
|
||||||
|
:max="limit.max"
|
||||||
|
:precision="0"
|
||||||
|
:step="1"
|
||||||
|
:on-blur="update"
|
||||||
|
></n-input-number>
|
||||||
|
<span class="split">:</span>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="base.b"
|
||||||
|
:min="limit.min"
|
||||||
|
:max="limit.max"
|
||||||
|
:precision="0"
|
||||||
|
:step="1"
|
||||||
|
:on-blur="update"
|
||||||
|
></n-input-number>
|
||||||
|
</n-form-item>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 计算比例 -->
|
||||||
|
<n-card size="small" title="计算比例">
|
||||||
|
<n-form-item
|
||||||
|
class="form-item-no-feedback"
|
||||||
|
:show-label="false"
|
||||||
|
>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="calc.a"
|
||||||
|
:disabled="mode === '2-to-1'"
|
||||||
|
:step="1"
|
||||||
|
:on-blur="update"
|
||||||
|
></n-input-number>
|
||||||
|
<span class="split">:</span>
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="calc.b"
|
||||||
|
:disabled="mode === '1-to-2'"
|
||||||
|
:step="1"
|
||||||
|
:on-blur="update"
|
||||||
|
></n-input-number>
|
||||||
|
</n-form-item>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
bignumber, divide, floor, multiply, number, round,
|
||||||
|
} from 'mathjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
NCard, NFormItem, NInputNumber, NSelect,
|
||||||
|
} from 'naive-ui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
reactive, ref,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
/** 基础比例 */
|
||||||
|
const base = reactive({
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 计算比例 */
|
||||||
|
const calc = reactive({
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 小数位数 */
|
||||||
|
const decimals = ref(5);
|
||||||
|
|
||||||
|
/** 数值范围限制 */
|
||||||
|
const limit = {
|
||||||
|
min: -99999999,
|
||||||
|
max: 99999999,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 模式 */
|
||||||
|
const mode = ref('1-to-2');
|
||||||
|
|
||||||
|
/** 计算 */
|
||||||
|
function calculate() {
|
||||||
|
|
||||||
|
let { min, max } = limit;
|
||||||
|
|
||||||
|
let useMode = mode.value;
|
||||||
|
let ratio = divide(bignumber(base.a), bignumber(base.b));
|
||||||
|
|
||||||
|
if (useMode === '1-to-2') {
|
||||||
|
|
||||||
|
// 注:只允许整数
|
||||||
|
let a = number(floor(calc.a));
|
||||||
|
|
||||||
|
(a < min) && (a = min);
|
||||||
|
(a > max) && (a = max);
|
||||||
|
|
||||||
|
calc.a = a;
|
||||||
|
calc.b = number(round(divide(bignumber(a), ratio), decimals.value));
|
||||||
|
|
||||||
|
} else if (useMode === '2-to-1') {
|
||||||
|
|
||||||
|
// 注:只允许整数
|
||||||
|
let b = number(floor(calc.b));
|
||||||
|
|
||||||
|
(b < min) && (b = min);
|
||||||
|
(b > max) && (b = max);
|
||||||
|
|
||||||
|
calc.a = number(round(multiply(bignumber(b), ratio), decimals.value));
|
||||||
|
calc.b = b;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新 */
|
||||||
|
function update() {
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.tool-detail-page {
|
||||||
|
:deep(.n-input-number) {
|
||||||
|
width: 12em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-select) {
|
||||||
|
width: 12em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split {
|
||||||
|
display: inline-block;
|
||||||
|
width: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
9
src/views/ToolboxView/Conversion/ConvertHtmlEntities.vue
Normal file
9
src/views/ToolboxView/Conversion/ConvertHtmlEntities.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Conversion/ConvertTimestamp.vue
Normal file
9
src/views/ToolboxView/Conversion/ConvertTimestamp.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Conversion/UrlEncodeDecode.vue
Normal file
9
src/views/ToolboxView/Conversion/UrlEncodeDecode.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Edit/CsvEditor.vue
Normal file
9
src/views/ToolboxView/Edit/CsvEditor.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
246
src/views/ToolboxView/Generator/GenerateRandomString.vue
Normal file
246
src/views/ToolboxView/Generator/GenerateRandomString.vue
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page">
|
||||||
|
|
||||||
|
<!-- 配置选项 -->
|
||||||
|
<n-card size="small" title="配置选项">
|
||||||
|
<n-form
|
||||||
|
class="form-no-feedback"
|
||||||
|
label-align="right"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="auto"
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-form-item label="字符串长度:">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="info.strLength"
|
||||||
|
:min="1"
|
||||||
|
:max="1024"
|
||||||
|
:step="1"
|
||||||
|
></n-input-number>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="字符串格式:">
|
||||||
|
<n-flex>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="info.option.hasNum"
|
||||||
|
>数字</n-checkbox>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="info.option.hasChar"
|
||||||
|
>字母</n-checkbox>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="info.option.hasSymbol"
|
||||||
|
>其他符号</n-checkbox>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="info.option.caseSensitive"
|
||||||
|
>大小写</n-checkbox>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="info.option.lowerCase"
|
||||||
|
>全小写(需关闭“大小写”)</n-checkbox>
|
||||||
|
</n-flex>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 结果 -->
|
||||||
|
<n-card size="small" title="结果">
|
||||||
|
<n-form
|
||||||
|
class="form-no-feedback"
|
||||||
|
label-align="right"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="auto"
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-form-item>
|
||||||
|
<n-input
|
||||||
|
v-model:value="info.result"
|
||||||
|
placeholder=""
|
||||||
|
type="textarea"
|
||||||
|
:readonly="true"
|
||||||
|
:rows="3"
|
||||||
|
></n-input>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 操作 -->
|
||||||
|
<n-card size="small" title="操作">
|
||||||
|
<n-flex>
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleGenerate"
|
||||||
|
>生成字符串</n-button>
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!info.result"
|
||||||
|
@click="handleCopy"
|
||||||
|
>复制结果</n-button>
|
||||||
|
</n-flex>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 算法参考 -->
|
||||||
|
<n-card size="small" title="算法参考">
|
||||||
|
<n-ul>
|
||||||
|
<n-li>
|
||||||
|
<n-a
|
||||||
|
href="https://www.cnblogs.com/hankuksui/p/9892729.html"
|
||||||
|
target="_blank"
|
||||||
|
>博客园 - hankuksui</n-a>
|
||||||
|
</n-li>
|
||||||
|
</n-ul>
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
NA, NButton, NCard, NCheckbox,
|
||||||
|
NFlex, NForm, NFormItem,
|
||||||
|
NInput, NInputNumber, NLi, NUl,
|
||||||
|
} from 'naive-ui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
reactive,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
$message,
|
||||||
|
} from '@/assets/js/naive-ui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useClipboard,
|
||||||
|
} from '@vueuse/core';
|
||||||
|
|
||||||
|
const clipboard = useClipboard({
|
||||||
|
legacy: true,
|
||||||
|
read: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = reactive({
|
||||||
|
strLength: 8,
|
||||||
|
option: {
|
||||||
|
caseSensitive: true,
|
||||||
|
hasNum: true,
|
||||||
|
hasChar: true,
|
||||||
|
hasSymbol: false,
|
||||||
|
lowerCase: false
|
||||||
|
},
|
||||||
|
result: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 生成随机字符串
|
||||||
|
* @param {number} strLength 长度
|
||||||
|
* @param {boolean} hasNum 是否包含数字
|
||||||
|
* @param {boolean} hasChar 是否包含字母
|
||||||
|
* @param {boolean} hasSymbol 是否包含其他符号
|
||||||
|
* @param {boolean} caseSensitive 是否包含大小写
|
||||||
|
* @param {boolean} lowerCase 是否全小写
|
||||||
|
* - 当 caseSensitive 为 false 时起作用
|
||||||
|
* @returns {string} 生成的字符串
|
||||||
|
*/
|
||||||
|
function genRandomStr(strLength, hasNum, hasChar, hasSymbol, caseSensitive, lowerCase) {
|
||||||
|
|
||||||
|
let result = '';
|
||||||
|
|
||||||
|
if (
|
||||||
|
hasNum === false &&
|
||||||
|
hasChar === false &&
|
||||||
|
hasSymbol === false
|
||||||
|
) {
|
||||||
|
return '请选中数字、字母或其他符号的其中一项!';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = strLength; i > 0; i--) {
|
||||||
|
|
||||||
|
let num = Math.floor((Math.random() * 94) + 33);
|
||||||
|
let flag = ((
|
||||||
|
(hasNum === false) && ((num >= 48) && (num <= 57))
|
||||||
|
) || (
|
||||||
|
(hasChar === false) && ((
|
||||||
|
(num >= 65) && (num <= 90)
|
||||||
|
) || (
|
||||||
|
(num >= 97) && (num <= 122)
|
||||||
|
))
|
||||||
|
) || (
|
||||||
|
(hasSymbol === false) && ((
|
||||||
|
(num >= 33) && (num <= 47)
|
||||||
|
) || (
|
||||||
|
(num >= 58) && (num <= 64)
|
||||||
|
) || (
|
||||||
|
(num >= 91) && (num <= 96)
|
||||||
|
) || (
|
||||||
|
(num >= 123) && (num <= 127)
|
||||||
|
)
|
||||||
|
)));
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* | CharCode | 符号 |
|
||||||
|
* | :--------- | :----- |
|
||||||
|
* | 033 -> 047 | ! -> / |
|
||||||
|
* | 048 -> 057 | 0 -> 9 |
|
||||||
|
* | 058 -> 064 | : -> @ |
|
||||||
|
* | 065 -> 090 | A -> Z |
|
||||||
|
* | 091 -> 096 | [ -> ` |
|
||||||
|
* | 097 -> 122 | a -> z |
|
||||||
|
* | 123 -> 127 | { -> |
|
||||||
|
*/
|
||||||
|
|
||||||
|
result += String.fromCharCode(num);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caseSensitive === false) {
|
||||||
|
result = (lowerCase ? result.toLocaleLowerCase() : result.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理复制操作 */
|
||||||
|
function handleCopy() {
|
||||||
|
if (clipboard.isSupported) {
|
||||||
|
return clipboard.copy(info.result).then(() => {
|
||||||
|
$message.success('复制成功');
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('复制失败:');
|
||||||
|
console.error(error);
|
||||||
|
$message.error('复制失败:异常');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$message.error('复制失败:当前浏览器不支持该操作');
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理生成操作 */
|
||||||
|
function handleGenerate() {
|
||||||
|
|
||||||
|
let length = info.strLength;
|
||||||
|
let opt = info.option;
|
||||||
|
let result = genRandomStr(length, opt.hasNum, opt.hasChar, opt.hasSymbol, opt.caseSensitive, opt.lowerCase);
|
||||||
|
|
||||||
|
info.result = result;
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.tool-detail-page {
|
||||||
|
:deep(.n-input-number) {
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-input--textarea) {
|
||||||
|
max-width: 48em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
9
src/views/ToolboxView/Generator/GenerateUrls.vue
Normal file
9
src/views/ToolboxView/Generator/GenerateUrls.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Minecraft/CalcChunkLocation.vue
Normal file
9
src/views/ToolboxView/Minecraft/CalcChunkLocation.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Minecraft/UuidConverter.vue
Normal file
9
src/views/ToolboxView/Minecraft/UuidConverter.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Network/WebSocketTestTool.vue
Normal file
9
src/views/ToolboxView/Network/WebSocketTestTool.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Other/OpenNewWindow.vue
Normal file
9
src/views/ToolboxView/Other/OpenNewWindow.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
9
src/views/ToolboxView/Other/RunJavaScript.vue
Normal file
9
src/views/ToolboxView/Other/RunJavaScript.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-detail-page"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
@@ -1,18 +1,205 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="toolbox-view flex-col">
|
<div class="toolbox-view flex-col">
|
||||||
<div class="app-view-header">
|
<div class="app-view-header">
|
||||||
<span>{{ TOOLBOX_MODULE_TITLE }}</span>
|
|
||||||
|
<!-- 返回上一级 -->
|
||||||
|
<n-button
|
||||||
|
v-show="isToolDetail"
|
||||||
|
class="back-button"
|
||||||
|
:text="true"
|
||||||
|
@click="handleCloseTool"
|
||||||
|
>
|
||||||
|
<span class="mdi mdi-arrow-left"></span>
|
||||||
|
</n-button>
|
||||||
|
|
||||||
|
<!-- 标题 -->
|
||||||
|
<span>{{ routeTitle }}</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="app-view-content is-transparent">
|
<div class="app-view-content is-transparent">
|
||||||
|
|
||||||
|
<!-- 工具列表 -->
|
||||||
|
<div class="tool-list">
|
||||||
|
<n-collapse
|
||||||
|
:default-expanded-names="toolList.map(item => item.id)"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- 分类项 -->
|
||||||
|
<n-collapse-item
|
||||||
|
v-for="categoryItem in toolList"
|
||||||
|
v-show="categoryItem.enabled"
|
||||||
|
:key="categoryItem.id"
|
||||||
|
:name="categoryItem.id"
|
||||||
|
:title="categoryItem.title"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- 工具项 -->
|
||||||
|
<div
|
||||||
|
v-for="toolItem in categoryItem.items"
|
||||||
|
v-show="toolItem.enabled"
|
||||||
|
:key="toolItem.id"
|
||||||
|
class="tool-item shadow-1"
|
||||||
|
@click="handleOpenTool(toolItem)"
|
||||||
|
>
|
||||||
|
<div class="item-header">
|
||||||
|
<n-tooltip placement="top-start" trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<span :class="['item-icon', toolItem.iconClass || 'mdi mdi-package-variant-closed']"></span>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div>创建:{{ toolItem.createdAt }}</div>
|
||||||
|
<div>更新:{{ toolItem.updatedAt }}</div>
|
||||||
|
<div>版本:{{ toolItem.version }}</div>
|
||||||
|
</div>
|
||||||
|
</n-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="item-body">
|
||||||
|
<div class="item-title">{{ toolItem.title }}</div>
|
||||||
|
<n-ellipsis
|
||||||
|
class="item-desc"
|
||||||
|
:line-clamp="2"
|
||||||
|
:tooltip="{ placement: 'bottom-start' }"
|
||||||
|
>{{ toolItem.desc }}</n-ellipsis>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</n-collapse-item>
|
||||||
|
|
||||||
|
</n-collapse>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 工具页面 -->
|
||||||
|
<div
|
||||||
|
v-show="isToolDetail"
|
||||||
|
class="tool-detail-wrapper"
|
||||||
|
>
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
TOOLBOX_MODULE_TITLE,
|
NButton, NCollapse, NCollapseItem, NEllipsis, NTooltip,
|
||||||
} from '@/config/modules';
|
} from 'naive-ui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useRoute, useRouter,
|
||||||
|
} from 'vue-router';
|
||||||
|
|
||||||
|
import {
|
||||||
|
toolList,
|
||||||
|
} from '@/assets/js/toolbox-data';
|
||||||
|
|
||||||
|
/** 是否为工具页面 */
|
||||||
|
const isToolDetail = computed(() => {
|
||||||
|
return route.meta.isToolDetail;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 路由 */
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
/** 路由 */
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
/** 页面标题 */
|
||||||
|
const routeTitle = computed(() => {
|
||||||
|
return route.meta.title;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 关闭工具 */
|
||||||
|
function handleCloseTool() {
|
||||||
|
return router.push({
|
||||||
|
name: 'ToolboxView',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 打开工具
|
||||||
|
* @param {ToolboxItem} data
|
||||||
|
*/
|
||||||
|
function handleOpenTool(data) {
|
||||||
|
return router.push({
|
||||||
|
name: `Toolbox/${data.component}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.back-button {
|
||||||
|
margin-right: 0.5em;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.tool-list {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-item {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 256px;
|
||||||
|
height: 132px;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
background-color: #FFF;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1;
|
||||||
|
transition: outline 0.25s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
outline-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-icon {
|
||||||
|
font-size: 32px;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.item-desc) {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.2;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-detail-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 20px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #FFF;
|
||||||
|
|
||||||
|
:deep(.tool-detail-page) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
> .n-card:not(:first-child) {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-no-feedback .n-form-item-feedback-wrapper,
|
||||||
|
.form-item-no-feedback .n-form-item-feedback-wrapper {
|
||||||
|
min-height: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
47
types/web.d.ts
vendored
47
types/web.d.ts
vendored
@@ -4,7 +4,7 @@ import type {
|
|||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
RouteLocationRaw,
|
RouteLocationRaw, RouteRecordRaw,
|
||||||
} from 'vue-router';
|
} from 'vue-router';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -33,6 +33,40 @@ declare global {
|
|||||||
_key?: string;
|
_key?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 工具箱分类 */
|
||||||
|
interface ToolboxCategory {
|
||||||
|
/** 分类唯一 ID */
|
||||||
|
id: string;
|
||||||
|
/** 分类名称 */
|
||||||
|
title: string;
|
||||||
|
/** 是否启用 */
|
||||||
|
enabled: boolean;
|
||||||
|
/** 工具列表 */
|
||||||
|
items: ToolboxItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 工具箱工具信息 */
|
||||||
|
interface ToolboxItem {
|
||||||
|
/** 工具唯一 ID */
|
||||||
|
id: string;
|
||||||
|
/** 工具名称 */
|
||||||
|
title: string;
|
||||||
|
/** 工具简介 */
|
||||||
|
desc: string;
|
||||||
|
/** 图标 */
|
||||||
|
iconClass: string;
|
||||||
|
/** 组件路径 */
|
||||||
|
component: string;
|
||||||
|
/** 创建日期 */
|
||||||
|
createdAt: string;
|
||||||
|
/** 更新日期 */
|
||||||
|
updatedAt: string;
|
||||||
|
/** 版本号 */
|
||||||
|
version: string;
|
||||||
|
/** 是否启用 */
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
// window
|
// window
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|
||||||
@@ -54,14 +88,25 @@ declare global {
|
|||||||
|
|
||||||
// Vue Router
|
// Vue Router
|
||||||
type VueRouteLocationRaw = RouteLocationRaw;
|
type VueRouteLocationRaw = RouteLocationRaw;
|
||||||
|
type VueRouteRecordRaw = RouteRecordRaw;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module 'vue-router' {
|
declare module 'vue-router' {
|
||||||
interface RouteMeta {
|
interface RouteMeta {
|
||||||
|
|
||||||
|
/** 主界面侧边栏图标 class */
|
||||||
iconClass?: string;
|
iconClass?: string;
|
||||||
|
|
||||||
|
/** 是否为工具页面 */
|
||||||
|
isToolDetail?: boolean;
|
||||||
|
|
||||||
|
/** 是否在主界面侧边栏显示 */
|
||||||
showInAside?: boolean;
|
showInAside?: boolean;
|
||||||
|
|
||||||
|
/** 页面标题 */
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,9 +14,15 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
assetsInlineLimit: 0,
|
assetsInlineLimit: 0,
|
||||||
},
|
},
|
||||||
|
esbuild: {
|
||||||
|
supported: {
|
||||||
|
bigint: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
envPrefix: 'V_ENV_',
|
envPrefix: 'V_ENV_',
|
||||||
plugins: [
|
plugins: [
|
||||||
legacy({
|
legacy({
|
||||||
|
polyfills: false,
|
||||||
renderLegacyChunks: true,
|
renderLegacyChunks: true,
|
||||||
renderModernChunks: true,
|
renderModernChunks: true,
|
||||||
targets: ['defaults', 'not IE 11'],
|
targets: ['defaults', 'not IE 11'],
|
||||||
|
Reference in New Issue
Block a user