feat: 删除战鼓相关代码 + 修复数据加载异常问题
This commit is contained in:
@@ -950,36 +950,5 @@
|
|||||||
"battleEndTime": {
|
"battleEndTime": {
|
||||||
"date": "2026-02-08",
|
"date": "2026-02-08",
|
||||||
"time": "00:00:00"
|
"time": "00:00:00"
|
||||||
},
|
|
||||||
"drumConfig": {
|
|
||||||
"sound": {
|
|
||||||
"volume": 1,
|
|
||||||
"frequency1": 150,
|
|
||||||
"frequency2": 100,
|
|
||||||
"attackTime": 0.01,
|
|
||||||
"decayTime": 0.3,
|
|
||||||
"type1": "sine",
|
|
||||||
"type2": "triangle",
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"animation": {
|
|
||||||
"beatInterval": 200,
|
|
||||||
"beatScale": 1.3,
|
|
||||||
"beatTranslateY": -15,
|
|
||||||
"beatRotate": 5,
|
|
||||||
"idlePulseDuration": 2,
|
|
||||||
"beatDuration": 100,
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"pattern": {
|
|
||||||
"strongBeats": [
|
|
||||||
1,
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"totalBeats": 4,
|
|
||||||
"accentMultiplier": 1.5,
|
|
||||||
"accentFrequencyOffset": 10,
|
|
||||||
"accentAnimation": 50
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
281
package-lock.json
generated
281
package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
|
"nodemon": "^3.1.11",
|
||||||
"sass": "^1.94.0",
|
"sass": "^1.94.0",
|
||||||
"vite": "^7.2.2"
|
"vite": "^7.2.2"
|
||||||
}
|
}
|
||||||
@@ -1282,12 +1283,59 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/anymatch": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/anymatch/node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/append-field": {
|
"node_modules/append-field": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/append-field/-/append-field-1.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/append-field/-/append-field-1.0.0.tgz",
|
||||||
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
|
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/body-parser": {
|
"node_modules/body-parser": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.0.tgz",
|
||||||
@@ -1308,13 +1356,23 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.1.1"
|
"fill-range": "^7.1.1"
|
||||||
},
|
},
|
||||||
@@ -1393,6 +1451,13 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/concat-stream": {
|
"node_modules/concat-stream": {
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz",
|
"resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||||
@@ -1712,7 +1777,6 @@
|
|||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
},
|
},
|
||||||
@@ -1816,6 +1880,19 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
|
||||||
@@ -1828,6 +1905,16 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-symbols": {
|
"node_modules/has-symbols": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
@@ -1889,6 +1976,13 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ignore-by-default": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/immutable": {
|
"node_modules/immutable": {
|
||||||
"version": "5.1.4",
|
"version": "5.1.4",
|
||||||
"resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.4.tgz",
|
"resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.4.tgz",
|
||||||
@@ -1911,13 +2005,25 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-extglob": {
|
"node_modules/is-extglob": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -1928,7 +2034,6 @@
|
|||||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-extglob": "^2.1.1"
|
"is-extglob": "^2.1.1"
|
||||||
},
|
},
|
||||||
@@ -1942,7 +2047,6 @@
|
|||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
@@ -2048,6 +2152,19 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
|
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
|
||||||
@@ -2172,6 +2289,96 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/nodemon": {
|
||||||
|
"version": "3.1.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/nodemon/-/nodemon-3.1.11.tgz",
|
||||||
|
"integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^3.5.2",
|
||||||
|
"debug": "^4",
|
||||||
|
"ignore-by-default": "^1.0.1",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"pstree.remy": "^1.1.8",
|
||||||
|
"semver": "^7.5.3",
|
||||||
|
"simple-update-notifier": "^2.0.0",
|
||||||
|
"supports-color": "^5.5.0",
|
||||||
|
"touch": "^3.1.0",
|
||||||
|
"undefsafe": "^2.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nodemon": "bin/nodemon.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/nodemon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nodemon/node_modules/chokidar": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nodemon/node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nodemon/node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -2299,6 +2506,13 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pstree.remy": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.14.0",
|
"version": "6.14.0",
|
||||||
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.0.tgz",
|
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.0.tgz",
|
||||||
@@ -2494,6 +2708,19 @@
|
|||||||
"@parcel/watcher": "^2.4.1"
|
"@parcel/watcher": "^2.4.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.7.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz",
|
||||||
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/send": {
|
"node_modules/send": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/send/-/send-1.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/send/-/send-1.2.0.tgz",
|
||||||
@@ -2609,6 +2836,19 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-update-notifier": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@@ -2650,6 +2890,19 @@
|
|||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
@@ -2673,7 +2926,6 @@
|
|||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
},
|
},
|
||||||
@@ -2690,6 +2942,16 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/touch": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/touch/-/touch-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"nodetouch": "bin/nodetouch.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-is": {
|
"node_modules/type-is": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz",
|
||||||
@@ -2710,6 +2972,13 @@
|
|||||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/undefsafe": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/unpipe": {
|
"node_modules/unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
|
"nodemon": "^3.1.11",
|
||||||
"sass": "^1.94.0",
|
"sass": "^1.94.0",
|
||||||
"vite": "^7.2.2"
|
"vite": "^7.2.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import {
|
|||||||
saveDisplayConfig as saveDisplayConfigToConfig,
|
saveDisplayConfig as saveDisplayConfigToConfig,
|
||||||
getBattleEndTime,
|
getBattleEndTime,
|
||||||
saveBattleEndTime as saveBattleEndTimeToConfig,
|
saveBattleEndTime as saveBattleEndTimeToConfig,
|
||||||
getDrumConfig,
|
|
||||||
saveDrumConfig as saveDrumConfigToConfig,
|
|
||||||
getBonusRules,
|
getBonusRules,
|
||||||
saveBonusRules as saveBonusRulesToConfig
|
saveBonusRules as saveBonusRulesToConfig
|
||||||
} from '../services/configService';
|
} from '../services/configService';
|
||||||
@@ -29,7 +27,7 @@ export let bonusRules = [
|
|||||||
export let systemUsers = [];
|
export let systemUsers = [];
|
||||||
export let displayConfig = null;
|
export let displayConfig = null;
|
||||||
export let battleEndTime = { date: new Date().toISOString().split('T')[0], time: '00:00:00' };
|
export let battleEndTime = { date: new Date().toISOString().split('T')[0], time: '00:00:00' };
|
||||||
export let drumConfig = {};
|
|
||||||
|
|
||||||
// 保存结束时间
|
// 保存结束时间
|
||||||
export const saveBattleEndTime = async (endTime) => {
|
export const saveBattleEndTime = async (endTime) => {
|
||||||
@@ -59,30 +57,7 @@ export const saveDisplayConfig = async (config) => {
|
|||||||
return await saveDisplayConfigToConfig(config);
|
return await saveDisplayConfigToConfig(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 保存战鼓配置
|
|
||||||
export const saveDrumConfig = async (config) => {
|
|
||||||
console.log('保存战鼓配置:', config);
|
|
||||||
|
|
||||||
// 深度合并配置,确保嵌套对象(如sound、animation、pattern)的属性不会丢失
|
|
||||||
drumConfig = {
|
|
||||||
...drumConfig,
|
|
||||||
...config,
|
|
||||||
sound: {
|
|
||||||
...drumConfig.sound,
|
|
||||||
...config.sound
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
...drumConfig.animation,
|
|
||||||
...config.animation
|
|
||||||
},
|
|
||||||
pattern: {
|
|
||||||
...drumConfig.pattern,
|
|
||||||
...config.pattern
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return await saveDrumConfigToConfig(drumConfig);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 保存奖金规则
|
// 保存奖金规则
|
||||||
export const saveBonusRules = async (rules) => {
|
export const saveBonusRules = async (rules) => {
|
||||||
@@ -118,7 +93,7 @@ export const refreshData = async () => {
|
|||||||
systemUsers = await getSystemUsers();
|
systemUsers = await getSystemUsers();
|
||||||
displayConfig = await getDisplayConfig();
|
displayConfig = await getDisplayConfig();
|
||||||
battleEndTime = await getBattleEndTime();
|
battleEndTime = await getBattleEndTime();
|
||||||
drumConfig = await getDrumConfig();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('刷新数据失败:', error);
|
console.error('刷新数据失败:', error);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// 配置文件API路径
|
// 配置文件API路径
|
||||||
const CONFIG_API_URL = '/api/config';
|
// 修复后(绝对路径,直接请求后端3000端口)
|
||||||
|
const CONFIG_API_URL = 'http://localhost:3000/api/config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取配置文件
|
* 读取配置文件
|
||||||
@@ -106,21 +107,7 @@ const getDefaultConfig = () => ({
|
|||||||
date: new Date().toISOString().split('T')[0],
|
date: new Date().toISOString().split('T')[0],
|
||||||
time: '00:00:00'
|
time: '00:00:00'
|
||||||
},
|
},
|
||||||
drumConfig: {
|
|
||||||
showDrum: false, // 控制战鼓的显示,默认不显示
|
|
||||||
sound: {
|
|
||||||
volume: 1.0,
|
|
||||||
enabled: false, // 控制声音播放,默认不播放
|
|
||||||
soundSrc: '' // 战鼓声音来源文件路径
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
pattern: {
|
|
||||||
strongBeats: [1],
|
|
||||||
totalBeats: 4
|
|
||||||
}
|
|
||||||
},
|
|
||||||
backgroundConfig: {
|
backgroundConfig: {
|
||||||
useBackgroundImage: true,
|
useBackgroundImage: true,
|
||||||
backgroundImage: '/battle-background.jpg', // 默认战旗背景图片
|
backgroundImage: '/battle-background.jpg', // 默认战旗背景图片
|
||||||
@@ -332,25 +319,7 @@ export const saveBattleEndTime = async (endTime) => {
|
|||||||
return await writeConfig(config);
|
return await writeConfig(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取战鼓配置
|
|
||||||
* @returns {Object} 战鼓配置
|
|
||||||
*/
|
|
||||||
export const getDrumConfig = async () => {
|
|
||||||
const config = await readConfig();
|
|
||||||
return config.drumConfig || getDefaultConfig().drumConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存战鼓配置
|
|
||||||
* @param {Object} drumConfig 战鼓配置
|
|
||||||
* @returns {boolean} 是否保存成功
|
|
||||||
*/
|
|
||||||
export const saveDrumConfig = async (drumConfig) => {
|
|
||||||
const config = await readConfig();
|
|
||||||
config.drumConfig = drumConfig;
|
|
||||||
return await writeConfig(config);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取背景配置
|
* 获取背景配置
|
||||||
|
|||||||
@@ -655,172 +655,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 战鼓配置 -->
|
|
||||||
<div v-if="currentTab === 'drum'" class="drum-config-content">
|
|
||||||
<h2 class="game-subtitle">🥁 战鼓配置管理</h2>
|
|
||||||
|
|
||||||
<!-- 音效配置 -->
|
|
||||||
<div class="config-section">
|
|
||||||
<h3 class="text-gold">🔊 音效配置</h3>
|
|
||||||
<div class="config-options">
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<input type="checkbox" v-model="localDrumConfig.sound.enabled">
|
|
||||||
<span>启用音效</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>音量 (0-1):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.sound.volume" min="0" max="1" step="0.1"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>起音时间 (s):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.sound.attackTime" min="0.001" max="0.5"
|
|
||||||
step="0.01" class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>衰减时间 (s):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.sound.decayTime" min="0.05" max="1" step="0.05"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<h4 style="margin-top: 15px; color: #666;">🎵 第一个音调</h4>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>音调类型:</span>
|
|
||||||
<select v-model="localDrumConfig.sound.type1" class="select-input">
|
|
||||||
<option value="sine">正弦波</option>
|
|
||||||
<option value="square">方波</option>
|
|
||||||
<option value="triangle">三角波</option>
|
|
||||||
<option value="sawtooth">锯齿波</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>频率 (Hz):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.sound.frequency1" min="50" max="500"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<h4 style="margin-top: 15px; color: #666;">🎵 第二个音调</h4>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>音调类型:</span>
|
|
||||||
<select v-model="localDrumConfig.sound.type2" class="select-input">
|
|
||||||
<option value="sine">正弦波</option>
|
|
||||||
<option value="square">方波</option>
|
|
||||||
<option value="triangle">三角波</option>
|
|
||||||
<option value="sawtooth">锯齿波</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>频率 (Hz):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.sound.frequency2" min="50" max="500"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 动画配置 -->
|
|
||||||
<div class="config-section">
|
|
||||||
<h3>🎬 动画配置</h3>
|
|
||||||
<div class="config-options">
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<input type="checkbox" v-model="localDrumConfig.animation.enabled">
|
|
||||||
<span>启用动画</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>节拍间隔 (ms):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.animation.beatInterval" min="50" max="1000"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>跳动缩放比例:</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.animation.beatScale" min="1.0" max="2.0"
|
|
||||||
step="0.1" class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>跳动上下位移 (px):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.animation.beatTranslateY" min="-50" max="50"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>跳动旋转角度 (deg):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.animation.beatRotate" min="0" max="20"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>单次跳动持续时间 (ms):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.animation.beatDuration" min="50" max="500"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 节拍模式配置 -->
|
|
||||||
<div class="config-section">
|
|
||||||
<h3>🎵 节拍模式配置</h3>
|
|
||||||
<div class="config-options">
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>每小节总拍数:</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.pattern.totalBeats" min="1" max="8"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>强拍位置 (1-4):</span>
|
|
||||||
<input type="text" v-model="localDrumConfig.pattern.strongBeatsStr" placeholder="如: 1,4"
|
|
||||||
class="text-input" @input="updateStrongBeats">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>强拍音量倍数:</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.pattern.accentMultiplier" min="1" max="3"
|
|
||||||
step="0.1" class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>强拍频率偏移 (%):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.pattern.accentFrequencyOffset" min="-50" max="50"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span>强拍动画增强 (%):</span>
|
|
||||||
<input type="number" v-model.number="localDrumConfig.pattern.accentAnimation" min="0" max="100"
|
|
||||||
class="width-input">
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 保存按钮 -->
|
<!-- 保存按钮 -->
|
||||||
@@ -954,8 +789,6 @@ import {
|
|||||||
saveDisplayConfig,
|
saveDisplayConfig,
|
||||||
battleEndTime,
|
battleEndTime,
|
||||||
saveBattleEndTime,
|
saveBattleEndTime,
|
||||||
drumConfig,
|
|
||||||
saveDrumConfig,
|
|
||||||
refreshData,
|
refreshData,
|
||||||
initializeData
|
initializeData
|
||||||
} from '../data/mockData.js';
|
} from '../data/mockData.js';
|
||||||
@@ -983,8 +816,7 @@ const tabs = [
|
|||||||
{ key: 'bonus', label: '奖金设置' },
|
{ key: 'bonus', label: '奖金设置' },
|
||||||
{ key: 'config', label: '显示配置' },
|
{ key: 'config', label: '显示配置' },
|
||||||
{ key: 'champion', label: '冠军Logo配置' },
|
{ key: 'champion', label: '冠军Logo配置' },
|
||||||
{ key: 'endTime', label: '结束时间设置' },
|
{ key: 'endTime', label: '结束时间设置' }
|
||||||
{ key: 'drum', label: '战鼓配置' }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 冠军Logo配置
|
// 冠军Logo配置
|
||||||
@@ -1011,18 +843,11 @@ onMounted(async () => {
|
|||||||
localDisplayConfig.value.crownPosition.top = '-100px';
|
localDisplayConfig.value.crownPosition.top = '-100px';
|
||||||
}
|
}
|
||||||
localBattleEndTime.value = { ...battleEndTime };
|
localBattleEndTime.value = { ...battleEndTime };
|
||||||
localDrumConfig.value = { ...drumConfig };
|
|
||||||
|
|
||||||
// 初始化冠军Logo配置
|
// 初始化冠军Logo配置
|
||||||
if (displayConfig.championLogos) {
|
if (displayConfig.championLogos) {
|
||||||
championLogos.value = { ...displayConfig.championLogos };
|
championLogos.value = { ...displayConfig.championLogos };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新处理强拍位置
|
|
||||||
if (localDrumConfig.value.pattern && localDrumConfig.value.pattern.strongBeats) {
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr =
|
|
||||||
localDrumConfig.value.pattern.strongBeats.join(',') || '1,4';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化数据失败:', error);
|
console.error('初始化数据失败:', error);
|
||||||
}
|
}
|
||||||
@@ -1138,13 +963,6 @@ const handleRefreshData = () => {
|
|||||||
localBonusRules.value = [...bonusRules];
|
localBonusRules.value = [...bonusRules];
|
||||||
localDisplayConfig.value = { ...displayConfig };
|
localDisplayConfig.value = { ...displayConfig };
|
||||||
localBattleEndTime.value = { ...battleEndTime };
|
localBattleEndTime.value = { ...battleEndTime };
|
||||||
localDrumConfig.value = { ...drumConfig };
|
|
||||||
|
|
||||||
// 重新处理强拍位置
|
|
||||||
if (localDrumConfig.value.pattern && localDrumConfig.value.pattern.strongBeats) {
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr =
|
|
||||||
localDrumConfig.value.pattern.strongBeats.join(',') || '1,4';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
alert('数据刷新成功!');
|
alert('数据刷新成功!');
|
||||||
@@ -1164,16 +982,6 @@ const localTeamRankings = ref([...teamRankings]);
|
|||||||
const localBonusRules = ref([...bonusRules]);
|
const localBonusRules = ref([...bonusRules]);
|
||||||
const localDisplayConfig = ref({ ...displayConfig });
|
const localDisplayConfig = ref({ ...displayConfig });
|
||||||
const localBattleEndTime = ref({ ...battleEndTime });
|
const localBattleEndTime = ref({ ...battleEndTime });
|
||||||
// 初始化本地战鼓配置副本
|
|
||||||
const localDrumConfig = ref({ ...drumConfig });
|
|
||||||
// 添加强拍位置的字符串表示,用于输入框
|
|
||||||
if (localDrumConfig.value.pattern && localDrumConfig.value.pattern.strongBeats) {
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr = localDrumConfig.value.pattern.strongBeats.join(',') || '1,4';
|
|
||||||
} else {
|
|
||||||
localDrumConfig.value.pattern = localDrumConfig.value.pattern || {};
|
|
||||||
localDrumConfig.value.pattern.strongBeats = [1, 4];
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr = '1,4';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组件挂载时初始化数据
|
// 组件挂载时初始化数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
@@ -1185,36 +993,12 @@ onMounted(async () => {
|
|||||||
localBonusRules.value = [...bonusRules];
|
localBonusRules.value = [...bonusRules];
|
||||||
localDisplayConfig.value = { ...displayConfig };
|
localDisplayConfig.value = { ...displayConfig };
|
||||||
localBattleEndTime.value = { ...battleEndTime };
|
localBattleEndTime.value = { ...battleEndTime };
|
||||||
localDrumConfig.value = { ...drumConfig };
|
|
||||||
|
|
||||||
// 重新处理强拍位置
|
|
||||||
if (localDrumConfig.value.pattern && localDrumConfig.value.pattern.strongBeats) {
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr =
|
|
||||||
localDrumConfig.value.pattern.strongBeats.join(',') || '1,4';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化数据失败:', error);
|
console.error('初始化数据失败:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新强拍位置数组
|
|
||||||
const updateStrongBeats = () => {
|
|
||||||
try {
|
|
||||||
const beatsStr = localDrumConfig.value.pattern.strongBeatsStr;
|
|
||||||
if (!beatsStr) {
|
|
||||||
localDrumConfig.value.pattern.strongBeats = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const beats = beatsStr.split(',')
|
|
||||||
.map(beat => parseInt(beat.trim()))
|
|
||||||
.filter(beat => !isNaN(beat) && beat > 0 && beat <= 8);
|
|
||||||
localDrumConfig.value.pattern.strongBeats = beats;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('更新强拍位置失败:', error);
|
|
||||||
localDrumConfig.value.pattern.strongBeats = [1, 4];
|
|
||||||
localDrumConfig.value.pattern.strongBeatsStr = '1,4';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 对话框状态
|
// 对话框状态
|
||||||
const showAddIndividual = ref(false);
|
const showAddIndividual = ref(false);
|
||||||
@@ -1326,12 +1110,6 @@ const saveData = async () => {
|
|||||||
localIndividualRankings.value.sort((a, b) => b.score - a.score);
|
localIndividualRankings.value.sort((a, b) => b.score - a.score);
|
||||||
localTeamRankings.value.sort((a, b) => b.totalScore - a.totalScore);
|
localTeamRankings.value.sort((a, b) => b.totalScore - a.totalScore);
|
||||||
|
|
||||||
// 保存战鼓配置前,确保强拍位置数组是最新的
|
|
||||||
updateStrongBeats();
|
|
||||||
// 移除临时的字符串表示,避免保存到配置中
|
|
||||||
const configToSave = { ...localDrumConfig.value };
|
|
||||||
delete configToSave.pattern.strongBeatsStr;
|
|
||||||
|
|
||||||
// 导入必要的配置服务函数
|
// 导入必要的配置服务函数
|
||||||
const { readConfig, writeConfig } = await import('../services/configService');
|
const { readConfig, writeConfig } = await import('../services/configService');
|
||||||
|
|
||||||
@@ -1346,7 +1124,6 @@ const saveData = async () => {
|
|||||||
// 保存冠军Logo配置
|
// 保存冠军Logo配置
|
||||||
currentConfig.displayConfig.championLogos = championLogos.value;
|
currentConfig.displayConfig.championLogos = championLogos.value;
|
||||||
currentConfig.battleEndTime = localBattleEndTime.value;
|
currentConfig.battleEndTime = localBattleEndTime.value;
|
||||||
currentConfig.drumConfig = configToSave;
|
|
||||||
|
|
||||||
// 一次性保存所有配置
|
// 一次性保存所有配置
|
||||||
const result = await writeConfig(currentConfig);
|
const result = await writeConfig(currentConfig);
|
||||||
|
|||||||
@@ -7,20 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 第二部分:战鼓动画(浮动并支持拖放) -->
|
|
||||||
<section v-if="localDisplayConfig.showDrum" class="drums-section card-game" @mousedown="startDrag"
|
|
||||||
@click="handleDrumClick" :style="{ left: drumsPosition.x + 'px', top: drumsPosition.y + 'px' }">
|
|
||||||
<div class="drums-container">
|
|
||||||
<!-- 战鼓动画在上面 -->
|
|
||||||
<div class="drums-animation">
|
|
||||||
<div class="drum glow-border" :class="{ beating: isBeating }">🥁</div>
|
|
||||||
<div class="drum" :class="{ beating: isBeating }">🥁</div>
|
|
||||||
<div class="trophy" style="font-size: 2.5rem; filter: drop-shadow(0 0 10px var(--gold-primary));">🏆</div>
|
|
||||||
<div class="drum" :class="{ beating: isBeating }">🥁</div>
|
|
||||||
<div class="drum" :class="{ beating: isBeating }">🥁</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- 任务设置模块 -->
|
<!-- 任务设置模块 -->
|
||||||
<section class="task-settings-section card-game">
|
<section class="task-settings-section card-game">
|
||||||
@@ -224,7 +211,6 @@ import {
|
|||||||
bonusRules,
|
bonusRules,
|
||||||
displayConfig,
|
displayConfig,
|
||||||
battleEndTime,
|
battleEndTime,
|
||||||
drumConfig,
|
|
||||||
initializeData
|
initializeData
|
||||||
} from '../data/mockData.js';
|
} from '../data/mockData.js';
|
||||||
import { readConfig } from '../services/configService.js';
|
import { readConfig } from '../services/configService.js';
|
||||||
@@ -692,17 +678,7 @@ const hours = ref(0);
|
|||||||
const minutes = ref(0);
|
const minutes = ref(0);
|
||||||
const seconds = ref(0);
|
const seconds = ref(0);
|
||||||
|
|
||||||
// 战鼓动画状态
|
|
||||||
const isBeating = ref(false);
|
|
||||||
let beatInterval = null;
|
|
||||||
let countdownInterval = null;
|
let countdownInterval = null;
|
||||||
|
|
||||||
// 音频上下文和战鼓音效
|
|
||||||
let audioContext = null;
|
|
||||||
const isPlayingSound = ref(false);
|
|
||||||
|
|
||||||
// 战鼓位置状态
|
|
||||||
const drumsPosition = ref({ x: 20, y: 20 });
|
|
||||||
// 倒计时位置状态已移除,直接在模板中使用固定位置
|
// 倒计时位置状态已移除,直接在模板中使用固定位置
|
||||||
// 奖金设置模块位置状态 - 使用reactive存储实际定位值
|
// 奖金设置模块位置状态 - 使用reactive存储实际定位值
|
||||||
const bonusPosition = reactive({ x: 'auto', y: 'auto' });
|
const bonusPosition = reactive({ x: 'auto', y: 'auto' });
|
||||||
@@ -726,13 +702,7 @@ function throttle(func, limit) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始拖动战鼓
|
|
||||||
const startDrag = (e) => {
|
|
||||||
isDragging = true;
|
|
||||||
dragOffset.x = e.clientX - drumsPosition.value.x;
|
|
||||||
dragOffset.y = e.clientY - drumsPosition.value.y;
|
|
||||||
e.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 开始拖动奖金模块(鼠标事件)
|
// 开始拖动奖金模块(鼠标事件)
|
||||||
const startBonusDrag = (e) => {
|
const startBonusDrag = (e) => {
|
||||||
@@ -792,10 +762,6 @@ const endTouch = (e) => {
|
|||||||
|
|
||||||
// 优化的拖动函数 - 使用节流减少更新频率(鼠标事件)
|
// 优化的拖动函数 - 使用节流减少更新频率(鼠标事件)
|
||||||
const drag = throttle((e) => {
|
const drag = throttle((e) => {
|
||||||
if (isDragging) {
|
|
||||||
drumsPosition.value.x = e.clientX - dragOffset.x;
|
|
||||||
drumsPosition.value.y = e.clientY - dragOffset.y;
|
|
||||||
}
|
|
||||||
if (isBonusDragging) {
|
if (isBonusDragging) {
|
||||||
// 计算新的位置
|
// 计算新的位置
|
||||||
const newX = e.clientX - bonusDragOffset.x;
|
const newX = e.clientX - bonusDragOffset.x;
|
||||||
@@ -881,237 +847,11 @@ const calculateCountdown = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化音频上下文
|
|
||||||
const initAudioContext = () => {
|
|
||||||
if (!audioContext) {
|
|
||||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 音频缓存,用于存储加载的MP3文件
|
|
||||||
const audioBufferCache = ref({});
|
|
||||||
|
|
||||||
// 加载MP3文件到音频缓冲区
|
|
||||||
const loadAudioFile = async (filePath) => {
|
|
||||||
try {
|
|
||||||
// 检查是否已缓存
|
|
||||||
if (audioBufferCache.value[filePath]) {
|
|
||||||
return audioBufferCache.value[filePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载音频文件
|
|
||||||
const response = await fetch(filePath);
|
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
|
||||||
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
||||||
|
|
||||||
// 缓存音频缓冲区
|
|
||||||
audioBufferCache.value[filePath] = audioBuffer;
|
|
||||||
return audioBuffer;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载音频文件失败:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 播放战鼓音效
|
|
||||||
const playDrumSound = async (isStrongBeat = false) => {
|
|
||||||
// 检查是否启用声音播放
|
|
||||||
if (!audioContext || isPlayingSound.value || drumConfig?.sound?.enabled === false) return;
|
|
||||||
|
|
||||||
isPlayingSound.value = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 使用配置的音效参数
|
|
||||||
const soundConfig = drumConfig?.sound || {};
|
|
||||||
const patternConfig = drumConfig?.pattern || {};
|
|
||||||
|
|
||||||
// 检查是否配置了MP3文件路径
|
|
||||||
if (soundConfig.soundSrc && soundConfig.soundSrc.trim() !== '') {
|
|
||||||
// 使用MP3文件播放
|
|
||||||
const audioBuffer = await loadAudioFile(soundConfig.soundSrc);
|
|
||||||
|
|
||||||
if (audioBuffer) {
|
|
||||||
// 创建音频源节点
|
|
||||||
const source = audioContext.createBufferSource();
|
|
||||||
const gainNode = audioContext.createGain();
|
|
||||||
|
|
||||||
// 连接节点
|
|
||||||
source.buffer = audioBuffer;
|
|
||||||
source.connect(gainNode);
|
|
||||||
gainNode.connect(audioContext.destination);
|
|
||||||
|
|
||||||
// 设置音量,支持强拍音量增强
|
|
||||||
const baseVolume = soundConfig.volume || 1.0;
|
|
||||||
const accentMultiplier = patternConfig.accentMultiplier || 1.2;
|
|
||||||
const volume = isStrongBeat ? baseVolume * accentMultiplier : baseVolume;
|
|
||||||
gainNode.gain.value = volume;
|
|
||||||
|
|
||||||
// 播放声音
|
|
||||||
source.start(0);
|
|
||||||
|
|
||||||
// 设置完成后重置播放状态
|
|
||||||
setTimeout(() => {
|
|
||||||
isPlayingSound.value = false;
|
|
||||||
}, audioBuffer.duration * 1000 + 100);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有配置MP3文件或加载失败,回退到合成音效
|
|
||||||
// 创建振荡器节点
|
|
||||||
const oscillator = audioContext.createOscillator();
|
|
||||||
const gainNode = audioContext.createGain();
|
|
||||||
|
|
||||||
// 连接节点
|
|
||||||
oscillator.connect(gainNode);
|
|
||||||
gainNode.connect(audioContext.destination);
|
|
||||||
|
|
||||||
// 设置战鼓音效参数,支持强拍
|
|
||||||
const baseVolume = soundConfig.volume || 1.0;
|
|
||||||
// 使用pattern配置中的强拍音量倍数
|
|
||||||
const accentMultiplier = patternConfig.accentMultiplier || 1.2;
|
|
||||||
const volume = isStrongBeat ? baseVolume * accentMultiplier : baseVolume;
|
|
||||||
|
|
||||||
// 使用soundConfig中的type1
|
|
||||||
oscillator.type = soundConfig.type1 || 'sine';
|
|
||||||
|
|
||||||
// 基础频率,支持强拍频率偏移
|
|
||||||
const baseFrequency = soundConfig.frequency1 || 150;
|
|
||||||
const frequencyOffset = isStrongBeat ? (patternConfig.accentFrequencyOffset || 0) / 100 : 0;
|
|
||||||
const actualFrequency = baseFrequency * (1 + frequencyOffset);
|
|
||||||
|
|
||||||
oscillator.frequency.setValueAtTime(actualFrequency, audioContext.currentTime);
|
|
||||||
// 频率渐变
|
|
||||||
oscillator.frequency.exponentialRampToValueAtTime(actualFrequency * 0.5, audioContext.currentTime + 0.1);
|
|
||||||
|
|
||||||
// 设置音量包络
|
|
||||||
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
|
|
||||||
gainNode.gain.linearRampToValueAtTime(volume, audioContext.currentTime + (soundConfig.attackTime || 0.01));
|
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + (soundConfig.decayTime || 0.3));
|
|
||||||
|
|
||||||
// 播放声音
|
|
||||||
oscillator.start();
|
|
||||||
oscillator.stop(audioContext.currentTime + (soundConfig.decayTime || 0.3));
|
|
||||||
|
|
||||||
// 双音调效果 - 始终使用
|
|
||||||
const oscillator2 = audioContext.createOscillator();
|
|
||||||
const gainNode2 = audioContext.createGain();
|
|
||||||
|
|
||||||
oscillator2.connect(gainNode2);
|
|
||||||
gainNode2.connect(audioContext.destination);
|
|
||||||
|
|
||||||
oscillator2.type = soundConfig.type2 || 'triangle';
|
|
||||||
oscillator2.frequency.setValueAtTime(soundConfig.frequency2 || 100, audioContext.currentTime);
|
|
||||||
|
|
||||||
gainNode2.gain.setValueAtTime(0, audioContext.currentTime);
|
|
||||||
gainNode2.gain.linearRampToValueAtTime(volume * 0.8, audioContext.currentTime + (soundConfig.attackTime || 0.01));
|
|
||||||
gainNode2.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + (soundConfig.decayTime || 0.3) + 0.2);
|
|
||||||
|
|
||||||
oscillator2.start();
|
|
||||||
oscillator2.stop(audioContext.currentTime + (soundConfig.decayTime || 0.3) + 0.2);
|
|
||||||
|
|
||||||
// 设置完成后重置播放状态
|
|
||||||
setTimeout(() => {
|
|
||||||
isPlayingSound.value = false;
|
|
||||||
}, (soundConfig.decayTime || 0.3) * 1000 + 150);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('播放战鼓音效出错:', error);
|
|
||||||
isPlayingSound.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 修改相关函数以支持异步
|
|
||||||
const handleDrumClick = async () => {
|
|
||||||
// 如果音频上下文未初始化,初始化它
|
|
||||||
if (!audioContext) {
|
|
||||||
initAudioContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果音频上下文被暂停,恢复它
|
|
||||||
if (audioContext.state === 'suspended') {
|
|
||||||
audioContext.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 触发战鼓动画和音效,使用配置的点击效果
|
|
||||||
const animationConfig = drumConfig?.animation || {};
|
|
||||||
isBeating.value = true;
|
|
||||||
await playDrumSound(true); // 点击总是强拍
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
isBeating.value = false;
|
|
||||||
}, animationConfig.clickBeatDuration || 250);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 战鼓动画效果
|
|
||||||
const startDrumAnimation = () => {
|
|
||||||
// 检查是否显示战鼓
|
|
||||||
if (drumConfig?.showDrum === false) return;
|
|
||||||
|
|
||||||
// 使用配置的动画和节拍参数
|
|
||||||
const animationConfig = drumConfig?.animation || {};
|
|
||||||
const patternConfig = drumConfig?.pattern || {};
|
|
||||||
|
|
||||||
// 检查是否启用动画
|
|
||||||
if (animationConfig.enabled === false) return;
|
|
||||||
|
|
||||||
let beatCount = 0;
|
|
||||||
// 使用配置的节拍间隔
|
|
||||||
const interval = animationConfig.beatInterval || 200;
|
|
||||||
|
|
||||||
beatInterval = setInterval(() => {
|
|
||||||
beatCount++;
|
|
||||||
// 使用配置的节拍模式和总拍数
|
|
||||||
const totalBeats = patternConfig.totalBeats || 4;
|
|
||||||
const currentBeat = ((beatCount - 1) % totalBeats) + 1;
|
|
||||||
|
|
||||||
// 根据节拍模式确定是否是强拍
|
|
||||||
const strongBeats = patternConfig.strongBeats || [1, 4];
|
|
||||||
const isStrongBeat = strongBeats.includes(currentBeat);
|
|
||||||
|
|
||||||
// 执行动画和音效
|
|
||||||
isBeating.value = true;
|
|
||||||
|
|
||||||
// 根据是否是强拍播放音效
|
|
||||||
playDrumSound(isStrongBeat);
|
|
||||||
|
|
||||||
// 设置CSS变量,支持强拍动画增强
|
|
||||||
const drums = document.querySelectorAll('.drum');
|
|
||||||
drums.forEach(drum => {
|
|
||||||
// 使用配置的动画参数
|
|
||||||
drum.style.setProperty('--drum-scale', isStrongBeat ?
|
|
||||||
(animationConfig.beatScale || 1.3) * (1 + (patternConfig.accentAnimation || 0) / 100) :
|
|
||||||
(animationConfig.beatScale || 1.3));
|
|
||||||
drum.style.setProperty('--drum-translate-y', isStrongBeat ?
|
|
||||||
`${(animationConfig.beatTranslateY || -15) * (1 + (patternConfig.accentAnimation || 0) / 100)}px` :
|
|
||||||
`${animationConfig.beatTranslateY || -15}px`);
|
|
||||||
drum.style.setProperty('--drum-rotate', `${animationConfig.beatRotate || 5}deg`);
|
|
||||||
drum.style.setProperty('--drum-brightness', isStrongBeat ? '1.4' : '1.3');
|
|
||||||
drum.style.setProperty('--drum-saturation', isStrongBeat ? '1.3' : '1.2');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 根据节拍类型设置持续时间
|
|
||||||
const beatDuration = isStrongBeat
|
|
||||||
? (animationConfig.beatDuration || 150)
|
|
||||||
: (animationConfig.beatDuration || 100);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
isBeating.value = false;
|
|
||||||
}, beatDuration);
|
|
||||||
}, interval);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 已移至文件中异步版本的handleDrumClick函数
|
|
||||||
|
|
||||||
// 跳转到管理员页面
|
// 跳转到管理员页面
|
||||||
const goToAdmin = () => {
|
const goToAdmin = () => {
|
||||||
router.push('/admin');
|
router.push('/admin');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听窗口点击事件,用于用户交互后初始化音频上下文
|
|
||||||
document.addEventListener('click', initAudioContext, { once: true });
|
|
||||||
document.addEventListener('touchstart', initAudioContext, { once: true });
|
|
||||||
|
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
// 计算并设置排名明细区域的最小高度,使其底部与视口对齐
|
// 计算并设置排名明细区域的最小高度,使其底部与视口对齐
|
||||||
const rankingsSection = document.querySelector('.rankings-section');
|
const rankingsSection = document.querySelector('.rankings-section');
|
||||||
@@ -1156,7 +896,6 @@ onMounted(async () => {
|
|||||||
|
|
||||||
calculateCountdown();
|
calculateCountdown();
|
||||||
countdownInterval = setInterval(calculateCountdown, 10); // 改为10ms更新一次以显示毫秒
|
countdownInterval = setInterval(calculateCountdown, 10); // 改为10ms更新一次以显示毫秒
|
||||||
startDrumAnimation();
|
|
||||||
// 监听窗口大小变化,确保排名明细与底部对齐
|
// 监听窗口大小变化,确保排名明细与底部对齐
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('resize', handleResize);
|
||||||
handleResize(); // 初始调整
|
handleResize(); // 初始调整
|
||||||
@@ -1187,7 +926,6 @@ const handleDisplayConfigChange = () => {
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (countdownInterval) clearInterval(countdownInterval);
|
if (countdownInterval) clearInterval(countdownInterval);
|
||||||
if (beatInterval) clearInterval(beatInterval);
|
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('resize', handleResize);
|
||||||
|
|
||||||
// 移除拖放相关的事件监听
|
// 移除拖放相关的事件监听
|
||||||
@@ -1198,12 +936,6 @@ onUnmounted(() => {
|
|||||||
document.removeEventListener('touchmove', touchMove);
|
document.removeEventListener('touchmove', touchMove);
|
||||||
document.removeEventListener('touchend', endTouch);
|
document.removeEventListener('touchend', endTouch);
|
||||||
document.removeEventListener('touchcancel', endTouch);
|
document.removeEventListener('touchcancel', endTouch);
|
||||||
|
|
||||||
// 清理音频资源
|
|
||||||
if (audioContext) {
|
|
||||||
audioContext.close();
|
|
||||||
audioContext = null;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -1725,97 +1457,7 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 战鼓部分 - 浮动并支持拖放 */
|
|
||||||
.drums-section {
|
|
||||||
position: fixed;
|
|
||||||
left: 20px;
|
|
||||||
top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
background: rgba(255, 255, 255, 0.95);
|
|
||||||
border-radius: 20px;
|
|
||||||
cursor: move;
|
|
||||||
z-index: 1000;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
||||||
transition: box-shadow 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drums-section:hover {
|
|
||||||
box-shadow: 0 6px 30px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
.drums-section:active {
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.drums-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drums-animation {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drum {
|
|
||||||
transition: transform 0.1s ease, filter 0.1s ease;
|
|
||||||
animation: idlePulse 2s infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drum.beating {
|
|
||||||
/* 使用CSS变量方便动态调整 */
|
|
||||||
--drum-scale: 1.3;
|
|
||||||
--drum-translate-y: -15px;
|
|
||||||
--drum-rotate: 5deg;
|
|
||||||
--drum-brightness: 1.3;
|
|
||||||
--drum-saturation: 1.2;
|
|
||||||
|
|
||||||
transform: scale(var(--drum-scale)) translateY(var(--drum-translate-y)) rotate(var(--drum-rotate));
|
|
||||||
filter: brightness(var(--drum-brightness)) saturate(var(--drum-saturation));
|
|
||||||
animation: drumBeat 0.1s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 战鼓闲置时的轻微脉动动画 */
|
|
||||||
@keyframes idlePulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 增强跳动效果的关键帧动画 */
|
|
||||||
@keyframes drumBeat {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: scale(var(--drum-scale, 1.3)) translateY(var(--drum-translate-y, -15px)) rotate(var(--drum-rotate, 5deg));
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.trophy {
|
|
||||||
animation: bounce 1s infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bounce {
|
|
||||||
from {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
transform: translateY(-10px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮样式 */
|
/* 按钮样式 */
|
||||||
.btn-game-secondary {
|
.btn-game-secondary {
|
||||||
@@ -2320,11 +1962,7 @@ onUnmounted(() => {
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 战鼓部分调整 */
|
|
||||||
.drums-section {
|
|
||||||
transform: scale(0.8);
|
|
||||||
/* 缩小战鼓元素 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. 倒计时模块调整 - 移至冠军战区上方,缩小时间显示为一行 */
|
/* 2. 倒计时模块调整 - 移至冠军战区上方,缩小时间显示为一行 */
|
||||||
.timer-float {
|
.timer-float {
|
||||||
|
|||||||
Reference in New Issue
Block a user