{"_id":"@3clear/components","_rev":"15-d271b6c64251b9412b87ed307d07e350","name":"@3clear/components","dist-tags":{"latest":"0.1.3"},"versions":{"0.0.2":{"name":"@3clear/components","version":"0.0.2","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.2","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"af47c931e86fd9deeca5e5148d5dc1c93e8838da","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.2.tgz","fileCount":37,"integrity":"sha512-KG1SDbCSiRvG6KpYA6lJ4ZB/XKJqZRcgAr9V/TvRBwRpRiw8Ro+SN+I9BmLLfNtBKLyg4uFEt5X7HcCibjQ6AA==","signatures":[{"sig":"MEQCICrM1Atg95jbB1rvs5Kw/8dOjMzJIXVQyDh/cX2+iDoYAiBCwajre6CkIEvqccM27XEsOsAkYdAuVoNKdngY1QrI0Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3777503},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./gis":"./dist/gis.js","./common":"./dist/common.js","./map-tool":"./dist/map-tool.js","./style.css":"./dist/style.css","./package.json":"./package.json"},"gitHead":"238e62b7d3df272f7cd793570ab79348f3816356","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.4","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.21.1","publishConfig":{"access":"restricted"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","pinia":"^3.0.4","moment":"^2.30.1","echarts":"^6.0.0","vue-router":"^5.0.4","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.2_1784887826234_0.397355502260484","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@3clear/components","version":"0.0.3","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.3","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"34ca73b3d5191e0b06d33e9cb008b5e31e08f264","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.3.tgz","fileCount":36,"integrity":"sha512-oMRM34PInbmjXd4AV7/xgRMLrtZSG4PqBPe8CwfM/Fs66RQs16+NoPYSNhIc019bzhKoRMxk8EJlCFoSH9k80Q==","signatures":[{"sig":"MEYCIQCbcJ4LdAQDgDgpmTNAdNRBDH544nN5QUal1qsApRQZPwIhAO33IQhaehczv4xbAy+PZ6fhl2h+3MvpYo+AoQu5eK6F","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3913832},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./map-tool":"./dist/map-tool.js","./style.css":"./dist/style.css","./package.json":"./package.json"},"gitHead":"ca614dc52fb5d6573e54a568f5ea92d8d4ba97ee","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"restricted"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","pinia":"^3.0.4","moment":"^2.30.1","echarts":"^6.0.0","vue-router":"^5.0.4","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.3_1785724019401_0.10725563833308027","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@3clear/components","version":"0.0.4","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.4","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"6d73baccb296aaa1fa981edf338ef6925eabd4b6","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.4.tgz","fileCount":41,"integrity":"sha512-go6l/GLBPm65/b/XF4NHWxzlAVyVVsZAoE587O6T4PEM2imFOlsUUfROXaYc6YL+1r4UbN6/SjshDtBCeobRiQ==","signatures":[{"sig":"MEUCIC1lXke975WeStew+xXP8a2c9H/DQLYRAOfc35klxxACAiEAxdC/+jw0ZvXPfQ3sTguQZrCP0KGgsn0c8FU0b45LEgM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":4917612},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./map-tool":"./dist/map-tool.js","./style.css":"./dist/style.css","./package.json":"./package.json"},"gitHead":"52296f25edd0747f1c5fc7c1357eef33967c3142","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"restricted"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","pinia":"^3.0.4","moment":"^2.30.1","echarts":"^6.0.0","vue-router":"^5.0.4","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.4_1785918230485_0.892409590669879","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"@3clear/components","version":"0.0.5","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.5","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"dceb406064b6e041bdc5263e52c63e5de43df478","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.5.tgz","fileCount":35,"integrity":"sha512-bWjTTqtKuxpVkZbtz6rnobIXV+/a3ivYWChzVwrIBaj4k/CKAc0eEgr9F6/RV7G6qVYNXgpS94ouNvCdp917Kg==","signatures":[{"sig":"MEQCIBRTahU7on8txnyEgqfUZMJwACx2LuJg6G7K02knU/v8AiAuwWTA5q4fBdav/fJC3GitoH8sULY1RfRnCl28khhP+g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5527197},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./map-tool":"./dist/map-tool.js","./style.css":"./dist/style.css","./package.json":"./package.json"},"gitHead":"1f69a707e7c073e4d9d131a3f9876afe47cd87a8","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"restricted"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","pinia":"^3.0.4","moment":"^2.30.1","echarts":"^6.0.0","vue-router":"^5.0.4","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.5_1786326015452_0.1880549155223432","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"@3clear/components","version":"0.0.6","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.6","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"8cf98973cba08bdd95a00cd5ccac76c991f44325","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.6.tgz","fileCount":45,"integrity":"sha512-NVTBjSqjWVPOOfDBSQ+iyhwiIeaDTTNAoQjqK92tBHMSAsiQTApYljmd43/qCLwj0bjR3GJfwEyaVkder9STCA==","signatures":[{"sig":"MEUCIFEPAKEfkhKPUwA4IgSL3DVmgcJ7Fm6pCHyLRraBfRR0AiEAnMu7XgtLKKg5rIWVXaJDL+Y7w1bx2xhBpA5VnkRIfAg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5861768},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./map-tool":"./dist/map-tool.js","./style.css":"./dist/style.css","./package.json":"./package.json"},"gitHead":"9be569d3cc518c366ceaf063de5f1cc5f6e3d89f","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"restricted"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","pinia":"^3.0.4","moment":"^2.30.1","echarts":"^6.0.0","vue-router":"^5.0.4","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.6_1786618169543_0.11658511203513866","host":"s3://npm-registry-packages-npm-production"}},"0.0.8":{"name":"@3clear/components","version":"0.0.8","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.8","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"f2d5d76fbdfbcffa3da71530e159474caad5461c","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.8.tgz","fileCount":26,"integrity":"sha512-SkyeGIFTaVjyr08cwLBlcIaLVKhZyhPqb1w8HPEfwTR1zwCTjsURYIePzwqXnQdbEurZf53agqh1BonqwHl0vw==","signatures":[{"sig":"MEUCIGv5w00D/FiQPOJIDGVIitbyIPwIUoLtmU7WPJ3XTzlsAiEAyy3APvk6FCsEJ1zS46PX4XMDmVScdpVpPwrz8iIIuns=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDAjg9ldXdofUdcSZVMYSTbHw64u/HnvhgWkF0zar8QNgIhAOnbXKBjguXlwGvecqerBEpVMw/gM3MsWZeeEoqYGtZ7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":598469},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./panel":"./dist/panel.js","./dialog":"./dist/dialog.js","./layouts":"./dist/layouts.js","./map-tool":"./dist/map-tool.js","./timeline":"./dist/timeline.js","./style.css":"./dist/style.css","./chart-data":"./dist/chart-data.js","./color-scale":"./dist/color-scale.js","./map-compare":"./dist/map-compare.js","./package.json":"./package.json","./weather-charts":"./dist/weather-charts.js","./height-selector":"./dist/height-selector.js"},"gitHead":"f66b95fa3cb98e1de933f52a0b4adbe799725aa4","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","moment":"^2.30.1","echarts":"^6.0.0","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"peerDependenciesMeta":{"moment":{"optional":true},"echarts":{"optional":true},"element-plus":{"optional":true},"@element-plus/icons-vue":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.8_1787901770993_0.16264901065346615","host":"s3://npm-registry-packages-npm-production"}},"0.0.9":{"name":"@3clear/components","version":"0.0.9","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.0.9","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"1f28f2493499597174a573a35f08e72ce58f6795","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.0.9.tgz","fileCount":28,"integrity":"sha512-K8meO//rismIV1zBOYWNPPR4RfsTtxj16qnaDvmmz+hYPEXflTKW5X6UkI6Kafyvnd0/4ffZ3OzbBwwwLnTzdA==","signatures":[{"sig":"MEUCICHU70K3oz0QhZ0F6EUHZ7IpfcolJTIbzFGoz7Rz6FIiAiEA6YWrPgOeuSzF98w6cxW6lBCpAwv/AaPpkRuqKc+7j/8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD5QxyTZNLvhlivJplkg/sToaB7eaFzM90W8wj9GDCaYgIgPlstDKARC4+qyXWoprNsbr2T5K7NQTbkwEiatjc8CZQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1499061},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./panel":"./dist/panel.js","./dialog":"./dist/dialog.js","./layouts":"./dist/layouts.js","./map-tool":"./dist/map-tool.js","./timeline":"./dist/timeline.js","./style.css":"./dist/style.css","./chart-data":"./dist/chart-data.js","./color-scale":"./dist/color-scale.js","./map-compare":"./dist/map-compare.js","./package.json":"./package.json","./weather-charts":"./dist/weather-charts.js","./height-selector":"./dist/height-selector.js","./china-region-tree.json":"./dist/china-region-tree.json"},"gitHead":"3dda4e4a28f207a3df4f7a91a9d3555df2fff82c","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","moment":"^2.30.1","echarts":"^6.0.0","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"peerDependenciesMeta":{"moment":{"optional":true},"echarts":{"optional":true},"element-plus":{"optional":true},"@element-plus/icons-vue":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/components_0.0.9_1787905910852_0.10846670776977518","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@3clear/components","version":"0.1.1","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.1.1","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"3c4a7d5fcabc4aae5115823fae19dfc7f47ce3bf","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.1.1.tgz","fileCount":33,"integrity":"sha512-mp/FIMPWciKAezeBhR20UF2gT7zIr6zLX9VjeCPjMq85zvtU2IFh9bH+JZRSgQAbORJQt6I/WGZjd6XTDdz1aQ==","signatures":[{"sig":"MEUCIC8ormTRJBn61bHK+xzLU5sQ0X7+GtonQlIKAbfyghjpAiEAkZU6TJDoSJuVH/bUB3SL2URwW469RJmneFQmly6Bnz8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIF+8Zc1agULqXGOhwfSYHMcw/Wnj7dzuKBKwCbUP+1LHAiEAwJG37supn1QTLoFa8ln+c0BvtBowwKyPvXo0cC7n968=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1600970},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./panel":"./dist/panel.js","./dialog":"./dist/dialog.js","./layouts":"./dist/layouts.js","./map-tool":"./dist/map-tool.js","./timeline":"./dist/timeline.js","./style.css":"./dist/style.css","./chart-data":"./dist/chart-data.js","./search-box":"./dist/search-box.js","./color-scale":"./dist/color-scale.js","./map-compare":"./dist/map-compare.js","./package.json":"./package.json","./weather-charts":"./dist/weather-charts.js","./height-selector":"./dist/height-selector.js","./weather-warning":"./dist/weather-warning.js","./china-region-tree.json":"./dist/china-region-tree.json"},"gitHead":"a6cdfd979338a302601ce4f8d1c7de0918131914","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","moment":"^2.30.1","echarts":"^6.0.0","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"peerDependenciesMeta":{"moment":{"optional":true},"echarts":{"optional":true},"element-plus":{"optional":true},"@element-plus/icons-vue":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/components_0.1.1_1788233241620_0.12995980192281031","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@3clear/components","version":"0.1.2","keywords":[],"author":"","license":"ISC","_id":"@3clear/components@0.1.2","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"dist":{"shasum":"a67f9e900a345cd3d088a3e8ab0b3684d59c64d4","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.1.2.tgz","fileCount":33,"integrity":"sha512-GsmYbd0/KBDEXwAIu5cCpm4cie9ZWF/J7r+vdtRX638i5VlZ+WIuMA+S+K7pGk5M0x+1P/O7ATLV2TPhKhCTKg==","signatures":[{"sig":"MEUCIQD5SX8EmliCLdcC+VChDv+YhqE5CFzxsYG0g9HlWRrIugIgWbu839Ai1II0x0hhL89LPJWRnS5POFMazDAYG//3vMU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIG49hUvZWhmZLARWJxipK6lpgwyuKp8/7jaqAc95IX6gAiBhJO/0rS2u1L3QP6M2w7eRkqeWwkQKhfogxyAAnZ5XUg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1620754},"main":"./dist/components.js","type":"module","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./panel":"./dist/panel.js","./dialog":"./dist/dialog.js","./layouts":"./dist/layouts.js","./map-tool":"./dist/map-tool.js","./timeline":"./dist/timeline.js","./style.css":"./dist/style.css","./chart-data":"./dist/chart-data.js","./search-box":"./dist/search-box.js","./color-scale":"./dist/color-scale.js","./map-compare":"./dist/map-compare.js","./package.json":"./package.json","./weather-charts":"./dist/weather-charts.js","./height-selector":"./dist/height-selector.js","./weather-warning":"./dist/weather-warning.js","./china-region-tree.json":"./dist/china-region-tree.json"},"gitHead":"a6cdfd979338a302601ce4f8d1c7de0918131914","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","moment":"^2.30.1","echarts":"^6.0.0","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"peerDependenciesMeta":{"moment":{"optional":true},"echarts":{"optional":true},"element-plus":{"optional":true},"@element-plus/icons-vue":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/components_0.1.2_1788312176776_0.8848431217705659","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"_id":"@3clear/components@0.1.3","dist":{"shasum":"91502ecab770f2b952c266fa0e244599d8c491cd","tarball":"https://registry.npmjs.org/@3clear/components/-/components-0.1.3.tgz","fileCount":33,"integrity":"sha512-j98hLfCwYQQRsnON5kyJU3aJJukh7YJSl/uN0mUxiqNmJ4wJUZd2G5JtiZd/96i0/seGGmBsSRFQI8idqvQ7rw==","signatures":[{"sig":"MEUCIBaAKGO7MqF5IxxUEmtq3WYlX86PJsI4oXuC3TdxCwzmAiEA1hBRY+pYsSs+2CbStrzSwOGnayR8qBYK4H+vsrQ3Bmg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD003E0qRN5DJsr8CO8V78dOBScuia5i9PffnLUqzUU6QIgdgeoBc/UaZWDD5wC9AzrVAKvK24BTZYi22bF6UG2eoY="}],"unpackedSize":1622932},"main":"./dist/components.js","name":"@3clear/components","type":"module","author":"","module":"./dist/components.js","exports":{".":"./dist/components.js","./air":"./dist/air.js","./panel":"./dist/panel.js","./dialog":"./dist/dialog.js","./layouts":"./dist/layouts.js","./map-tool":"./dist/map-tool.js","./timeline":"./dist/timeline.js","./style.css":"./dist/style.css","./chart-data":"./dist/chart-data.js","./search-box":"./dist/search-box.js","./color-scale":"./dist/color-scale.js","./map-compare":"./dist/map-compare.js","./package.json":"./package.json","./weather-charts":"./dist/weather-charts.js","./height-selector":"./dist/height-selector.js","./weather-warning":"./dist/weather-warning.js","./china-region-tree.json":"./dist/china-region-tree.json"},"gitHead":"e3e5caa6ee6a324efe7ad9c4c82b12492693b9e3","license":"ISC","scripts":{"build":"\"$npm_node_execpath\" ../../node_modules/vite/bin/vite.js build","pack:local":"npm pack"},"version":"0.1.3","_npmUser":{"name":"3clear","email":"qixw@3clear.com"},"keywords":[],"_npmVersion":"10.9.8","description":"3clear Vue component library for common dashboard and GIS UI components.","directories":{},"maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"sideEffects":["*.css","**/*.css"],"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"d3":"^7.9.0","sass":"^1.99.0","vite":"^6.4.2","@vitejs/plugin-vue":"^6.0.6","unplugin-auto-import":"^21.0.0"},"peerDependencies":{"vue":"^3.5.32","moment":"^2.30.1","echarts":"^6.0.0","element-plus":"^2.13.7","@element-plus/icons-vue":"^2.3.2"},"peerDependenciesMeta":{"moment":{"optional":true},"echarts":{"optional":true},"element-plus":{"optional":true},"@element-plus/icons-vue":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/components_0.1.3_1788335406075_0.21473263805747944"}}},"time":{"created":"2026-07-24T10:10:26.030Z","modified":"2026-09-02T07:50:06.383Z","0.1.0":"2026-07-08T11:32:04.164Z","0.0.1":"2026-07-08T11:51:59.926Z","0.0.2":"2026-07-24T10:10:26.410Z","0.0.3":"2026-08-03T02:26:59.579Z","0.0.4":"2026-08-05T08:23:50.680Z","0.0.5":"2026-08-10T01:40:15.645Z","0.0.6":"2026-08-13T10:49:29.729Z","0.0.8":"2026-08-28T07:22:51.082Z","0.0.9":"2026-08-28T08:31:50.980Z","0.1.1":"2026-09-01T03:27:21.726Z","0.1.2":"2026-09-02T01:22:56.868Z","0.1.3":"2026-09-02T07:50:06.180Z"},"license":"ISC","keywords":[],"description":"3clear Vue component library for common dashboard and GIS UI components.","maintainers":[{"name":"3clear","email":"qixw@3clear.com"}],"readme":"# @3clear/components\n\n`@3clear/components` 是 3clear 一张图 / 大屏项目抽出的 Vue 3 组件包，提供通用界面、布局、图表，以及气象和空气质量专题组件。\n\n当前包包含：\n\n- 交互控件：空态、弹窗、气象与空气质量站点详情、层级选择器、坐标搜索框、色标编辑器、时间轴、图例、地图工具和气象预警。\n- 菜单与布局：气象业务地图布局、大气业务地图布局、分屏对比布局、气象业务菜单和大气业务菜单。\n- 图表：通用时序图、统计图、玫瑰图及六个气象 / 环境图表。\n- 配套数据：全国省市区县树形 JSON，通过独立子路径导入。\n- `style.css`：组件基础样式、图标字体及主题变量。\n\n组件不请求业务接口；数据、业务状态和内容生命周期由页面管理。所有组件入口均不依赖 BaseGIS、Leaflet 或 axios；`MapCompare` 只做布局，不创建地图或处理地图联动。\n\n## 能力总览\n\n以下按类型展示组件能力；组合组件按一组展示，插件、兼容别名和辅助函数不单独计入卡片。点击名称可查看对应组件的说明和导入示例。\n\n示例链接对应仓库测试页，远程部署内容以实际部署版本为准。本地执行 `npm run dev` 后可访问同名路由，默认部署前缀为 `/lgmap/`；实际前缀以项目 Vite `base` 配置为准。\n\n### 交互控件（14）\n\n<table width=\"90%\">\n  <thead>\n    <tr>\n      <th width=\"18%\"><small>名称</small></th>\n      <th width=\"22%\"><small>组件名称</small></th>\n      <th width=\"45%\"><small>介绍</small></th>\n      <th width=\"15%\"><small>查看</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><small><a href=\"#empty-state\"><strong>通用空态</strong></a></small></td>\n      <td><small><code>EmptyState</code></small></td>\n      <td><small>默认空态插画和“暂无数据”，支持自定义说明、图片与操作按钮。</small></td>\n      <td><small><a href=\"#empty-state\">查看说明</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-dialog\"><strong>通用弹窗</strong></a></small></td>\n      <td><small><code>AirDialog</code></small></td>\n      <td><small>通用浅色弹窗，支持拖拽、缩小、最大化与还原。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-quality-station-detail\"><strong>空气质量站点详情</strong></a></small></td>\n      <td><small><code>AirQualityStationDetail</code></small></td>\n      <td><small>站点 AQI、污染物实况、粒度切换和趋势图。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#weather-station-dialog\"><strong>气象站点详情</strong></a></small></td>\n      <td><small><code>WeatherStationDialog</code></small></td>\n      <td><small>温湿压风实况、粒度切换、趋势图与窗口控制。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#height-selector\"><strong>高度层级选择器</strong></a></small></td>\n      <td><small><code>HeightSelector</code></small></td>\n      <td><small>选择离散气压层或高度层级。</small></td>\n      <td><small><a href=\"#height-selector\">查看说明</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#search-box\"><strong>搜索框</strong></a></small></td>\n      <td><small><code>SearchBox</code></small></td>\n      <td><small>筛选外部提供的地点树，选择时只输出标准经纬度。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-49\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#color-scale-editor\"><strong>色标编辑器</strong></a></small></td>\n      <td><small><code>ColorScaleEditor</code></small></td>\n      <td><small>编辑渐变或分段色标，支持草稿预览、校验与应用。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-45\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#timeline\"><strong>气象业务时间轴</strong></a></small></td>\n      <td><small><code>TimeLine</code></small></td>\n      <td><small>按照指定时间列表进行时次选择、步进与播放。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-time-line\"><strong>大气业务时间轴</strong></a></small></td>\n      <td><small><code>AirTimeLine</code></small></td>\n      <td><small>面向大气业务的小时级时间轴。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#time-slider\"><strong>通用时间轴</strong></a></small></td>\n      <td><small><code>TimeSlider</code></small></td>\n      <td><small>支持小时、日、月、年粒度，以及起报时间和播放控制。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-38\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#legend-ui\"><strong>通用图例</strong></a></small></td>\n      <td><small><code>LegendUI</code></small></td>\n      <td><small>支持通用色标模型和 <code>legendOpt</code> 配置。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-quality-legend\"><strong>大气业务图例</strong></a></small></td>\n      <td><small><code>AirQualityLegend</code></small></td>\n      <td><small>提供默认六级空气质量图例，也支持自定义色标。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#map-tool\"><strong>地图工具</strong></a></small></td>\n      <td><small><code>MapTool</code></small></td>\n      <td><small>提供缩放、复位、底图、引擎切换与测量操作。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#weather-warning\"><strong>气象预警</strong></a></small></td>\n      <td><small><code>WeatherWarning</code></small></td>\n      <td><small>展示四级预警样式、标题正文、区域与时间信息。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-47\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n  </tbody>\n</table>\n\n### 菜单与布局（5）\n\n<table width=\"90%\">\n  <thead>\n    <tr>\n      <th width=\"18%\"><small>名称</small></th>\n      <th width=\"22%\"><small>组件名称</small></th>\n      <th width=\"45%\"><small>介绍</small></th>\n      <th width=\"15%\"><small>查看</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><small><a href=\"#map-workbench-layout\"><strong>气象业务地图布局</strong></a></small></td>\n      <td><small><code>MapWorkbenchLayout</code></small></td>\n      <td><small>地图与悬浮面板、工具、时间轴布局。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-map-layout\"><strong>大气业务地图布局</strong></a></small></td>\n      <td><small><code>AirMapLayout</code></small></td>\n      <td><small>大气业务地图布局，支持左右面板收起。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#map-compare\"><strong>分屏对比布局</strong></a></small></td>\n      <td><small><code>MapCompare</code></small></td>\n      <td><small>自动分屏 / 自定义网格、选中与拖拽；插槽承载任意业务内容。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-36\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#panel-ui\"><strong>气象业务菜单</strong></a></small></td>\n      <td><small><code>PanelUI</code></small></td>\n      <td><small>气象业务图层与要素选择，支持分组、勾选和操作事件。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-9\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#air-source-panel\"><strong>大气业务菜单</strong></a></small></td>\n      <td><small><code>AirSourcePanel</code></small></td>\n      <td><small>大气业务图层分组、勾选、激活与分组收起。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-13\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n  </tbody>\n</table>\n\n### 图表与数据（10）\n\n<table width=\"90%\">\n  <thead>\n    <tr>\n      <th width=\"18%\"><small>名称</small></th>\n      <th width=\"22%\"><small>组件名称</small></th>\n      <th width=\"45%\"><small>介绍</small></th>\n      <th width=\"15%\"><small>查看</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><small><a href=\"#base-time-series-chart\"><strong>通用时间序列图</strong></a></small></td>\n      <td><small><code>BaseTimeSeriesChart</code></small></td>\n      <td><small>多序列时序折线 / 柱形与实况预报对比。</small></td>\n      <td><small>—</small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#base-stat-chart\"><strong>通用统计图</strong></a></small></td>\n      <td><small><code>BaseStatChart</code></small></td>\n      <td><small>柱状、环形饼图与排名条。</small></td>\n      <td><small>—</small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#wind-rose\"><strong>玫瑰图</strong></a></small></td>\n      <td><small><code>WindRose</code></small></td>\n      <td><small>已聚合风频 / 污染浓度的极坐标玫瑰图。</small></td>\n      <td><small>—</small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#sounding-chart\"><strong>探空综合图</strong></a></small></td>\n      <td><small><code>SoundingChart</code></small></td>\n      <td><small>探空综合图、风廓线与气象参数。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-24\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#temperature-humidity-profile\"><strong>温湿廓线图</strong></a></small></td>\n      <td><small><code>TemperatureHumidityProfile</code></small></td>\n      <td><small>独立温湿廓线、能量区与风羽。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-35\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#upper-air-profile\"><strong>高空大气剖面</strong></a></small></td>\n      <td><small><code>UpperAirProfile</code></small></td>\n      <td><small>时次 × 气压层的高空大气剖面。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-30\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#time-height-heatmap\"><strong>时间—高度热力图</strong></a></small></td>\n      <td><small><code>TimeHeightHeatmap</code></small></td>\n      <td><small>时间 × 高度的连续格点热力图。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-31\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#composite-wind-profile\"><strong>合成风剖面</strong></a></small></td>\n      <td><small><code>CompositeWindProfile</code></small></td>\n      <td><small>剖面路径 × 垂直层的风羽图。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-33\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#pollution-calendar\"><strong>污染日历</strong></a></small></td>\n      <td><small><code>PollutionCalendar</code></small></td>\n      <td><small>日均 AQI 与首要污染物的 PC 日历网格。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-32\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n    <tr>\n      <td><small><a href=\"#china-region-tree-usage\"><strong>全国省市区县 JSON</strong></a></small></td>\n      <td><small><code>china-region-tree.json</code>（数据）</small></td>\n      <td><small>原生 <code>el-cascader</code> 配套树形数据，支持名称搜索与任一级选择。</small></td>\n      <td><small><a href=\"http://61.50.111.214:31166/lgmap/test-page-46\" target=\"_blank\" rel=\"noopener noreferrer\">查看示例</a></small></td>\n    </tr>\n  </tbody>\n</table>\n\n### 更多图表\n\n现有组件未覆盖的图表样式和 ECharts 配置，可从以下两个社区继续查找：\n\n- [Make A Pie · ECharts 图表案例](https://www.makeapie.cn/echarts)\n- [ISQQW · ECharts 图表集](https://www.isqqw.com/)\n\n## 安装\n\n仅使用色标、层级选择器、气象预警或纯布局时，安装组件包与 Vue 即可：\n\n```bash\nnpm install @3clear/components vue\n```\n\n使用全国省市区数据并接入原生 `el-cascader` 时，安装 Vue 和 Element Plus：\n\n```bash\nnpm install @3clear/components vue element-plus\n```\n\n使用通用图表或 `AirQualityStationDetail` 时，再安装 ECharts：\n\n```bash\nnpm install @3clear/components vue echarts\n```\n\n使用根入口或全部组件时，安装完整依赖：\n\n```bash\nnpm install @3clear/components vue element-plus @element-plus/icons-vue echarts moment\n```\n\n依赖版本范围以 [package.json](./package.json) 为准。`d3` 已随构建产物发布，无需单独安装；所有入口均不要求安装 `@3clear/basegis`、Leaflet 或 axios。\n\n使用组件时统一引入组件样式；仅导入上述 JSON 数据无需此样式：\n\n```js\nimport '@3clear/components/style.css'\n```\n\n使用 Element Plus 控件时，项目还需注册控件并引入其样式。业务内容如果实际使用地图，再由页面安装地图依赖、加载资源并管理实例；布局不会代为完成。\n\n### 项目初始化\n\n`EmptyState`、`BaseDialog`、`AirDialog`、`PanelUI`、`MapTool` 和时间轴等组件使用 Element Plus 控件，项目需注册相应组件。下面采用全局注册；已有按需注册方案时可沿用。仅使用 `color-scale`、`height-selector`、`layouts`、`map-compare`、`search-box`、`weather-warning` 时，不需要 Element Plus 或这一步注册。\n\n```js\nimport { createApp } from 'vue'\nimport ElementPlus from 'element-plus'\nimport App from '@/App.vue'\nimport 'element-plus/dist/index.css'\nimport '@3clear/components/style.css'\n\nconst app = createApp(App)\napp.use(ElementPlus)\napp.mount('#app')\n```\n\n上例约定 `@` 指向项目的 `src`。文中的完整 Vue 示例显式导入所用组合式 API，不要求项目配置自动导入；仅展示模板的片段需放入已有页面并补充对应数据。\n\n## 快速开始\n\n以下完整 Vue 示例只需要组件包与 Vue，展示两个内容区域，不依赖 GIS 或 Element Plus：\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { MapCompare, MapComparePane } from '@3clear/components/map-compare'\nimport '@3clear/components/style.css'\n\nconst activePane = ref('overview')\nconst records = [\n  { name: '站点 A', value: 42 },\n  { name: '站点 B', value: 58 },\n]\n</script>\n\n<template>\n  <MapCompare v-model=\"activePane\" :height=\"420\">\n    <MapComparePane name=\"overview\" title=\"概览\">\n      <section class=\"quick-start-pane\">\n        <p>当前有 {{ records.length }} 条记录。</p>\n        <p>这里可以替换为已有的地图、图表或业务组件。</p>\n      </section>\n    </MapComparePane>\n    <MapComparePane name=\"records\" title=\"明细\">\n      <section class=\"quick-start-pane\">\n        <table>\n          <thead><tr><th>站点</th><th>数值</th></tr></thead>\n          <tbody>\n            <tr v-for=\"record in records\" :key=\"record.name\">\n              <td>{{ record.name }}</td><td>{{ record.value }}</td>\n            </tr>\n          </tbody>\n        </table>\n      </section>\n    </MapComparePane>\n  </MapCompare>\n</template>\n\n<style scoped lang=\"scss\">\n.quick-start-pane {\n  box-sizing: border-box;\n  width: 100%;\n  height: 100%;\n  padding: 16px;\n  overflow: auto;\n  color: #ebf4ff;\n}\n</style>\n```\n\n布局只提供位置和空间。地图初始化、图表数据、容器尺寸适配及销毁由各自的内容组件处理；布局编辑和自定义网格见 [MapCompare](#map-compare)。\n\n## 样式与主题\n\n组件包提供深浅两套主题变量，默认值为深色。使用 `--dt-component-*` 变量的组件，可随容器上的 `dt-component-theme-light` / `dt-component-theme-dark` 切换；地图布局等独立样式不会全部随之变化。可通过 SCSS 覆盖变量：\n\n```scss\n.business-page {\n  --dt-component-primary: #1677ff;\n  --dt-component-bg: rgba(255, 255, 255, 0.96);\n  --dt-component-text-primary: #1f2d3d;\n}\n```\n\n变量作用于继承它们的组件；默认挂到 `body` 的弹窗需在 `body` / `:root` 设置主题，或调整挂载位置。Air 专题组件保留自身浅色样式，图表绘图区还可通过各自的 `option` / `config` 配置。\n\n<a id=\"empty-state\"></a>\n\n## EmptyState\n\n### 作用\n\n`EmptyState` 基于 Element Plus `el-empty`，默认展示内置空态 SVG 和“暂无数据”。它只负责呈现，不判断数据是否为空，也不触发重新请求。\n\n### 使用方式\n\n```vue\n<script setup>\nimport { EmptyState } from '@3clear/components'\nimport '@3clear/components/style.css'\n\nfunction reload() {\n  // 由业务页面重新请求数据。\n}\n</script>\n\n<template>\n  <div style=\"height: 536px\">\n    <EmptyState>\n      <el-button type=\"primary\" @click=\"reload\">重新加载</el-button>\n    </EmptyState>\n  </div>\n</template>\n```\n\n不传默认插槽时不显示底部操作区，与设计图一致。\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `description` | 否 | `暂无数据` | 空态说明文字。 |\n| `image` | 否 | 内置空态 SVG | 自定义图片 URL。 |\n| `imageSize` | 否 | `338` | 图片宽度，单位为像素；窄容器内不会超过可用宽度。 |\n\n### 插槽\n\n| 插槽 | 说明 |\n| --- | --- |\n| `description` | 完全自定义说明内容。 |\n| `default` | 放置 `el-button` 等空态操作。 |\n\n组件没有自定义事件或公开实例方法。宿主需注册 Element Plus；当前只从 npm 根入口具名导出，没有独立子入口。\n\n仓库中的 `/test-page-50` 提供默认空态、图片尺寸与操作按钮的交互预览。\n\n<a id=\"base-dialog\"></a>\n\n## BaseDialog\n\n### 作用\n\n`BaseDialog` 用于业务弹窗。它封装了 Element Plus 的 `el-dialog`，内置标题栏窗口控制、拖动、默认底部按钮，并会把未显式声明的属性继续透传给 `el-dialog`，例如 `align-center`、`before-close` 等。\n\n### 使用方式\n\n```vue\n<template>\n  <button type=\"button\" @click=\"visible = true\">查看站点详情</button>\n  <BaseDialog\n    v-model=\"visible\"\n    title=\"站点详情\"\n    width=\"560px\"\n    @confirm=\"visible = false\"\n  >\n    <div>这里放业务内容</div>\n  </BaseDialog>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { BaseDialog } from '@3clear/components/dialog'\nimport '@3clear/components/style.css'\n\nconst visible = ref(false)\n</script>\n```\n\n自定义头部：\n\n```vue\n<BaseDialog v-model=\"visible\" title=\"详情\" destroy-on-close align-center>\n  <template #header=\"{ title, isMinimized, isMaximized, close, minimize, maximize }\">\n    <strong>{{ title }}</strong>\n    <button type=\"button\" @click=\"minimize\">{{ isMinimized ? '展开' : '缩小' }}</button>\n    <button type=\"button\" @click=\"maximize\">{{ isMaximized ? '还原' : '放大' }}</button>\n    <button type=\"button\" @click=\"close\">关闭</button>\n  </template>\n\n  内容\n</BaseDialog>\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `v-model` / `modelValue` | 是 | `false` | 控制弹窗显示隐藏。 |\n| `title` | 否 | `提示` | 弹窗标题。 |\n| `width` | 否 | `520px` | 弹窗宽度，支持字符串或数字。 |\n| `confirmText` | 否 | `确定` | 默认底部确认按钮文案。 |\n| `cancelText` | 否 | `取消` | 默认底部取消按钮文案。 |\n| `showFooter` | 否 | `true` | 是否显示默认底部按钮；存在 `footer` 插槽时也会显示底部区域。 |\n| `closeOnClickModal` | 否 | `false` | 是否允许点击遮罩关闭。 |\n| `closeOnPressEscape` | 否 | `true` | 是否允许按 Esc 关闭。 |\n| `appendToBody` | 否 | `true` | 是否插入到 `body`。 |\n| `modal` | 否 | `true` | 是否显示遮罩；缩小时会自动关闭遮罩。 |\n| `lockScroll` | 否 | `true` | 是否锁定页面滚动；缩小时会自动关闭锁定。 |\n| `destroyOnClose` | 否 | `false` | 关闭时是否销毁内容。 |\n| `showWindowControls` | 否 | `true` | 是否显示右上角窗口控制区。 |\n| `minimizable` | 否 | `true` | 是否允许缩小到底部。 |\n| `maximizable` | 否 | `true` | 是否允许最大化 / 还原。 |\n| `closable` | 否 | `true` | 是否显示关闭按钮。 |\n| `draggable` | 否 | `true` | 是否允许按住标题栏拖动，最大化时不可拖动。 |\n| 其他 `el-dialog` 属性 | 否 | - | 未声明的属性会通过 `$attrs` 透传给 `el-dialog`。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `update:modelValue(value)` | 显示状态变化。 |\n| `confirm` | 点击默认确认按钮时触发；组件不会自动关闭，需要页面按业务决定。 |\n| `cancel` | 点击默认取消按钮时触发，并尝试关闭弹窗。 |\n| `close` | 对应 `el-dialog` 的关闭事件。 |\n| `closed` | 对应 `el-dialog` 的关闭动画结束事件。 |\n| `open` | 对应 `el-dialog` 的打开事件。 |\n| `opened` | 对应 `el-dialog` 的打开动画结束事件。 |\n| `open-auto-focus` | 对应 `el-dialog` 的自动聚焦事件。 |\n| `close-auto-focus` | 对应 `el-dialog` 的关闭后自动聚焦事件。 |\n\n### 插槽\n\n| 插槽 | 说明 |\n| --- | --- |\n| `default` | 弹窗主体内容。 |\n| `header` | 自定义头部；插槽参数包含 `title`、`isMinimized`、`isMaximized`、`close`、`minimize`、`maximize`、`toggleMinimize`、`toggleMaximize`。 |\n| `footer` | 自定义底部；传入后替换默认确认 / 取消按钮。 |\n\n<a id=\"air-dialog\"></a>\n\n## AirDialog\n\n采用通用浅色样式，支持关闭、缩小、放大、还原与拖拽。Props、事件和插槽与 [BaseDialog](#base-dialog) 相同，无需重复维护两份参数表。\n\n默认确认按钮只触发 `confirm`，由页面决定是否关闭；取消按钮会尝试关闭，仍可被 `before-close` 拦截。传入 `footer` 插槽时，即使 `showFooter: false` 也会显示底部区域。\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { AirDialog, AirQualityStationDetail } from '@3clear/components/air'\n\nconst visible = ref(false)\nconst station = ref(null)\nconst trendData = ref([])\nconst granularity = ref('hour')\nconst pollutant = ref('pm25')\n</script>\n\n<template>\n  <button type=\"button\" @click=\"visible = true\">查看点位详情</button>\n  <AirDialog\n    v-model=\"visible\"\n    title=\"点位详情\"\n    width=\"480px\"\n    :show-footer=\"false\"\n    :modal=\"false\"\n  >\n    <AirQualityStationDetail\n      v-model:granularity=\"granularity\"\n      v-model:pollutant=\"pollutant\"\n      :station=\"station\"\n      :data-time=\"station?.dataTime || ''\"\n      :trend-data=\"trendData\"\n    />\n  </AirDialog>\n</template>\n```\n\n<a id=\"air-quality-station-detail\"></a>\n\n## AirQualityStationDetail\n\n用于 `AirDialog` 的空气质量站点详情内容，展示 AQI、六项污染物、气象信息和趋势图。组件不请求业务接口，站点实况与趋势数据均由页面传入。\n\n```vue\n<AirQualityStationDetail\n  v-model:granularity=\"granularity\"\n  v-model:pollutant=\"pollutant\"\n  :station=\"station\"\n  :data-time=\"dataTime\"\n  :trend-data=\"trendData\"\n  :chart-height=\"270\"\n/>\n```\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `station` | `Object` | `{}` | 当前站点实况，包含 AQI、污染物及可选气象字段。 |\n| `dataTime` | `String` | `''` | 详情中显示的监测时间。 |\n| `trendData` | `Array` | `[]` | 页面加载并传入的站点趋势序列。 |\n| `granularity` | `String` | `'hour'` | `year / month / day / hour`，支持 `v-model:granularity`。 |\n| `pollutant` | `String` | `'pm25'` | `pm25 / pm10 / o3 / no2 / so2 / co`，支持 `v-model:pollutant`。 |\n| `chartHeight` | `Number \\| String` | `270` | 趋势图高度。 |\n| `loading` | `Boolean` | `false` | 是否显示趋势数据加载状态。 |\n| `error` | `String \\| Object` | `''` | 趋势数据错误状态。 |\n\n`trendData` 每项使用 `dataTime / time / date` 之一标识时间，可带 `aqi`、六项污染物和 `isForecast / forecast / type: 'forecast'` 预报标记。`granularity` 和 `pollutant` 变化时，除对应的 `update:*` 事件外，还会触发 `granularity-change` 或 `pollutant-change`，页面可据此重新加载趋势数据。\n\n<a id=\"map-workbench-layout\"></a>\n\n## MapWorkbenchLayout\n\n气象业务地图布局，地图容器铺满底层，面板、工具区、时间轴等内容通过插槽悬浮。外层容器需有明确高度，地图 DOM 需设置满宽高。\n\n```vue\n<template>\n  <MapWorkbenchLayout>\n    <template #map>\n      <div id=\"map\" class=\"page-map\" />\n    </template>\n\n    <template #panel>\n      <PanelUI v-model=\"selectedLayers\" :sections=\"sections\" />\n    </template>\n\n    <template #topRight>\n      <MapTool :map-core=\"mapCore\" />\n    </template>\n\n    <template #bottomLeft>\n      <TimeLine @timeChange=\"loadDataByTime\" />\n    </template>\n  </MapWorkbenchLayout>\n</template>\n```\n\n插槽：\n\n| 插槽 | 必填 | 说明 |\n| --- | --- | --- |\n| `map` | 推荐 | 地图主容器，通常需要自己设置满宽高。 |\n| `panel` | 否 | 左侧面板区域。 |\n| `top` | 否 | 顶部居中区域。 |\n| `topRight` | 否 | 右上角工具区。 |\n| `right` | 否 | 右侧工具区；和 `topRight` 使用同一悬浮位置，通常二选一。 |\n| `bottomLeft` | 否 | 底部左侧区域，常放时间轴。 |\n| `bottomRight` | 否 | 底部右侧区域，常放图例或状态信息。 |\n\n<a id=\"air-map-layout\"></a>\n\n## AirMapLayout\n\n大气业务地图布局，内部提供左右面板、地图主区域、顶部浮层和底部时间轴区域。当前没有组件 Props，尺寸由组件样式和外部容器控制。\n\n插槽：\n\n| 插槽 | 必填 | 说明 |\n| --- | --- | --- |\n| `map` | 建议 | 地图容器区域，通常放 GIS 容器 DOM。 |\n| `left` | 否 | 左侧面板；传入后自动显示左侧收起按钮。 |\n| `right` | 否 | 右侧面板；传入后自动显示右侧收起按钮。 |\n| `topLeft` | 否 | 地图左上角浮层，常用于搜索框。 |\n| `topCenter` | 否 | 地图顶部居中浮层，常用于工具栏。 |\n| `mapActions` | 否 | 地图右侧操作浮层。 |\n| `timeline` | 否 | 底部时间轴区域，可同时放时间轴和图例。 |\n\n事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `change` | `payload` | 左右面板收起状态变化时触发。 |\n\n`change` 参数：\n\n```js\n{\n  panel: 'left', // left 或 right\n  leftCollapsed: false,\n  rightCollapsed: false,\n}\n```\n\n<a id=\"map-compare\"></a>\n\n## MapCompare\n\n`MapCompare + MapComparePane` 是只依赖 Vue 的分屏布局，组合方式类似 `Tabs + TabPane`。它只负责面板排列、选中、拖拽和尺寸调整，不判断插槽内容的类型，不创建地图、图表或表格实例。\n\n### 组件关系与用法选择\n\n`MapCompare` 内部使用 `SplitMapCompareLayout`，`MapComparePane` 内部使用 `SplitMapPanel`，共用同一套网格、拖拽和尺寸调整实现。\n\n常规使用 `MapCompare + MapComparePane`：组件自动注册面板、生成布局并管理选中状态，也支持通过 `v-model:layout` 自定义位置。需要自行维护面板标识、完整网格位置和选中状态时，可以直接使用[底层网格组件](#split-map-compare-layout)。\n\n### 使用示例\n\n下面的示例只放普通内容，不需要 GIS 或 Element Plus：\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { MapCompare, MapComparePane } from '@3clear/components/map-compare'\nimport '@3clear/components/style.css'\n\nconst compareRef = ref(null)\nconst activePane = ref('overview')\nconst editable = ref(false)\nconst rows = [\n  { city: '北京', value: 42 },\n  { city: '上海', value: 58 },\n]\n</script>\n\n<template>\n  <label><input v-model=\"editable\" type=\"checkbox\" /> 编辑布局</label>\n  <button type=\"button\" @click=\"compareRef?.resetLayout()\">恢复布局</button>\n  <MapCompare ref=\"compareRef\" v-model=\"activePane\" :editable=\"editable\" height=\"420px\">\n    <MapComparePane name=\"overview\" title=\"业务概览\">\n      <section class=\"pane-content\">\n        <h3>这里放你的业务组件</h3>\n        <p>地图、图表等内容由业务组件自己初始化、更新和销毁。</p>\n      </section>\n    </MapComparePane>\n    <MapComparePane name=\"data\" title=\"数据\">\n      <template #header=\"{ active }\">\n        <strong>普通表格{{ active ? ' · 已选中' : '' }}</strong>\n      </template>\n      <table class=\"pane-content\">\n        <thead><tr><th>城市</th><th>示例数值</th></tr></thead>\n        <tbody><tr v-for=\"row in rows\" :key=\"row.city\"><td>{{ row.city }}</td><td>{{ row.value }}</td></tr></tbody>\n      </table>\n    </MapComparePane>\n  </MapCompare>\n</template>\n\n<style scoped lang=\"scss\">\n.pane-content {\n  box-sizing: border-box;\n  width: 100%;\n  padding: 16px;\n  color: #ebf4ff;\n}\n</style>\n```\n\n组件为 1～5 屏提供预设布局，更多 Pane 使用普通网格。动态增删 Pane 时只更新布局和选中状态；插槽中业务组件的挂载与卸载遵循 Vue 生命周期。拖拽只改变面板位置和尺寸，不重新创建内容。面板 `name` 需唯一且非空；可通过稳定的 `key` 保持内容身份。\n\n[第 36 页](http://61.50.111.214:31166/lgmap/test-page-36) 展示地图、统计图、站点摘要与普通内容混排。地图由该页面自己的 `DemoMap` 创建、销毁和响应容器尺寸变化，联动由页面使用 `MapViewLinkController` 实现；这些逻辑不在组件包中。\n\n`MapCompare` Props：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue / v-model` | `String` | `''` | 当前选中面板名称；未传时自动选中第一个有效子项。 |\n| `height` | `String / Number` | `480` | 组件高度；数字按 px 处理，也可传 `100%`、`60vh`。 |\n| `layout / v-model:layout` | `Object` | `undefined` | `name -> {x,y,width,height}`；不传时按 Pane 数量自动排列。 |\n| `columns` / `rows` | `Number` | `12` | 网格列数和行数。 |\n| `gap` | `Number` | `4` | 面板间距，单位 px。 |\n| `editable` | `Boolean` | `false` | 是否允许拖动标题、通过右下角手柄调整尺寸。 |\n\n`MapCompare` 事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `name` | 更新当前选中面板，用于 `v-model`。 |\n| `change` | `{name}` | 选中面板变化；不包含业务实例。 |\n| `update:layout` | `layout` | 更新布局，用于 `v-model:layout`。 |\n| `layout-change` | `{panelId,placement,layout}` 或重置时 `{reason:'reset',layout}` | 面板位置、尺寸或整体布局变化。 |\n| `interaction-end` | `{panelId,type,placement}` | 一次拖动或缩放结束。 |\n\n父组件提供 `default` 插槽放置 Pane，`empty` 插槽显示无有效面板的占位内容。实例只暴露 `getLayout()`、`resetLayout()`、`setActive(name)`，分别用于读取布局、恢复自动排列和选中面板。\n\n`MapComparePane` Props：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `name` | `String` | 必填 | 唯一、非空的面板名称。 |\n| `title` | `String` | `''` | 默认标题；不传时显示 `name`。 |\n\nPane 插槽：\n\n| 插槽 | 参数 | 用途 |\n| --- | --- | --- |\n| `header` | `{name,active,placement}` | 自定义面板标题或工具。 |\n| `default` | `{name,active,placement}` | 面板主体，直接放任意组件或 HTML；不再是地图覆盖层。 |\n\nPane 不提供业务生命周期事件或实例方法。内容默认占据标题下方的区域；需要铺满时由业务组件自行设置 `width: 100%; height: 100%`，需要滚动时由内容自行设置 `overflow`。地图或图表可在自己的组件中通过 `ResizeObserver` 处理容器尺寸变化，也可由页面监听布局事件后调整；布局不调用它们的 API。\n\n**从旧的自动建图用法迁移：**\n\n- 保留 `MapCompare`、`MapComparePane` 与 `MapCompareItem` 名称；`MapCompareItem` 仍是 Pane 别名。\n- 移除父组件的 `linked`、`realtime`、`linkMode`、`linkStrategy`，以及 Pane 的 `engine`、`mapOptions`、`options`、`linkGroup`、`linkEnabled`。\n- 原 `ready` / `error` / `before-destroy` / `map-*` 事件，以及 `getMap()`、`getMaps()`、`getActiveMap()`、`getState()`、`sync()`、`resize()`、`zoomIn()`、`zoomOut()` 已移除。请在自己的业务内容组件中创建、保存和清理实例；需要联动时由页面调用对应能力。\n- `change` 现在只返回 `{name}`，插槽不再提供地图实例、加载或错误状态。自定义这些状态时，直接放到内容组件里。\n\n<a id=\"split-map-compare-layout\"></a>\n\n### 底层网格组件：SplitMapCompareLayout + SplitMapPanel\n\n`SplitMapCompareLayout` 负责网格位置、拖拽和尺寸调整，`SplitMapPanel` 承载每屏内容。直接使用这一层时，页面提供 `layout`，并通过 `active-panel-id` 和 `panel-activate` 管理选中状态；不会自动按面板数量排列。两个组件都不判断内容类型、不管理业务实例。\n\n下面仅演示网格布局；地图容器的初始化、数据加载和销毁由页面自行实现。可监听 `interaction-end` 调用对应地图的 `resize()`。\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { SplitMapCompareLayout, SplitMapPanel } from '@3clear/components/layouts'\n\nconst layout = ref({\n  'map-a': { x: 1, y: 1, width: 6, height: 12 },\n  'map-b': { x: 7, y: 1, width: 6, height: 12 },\n})\nconst activePanelId = ref('map-a')\n</script>\n\n<template>\n  <SplitMapCompareLayout\n    v-model:layout=\"layout\"\n    class=\"compare-layout\"\n    editable\n    :active-panel-id=\"activePanelId\"\n    @panel-activate=\"activePanelId = $event\"\n  >\n    <SplitMapPanel panel-id=\"map-a\">\n      <template #header><strong>屏幕 1</strong></template>\n      <div id=\"map-a-container\" class=\"map-container\" />\n    </SplitMapPanel>\n\n    <SplitMapPanel panel-id=\"map-b\">\n      <template #header><strong>屏幕 2</strong></template>\n      <div id=\"map-b-container\" class=\"map-container\" />\n    </SplitMapPanel>\n  </SplitMapCompareLayout>\n</template>\n\n<style scoped lang=\"scss\">\n.compare-layout {\n  height: 600px;\n}\n\n.map-container {\n  width: 100%;\n  height: 100%;\n}\n</style>\n```\n\n默认网格是 `12 × 12`，可通过 `columns`、`rows` 修改。上面的双屏布局中，每个面板占 6 列、12 行。\n\n布局项的数据结构：\n\n| 字段 | 类型 | 说明 |\n| --- | --- | --- |\n| `x` | `Number` | 起始列，从 1 开始。 |\n| `y` | `Number` | 起始行，从 1 开始。 |\n| `width` | `Number` | 占用列数。 |\n| `height` | `Number` | 占用行数。 |\n\n`SplitMapCompareLayout` Props：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `layout` | `Object` | `{}` | `panelId -> {x,y,width,height}` 的布局映射。 |\n| `columns` | `Number` | `12` | 网格列数，默认横向 12 格。 |\n| `rows` | `Number` | `12` | 网格行数，默认纵向 12 格。 |\n| `gap` | `Number` | `4` | 面板间距，单位 px。 |\n| `editable` | `Boolean` | `false` | 开启后可拖动标题改变位置，并拖动右下角改变尺寸。 |\n| `activePanelId` | `String` | `''` | 当前主面板，用于高亮和层级控制。 |\n\n事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:layout` | `layout` | 配合 `v-model:layout` 更新布局。 |\n| `layout-change` | `{panelId,placement,layout}` | 拖动或缩放过程中的实时布局。 |\n| `panel-activate` | `panelId` | 用户按下某个面板时触发。 |\n| `interaction-end` | `{panelId,type,placement}` | 移动或缩放完成，建议在此刷新地图尺寸。 |\n\n`SplitMapCompareLayout` 插槽：\n\n| 插槽 | 参数 | 说明 |\n| --- | --- | --- |\n| `default` | 无 | 放置一个或多个 `SplitMapPanel`。 |\n| `empty` | 无 | 未传默认插槽时的占位内容。 |\n\n`SplitMapPanel` Props：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `panelId` | `String` | 必填 | 面板唯一 id，必须与 `layout` 中的 key 一致。 |\n| `title` | `String` | `''` | 未传 `header` 插槽时显示的标题。 |\n\n`SplitMapPanel` 插槽：\n\n| 插槽 | 参数 | 说明 |\n| --- | --- | --- |\n| `header` | `{panelId,placement}` | 当前屏幕的标题、模式和时次控制区。 |\n| `default` | `{panelId,placement}` | 当前屏幕内容，通常放地图容器或业务地图组件。 |\n\n<a id=\"panel-ui\"></a>\n\n## PanelUI\n\n### 作用\n\n`PanelUI` 是气象业务地图常用的图层 / 要素选择菜单。它只负责展示、选择和事件透出；具体图层开关、接口请求、地图渲染应由页面根据事件处理。\n\n### 使用方式\n\n```vue\n<template>\n  <PanelUI\n    v-model=\"selectedLayers\"\n    :filterable=\"true\"\n    title=\"图层面板\"\n    subtitle=\"选择需要展示的图层\"\n    :sections=\"sections\"\n    :footer-actions=\"footerActions\"\n    @change=\"onLayerChange\"\n    @action=\"onPanelAction\"\n  />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { PanelUI } from '@3clear/components/panel'\n\nconst selectedLayers = ref(['surface-station'])\nconst sections = [\n  {\n    id: 'weather',\n    title: '气象实况',\n    titleMode: 'major',\n    columns: 2,\n    items: [\n      { value: 'surface-station', label: '地面站' },\n      { value: 'radar', label: '雷达', badge: '新' },\n    ],\n  },\n  {\n    id: 'satellite',\n    title: '卫星',\n    selectionMode: 'single',\n    items: [\n      { value: 'fy2', label: 'FY-2' },\n      { value: 'fy4', label: 'FY-4' },\n    ],\n  },\n]\nconst footerActions = [\n  { key: 'clear', label: '清空', type: 'warning' },\n]\n\nfunction onLayerChange(value, payload) {\n  console.log('选中值', value, payload)\n}\n\nfunction onPanelAction(action) {\n  console.log('底部动作', action)\n}\n</script>\n```\n\n`filterable` 是布尔属性，默认 `false`。使用 `:filterable=\"true\"` 显示顶部要素筛选框，`:filterable=\"false\"` 隐藏；关闭后恢复完整列表，已选值保持不变。第 9 页通过 `:filterable=\"panelConfig.filterable\"` 控制显隐，`panelConfig.filterable` 默认 `true`。\n\n输入去除首尾空白后，按实际显示名称（`item.label || item.name || item.value`）进行忽略大小写的包含匹配，不匹配分组标题。没有匹配项时显示“没有匹配的要素”，清空输入恢复展示。\n\n筛选本身只改变显示，不请求接口、不修改已选值，也不触发 `change` 或地图联动。点击选项仍按原规则选择，分组单选仍以完整分组为范围，不受筛选隐藏项影响。\n\n<a id=\"panel-ui-plugin\"></a>\n\n### PanelUIPlugin 全局注册\n\n```js\nimport { createApp } from 'vue'\nimport { PanelUIPlugin } from '@3clear/components/panel'\nimport App from '@/App.vue'\n\nconst app = createApp(App)\napp.use(PanelUIPlugin)\n\n// 如需自定义注册名，将上一行替换为：\n// app.use(PanelUIPlugin, { name: 'GisPanel' })\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `v-model` / `modelValue` | 否 | `[]` | 当前选中值。多选通常为数组，单选可为字符串或数字。 |\n| `sections` | 否 | `[]` | 分组配置；不传或为空时使用内置示例分组。 |\n| `filterable` | 否 | `false` | `Boolean`；是否显示顶部要素名称筛选框，仅过滤展示。 |\n| `title` | 否 | `''` | 面板标题；为空时显示默认标题 `图层面板`。 |\n| `subtitle` | 否 | `''` | 面板副标题。 |\n| `visible` | 否 | `true` | 是否显示面板。 |\n| `collapsed` | 否 | `false` | 是否收起面板内容。 |\n| `collapsible` | 否 | `true` | 是否显示收起 / 展开按钮。 |\n| `showHeader` | 否 | `true` | 是否显示头部。 |\n| `closable` | 否 | `false` | 是否显示关闭按钮。 |\n| `disabled` | 否 | `false` | 是否禁用选项选择和筛选输入。 |\n| `multiple` | 否 | `true` | 默认选择模式是否多选。 |\n| `clearable` | 否 | `true` | 单选时是否允许再次点击已选项清空。 |\n| `showActiveCount` | 否 | `true` | 是否显示选中数量。 |\n| `footerActions` | 否 | `[]` | 底部按钮配置。 |\n| `backgroundColor` | 否 | `''` | 面板背景色；不传时使用 `--dt-component-bg`。 |\n| `checkedIcon` | 否 | `''` | 选中状态默认图标 URL。 |\n| `uncheckedIcon` | 否 | `''` | 未选中状态默认图标 URL。 |\n| `emptyText` | 否 | `''` | 无分组时的空状态文案。 |\n\n### `sections` 配置\n\n| 字段 | 必填 | 说明 |\n| --- | --- | --- |\n| `id` | 否 | 分组唯一标识；不传时用标题或索引兜底。 |\n| `title` | 否 | 分组标题。 |\n| `description` | 否 | 分组标题旁的简短说明。 |\n| `hidden` | 否 | 是否隐藏当前分组。 |\n| `titleMode` | 否 | `major` 使用主标题样式，其他值使用次级标题样式。 |\n| `major` | 否 | 兼容字段；为 `true` 时默认按主标题样式显示。 |\n| `columns` | 否 | 每行列数，默认 `2`。 |\n| `multiple` | 否 | 当前分组是否多选。 |\n| `selectionMode` | 否 | 可选 `single`、`radio`、`multiple`、`checkbox`。 |\n| `items` | 是 | 当前分组选项数组。 |\n\n分组选项常用字段：\n\n| 字段 | 说明 |\n| --- | --- |\n| `value` | 选中值，优先级最高。 |\n| `id` | 备用选中值。 |\n| `label` | 显示文案，优先级最高。 |\n| `name` | 备用显示文案。 |\n| `hidden` | 是否隐藏当前项。 |\n| `disabled` | 是否禁用当前项。 |\n| `icon` / `uncheckedIcon` | 未选中图标 URL。 |\n| `activeIcon` / `checkedIcon` | 选中图标 URL。 |\n| `badge` | 右侧标签文案。 |\n\n`footerActions` 按钮字段：\n\n| 字段 | 说明 |\n| --- | --- |\n| `key` | 唯一标识。 |\n| `label` | 按钮文案。 |\n| `type` | Element Plus 按钮类型，默认 `primary`。 |\n| `plain` | 是否朴素按钮；默认按 `true` 处理，显式传 `false` 可关闭。 |\n| `disabled` | 是否禁用按钮。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `update:modelValue(value)` | 选中值变化。 |\n| `change(value, payload)` | 选中值变化，包含 `item`、`section`、`multiple`、`selected`、`selectedValues` 等上下文。 |\n| `item-click(item, section, payload)` | 点击某个可用选项时触发。 |\n| `update:collapsed(value)` | 收起状态变化。 |\n| `close` | 点击关闭按钮时触发。 |\n| `action(action)` | 点击底部动作按钮时触发。 |\n\n### 插槽\n\n| 插槽 | 说明 |\n| --- | --- |\n| `default` | 追加在面板内容区和底部动作之前，适合放少量自定义内容。 |\n\n<a id=\"air-source-panel\"></a>\n\n## AirSourcePanel\n\n大气业务图层菜单，支持图层分组、勾选、点击激活和分组收起。\n\n`filterable` 默认 `false`；`:filterable=\"true\"` 显示顶部名称筛选框，`:filterable=\"false\"` 隐藏。第 13 页通过 `:filterable=\"panelConfig.filterable\"` 控制，`panelConfig.filterable` 默认 `true`。筛选词去除首尾空白后，按 `item.label` 忽略大小写做包含匹配，不匹配分组标题；无匹配时显示“没有匹配的要素”。\n\n筛选词非空时临时展开匹配分组，期间不能手动折叠；清空或关闭筛选框后恢复完整列表及先前的折叠状态。输入、清空和隐藏只影响显示，不改变勾选 `modelValue` 或激活 `activeValue`，不触发 `change`、`item-click`、`section-toggle`，也不请求接口或操作地图；点击选项仍按原规则选择。\n\n参数：\n\n| 参数 | 类型 | 默认值 | 必填 | 说明 |\n| --- | --- | --- | --- | --- |\n| `modelValue` | `Array` | `[]` | 否 | 当前勾选值，配合 `v-model` 使用。 |\n| `activeValue` | `String/Number` | `''` | 否 | 当前激活值，配合 `v-model:active-value` 使用。 |\n| `sections` | `Array` | `[]` | 否 | 图层分组数据；为空时使用内置空气质量分组。 |\n| `filterable` | `Boolean` | `false` | 否 | 是否显示顶部名称筛选框，仅过滤展示；关闭时恢复列表与折叠状态。 |\n| `defaultCollapsedSections` | `Array` | `[]` | 否 | 初始收起的分组 id，只在初始化时生效。 |\n\n`sections` 数据：\n\n```js\n[\n  {\n    id: 'station',       // 可选，分组唯一值\n    title: '环境空气',    // 分组标题\n    iconText: '环',      // 可选，分组圆形图标文字\n    items: [\n      {\n        label: '国控站',       // 展示文字\n        value: 'national',    // 业务值\n        title: '国控站',       // 可选，悬浮提示\n        checked: true,        // 可选，初始勾选\n        active: true,         // 可选，初始激活\n        disabled: false,      // 可选，是否禁用\n      },\n    ],\n  },\n]\n```\n\n事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `Array` | 勾选值变化，用于 `v-model`。 |\n| `update:activeValue` | `String/Number` | 激活值变化，用于 `v-model:active-value`。 |\n| `change` | `payload` | 勾选或点击图层按钮时触发。 |\n| `item-click` | `payload` | 点击图层按钮时触发；仅点复选框不会触发。 |\n| `section-toggle` | `payload` | 用户手动展开或收起分组时触发；名称筛选的临时展开不触发。 |\n\n`change` 参数：\n\n```js\n{\n  value: ['national', 'micro'],\n  item: { label: '微站', value: 'micro' },\n  section: { id: 'station', title: '环境空气' },\n  selected: true,\n  source: 'button', // button 或 checkbox\n  canceledButtonValue: '',\n}\n```\n\n<a id=\"height-selector\"></a>\n\n## HeightSelector\n\n### 作用\n\n`HeightSelector` 负责离散层级的展示和选择。层级按照索引等分，适合 100、150、200、250、300、400、500、700、850、925、1000 这类间隔不规则的气压值。\n\n### 推荐用法\n\n```vue\n<template>\n  <HeightSelector\n    v-model=\"pressure\"\n    :levels=\"pressureLevels\"\n    @change=\"loadPressureLayer\"\n  />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { HeightSelector } from '@3clear/components/height-selector'\nimport '@3clear/components/style.css'\n\nconst pressure = ref(1000)\nconst pressureLevels = [100, 150, 200, 250, 300, 400, 500, 700, 850, 925, 1000]\n\nfunction loadPressureLayer(value) {\n  console.log('加载气压层', value)\n}\n</script>\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `v-model` / `modelValue` | 否 | `null` | 当前选中层级，支持 `number` 和 `string`。 |\n| `levels` | 否 | `[100, 150, 200, 250, 300, 400, 500, 700, 850, 925, 1000]` | 层级数组；自动去重并按数值从小到大排列。 |\n| `heightOpt` | 否 | - | `levels` 的兼容别名，传入后优先于 `levels`。 |\n| `defaultValue` | 否 | `1000` | 未传 `v-model` 时的默认层级；不存在时回退到最后一项。 |\n| `title` | 否 | `气压` | 标题。 |\n| `unit` | 否 | `hPa` | 标题中的单位；传空字符串可隐藏单位。 |\n| `width` | 否 | `110` | 组件宽度，数字按 px 处理，也支持 CSS 尺寸字符串。 |\n| `trackHeight` | 否 | `400` | 轨道高度，数字按 px 处理，也支持 CSS 尺寸字符串。 |\n| `disabled` | 否 | `false` | 是否禁用交互。 |\n| `ariaLabel` | 否 | `''` | 无障碍名称；为空时使用标题和单位。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `update:modelValue(value)` | 选中层级变化时触发，用于 `v-model`。 |\n| `change(value)` | 点击、拖动或键盘操作完成后触发。 |\n| `updateHeight(value)` | 兼容事件，与 `change` 同步触发。 |\n\n键盘聚焦组件后，可使用 `↑`、`↓` 切换相邻层级，使用 `Home`、`End` 跳到顶部或底部层级。\n\n<a id=\"search-box\"></a>\n\n## SearchBox\n\n纯 Vue 坐标搜索框。候选数据由外部传入，组件不请求地点接口、不加载行政区 JSON，也不接收地图实例。树形节点会转换成只读搜索索引；同名项以完整路径显示。\n\n```vue\n<script setup>\nimport { SearchBox } from '@3clear/components/search-box'\nimport chinaRegionTree from '@3clear/components/china-region-tree.json'\nimport '@3clear/components/style.css'\n\nfunction handleCoordinate({ longitude, latitude }) {\n  // 页面或布局组合层决定如何操作自己的地图。\n  mapCore.setInitialView({ center: [longitude, latitude], zoom: 8 })\n}\n</script>\n\n<template>\n  <SearchBox :options=\"chinaRegionTree\" @select=\"handleCoordinate\" />\n</template>\n```\n\nProps：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `options` | `Array` | `[]` | 树形或平铺候选项；读取 `label / name`、`longitude / lng`、`latitude / lat`、`children`。 |\n| `placeholder` | `String` | `搜索地点` | 输入框占位文字。 |\n| `disabled` | `Boolean` | `false` | 禁用输入和候选选择。 |\n| `maxResults` | `Number` | `10` | 最多显示的匹配结果数。 |\n\n事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `select` | `{ longitude, latitude }` | 选择有效结果时触发；不包含原始节点、地图实例、引擎或视角参数。 |\n\n搜索同时匹配完整名称路径和 `adcode / value`，空关键词不会展开全部候选项。行政区数据中的坐标只是区域代表点，不是地址或 POI 地理编码结果。第 49 页展示“`SearchBox` → 页面布局组合层 → `BaseGIS`”的真实调用链；详细边界见 [源码文档](../../src/components/SearchBox/README.md)。\n\n<a id=\"color-scale-editor\"></a>\n\n## ColorScaleEditor\n\n编辑“数值 → 颜色”的映射，支持连续渐变、连续分段、均分显示、增删行、HEX 调色、标签、反转颜色和取色预览。组件可以独立使用；编辑过程只修改内部草稿，点击“应用”并校验通过后才输出完整配置。\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { ColorBar, ColorScaleEditor, createDefaultColorScale } from '@3clear/components/color-scale'\nimport '@3clear/components/style.css'\n\nconst colorScale = ref(createDefaultColorScale())\n\nfunction handleApply(data) {\n  colorScale.value = data\n}\n</script>\n\n<template>\n  <ColorScaleEditor :model-value=\"colorScale\" @apply=\"handleApply\" />\n  <ColorBar :color-scale=\"colorScale\" />\n</template>\n```\n\n只需回填时，也可使用 `<ColorScaleEditor v-model=\"colorScale\" />`，仍然只在有效应用后更新。`AirQualityLegend`、`ColorBar` 和 `LegendUI` 都可直接接收同一配置，无需拆分颜色和文字数组。\n\n### 参数与事件\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` / `v-model` | `Object` | `createDefaultColorScale()` | 最近载入或应用的配置，结构见下文。 |\n| `disabled` | `Boolean` | `false` | 禁用编辑和操作按钮。 |\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `data` | 应用有效色标时输出完整配置，用于 `v-model`。 |\n| `apply` | `data` | 与输入结构相同的完整配置，没有额外包装层。 |\n| `cancel` | 无 | 恢复最近载入 / 已应用的配置，不输出新配置。 |\n\n`update:modelValue` 与 `apply` 分别返回独立对象，不共享输入对象或内部草稿。恢复初始配置不触发应用事件；外部更新 `modelValue` 会重置草稿。组件不负责接口请求、文件导入导出或持久化。\n\n### 配置模型\n\n输入、应用输出、色条和取色函数统一使用 `{ name, unit, mode, equalSpacing, items }`。每行固定为 `{ value, min, max, color, label }`，未使用的数值字段保留 `null`。\n\n| 字段 | 连续渐变 `continuous` | 分段着色 `discrete` |\n| --- | --- | --- |\n| `name` / `unit` | 字符串，可为空。 | 字符串，可为空。 |\n| `items` | 至少两个节点，`value` 严格递增。 | 至少一段；每段 `min < max`，前段 `max` 等于后段 `min`。 |\n| `items[].value` | 有限数字。 | `null`。 |\n| `items[].min` / `max` | `null`。 | 有限数字，不允许区间重叠或空隙。 |\n| `items[].color` | 六位 HEX，如 `#2563EB`。 | 六位 HEX，如 `#2563EB`。 |\n| `items[].label` | 必须为字符串，可为空。 | 必须为字符串，可为空；空标签由色条显示区间文字。 |\n| `equalSpacing` | `true` 时节点等距，否则按数值跨度。 | `true` 时分段等长，否则按区间跨度。 |\n\n`equalSpacing` 可省略，默认 `false`，应用输出会补齐。它只改变显示位置，不改变阈值和取色结果。配置数值不接受数字字符串，颜色不接受三位 HEX 或透明度，也不接受 `stops` / `segments` 模型。\n\n分段示例（自定义演示阈值，不代表业务分级标准）：\n\n```json\n{\n  \"name\": \"浓度\",\n  \"unit\": \"μg/m³\",\n  \"mode\": \"discrete\",\n  \"equalSpacing\": true,\n  \"items\": [\n    { \"value\": null, \"min\": 0, \"max\": 20, \"color\": \"#22C55E\", \"label\": \"低\" },\n    { \"value\": null, \"min\": 20, \"max\": 100, \"color\": \"#EF4444\", \"label\": \"高\" }\n  ]\n}\n```\n\n连续节点示例：`{ value: 20, min: null, max: null, color: '#22C55E', label: '' }`；按 `value` 升序提供至少两项。\n\n### 辅助函数\n\n| 函数 | 说明 |\n| --- | --- |\n| `createDefaultColorScale(mode = 'continuous')` | 创建独立示例配置；模式可为 `continuous` / `discrete`，默认不均分。 |\n| `getColorScaleColor(value, scale)` | 连续模式在相邻节点间插值，分段模式返回区间色；不修改配置。 |\n\n分段区间左闭右开，最后一段包含最大值；上例的 `20` 和 `100` 都使用第二段颜色。超出范围时取首色 / 尾色。缺测、非有限取样值或非法配置返回 `'transparent'`；取样值允许有限数字字符串，`0` 是有效值。\n\n仓库 `/test-page-45` 展示独立编辑器，应用回调打印完整配置；色条联动参照上例，保存由页面自行实现。\n\n<a id=\"timeline\"></a>\n\n## TimeLine\n\n### 作用\n\n`TimeLine` 用于展示时间轴，支持上一点、下一点、播放、停止、按页翻动、日期选择和指定时间列表。\n\n### 使用方式\n\n```vue\n<template>\n  <TimeLine\n    :now-date=\"currentTime\"\n    :time-list=\"timeList\"\n    :auto-trigger=\"false\"\n    unit=\"hour\"\n    @timeChange=\"onTimeChange\"\n  />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { TimeLine } from '@3clear/components/timeline'\n\nconst currentTime = ref('2025-10-29 12:00:00')\nconst timeList = [\n  '2025-10-29 08:00:00',\n  '2025-10-29 11:00:00',\n  '2025-10-29 14:00:00',\n]\n\nfunction onTimeChange(time) {\n  currentTime.value = time\n}\n</script>\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `nowDate` | 否 | 当前整点 | 当前激活时间，支持 `Date` 或字符串。 |\n| `timeList` | 否 | `[]` | 指定可选时间列表；有值时按列表跳转，并自动对齐到最近时间。 |\n| `autoTrigger` | 否 | `true` | 是否在初始化时自动触发 `timeChange`；不屏蔽点击、播放等交互事件。 |\n| `time_int` | 否 | `2000` | 播放间隔，单位毫秒。 |\n| `step` | 否 | `1` | 时间步长。 |\n| `unit` | 否 | `hour` | 时间单位，可用 `hour`、`minute`、`second`。 |\n| `lineStep` | 否 | `12` | 当前屏展示多少个时间点。 |\n| `dateLabelFormat` | 否 | `MM/DD` | 日期标签格式，使用 `moment` 格式。 |\n| `timeLabelFormat` | 否 | `''` | 自定义时间标签格式；为空时按 `unit` 自动选择格式。 |\n| `dateTimeShow` | 否 | `true` | 是否显示日期选择器。 |\n| `isForecast` | 否 | `false` | 是否显示起报小时选择。 |\n| `bgcColor` | 否 | `''` | 时间轴背景色。 |\n| `fontColor` | 否 | `white` | 文字颜色。 |\n| `activeShowLocation` | 否 | `before` | 激活点在列表中的显示策略；`before` 表示从激活点开始向后展示，其他值表示让激活点尽量靠后。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `timeChange(time)` | 当前时间变化，时间字符串格式由 `unit` / `timeList` 决定。 |\n\n<a id=\"air-time-line\"></a>\n\n## AirTimeLine\n\n小时时间轴，统一输出 `YYYY-MM-DD HH:00:00` 格式，支持前后切换和自动播放，固定展示选中日期前后各两天。\n\n参数：\n\n| 参数 | 类型 | 默认值 | 必填 | 说明 |\n| --- | --- | --- | --- | --- |\n| `fontColor` | `String` | `'#6E7580'` | 否 | 日期选择器文字颜色。 |\n| `dateTimeShow` | `Boolean` | `true` | 否 | 是否显示日期选择器。 |\n| `time_int` | `Number` | `2000` | 否 | 自动播放间隔，单位毫秒。 |\n| `timeLineDate` | `String/Date` | `''` | 否 | 当前时间，建议配合 `v-model:time-line-date`。 |\n| `lastTime` | `String/Date` | `''` | 否 | 最新数据时间。 |\n| `refreshTime` | `String/Date` | `''` | 否 | 外部刷新值，变化后同步时间轴并触发 `refresh`。 |\n\n事件：\n\n| 事件 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:timeLineDate` | `String` | 当前时间变化。 |\n| `timeChange` | `String` | 用户切换时间或播放推进时触发。 |\n| `change` | `String` | 与 `timeChange` 同步触发。 |\n| `refresh` | `String` | `refreshTime` 变化或调用 `refresh()` 时触发。 |\n\n通过组件 `ref` 暴露的方法：\n\n| 方法 | 参数 | 说明 |\n| --- | --- | --- |\n| `refresh` | `String/Date` | 同步时间并重建时间轴，会触发 `refresh`。 |\n| `initialFun` | `String/Date` | 重建时间轴，不主动触发业务时间变化。 |\n| `playFun` | 无 | 开始自动播放。 |\n| `stopPlay` | 无 | 停止自动播放。 |\n| `previousFun` | 无 | 向前一小时。 |\n| `nextFun` | 无 | 向后一小时。 |\n\n使用示例：\n\n```vue\n<AirTimeLine\n  ref=\"timelineRef\"\n  v-model:time-line-date=\"currentTime\"\n  :last-time=\"latestTime\"\n  :time_int=\"3000\"\n  @timeChange=\"loadData\"\n  @refresh=\"handleRefresh\"\n/>\n```\n\n<a id=\"time-slider\"></a>\n\n## TimeSlider\n\n### 作用\n\n`TimeSlider` 是支持小时、日、月、年粒度，带开始日期、进度色、步进和自动播放的公共时间轴。组件使用 `v-model` 管理当前时次，不依赖 Cesium、Leaflet 或业务接口。\n\n### 使用方式\n\n```vue\n<template>\n  <TimeSlider\n    v-model=\"currentTime\"\n    v-model:forecast-time=\"forecastTime\"\n    :start-date=\"startDate\"\n    :is-forecast=\"isForecast\"\n    :date-length=\"5\"\n    :unit=\"unit\"\n    @change=\"loadData\"\n    @forecast-time-change=\"loadForecastData\"\n  />\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { TimeSlider } from '@3clear/components/timeline'\n\nconst currentTime = ref(new Date())\nconst forecastTime = ref(new Date())\nconst startDate = ref(new Date())\nconst isForecast = ref(true)\nconst unit = ref('hour')\n\nfunction loadData(time, detail) {\n  console.log('当前时次', time, detail.source)\n}\n\nfunction loadForecastData(time, detail) {\n  console.log('起报时间', time, detail.source)\n}\n</script>\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | 否 | 当前时间，按 `unit` 对齐 | 当前选择时间，支持 `Date`、字符串或时间戳。 |\n| `startDate` | 否 | 当前日期 | 时间范围的开始日期。 |\n| `maxStartDate` | 否 | 当前日期 | 允许选择的最大开始日期；传 `null` 不限制。 |\n| `isForecast` | 否 | `false` | 是否在开始时间前显示起报时间选择。 |\n| `forecastTime` | 否 | 当前时间，按 `unit` 对齐 | 起报时间，支持 `Date`、字符串或时间戳；选择器会随 `unit` 切换为小时、日、月或年粒度。 |\n| `dateLength` | 否 | `7` | 兼容范围配置：小时模式代表天数，其他模式代表当前粒度数量。 |\n| `unit` | 否 | `hour` | 时间粒度，可用 `hour`、`day`、`month`、`year`。 |\n| `rangeLength` | 否 | `0` | 当前粒度的范围数量；大于 `0` 时优先于 `dateLength`。小时模式未传时按 `dateLength × 24` 计算。 |\n| `hourStep` | 否 | `3` | 宽度足够时的小时刻度间隔。 |\n| `minVisibleDays` | 否 | `5` | 小时模式下响应式布局至少显示的日期数，不超过配置范围。 |\n| `hourNodeMinWidth` | 否 | `16` | 小时模式下估算可见范围的刻度参考宽度，单位 px。 |\n| `playInterval` | 否 | `800` | 自动播放间隔，单位毫秒。 |\n| `unlimitedPrevious` | 否 | `true` | 是否允许向开始日期以前步进。 |\n| `visualDatePosition` | 否 | `start` | `start` / `end`，初始显示窗口靠范围开始端或结束端。 |\n| `stepOptions` | 否 | `[{ label: '1h', hours: 1 }]` | 小时模式只读取 `hours === 1` 项的按钮文案；不用于配置多种步长。 |\n| `startLabel` | 否 | `开始时间` | 左侧日期区域标题。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `update:modelValue(time)` | `v-model` 当前时间更新。 |\n| `change(time, detail)` | 当前时间变化；`detail.source` 表示操作来源，切换粒度时为 `unit-change`。 |\n| `play-change(playing)` | 播放状态变化。 |\n| `start-date-change(date)` | 开始日期变化。 |\n| `update:forecastTime(time)` | `v-model:forecast-time` 起报时间更新。 |\n| `forecast-time-change(time, detail)` | 起报时间变化；`detail.source` 为 `select` 或 `unit-change`。 |\n\n时间事件输出 `Date` 对象。`change` 的 `detail.source` 可为 `select`、`step`、`play`、`current`、`start-date` 或 `unit-change`。切换 `unit` 会同时对齐当前时间和起报时间；起报选择器在小时模式显示日期与小时，在日 / 月 / 年模式分别只选择日期、月份或年份。\n\n日 / 月 / 年模式可设置 `:range-length=\"12\"` 等范围数量。例如 `unit=\"month\" :range-length=\"12\"` 表示 12 个月，每次按钮操作推进一个月；`startDate` 会对齐到所在月第一天。\n\n### 暴露方法\n\n| 方法 | 说明 |\n| --- | --- |\n| `play()` | 切换播放 / 暂停状态，再次调用会暂停。 |\n| `stop()` | 停止播放。 |\n| `goCurrentTime()` | 停止播放并回到按当前粒度对齐的系统时间。 |\n| `step(amount)` | 按当前 `unit` 步进，如 `step(-1)`、`step(1)`。 |\n\n自动播放每次推进一个当前粒度，到达当前可见窗口末尾后从窗口首项循环；不是自动遍历整个配置范围。组件没有插槽。\n\n<a id=\"legend-ui\"></a>\n\n## LegendUI\n\n### 作用\n\n`LegendUI` 用于展示图例，支持连续渐变色带和分类色带。\n\n传入 `<LegendUI :color-scale=\"colorScale\" />` 时，使用 [ColorBar](#color-bar) 的显示规则，并支持 `direction=\"vertical\"`。`colorScale` 优先于 `legendOpt`；不传时使用下面的 `legendOpt` 配置。\n\n### 使用方式\n\n```vue\n<template>\n  <LegendUI :legend-opt=\"legendOpt\" />\n</template>\n\n<script setup>\nimport { LegendUI } from '@3clear/components/color-scale'\n\nconst legendOpt = {\n  label: ['低', '中', '高'],\n  color: ['#0080ff', '#00ffc8', '#f7b42d', '#d0240e'],\n  unit: '℃',\n  legendType: 'classify',\n}\n</script>\n```\n\n连续渐变色带：\n\n```js\nconst legendOpt = {\n  label: [0, 10, 20, 30],\n  color: ['#0080ff', '#00ffc8', '#f7b42d', '#d0240e'],\n  unit: 'mm',\n  legendType: 'gradient',\n}\n```\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `colorScale` | 否 | `null` | 新色标配置；传入时优先于 `legendOpt`，模板使用 `:color-scale`。 |\n| `direction` | 否 | `'horizontal'` | 传入 `colorScale` 时生效，可为 `horizontal` / `vertical`；旧 `legendOpt` 展示不变。 |\n| `legendOpt` | 否 | 内置温度图例 | 图例配置对象。 |\n| `legendOpt.label` | 否 | `[-68, -48, -28, -8, 11, 31, 51]` | 刻度或分类文案。 |\n| `legendOpt.color` | 否 | 内置颜色数组 | 色带颜色数组。 |\n| `legendOpt.unit` | 否 | `℃` | 单位；有值时显示在“图例”标题后。 |\n| `legendOpt.legendType` | 否 | `classify` | `classify` 为分类色带；其他值按连续渐变处理。 |\n\n<a id=\"air-quality-legend\"></a>\n\n## AirQualityLegend\n\n不传 `colorScale` 时保留原固定六级空气质量图例：优、良、轻度、中度、重度、严重。传入配置后直接展示配置的颜色与文字：\n\n```vue\n<AirQualityLegend />\n<AirQualityLegend :color-scale=\"colorScale\" />\n```\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `colorScale` | `Object` | `null` | [色标配置模型](#color-scale-editor)；不传时显示固定六级图例。 |\n| `direction` | `String` | `'horizontal'` | `horizontal` / `vertical`，仅传入 `colorScale` 时生效。 |\n\n组件保留浅色外观；传入配置后的显示规则与 [ColorBar](#color-bar) 一致，无效配置显示空态。没有事件或插槽。\n\n<a id=\"color-bar\"></a>\n\n## ColorBar\n\n通用紧凑色条，直接接收 `ColorScaleEditor` 配置。`equalSpacing` 缺省为 `false`，按数值跨度显示；设为 `true` 时连续节点等距、分段等长。横向分段颜色下方为居中标签，空标签显示 `min–max`；横竖方向都遵循均分设置。\n\n```vue\n<ColorBar :color-scale=\"colorScale\" />\n<ColorBar :color-scale=\"colorScale\" direction=\"vertical\" />\n```\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `colorScale` | `Object` | `null` | 连续 / 分段模型；无效配置显示“暂无有效色标”。 |\n| `direction` | `String` | `'horizontal'` | `horizontal` / `vertical`。 |\n\n默认宽 210px、横向色条高 5px、文字行高 42px，可用 CSS 覆盖宽度。配置结构和均分规则见 [ColorScaleEditor](#color-scale-editor)；`name` / `unit` 用于悬停及无障碍信息，不额外绘制标题行。组件遵循通用主题，没有事件或插槽。\n\n<a id=\"map-tool\"></a>\n\n## MapTool\n\n### 作用\n\n`MapTool` 是基于 `BaseGIS` 的地图工具条，支持放大、缩小、复位、Cesium / Leaflet 切换、底图切换、距离测量、面积测量和切面入口。需要传入已初始化的 `BaseGIS`，不要直接传原生 Leaflet / Cesium 实例。\n\n### 使用方式\n\n下面将地图实例作为属性传入工具条封装；地图的初始化和销毁由持有实例的页面负责。\n\n```vue\n<script setup>\nimport { MapTool } from '@3clear/components/map-tool'\n\ndefineProps({\n  mapCore: { type: Object, required: true },\n})\n\nconst selectedArea = {\n  startLon: 100,\n  startLat: 30,\n  endLon: 110,\n  endLat: 40,\n}\n</script>\n\n<template>\n  <MapTool\n    :map-core=\"mapCore\"\n    :selected-area=\"selectedArea\"\n    @change-scene-mode=\"payload => console.log(payload)\"\n  />\n</template>\n```\n\n`MapTool` 会调用 `BaseGIS.setEngine()` 自动切换引擎。图片、网格、海量点、点位抽稀、等值线和三维体等 BaseGIS 托管图层会自动恢复，页面不需要传 `reloadOnSwitch`，也不需要重新请求接口。\n\n只有风场、剖面、一次性绘制对象或页面直接创建的 Cesium / Leaflet 对象需要使用 `reloadOnSwitch`：\n\n```vue\n<MapTool\n  :map-core=\"mapCore\"\n  :reload-on-switch=\"reloadLayers\"\n  @change-scene-mode=\"onSceneModeChange\"\n/>\n```\n\n`reloadLayers({ engineType, sceneMode, mapCore })` 由页面实现，只恢复非托管的自定义资源；可返回 Promise。\n\n### 参数\n\n| 参数 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `mapCore` | 推荐 | `null` | `BaseGIS` 实例。缩放、复位、底图、测量、切面等优先使用它。 |\n| `selectedArea` | 否 | `{}` | 复位到指定范围时使用，字段为 `startLon`、`startLat`、`endLon`、`endLat`。 |\n| `reloadOnSwitch` | 否 | `null` | 切换成功且托管图层恢复后执行；仅用于恢复非托管的自定义资源。 |\n| `mapView` | 否 | `{}` | 兼容旧地图对象，优先级低于 `mapCore`。 |\n| `tools` | 否 | 默认工具数组 | 工具按钮配置，按数组顺序显示；支持字符串，也支持带 `key` / `type` / `name` 的对象。 |\n\n默认工具：\n\n```js\n['zoom-in', 'zoom-out', 'reset-view', 'scene-mode', 'basemap', 'measure']\n```\n\n支持的工具 key：\n\n| key | 说明 |\n| --- | --- |\n| `zoom-in` | 放大。 |\n| `zoom-out` | 缩小。 |\n| `reset-view` | 复位视角；有 `selectedArea` 时优先飞到指定范围。 |\n| `scene-mode` | Cesium 3D / Leaflet 2D 切换。 |\n| `basemap` | 底图下拉切换，内置矢量、地形、影像、纯净底图。 |\n| `measure` | 测量下拉，支持距离测量、面积测量、清除。 |\n| `section` | 切面入口，支持自定义绘制和自定义坐标。 |\n\n说明：重复工具会自动去重，不支持的 key 会被忽略。\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `handleZoomInOut(flag)` | 放大 / 缩小时触发，`flag` 为 `in` 或 `out`。 |\n| `changeBasemap(payload)` | 底图切换成功时触发，`payload` 包含 `type` 和 `basemapId`。 |\n| `changeSceneMode(payload)` | 2D / 3D 切换成功时触发，`payload` 包含 `engineType` 和 `sceneMode`。 |\n| `changeMeasure(type)` | 测量类型变化时触发，`0` 清除，`1` 测距，`2` 测面。 |\n| `drawLine(location)` | 切面线绘制入口触发；自定义坐标时会带经纬度和 `showCut`。 |\n\n<a id=\"use-map-tool\"></a>\n\n### `useMapTool`\n\n`useMapTool` 是 `MapTool` 内部逻辑的组合式封装，适合需要自定义工具条外观、但复用同一套地图操作逻辑的场景。\n\n```js\nimport { useMapTool } from '@3clear/components/map-tool'\n\nconst {\n  visibleTools,\n  toolWrapperStyle,\n  zoomInOut,\n  handleResize,\n  handleSwitch,\n  handleCommand,\n  handleMeasure,\n  handleDissect,\n} = useMapTool(props, emit)\n```\n\n常用返回值：\n\n| 返回值 | 说明 |\n| --- | --- |\n| `visibleTools` | 规范化后的可见工具 key。 |\n| `toolWrapperStyle` | 根据工具数量生成的容器宽度和栅格列样式。 |\n| `zoomInOut(flag)` | 执行放大或缩小。 |\n| `handleResize(area)` | 执行复位视角。 |\n| `handleSwitch()` | 切换 Cesium / Leaflet。 |\n| `handleCommand(type)` | 切换底图。 |\n| `handleMeasure(type)` | 开启距离 / 面积测量或清除测量。 |\n| `handleDissect(type)` | 处理切面入口。 |\n| `form` / `rules` / `ruleFormRef` | 自定义坐标切面表单状态。 |\n\n<a id=\"base-time-series-chart\"></a>\n\n## BaseTimeSeriesChart\n\n通用时间序列图只约定“序列 + 时间点”，不内置实况、预报或污染物字段。推荐每个点使用 `{ time, value }`；`value: null` 表示有时次但曲线在此处断开。\n\n```vue\n<script setup>\nimport { BaseTimeSeriesChart } from '@3clear/components/chart-data'\n\nconst series = [\n  {\n    name: '实况',\n    data: [\n      { time: '2026-08-25 08:00', value: 42 },\n      { time: '2026-08-25 09:00', value: 46 },\n    ],\n  },\n  {\n    name: '预报',\n    data: [\n      { time: '2026-08-25 09:00', value: 45 },\n      { time: '2026-08-25 10:00', value: 51 },\n    ],\n    lineStyle: { type: 'dashed' },\n  },\n]\n</script>\n\n<template>\n  <BaseTimeSeriesChart\n    title=\"PM₂.₅ 浓度时序\"\n    :series=\"series\"\n    unit=\"μg/m³\"\n    :show-data-zoom=\"true\"\n    @point-click=\"payload => console.log(payload)\"\n  />\n</template>\n```\n\n主要 Props：\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `series` | `Array` | `[]` | `{name,data,color?,type?,smooth?,lineStyle?,area?,unit?}`；`data` 推荐 `{time,value}`。 |\n| `xAxisType` | `time \\| category` | `time` | 时间轴或离散分类轴。 |\n| `xAxisName` / `yAxisName` | `String` | `''` | 坐标轴名称。 |\n| `unit` | `String` | `''` | 公共数值单位；单条序列的 `unit` 可覆盖它。 |\n| `showLegend` | `Boolean` | `true` | 是否显示图例。 |\n| `showDataZoom` | `Boolean` | `false` | 是否显示横向缩放条并启用滚轮缩放。 |\n| `connectNulls` | `Boolean` | `false` | 是否连接空值两侧的线段。 |\n\n共享的状态、事件、插槽和实例方法见[通用图表公共 API](#chart-common-api)。\n\n<a id=\"base-stat-chart\"></a>\n\n## BaseStatChart\n\n统计图使用单指标数据 `{ name, value, color? }`。`bar` 保持输入顺序，`rank-bar` 自动按数值降序，`pie` 使用环形饼图。\n\n```vue\n<script setup>\nimport { BaseStatChart } from '@3clear/components/chart-data'\n</script>\n\n<template>\n  <BaseStatChart\n    type=\"rank-bar\"\n    :data=\"[\n      { name: '北京', value: 72 },\n      { name: '天津', value: 61 },\n      { name: '济南', value: 54 },\n    ]\"\n    series-name=\"PM₂.₅\"\n    unit=\"μg/m³\"\n    @point-click=\"payload => console.log(payload)\"\n  />\n</template>\n```\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `type` | `bar \\| pie \\| rank-bar` | `bar` | 统计图类型。 |\n| `data` | `Array` | `[]` | 默认读取 `{name,value,color?}`。 |\n| `nameKey` / `valueKey` | `String \\| Function` | `name` / `value` | 读取字段；函数签名为 `(record,index)`。 |\n| `seriesName` | `String` | `数值` | Tooltip 中的指标名称。 |\n| `unit` | `String` | `''` | 数值单位。 |\n| `limit` | `Number` | `0` | 大于 0 时只展示前 N 项；排名图在排序后截取。 |\n| `showLabel` / `showLegend` | `Boolean` | `true` | 控制数值标签；`showLegend` 仅用于饼图图例。 |\n\n共享的状态、事件、插槽和实例方法见[通用图表公共 API](#chart-common-api)。\n\n<a id=\"wind-rose\"></a>\n\n## WindRose\n\n`WindRose` 只渲染聚合结果，不在组件内部猜测风速分箱或污染统计口径。`directions` 从北向开始顺时针排列，每条 `series.data` 按相同下标对应方位；不足的项补空值，超出的项忽略。\n\n```vue\n<script setup>\nimport { WindRose } from '@3clear/components/chart-data'\n</script>\n\n<template>\n  <WindRose\n    :directions=\"['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']\"\n    :series=\"[\n      { name: '0～2 m/s', data: [2, 3, 4, 2, 1, 2, 4, 3] },\n      { name: '2～4 m/s', data: [4, 5, 8, 4, 3, 3, 7, 5] },\n    ]\"\n    unit=\"%\"\n    :stacked=\"true\"\n  />\n</template>\n```\n\n污染玫瑰通常传一个浓度序列并设置 `:stacked=\"false\"`。组件使用极坐标柱形。\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `directions` | `Array` | 16 方位 | 北向起始、顺时针方向标签。 |\n| `series` | `Array` | `[]` | `{name,data,color?,itemStyle?,label?}`，数据按方位下标对应。 |\n| `unit` | `String` | `%` | 径向轴和 Tooltip 单位。 |\n| `stacked` | `Boolean` | `true` | 是否堆叠柱形序列。 |\n| `max` | `Number` | 自动 | 径向轴最大值。 |\n| `startAngle` / `clockwise` | `Number` / `Boolean` | `90` / `true` | 方位起始角和排列方向。 |\n| `showLabel` / `showLegend` | `Boolean` | `false` / `true` | 是否显示柱值标签和序列图例。 |\n| `colors` | `Array` | 内置色板 | 没有在单条序列指定 `color` 时使用的颜色序列。 |\n\n`WindRose` 管理一组极坐标；`option.polar`、`option.angleAxis` 或 `option.radiusAxis` 使用数组时只读取并深合并第 0 项。\n\n共享的状态、事件、插槽和实例方法见[通用图表公共 API](#chart-common-api)。\n\n<a id=\"chart-common-api\"></a>\n\n## 通用图表公共 API\n\n`BaseTimeSeriesChart`、`BaseStatChart` 和 `WindRose` 共享以下能力：\n\n| 分类 | API | 说明 |\n| --- | --- | --- |\n| Props | `title`、`subtitle`、`height`、`loading`、`loadingText`、`error`、`emptyText`、`autoresize`、`renderer`、`theme`、`initOptions`、`colors`、`option` | `option` 用于覆盖布局和样式；结构化数据 Props 始终负责 series data。 |\n| Events | `ready`、`point-click`、`point-hover`、`point-leave`、`legend-change`；时间序列图另有 `datazoom` | 点事件返回标准字段、原始 `source` 和 ECharts `params`。 |\n| Slots | `header`、`loading`、`error`、`empty`、`footer` | 替换标题、状态或底部扩展区。 |\n| Exposes | `redraw`、`resize`、`setOption`、`getOption`、`getChartInstance`、`dispatchAction`、`getDataURL` | 命令式高级能力；常规更新优先修改 Props。 |\n\n`BaseTimeSeriesChart` 和 `BaseStatChart` 的默认高度为 `360px`，`WindRose` 为 `420px`。`ready` 返回 ECharts 实例；点事件的主要字段如下，均附带原始 `source` 和 ECharts `params`：\n\n| 组件 | 点事件字段 |\n| --- | --- |\n| `BaseTimeSeriesChart` | `time`、`value`、`seriesName`、`seriesIndex`、`dataIndex`。 |\n| `BaseStatChart` | `name`、`value`、`dataIndex`、`sourceIndex`（输入数组中的原始下标）。 |\n| `WindRose` | `direction`、`value`、`seriesName`、`seriesIndex`、`directionIndex`。 |\n\n时间序列图和玫瑰图的 `option.series` 可按 `id`、`name` 或下标补充样式；统计图只读取 `option.series[0]`。其中的 `data`、`name` 和 `type` 不会覆盖组件的结构化数据。\n\n<a id=\"sounding-chart\"></a>\n\n## SoundingChart\n\n### 作用\n\n`SoundingChart` 用于展示单站探空廓线。主图为 Skew-T 对数气压图，包含温度、露点、气块轨迹、CAPE / CIN 填色、风羽和悬浮提示；右侧可显示风廓线图及 CAPE、CIN、LCL、LFC 等参数。\n\n组件只负责数据归一化、参数计算和绘图，不请求接口。`profile` 或 `config` 变化后会自动重绘，页面通常不需要手动调用 `redraw()`。\n\n### 使用方式\n\n```vue\n<template>\n  <div class=\"sounding-page\">\n    <SoundingChart\n      ref=\"chartRef\"\n      :profile=\"profile\"\n      :indices=\"indices\"\n      :config=\"chartConfig\"\n    />\n  </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { SoundingChart } from '@3clear/components/weather-charts'\nimport '@3clear/components/style.css'\n\nconst chartRef = ref(null)\n\n// 每项表示一个气压层。推荐按气压从高到低传入，组件计算参数时也会按该顺序整理。\nconst profile = ref([\n  { press: 1000, height: 110, temp: 26, dew: 20, wd: 160, ws: 4 },\n  { press: 925, height: 760, temp: 20, dew: 16, wd: 180, ws: 7 },\n  { press: 850, height: 1450, temp: 15, dew: 10, wd: 200, ws: 10 },\n  { press: 700, height: 3100, temp: 4, dew: -2, wd: 230, ws: 15 },\n  { press: 500, height: 5700, temp: -10, dew: -22, wd: 250, ws: 22 },\n  { press: 300, height: 9200, temp: -35, dew: -48, wd: 270, ws: 30 },\n  { press: 200, height: 11800, temp: -52, dew: -62, wd: 285, ws: 38 },\n])\n\n// preferProvidedIndices 为 true 时，后端指数会覆盖组件根据 profile 计算出的同名指数。\nconst indices = ref({\n  SBCAPE: { value: 1280 },\n  SBCIN: { value: -42 },\n  LCL: { value: 860 },\n  LFC: { value: 1420 },\n  EL: { value: 11200 },\n  H0: { value: 4380 },\n  convectiveTemperature: { value: 31.5 },\n})\n\nconst chartConfig = ref({\n  skewTWidth: 600,\n  skewTHeight: 470,\n  showHodograph: true,\n  showParameters: true,\n  showTooltip: true,\n  showLegend: true,\n  preferProvidedIndices: true,\n  colors: {\n    temperature: '#3c47a8',\n    dewPoint: '#218829',\n    parcel: '#f71e00',\n  },\n})\n\n// profile 和 config 是响应式数据，赋新值或修改数组内容后组件会自动更新。\nfunction updateProfile(nextProfile, nextIndices = {}) {\n  profile.value = nextProfile\n  indices.value = nextIndices\n}\n\n// 容器尺寸或外部布局变化但数据未变化时，可以按需手动重绘。\nfunction redrawChart() {\n  chartRef.value?.redraw()\n}\n</script>\n\n<style scoped lang=\"scss\">\n.sounding-page {\n  width: 100%;\n  overflow: auto;\n}\n</style>\n```\n\n### 参数\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- | --- |\n| `profile` | `Array<ProfileItem>` | 是 | `[]` | 探空垂直廓线。空数组时显示空状态。 |\n| `indices` | `Object` | 否 | `{}` | 外部计算的气象指数；只有 `preferProvidedIndices: true` 时用于覆盖组件计算值。 |\n| `config` | `Object` | 否 | `{}` | 尺寸、显隐、范围、颜色和参数列表配置。 |\n\n### `profile` 数据\n\n| 标准字段 | 可用别名 | 类型 | 单位 | 说明 |\n| --- | --- | --- | --- | --- |\n| `press` | 无 | `number \\| string` | hPa | 气压。该字段必须能转换成有限数字，否则整层数据会被忽略。 |\n| `height` | `geopHigh` | `number \\| string` | m | 位势高度。参数计算需要该字段。 |\n| `temp` | `airTemp` | `number \\| string` | ℃ | 气温。 |\n| `dew` | `dewTemp` | `number \\| string` | ℃ | 露点温度。 |\n| `wd` | `windDir` | `number \\| string` | ° | 风向，气象角度。 |\n| `ws` | `windSpd` | `number \\| string` | m/s | 风速。 |\n\n数值字符串会自动转换成数字。`null`、`undefined`、空字符串和 `-999` 会按缺测值处理。绘制温湿廓线至少需要 `press`、`temp`、`dew`；计算右侧参数还需要 `height`；绘制风羽和风廓线需要 `wd`、`ws`。\n\n接口字段别名可以直接使用，例如：\n\n```js\nconst profile = [\n  {\n    press: '1000',\n    geopHigh: '110',\n    airTemp: '26.0',\n    dewTemp: '20.0',\n    windDir: '160',\n    windSpd: '4.0',\n  },\n]\n```\n\n### `indices` 数据\n\n支持的键为 `SBCAPE`、`SBCIN`、`LCL`、`LFC`、`EL`、`H0`、`convectiveTemperature`。每个值既可以直接传数字，也可以传 `{ value }`：\n\n```js\nconst indices = {\n  SBCAPE: 1280,\n  SBCIN: { value: -42 },\n  LCL: 860,\n}\n```\n\n`-999`、`null`、`undefined` 会被忽略，对应位置继续使用组件计算值。组件不会转换单位，外部指数应使用参数列表中约定的单位：CAPE / CIN 为 `J/kg`，高度为 `m`，对流温度为 `℃`。\n\n### `config` 配置\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `skewTWidth` | `number` | `600` | Skew-T 主图宽度，单位 px。 |\n| `skewTHeight` | `number` | `470` | Skew-T 主图高度，单位 px。 |\n| `hodographWidth` | `number` | `350` | 风廓线图宽度，单位 px。 |\n| `hodographHeight` | `number` | `260` | 风廓线图高度，单位 px。 |\n| `sideWidth` | `number` | `400` | 右侧风廓线和参数区域宽度，单位 px。 |\n| `maxWindSpeed` | `number` | `45` | 风廓线图横纵坐标的最大风速，单位 m/s。 |\n| `temperatureRange` | `[number, number]` | `[-80, 40]` | 主图温度范围，依次为最小值、最大值，单位 ℃。 |\n| `pressureRange` | `[number, number]` | `[1050, 100]` | 主图气压范围，依次为底部最大气压、顶部最小气压，单位 hPa。 |\n| `showHodograph` | `boolean` | `true` | 是否显示右侧风廓线图。 |\n| `showParameters` | `boolean` | `true` | 是否显示右侧参数列表。 |\n| `showTooltip` | `boolean` | `true` | 是否显示温湿曲线数据点的悬浮提示。 |\n| `showLegend` | `boolean` | `true` | 是否显示主图图例。 |\n| `preferProvidedIndices` | `boolean` | `false` | 是否优先使用 `indices` 中的外部指数。 |\n| `emptyText` | `string` | `暂无探空数据` | `profile` 为空时的提示文案。 |\n| `colors` | `Object` | 见下表 | 业务曲线及能量区域颜色。 |\n| `parameterItems` | `Array<ParameterItem>` | 内置 7 项 | 右侧参数的显示项、顺序、文案和单位；传入数组后会整体替换默认列表。 |\n\n`colors` 可配置项：\n\n| 字段 | 默认值 | 说明 |\n| --- | --- | --- |\n| `temperature` | `#3c47a8` | 温度曲线颜色。 |\n| `dewPoint` | `#218829` | 露点曲线颜色。 |\n| `parcel` | `#f71e00` | 气块轨迹颜色。 |\n| `cape` | `rgba(239, 68, 68, 0.22)` | CAPE 区域填充色。 |\n| `cin` | `rgba(59, 130, 246, 0.2)` | CIN 区域填充色。 |\n\n`parameterItems` 每项包含 `key`、`label`、`unit`。可用 `key` 为 `sbcape`、`sbcin`、`lcl`、`lfc`、`el`、`h0`、`convectiveTemperature`：\n\n```js\nconst chartConfig = {\n  parameterItems: [\n    { key: 'sbcape', label: 'CAPE', unit: 'J/kg' },\n    { key: 'lcl', label: '抬升凝结高度', unit: 'm' },\n    { key: 'convectiveTemperature', label: '对流温度', unit: '℃' },\n  ],\n}\n```\n\n### 暴露方法\n\n通过模板 `ref` 可以调用：\n\n| 方法 | 返回值 | 说明 |\n| --- | --- | --- |\n| `redraw()` | `Promise<void>` | 重新归一化 `profile` 并完整重绘。响应式数据更新时通常不需要手动调用。 |\n| `clear()` | `void` | 删除组件当前生成的 SVG 内容，不修改传入的数据。 |\n\n### 事件与插槽\n\n当前组件没有对外事件和插槽。\n\n<a id=\"temperature-humidity-profile\"></a>\n\n## TemperatureHumidityProfile\n\n### 作用\n\n`TemperatureHumidityProfile` 是从 `SoundingChart` 主图抽出的独立温湿廓线组件，展示温度、露点、状态曲线、CAPE / CIN 能量区、干湿绝热线、等饱和比湿线、风羽和悬浮提示，不包含右侧风廓线及气象参数区。\n\n组件只负责绘图，不请求接口。内部复用 `SoundingChart` 的主图内核，确保独立图与探空综合图显示一致。\n\n### 使用方式\n\n```vue\n<template>\n  <div class=\"chart-container\">\n    <TemperatureHumidityProfile\n      ref=\"profileRef\"\n      :profile=\"profile\"\n      :option=\"option\"\n    />\n  </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { TemperatureHumidityProfile } from '@3clear/components/weather-charts'\nimport '@3clear/components/style.css'\n\nconst profileRef = ref(null)\nconst profile = ref([\n  { press: 1000, height: 110, temp: 26, dew: 20, wd: 160, ws: 4 },\n  { press: 850, height: 1450, temp: 15, dew: 10, wd: 200, ws: 10 },\n  { press: 700, height: 3100, temp: 4, dew: -2, wd: 230, ws: 15 },\n  { press: 500, height: 5700, temp: -10, dew: -22, wd: 250, ws: 22 },\n])\n\n// 用法与 ECharts 相似：只写需要改的字段，其余使用组件默认值。\nconst option = {\n  backgroundColor: '#f8fbff',\n  tooltip: { show: true },\n  legend: { show: true, top: 12, right: 8 },\n  xAxis: { min: -80, max: 40, interval: 10 },\n  series: [\n    {\n      id: 'temperature',\n      lineStyle: { color: '#4f46e5', width: 3 },\n    },\n    {\n      id: 'dewPoint',\n      lineStyle: { color: '#16a34a', width: 3 },\n    },\n  ],\n}\n\n// 也可以命令式局部更新，series 会按 id 合并。\nfunction highlightTemperature() {\n  profileRef.value?.setOption({\n    series: [\n      { id: 'temperature', lineStyle: { color: '#ef4444', width: 4 } },\n    ],\n  })\n}\n</script>\n\n<style scoped lang=\"scss\">\n.chart-container {\n  width: 700px;\n  height: 600px;\n}\n</style>\n```\n\n### 参数\n\n| 参数 | 类型 | 必填 | 默认值 | 说明 |\n| --- | --- | --- | --- | --- |\n| `profile` | `Array<ProfileItem>` | 是 | `[]` | 探空垂直廓线，字段结构与 `SoundingChart` 相同。 |\n| `option` | `Object` | 否 | `{}` | 类 ECharts 配置，与默认 option 深度合并。 |\n| `autoresize` | `boolean` | 否 | `true` | 是否监听容器尺寸并自动重绘。 |\n\n`profile` 标准字段为 `press`、`height`、`temp`、`dew`、`wd`、`ws`，并兼容 `geopHigh`、`airTemp`、`dewTemp`、`windDir`、`windSpd`。其中风向、风速缺失时温湿曲线仍可绘制，对应层不显示有效风羽。\n\n组件尺寸跟随外层容器：通常只需要给容器设置宽高，无需在 option 中重复配置。组件默认高度为 `470px`。\n\n### `option` 主要配置\n\n| 配置 | 说明 |\n| --- | --- |\n| `backgroundColor` | 图表背景色。 |\n| `textStyle` | 全局文字颜色、字号和字体。 |\n| `grid` | 绘图区 `top / right / bottom / left` 边距。 |\n| `tooltip` | 悬浮提示的显隐、样式、指示线和 `formatter`。 |\n| `legend` | 图例显隐、位置、样式、`data` 和 `formatter`。 |\n| `xAxis` | 温度范围、间隔、轴线、标签、分隔线和 0℃ 线。 |\n| `yAxis` | 气压范围、刻度、轴线、标签、分隔线和高度标签。`heightLabel.distribute` 默认为 `true`，标签等距排列；设为 `false` 可恢复到对应气压层位置。 |\n| `guides` | 干绝热线、湿绝热线、等饱和比湿线和零度层标记。 |\n| `windBarb` | 风羽显隐、颜色、粗细、长度和引导线。 |\n| `series` | 内置曲线、能量区，以及自定义垂直曲线。 |\n| `empty` | 无数据文案及样式。 |\n\n内置 `series.id` 为 `temperature`、`dewPoint`、`parcel`、`cape`、`cin`。覆盖内置系列时建议始终使用 `id`，这样局部配置不会丢失其他默认曲线。\n\n新增自定义垂直曲线时，传入新 `id` 并用 `encode` 指定温度值和气压值字段：\n\n```js\nconst option = {\n  series: [\n    {\n      id: 'wetBulb',\n      name: '湿球温度',\n      type: 'line',\n      encode: { x: 'wetBulb', y: 'press' },\n      lineStyle: { color: '#8b5cf6', width: 2, type: 'dashed' },\n    },\n  ],\n}\n```\n\n`encode.x / encode.y` 也可传 `(item, index) => value` 函数。自定义系列未传 `data` 时使用 `profile`，传入 `data` 时使用系列自己的数据。\n\n### 暴露方法\n\n| 方法 | 说明 |\n| --- | --- |\n| `setOption(nextOption, options?)` | 局部合并配置；`options.notMerge: true` 时放弃当前实例配置，从默认值重新生成。 |\n| `getOption()` | 返回当前完整 option 副本。 |\n| `resize({ width?, height? })` | 按容器或指定尺寸重绘。 |\n| `clear()` | 清空当前 SVG 图形。 |\n| `redraw()` | 使用当前数据和 option 手动重绘。 |\n\n### 事件\n\n| 事件 | 说明 |\n| --- | --- |\n| `option-change(option)` | 调用组件实例 `setOption()` 后触发，返回合并后的完整配置。 |\n\n组件包还导出 `temperatureHumidityProfileDefaultOption`、`mergeTemperatureHumidityProfileOption()` 和 `cloneTemperatureHumidityProfileOption()`，用于查看默认值或在业务层预合并配置。\n\n<a id=\"upper-air-profile\"></a>\n\n## UpperAirProfile\n\n### 作用\n\n`UpperAirProfile` 使用 Canvas 展示“预报时次 × 气压层”高空大气剖面：底色表示温度，风羽表示风向风速，青色 / 粉色圆点表示上升 / 下沉，棕色描边表示相邻气压层逆温。组件还可显示边界层高度与结构诊断，点击格点会返回完整数据。\n\n组件不请求接口，不依赖 ECharts、Element Plus 或 GIS 引擎。\n\n### 使用方式\n\n```vue\n<script setup>\nimport { ref } from 'vue'\nimport { UpperAirProfile } from '@3clear/components/weather-charts'\nimport '@3clear/components/style.css'\n\nconst selectedIndex = ref(0)\nconst profiles = ref([\n  {\n    dataTime: '2026-07-29T08:00:00+08:00',\n    predictionInterval: 0,\n    boundaryLayerHeight: 620,\n    levels: [\n      {\n        pressureHpa: 1000,\n        geopotentialHeight: 120,\n        temperature: 29.5,\n        relativeHumidity: 68,\n        windSpeed: 3.2,\n","readmeFilename":"README.md"}