Compare commits
1 Commits
main
...
codex/remo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61156eca02 |
10
README.md
10
README.md
@@ -28,11 +28,11 @@ pnpm install
|
|||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
组件库将 Vue、D3、Ant Design Vue 和 vue3-colorpicker 作为 peer dependency;直接安装到业务项目时请一并
|
组件库将 Vue、D3 和 vue3-colorpicker 作为 peer dependency;直接安装到业务项目时请一并
|
||||||
安装这些依赖:
|
安装这些依赖:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm add waveform-analysis vue d3 ant-design-vue vue3-colorpicker
|
pnpm add waveform-analysis vue d3 vue3-colorpicker
|
||||||
```
|
```
|
||||||
|
|
||||||
### 运行时版本要求
|
### 运行时版本要求
|
||||||
@@ -40,11 +40,11 @@ pnpm add waveform-analysis vue d3 ant-design-vue vue3-colorpicker
|
|||||||
组件库支持以下运行时版本:
|
组件库支持以下运行时版本:
|
||||||
|
|
||||||
| 依赖 | 支持版本 |
|
| 依赖 | 支持版本 |
|
||||||
| -------------- | ------------- |
|
| ---- | ------------- |
|
||||||
| Vue | `>=3.2.33 <4` |
|
| Vue | `>=3.2.33 <4` |
|
||||||
| Ant Design Vue | `>=3.2.20 <4` |
|
| D3 | `>=7.9.0 <8` |
|
||||||
|
|
||||||
安装时请确保业务项目中的 Vue 与 Ant Design Vue 版本满足上述范围。
|
安装时请确保业务项目中的 Vue 与 D3 版本满足上述范围。
|
||||||
|
|
||||||
## 发布
|
## 发布
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
"test:coverage": "vitest run --coverage"
|
"test:coverage": "vitest run --coverage"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"ant-design-vue": ">=3.2.20 <4",
|
|
||||||
"d3": ">=7.9.0 <8",
|
"d3": ">=7.9.0 <8",
|
||||||
"vue": ">=3.2.33 <4",
|
"vue": ">=3.2.33 <4",
|
||||||
"vue3-colorpicker": ">=2.3.0 <3"
|
"vue3-colorpicker": ">=2.3.0 <3"
|
||||||
@@ -47,7 +46,6 @@
|
|||||||
"@vitejs/plugin-vue": "6.0.8",
|
"@vitejs/plugin-vue": "6.0.8",
|
||||||
"@vitest/coverage-v8": "4.1.10",
|
"@vitest/coverage-v8": "4.1.10",
|
||||||
"@vue/test-utils": "2.4.11",
|
"@vue/test-utils": "2.4.11",
|
||||||
"ant-design-vue": "4.2.6",
|
|
||||||
"d3": "7.9.0",
|
"d3": "7.9.0",
|
||||||
"eslint": "10.7.0",
|
"eslint": "10.7.0",
|
||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
|
|||||||
198
pnpm-lock.yaml
generated
198
pnpm-lock.yaml
generated
@@ -26,9 +26,6 @@ importers:
|
|||||||
'@vue/test-utils':
|
'@vue/test-utils':
|
||||||
specifier: 2.4.11
|
specifier: 2.4.11
|
||||||
version: 2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@6.0.3))
|
version: 2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@6.0.3))
|
||||||
ant-design-vue:
|
|
||||||
specifier: 4.2.6
|
|
||||||
version: 4.2.6(vue@3.5.40(typescript@6.0.3))
|
|
||||||
d3:
|
d3:
|
||||||
specifier: 7.9.0
|
specifier: 7.9.0
|
||||||
version: 7.9.0
|
version: 7.9.0
|
||||||
@@ -77,17 +74,6 @@ packages:
|
|||||||
'@aesoper/normal-utils@0.1.5':
|
'@aesoper/normal-utils@0.1.5':
|
||||||
resolution: {integrity: sha512-LFF/6y6h5mfwhnJaWqqxuC8zzDaHCG62kMRkd8xhDtq62TQj9dM17A9DhE87W7DhiARJsHLgcina/9P4eNCN1w==}
|
resolution: {integrity: sha512-LFF/6y6h5mfwhnJaWqqxuC8zzDaHCG62kMRkd8xhDtq62TQj9dM17A9DhE87W7DhiARJsHLgcina/9P4eNCN1w==}
|
||||||
|
|
||||||
'@ant-design/colors@6.0.0':
|
|
||||||
resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
|
|
||||||
|
|
||||||
'@ant-design/icons-svg@4.5.0':
|
|
||||||
resolution: {integrity: sha512-1BTUFyKPTBZ53MuTP8s0k5SFEXL7o3VHEOwLgzaoWKwnBeqIcqUtVshc4SKzhI6uACfqhJqBwBUE9FsWR3uULA==}
|
|
||||||
|
|
||||||
'@ant-design/icons-vue@7.0.1':
|
|
||||||
resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
|
|
||||||
peerDependencies:
|
|
||||||
vue: '>=3.0.3'
|
|
||||||
|
|
||||||
'@asamuzakjp/css-color@5.1.11':
|
'@asamuzakjp/css-color@5.1.11':
|
||||||
resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==}
|
resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
||||||
@@ -116,10 +102,6 @@ packages:
|
|||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@babel/runtime@7.29.7':
|
|
||||||
resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
|
|
||||||
engines: {node: '>=6.9.0'}
|
|
||||||
|
|
||||||
'@babel/types@7.29.7':
|
'@babel/types@7.29.7':
|
||||||
resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
|
resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -168,10 +150,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
|
resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
|
||||||
engines: {node: '>=20.19.0'}
|
engines: {node: '>=20.19.0'}
|
||||||
|
|
||||||
'@ctrl/tinycolor@3.6.1':
|
|
||||||
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
'@emnapi/core@1.11.1':
|
'@emnapi/core@1.11.1':
|
||||||
resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
|
resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
|
||||||
|
|
||||||
@@ -181,12 +159,6 @@ packages:
|
|||||||
'@emnapi/wasi-threads@1.2.2':
|
'@emnapi/wasi-threads@1.2.2':
|
||||||
resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
|
resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
|
||||||
|
|
||||||
'@emotion/hash@0.9.2':
|
|
||||||
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
|
|
||||||
|
|
||||||
'@emotion/unitless@0.8.1':
|
|
||||||
resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
|
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.9.1':
|
'@eslint-community/eslint-utils@4.9.1':
|
||||||
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
|
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -386,9 +358,6 @@ packages:
|
|||||||
'@rolldown/pluginutils@1.0.1':
|
'@rolldown/pluginutils@1.0.1':
|
||||||
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
|
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
|
||||||
|
|
||||||
'@simonwep/pickr@1.8.2':
|
|
||||||
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
|
||||||
|
|
||||||
'@standard-schema/spec@1.1.0':
|
'@standard-schema/spec@1.1.0':
|
||||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||||
|
|
||||||
@@ -710,15 +679,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
ant-design-vue@4.2.6:
|
|
||||||
resolution: {integrity: sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==}
|
|
||||||
engines: {node: '>=12.22.0'}
|
|
||||||
peerDependencies:
|
|
||||||
vue: '>=3.2.0'
|
|
||||||
|
|
||||||
array-tree-filter@2.1.0:
|
|
||||||
resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==}
|
|
||||||
|
|
||||||
assertion-error@2.0.1:
|
assertion-error@2.0.1:
|
||||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -726,9 +686,6 @@ packages:
|
|||||||
ast-v8-to-istanbul@1.0.5:
|
ast-v8-to-istanbul@1.0.5:
|
||||||
resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==}
|
resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==}
|
||||||
|
|
||||||
async-validator@4.2.5:
|
|
||||||
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
|
|
||||||
|
|
||||||
balanced-match@1.0.2:
|
balanced-match@1.0.2:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
|
|
||||||
@@ -768,18 +725,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
|
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
compute-scroll-into-view@1.0.20:
|
|
||||||
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
|
||||||
|
|
||||||
config-chain@1.1.13:
|
config-chain@1.1.13:
|
||||||
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
|
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
|
||||||
|
|
||||||
convert-source-map@2.0.0:
|
convert-source-map@2.0.0:
|
||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
|
|
||||||
core-js@3.49.0:
|
|
||||||
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
|
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -927,9 +878,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
|
resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
||||||
|
|
||||||
dayjs@1.11.21:
|
|
||||||
resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==}
|
|
||||||
|
|
||||||
debug@4.4.3:
|
debug@4.4.3:
|
||||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -952,12 +900,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
dom-align@1.12.4:
|
|
||||||
resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==}
|
|
||||||
|
|
||||||
dom-scroll-into-view@2.0.1:
|
|
||||||
resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
|
|
||||||
|
|
||||||
eastasianwidth@0.2.0:
|
eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
|
|
||||||
@@ -1163,10 +1105,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
is-plain-object@3.0.1:
|
|
||||||
resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
is-plain-object@5.0.0:
|
is-plain-object@5.0.0:
|
||||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1203,9 +1141,6 @@ packages:
|
|||||||
js-tokens@10.0.0:
|
js-tokens@10.0.0:
|
||||||
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
|
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
|
||||||
|
|
||||||
jsdom@29.1.1:
|
jsdom@29.1.1:
|
||||||
resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==}
|
resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==}
|
||||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0}
|
engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0}
|
||||||
@@ -1312,13 +1247,6 @@ packages:
|
|||||||
lodash-es@4.18.1:
|
lodash-es@4.18.1:
|
||||||
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
||||||
|
|
||||||
lodash@4.18.1:
|
|
||||||
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
|
|
||||||
|
|
||||||
loose-envify@1.4.0:
|
|
||||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
@@ -1362,9 +1290,6 @@ packages:
|
|||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
nanopop@2.4.2:
|
|
||||||
resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==}
|
|
||||||
|
|
||||||
natural-compare@1.4.0:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
@@ -1451,9 +1376,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1:
|
|
||||||
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
|
||||||
|
|
||||||
robust-predicates@3.0.3:
|
robust-predicates@3.0.3:
|
||||||
resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
|
resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
|
||||||
|
|
||||||
@@ -1472,17 +1394,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
||||||
engines: {node: '>=v12.22.7'}
|
engines: {node: '>=v12.22.7'}
|
||||||
|
|
||||||
scroll-into-view-if-needed@2.2.31:
|
|
||||||
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
|
||||||
|
|
||||||
semver@7.8.5:
|
semver@7.8.5:
|
||||||
resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
|
resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
shallow-equal@1.2.1:
|
|
||||||
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
|
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1524,9 +1440,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
|
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
stylis@4.4.0:
|
|
||||||
resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==}
|
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1534,10 +1447,6 @@ packages:
|
|||||||
symbol-tree@3.2.4:
|
symbol-tree@3.2.4:
|
||||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||||
|
|
||||||
throttle-debounce@5.0.2:
|
|
||||||
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
|
|
||||||
engines: {node: '>=12.22'}
|
|
||||||
|
|
||||||
tinybench@2.9.0:
|
tinybench@2.9.0:
|
||||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||||
|
|
||||||
@@ -1722,12 +1631,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=5.0.0'
|
typescript: '>=5.0.0'
|
||||||
|
|
||||||
vue-types@3.0.2:
|
|
||||||
resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
|
|
||||||
engines: {node: '>=10.15.0'}
|
|
||||||
peerDependencies:
|
|
||||||
vue: ^3.0.0
|
|
||||||
|
|
||||||
vue-types@4.2.1:
|
vue-types@4.2.1:
|
||||||
resolution: {integrity: sha512-DNQZmJuOvovLUIp0BENRkdnZHbI0V4e2mNvjAZOAXKD56YGvRchtUYOXA/XqTxdv7Ng5SJLZqRKRpAhm5NLaPQ==}
|
resolution: {integrity: sha512-DNQZmJuOvovLUIp0BENRkdnZHbI0V4e2mNvjAZOAXKD56YGvRchtUYOXA/XqTxdv7Ng5SJLZqRKRpAhm5NLaPQ==}
|
||||||
engines: {node: '>=12.16.0'}
|
engines: {node: '>=12.16.0'}
|
||||||
@@ -1758,9 +1661,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
warning@4.0.3:
|
|
||||||
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
|
|
||||||
|
|
||||||
webidl-conversions@8.0.1:
|
webidl-conversions@8.0.1:
|
||||||
resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
|
resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
@@ -1814,18 +1714,6 @@ snapshots:
|
|||||||
|
|
||||||
'@aesoper/normal-utils@0.1.5': {}
|
'@aesoper/normal-utils@0.1.5': {}
|
||||||
|
|
||||||
'@ant-design/colors@6.0.0':
|
|
||||||
dependencies:
|
|
||||||
'@ctrl/tinycolor': 3.6.1
|
|
||||||
|
|
||||||
'@ant-design/icons-svg@4.5.0': {}
|
|
||||||
|
|
||||||
'@ant-design/icons-vue@7.0.1(vue@3.5.40(typescript@6.0.3))':
|
|
||||||
dependencies:
|
|
||||||
'@ant-design/colors': 6.0.0
|
|
||||||
'@ant-design/icons-svg': 4.5.0
|
|
||||||
vue: 3.5.40(typescript@6.0.3)
|
|
||||||
|
|
||||||
'@asamuzakjp/css-color@5.1.11':
|
'@asamuzakjp/css-color@5.1.11':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@asamuzakjp/generational-cache': 1.0.1
|
'@asamuzakjp/generational-cache': 1.0.1
|
||||||
@@ -1854,8 +1742,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.29.7
|
'@babel/types': 7.29.7
|
||||||
|
|
||||||
'@babel/runtime@7.29.7': {}
|
|
||||||
|
|
||||||
'@babel/types@7.29.7':
|
'@babel/types@7.29.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-string-parser': 7.29.7
|
'@babel/helper-string-parser': 7.29.7
|
||||||
@@ -1891,8 +1777,6 @@ snapshots:
|
|||||||
|
|
||||||
'@csstools/css-tokenizer@4.0.0': {}
|
'@csstools/css-tokenizer@4.0.0': {}
|
||||||
|
|
||||||
'@ctrl/tinycolor@3.6.1': {}
|
|
||||||
|
|
||||||
'@emnapi/core@1.11.1':
|
'@emnapi/core@1.11.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emnapi/wasi-threads': 1.2.2
|
'@emnapi/wasi-threads': 1.2.2
|
||||||
@@ -1909,10 +1793,6 @@ snapshots:
|
|||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@emotion/hash@0.9.2': {}
|
|
||||||
|
|
||||||
'@emotion/unitless@0.8.1': {}
|
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.9.1(eslint@10.7.0)':
|
'@eslint-community/eslint-utils@4.9.1(eslint@10.7.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 10.7.0
|
eslint: 10.7.0
|
||||||
@@ -2050,11 +1930,6 @@ snapshots:
|
|||||||
|
|
||||||
'@rolldown/pluginutils@1.0.1': {}
|
'@rolldown/pluginutils@1.0.1': {}
|
||||||
|
|
||||||
'@simonwep/pickr@1.8.2':
|
|
||||||
dependencies:
|
|
||||||
core-js: 3.49.0
|
|
||||||
nanopop: 2.4.2
|
|
||||||
|
|
||||||
'@standard-schema/spec@1.1.0': {}
|
'@standard-schema/spec@1.1.0': {}
|
||||||
|
|
||||||
'@tybys/wasm-util@0.10.3':
|
'@tybys/wasm-util@0.10.3':
|
||||||
@@ -2483,34 +2358,6 @@ snapshots:
|
|||||||
|
|
||||||
ansi-styles@6.2.3: {}
|
ansi-styles@6.2.3: {}
|
||||||
|
|
||||||
ant-design-vue@4.2.6(vue@3.5.40(typescript@6.0.3)):
|
|
||||||
dependencies:
|
|
||||||
'@ant-design/colors': 6.0.0
|
|
||||||
'@ant-design/icons-vue': 7.0.1(vue@3.5.40(typescript@6.0.3))
|
|
||||||
'@babel/runtime': 7.29.7
|
|
||||||
'@ctrl/tinycolor': 3.6.1
|
|
||||||
'@emotion/hash': 0.9.2
|
|
||||||
'@emotion/unitless': 0.8.1
|
|
||||||
'@simonwep/pickr': 1.8.2
|
|
||||||
array-tree-filter: 2.1.0
|
|
||||||
async-validator: 4.2.5
|
|
||||||
csstype: 3.2.3
|
|
||||||
dayjs: 1.11.21
|
|
||||||
dom-align: 1.12.4
|
|
||||||
dom-scroll-into-view: 2.0.1
|
|
||||||
lodash: 4.18.1
|
|
||||||
lodash-es: 4.18.1
|
|
||||||
resize-observer-polyfill: 1.5.1
|
|
||||||
scroll-into-view-if-needed: 2.2.31
|
|
||||||
shallow-equal: 1.2.1
|
|
||||||
stylis: 4.4.0
|
|
||||||
throttle-debounce: 5.0.2
|
|
||||||
vue: 3.5.40(typescript@6.0.3)
|
|
||||||
vue-types: 3.0.2(vue@3.5.40(typescript@6.0.3))
|
|
||||||
warning: 4.0.3
|
|
||||||
|
|
||||||
array-tree-filter@2.1.0: {}
|
|
||||||
|
|
||||||
assertion-error@2.0.1: {}
|
assertion-error@2.0.1: {}
|
||||||
|
|
||||||
ast-v8-to-istanbul@1.0.5:
|
ast-v8-to-istanbul@1.0.5:
|
||||||
@@ -2519,8 +2366,6 @@ snapshots:
|
|||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
js-tokens: 10.0.0
|
js-tokens: 10.0.0
|
||||||
|
|
||||||
async-validator@4.2.5: {}
|
|
||||||
|
|
||||||
balanced-match@1.0.2: {}
|
balanced-match@1.0.2: {}
|
||||||
|
|
||||||
balanced-match@4.0.4: {}
|
balanced-match@4.0.4: {}
|
||||||
@@ -2551,8 +2396,6 @@ snapshots:
|
|||||||
|
|
||||||
commander@7.2.0: {}
|
commander@7.2.0: {}
|
||||||
|
|
||||||
compute-scroll-into-view@1.0.20: {}
|
|
||||||
|
|
||||||
config-chain@1.1.13:
|
config-chain@1.1.13:
|
||||||
dependencies:
|
dependencies:
|
||||||
ini: 1.3.8
|
ini: 1.3.8
|
||||||
@@ -2560,8 +2403,6 @@ snapshots:
|
|||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
core-js@3.49.0: {}
|
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
path-key: 3.1.1
|
||||||
@@ -2736,8 +2577,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@noble/hashes'
|
- '@noble/hashes'
|
||||||
|
|
||||||
dayjs@1.11.21: {}
|
|
||||||
|
|
||||||
debug@4.4.3:
|
debug@4.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@@ -2752,10 +2591,6 @@ snapshots:
|
|||||||
|
|
||||||
detect-libc@2.1.2: {}
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
dom-align@1.12.4: {}
|
|
||||||
|
|
||||||
dom-scroll-into-view@2.0.1: {}
|
|
||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
|
|
||||||
editorconfig@1.0.7:
|
editorconfig@1.0.7:
|
||||||
@@ -2949,8 +2784,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
is-plain-object@3.0.1: {}
|
|
||||||
|
|
||||||
is-plain-object@5.0.0: {}
|
is-plain-object@5.0.0: {}
|
||||||
|
|
||||||
is-potential-custom-element-name@1.0.1: {}
|
is-potential-custom-element-name@1.0.1: {}
|
||||||
@@ -2988,8 +2821,6 @@ snapshots:
|
|||||||
|
|
||||||
js-tokens@10.0.0: {}
|
js-tokens@10.0.0: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
|
||||||
|
|
||||||
jsdom@29.1.1:
|
jsdom@29.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@asamuzakjp/css-color': 5.1.11
|
'@asamuzakjp/css-color': 5.1.11
|
||||||
@@ -3086,12 +2917,6 @@ snapshots:
|
|||||||
|
|
||||||
lodash-es@4.18.1: {}
|
lodash-es@4.18.1: {}
|
||||||
|
|
||||||
lodash@4.18.1: {}
|
|
||||||
|
|
||||||
loose-envify@1.4.0:
|
|
||||||
dependencies:
|
|
||||||
js-tokens: 4.0.0
|
|
||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
lru-cache@11.5.2: {}
|
lru-cache@11.5.2: {}
|
||||||
@@ -3128,8 +2953,6 @@ snapshots:
|
|||||||
|
|
||||||
nanoid@3.3.16: {}
|
nanoid@3.3.16: {}
|
||||||
|
|
||||||
nanopop@2.4.2: {}
|
|
||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
nopt@7.2.1:
|
nopt@7.2.1:
|
||||||
@@ -3203,8 +3026,6 @@ snapshots:
|
|||||||
|
|
||||||
require-from-string@2.0.2: {}
|
require-from-string@2.0.2: {}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1: {}
|
|
||||||
|
|
||||||
robust-predicates@3.0.3: {}
|
robust-predicates@3.0.3: {}
|
||||||
|
|
||||||
rolldown@1.1.5:
|
rolldown@1.1.5:
|
||||||
@@ -3236,14 +3057,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
xmlchars: 2.2.0
|
xmlchars: 2.2.0
|
||||||
|
|
||||||
scroll-into-view-if-needed@2.2.31:
|
|
||||||
dependencies:
|
|
||||||
compute-scroll-into-view: 1.0.20
|
|
||||||
|
|
||||||
semver@7.8.5: {}
|
semver@7.8.5: {}
|
||||||
|
|
||||||
shallow-equal@1.2.1: {}
|
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
shebang-regex: 3.0.0
|
shebang-regex: 3.0.0
|
||||||
@@ -3280,16 +3095,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 6.2.2
|
ansi-regex: 6.2.2
|
||||||
|
|
||||||
stylis@4.4.0: {}
|
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag: 4.0.0
|
has-flag: 4.0.0
|
||||||
|
|
||||||
symbol-tree@3.2.4: {}
|
symbol-tree@3.2.4: {}
|
||||||
|
|
||||||
throttle-debounce@5.0.2: {}
|
|
||||||
|
|
||||||
tinybench@2.9.0: {}
|
tinybench@2.9.0: {}
|
||||||
|
|
||||||
tinycolor2@1.6.0: {}
|
tinycolor2@1.6.0: {}
|
||||||
@@ -3417,11 +3228,6 @@ snapshots:
|
|||||||
'@vue/language-core': 3.3.7
|
'@vue/language-core': 3.3.7
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
|
|
||||||
vue-types@3.0.2(vue@3.5.40(typescript@6.0.3)):
|
|
||||||
dependencies:
|
|
||||||
is-plain-object: 3.0.1
|
|
||||||
vue: 3.5.40(typescript@6.0.3)
|
|
||||||
|
|
||||||
vue-types@4.2.1(vue@3.5.40(typescript@6.0.3)):
|
vue-types@4.2.1(vue@3.5.40(typescript@6.0.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
is-plain-object: 5.0.0
|
is-plain-object: 5.0.0
|
||||||
@@ -3452,10 +3258,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
xml-name-validator: 5.0.0
|
xml-name-validator: 5.0.0
|
||||||
|
|
||||||
warning@4.0.3:
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
webidl-conversions@8.0.1: {}
|
webidl-conversions@8.0.1: {}
|
||||||
|
|
||||||
whatwg-mimetype@5.0.0: {}
|
whatwg-mimetype@5.0.0: {}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { flushPromises, mount } from '@vue/test-utils'
|
import { flushPromises, mount } from '@vue/test-utils'
|
||||||
import { InputNumber, Select } from 'ant-design-vue'
|
|
||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import { ColorPicker } from 'vue3-colorpicker'
|
import { ColorPicker } from 'vue3-colorpicker'
|
||||||
|
|
||||||
@@ -53,9 +52,9 @@ describe('App workspace layout', { timeout: 20_000 }, () => {
|
|||||||
expect(frameControls.find('[aria-label="图框线宽"]').exists()).toBe(true)
|
expect(frameControls.find('[aria-label="图框线宽"]').exists()).toBe(true)
|
||||||
expect(frameControls.find('[aria-label="图框线型"]').exists()).toBe(true)
|
expect(frameControls.find('[aria-label="图框线型"]').exists()).toBe(true)
|
||||||
expect(frameControls.find('[aria-label="显示图框水印"]').exists()).toBe(true)
|
expect(frameControls.find('[aria-label="显示图框水印"]').exists()).toBe(true)
|
||||||
expect(frameControls.get('.frame-style-control--switch .ant-switch').classes()).toContain(
|
expect(
|
||||||
'ant-switch-small',
|
frameControls.get('.frame-style-control--switch .native-switch').attributes('role'),
|
||||||
)
|
).toBe('switch')
|
||||||
const titleControls = panel.get('.title-controls')
|
const titleControls = panel.get('.title-controls')
|
||||||
expect(panel.find('[aria-label="显示标题"]').exists()).toBe(true)
|
expect(panel.find('[aria-label="显示标题"]').exists()).toBe(true)
|
||||||
expect(titleControls.find('[aria-label="标题名称"]').exists()).toBe(true)
|
expect(titleControls.find('[aria-label="标题名称"]').exists()).toBe(true)
|
||||||
@@ -85,8 +84,8 @@ describe('App workspace layout', { timeout: 20_000 }, () => {
|
|||||||
expect(chart.props('cleanView')).toBe(false)
|
expect(chart.props('cleanView')).toBe(false)
|
||||||
expect(chart.props('zeroLine')).toMatchObject({ visible: false, color: '#98a2b3', width: 1 })
|
expect(chart.props('zeroLine')).toMatchObject({ visible: false, color: '#98a2b3', width: 1 })
|
||||||
|
|
||||||
await wrapper.get('[aria-label="净图模式"]').trigger('click')
|
await wrapper.get('[aria-label="净图模式"]').setValue(true)
|
||||||
await wrapper.get('[aria-label="显示零值参考线"]').trigger('click')
|
await wrapper.get('[aria-label="显示零值参考线"]').setValue(true)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
||||||
expect(chart.props('cleanView')).toBe(true)
|
expect(chart.props('cleanView')).toBe(true)
|
||||||
@@ -237,7 +236,7 @@ describe('App workspace layout', { timeout: 20_000 }, () => {
|
|||||||
expect(renderedTitle().attributes('style')).toContain('font-style: normal')
|
expect(renderedTitle().attributes('style')).toContain('font-style: normal')
|
||||||
expect(renderedTitle().attributes('style')).toContain('text-decoration: none')
|
expect(renderedTitle().attributes('style')).toContain('text-decoration: none')
|
||||||
|
|
||||||
await wrapper.get('[aria-label="显示标题"]').trigger('click')
|
await wrapper.get('[aria-label="显示标题"]').setValue(false)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
expect(wrapper.find('.waveform-chart__title-area').exists()).toBe(false)
|
expect(wrapper.find('.waveform-chart__title-area').exists()).toBe(false)
|
||||||
|
|
||||||
@@ -250,17 +249,17 @@ describe('App workspace layout', { timeout: 20_000 }, () => {
|
|||||||
|
|
||||||
const frameControls = wrapper.get('.frame-style-controls')
|
const frameControls = wrapper.get('.frame-style-controls')
|
||||||
const colorPickers = frameControls.findAllComponents(ColorPicker)
|
const colorPickers = frameControls.findAllComponents(ColorPicker)
|
||||||
const widthInput = frameControls.findAllComponents(InputNumber)[0]
|
const widthInput = frameControls.get('[aria-label="图框线宽"]')
|
||||||
const styleSelect = frameControls.findAllComponents(Select)[0]
|
const styleSelect = frameControls.get('[aria-label="图框线型"]')
|
||||||
|
|
||||||
expect(colorPickers).toHaveLength(2)
|
expect(colorPickers).toHaveLength(2)
|
||||||
expect(widthInput).toBeDefined()
|
expect(widthInput.element.tagName).toBe('INPUT')
|
||||||
expect(styleSelect).toBeDefined()
|
expect(styleSelect.element.tagName).toBe('SELECT')
|
||||||
|
|
||||||
colorPickers[0].vm.$emit('update:pureColor', 'rgba(220, 38, 38, 0.8)')
|
colorPickers[0].vm.$emit('update:pureColor', 'rgba(220, 38, 38, 0.8)')
|
||||||
colorPickers[1].vm.$emit('update:pureColor', 'rgba(14, 165, 233, 0.25)')
|
colorPickers[1].vm.$emit('update:pureColor', 'rgba(14, 165, 233, 0.25)')
|
||||||
widthInput?.vm.$emit('update:value', 3)
|
await widthInput.setValue('3')
|
||||||
styleSelect?.vm.$emit('update:value', 'dashed')
|
await styleSelect.setValue('dashed')
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
||||||
const frames = wrapper.findAll('.waveform-chart__plot-frame')
|
const frames = wrapper.findAll('.waveform-chart__plot-frame')
|
||||||
@@ -291,11 +290,11 @@ describe('App workspace layout', { timeout: 20_000 }, () => {
|
|||||||
|
|
||||||
expect(initialWatermarks.length).toBeGreaterThan(1)
|
expect(initialWatermarks.length).toBeGreaterThan(1)
|
||||||
|
|
||||||
await watermarkToggle.trigger('click')
|
await watermarkToggle.setValue(false)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
expect(wrapper.findAll('.waveform-chart__watermark')).toHaveLength(0)
|
expect(wrapper.findAll('.waveform-chart__watermark')).toHaveLength(0)
|
||||||
|
|
||||||
await watermarkToggle.trigger('click')
|
await watermarkToggle.setValue(true)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
expect(
|
expect(
|
||||||
wrapper.findAll('.waveform-chart__watermark').map((watermark) => watermark.text()),
|
wrapper.findAll('.waveform-chart__watermark').map((watermark) => watermark.text()),
|
||||||
|
|||||||
255
src/App.vue
255
src/App.vue
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button, Input, InputNumber, Radio, Select, Switch } from 'ant-design-vue'
|
|
||||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import { ColorPicker } from 'vue3-colorpicker'
|
import { ColorPicker } from 'vue3-colorpicker'
|
||||||
import 'vue3-colorpicker/style.css'
|
import 'vue3-colorpicker/style.css'
|
||||||
@@ -313,6 +312,12 @@ function resetTitleTextStyle() {
|
|||||||
titleUnderline.value = false
|
titleUnderline.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clampNumber(value: unknown, min: number, max: number, fallback: number) {
|
||||||
|
const number = typeof value === 'number' ? value : Number(value)
|
||||||
|
if (!Number.isFinite(number)) return fallback
|
||||||
|
return Math.min(max, Math.max(min, number))
|
||||||
|
}
|
||||||
|
|
||||||
function handleWindowKeydown(event: KeyboardEvent) {
|
function handleWindowKeydown(event: KeyboardEvent) {
|
||||||
if (event.key === 'Escape') closeControls()
|
if (event.key === 'Escape') closeControls()
|
||||||
}
|
}
|
||||||
@@ -323,15 +328,15 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="workspace">
|
<main class="workspace">
|
||||||
<Button
|
<button
|
||||||
|
type="button"
|
||||||
class="mobile-control-toggle"
|
class="mobile-control-toggle"
|
||||||
size="small"
|
|
||||||
:aria-expanded="controlsOpen"
|
:aria-expanded="controlsOpen"
|
||||||
aria-controls="waveform-control-panel"
|
aria-controls="waveform-control-panel"
|
||||||
@click="controlsOpen = true"
|
@click="controlsOpen = true"
|
||||||
>
|
>
|
||||||
控制面板
|
控制面板
|
||||||
</Button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="controlsOpen"
|
v-if="controlsOpen"
|
||||||
@@ -348,32 +353,50 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
aria-label="波形图控制"
|
aria-label="波形图控制"
|
||||||
>
|
>
|
||||||
<div class="control-panel__scroll">
|
<div class="control-panel__scroll">
|
||||||
<Button class="control-panel__close" type="text" size="small" @click="closeControls">
|
<button class="control-panel__close" type="button" @click="closeControls">关闭</button>
|
||||||
关闭
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<section class="control-section">
|
<section class="control-section">
|
||||||
<h2>显示方式</h2>
|
<h2>显示方式</h2>
|
||||||
<Radio.Group
|
<div class="display-mode-control" role="radiogroup" aria-label="波形展示方式">
|
||||||
v-model:value="displayMode"
|
<label
|
||||||
class="display-mode-control"
|
><input v-model="displayMode" type="radio" value="independent" /><span
|
||||||
button-style="solid"
|
>单独坐标</span
|
||||||
size="small"
|
></label
|
||||||
aria-label="波形展示方式"
|
|
||||||
>
|
>
|
||||||
<Radio.Button value="independent">单独坐标</Radio.Button>
|
<label
|
||||||
<Radio.Button value="separated">多道分离</Radio.Button>
|
><input v-model="displayMode" type="radio" value="separated" /><span
|
||||||
<Radio.Button value="compact">多道紧凑</Radio.Button>
|
>多道分离</span
|
||||||
</Radio.Group>
|
></label
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
><input v-model="displayMode" type="radio" value="compact" /><span
|
||||||
|
>多道紧凑</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="control-section">
|
<section class="control-section">
|
||||||
<h2>视图</h2>
|
<h2>视图</h2>
|
||||||
<Button block aria-label="重置波形视图" @click="resetWaveformViewport">重置视图</Button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="control-action control-action--block"
|
||||||
|
aria-label="重置波形视图"
|
||||||
|
@click="resetWaveformViewport"
|
||||||
|
>
|
||||||
|
重置视图
|
||||||
|
</button>
|
||||||
<div class="auxiliary-style-controls" style="margin-top: 10px">
|
<div class="auxiliary-style-controls" style="margin-top: 10px">
|
||||||
<label class="frame-style-control frame-style-control--switch">
|
<label class="frame-style-control frame-style-control--switch">
|
||||||
<span>净图</span>
|
<span>净图</span>
|
||||||
<Switch v-model:checked="cleanView" size="small" aria-label="净图模式" />
|
<input
|
||||||
|
v-model="cleanView"
|
||||||
|
class="native-switch"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
|
aria-label="净图模式"
|
||||||
|
@click.stop
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -381,7 +404,14 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
<section class="control-section">
|
<section class="control-section">
|
||||||
<div class="control-section__header">
|
<div class="control-section__header">
|
||||||
<h2>零值参考线</h2>
|
<h2>零值参考线</h2>
|
||||||
<Switch v-model:checked="zeroLineVisible" size="small" aria-label="显示零值参考线" />
|
<input
|
||||||
|
v-model="zeroLineVisible"
|
||||||
|
class="native-switch"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
|
aria-label="显示零值参考线"
|
||||||
|
@click.stop
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="auxiliary-style-controls zero-line-controls" style="margin-top: 10px">
|
<div class="auxiliary-style-controls zero-line-controls" style="margin-top: 10px">
|
||||||
<label class="frame-style-control">
|
<label class="frame-style-control">
|
||||||
@@ -398,48 +428,73 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
</label>
|
</label>
|
||||||
<label class="frame-style-control">
|
<label class="frame-style-control">
|
||||||
<span>线宽</span>
|
<span>线宽</span>
|
||||||
<InputNumber
|
<input
|
||||||
v-model:value="zeroLineWidth"
|
v-model.number="zeroLineWidth"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
:min="0.5"
|
:min="0.5"
|
||||||
:max="10"
|
:max="10"
|
||||||
:step="0.5"
|
:step="0.5"
|
||||||
size="small"
|
|
||||||
aria-label="零值参考线线宽"
|
aria-label="零值参考线线宽"
|
||||||
|
@blur="zeroLineWidth = clampNumber(zeroLineWidth, 0.5, 10, 1)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="frame-style-control">
|
<label class="frame-style-control">
|
||||||
<span>线型</span>
|
<span>线型</span>
|
||||||
<Select
|
<select v-model="zeroLineDash" class="native-select" aria-label="零值参考线线型">
|
||||||
v-model:value="zeroLineDash"
|
<option
|
||||||
:options="zeroLineDashOptions"
|
v-for="option in zeroLineDashOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="零值参考线线型"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="control-section">
|
<section class="control-section">
|
||||||
<h2>叠加方式</h2>
|
<h2>叠加方式</h2>
|
||||||
<Radio.Group
|
<div class="display-mode-control" role="radiogroup" aria-label="波形叠加方式">
|
||||||
v-model:value="overlayMode"
|
<label
|
||||||
class="display-mode-control"
|
><input v-model="overlayMode" type="radio" value="single-axis" /><span
|
||||||
button-style="solid"
|
>单值轴</span
|
||||||
size="small"
|
></label
|
||||||
aria-label="波形叠加方式"
|
|
||||||
>
|
>
|
||||||
<Radio.Button value="single-axis">单值轴</Radio.Button>
|
<label
|
||||||
<Radio.Button value="multi-axis">多值轴</Radio.Button>
|
><input v-model="overlayMode" type="radio" value="multi-axis" /><span
|
||||||
</Radio.Group>
|
>多值轴</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="control-section">
|
<section class="control-section">
|
||||||
<h2>图框布局</h2>
|
<h2>图框布局</h2>
|
||||||
<div class="grid-size-control" aria-label="波形网格尺寸">
|
<div class="grid-size-control" aria-label="波形网格尺寸">
|
||||||
<InputNumber v-model:value="rowCount" :min="1" :max="10" size="small" />
|
<input
|
||||||
|
v-model.number="rowCount"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max="10"
|
||||||
|
step="1"
|
||||||
|
aria-label="波形网格行数"
|
||||||
|
@blur="rowCount = clampNumber(rowCount, 1, 10, 2)"
|
||||||
|
/>
|
||||||
<span>行</span>
|
<span>行</span>
|
||||||
<span class="control-separator">×</span>
|
<span class="control-separator">×</span>
|
||||||
<InputNumber v-model:value="columnCount" :min="1" :max="10" size="small" />
|
<input
|
||||||
|
v-model.number="columnCount"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max="10"
|
||||||
|
step="1"
|
||||||
|
aria-label="波形网格列数"
|
||||||
|
@blur="columnCount = clampNumber(columnCount, 1, 10, 1)"
|
||||||
|
/>
|
||||||
<span>列</span>
|
<span>列</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -473,30 +528,38 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
</label>
|
</label>
|
||||||
<label class="frame-style-control">
|
<label class="frame-style-control">
|
||||||
<span>线宽</span>
|
<span>线宽</span>
|
||||||
<InputNumber
|
<input
|
||||||
v-model:value="frameBorderWidth"
|
v-model.number="frameBorderWidth"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="10"
|
:max="10"
|
||||||
:step="0.5"
|
:step="0.5"
|
||||||
size="small"
|
|
||||||
aria-label="图框线宽"
|
aria-label="图框线宽"
|
||||||
|
@blur="frameBorderWidth = clampNumber(frameBorderWidth, 0, 10, 1)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="frame-style-control">
|
<label class="frame-style-control">
|
||||||
<span>线型</span>
|
<span>线型</span>
|
||||||
<Select
|
<select v-model="frameBorderStyle" class="native-select" aria-label="图框线型">
|
||||||
v-model:value="frameBorderStyle"
|
<option
|
||||||
:options="frameBorderStyleOptions"
|
v-for="option in frameBorderStyleOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="图框线型"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="frame-style-control frame-style-control--switch">
|
<label class="frame-style-control frame-style-control--switch">
|
||||||
<span>水印</span>
|
<span>水印</span>
|
||||||
<Switch
|
<input
|
||||||
v-model:checked="frameWatermarkVisible"
|
v-model="frameWatermarkVisible"
|
||||||
size="small"
|
class="native-switch"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
aria-label="显示图框水印"
|
aria-label="显示图框水印"
|
||||||
|
@click.stop
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -505,41 +568,56 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
<section class="control-section title-control-section">
|
<section class="control-section title-control-section">
|
||||||
<div class="control-section__header">
|
<div class="control-section__header">
|
||||||
<h2>标题</h2>
|
<h2>标题</h2>
|
||||||
<Switch v-model:checked="titleVisible" size="small" aria-label="显示标题" />
|
<input
|
||||||
|
v-model="titleVisible"
|
||||||
|
class="native-switch"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
|
aria-label="显示标题"
|
||||||
|
@click.stop
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="title-controls">
|
<div class="title-controls">
|
||||||
<label class="title-control title-control--wide">
|
<label class="title-control title-control--wide">
|
||||||
<span>标题名称</span>
|
<span>标题名称</span>
|
||||||
<Input v-model:value="titleText" size="small" aria-label="标题名称" />
|
<input v-model="titleText" class="native-input" type="text" aria-label="标题名称" />
|
||||||
</label>
|
</label>
|
||||||
<label class="title-control title-control--wide">
|
<label class="title-control title-control--wide">
|
||||||
<span>对齐方式</span>
|
<span>对齐方式</span>
|
||||||
<Select
|
<select v-model="titleAlign" class="native-select" aria-label="标题对齐方式">
|
||||||
v-model:value="titleAlign"
|
<option
|
||||||
:options="titleAlignOptions"
|
v-for="option in titleAlignOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="标题对齐方式"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="title-control">
|
<label class="title-control">
|
||||||
<span>字体</span>
|
<span>字体</span>
|
||||||
<Select
|
<select v-model="titleFontFamily" class="native-select" aria-label="标题字体">
|
||||||
v-model:value="titleFontFamily"
|
<option
|
||||||
:options="titleFontFamilyOptions"
|
v-for="option in titleFontFamilyOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="标题字体"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="title-control">
|
<label class="title-control">
|
||||||
<span>字号</span>
|
<span>字号</span>
|
||||||
<InputNumber
|
<input
|
||||||
v-model:value="titleFontSize"
|
v-model.number="titleFontSize"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
:min="8"
|
:min="8"
|
||||||
:max="72"
|
:max="72"
|
||||||
:step="1"
|
:step="1"
|
||||||
size="small"
|
|
||||||
aria-label="标题字号"
|
aria-label="标题字号"
|
||||||
|
@blur="titleFontSize = clampNumber(titleFontSize, 8, 72, 14)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="title-control">
|
<div class="title-control">
|
||||||
@@ -587,14 +665,15 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
</div>
|
</div>
|
||||||
<label class="title-control">
|
<label class="title-control">
|
||||||
<span>旋转</span>
|
<span>旋转</span>
|
||||||
<InputNumber
|
<input
|
||||||
v-model:value="titleRotation"
|
v-model.number="titleRotation"
|
||||||
|
class="native-input"
|
||||||
|
type="number"
|
||||||
:min="-180"
|
:min="-180"
|
||||||
:max="180"
|
:max="180"
|
||||||
:step="1"
|
:step="1"
|
||||||
addon-after="°"
|
|
||||||
size="small"
|
|
||||||
aria-label="标题旋转角度"
|
aria-label="标题旋转角度"
|
||||||
|
@blur="titleRotation = clampNumber(titleRotation, -180, 180, 0)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="title-control title-control--color">
|
<div class="title-control title-control--color">
|
||||||
@@ -616,21 +695,27 @@ onBeforeUnmount(() => window.removeEventListener('keydown', handleWindowKeydown)
|
|||||||
<h2>图例</h2>
|
<h2>图例</h2>
|
||||||
<label class="select-control">
|
<label class="select-control">
|
||||||
<span>位置</span>
|
<span>位置</span>
|
||||||
<Select
|
<select v-model="legendPosition" class="native-select" aria-label="图例位置">
|
||||||
v-model:value="legendPosition"
|
<option
|
||||||
:options="legendPositionOptions"
|
v-for="option in legendPositionOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="图例位置"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="select-control">
|
<label class="select-control">
|
||||||
<span>排列</span>
|
<span>排列</span>
|
||||||
<Select
|
<select v-model="legendOrientation" class="native-select" aria-label="图例排列">
|
||||||
v-model:value="legendOrientation"
|
<option
|
||||||
:options="legendOrientationOptions"
|
v-for="option in legendOrientationOptions"
|
||||||
size="small"
|
:key="option.value"
|
||||||
aria-label="图例排列"
|
:value="option.value"
|
||||||
/>
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="legend-color-control">
|
<label class="legend-color-control">
|
||||||
<span>背景</span>
|
<span>背景</span>
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ describe('WaveformChart', () => {
|
|||||||
expect(wrapper.find('.waveform-chart__label').exists()).toBe(false)
|
expect(wrapper.find('.waveform-chart__label').exists()).toBe(false)
|
||||||
expect(wrapper.find('.waveform-chart__zero-line').exists()).toBe(false)
|
expect(wrapper.find('.waveform-chart__zero-line').exists()).toBe(false)
|
||||||
expect(wrapper.find('.waveform-annotation-layer').exists()).toBe(false)
|
expect(wrapper.find('.waveform-annotation-layer').exists()).toBe(false)
|
||||||
expect(wrapper.find('.ant-pagination').exists()).toBe(false)
|
expect(wrapper.find('.waveform-chart__pagination').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('preserves every track geometry in a multi-column clean view', async () => {
|
it('preserves every track geometry in a multi-column clean view', async () => {
|
||||||
@@ -804,11 +804,11 @@ describe('WaveformChart', () => {
|
|||||||
expect(
|
expect(
|
||||||
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
|
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
|
||||||
).toEqual(['channel-0', 'channel-1'])
|
).toEqual(['channel-0', 'channel-1'])
|
||||||
const previousButton = () => wrapper.get('.ant-pagination-prev button')
|
const previousButton = () => wrapper.get('[aria-label="上一页"]')
|
||||||
const nextButton = () => wrapper.get('.ant-pagination-next button')
|
const nextButton = () => wrapper.get('[aria-label="下一页"]')
|
||||||
|
|
||||||
expect(wrapper.get('.ant-pagination-item-1').classes()).toContain('ant-pagination-item-active')
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('1')
|
||||||
expect(wrapper.get('.ant-pagination-prev').classes()).toContain('ant-pagination-disabled')
|
expect(previousButton().attributes('disabled')).toBeDefined()
|
||||||
|
|
||||||
await nextButton().trigger('click')
|
await nextButton().trigger('click')
|
||||||
expect(
|
expect(
|
||||||
@@ -817,7 +817,7 @@ describe('WaveformChart', () => {
|
|||||||
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([2, 3])
|
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([2, 3])
|
||||||
|
|
||||||
await previousButton().trigger('click')
|
await previousButton().trigger('click')
|
||||||
expect(wrapper.get('.ant-pagination-item-1').classes()).toContain('ant-pagination-item-active')
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('1')
|
||||||
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([1, 3])
|
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([1, 3])
|
||||||
|
|
||||||
await nextButton().trigger('click')
|
await nextButton().trigger('click')
|
||||||
@@ -825,8 +825,8 @@ describe('WaveformChart', () => {
|
|||||||
expect(
|
expect(
|
||||||
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
|
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
|
||||||
).toEqual(['channel-4'])
|
).toEqual(['channel-4'])
|
||||||
expect(wrapper.get('.ant-pagination-item-3').classes()).toContain('ant-pagination-item-active')
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('3')
|
||||||
expect(wrapper.get('.ant-pagination-next').classes()).toContain('ant-pagination-disabled')
|
expect(nextButton().attributes('disabled')).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('overlays series with the same track ID without changing the next frame', async () => {
|
it('overlays series with the same track ID without changing the next frame', async () => {
|
||||||
@@ -905,7 +905,7 @@ describe('WaveformChart', () => {
|
|||||||
'1',
|
'1',
|
||||||
'2',
|
'2',
|
||||||
])
|
])
|
||||||
expect(wrapper.find('.ant-pagination').exists()).toBe(false)
|
expect(wrapper.find('.waveform-chart__pagination').exists()).toBe(false)
|
||||||
|
|
||||||
const firstTrackOverlay = tracks[0].get('.waveform-chart__overlay')
|
const firstTrackOverlay = tracks[0].get('.waveform-chart__overlay')
|
||||||
const overlayWidth = Number(firstTrackOverlay.attributes('width'))
|
const overlayWidth = Number(firstTrackOverlay.attributes('width'))
|
||||||
@@ -1362,7 +1362,7 @@ describe('WaveformChart', () => {
|
|||||||
const initialMargin = wrapper.attributes('data-chart-left-margin')
|
const initialMargin = wrapper.attributes('data-chart-left-margin')
|
||||||
const initialLabelX = wrapper.get('.waveform-chart__track').attributes('data-y-axis-label-x')
|
const initialLabelX = wrapper.get('.waveform-chart__track').attributes('data-y-axis-label-x')
|
||||||
|
|
||||||
await wrapper.get('.ant-pagination-next button').trigger('click')
|
await wrapper.get('[aria-label="下一页"]').trigger('click')
|
||||||
|
|
||||||
expect(wrapper.attributes('data-chart-left-margin')).toBe(initialMargin)
|
expect(wrapper.attributes('data-chart-left-margin')).toBe(initialMargin)
|
||||||
expect(wrapper.get('.waveform-chart__track').attributes('data-y-axis-label-x')).toBe(
|
expect(wrapper.get('.waveform-chart__track').attributes('data-y-axis-label-x')).toBe(
|
||||||
@@ -1467,12 +1467,12 @@ describe('WaveformChart', () => {
|
|||||||
const wrapper = await mountSizedChart(gridSeries(5), {
|
const wrapper = await mountSizedChart(gridSeries(5), {
|
||||||
grid: { rowCount: 1, columnCount: 1 },
|
grid: { rowCount: 1, columnCount: 1 },
|
||||||
})
|
})
|
||||||
await wrapper.get('.ant-pagination-next button').trigger('click')
|
await wrapper.get('[aria-label="下一页"]').trigger('click')
|
||||||
expect(wrapper.get('.ant-pagination-item-2').classes()).toContain('ant-pagination-item-active')
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('2')
|
||||||
|
|
||||||
await wrapper.setProps({ grid: { rowCount: 2, columnCount: 1 } })
|
await wrapper.setProps({ grid: { rowCount: 2, columnCount: 1 } })
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
expect(wrapper.get('.ant-pagination-item-1').classes()).toContain('ant-pagination-item-active')
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('1')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps the shared x domain stable while paging separated and compact grids', async () => {
|
it('keeps the shared x domain stable while paging separated and compact grids', async () => {
|
||||||
@@ -1482,7 +1482,7 @@ describe('WaveformChart', () => {
|
|||||||
grid: { rowCount: 1, columnCount: 1 },
|
grid: { rowCount: 1, columnCount: 1 },
|
||||||
})
|
})
|
||||||
const initialEnd = wrapper.get('.waveform-chart__axis-endpoint--end').text()
|
const initialEnd = wrapper.get('.waveform-chart__axis-endpoint--end').text()
|
||||||
await wrapper.get('.ant-pagination-next button').trigger('click')
|
await wrapper.get('[aria-label="下一页"]').trigger('click')
|
||||||
expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe(initialEnd)
|
expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe(initialEnd)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1564,7 +1564,7 @@ describe('WaveformChart', () => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
expect(wrapper.find('[data-annotation-id="channel-2-note"]').exists()).toBe(false)
|
expect(wrapper.find('[data-annotation-id="channel-2-note"]').exists()).toBe(false)
|
||||||
await wrapper.get('.ant-pagination-next button').trigger('click')
|
await wrapper.get('[aria-label="下一页"]').trigger('click')
|
||||||
expect(wrapper.find('[data-annotation-id="channel-2-note"]').exists()).toBe(true)
|
expect(wrapper.find('[data-annotation-id="channel-2-note"]').exists()).toBe(true)
|
||||||
})
|
})
|
||||||
it('renders a path for sample data and responds to width changes', async () => {
|
it('renders a path for sample data and responds to width changes', async () => {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Pagination } from 'ant-design-vue'
|
|
||||||
import {
|
import {
|
||||||
bisector,
|
bisector,
|
||||||
pointer,
|
pointer,
|
||||||
@@ -66,7 +65,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
getGridGap,
|
getGridGap,
|
||||||
getPageCount,
|
getPageCount,
|
||||||
getPageSize,
|
|
||||||
normalizeGridOptions,
|
normalizeGridOptions,
|
||||||
paginateSeries,
|
paginateSeries,
|
||||||
resolveGridCellGeometry,
|
resolveGridCellGeometry,
|
||||||
@@ -78,6 +76,7 @@ import { buildTrackLayouts, measureTrackYAxisClearance, Y_AXIS_EXPONENT_GAP } fr
|
|||||||
import { calculateRotatedTitleLayout, TITLE_AREA_HORIZONTAL_PADDING } from './core/title'
|
import { calculateRotatedTitleLayout, TITLE_AREA_HORIZONTAL_PADDING } from './core/title'
|
||||||
import { usePreparedWaveformSeries } from './core/useWaveformData'
|
import { usePreparedWaveformSeries } from './core/useWaveformData'
|
||||||
import WaveformAnnotationEditor from './annotation/WaveformAnnotationEditor.vue'
|
import WaveformAnnotationEditor from './annotation/WaveformAnnotationEditor.vue'
|
||||||
|
import WaveformPagination from './WaveformPagination.vue'
|
||||||
import { useWaveformInstanceId } from '../utils/waveformId'
|
import { useWaveformInstanceId } from '../utils/waveformId'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
@@ -1990,15 +1989,11 @@ onBeforeUnmount(() => {
|
|||||||
</text>
|
</text>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<Pagination
|
<WaveformPagination
|
||||||
v-if="gridOptions.showPagination && pageCount > 1 && !isCleanView"
|
v-if="gridOptions.showPagination && pageCount > 1 && !isCleanView"
|
||||||
class="waveform-chart__pagination"
|
class="waveform-chart__pagination"
|
||||||
aria-label="波形分页"
|
|
||||||
:current="currentPage"
|
:current="currentPage"
|
||||||
:page-size="getPageSize(gridOptions)"
|
:page-count="pageCount"
|
||||||
:total="chartTracks.length"
|
|
||||||
:show-size-changer="false"
|
|
||||||
:show-quick-jumper="false"
|
|
||||||
@change="goToPage"
|
@change="goToPage"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -2097,17 +2092,6 @@ onBeforeUnmount(() => {
|
|||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.waveform-chart__pagination :deep(.ant-pagination-item),
|
|
||||||
.waveform-chart__pagination :deep(.ant-pagination-prev .ant-pagination-item-link),
|
|
||||||
.waveform-chart__pagination :deep(.ant-pagination-next .ant-pagination-item-link) {
|
|
||||||
background: #fff;
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.waveform-chart__pagination :deep(.ant-pagination-item-active) {
|
|
||||||
border-color: #1677ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.waveform-chart__grid-slot-placeholder {
|
.waveform-chart__grid-slot-placeholder {
|
||||||
fill: #fafbfc;
|
fill: #fafbfc;
|
||||||
stroke: #e4e7ec;
|
stroke: #e4e7ec;
|
||||||
|
|||||||
42
src/components/WaveformPagination.test.ts
Normal file
42
src/components/WaveformPagination.test.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
import WaveformPagination from './WaveformPagination.vue'
|
||||||
|
|
||||||
|
describe('WaveformPagination', () => {
|
||||||
|
it('renders all pages and disables the first-page previous button', () => {
|
||||||
|
const wrapper = mount(WaveformPagination, { props: { current: 1, pageCount: 3 } })
|
||||||
|
|
||||||
|
expect(wrapper.findAll('.waveform-pagination__page').map((page) => page.text())).toEqual([
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
])
|
||||||
|
expect(wrapper.get('[aria-label="上一页"]').attributes('disabled')).toBeDefined()
|
||||||
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses ellipses for larger page counts and emits valid page changes', async () => {
|
||||||
|
const wrapper = mount(WaveformPagination, { props: { current: 5, pageCount: 12 } })
|
||||||
|
|
||||||
|
expect(wrapper.findAll('.waveform-pagination__page').map((page) => page.text())).toEqual([
|
||||||
|
'1',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'12',
|
||||||
|
])
|
||||||
|
expect(wrapper.findAll('.waveform-pagination__ellipsis')).toHaveLength(2)
|
||||||
|
|
||||||
|
await wrapper.get('[aria-label="第 6 页"]').trigger('click')
|
||||||
|
expect(wrapper.emitted('change')).toEqual([[6]])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clamps invalid current values and does not emit when already at a boundary', async () => {
|
||||||
|
const wrapper = mount(WaveformPagination, { props: { current: 99, pageCount: 3 } })
|
||||||
|
|
||||||
|
expect(wrapper.get('[aria-current="page"]').text()).toBe('3')
|
||||||
|
await wrapper.get('[aria-label="下一页"]').trigger('click')
|
||||||
|
expect(wrapper.emitted('change')).toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
142
src/components/WaveformPagination.vue
Normal file
142
src/components/WaveformPagination.vue
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
current: number
|
||||||
|
pageCount: number
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [page: number]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
type PageToken = number | 'start-ellipsis' | 'end-ellipsis'
|
||||||
|
|
||||||
|
const normalizedPageCount = computed(() => Math.max(1, Math.floor(props.pageCount) || 1))
|
||||||
|
const normalizedCurrent = computed(() =>
|
||||||
|
Math.min(normalizedPageCount.value, Math.max(1, Math.floor(props.current) || 1)),
|
||||||
|
)
|
||||||
|
|
||||||
|
const pageTokens = computed<PageToken[]>(() => {
|
||||||
|
const pageCount = normalizedPageCount.value
|
||||||
|
const current = normalizedCurrent.value
|
||||||
|
if (pageCount <= 7) return Array.from({ length: pageCount }, (_, index) => index + 1)
|
||||||
|
if (current <= 4) return [1, 2, 3, 4, 5, 'end-ellipsis', pageCount]
|
||||||
|
if (current >= pageCount - 3) {
|
||||||
|
return [
|
||||||
|
1,
|
||||||
|
'start-ellipsis',
|
||||||
|
pageCount - 4,
|
||||||
|
pageCount - 3,
|
||||||
|
pageCount - 2,
|
||||||
|
pageCount - 1,
|
||||||
|
pageCount,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return [1, 'start-ellipsis', current - 1, current, current + 1, 'end-ellipsis', pageCount]
|
||||||
|
})
|
||||||
|
|
||||||
|
function selectPage(page: number) {
|
||||||
|
const nextPage = Math.min(normalizedPageCount.value, Math.max(1, Math.floor(page)))
|
||||||
|
if (nextPage !== normalizedCurrent.value) emit('change', nextPage)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<nav class="waveform-pagination" aria-label="波形分页">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="waveform-pagination__previous"
|
||||||
|
aria-label="上一页"
|
||||||
|
:disabled="normalizedCurrent === 1"
|
||||||
|
@click="selectPage(normalizedCurrent - 1)"
|
||||||
|
>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
<template v-for="token in pageTokens" :key="token">
|
||||||
|
<span
|
||||||
|
v-if="typeof token !== 'number'"
|
||||||
|
class="waveform-pagination__ellipsis"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
…
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
type="button"
|
||||||
|
class="waveform-pagination__page"
|
||||||
|
:class="{ 'is-active': token === normalizedCurrent }"
|
||||||
|
:aria-current="token === normalizedCurrent ? 'page' : undefined"
|
||||||
|
:aria-label="`第 ${token} 页`"
|
||||||
|
@click="selectPage(token)"
|
||||||
|
>
|
||||||
|
{{ token }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="waveform-pagination__next"
|
||||||
|
aria-label="下一页"
|
||||||
|
:disabled="normalizedCurrent === normalizedPageCount"
|
||||||
|
@click="selectPage(normalizedCurrent + 1)"
|
||||||
|
>
|
||||||
|
›
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.waveform-pagination {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 1px 2px rgb(16 24 40 / 8%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.waveform-pagination button {
|
||||||
|
display: inline-grid;
|
||||||
|
min-width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 6px;
|
||||||
|
color: #344054;
|
||||||
|
font: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waveform-pagination button:hover:not(:disabled),
|
||||||
|
.waveform-pagination button:focus-visible {
|
||||||
|
color: #0958d9;
|
||||||
|
border-color: #1677ff;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waveform-pagination button.is-active {
|
||||||
|
color: #0958d9;
|
||||||
|
background: #e6f4ff;
|
||||||
|
border-color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waveform-pagination button:disabled {
|
||||||
|
color: #bfc4cc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waveform-pagination__ellipsis {
|
||||||
|
display: inline-grid;
|
||||||
|
min-width: 20px;
|
||||||
|
height: 28px;
|
||||||
|
color: #98a2b3;
|
||||||
|
font-size: 12px;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import 'ant-design-vue/dist/reset.css'
|
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import './styles.css'
|
import './styles.css'
|
||||||
|
|||||||
134
src/styles.css
134
src/styles.css
@@ -17,6 +17,12 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
#app {
|
#app {
|
||||||
@@ -91,16 +97,124 @@ body {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control-panel .native-input,
|
||||||
|
.control-panel .native-select {
|
||||||
|
min-width: 0;
|
||||||
|
height: 28px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
color: #101828;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d0d5dd;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-input:focus-visible,
|
||||||
|
.control-panel .native-select:focus-visible,
|
||||||
|
.control-panel button:focus-visible {
|
||||||
|
border-color: #1677ff;
|
||||||
|
outline: 2px solid rgb(22 119 255 / 20%);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-switch {
|
||||||
|
position: relative;
|
||||||
|
width: 30px;
|
||||||
|
height: 18px;
|
||||||
|
margin: 0;
|
||||||
|
appearance: none;
|
||||||
|
background: #d0d5dd;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-switch::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
left: 3px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
content: '';
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 1px 2px rgb(16 24 40 / 20%);
|
||||||
|
transition: transform 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-switch:checked {
|
||||||
|
background: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-switch:checked::after {
|
||||||
|
transform: translateX(12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel .native-switch:focus-visible {
|
||||||
|
outline: 2px solid rgb(22 119 255 / 35%);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-action,
|
||||||
|
.mobile-control-toggle,
|
||||||
|
.control-panel__close {
|
||||||
|
padding: 5px 10px;
|
||||||
|
color: #344054;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d0d5dd;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-action:hover,
|
||||||
|
.mobile-control-toggle:hover,
|
||||||
|
.control-panel__close:hover {
|
||||||
|
color: #0958d9;
|
||||||
|
border-color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-action--block {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.display-mode-control {
|
.display-mode-control {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
white-space: nowrap;
|
overflow: hidden;
|
||||||
|
border: 1px solid #d0d5dd;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.display-mode-control .ant-radio-button-wrapper {
|
.display-mode-control label {
|
||||||
|
position: relative;
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
padding-inline: 7px;
|
min-width: 0;
|
||||||
|
padding: 5px 7px;
|
||||||
|
color: #475467;
|
||||||
|
font-size: 12px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-mode-control label + label {
|
||||||
|
border-left: 1px solid #d0d5dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-mode-control input {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display-mode-control input:checked + span {
|
||||||
|
color: #0958d9;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-size-control {
|
.grid-size-control {
|
||||||
@@ -112,7 +226,7 @@ body {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-size-control .ant-input-number {
|
.grid-size-control .native-input {
|
||||||
width: 58px;
|
width: 58px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +248,7 @@ body {
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-control .ant-select {
|
.select-control .native-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,12 +285,12 @@ body {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame-style-control .ant-input-number,
|
.frame-style-control .native-input,
|
||||||
.frame-style-control .ant-select {
|
.frame-style-control .native-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.frame-style-control--switch .ant-switch {
|
.frame-style-control--switch .native-switch {
|
||||||
width: auto;
|
width: auto;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
@@ -210,8 +324,8 @@ body {
|
|||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-control .ant-select,
|
.title-control .native-select,
|
||||||
.title-control .ant-input-number {
|
.title-control .native-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
const peerDependencies = ['vue', 'd3', 'ant-design-vue', 'vue3-colorpicker']
|
const peerDependencies = ['vue', 'd3', 'vue3-colorpicker']
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
|||||||
Reference in New Issue
Block a user