init
This commit is contained in:
commit
e406e68474
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
raw
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Vue 3 + TypeScript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
||||
353
bun.lock
Normal file
353
bun.lock
Normal file
@ -0,0 +1,353 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "asm-introduction",
|
||||
"dependencies": {
|
||||
"jszip": "^3.10.1",
|
||||
"vue": "^3.5.17",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"sass-embedded": "^1.90.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^7.0.4",
|
||||
"vue-tsc": "^2.2.12",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.0" }, "bin": "./bin/babel-parser.js" }, "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||
|
||||
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.6.3", "", {}, "sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.8", "", { "os": "aix", "cpu": "ppc64" }, "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.8", "", { "os": "android", "cpu": "arm" }, "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.8", "", { "os": "android", "cpu": "arm64" }, "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.8", "", { "os": "android", "cpu": "x64" }, "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.8", "", { "os": "linux", "cpu": "arm" }, "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.8", "", { "os": "linux", "cpu": "ia32" }, "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.8", "", { "os": "linux", "cpu": "x64" }, "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.8", "", { "os": "none", "cpu": "x64" }, "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.8", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.8", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.8", "", { "os": "sunos", "cpu": "x64" }, "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.8", "", { "os": "win32", "cpu": "x64" }, "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
|
||||
|
||||
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
||||
|
||||
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
|
||||
|
||||
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="],
|
||||
|
||||
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="],
|
||||
|
||||
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="],
|
||||
|
||||
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="],
|
||||
|
||||
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="],
|
||||
|
||||
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.29", "", {}, "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.46.2", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.46.2", "", { "os": "android", "cpu": "arm64" }, "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.46.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.46.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.46.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.46.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.46.2", "", { "os": "linux", "cpu": "arm" }, "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.46.2", "", { "os": "linux", "cpu": "arm" }, "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.46.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.46.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg=="],
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA=="],
|
||||
|
||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.46.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.46.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.46.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.46.2", "", { "os": "linux", "cpu": "x64" }, "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.46.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.46.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.46.2", "", { "os": "win32", "cpu": "x64" }, "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||
|
||||
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.29" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vue": "^3.2.25" } }, "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw=="],
|
||||
|
||||
"@volar/language-core": ["@volar/language-core@2.4.15", "", { "dependencies": { "@volar/source-map": "2.4.15" } }, "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA=="],
|
||||
|
||||
"@volar/source-map": ["@volar/source-map@2.4.15", "", {}, "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg=="],
|
||||
|
||||
"@volar/typescript": ["@volar/typescript@2.4.15", "", { "dependencies": { "@volar/language-core": "2.4.15", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg=="],
|
||||
|
||||
"@vue/compiler-core": ["@vue/compiler-core@3.5.18", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/shared": "3.5.18", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw=="],
|
||||
|
||||
"@vue/compiler-dom": ["@vue/compiler-dom@3.5.18", "", { "dependencies": { "@vue/compiler-core": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A=="],
|
||||
|
||||
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.18", "", { "dependencies": { "@babel/parser": "^7.28.0", "@vue/compiler-core": "3.5.18", "@vue/compiler-dom": "3.5.18", "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA=="],
|
||||
|
||||
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.18", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g=="],
|
||||
|
||||
"@vue/compiler-vue2": ["@vue/compiler-vue2@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A=="],
|
||||
|
||||
"@vue/language-core": ["@vue/language-core@2.2.12", "", { "dependencies": { "@volar/language-core": "2.4.15", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^1.0.3", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA=="],
|
||||
|
||||
"@vue/reactivity": ["@vue/reactivity@3.5.18", "", { "dependencies": { "@vue/shared": "3.5.18" } }, "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg=="],
|
||||
|
||||
"@vue/runtime-core": ["@vue/runtime-core@3.5.18", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/shared": "3.5.18" } }, "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w=="],
|
||||
|
||||
"@vue/runtime-dom": ["@vue/runtime-dom@3.5.18", "", { "dependencies": { "@vue/reactivity": "3.5.18", "@vue/runtime-core": "3.5.18", "@vue/shared": "3.5.18", "csstype": "^3.1.3" } }, "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw=="],
|
||||
|
||||
"@vue/server-renderer": ["@vue/server-renderer@3.5.18", "", { "dependencies": { "@vue/compiler-ssr": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "vue": "3.5.18" } }, "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA=="],
|
||||
|
||||
"@vue/shared": ["@vue/shared@3.5.18", "", {}, "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA=="],
|
||||
|
||||
"@vue/tsconfig": ["@vue/tsconfig@0.7.0", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg=="],
|
||||
|
||||
"alien-signals": ["alien-signals@1.0.13", "", {}, "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
|
||||
|
||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||
|
||||
"colorjs.io": ["colorjs.io@0.5.2", "", {}, "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"de-indent": ["de-indent@1.0.2", "", {}, "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="],
|
||||
|
||||
"detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.8", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.8", "@esbuild/android-arm": "0.25.8", "@esbuild/android-arm64": "0.25.8", "@esbuild/android-x64": "0.25.8", "@esbuild/darwin-arm64": "0.25.8", "@esbuild/darwin-x64": "0.25.8", "@esbuild/freebsd-arm64": "0.25.8", "@esbuild/freebsd-x64": "0.25.8", "@esbuild/linux-arm": "0.25.8", "@esbuild/linux-arm64": "0.25.8", "@esbuild/linux-ia32": "0.25.8", "@esbuild/linux-loong64": "0.25.8", "@esbuild/linux-mips64el": "0.25.8", "@esbuild/linux-ppc64": "0.25.8", "@esbuild/linux-riscv64": "0.25.8", "@esbuild/linux-s390x": "0.25.8", "@esbuild/linux-x64": "0.25.8", "@esbuild/netbsd-arm64": "0.25.8", "@esbuild/netbsd-x64": "0.25.8", "@esbuild/openbsd-arm64": "0.25.8", "@esbuild/openbsd-x64": "0.25.8", "@esbuild/openharmony-arm64": "0.25.8", "@esbuild/sunos-x64": "0.25.8", "@esbuild/win32-arm64": "0.25.8", "@esbuild/win32-ia32": "0.25.8", "@esbuild/win32-x64": "0.25.8" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q=="],
|
||||
|
||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="],
|
||||
|
||||
"immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="],
|
||||
|
||||
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
||||
|
||||
"jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="],
|
||||
|
||||
"lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
||||
|
||||
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
||||
|
||||
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||
|
||||
"rollup": ["rollup@4.46.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.46.2", "@rollup/rollup-android-arm64": "4.46.2", "@rollup/rollup-darwin-arm64": "4.46.2", "@rollup/rollup-darwin-x64": "4.46.2", "@rollup/rollup-freebsd-arm64": "4.46.2", "@rollup/rollup-freebsd-x64": "4.46.2", "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", "@rollup/rollup-linux-arm-musleabihf": "4.46.2", "@rollup/rollup-linux-arm64-gnu": "4.46.2", "@rollup/rollup-linux-arm64-musl": "4.46.2", "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", "@rollup/rollup-linux-ppc64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-musl": "4.46.2", "@rollup/rollup-linux-s390x-gnu": "4.46.2", "@rollup/rollup-linux-x64-gnu": "4.46.2", "@rollup/rollup-linux-x64-musl": "4.46.2", "@rollup/rollup-win32-arm64-msvc": "4.46.2", "@rollup/rollup-win32-ia32-msvc": "4.46.2", "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg=="],
|
||||
|
||||
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
"sass": ["sass@1.90.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q=="],
|
||||
|
||||
"sass-embedded": ["sass-embedded@1.90.0", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.90.0", "sass-embedded-android-arm": "1.90.0", "sass-embedded-android-arm64": "1.90.0", "sass-embedded-android-riscv64": "1.90.0", "sass-embedded-android-x64": "1.90.0", "sass-embedded-darwin-arm64": "1.90.0", "sass-embedded-darwin-x64": "1.90.0", "sass-embedded-linux-arm": "1.90.0", "sass-embedded-linux-arm64": "1.90.0", "sass-embedded-linux-musl-arm": "1.90.0", "sass-embedded-linux-musl-arm64": "1.90.0", "sass-embedded-linux-musl-riscv64": "1.90.0", "sass-embedded-linux-musl-x64": "1.90.0", "sass-embedded-linux-riscv64": "1.90.0", "sass-embedded-linux-x64": "1.90.0", "sass-embedded-unknown-all": "1.90.0", "sass-embedded-win32-arm64": "1.90.0", "sass-embedded-win32-x64": "1.90.0" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-XP1EltyLLfuU5FsGVjSz8PcT925oA3rDnJTWOEBHR42k62ZEbKTcZ4gVlFwKi0Ggzi5E8v1K2BplD8ELHwusYg=="],
|
||||
|
||||
"sass-embedded-all-unknown": ["sass-embedded-all-unknown@1.90.0", "", { "dependencies": { "sass": "1.90.0" }, "cpu": [ "!arm", "!x64", "!arm64", ] }, "sha512-/n7jTQvI+hftDDrHzK19G4pxfDzOhtjuQO1K54ui1pT2S0sWfWDjCYUbQgtWQ6FO7g5qWS0hgmrWdc7fmS3rgA=="],
|
||||
|
||||
"sass-embedded-android-arm": ["sass-embedded-android-arm@1.90.0", "", { "os": "android", "cpu": "arm" }, "sha512-usF6kVJQWa1CMgPH1nCT1y8KEmAT2fzB00dDIPBYHq8U5VZLCihi2bJRP5U9NlcwP1TlKGKCjwsbIdSjDKfecg=="],
|
||||
|
||||
"sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.90.0", "", { "os": "android", "cpu": "arm64" }, "sha512-bkTlewzWksa6Sj4Zs1CWiutnvUbsO3xuYh2QBRknXsOtuMlfTPoXnwhCnyE4lSvUxw2qxSbv+NdQev9qMfsBgA=="],
|
||||
|
||||
"sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.90.0", "", { "os": "android", "cpu": "none" }, "sha512-bpqCIOaX+0Lou/BNJ4iJIKbWbVaYXFdg26C3gG6gxxKZRzp/6OYCxHrIQDwhKz6YC8Q5rwNPMpfDVYbWPcgroA=="],
|
||||
|
||||
"sass-embedded-android-x64": ["sass-embedded-android-x64@1.90.0", "", { "os": "android", "cpu": "x64" }, "sha512-GNxVKnCMd/p2icZ+Q4mhvNk19NrLXq1C4guiqjrycHYQLEnxRkjbW1QXYiL+XyDn4e+Bcq0knzG0I9pMuNZxkg=="],
|
||||
|
||||
"sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.90.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-qr4KBMJfBA+lzXiWnP00qzpLzHQzGd1OSK3VHcUFjZ8l7VOYf2R7Tc3fcTLhpaNPMJtTK0jrk8rFqBvsiZExnA=="],
|
||||
|
||||
"sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.90.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-z2nr1nNqtWDLVRwTbHtL7zriK90U7O/Gb15UaCSMYeAz9Y+wog5s/sDEKm0+GsVdzzkaCaMZRWGN4jTilnUwmQ=="],
|
||||
|
||||
"sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.90.0", "", { "os": "linux", "cpu": "arm" }, "sha512-FeBxI5Q2HvM3CCadcEcQgvWbDPVs2YEF0PZ87fbAVTCG8dV+iNnQreSz7GRJroknpvbRhm5t2gedvcgmTnPb2Q=="],
|
||||
|
||||
"sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.90.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-SPMcGZuP71Fj8btCGtlBnv8h8DAbJn8EQfLzXs9oo6NGFFLVjNGiFpqGfgtUV6DLWCuaRyEFeViO7wZow/vKGQ=="],
|
||||
|
||||
"sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.90.0", "", { "os": "linux", "cpu": "arm" }, "sha512-EB2z0fUXdUdvSoddf4DzdZQkD/xyreD72gwAi8YScgUvR4HMXI7bLcK/n78Rft6OnqvV8090hjC8FsLDo3x5xQ=="],
|
||||
|
||||
"sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.90.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-xLH7+PFq763MoEm3vI7hQk5E+nStiLWbijHEYW/tEtCbcQIphgzSkDItEezxXew3dU4EJ1jqrBUySPdoXFLqWA=="],
|
||||
|
||||
"sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.90.0", "", { "os": "linux", "cpu": "none" }, "sha512-L21UkOgnSrD+ERF+jo1IWneGv40t0ap9+3cI+wZWYhQS5MkxponhT9QaNU57JEDJwB9mOl01LVw14opz4SN+VQ=="],
|
||||
|
||||
"sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.90.0", "", { "os": "linux", "cpu": "x64" }, "sha512-NeAycQlsdhFdnIeSmRmScYUyCd+uE+x15NLFunbF8M0PgCKurrUhaxgGKSuBbaK56FpxarKOHCqcOrWbemIGzQ=="],
|
||||
|
||||
"sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.90.0", "", { "os": "linux", "cpu": "none" }, "sha512-lJopaQhW8S+kaQ61vMqq3c+bOurcf9RdZf2EmzQYpc2y1vT5cWfRNrRkbAgO/23IQxsk/fq3UIUnsjnyQmi6MA=="],
|
||||
|
||||
"sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.90.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Cc061gBfMPwH9rN7neQaH36cvOQC+dFMSGIeX5qUOhrEL4Ng51iqBV6aI4RIB1jCFGth6eDydVRN1VdV9qom8A=="],
|
||||
|
||||
"sass-embedded-unknown-all": ["sass-embedded-unknown-all@1.90.0", "", { "dependencies": { "sass": "1.90.0" }, "os": [ "!linux", "!win32", "!darwin", "!android", ] }, "sha512-DBGzHVCJDqtjTHZFohush9YTxd4ZxhIygIRTNRXnA0359woF9Z8AS7/YxfzwkqrTX5durSJa6ZamGFYVLoRphQ=="],
|
||||
|
||||
"sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.90.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-c3/vL/CATnaW3x/6kcNbCROEOUU7zvJpIURp7M9664GJj08/gLPRWKNruw0OkAPQ3C5TTQz7+/fQWEpRA6qmvA=="],
|
||||
|
||||
"sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.90.0", "", { "os": "win32", "cpu": "x64" }, "sha512-PFwdW7AYtCkwi3NfWFeexvIZEJ0nuShp8Bjjc3px756+18yYwBWa78F4TGdIQmJfpYKBhgkVjFOctwq+NCHntA=="],
|
||||
|
||||
"setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||
|
||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="],
|
||||
|
||||
"sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
|
||||
|
||||
"vite": ["vite@7.0.6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg=="],
|
||||
|
||||
"vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
|
||||
|
||||
"vue": ["vue@3.5.18", "", { "dependencies": { "@vue/compiler-dom": "3.5.18", "@vue/compiler-sfc": "3.5.18", "@vue/runtime-dom": "3.5.18", "@vue/server-renderer": "3.5.18", "@vue/shared": "3.5.18" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA=="],
|
||||
|
||||
"vue-tsc": ["vue-tsc@2.2.12", "", { "dependencies": { "@volar/typescript": "2.4.15", "@vue/language-core": "2.2.12" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "./bin/vue-tsc.js" } }, "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
}
|
||||
}
|
||||
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "asm-introduction",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"jszip": "^3.10.1",
|
||||
"vue": "^3.5.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"sass-embedded": "^1.90.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^7.0.4",
|
||||
"vue-tsc": "^2.2.12"
|
||||
}
|
||||
}
|
||||
274
src/App.vue
Normal file
274
src/App.vue
Normal file
@ -0,0 +1,274 @@
|
||||
<script setup lang="ts">
|
||||
import Loader from './views/Loader.vue';
|
||||
import s1Icon from './assets/s1_icon.png';
|
||||
import s2Icon from './assets/s2_icon.png';
|
||||
import s3Icon from './assets/s3_icon.png';
|
||||
import s4Icon from './assets/s4_icon.png';
|
||||
import AniEle from './ani-comp/AniEle.vue';
|
||||
import { computed, ref, useTemplateRef } from 'vue';
|
||||
import eas from './assets/audio';
|
||||
|
||||
const currentStage = ref(-1)
|
||||
|
||||
const stages = [1, 2, 3, 4]
|
||||
|
||||
const stageIcons = [
|
||||
s1Icon,
|
||||
s2Icon,
|
||||
s3Icon,
|
||||
s4Icon,
|
||||
]
|
||||
|
||||
const icon_grow = new URL('./assets/按钮高亮.zip', import.meta.url).href;
|
||||
const icon_intro = new URL('./assets/按钮引导.zip', import.meta.url).href;
|
||||
|
||||
const home_intro = new URL('./assets/首页引导.zip', import.meta.url).href;
|
||||
const egg_intro = new URL('./assets/晶圆引导.zip', import.meta.url).href;
|
||||
|
||||
const loading = ref(true);
|
||||
|
||||
|
||||
const mainVideo = useTemplateRef('main-video');
|
||||
|
||||
function continueAnimation() {
|
||||
const cR = mainVideo.value?.getCurrentRule().name
|
||||
console.log('continueAnimation', cR);
|
||||
|
||||
|
||||
switch (cR) {
|
||||
case 'intro-enter':
|
||||
mainVideo.value?.jumpTo('intro-out');
|
||||
eas.play('water_interface')
|
||||
eas.play('shimmering_light')
|
||||
eas.play('whoosh')
|
||||
break;
|
||||
case 'egg-loop':
|
||||
mainVideo.value?.jumpToSoftly('egg-out');
|
||||
eas.play('water_interface')
|
||||
eas.play('whoosh')
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const currentFrame = ref(0);
|
||||
|
||||
const showHomeIntro = computed(() => {
|
||||
return currentFrame.value == 34;
|
||||
});
|
||||
|
||||
const showEggIntro = computed(() => {
|
||||
return currentFrame.value >= 124 && currentFrame.value < 175;
|
||||
});
|
||||
|
||||
function onFrameProgress(frame: number) {
|
||||
// console.log('onFrameProgress', frame);
|
||||
|
||||
currentFrame.value = frame;
|
||||
if (frame === 240) {
|
||||
currentStage.value = 0;
|
||||
} else if (frame === 339) {
|
||||
currentStage.value = 1;
|
||||
} else if (frame === 498) {
|
||||
currentStage.value = 2;
|
||||
} else if (frame === 638) {
|
||||
currentStage.value = 3;
|
||||
} else if (frame === 1045) {
|
||||
currentStage.value = -1; // Reset current stage when reaching the end
|
||||
mainVideo.value?.jumpTo('intro-enter'); // Loop back to intro
|
||||
}
|
||||
|
||||
if (frame == 868) {
|
||||
eas.play('whoosh');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function clickBtn(index: number) {
|
||||
if (currentStage.value === index) {
|
||||
mainVideo.value?.jumpTo(`stage-${index + 1}`);
|
||||
eas.play('water_interface')
|
||||
currentStage.value = -1; // Reset current stage after clicking
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const bgm = useTemplateRef('bgm-ele');
|
||||
const bgmURL = new URL('./assets/audio/The AI Technology.mp3', import.meta.url).href;
|
||||
|
||||
window.addEventListener('pointerdown', () => {
|
||||
if (bgm.value?.paused) {
|
||||
bgm.value.play().catch((error) => {
|
||||
console.error('Error playing background music:', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const isPortrait = ref(window.innerHeight > window.innerWidth);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
isPortrait.value = window.innerHeight > window.innerWidth;
|
||||
});
|
||||
|
||||
document.addEventListener('pointerdown', (e) => {
|
||||
//鼠标中键
|
||||
if (e.buttons == 4) {
|
||||
// 处理鼠标中键点击事件
|
||||
document.body.requestFullscreen().catch((error) => {
|
||||
console.error('Error entering fullscreen:', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const loadProgress = ref({ download: 0, decode: 0 });
|
||||
|
||||
const mainVideoURL = new URL('./assets/main.mp4', import.meta.url).href;
|
||||
const mainZipURL = new URL('./assets/main.zip', import.meta.url).href;
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app" :class="{ rotate: isPortrait }">
|
||||
<audio :src="bgmURL" loop autoplay ref="bgm-ele"></audio>
|
||||
|
||||
<Transition name="fade">
|
||||
<Loader v-if="loadProgress.decode < 1" :progress="loadProgress" />
|
||||
</Transition>
|
||||
|
||||
<AniEle ref="main-video" class="main-video" :rules="[
|
||||
{ name: 'intro-enter', duration: 33, frame: 35, loop: 1, pauseAfter: true },
|
||||
{ name: 'intro-out', duration: 33, frame: 89, loop: 1 },
|
||||
{ name: 'egg-loop', duration: 33, frame: 50, loop: 0 },
|
||||
{ name: 'egg-out', duration: 33, frame: 67, loop: 1, pauseAfter: true },
|
||||
{ name: 'stage-1', duration: 33, frame: 99, loop: 1, pauseAfter: true },
|
||||
{ name: 'stage-2', duration: 33, frame: 159, loop: 1, pauseAfter: true },
|
||||
{ name: 'stage-3', duration: 33, frame: 140, loop: 1, pauseAfter: true },
|
||||
{ name: 'stage-4', duration: 33, frame: 407, loop: 1 },
|
||||
]" :width="1920" :height="1080" stretch autoPlay log @click="continueAnimation"
|
||||
:url="{ video: mainVideoURL, zip: mainZipURL }" type="video" @loading="loadProgress = $event"
|
||||
@progress="onFrameProgress" />
|
||||
|
||||
<Transition name="fade">
|
||||
<AniEle v-if="showHomeIntro" :url="home_intro" :width="444" :height="50" :rules="[
|
||||
{ name: 'main', loop: 0, duration: 33, frame: 24 },
|
||||
]" class="home-intro intro-text" />
|
||||
</Transition>
|
||||
<Transition name="fade">
|
||||
<AniEle v-if="showEggIntro" :url="egg_intro" :width="516" :height="54" :rules="[
|
||||
{ name: 'main', loop: 0, duration: 33, frame: 25 },
|
||||
]" class="egg-intro intro-text" />
|
||||
</Transition>
|
||||
|
||||
<Transition name="slide-in">
|
||||
<div class="actions" v-if="currentStage >= 0">
|
||||
<div class="action" v-for="(s, index) in stages" :key="index"
|
||||
:style="{ cursor: currentStage == index ? 'pointer' : 'not-allowed' }" @click="clickBtn(index)">
|
||||
<img src="./assets/icon_bg.png" alt="" class="bg" />
|
||||
<img :src="stageIcons[index]" alt="" class="icon" />
|
||||
<AniEle :url="icon_grow" :width="210" :height="242" :rules="[{
|
||||
name: 'grow',
|
||||
duration: 33,
|
||||
frame: 24,
|
||||
loop: 0,
|
||||
}]" class="grow" v-if="index == currentStage" />
|
||||
<AniEle :url="icon_intro" :width="425" :height="54" :rules="[
|
||||
{ name: 'enter', duration: 33, frame: 25, loop: 1, },
|
||||
{ name: 'loop', duration: 33, frame: 23, loop: 0, }]" v-if="index == currentStage" class="intro" />
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.intro-text {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1000;
|
||||
height: 4.4vmin;
|
||||
pointer-events: none;
|
||||
|
||||
&.home-intro {
|
||||
left: 50%;
|
||||
top: 63%;
|
||||
}
|
||||
|
||||
&.egg-intro {
|
||||
left: 70%;
|
||||
top: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.app {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
&.rotate {
|
||||
height: 100vw;
|
||||
width: 100vh;
|
||||
transform: rotate(90deg) translateY(-100%);
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.actions {
|
||||
height: 100%;
|
||||
background-color: #411341;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding: 7vmin 7vmin 7vmin 8vmin;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.action {
|
||||
position: relative;
|
||||
|
||||
.bg {
|
||||
height: 18vmin;
|
||||
}
|
||||
|
||||
.grow {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 22vmin;
|
||||
width: fit-content;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 8vmin;
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: absolute;
|
||||
left: -4vmin;
|
||||
top: 50%;
|
||||
transform: translate(-100%, -100%);
|
||||
height: 5vmin;
|
||||
}
|
||||
}
|
||||
|
||||
.main-video {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
425
src/ani-comp/AniEle.vue
Normal file
425
src/ani-comp/AniEle.vue
Normal file
@ -0,0 +1,425 @@
|
||||
<template>
|
||||
<div class="ani-ele">
|
||||
<canvas v-if="!loading && !error" ref="canvasRef" :class="{ stretch }" :width="canvasWidth"
|
||||
:height="canvasHeight"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUnmount, watch } from 'vue'
|
||||
import { loadFromResSmartly } from './utils'
|
||||
|
||||
import type { AnimationRule } from './types'
|
||||
|
||||
interface Props {
|
||||
url: string | {
|
||||
zip?: string
|
||||
video?: string
|
||||
}
|
||||
rules: AnimationRule[]
|
||||
width: number
|
||||
height: number
|
||||
autoPlay?: boolean
|
||||
log?: boolean
|
||||
stretch?: boolean
|
||||
type?: 'zip' | 'video'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
autoPlay: true,
|
||||
log: true,
|
||||
type: 'zip',
|
||||
})
|
||||
|
||||
// 响应式状态
|
||||
const loading = ref(false)
|
||||
const error = ref('')
|
||||
const progress = ref(0)
|
||||
const images = ref<string[]>([])
|
||||
const loadedImages = ref<CanvasImageSource[]>([])
|
||||
const canvasRef = ref<HTMLCanvasElement>()
|
||||
const canvasWidth = ref(props.width)
|
||||
const canvasHeight = ref(props.height)
|
||||
|
||||
const isPlaying = ref(false)
|
||||
const isPaused = ref(false)
|
||||
const currentRuleIndex = ref(0)
|
||||
const currentFrame = ref(0)
|
||||
const currentLoopCount = ref(0)
|
||||
const animationId = ref<number>()
|
||||
const lastFrameTime = ref(0)
|
||||
const pendingJumpTo = ref<string>()
|
||||
const pendingJumpResolver = ref<((success: boolean) => void) | null>(null)
|
||||
|
||||
|
||||
// loadImageSequence 函数 (不变)
|
||||
const loadImageSequence = async (resUrl: string | { zip?: string, video?: string }) => {
|
||||
try {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
progress.value = 0
|
||||
images.value = []
|
||||
loadedImages.value = []
|
||||
console.log(`开始加载图片序列: ${resUrl}`);
|
||||
|
||||
|
||||
loadedImages.value = await loadFromResSmartly({
|
||||
url: typeof resUrl === 'string' ? { zip: resUrl } : resUrl,
|
||||
rules: props.rules,
|
||||
onprogress: (p) => emit('loading', p)
|
||||
})
|
||||
|
||||
loading.value = false
|
||||
if (props.log) console.log(`成功加载 ${images.value.length} 张图片`);
|
||||
|
||||
if (props.autoPlay) {
|
||||
startAnimation()
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('加载图片序列失败:', err)
|
||||
error.value = err instanceof Error ? err.message : '未知错误'
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'progress', frameIndex: number): void
|
||||
(e: 'loading', progress: { download: number, decode: number }): void
|
||||
}>();
|
||||
|
||||
|
||||
// drawFrame 函数 (不变)
|
||||
const drawFrame = (frameIndex: number) => {
|
||||
if (!canvasRef.value || !loadedImages.value.length) return
|
||||
const safeIndex = Math.max(0, Math.min(frameIndex, loadedImages.value.length - 1))
|
||||
|
||||
const canvas = canvasRef.value
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) return
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
const img = loadedImages.value[safeIndex]
|
||||
// 如果img加载失败,它仍然是一个Image对象,但drawImage不会绘制任何内容,
|
||||
// 从而使该帧保持透明,这正是我们想要的效果。
|
||||
if (img) {
|
||||
try {
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
||||
} catch (e) {
|
||||
console.error(`绘制帧 ${safeIndex} 时出错:`, e)
|
||||
}
|
||||
}
|
||||
|
||||
emit('progress', safeIndex)
|
||||
}
|
||||
|
||||
const jumpToRule = (ruleName: string): boolean => {
|
||||
const ruleIndex = findRuleIndex(ruleName)
|
||||
if (ruleIndex === -1) {
|
||||
console.warn(`未找到名为 "${ruleName}" 的规则`)
|
||||
if (pendingJumpResolver.value) {
|
||||
pendingJumpResolver.value(false);
|
||||
pendingJumpResolver.value = null;
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (props.log) console.log(`跳转到规则 "${ruleName}" (索引: ${ruleIndex})`);
|
||||
|
||||
if (isPlaying.value) {
|
||||
stopAnimation()
|
||||
}
|
||||
|
||||
currentRuleIndex.value = ruleIndex
|
||||
currentLoopCount.value = 0
|
||||
const targetRule = props.rules[ruleIndex]
|
||||
|
||||
let startFrame = targetRule.startFrame ?? 0
|
||||
if (targetRule.startFrame === undefined) {
|
||||
for (let i = 0; i < ruleIndex; i++) {
|
||||
startFrame += props.rules[i].frame
|
||||
}
|
||||
}
|
||||
|
||||
const endFrame = targetRule.endFrame ?? (startFrame + targetRule.frame - 1);
|
||||
currentFrame.value = targetRule.reverse ? endFrame : startFrame;
|
||||
|
||||
if (props.log) {
|
||||
console.log(`跳转到规则 "${ruleName}", 实际开始帧: ${currentFrame.value}, 规则帧范围: ${startFrame} - ${endFrame}`);
|
||||
}
|
||||
|
||||
drawFrame(currentFrame.value)
|
||||
isPaused.value = false
|
||||
pendingJumpTo.value = undefined
|
||||
|
||||
isPlaying.value = true
|
||||
lastFrameTime.value = performance.now()
|
||||
animate()
|
||||
|
||||
if (pendingJumpResolver.value) {
|
||||
pendingJumpResolver.value(true);
|
||||
pendingJumpResolver.value = null;
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// startAnimation 函数 (不变)
|
||||
const startAnimation = () => {
|
||||
if (!props.rules.length || !loadedImages.value.length || isPlaying.value) return
|
||||
|
||||
isPlaying.value = true
|
||||
isPaused.value = false
|
||||
|
||||
if (currentRuleIndex.value >= props.rules.length) {
|
||||
resetAnimation()
|
||||
}
|
||||
|
||||
const currentRule = props.rules[currentRuleIndex.value]
|
||||
let startFrame = currentRule.startFrame ?? 0
|
||||
if (currentRule.startFrame === undefined) {
|
||||
for (let i = 0; i < currentRuleIndex.value; i++) {
|
||||
startFrame += props.rules[i].frame
|
||||
}
|
||||
}
|
||||
|
||||
const endFrame = currentRule.endFrame ?? (startFrame + currentRule.frame - 1);
|
||||
currentFrame.value = currentRule.reverse ? endFrame : startFrame;
|
||||
|
||||
if (props.log) console.log(`开始播放规则 "${currentRule.name}", 实际开始帧: ${currentFrame.value}`);
|
||||
|
||||
lastFrameTime.value = performance.now()
|
||||
animate()
|
||||
}
|
||||
|
||||
// animate 函数 (不变)
|
||||
const animate = () => {
|
||||
if (!isPlaying.value || currentRuleIndex.value >= props.rules.length) {
|
||||
animationId.value = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
animationId.value = requestAnimationFrame(animate);
|
||||
|
||||
const now = performance.now();
|
||||
const currentRule = props.rules[currentRuleIndex.value];
|
||||
const frameDuration = currentRule.duration ?? 33; // 默认约30fps
|
||||
|
||||
if (now - lastFrameTime.value >= frameDuration) {
|
||||
lastFrameTime.value = now - (now - lastFrameTime.value) % frameDuration;
|
||||
|
||||
let startFrame = currentRule.startFrame ?? 0;
|
||||
if (currentRule.startFrame === undefined) {
|
||||
for (let i = 0; i < currentRuleIndex.value; i++) {
|
||||
startFrame += props.rules[i].frame;
|
||||
}
|
||||
}
|
||||
const endFrame = currentRule.endFrame ?? (startFrame + currentRule.frame - 1);
|
||||
|
||||
let nextFrame = currentFrame.value + (currentRule.reverse ? -1 : 1);
|
||||
|
||||
const isEndOfRuleSegment = currentRule.reverse ? (nextFrame < startFrame) : (nextFrame > endFrame);
|
||||
|
||||
if (isEndOfRuleSegment) {
|
||||
currentLoopCount.value++;
|
||||
|
||||
if (pendingJumpTo.value) {
|
||||
const targetRule = pendingJumpTo.value;
|
||||
pendingJumpTo.value = undefined;
|
||||
if (props.log) console.log(`软跳转触发,目标规则 "${targetRule}"`);
|
||||
jumpToRule(targetRule);
|
||||
return;
|
||||
}
|
||||
|
||||
const isRuleFinished = currentRule.loop > 0 && currentLoopCount.value >= currentRule.loop;
|
||||
|
||||
if (isRuleFinished) {
|
||||
if (currentRule.pauseAfter) {
|
||||
isPaused.value = true;
|
||||
isPlaying.value = false;
|
||||
if (props.log) console.log(`规则 "${currentRule.name}" 完成,暂停等待跳转指令`);
|
||||
drawFrame(currentRule.reverse ? startFrame : endFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
currentRuleIndex.value++;
|
||||
currentLoopCount.value = 0;
|
||||
|
||||
if (currentRuleIndex.value >= props.rules.length) {
|
||||
isPlaying.value = false;
|
||||
if (props.log) console.log('所有规则播放完毕');
|
||||
drawFrame(currentRule.reverse ? startFrame : endFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
const nextRule = props.rules[currentRuleIndex.value];
|
||||
let nextRuleStartFrame = nextRule.startFrame ?? (endFrame + 1);
|
||||
const nextRuleEndFrame = nextRule.endFrame ?? (nextRuleStartFrame + nextRule.frame - 1);
|
||||
|
||||
currentFrame.value = nextRule.reverse ? nextRuleEndFrame : nextRuleStartFrame;
|
||||
if (props.log) console.log(`进入下一规则 "${nextRule.name}", 实际开始帧: ${currentFrame.value}`);
|
||||
|
||||
} else {
|
||||
currentFrame.value = currentRule.reverse ? endFrame : startFrame;
|
||||
}
|
||||
} else {
|
||||
currentFrame.value = nextFrame;
|
||||
}
|
||||
|
||||
drawFrame(currentFrame.value);
|
||||
}
|
||||
};
|
||||
|
||||
const stopAnimation = () => {
|
||||
isPlaying.value = false
|
||||
isPaused.value = false
|
||||
if (animationId.value) {
|
||||
cancelAnimationFrame(animationId.value)
|
||||
animationId.value = undefined
|
||||
}
|
||||
if (pendingJumpResolver.value) {
|
||||
pendingJumpResolver.value(false);
|
||||
pendingJumpResolver.value = null;
|
||||
}
|
||||
pendingJumpTo.value = undefined;
|
||||
}
|
||||
|
||||
const resetAnimation = () => {
|
||||
stopAnimation()
|
||||
currentRuleIndex.value = 0
|
||||
currentFrame.value = 0
|
||||
currentLoopCount.value = 0
|
||||
if (loadedImages.value.length > 0) {
|
||||
drawFrame(0)
|
||||
}
|
||||
}
|
||||
|
||||
// togglePlayback, resumeFromPause (不变)
|
||||
const togglePlayback = () => {
|
||||
if (isPlaying.value) {
|
||||
stopAnimation()
|
||||
} else {
|
||||
startAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
const resumeFromPause = () => {
|
||||
if (isPaused.value) {
|
||||
isPaused.value = false
|
||||
isPlaying.value = true
|
||||
lastFrameTime.value = performance.now()
|
||||
animate()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即跳转到指定规则,会打断当前动画。
|
||||
* @param {string} ruleName 要跳转到的规则名。
|
||||
*/
|
||||
const jumpTo = (ruleName: string) => {
|
||||
return jumpToRule(ruleName)
|
||||
}
|
||||
|
||||
/**
|
||||
* “软”跳转。该跳转会等到当前规则循环结束后再执行。
|
||||
* 如果动画已暂停或停止,则立即跳转。
|
||||
* @param {string} ruleName 要跳转到的规则名。
|
||||
* @returns {Promise<boolean>} 一个Promise,当成功跳转到目标规则时 resolve(true),否则 resolve(false)。
|
||||
*/
|
||||
const jumpToSoftly = (ruleName: string): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
const ruleIndex = findRuleIndex(ruleName);
|
||||
if (ruleIndex === -1) {
|
||||
console.warn(`无法设置软跳转:未找到规则 "${ruleName}"。`);
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingJumpResolver.value) {
|
||||
pendingJumpResolver.value(false);
|
||||
}
|
||||
pendingJumpResolver.value = resolve;
|
||||
|
||||
if (isPaused.value || !isPlaying.value) {
|
||||
if (props.log) console.log(`动画已暂停或停止。立即执行跳转到 "${ruleName}"。`);
|
||||
jumpToRule(ruleName);
|
||||
} else if (isPlaying.value) {
|
||||
if (props.log) console.log(`已计划软跳转到 "${ruleName}"。将在当前循环结束后触发。`);
|
||||
pendingJumpTo.value = ruleName;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// watch 和生命周期钩子 (不变)
|
||||
watch(() => props.url, (newUrl) => {
|
||||
if (newUrl) {
|
||||
resetAnimation()
|
||||
images.value.forEach(url => URL.revokeObjectURL(url));
|
||||
images.value = [];
|
||||
loadedImages.value = [];
|
||||
loadImageSequence(newUrl)
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => props.rules, () => {
|
||||
if (loadedImages.value.length > 0) {
|
||||
resetAnimation()
|
||||
if (props.autoPlay) {
|
||||
startAnimation()
|
||||
}
|
||||
}
|
||||
}, { deep: true })
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
resetAnimation();
|
||||
images.value.forEach(url => URL.revokeObjectURL(url));
|
||||
});
|
||||
|
||||
// findRuleIndex (不变)
|
||||
const findRuleIndex = (ruleName: string): number => {
|
||||
return props.rules.findIndex(rule => rule.name === ruleName)
|
||||
}
|
||||
|
||||
// defineExpose (不变)
|
||||
defineExpose({
|
||||
images,
|
||||
loadedImages,
|
||||
loading,
|
||||
error,
|
||||
isPlaying,
|
||||
isPaused,
|
||||
currentFrame,
|
||||
currentRuleIndex,
|
||||
currentLoopCount,
|
||||
reload: () => loadImageSequence(props.url),
|
||||
play: startAnimation,
|
||||
pause: stopAnimation,
|
||||
reset: resetAnimation,
|
||||
toggle: togglePlayback,
|
||||
resume: resumeFromPause,
|
||||
/** 立即跳转,会打断当前动画。 */
|
||||
jumpTo,
|
||||
/** 在当前动画循环结束后跳转,返回一个Promise。 */
|
||||
jumpToSoftly,
|
||||
drawFrame: (frameIndex: number) => drawFrame(frameIndex),
|
||||
findRuleIndex,
|
||||
getRules: () => props.rules,
|
||||
getCurrentRule: () => props.rules[currentRuleIndex.value],
|
||||
getRuleByName: (name: string) => props.rules.find(rule => rule.name === name)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
canvas {
|
||||
display: block;
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
canvas.stretch {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
||||
14
src/ani-comp/types.ts
Normal file
14
src/ani-comp/types.ts
Normal file
@ -0,0 +1,14 @@
|
||||
interface AnimationRule {
|
||||
name: string
|
||||
frame: number
|
||||
duration?: number
|
||||
loop: number
|
||||
startFrame?: number
|
||||
endFrame?: number
|
||||
reverse?: boolean
|
||||
easing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out'
|
||||
pauseAfter?: boolean
|
||||
}
|
||||
|
||||
|
||||
export type { AnimationRule }
|
||||
128
src/ani-comp/utils.ts
Normal file
128
src/ani-comp/utils.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import JSZip from 'jszip'
|
||||
import type { AnimationRule } from './types';
|
||||
import { extractFrameFromVideo } from './vFrameExtractor';
|
||||
|
||||
export async function loadFromResSmartly({ url, rules, onprogress }: {
|
||||
url: { zip?: string, video?: string },
|
||||
rules: AnimationRule[],
|
||||
onprogress?: (progress: { download: number, decode: number }) => void
|
||||
}): Promise<CanvasImageSource[]> {
|
||||
const isChromium = navigator.userAgent.includes('Chrome') || navigator.userAgent.includes('Chromium');
|
||||
const useWebCodec = isChromium && 'VideoDecoder' in window;
|
||||
|
||||
const finalType =
|
||||
useWebCodec && url.video ? 'video' :
|
||||
(url.zip ? 'zip' : 'none');
|
||||
|
||||
if (finalType == 'none') throw new Error('No valid resource type provided. Use "zip" or "video".');
|
||||
|
||||
return loadFromRes({
|
||||
url: finalType === 'zip' ? url.zip! : url.video!,
|
||||
type: finalType,
|
||||
rules,
|
||||
onprogress
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadFromRes({ url, type, rules, onprogress }: {
|
||||
url: string,
|
||||
type: 'zip' | 'video',
|
||||
rules: AnimationRule[],
|
||||
onprogress?: (progress: { download: number, decode: number }) => void
|
||||
}): Promise<CanvasImageSource[]> {
|
||||
if (type === 'zip') {
|
||||
const urls = await loadzip(url, p => (onprogress?.({ download: p, decode: 0 })));
|
||||
const images = await loadAllImages(urls);
|
||||
onprogress?.({ download: 1, decode: 1 });
|
||||
return images
|
||||
} else if (type === 'video') {
|
||||
return extractFrameFromVideo(url, rules?.reduce((acc, rule) => acc + rule.frame, 0), onprogress);
|
||||
} else {
|
||||
throw new Error('Unsupported type. Use "zip" or "video".');
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadzip(url: string, onprogress?: (progress: number) => void): Promise<string[]> {
|
||||
const zipBlob = await downloadRes(url, (progress) => {
|
||||
onprogress?.(progress * 0.8);
|
||||
});
|
||||
console.log(`加载压缩包: ${url}, 大小: ${(zipBlob.byteLength / 1024).toFixed(2)} KB`);
|
||||
const zip = new JSZip()
|
||||
const zipData = await zip.loadAsync(zipBlob)
|
||||
console.log(`压缩包加载完成,包含文件: ${Object.keys(zipData.files).length} 个文件`);
|
||||
|
||||
onprogress?.(60);
|
||||
|
||||
const webpFiles = Object.keys(zipData.files)
|
||||
.filter(name => !zipData.files[name].dir && (name.endsWith('.webp') || name.endsWith('.png') || name.endsWith('.jpg')))
|
||||
.sort((a, b) => {
|
||||
const numA = parseInt(a.match(/(\d+)\.\w+$/)?.[1] || '0')
|
||||
const numB = parseInt(b.match(/(\d+)\.\w+$/)?.[1] || '0')
|
||||
return numA - numB
|
||||
})
|
||||
|
||||
if (webpFiles.length === 0) {
|
||||
throw new Error('压缩包中没有找到支持的图片文件 (webp, png, jpg)')
|
||||
}
|
||||
|
||||
const imageUrls: string[] = []
|
||||
for (let i = 0; i < webpFiles.length; i++) {
|
||||
const fileName = webpFiles[i]
|
||||
const file = zipData.files[fileName]
|
||||
const imageBlob = await file.async('blob')
|
||||
const blobUrl = URL.createObjectURL(imageBlob)
|
||||
imageUrls.push(blobUrl)
|
||||
}
|
||||
|
||||
onprogress?.(100);
|
||||
|
||||
return imageUrls
|
||||
|
||||
}
|
||||
|
||||
export async function loadAllImages(urls: string[]) {
|
||||
const images: HTMLImageElement[] = []
|
||||
for (const url of urls) {
|
||||
const img = new Image()
|
||||
img.src = url
|
||||
await new Promise((resolve, reject) => {
|
||||
img.onload = () => resolve(undefined)
|
||||
img.onerror = () => resolve(undefined)
|
||||
})
|
||||
images.push(img)
|
||||
}
|
||||
return images
|
||||
}
|
||||
|
||||
// 下载视频文件
|
||||
export async function downloadRes(url: string, onProgress: (progress: number) => void): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.open('GET', url, true)
|
||||
xhr.responseType = 'arraybuffer'
|
||||
|
||||
xhr.onprogress = (event) => {
|
||||
if (event.lengthComputable) {
|
||||
const percentComplete = event.loaded / event.total
|
||||
onProgress(percentComplete)
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
if (xhr.status !== 200) {
|
||||
reject(new Error(`Failed to load video: ${xhr.statusText}`))
|
||||
return
|
||||
}
|
||||
|
||||
if (!xhr.response) {
|
||||
reject(new Error('Failed to load video data'))
|
||||
return
|
||||
}
|
||||
|
||||
resolve(xhr.response)
|
||||
}
|
||||
|
||||
xhr.onerror = () => reject(new Error('Network error occurred'))
|
||||
xhr.send()
|
||||
})
|
||||
}
|
||||
80
src/ani-comp/vFrameExtractor/index.ts
Normal file
80
src/ani-comp/vFrameExtractor/index.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { downloadRes } from "../utils"
|
||||
|
||||
|
||||
// 创建 Worker 并处理帧提取
|
||||
async function extractFramesWithWorker(
|
||||
blobPath: string,
|
||||
expectFrames: number,
|
||||
onProgress: (progress: number, totalSize: number) => void
|
||||
): Promise<VideoFrame[]> {
|
||||
let totalSize = 0
|
||||
return new Promise((resolve, reject) => {
|
||||
const frames: VideoFrame[] = []
|
||||
const worker = new Worker(new URL('./worker.js', import.meta.url),
|
||||
{ type: 'classic' }
|
||||
)
|
||||
|
||||
const handleWorkerMessage = (event: MessageEvent) => {
|
||||
const data = event.data
|
||||
if (!data) return
|
||||
|
||||
for (const key in data) {
|
||||
if (key === 'append_frame') {
|
||||
const frame = data[key] as VideoFrame
|
||||
frames.push(frame)
|
||||
totalSize += frame.allocationSize()
|
||||
onProgress(frames.length / expectFrames, totalSize )
|
||||
|
||||
if (frames.length >= expectFrames) {
|
||||
worker.removeEventListener('message', handleWorkerMessage)
|
||||
worker.terminate()
|
||||
resolve(frames)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// console.log(`[vFrameExtractor]:`, key, data[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
worker.addEventListener('message', handleWorkerMessage)
|
||||
worker.addEventListener('error', (error) => {
|
||||
worker.terminate()
|
||||
reject(new Error(`Worker error: ${error.message}`))
|
||||
})
|
||||
|
||||
worker.postMessage({ dataUri: blobPath })
|
||||
})
|
||||
}
|
||||
|
||||
// 主函数
|
||||
export async function extractFrameFromVideo(
|
||||
videoPath: string,
|
||||
expectFrames: number,
|
||||
onProgress?: (progress: { download: number, decode: number}) => void
|
||||
): Promise<VideoFrame[]> {
|
||||
try {
|
||||
// 下载视频
|
||||
const arrayBuffer = await downloadRes(videoPath, (downloadProgress) => {
|
||||
onProgress?.({ download: downloadProgress, decode: 0})
|
||||
})
|
||||
|
||||
// 创建 Blob 和 URL
|
||||
const blob = new Blob([arrayBuffer], { type: 'video/mp4' })
|
||||
const blobPath = URL.createObjectURL(blob)
|
||||
|
||||
try {
|
||||
// 提取帧
|
||||
const frames = await extractFramesWithWorker(blobPath, expectFrames, (decodeProgress) => {
|
||||
onProgress?.({ download: 1, decode: decodeProgress })
|
||||
})
|
||||
|
||||
return frames
|
||||
} finally {
|
||||
// 清理 URL
|
||||
URL.revokeObjectURL(blobPath)
|
||||
}
|
||||
} catch (error) {
|
||||
throw error instanceof Error ? error : new Error('Unknown error occurred')
|
||||
}
|
||||
}
|
||||
174
src/ani-comp/vFrameExtractor/worker.js
Normal file
174
src/ani-comp/vFrameExtractor/worker.js
Normal file
File diff suppressed because one or more lines are too long
BIN
src/assets/audio/Shimmering Light 02.mp3
Normal file
BIN
src/assets/audio/Shimmering Light 02.mp3
Normal file
Binary file not shown.
BIN
src/assets/audio/The AI Technology.mp3
Normal file
BIN
src/assets/audio/The AI Technology.mp3
Normal file
Binary file not shown.
BIN
src/assets/audio/Water Interface Button 03.mp3
Normal file
BIN
src/assets/audio/Water Interface Button 03.mp3
Normal file
Binary file not shown.
BIN
src/assets/audio/Whoosh 01.mp3
Normal file
BIN
src/assets/audio/Whoosh 01.mp3
Normal file
Binary file not shown.
13
src/assets/audio/index.ts
Normal file
13
src/assets/audio/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { EasyAudio } from "./utils";
|
||||
|
||||
import water_interface from "./Water Interface Button 03.mp3"
|
||||
import whoosh from "./Whoosh 01.mp3"
|
||||
import shimmering_light from "./Shimmering Light 02.mp3"
|
||||
|
||||
const ea = new EasyAudio([
|
||||
{ name: "water_interface", audioUrl: water_interface, volume: 0.8 },
|
||||
{ name: "whoosh", audioUrl: whoosh, volume: 0.9 },
|
||||
{ name: "shimmering_light", audioUrl: shimmering_light, volume: 0.9 },
|
||||
]);
|
||||
|
||||
export default ea;
|
||||
114
src/assets/audio/utils.ts
Normal file
114
src/assets/audio/utils.ts
Normal file
@ -0,0 +1,114 @@
|
||||
export class EasyAudio {
|
||||
private static audioCtx: AudioContext | null = null;
|
||||
private buffers: Map<string, AudioBuffer> = new Map();
|
||||
private sources: Map<string, AudioBufferSourceNode> = new Map();
|
||||
private audioOptions: Map<
|
||||
string,
|
||||
{ audioUrl: string; loop?: boolean; volume?: number }
|
||||
> = new Map();
|
||||
|
||||
private get audioCtx(): AudioContext {
|
||||
if (!EasyAudio.audioCtx) {
|
||||
EasyAudio.audioCtx = new AudioContext();
|
||||
}
|
||||
return EasyAudio.audioCtx;
|
||||
}
|
||||
|
||||
constructor(
|
||||
audios?:
|
||||
| { name: string; audioUrl: string | URL; loop?: boolean; volume?: number }
|
||||
| { name: string; audioUrl: string | URL; loop?: boolean; volume?: number }[]
|
||||
) {
|
||||
if (audios) {
|
||||
this.add(audios);
|
||||
}
|
||||
}
|
||||
|
||||
private async createAudioBuffer(audioUrl: string): Promise<AudioBuffer> {
|
||||
const response = await fetch(audioUrl);
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
return await this.audioCtx.decodeAudioData(arrayBuffer);
|
||||
}
|
||||
|
||||
private async loadAudio(name: string) {
|
||||
const options = this.audioOptions.get(name);
|
||||
if (!options) {
|
||||
throw new Error(`音频 ${name} 未找到`);
|
||||
}
|
||||
const buffer = await this.createAudioBuffer(options.audioUrl);
|
||||
this.buffers.set(name, buffer);
|
||||
}
|
||||
|
||||
async load(): Promise<void> {
|
||||
const promises = Array.from(this.audioOptions.keys()).map(name =>
|
||||
this.loadAudio(name)
|
||||
);
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
add(
|
||||
audios:
|
||||
| { name: string; audioUrl: string | URL; loop?: boolean; volume?: number }
|
||||
| { name: string; audioUrl: string | URL; loop?: boolean; volume?: number }[]
|
||||
): void {
|
||||
if (Array.isArray(audios)) {
|
||||
audios.forEach(audio => {
|
||||
this.audioOptions.set(audio.name, {
|
||||
audioUrl: typeof (audio.audioUrl) === "string" ? audio.audioUrl : audio.audioUrl.href,
|
||||
loop: audio.loop,
|
||||
volume: audio.volume,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.audioOptions.set(audios.name, {
|
||||
audioUrl: typeof (audios.audioUrl) === "string" ? audios.audioUrl : audios.audioUrl.href,
|
||||
loop: audios.loop,
|
||||
volume: audios.volume,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async play(name: string) {
|
||||
if (!this.buffers.has(name)) {
|
||||
await this.loadAudio(name);
|
||||
}
|
||||
|
||||
const buffer = this.buffers.get(name);
|
||||
const options = this.audioOptions.get(name);
|
||||
if (!buffer || !options) {
|
||||
throw new Error(`音频 ${name} 未找到`);
|
||||
}
|
||||
|
||||
const source = this.audioCtx.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.loop = options.loop || false;
|
||||
|
||||
let gainNode: GainNode | null = null;
|
||||
if (options.volume !== undefined) {
|
||||
gainNode = this.audioCtx.createGain();
|
||||
gainNode.gain.value = options.volume;
|
||||
source.connect(gainNode);
|
||||
gainNode.connect(this.audioCtx.destination);
|
||||
} else {
|
||||
source.connect(this.audioCtx.destination);
|
||||
}
|
||||
|
||||
source.start();
|
||||
this.sources.set(name, source);
|
||||
console.log(`音频 ${name} 播放`);
|
||||
|
||||
}
|
||||
|
||||
stop(name: string) {
|
||||
const source = this.sources.get(name);
|
||||
if (source) {
|
||||
source.stop();
|
||||
this.sources.delete(name);
|
||||
}
|
||||
}
|
||||
|
||||
stopAll() {
|
||||
this.sources.forEach(source => source.stop());
|
||||
this.sources.clear();
|
||||
}
|
||||
}
|
||||
BIN
src/assets/icon_bg.png
Normal file
BIN
src/assets/icon_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/main.mp4
Normal file
BIN
src/assets/main.mp4
Normal file
Binary file not shown.
BIN
src/assets/main.zip
Normal file
BIN
src/assets/main.zip
Normal file
Binary file not shown.
BIN
src/assets/s1_icon.png
Normal file
BIN
src/assets/s1_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/assets/s2_icon.png
Normal file
BIN
src/assets/s2_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/assets/s3_icon.png
Normal file
BIN
src/assets/s3_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/s4_icon.png
Normal file
BIN
src/assets/s4_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/vue.svg
Normal file
1
src/assets/vue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 496 B |
BIN
src/assets/按钮引导.zip
Normal file
BIN
src/assets/按钮引导.zip
Normal file
Binary file not shown.
BIN
src/assets/按钮高亮.zip
Normal file
BIN
src/assets/按钮高亮.zip
Normal file
Binary file not shown.
BIN
src/assets/晶圆引导.zip
Normal file
BIN
src/assets/晶圆引导.zip
Normal file
Binary file not shown.
BIN
src/assets/首页引导.zip
Normal file
BIN
src/assets/首页引导.zip
Normal file
Binary file not shown.
41
src/components/HelloWorld.vue
Normal file
41
src/components/HelloWorld.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps<{ msg: string }>()
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<div class="card">
|
||||
<button type="button" @click="count++">count is {{ count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test HMR
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Check out
|
||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
||||
>create-vue</a
|
||||
>, the official Vue + Vite starter
|
||||
</p>
|
||||
<p>
|
||||
Learn more about IDE Support for Vue in the
|
||||
<a
|
||||
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
|
||||
target="_blank"
|
||||
>Vue Docs Scaling up Guide</a
|
||||
>.
|
||||
</p>
|
||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
5
src/main.ts
Normal file
5
src/main.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
34
src/style.css
Normal file
34
src/style.css
Normal file
@ -0,0 +1,34 @@
|
||||
body{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.slide-in-enter-active,
|
||||
.slide-in-leave-active {
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.slide-in-enter-from,
|
||||
.slide-in-leave-to {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
#app{
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
48
src/views/Loader.vue
Normal file
48
src/views/Loader.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="loader">
|
||||
<div class="progress">
|
||||
<div class="progress-bar-download" :style="{ width: `${progress.download * 100}%` }"></div>
|
||||
<div class="progress-bar-decode" :style="{ width: `${progress.decode * 100}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
progress: { download: number, decode: number }
|
||||
}>();
|
||||
</script>
|
||||
<style scoped>
|
||||
.loader {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vmin;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.progress {
|
||||
position: relative;
|
||||
height: 1.6vmin;
|
||||
width: 60%;
|
||||
background: #eee;
|
||||
border-radius: .8vmin;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar-download,
|
||||
.progress-bar-decode {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
transition: width 0.2s;
|
||||
}
|
||||
|
||||
.progress-bar-download {
|
||||
background: #5A335A99;
|
||||
}
|
||||
|
||||
.progress-bar-decode {
|
||||
background: #5A335A;
|
||||
}
|
||||
</style>
|
||||
8
src/vite-env.d.ts
vendored
Normal file
8
src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
takeHeapSnapshot?: () => void;
|
||||
vframes: VideoFrame[];
|
||||
}
|
||||
}
|
||||
13
tsconfig.app.json
Normal file
13
tsconfig.app.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
||||
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
25
tsconfig.node.json
Normal file
25
tsconfig.node.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
11
vite.config.ts
Normal file
11
vite.config.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
server:{
|
||||
port:9999,
|
||||
host: '0.0.0.0'
|
||||
}
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user