feat:部分功能优化
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 2m1s
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 2m1s
This commit is contained in:
parent
bfde0250e3
commit
e3f81d4f7b
519
package-lock.json
generated
519
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"@bddh/starling-realtime-client": "^2.0.9",
|
||||
"crypto-js": "^4.2.0",
|
||||
"element-plus": "^2.9.7",
|
||||
"opencc-js": "^1.4.0",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
@ -2010,24 +2011,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
|
||||
@ -2045,24 +2028,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
|
||||
@ -2080,24 +2045,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
|
||||
@ -4546,6 +4493,12 @@
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/opencc-js": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/opencc-js/-/opencc-js-1.4.0.tgz",
|
||||
"integrity": "sha512-SEb4huI5+lT4CFPA4sgs+NAOOgpcmdHZ+vYxhRLR1bQWIt6VRwpFPjWgTJAWAg1MviDcXTBe5zVoUOVxVxNK8w==",
|
||||
"license": "MIT AND Apache-2.0"
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
|
||||
@ -5258,420 +5211,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
|
||||
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/android-arm": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
|
||||
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/android-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
|
||||
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
|
||||
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
|
||||
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
|
||||
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
|
||||
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
|
||||
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
|
||||
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
|
||||
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/@vitest/mocker": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-4.1.8.tgz",
|
||||
@ -5699,50 +5238,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/esbuild": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.0.tgz",
|
||||
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.28.0",
|
||||
"@esbuild/android-arm": "0.28.0",
|
||||
"@esbuild/android-arm64": "0.28.0",
|
||||
"@esbuild/android-x64": "0.28.0",
|
||||
"@esbuild/darwin-arm64": "0.28.0",
|
||||
"@esbuild/darwin-x64": "0.28.0",
|
||||
"@esbuild/freebsd-arm64": "0.28.0",
|
||||
"@esbuild/freebsd-x64": "0.28.0",
|
||||
"@esbuild/linux-arm": "0.28.0",
|
||||
"@esbuild/linux-arm64": "0.28.0",
|
||||
"@esbuild/linux-ia32": "0.28.0",
|
||||
"@esbuild/linux-loong64": "0.28.0",
|
||||
"@esbuild/linux-mips64el": "0.28.0",
|
||||
"@esbuild/linux-ppc64": "0.28.0",
|
||||
"@esbuild/linux-riscv64": "0.28.0",
|
||||
"@esbuild/linux-s390x": "0.28.0",
|
||||
"@esbuild/linux-x64": "0.28.0",
|
||||
"@esbuild/netbsd-arm64": "0.28.0",
|
||||
"@esbuild/netbsd-x64": "0.28.0",
|
||||
"@esbuild/openbsd-arm64": "0.28.0",
|
||||
"@esbuild/openbsd-x64": "0.28.0",
|
||||
"@esbuild/openharmony-arm64": "0.28.0",
|
||||
"@esbuild/sunos-x64": "0.28.0",
|
||||
"@esbuild/win32-arm64": "0.28.0",
|
||||
"@esbuild/win32-ia32": "0.28.0",
|
||||
"@esbuild/win32-x64": "0.28.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/estree-walker": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
"@bddh/starling-realtime-client": "^2.0.9",
|
||||
"crypto-js": "^4.2.0",
|
||||
"element-plus": "^2.9.7",
|
||||
"opencc-js": "^1.4.0",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
|
||||
764
src/App.vue
764
src/App.vue
File diff suppressed because it is too large
Load Diff
BIN
src/assets/avatar.png
Normal file
BIN
src/assets/avatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 281 KiB |
@ -1,10 +1,8 @@
|
||||
<template>
|
||||
<div class="subtitle-panel">
|
||||
<div
|
||||
class="subtitle-content ai-only-mode"
|
||||
ref="scrollContainerRef"
|
||||
>
|
||||
<div v-if="aiSubtitle" class="ai-subtitle-bar" ref="aiSubtitleBarRef" @scroll="handleScroll">
|
||||
<!-- AI字幕 -->
|
||||
<div class="subtitle-content ai-only-mode" ref="scrollContainerRef">
|
||||
<div v-if="aiSubtitle" class="ai-subtitle-bar" ref="aiSubtitleBarRef">
|
||||
<div
|
||||
class="ai-subtitle-text"
|
||||
ref="aiSubtitleTextRef"
|
||||
@ -12,6 +10,24 @@
|
||||
>
|
||||
{{ aiSubtitle }}
|
||||
</div>
|
||||
<!-- 滚动指示器 -->
|
||||
<div
|
||||
v-if="aiTextOverflow"
|
||||
class="scroll-hint"
|
||||
@click="scrollAIToBottom"
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="14"
|
||||
height="14"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="subtitle-placeholder">
|
||||
<svg
|
||||
@ -27,54 +43,138 @@
|
||||
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
||||
/>
|
||||
</svg>
|
||||
等待AI回复...
|
||||
等待AI回覆...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, watch, nextTick, onMounted} from "vue";
|
||||
import { ref, watch, nextTick, onMounted, onBeforeUnmount } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
aiSubtitle: string;
|
||||
}>();
|
||||
|
||||
// 滚动容器ref:指向 .subtitle-content(实际可滚动容器)
|
||||
const scrollContainerRef = ref<HTMLElement | null>(null);
|
||||
const aiSubtitleBarRef = ref<HTMLElement | null>(null);
|
||||
const aiSubtitleTextRef = ref<HTMLElement | null>(null);
|
||||
|
||||
// ===== AI字幕自适应字号 =====
|
||||
const aiFontSize = ref(18);
|
||||
const isUserScrolling = ref(false);
|
||||
const aiTextOverflow = ref(false);
|
||||
|
||||
// 检测是否为 1440×2560 目标分辨率
|
||||
const isTargetResolution = ref(false);
|
||||
|
||||
/**
|
||||
* 检测当前视口是否为 1440×2560 分辨率
|
||||
* 使用 window.innerWidth 和 innerHeight 精确匹配
|
||||
*/
|
||||
const checkResolution = () => {
|
||||
const TARGET_WIDTH = 1440;
|
||||
const TARGET_HEIGHT = 2560;
|
||||
console.log("------------", window.innerWidth, window.innerHeight);
|
||||
isTargetResolution.value =
|
||||
(window.innerWidth === TARGET_WIDTH &&
|
||||
window.innerHeight === TARGET_HEIGHT) ||
|
||||
(window.innerWidth > 1000 && window.innerHeight > 1680);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取目标分辨率下的字号基准值
|
||||
* 1440×2560 下使用更大的字号以确保清晰可读
|
||||
*/
|
||||
const getTargetFontSizeBase = (textLength: number): number => {
|
||||
if (textLength <= 50) return 36;
|
||||
if (textLength <= 100) return 32;
|
||||
if (textLength <= 200) return 28;
|
||||
if (textLength <= 400) return 24;
|
||||
return 22;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取普通分辨率下的字号基准值
|
||||
*/
|
||||
const getNormalFontSizeBase = (textLength: number): number => {
|
||||
if (textLength <= 50) return 18;
|
||||
if (textLength <= 100) return 16;
|
||||
if (textLength <= 200) return 14;
|
||||
if (textLength <= 400) return 13;
|
||||
return 12;
|
||||
};
|
||||
|
||||
// 计算AI字幕字号:根据分辨率和文本长度动态调整
|
||||
const computeAIFontSize = () => {
|
||||
const text = props.aiSubtitle;
|
||||
console.log("------------", text);
|
||||
if (!text) {
|
||||
aiFontSize.value = 18;
|
||||
aiFontSize.value = isTargetResolution.value ? 36 : 18;
|
||||
return;
|
||||
}
|
||||
|
||||
const len = text.length;
|
||||
if (len <= 50) aiFontSize.value = 18;
|
||||
else if (len <= 100) aiFontSize.value = 16;
|
||||
else if (len <= 200) aiFontSize.value = 14;
|
||||
else if (len <= 400) aiFontSize.value = 13;
|
||||
else aiFontSize.value = 12;
|
||||
aiFontSize.value = isTargetResolution.value
|
||||
? getTargetFontSizeBase(len)
|
||||
: getNormalFontSizeBase(len);
|
||||
};
|
||||
|
||||
const handleScroll = () => {
|
||||
if (!aiSubtitleBarRef.value) return;
|
||||
const { scrollTop, scrollHeight, clientHeight } = aiSubtitleBarRef.value;
|
||||
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
||||
isUserScrolling.value = !isAtBottom;
|
||||
// 检测AI字幕是否溢出
|
||||
const checkAIOverflow = () => {
|
||||
nextTick(() => {
|
||||
const bar = aiSubtitleBarRef.value;
|
||||
const textEl = aiSubtitleTextRef.value;
|
||||
if (bar && textEl) {
|
||||
aiTextOverflow.value = textEl.scrollHeight > bar.clientHeight + 4;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const scrollAIToBottom = () => {
|
||||
if (aiSubtitleBarRef.value) {
|
||||
aiSubtitleBarRef.value.scrollTo({
|
||||
top: aiSubtitleBarRef.value.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理视口尺寸变化:重新检测分辨率并更新字号
|
||||
*/
|
||||
const handleResize = () => {
|
||||
const wasTarget = isTargetResolution.value;
|
||||
checkResolution();
|
||||
// 如果分辨率状态变化,重新计算字号
|
||||
if (wasTarget !== isTargetResolution.value) {
|
||||
computeAIFontSize();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 初始检测分辨率
|
||||
checkResolution();
|
||||
computeAIFontSize();
|
||||
// 监听视口尺寸变化
|
||||
window.addEventListener("resize", handleResize);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
});
|
||||
|
||||
// ===== 监听变化 =====
|
||||
|
||||
// AI字幕变化时:自适应字号 + 检测溢出 + 自动滚动
|
||||
watch(
|
||||
() => props.aiSubtitle,
|
||||
() => {
|
||||
computeAIFontSize();
|
||||
checkAIOverflow();
|
||||
// 自动滚动AI字幕到底部
|
||||
nextTick(() => {
|
||||
if (aiSubtitleBarRef.value && !isUserScrolling.value) {
|
||||
if (aiSubtitleBarRef.value) {
|
||||
aiSubtitleBarRef.value.scrollTo({
|
||||
top: aiSubtitleBarRef.value.scrollHeight,
|
||||
behavior: "smooth",
|
||||
@ -92,6 +192,7 @@ watch(
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* ===== 字幕内容 ===== */
|
||||
.subtitle-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
@ -129,16 +230,16 @@ watch(
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* ===== AI字幕 ===== */
|
||||
.ai-only-mode {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.ai-subtitle-bar {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
@ -171,4 +272,64 @@ watch(
|
||||
transition: font-size 0.3s ease;
|
||||
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.scroll-hint {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: rgba(108, 140, 255, 0.3);
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
cursor: pointer;
|
||||
margin: 8px auto 0;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(108, 140, 255, 0.5);
|
||||
transform: translateX(-50%) scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 1440×2560 分辨率专用样式 ===== */
|
||||
@media (min-width: 1000px) and (min-height: 1680px) {
|
||||
.subtitle-placeholder {
|
||||
font-size: 24px;
|
||||
line-height: 1.75;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* AI字幕:字号由 JavaScript 动态控制,此处仅设置辅助样式 */
|
||||
.ai-subtitle-text {
|
||||
line-height: 1.75;
|
||||
letter-spacing: 0.6px;
|
||||
font-weight: 400;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
/* 字幕容器:背景与边框适配大字号 */
|
||||
.ai-subtitle-bar {
|
||||
padding: 18px 24px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(108, 140, 255, 0.12) 0%,
|
||||
rgba(79, 110, 247, 0.06) 100%
|
||||
);
|
||||
border: 1px solid rgba(108, 140, 255, 0.15);
|
||||
}
|
||||
|
||||
/* 滚动指示器:尺寸适配 */
|
||||
.scroll-hint {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,10 +4,9 @@ import RealTimeHuman from "@bddh/starling-realtime-client";
|
||||
import { checkPlayUnMute } from "@/utils/audioUtils";
|
||||
import { SilenceDetector } from "@/utils/SilenceDetector";
|
||||
import { TokenManager } from "@/utils/tokenManager";
|
||||
import type { ChatMessage, SubtitleMode } from "@/types";
|
||||
import type { ChatMessage } from "@/types";
|
||||
|
||||
const DEFAULT_TEXT =
|
||||
"你好!我是皮特教授,欢迎向我提问任何有关电池的问题。";
|
||||
const DEFAULT_TEXT = "你好!我是皮特教授,歡迎向我提問任何有關電池的問題。";
|
||||
const OPENING_TTS_DELAY_MS = 200;
|
||||
const SILENCE_TIMEOUT_MS = 5000;
|
||||
// 最短有效语音时长(秒),低于此时长视为无效输入
|
||||
@ -17,7 +16,15 @@ const BROADCAST_TIMEOUT_MS = 60000;
|
||||
const APPID = "i-sfyrkdr0ubepa";
|
||||
const APP_KEY = "72vpdansbpg8nxjbxzhp";
|
||||
// 打断词列表:识别到这些词时自动打断播报
|
||||
const INTERRUPT_KEYWORDS = ["稍等一下", "停一下", "抱歉打断一下", "不好意思", "对不起", "停", "闭嘴"];
|
||||
const INTERRUPT_KEYWORDS = [
|
||||
"稍等一下",
|
||||
"停一下",
|
||||
"抱歉打断一下",
|
||||
"不好意思",
|
||||
"对不起",
|
||||
"停",
|
||||
"闭嘴",
|
||||
];
|
||||
|
||||
/**
|
||||
* 检测文本是否包含实质内容(去除空白和标点后仍有字符)
|
||||
@ -127,7 +134,6 @@ export function useDigitalHuman(options?: {
|
||||
const isBroadcasting = ref(false);
|
||||
|
||||
// 字幕相关
|
||||
const subtitleMode = ref<SubtitleMode>("ai-only");
|
||||
const currentAISubtitle = ref("");
|
||||
const currentUserSubtitle = ref("");
|
||||
const chatMessages = ref<ChatMessage[]>([]);
|
||||
@ -329,10 +335,14 @@ export function useDigitalHuman(options?: {
|
||||
if (pickPhase.value === "broadcasting") {
|
||||
const hasInterrupt = containsInterruptKeyword(subtitleContent);
|
||||
if (hasInterrupt) {
|
||||
console.info(`[打断词检测] 播报中识别到打断词: "${subtitleContent}",自动打断(仅中断播报,不调用LLM)`);
|
||||
console.info(
|
||||
`[打断词检测] 播报中识别到打断词: "${subtitleContent}",自动打断(仅中断播报,不调用LLM)`,
|
||||
);
|
||||
interrupt();
|
||||
} else {
|
||||
console.info(`[打断词检测] 播报中收到ASR结果: "${subtitleContent}",非打断词,忽略`);
|
||||
console.info(
|
||||
`[打断词检测] 播报中收到ASR结果: "${subtitleContent}",非打断词,忽略`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -348,9 +358,7 @@ export function useDigitalHuman(options?: {
|
||||
if (pickPhase.value === "idle") {
|
||||
// 忽略打断后3秒内到达的延迟ASR结果(避免打断词被当作新输入)
|
||||
if (Date.now() - lastInterruptTime < 3000) {
|
||||
console.info(
|
||||
"[状态机] 打断后延迟到达的ASR结果,忽略",
|
||||
);
|
||||
console.info("[状态机] 打断后延迟到达的ASR结果,忽略");
|
||||
break;
|
||||
}
|
||||
const hasSubstance = hasSubstantialContent(subtitleContent);
|
||||
@ -846,7 +854,6 @@ export function useDigitalHuman(options?: {
|
||||
// 播报状态
|
||||
isBroadcasting,
|
||||
// 字幕
|
||||
subtitleMode,
|
||||
currentAISubtitle,
|
||||
currentUserSubtitle,
|
||||
chatMessages,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { ref } from "vue";
|
||||
import OpenCC from "opencc-js";
|
||||
|
||||
// 火山方舟 Chat Completions API 配置
|
||||
const LLM_API_URL =
|
||||
@ -51,7 +52,7 @@ export function useLLM() {
|
||||
|
||||
const SYSTEM_PROMPT: LLMMessage = {
|
||||
role: "system",
|
||||
content: "你是一个友好的数字人助手,请用简洁自然的语言回答用户的问题。",
|
||||
content: "你是一個友善的數位人助手,請用簡潔自然的語言回答使用者的問題。",
|
||||
};
|
||||
|
||||
const sendToLLM = async (userMessage: string): Promise<string> => {
|
||||
@ -102,7 +103,7 @@ export function useLLM() {
|
||||
|
||||
return aiReply;
|
||||
} catch (err: any) {
|
||||
const errorMsg = err.message || "请求失败";
|
||||
const errorMsg = err.message || "請求失敗";
|
||||
error.value = errorMsg;
|
||||
console.error("LLM请求错误:", err);
|
||||
throw err;
|
||||
@ -143,7 +144,9 @@ export function useLLM() {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const aiReply = data.text || "";
|
||||
// 将简体中文回复转换为繁体中文
|
||||
const rawText = data.text || "";
|
||||
const aiReply = OpenCC.Converter({ from: "cn", to: "tw" })(rawText);
|
||||
|
||||
conversationHistory.value.push({
|
||||
role: "user",
|
||||
@ -157,7 +160,7 @@ export function useLLM() {
|
||||
|
||||
return aiReply;
|
||||
} catch (err: any) {
|
||||
const errorMsg = err.message || "请求失败";
|
||||
const errorMsg = err.message || "請求失敗";
|
||||
error.value = errorMsg;
|
||||
console.error("ChatBase请求错误:", err);
|
||||
throw err;
|
||||
|
||||
@ -5,11 +5,3 @@ export interface ChatMessage {
|
||||
timestamp: number;
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
export type SubtitleMode = 'ai-only' | 'bubble' | 'merged';
|
||||
|
||||
export const SUBTITLE_MODE_LABELS: Record<SubtitleMode, string> = {
|
||||
'ai-only': 'AI字幕',
|
||||
'bubble': '对话气泡',
|
||||
'merged': '合并气泡',
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user