mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
chore: some typescript fixups and update vue and ts version
This commit is contained in:
parent
6ea9370c49
commit
32865edca5
@ -46,8 +46,6 @@ module.exports = {
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
],
|
||||
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/html-self-closing': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
|
||||
@ -60,9 +60,9 @@
|
||||
"terser-webpack-plugin": "^5.0.1",
|
||||
"to-string-loader": "^1.2.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.9.5",
|
||||
"typescript": "5.8.3",
|
||||
"vue-loader": "^17.2.2",
|
||||
"vue-tsc": "^1.8.1",
|
||||
"vue-tsc": "^2.2.10",
|
||||
"webpack": "^5.31.2",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-cli": "^4.6.0",
|
||||
@ -80,7 +80,7 @@
|
||||
"protobufjs": "^6.11.2",
|
||||
"streamsaver": "^2.0.6",
|
||||
"tippy.js": "^6.3.1",
|
||||
"vue": "^3.3.4"
|
||||
"vue": "3.5.16"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
|
||||
339
pnpm-lock.yaml
generated
339
pnpm-lock.yaml
generated
@ -41,8 +41,8 @@ dependencies:
|
||||
specifier: ^6.3.1
|
||||
version: registry.npmmirror.com/tippy.js@6.3.7
|
||||
vue:
|
||||
specifier: ^3.3.4
|
||||
version: registry.npmmirror.com/vue@3.5.13(typescript@4.9.5)
|
||||
specifier: 3.5.16
|
||||
version: registry.npmmirror.com/vue@3.5.16(typescript@5.8.3)
|
||||
|
||||
devDependencies:
|
||||
'@babel/core':
|
||||
@ -101,10 +101,10 @@ devDependencies:
|
||||
version: registry.npmmirror.com/@types/ws@8.18.1
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^5.50.0
|
||||
version: registry.npmmirror.com/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@4.9.5)
|
||||
version: registry.npmmirror.com/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^5.50.0
|
||||
version: registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
version: registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
'@vue/tsconfig':
|
||||
specifier: ^0.1.3
|
||||
version: registry.npmmirror.com/@vue/tsconfig@0.1.3(@types/node@17.0.45)
|
||||
@ -182,16 +182,16 @@ devDependencies:
|
||||
version: registry.npmmirror.com/to-string-loader@1.2.0
|
||||
ts-node:
|
||||
specifier: ^10.7.0
|
||||
version: registry.npmmirror.com/ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)
|
||||
version: registry.npmmirror.com/ts-node@10.9.2(@types/node@17.0.45)(typescript@5.8.3)
|
||||
typescript:
|
||||
specifier: ^4.9.5
|
||||
version: registry.npmmirror.com/typescript@4.9.5
|
||||
specifier: 5.8.3
|
||||
version: registry.npmmirror.com/typescript@5.8.3
|
||||
vue-loader:
|
||||
specifier: ^17.2.2
|
||||
version: registry.npmmirror.com/vue-loader@17.4.2(vue@3.5.13)(webpack@5.99.7)
|
||||
version: registry.npmmirror.com/vue-loader@17.4.2(vue@3.5.16)(webpack@5.99.7)
|
||||
vue-tsc:
|
||||
specifier: ^1.8.1
|
||||
version: registry.npmmirror.com/vue-tsc@1.8.27(typescript@4.9.5)
|
||||
specifier: ^2.2.10
|
||||
version: registry.npmmirror.com/vue-tsc@2.2.10(typescript@5.8.3)
|
||||
webpack:
|
||||
specifier: ^5.31.2
|
||||
version: registry.npmmirror.com/webpack@5.99.7(webpack-cli@4.10.0)
|
||||
@ -285,7 +285,7 @@ packages:
|
||||
version: 7.27.1
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@babel/helper-compilation-targets@7.27.1:
|
||||
@ -362,7 +362,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/traverse': registry.npmmirror.com/@babel/traverse@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -374,7 +374,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/traverse': registry.npmmirror.com/@babel/traverse@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -402,7 +402,7 @@ packages:
|
||||
version: 7.27.1
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@babel/helper-plugin-utils@7.27.1:
|
||||
@ -453,7 +453,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/traverse': registry.npmmirror.com/@babel/traverse@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -485,7 +485,7 @@ packages:
|
||||
dependencies:
|
||||
'@babel/template': registry.npmmirror.com/@babel/template@7.27.1
|
||||
'@babel/traverse': registry.npmmirror.com/@babel/traverse@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -508,6 +508,16 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@babel/parser@7.27.4:
|
||||
resolution: {integrity: sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/parser/-/parser-7.27.4.tgz}
|
||||
name: '@babel/parser'
|
||||
version: 7.27.4
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': registry.npmmirror.com/@babel/types@7.27.3
|
||||
|
||||
registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.22.10):
|
||||
resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz}
|
||||
@ -1568,6 +1578,16 @@ packages:
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': registry.npmmirror.com/@babel/helper-string-parser@7.27.1
|
||||
'@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier@7.27.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@babel/types@7.27.3:
|
||||
resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/types/-/types-7.27.3.tgz}
|
||||
name: '@babel/types'
|
||||
version: 7.27.3
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': registry.npmmirror.com/@babel/helper-string-parser@7.27.1
|
||||
'@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier@7.27.1
|
||||
|
||||
registry.npmmirror.com/@cspotcode/source-map-support@0.8.1:
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz}
|
||||
@ -2297,7 +2317,7 @@ packages:
|
||||
'@types/node': registry.npmmirror.com/@types/node@17.0.45
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@4.9.5):
|
||||
registry.npmmirror.com/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.1)(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.62.0
|
||||
name: '@typescript-eslint/eslint-plugin'
|
||||
@ -2312,23 +2332,23 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': registry.npmmirror.com/@eslint-community/regexpp@4.12.1
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager@5.62.0
|
||||
'@typescript-eslint/type-utils': registry.npmmirror.com/@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/type-utils': registry.npmmirror.com/@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
debug: registry.npmmirror.com/debug@4.4.0
|
||||
eslint: registry.npmmirror.com/eslint@8.57.1
|
||||
graphemer: registry.npmmirror.com/graphemer@1.4.0
|
||||
ignore: registry.npmmirror.com/ignore@5.3.2
|
||||
natural-compare-lite: registry.npmmirror.com/natural-compare-lite@1.4.0
|
||||
semver: registry.npmmirror.com/semver@7.7.1
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@4.9.5)
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@5.8.3)
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.9.5):
|
||||
registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.62.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/parser/5.62.0
|
||||
name: '@typescript-eslint/parser'
|
||||
@ -2343,10 +2363,10 @@ packages:
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager@5.62.0
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@5.62.0
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5)
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)
|
||||
debug: registry.npmmirror.com/debug@4.4.0
|
||||
eslint: registry.npmmirror.com/eslint@8.57.1
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -2361,7 +2381,7 @@ packages:
|
||||
'@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys@5.62.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@4.9.5):
|
||||
registry.npmmirror.com/@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/type-utils/5.62.0
|
||||
name: '@typescript-eslint/type-utils'
|
||||
@ -2374,12 +2394,12 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
debug: registry.npmmirror.com/debug@4.4.0
|
||||
eslint: registry.npmmirror.com/eslint@8.57.1
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@4.9.5)
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@5.8.3)
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -2391,7 +2411,7 @@ packages:
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5):
|
||||
registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/typescript-estree/5.62.0
|
||||
name: '@typescript-eslint/typescript-estree'
|
||||
@ -2409,13 +2429,13 @@ packages:
|
||||
globby: registry.npmmirror.com/globby@11.1.0
|
||||
is-glob: registry.npmmirror.com/is-glob@4.0.3
|
||||
semver: registry.npmmirror.com/semver@7.7.1
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@4.9.5)
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
tsutils: registry.npmmirror.com/tsutils@3.21.0(typescript@5.8.3)
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@4.9.5):
|
||||
registry.npmmirror.com/@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.62.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/utils/5.62.0
|
||||
name: '@typescript-eslint/utils'
|
||||
@ -2429,7 +2449,7 @@ packages:
|
||||
'@types/semver': registry.npmmirror.com/@types/semver@7.7.0
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager@5.62.0
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@5.62.0
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5)
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)
|
||||
eslint: registry.npmmirror.com/eslint@8.57.1
|
||||
eslint-scope: registry.npmmirror.com/eslint-scope@5.1.1
|
||||
semver: registry.npmmirror.com/semver@7.7.1
|
||||
@ -2454,137 +2474,144 @@ packages:
|
||||
version: 1.3.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/language-core@1.11.1:
|
||||
resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/language-core/-/language-core-1.11.1.tgz}
|
||||
registry.npmmirror.com/@volar/language-core@2.4.14:
|
||||
resolution: {integrity: sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.14.tgz}
|
||||
name: '@volar/language-core'
|
||||
version: 1.11.1
|
||||
version: 2.4.14
|
||||
dependencies:
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map@1.11.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map@2.4.14
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/source-map@1.11.1:
|
||||
resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/source-map/-/source-map-1.11.1.tgz}
|
||||
registry.npmmirror.com/@volar/source-map@2.4.14:
|
||||
resolution: {integrity: sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.14.tgz}
|
||||
name: '@volar/source-map'
|
||||
version: 1.11.1
|
||||
dependencies:
|
||||
muggle-string: registry.npmmirror.com/muggle-string@0.3.1
|
||||
version: 2.4.14
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/typescript@1.11.1:
|
||||
resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/typescript/-/typescript-1.11.1.tgz}
|
||||
registry.npmmirror.com/@volar/typescript@2.4.14:
|
||||
resolution: {integrity: sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.14.tgz}
|
||||
name: '@volar/typescript'
|
||||
version: 1.11.1
|
||||
version: 2.4.14
|
||||
dependencies:
|
||||
'@volar/language-core': registry.npmmirror.com/@volar/language-core@1.11.1
|
||||
'@volar/language-core': registry.npmmirror.com/@volar/language-core@2.4.14
|
||||
path-browserify: registry.npmmirror.com/path-browserify@1.0.1
|
||||
vscode-uri: registry.npmmirror.com/vscode-uri@3.1.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@vue/compiler-core@3.5.13:
|
||||
resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/compiler-core@3.5.16:
|
||||
resolution: {integrity: sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.16.tgz}
|
||||
name: '@vue/compiler-core'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@babel/parser': registry.npmmirror.com/@babel/parser@7.27.1
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@babel/parser': registry.npmmirror.com/@babel/parser@7.27.4
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
entities: registry.npmmirror.com/entities@4.5.0
|
||||
estree-walker: registry.npmmirror.com/estree-walker@2.0.2
|
||||
source-map-js: registry.npmmirror.com/source-map-js@1.2.1
|
||||
|
||||
registry.npmmirror.com/@vue/compiler-dom@3.5.13:
|
||||
resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/compiler-dom@3.5.16:
|
||||
resolution: {integrity: sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz}
|
||||
name: '@vue/compiler-dom'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
|
||||
registry.npmmirror.com/@vue/compiler-sfc@3.5.13:
|
||||
resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/compiler-sfc@3.5.16:
|
||||
resolution: {integrity: sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz}
|
||||
name: '@vue/compiler-sfc'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@babel/parser': registry.npmmirror.com/@babel/parser@7.27.1
|
||||
'@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core@3.5.13
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.13
|
||||
'@vue/compiler-ssr': registry.npmmirror.com/@vue/compiler-ssr@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@babel/parser': registry.npmmirror.com/@babel/parser@7.27.4
|
||||
'@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core@3.5.16
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.16
|
||||
'@vue/compiler-ssr': registry.npmmirror.com/@vue/compiler-ssr@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
estree-walker: registry.npmmirror.com/estree-walker@2.0.2
|
||||
magic-string: registry.npmmirror.com/magic-string@0.30.17
|
||||
postcss: registry.npmmirror.com/postcss@8.5.3
|
||||
source-map-js: registry.npmmirror.com/source-map-js@1.2.1
|
||||
|
||||
registry.npmmirror.com/@vue/compiler-ssr@3.5.13:
|
||||
resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/compiler-ssr@3.5.16:
|
||||
resolution: {integrity: sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz}
|
||||
name: '@vue/compiler-ssr'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
|
||||
registry.npmmirror.com/@vue/language-core@1.8.27(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/language-core/-/language-core-1.8.27.tgz}
|
||||
id: registry.npmmirror.com/@vue/language-core/1.8.27
|
||||
registry.npmmirror.com/@vue/compiler-vue2@2.7.16:
|
||||
resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz}
|
||||
name: '@vue/compiler-vue2'
|
||||
version: 2.7.16
|
||||
dependencies:
|
||||
de-indent: registry.npmmirror.com/de-indent@1.0.2
|
||||
he: registry.npmmirror.com/he@1.2.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@vue/language-core@2.2.10(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.10.tgz}
|
||||
id: registry.npmmirror.com/@vue/language-core/2.2.10
|
||||
name: '@vue/language-core'
|
||||
version: 1.8.27
|
||||
version: 2.2.10
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@volar/language-core': registry.npmmirror.com/@volar/language-core@1.11.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map@1.11.1
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
computeds: registry.npmmirror.com/computeds@0.0.1
|
||||
'@volar/language-core': registry.npmmirror.com/@volar/language-core@2.4.14
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.16
|
||||
'@vue/compiler-vue2': registry.npmmirror.com/@vue/compiler-vue2@2.7.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
alien-signals: registry.npmmirror.com/alien-signals@1.0.13
|
||||
minimatch: registry.npmmirror.com/minimatch@9.0.5
|
||||
muggle-string: registry.npmmirror.com/muggle-string@0.3.1
|
||||
muggle-string: registry.npmmirror.com/muggle-string@0.4.1
|
||||
path-browserify: registry.npmmirror.com/path-browserify@1.0.1
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
vue-template-compiler: registry.npmmirror.com/vue-template-compiler@2.7.16
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@vue/reactivity@3.5.13:
|
||||
resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/reactivity@3.5.16:
|
||||
resolution: {integrity: sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.16.tgz}
|
||||
name: '@vue/reactivity'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
|
||||
registry.npmmirror.com/@vue/runtime-core@3.5.13:
|
||||
resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/runtime-core@3.5.16:
|
||||
resolution: {integrity: sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.16.tgz}
|
||||
name: '@vue/runtime-core'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@vue/reactivity': registry.npmmirror.com/@vue/reactivity@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@vue/reactivity': registry.npmmirror.com/@vue/reactivity@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
|
||||
registry.npmmirror.com/@vue/runtime-dom@3.5.13:
|
||||
resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/runtime-dom@3.5.16:
|
||||
resolution: {integrity: sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz}
|
||||
name: '@vue/runtime-dom'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
dependencies:
|
||||
'@vue/reactivity': registry.npmmirror.com/@vue/reactivity@3.5.13
|
||||
'@vue/runtime-core': registry.npmmirror.com/@vue/runtime-core@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
'@vue/reactivity': registry.npmmirror.com/@vue/reactivity@3.5.16
|
||||
'@vue/runtime-core': registry.npmmirror.com/@vue/runtime-core@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
csstype: registry.npmmirror.com/csstype@3.1.3
|
||||
|
||||
registry.npmmirror.com/@vue/server-renderer@3.5.13(vue@3.5.13):
|
||||
resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz}
|
||||
id: registry.npmmirror.com/@vue/server-renderer/3.5.13
|
||||
registry.npmmirror.com/@vue/server-renderer@3.5.16(vue@3.5.16):
|
||||
resolution: {integrity: sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.16.tgz}
|
||||
id: registry.npmmirror.com/@vue/server-renderer/3.5.16
|
||||
name: '@vue/server-renderer'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
peerDependencies:
|
||||
vue: 3.5.13
|
||||
vue: 3.5.16
|
||||
dependencies:
|
||||
'@vue/compiler-ssr': registry.npmmirror.com/@vue/compiler-ssr@3.5.13
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
vue: registry.npmmirror.com/vue@3.5.13(typescript@4.9.5)
|
||||
'@vue/compiler-ssr': registry.npmmirror.com/@vue/compiler-ssr@3.5.16
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
vue: registry.npmmirror.com/vue@3.5.16(typescript@5.8.3)
|
||||
|
||||
registry.npmmirror.com/@vue/shared@3.5.13:
|
||||
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz}
|
||||
registry.npmmirror.com/@vue/shared@3.5.16:
|
||||
resolution: {integrity: sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/shared/-/shared-3.5.16.tgz}
|
||||
name: '@vue/shared'
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
|
||||
registry.npmmirror.com/@vue/tsconfig@0.1.3(@types/node@17.0.45):
|
||||
resolution: {integrity: sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz}
|
||||
@ -2891,6 +2918,12 @@ packages:
|
||||
require-from-string: registry.npmmirror.com/require-from-string@2.0.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/alien-signals@1.0.13:
|
||||
resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz}
|
||||
name: alien-signals
|
||||
version: 1.0.13
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/ansi-align@3.0.1:
|
||||
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-align/-/ansi-align-3.0.1.tgz}
|
||||
name: ansi-align
|
||||
@ -3531,12 +3564,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/computeds@0.0.1:
|
||||
resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/computeds/-/computeds-0.0.1.tgz}
|
||||
name: computeds
|
||||
version: 0.0.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz}
|
||||
name: concat-map
|
||||
@ -4157,7 +4184,7 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
debug: registry.npmmirror.com/debug@3.2.7
|
||||
eslint: registry.npmmirror.com/eslint@8.57.1
|
||||
eslint-import-resolver-node: registry.npmmirror.com/eslint-import-resolver-node@0.3.9
|
||||
@ -4179,7 +4206,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@rtsao/scc': registry.npmmirror.com/@rtsao/scc@1.1.0
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3)
|
||||
array-includes: registry.npmmirror.com/array-includes@3.1.8
|
||||
array.prototype.findlastindex: registry.npmmirror.com/array.prototype.findlastindex@1.2.6
|
||||
array.prototype.flat: registry.npmmirror.com/array.prototype.flat@1.3.3
|
||||
@ -5819,10 +5846,10 @@ packages:
|
||||
version: 2.1.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/muggle-string@0.3.1:
|
||||
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/muggle-string/-/muggle-string-0.3.1.tgz}
|
||||
registry.npmmirror.com/muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz}
|
||||
name: muggle-string
|
||||
version: 0.3.1
|
||||
version: 0.4.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/nanoid@3.3.11:
|
||||
@ -7748,7 +7775,7 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5):
|
||||
registry.npmmirror.com/ts-node@10.9.2(@types/node@17.0.45)(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ts-node/-/ts-node-10.9.2.tgz}
|
||||
id: registry.npmmirror.com/ts-node/10.9.2
|
||||
name: ts-node
|
||||
@ -7777,7 +7804,7 @@ packages:
|
||||
create-require: registry.npmmirror.com/create-require@1.1.1
|
||||
diff: registry.npmmirror.com/diff@4.0.2
|
||||
make-error: registry.npmmirror.com/make-error@1.3.6
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
v8-compile-cache-lib: registry.npmmirror.com/v8-compile-cache-lib@3.0.1
|
||||
yn: registry.npmmirror.com/yn@3.1.1
|
||||
dev: true
|
||||
@ -7799,7 +7826,7 @@ packages:
|
||||
version: 1.14.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/tsutils@3.21.0(typescript@4.9.5):
|
||||
registry.npmmirror.com/tsutils@3.21.0(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz}
|
||||
id: registry.npmmirror.com/tsutils/3.21.0
|
||||
name: tsutils
|
||||
@ -7809,7 +7836,7 @@ packages:
|
||||
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
|
||||
dependencies:
|
||||
tslib: registry.npmmirror.com/tslib@1.14.1
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/type-check@0.4.0:
|
||||
@ -7881,11 +7908,11 @@ packages:
|
||||
reflect.getprototypeof: registry.npmmirror.com/reflect.getprototypeof@1.0.10
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/typescript@4.9.5:
|
||||
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/typescript/-/typescript-4.9.5.tgz}
|
||||
registry.npmmirror.com/typescript@5.8.3:
|
||||
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz}
|
||||
name: typescript
|
||||
version: 4.9.5
|
||||
engines: {node: '>=4.2.0'}
|
||||
version: 5.8.3
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
registry.npmmirror.com/unbox-primitive@1.1.0:
|
||||
@ -8000,6 +8027,12 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vscode-uri@3.1.0:
|
||||
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz}
|
||||
name: vscode-uri
|
||||
version: 3.1.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue-eslint-parser@9.4.3(eslint@8.57.1):
|
||||
resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz}
|
||||
id: registry.npmmirror.com/vue-eslint-parser/9.4.3
|
||||
@ -8021,7 +8054,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue-loader@17.4.2(vue@3.5.13)(webpack@5.99.7):
|
||||
registry.npmmirror.com/vue-loader@17.4.2(vue@3.5.16)(webpack@5.99.7):
|
||||
resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-loader/-/vue-loader-17.4.2.tgz}
|
||||
id: registry.npmmirror.com/vue-loader/17.4.2
|
||||
name: vue-loader
|
||||
@ -8038,52 +8071,42 @@ packages:
|
||||
dependencies:
|
||||
chalk: registry.npmmirror.com/chalk@4.1.2
|
||||
hash-sum: registry.npmmirror.com/hash-sum@2.0.0
|
||||
vue: registry.npmmirror.com/vue@3.5.13(typescript@4.9.5)
|
||||
vue: registry.npmmirror.com/vue@3.5.16(typescript@5.8.3)
|
||||
watchpack: registry.npmmirror.com/watchpack@2.4.2
|
||||
webpack: registry.npmmirror.com/webpack@5.99.7(webpack-cli@4.10.0)
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue-template-compiler@2.7.16:
|
||||
resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz}
|
||||
name: vue-template-compiler
|
||||
version: 2.7.16
|
||||
dependencies:
|
||||
de-indent: registry.npmmirror.com/de-indent@1.0.2
|
||||
he: registry.npmmirror.com/he@1.2.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue-tsc@1.8.27(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.8.27.tgz}
|
||||
id: registry.npmmirror.com/vue-tsc/1.8.27
|
||||
registry.npmmirror.com/vue-tsc@2.2.10(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.10.tgz}
|
||||
id: registry.npmmirror.com/vue-tsc/2.2.10
|
||||
name: vue-tsc
|
||||
version: 1.8.27
|
||||
version: 2.2.10
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
typescript: '>=5.0.0'
|
||||
dependencies:
|
||||
'@volar/typescript': registry.npmmirror.com/@volar/typescript@1.11.1
|
||||
'@vue/language-core': registry.npmmirror.com/@vue/language-core@1.8.27(typescript@4.9.5)
|
||||
semver: registry.npmmirror.com/semver@7.7.1
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
'@volar/typescript': registry.npmmirror.com/@volar/typescript@2.4.14
|
||||
'@vue/language-core': registry.npmmirror.com/@vue/language-core@2.2.10(typescript@5.8.3)
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue@3.5.13(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz}
|
||||
id: registry.npmmirror.com/vue/3.5.13
|
||||
registry.npmmirror.com/vue@3.5.16(typescript@5.8.3):
|
||||
resolution: {integrity: sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue/-/vue-3.5.16.tgz}
|
||||
id: registry.npmmirror.com/vue/3.5.16
|
||||
name: vue
|
||||
version: 3.5.13
|
||||
version: 3.5.16
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.13
|
||||
'@vue/compiler-sfc': registry.npmmirror.com/@vue/compiler-sfc@3.5.13
|
||||
'@vue/runtime-dom': registry.npmmirror.com/@vue/runtime-dom@3.5.13
|
||||
'@vue/server-renderer': registry.npmmirror.com/@vue/server-renderer@3.5.13(vue@3.5.13)
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.13
|
||||
typescript: registry.npmmirror.com/typescript@4.9.5
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom@3.5.16
|
||||
'@vue/compiler-sfc': registry.npmmirror.com/@vue/compiler-sfc@3.5.16
|
||||
'@vue/runtime-dom': registry.npmmirror.com/@vue/runtime-dom@3.5.16
|
||||
'@vue/server-renderer': registry.npmmirror.com/@vue/server-renderer@3.5.16(vue@3.5.16)
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared@3.5.16
|
||||
typescript: registry.npmmirror.com/typescript@5.8.3
|
||||
|
||||
registry.npmmirror.com/watchpack@2.4.2:
|
||||
resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/watchpack/-/watchpack-2.4.2.tgz}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="multiple-widgets">
|
||||
<div ref="el" class="multiple-widgets">
|
||||
<DefaultWidget
|
||||
v-for="item in items"
|
||||
:key="item.name"
|
||||
@ -13,30 +13,22 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { DefaultWidget } from '@/ui'
|
||||
import { CheckInItem, checkInItems } from './check-in-item'
|
||||
import { type CheckInItem, checkInItems } from './check-in-item'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
DefaultWidget,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: checkInItems,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async runItemAction(item: CheckInItem, event: MouseEvent) {
|
||||
try {
|
||||
// 一开始可能是 undefined
|
||||
this.$set(item, 'disabled', true)
|
||||
const button = this.$el.querySelector(`[data-name='${item.name}']`) as HTMLDivElement
|
||||
await item.action(button, event)
|
||||
} finally {
|
||||
item.disabled = false
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
const el = ref<HTMLDivElement>(null)
|
||||
const items = reactive(checkInItems)
|
||||
|
||||
const runItemAction = async (item: CheckInItem, event: MouseEvent) => {
|
||||
try {
|
||||
// 一开始可能是 undefined
|
||||
item.disabled = true
|
||||
const button = el.value.querySelector(`[data-name='${item.name}']`) as HTMLDivElement
|
||||
await item.action(button, event)
|
||||
} finally {
|
||||
item.disabled = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
<div ref="element" class="multiple-widgets">
|
||||
<VPopup
|
||||
ref="medalPopup"
|
||||
v-model:open="medalOpen"
|
||||
v-model="medalOpen"
|
||||
class="badge-popup widgets-popup medal"
|
||||
:trigger-element="medalButton"
|
||||
:trigger-element="$refs.medalButton"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
@ -28,9 +28,9 @@
|
||||
|
||||
<VPopup
|
||||
ref="titlePopup"
|
||||
v-model:open="titleOpen"
|
||||
v-model="titleOpen"
|
||||
class="badge-popup widgets-popup title"
|
||||
:trigger-element="titleButton"
|
||||
:trigger-element="$refs.titleButton"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { OptionsOfMetadata, defineOptionsMetadata } from '@/components/define'
|
||||
import { type OptionsOfMetadata, defineOptionsMetadata } from '@/components/define'
|
||||
import { getNumberValidator } from '@/core/utils'
|
||||
|
||||
export const badgeHelperOptions = defineOptionsMetadata({
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, onBeforeMount } from 'vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { ChatPanelFitOptions, ChatPanelFitOptionsMinWidth } from './options'
|
||||
import { type ChatPanelFitOptions, ChatPanelFitOptionsMinWidth } from './options'
|
||||
|
||||
const options = reactive(getComponentSettings<ChatPanelFitOptions>('liveChatPanelFit').options)
|
||||
onBeforeMount(() => {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { App } from 'vue'
|
||||
import { defineComponentMetadata } from '@/components/define'
|
||||
import {
|
||||
addComponentListener,
|
||||
@ -8,7 +9,12 @@ import { select, sq } from '@/core/spin-query'
|
||||
import { mountVueComponent } from '@/core/utils'
|
||||
import { useScopedConsole } from '@/core/utils/log'
|
||||
import { liveUrls } from '@/core/utils/urls'
|
||||
import { ChatPanelFitOptions, ChatPanelFitOptionsMinWidth, chatPanelFitOptions } from './options'
|
||||
import {
|
||||
type ChatPanelFitOptions,
|
||||
ChatPanelFitOptionsMinWidth,
|
||||
chatPanelFitOptions,
|
||||
} from './options'
|
||||
import type ChatPanelFitDraggerVue from './ChatPanelFitDragger.vue'
|
||||
|
||||
const name = 'liveChatPanelFit'
|
||||
const console = useScopedConsole(name)
|
||||
@ -37,7 +43,8 @@ const calcPanelWidth = () => {
|
||||
}
|
||||
const debounceCalcPanelWidth = lodash.debounce(calcPanelWidth, 200)
|
||||
|
||||
let draggerInstance: Vue
|
||||
let draggerInstance: InstanceType<typeof ChatPanelFitDraggerVue> | undefined
|
||||
let draggerApp: App<HTMLDivElement> | undefined
|
||||
const load = async () => {
|
||||
addComponentListener(`${name}.targetRatio`, calcPanelWidth)
|
||||
addComponentListener(`${name}.maxWidth`, calcPanelWidth)
|
||||
@ -59,8 +66,10 @@ const load = async () => {
|
||||
return
|
||||
}
|
||||
const { default: ChatPanelFitDragger } = await import('./ChatPanelFitDragger.vue')
|
||||
draggerInstance = mountVueComponent(ChatPanelFitDragger)
|
||||
asideToggleButton.insertAdjacentElement('afterend', draggerInstance.$el)
|
||||
const [el, vm, app] = mountVueComponent(ChatPanelFitDragger)
|
||||
draggerInstance = vm
|
||||
draggerApp = app
|
||||
asideToggleButton.insertAdjacentElement('afterend', el)
|
||||
}
|
||||
const unload = () => {
|
||||
removeComponentListener(`${name}.targetRatio`, calcPanelWidth)
|
||||
@ -70,8 +79,9 @@ const unload = () => {
|
||||
document.documentElement.style.removeProperty('--live-chat-panel-width')
|
||||
if (draggerInstance) {
|
||||
draggerInstance.$el.remove()
|
||||
draggerInstance.$destroy()
|
||||
draggerApp.unmount()
|
||||
draggerInstance = undefined
|
||||
draggerApp = undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { OptionsOfMetadata, defineOptionsMetadata } from '@/components/define'
|
||||
import { type OptionsOfMetadata, defineOptionsMetadata } from '@/components/define'
|
||||
import { getNumberValidator } from '@/core/utils'
|
||||
|
||||
export const ChatPanelFitOptionsMinWidth = 190
|
||||
|
||||
@ -15,18 +15,18 @@
|
||||
</ExtraOptionsPanel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, useTemplateRef } from 'vue'
|
||||
import { TextArea } from '@/ui'
|
||||
import SwitchOptionsMin from './SwitchOptionsMin.vue'
|
||||
import { SwitchMetadataOption } from '@/components/switch-options'
|
||||
import type { SwitchMetadataOption } from '@/components/switch-options'
|
||||
import ExtraOptionsPanel from './ExtraOptionsPanel.vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { Toast } from '@/core/toast'
|
||||
import { delay } from '@/core/utils'
|
||||
import { useScopedConsole } from '@/core/utils/log'
|
||||
import { fontFamilyDefaultValue, coverOptionsName, coverOptionsDefaultValue } from '../data'
|
||||
import { ExtraOptionsPanelInitData } from './extra-options-panel'
|
||||
import type { ExtraOptionsPanelInitData } from './extra-options-panel'
|
||||
|
||||
const initData: ExtraOptionsPanelInitData = {
|
||||
header: {
|
||||
@ -89,91 +89,80 @@ for (const coverOptionName of coverOptionsName) {
|
||||
|
||||
const console = useScopedConsole('自定义字体')
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ExtraOptionsPanel,
|
||||
TextArea,
|
||||
SwitchOptionsMin,
|
||||
},
|
||||
const extraOptionsPanel =
|
||||
useTemplateRef<InstanceType<typeof ExtraOptionsPanel>>('extraOptionsPanel')
|
||||
const isPeeking = ref(false)
|
||||
const isMouseOverPeekIcon = ref(false)
|
||||
const inputFontFamily = ref(getComponentSettings('customFontFamily').options.fontFamily)
|
||||
|
||||
data() {
|
||||
return {
|
||||
isPeeking: false,
|
||||
isMouseOverPeekIcon: false,
|
||||
initData,
|
||||
// 设置 inputFontFamily 初始值为组件 fontFamily 选项的值
|
||||
inputFontFamily: getComponentSettings('customFontFamily').options.fontFamily,
|
||||
switchOptionsComponentOptions,
|
||||
}
|
||||
},
|
||||
watch(
|
||||
() => inputFontFamily.value,
|
||||
lodash.debounce((value: string) => {
|
||||
getComponentSettings('customFontFamily').options.fontFamily = value
|
||||
}, 1000),
|
||||
)
|
||||
|
||||
watch: {
|
||||
// 监听 inputFontFamily 修改动作,实时修改组件 fontFamily 选项为 inputFontFamily 修改后的新值,并拥有 1000ms 防抖
|
||||
inputFontFamily: lodash.debounce(value => {
|
||||
getComponentSettings('customFontFamily').options.fontFamily = value
|
||||
}, 1000),
|
||||
watch(isMouseOverPeekIcon, async (value: boolean) => {
|
||||
if (!value) {
|
||||
isPeeking.value = false
|
||||
return
|
||||
}
|
||||
if (value) {
|
||||
await delay(200)
|
||||
}
|
||||
if (isMouseOverPeekIcon.value) {
|
||||
isPeeking.value = true
|
||||
}
|
||||
})
|
||||
|
||||
async isMouseOverPeekIcon(value: boolean) {
|
||||
if (!value) {
|
||||
this.isPeeking = false
|
||||
return
|
||||
}
|
||||
if (value) {
|
||||
await delay(200)
|
||||
}
|
||||
if (this.isMouseOverPeekIcon) {
|
||||
this.isPeeking = true
|
||||
}
|
||||
},
|
||||
},
|
||||
const toggleDisplay = () => {
|
||||
extraOptionsPanel.value.popupOpen = !extraOptionsPanel.value.popupOpen
|
||||
}
|
||||
|
||||
mounted() {
|
||||
// 当在 v-for 中使用模板引用时,相应的引用中包含的值是一个数组
|
||||
// 但 ref 数组并不保证与源数组相同的顺序,所以统一命名且不加用以区分的后缀,仅靠数组选择元素是不现实的
|
||||
// https://cn.vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for
|
||||
const setIsMouseOverPeekIconToTrue = () => {
|
||||
isMouseOverPeekIcon.value = true
|
||||
}
|
||||
|
||||
const action0Reset = this.$refs.extraOptionsPanel.$refs.action0[0].$el as HTMLElement
|
||||
action0Reset.addEventListener('click', this.confirmResetOptions)
|
||||
const setIsMouseOverPeekIconToFalse = () => {
|
||||
isMouseOverPeekIcon.value = false
|
||||
}
|
||||
|
||||
const action1Peek = this.$refs.extraOptionsPanel.$refs.action1[0].$el as HTMLElement
|
||||
action1Peek.addEventListener('mouseover', this.setIsMouseOverPeekIconToTrue)
|
||||
action1Peek.addEventListener('mouseout', this.setIsMouseOverPeekIconToFalse)
|
||||
},
|
||||
const resetOptions = () => {
|
||||
// 重置字体选项
|
||||
getComponentSettings('customFontFamily').options.fontFamily = fontFamilyDefaultValue
|
||||
inputFontFamily.value = fontFamilyDefaultValue
|
||||
|
||||
methods: {
|
||||
toggleDisplay() {
|
||||
this.$refs.extraOptionsPanel.popupOpen = !this.$refs.extraOptionsPanel.popupOpen
|
||||
},
|
||||
// 重置覆盖选项
|
||||
for (const coverOptionName of coverOptionsName) {
|
||||
const defaultValue = coverOptionsDefaultValue[coverOptionName.camel]
|
||||
getComponentSettings('customFontFamily').options[coverOptionName.camel] = defaultValue
|
||||
}
|
||||
|
||||
setIsMouseOverPeekIconToTrue() {
|
||||
this.isMouseOverPeekIcon = true
|
||||
},
|
||||
Toast.success('更多选项面板中的所有选项已成功被重置为默认值', '自定义字体', 2000)
|
||||
console.log('更多选项面板中的所有选项已成功被重置为默认值')
|
||||
}
|
||||
|
||||
setIsMouseOverPeekIconToFalse() {
|
||||
this.isMouseOverPeekIcon = false
|
||||
},
|
||||
const confirmResetOptions = () => {
|
||||
if (confirm('确定将面板中的所有选项重置为默认值吗?')) {
|
||||
resetOptions()
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 当在 v-for 中使用模板引用时,相应的引用中包含的值是一个数组
|
||||
// 但 ref 数组并不保证与源数组相同的顺序,所以统一命名且不加用以区分的后缀,仅靠数组选择元素是不现实的
|
||||
// https://cn.vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for
|
||||
|
||||
confirmResetOptions() {
|
||||
if (confirm('确定将面板中的所有选项重置为默认值吗?')) {
|
||||
this.resetOptions()
|
||||
}
|
||||
},
|
||||
const panel = extraOptionsPanel.value
|
||||
const action0Reset = panel.$refs.action0[0].$el as HTMLElement
|
||||
action0Reset.addEventListener('click', confirmResetOptions)
|
||||
|
||||
resetOptions() {
|
||||
// 重置字体选项
|
||||
getComponentSettings('customFontFamily').options.fontFamily = fontFamilyDefaultValue
|
||||
this.inputFontFamily = fontFamilyDefaultValue
|
||||
const action1Peek = panel.$refs.action1[0].$el as HTMLElement
|
||||
action1Peek.addEventListener('mouseover', setIsMouseOverPeekIconToTrue)
|
||||
action1Peek.addEventListener('mouseout', setIsMouseOverPeekIconToFalse)
|
||||
})
|
||||
|
||||
// 重置覆盖选项
|
||||
for (const coverOptionName of coverOptionsName) {
|
||||
const defaultValue = coverOptionsDefaultValue[coverOptionName.camel]
|
||||
getComponentSettings('customFontFamily').options[coverOptionName.camel] = defaultValue
|
||||
}
|
||||
|
||||
Toast.success('更多选项面板中的所有选项已成功被重置为默认值', '自定义字体', 2000)
|
||||
console.log('更多选项面板中的所有选项已成功被重置为默认值')
|
||||
},
|
||||
},
|
||||
defineExpose({
|
||||
toggleDisplay,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { mountVueComponent } from '@/core/utils'
|
||||
import type PanelVue from './Panel.vue'
|
||||
|
||||
let panelVm: Vue & {
|
||||
toggleDisplay: () => void
|
||||
}
|
||||
let panelVm: InstanceType<typeof PanelVue> | null = null
|
||||
|
||||
const getPanelLoadState = () => {
|
||||
return Boolean(panelVm)
|
||||
}
|
||||
|
||||
const mountPanel = async () => {
|
||||
const panel = await import('./Panel.vue').then(m => m.default)
|
||||
panelVm = mountVueComponent(panel)
|
||||
document.body.insertAdjacentElement('beforeend', panelVm.$el)
|
||||
const panel = await import('./Panel.vue')
|
||||
const [el, vm] = mountVueComponent(panel)
|
||||
panelVm = vm
|
||||
document.body.insertAdjacentElement('beforeend', el)
|
||||
}
|
||||
|
||||
export const loadPanel = async () => {
|
||||
@ -22,5 +22,5 @@ export const loadPanel = async () => {
|
||||
}
|
||||
|
||||
export const togglePanelDisplay = async () => {
|
||||
panelVm.toggleDisplay()
|
||||
panelVm?.toggleDisplay()
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ import {
|
||||
|
||||
import { popupProps, usePopup } from '../mixins'
|
||||
import type { HistoryItem, TypeFilter } from './types'
|
||||
import { getHistoryItems, group, HistoryType } from './types'
|
||||
import { getHistoryItems, group, HistoryType, navbarFilterTypes } from './types'
|
||||
|
||||
function search(this: InstanceType<typeof ThisComponent>) {
|
||||
this.reloadHistoryItems()
|
||||
|
||||
@ -6,19 +6,7 @@
|
||||
@click="toggleNavbarSettings()"
|
||||
/>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { DefaultWidget } from '@/ui'
|
||||
import { loadNavbarSettings, toggleNavbarSettings } from './vm'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
DefaultWidget,
|
||||
},
|
||||
methods: {
|
||||
async loadNavbarSettings() {
|
||||
await loadNavbarSettings()
|
||||
},
|
||||
toggleNavbarSettings,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="">{{ content }}</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import {
|
||||
addComponentListener,
|
||||
getComponentSettings,
|
||||
@ -9,34 +10,19 @@ import {
|
||||
} from '@/core/settings'
|
||||
import type { CustomNavbarOptions } from '..'
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
isBangumiLinkHidden:
|
||||
getComponentSettings<CustomNavbarOptions>('customNavbar').options.hidden.includes(
|
||||
'bangumi',
|
||||
),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
content() {
|
||||
if (this.isBangumiLinkHidden) {
|
||||
return '番剧'
|
||||
}
|
||||
return '追番追剧'
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
addComponentListener('customNavbar.hidden', this.updateBangumiLinkStatus)
|
||||
},
|
||||
beforeDestroy() {
|
||||
removeComponentListener('customNavbar.hidden', this.updateBangumiLinkStatus)
|
||||
},
|
||||
methods: {
|
||||
updateBangumiLinkStatus(hiddenItems: string[]) {
|
||||
const isBangumiLinkHidden = hiddenItems.includes('bangumi')
|
||||
this.isBangumiLinkHidden = isBangumiLinkHidden
|
||||
},
|
||||
},
|
||||
const isBangumiLinkHidden = ref(
|
||||
getComponentSettings<CustomNavbarOptions>('customNavbar').options.hidden.includes('bangumi'),
|
||||
)
|
||||
|
||||
const content = computed(() => (isBangumiLinkHidden.value ? '番剧' : '追番追剧'))
|
||||
const updateBangumiLinkStatus = (hiddenItems: string[]) => {
|
||||
isBangumiLinkHidden.value = hiddenItems.includes('bangumi')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
addComponentListener('customNavbar.hidden', updateBangumiLinkStatus)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
removeComponentListener('customNavbar.hidden', updateBangumiLinkStatus)
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -8,63 +8,54 @@
|
||||
<MinimalHomeOperations v-if="cards.length > 0" @refresh="refresh" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, useTemplateRef } from 'vue'
|
||||
import { getVideoFeeds } from '@/components/feeds/api'
|
||||
import type { VideoCard } from '@/components/feeds/video-card'
|
||||
import VideoCardComponent from '@/components/feeds/VideoCard.vue'
|
||||
import type { VideoCard as VideoCardType } from '@/components/feeds/video-card'
|
||||
import VideoCard from '@/components/feeds/VideoCard.vue'
|
||||
import { logError } from '@/core/utils/log'
|
||||
import { ascendingStringSort } from '@/core/utils/sort'
|
||||
import { ScrollTrigger, VEmpty } from '@/ui'
|
||||
|
||||
import type { ScrollTrigger as ScrollTriggerType } from '@/ui'
|
||||
import MinimalHomeOperations from '../MinimalHomeOperations.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { ScrollTrigger, VEmpty, VideoCard: VideoCardComponent, MinimalHomeOperations },
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
cards: [] as VideoCard[],
|
||||
error: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loaded(): boolean {
|
||||
return !this.loading && !this.error
|
||||
},
|
||||
lastID(): string | null {
|
||||
if (!this.cards.length) {
|
||||
return null
|
||||
}
|
||||
const cards: VideoCard[] = [...this.cards]
|
||||
return cards.sort(ascendingStringSort(c => c.id))[0].id
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async loadCards() {
|
||||
try {
|
||||
this.error = false
|
||||
this.loading = true
|
||||
this.$refs.scrollTrigger.setLoadState('loading')
|
||||
this.cards = lodash.uniqBy(
|
||||
[...this.cards, ...(await getVideoFeeds('video', this.lastID))],
|
||||
it => it.id,
|
||||
)
|
||||
} catch (error) {
|
||||
logError(error)
|
||||
this.error = true
|
||||
this.$refs.scrollTrigger.setLoadState('error')
|
||||
} finally {
|
||||
this.loading = false
|
||||
if (this.loaded) {
|
||||
this.$refs.scrollTrigger.setLoadState('loaded')
|
||||
}
|
||||
}
|
||||
},
|
||||
async refresh() {
|
||||
this.cards = []
|
||||
this.$refs.scrollTrigger.resetIsFirstLoad()
|
||||
},
|
||||
},
|
||||
const loading = ref(true)
|
||||
const cards = ref<VideoCardType[]>([])
|
||||
const error = ref(false)
|
||||
|
||||
const scrollTrigger = useTemplateRef<InstanceType<typeof ScrollTriggerType>>('scrollTrigger')
|
||||
|
||||
const loaded = computed(() => !loading.value && !error.value)
|
||||
|
||||
const lastID = computed(() => {
|
||||
if (!cards.value.length) {
|
||||
return null
|
||||
}
|
||||
const sorted = [...cards.value].sort(ascendingStringSort(c => c.id))
|
||||
return sorted[0].id
|
||||
})
|
||||
|
||||
const loadCards = async () => {
|
||||
try {
|
||||
error.value = false
|
||||
loading.value = true
|
||||
scrollTrigger.value.setLoadState('loading')
|
||||
const newCards = await getVideoFeeds('video', lastID.value)
|
||||
cards.value = lodash.uniqBy([...cards.value, ...newCards], it => it.id)
|
||||
} catch (e) {
|
||||
logError(e)
|
||||
error.value = true
|
||||
scrollTrigger.value.setLoadState('error')
|
||||
} finally {
|
||||
loading.value = false
|
||||
if (loaded.value) {
|
||||
scrollTrigger.value.setLoadState('loaded')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const refresh = async () => {
|
||||
cards.value = []
|
||||
scrollTrigger.value.resetIsFirstLoad()
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<VPopup
|
||||
ref="popup"
|
||||
v-model="isOpen"
|
||||
class="like-black-list"
|
||||
fixed
|
||||
@ -44,59 +43,47 @@
|
||||
</div>
|
||||
</VPopup>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref, defineProps, defineEmits, watch, useTemplateRef } from 'vue'
|
||||
import { VPopup, TextBox, VIcon, VButton } from '@/ui'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VPopup,
|
||||
TextBox,
|
||||
VIcon,
|
||||
VButton,
|
||||
},
|
||||
props: {
|
||||
triggerElement: {
|
||||
type: HTMLElement,
|
||||
default: null,
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
titleName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isOpen: false,
|
||||
isLoaded: false,
|
||||
name: '',
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.isLoaded = true
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.$refs.popup.toggle()
|
||||
},
|
||||
changeName(val: string) {
|
||||
this.name = val
|
||||
},
|
||||
add() {
|
||||
if (this.name.length && !this.list.includes(this.name)) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
this.list.push(this.name)
|
||||
}
|
||||
this.name = ''
|
||||
},
|
||||
toggleVisible(item: string) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
this.list.splice(this.list.indexOf(item), 1)
|
||||
},
|
||||
},
|
||||
const props = defineProps<{
|
||||
triggerElement?: HTMLElement | null
|
||||
list?: string[]
|
||||
titleName?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:list'])
|
||||
|
||||
const isOpen = ref(false)
|
||||
const isLoaded = ref(false)
|
||||
const name = ref('')
|
||||
|
||||
const list = ref<string[]>(props.list ? [...props.list] : [])
|
||||
|
||||
const changeName = (val: string) => {
|
||||
name.value = val
|
||||
}
|
||||
|
||||
const add = () => {
|
||||
if (name.value.length && !list.value.includes(name.value)) {
|
||||
list.value.push(name.value)
|
||||
emit('update:list', [...list.value])
|
||||
}
|
||||
name.value = ''
|
||||
}
|
||||
|
||||
function toggleVisible(item: string) {
|
||||
const idx = list.value.indexOf(item)
|
||||
if (idx !== -1) {
|
||||
list.value.splice(idx, 1)
|
||||
emit('update:list', [...list.value])
|
||||
}
|
||||
}
|
||||
|
||||
isLoaded.value = true
|
||||
defineExpose({
|
||||
isOpen,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { defineComponentMetadata } from '@/components/define'
|
||||
import { select } from '@/core/spin-query'
|
||||
import { matchUrlPattern, playerReady } from '@/core/utils'
|
||||
import { feedsUrls, videoAndBangumiUrls } from '@/core/utils/urls'
|
||||
import { KeyBindingAction } from '../keymap/bindings'
|
||||
import type { KeyBindingAction } from '../keymap/bindings'
|
||||
import { forEachFeedsCard } from '@/components/feeds/api'
|
||||
import { BlackListDataKey, loadlikeButton } from './vm'
|
||||
import { getData, registerData } from '@/plugins/data'
|
||||
|
||||
@ -5,66 +5,53 @@
|
||||
</VButton>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { VButton, VIcon } from '@/ui'
|
||||
import { getData } from '@/plugins/data'
|
||||
import { BlackListDataKey } from './vm'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VButton,
|
||||
VIcon,
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isClick: false,
|
||||
isLike: false,
|
||||
totalLikeCnt: 0,
|
||||
curLikeCnt: 0,
|
||||
feedsLikeQueue: [] as HTMLElement[],
|
||||
const isClick = ref(false)
|
||||
const isLike = ref(false)
|
||||
const totalLikeCnt = ref(0)
|
||||
const curLikeCnt = ref(0)
|
||||
const feedsLikeQueue = ref([] as HTMLElement[])
|
||||
|
||||
const like = () => {
|
||||
if (isClick.value) {
|
||||
return
|
||||
}
|
||||
isClick.value = true
|
||||
const list = getData(BlackListDataKey)[0].users as string[]
|
||||
// forEachFeedsCard异步执行顺序有问题,不能及时同步,用dqa代替
|
||||
const likeButtons = (
|
||||
Array.from(document.getElementsByClassName('bili-dyn-title__text')) as HTMLElement[]
|
||||
).reduce((buttons, e) => {
|
||||
if (list.includes(e.textContent.trim())) {
|
||||
return buttons
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
like() {
|
||||
if (this.isClick) {
|
||||
return
|
||||
}
|
||||
this.isClick = true
|
||||
// forEachFeedsCard异步执行顺序有问题,不能及时同步,用dqa代替
|
||||
const likeButtons = (
|
||||
Array.from(document.getElementsByClassName('bili-dyn-title__text')) as HTMLElement[]
|
||||
).reduce((buttons, e) => {
|
||||
if (this.list.includes(e.textContent.trim())) {
|
||||
return buttons
|
||||
}
|
||||
const likeButton = e.closest('.bili-dyn-item__main').querySelector('.bili-dyn-action.like')
|
||||
if (likeButton && !likeButton.classList.contains('active')) {
|
||||
buttons.push(likeButton as HTMLElement)
|
||||
}
|
||||
return buttons
|
||||
}, [] as HTMLElement[])
|
||||
this.feedsLikeQueue.push(...likeButtons)
|
||||
this.totalLikeCnt = this.feedsLikeQueue.length
|
||||
this.curLikeCnt = 0
|
||||
this.isLike = true
|
||||
const t = window.setInterval(() => {
|
||||
if (this.feedsLikeQueue.length === 0) {
|
||||
this.isLike = false
|
||||
this.isClick = false
|
||||
clearInterval(t)
|
||||
return
|
||||
}
|
||||
const button = this.feedsLikeQueue.shift()
|
||||
button?.click()
|
||||
this.curLikeCnt++
|
||||
}, 1200)
|
||||
},
|
||||
},
|
||||
})
|
||||
const likeButton = e.closest('.bili-dyn-item__main').querySelector('.bili-dyn-action.like')
|
||||
if (likeButton && !likeButton.classList.contains('active')) {
|
||||
buttons.push(likeButton as HTMLElement)
|
||||
}
|
||||
return buttons
|
||||
}, [] as HTMLElement[])
|
||||
feedsLikeQueue.value.push(...likeButtons)
|
||||
totalLikeCnt.value = feedsLikeQueue.value.length
|
||||
curLikeCnt.value = 0
|
||||
isLike.value = true
|
||||
const t = window.setInterval(() => {
|
||||
if (feedsLikeQueue.value.length === 0) {
|
||||
isLike.value = false
|
||||
isClick.value = false
|
||||
clearInterval(t)
|
||||
return
|
||||
}
|
||||
const button = feedsLikeQueue.value.shift()
|
||||
button?.click()
|
||||
curLikeCnt.value++
|
||||
}, 1200)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@ -1,44 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="custom-black-list-extra-options">
|
||||
<VButton ref="button" @mouseover="setBlackListProps" @click="toggleBlackList">
|
||||
<VButton ref="button" @mouseover="setBlackListPropsWrapper" @click="toggleBlackList">
|
||||
黑名单
|
||||
<VIcon icon="right-arrow" :size="16" />
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { VIcon, VButton } from '@/ui'
|
||||
import { loadBlackList, setBlackListProps, toggleBlackList } from './vm'
|
||||
<script lang="ts" setup>
|
||||
import { useTemplateRef } from 'vue'
|
||||
import { VIcon, type VButton } from '@/ui'
|
||||
import { loadBlackList, toggleBlackList } from './vm'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VIcon,
|
||||
VButton,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFirstLoad: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.$refs.popup.toggle()
|
||||
},
|
||||
async setBlackListProps() {
|
||||
if (this.isFirstLoad) {
|
||||
return
|
||||
}
|
||||
this.isFirstLoad = await loadBlackList()
|
||||
if (this.isFirstLoad) {
|
||||
const triggerButton = this.$refs.button.$el as HTMLElement
|
||||
setBlackListProps(triggerButton)
|
||||
}
|
||||
},
|
||||
toggleBlackList,
|
||||
},
|
||||
})
|
||||
const button = useTemplateRef<InstanceType<typeof VButton>>('button')
|
||||
|
||||
const setBlackListPropsWrapper = async () => {
|
||||
await loadBlackList(button.value.$el as HTMLElement)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.custom-black-list-extra-options {
|
||||
|
||||
@ -2,47 +2,34 @@ import { select } from '@/core/spin-query'
|
||||
import { mountVueComponent } from '@/core/utils'
|
||||
import { getData } from '@/plugins/data'
|
||||
|
||||
import type blackListVue from './blackList.vue'
|
||||
|
||||
export const BlackListDataKey = 'like-black-List.data'
|
||||
let blacklistVM: InstanceType<typeof blackListVue> | null = null
|
||||
|
||||
type SettingsVmType = Vue & {
|
||||
toggle: () => void
|
||||
triggerElement: HTMLElement
|
||||
list: string[]
|
||||
titleName: string
|
||||
export const loadlikeButton = async () => {
|
||||
const LikeButton = await import('./like.vue')
|
||||
const [el] = mountVueComponent(LikeButton)
|
||||
const bg = (await select('#app')) as HTMLElement
|
||||
bg.insertAdjacentElement('afterbegin', el)
|
||||
}
|
||||
let blacklistVM: SettingsVmType = null
|
||||
|
||||
export const setBlackListProps = (element: HTMLElement) => {
|
||||
if (!blacklistVM) {
|
||||
export const loadBlackList = async (element: HTMLElement) => {
|
||||
if (blacklistVM) {
|
||||
return
|
||||
}
|
||||
blacklistVM.triggerElement = element
|
||||
const blackList = getData(BlackListDataKey)
|
||||
blacklistVM.list = blackList[0].users
|
||||
blacklistVM.titleName = '黑名单'
|
||||
}
|
||||
export const loadlikeButton = async () => {
|
||||
const LikeButton = await import('./like.vue').then(m => m.default)
|
||||
const blackList = getData(BlackListDataKey)
|
||||
const likebuttonVM: Vue & { list: string[] } = mountVueComponent(LikeButton)
|
||||
likebuttonVM.list = blackList[0].users
|
||||
const bg = (await select('#app')) as HTMLElement
|
||||
bg.insertAdjacentElement('afterbegin', likebuttonVM.$el)
|
||||
}
|
||||
|
||||
export const loadBlackList = async () => {
|
||||
if (blacklistVM) {
|
||||
return false
|
||||
}
|
||||
const blackList = await import('./blackList.vue').then(m => m.default)
|
||||
blacklistVM = mountVueComponent(blackList)
|
||||
document.body.insertAdjacentElement('beforeend', blacklistVM.$el)
|
||||
return true
|
||||
const blackList = await import('./blackList.vue')
|
||||
const [el, vm] = mountVueComponent(blackList, {
|
||||
triggerElement: element,
|
||||
list: getData(BlackListDataKey)[0].users,
|
||||
titleName: '黑名单',
|
||||
})
|
||||
blacklistVM = vm
|
||||
document.body.insertAdjacentElement('beforeend', el)
|
||||
}
|
||||
|
||||
export const toggleBlackList = async () => {
|
||||
if (!blacklistVM) {
|
||||
await loadBlackList()
|
||||
if (blacklistVM) {
|
||||
blacklistVM.isOpen = false
|
||||
}
|
||||
blacklistVM?.toggle()
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { registerAndGetData } from '@/plugins/data'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { CommentContentReplaceHandler } from './types'
|
||||
import { CommentContentReplaceOptions } from '../options'
|
||||
import { NodeContentReplacer } from './node-content-replacer'
|
||||
import type { CommentContentReplaceHandler } from './types'
|
||||
import type { CommentContentReplaceOptions } from '../options'
|
||||
import type { NodeContentReplacer } from './node-content-replacer'
|
||||
import { EmoticonToEmoticonReplacer } from './emoticon-to-emoticon'
|
||||
import { EmoticonToTextReplacer } from './emoticon-to-text'
|
||||
import { RecursiveReplacer } from './recursive'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
|
||||
import { defineOptionsMetadata, type OptionsOfMetadata } from '@/components/define'
|
||||
|
||||
export const commentContentReplaceOptions = defineOptionsMetadata({
|
||||
replaceMap: {
|
||||
|
||||
@ -29,31 +29,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { VButton, TextBox, VIcon } from '@/ui'
|
||||
import { CommentContentReplaceRow } from './row'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VButton,
|
||||
VIcon,
|
||||
TextBox,
|
||||
},
|
||||
props: {
|
||||
row: {
|
||||
required: true,
|
||||
type: CommentContentReplaceRow,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
emitChange(event: { from: string; to: string }) {
|
||||
this.$emit('change', event)
|
||||
},
|
||||
emitDelete() {
|
||||
this.$emit('delete')
|
||||
},
|
||||
const { row } = defineProps({
|
||||
row: {
|
||||
required: true,
|
||||
type: CommentContentReplaceRow,
|
||||
},
|
||||
})
|
||||
const emits = defineEmits(['change', 'delete'])
|
||||
const emitChange = (event: { from: string; to: string }) => {
|
||||
emits('change', event)
|
||||
}
|
||||
const emitDelete = () => {
|
||||
emits('delete')
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="comment-content-replace-extra-options">
|
||||
<div class="comment-content-replace-rows">
|
||||
<template v-for="(row, index) of rows">
|
||||
<template v-for="(row, index) of rows" :key="row.key">
|
||||
<ContentReplaceRow
|
||||
:key="row.key"
|
||||
:row="row"
|
||||
@change="handleRowChange(row, $event)"
|
||||
@delete="handleRowDelete(row)"
|
||||
@ -21,52 +20,38 @@
|
||||
</VButton>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { deleteValue } from '@/core/utils'
|
||||
import { VButton, VIcon } from '@/ui'
|
||||
import { CommentContentReplaceOptions } from '../options'
|
||||
import type { CommentContentReplaceOptions } from '../options'
|
||||
import { CommentContentReplaceRow } from './row'
|
||||
import ContentReplaceRow from './ContentReplaceRow.vue'
|
||||
|
||||
const { options } = getComponentSettings<CommentContentReplaceOptions>('commentContentReplace')
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
ContentReplaceRow,
|
||||
VButton,
|
||||
VIcon,
|
||||
},
|
||||
data() {
|
||||
const { replaceMap } = options
|
||||
|
||||
const rows = Object.entries(replaceMap).map(
|
||||
([from, to]) => new CommentContentReplaceRow(from, to),
|
||||
)
|
||||
return {
|
||||
rows,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveSettings() {
|
||||
const validRows = (this.rows as CommentContentReplaceRow[])
|
||||
.map(row => [row.from, row.to])
|
||||
.filter(([from]) => Boolean(from))
|
||||
options.replaceMap = Object.fromEntries(validRows)
|
||||
},
|
||||
handleRowChange(row: CommentContentReplaceRow, event: { from: string; to: string }) {
|
||||
row.from = event.from
|
||||
row.to = event.to
|
||||
this.saveSettings()
|
||||
},
|
||||
handleRowDelete(row: CommentContentReplaceRow) {
|
||||
deleteValue(this.rows, it => it === row)
|
||||
this.saveSettings()
|
||||
},
|
||||
handleRowAdd() {
|
||||
this.rows.push(new CommentContentReplaceRow())
|
||||
},
|
||||
},
|
||||
})
|
||||
const { replaceMap } = options
|
||||
|
||||
const rows = reactive(
|
||||
Object.entries(replaceMap).map(([from, to]) => new CommentContentReplaceRow(from, to)),
|
||||
)
|
||||
const saveSettings = () => {
|
||||
const validRows = rows.map(row => [row.from, row.to]).filter(([from]) => Boolean(from))
|
||||
options.replaceMap = Object.fromEntries(validRows)
|
||||
}
|
||||
const handleRowChange = (row: CommentContentReplaceRow, event: { from: string; to: string }) => {
|
||||
row.from = event.from
|
||||
row.to = event.to
|
||||
saveSettings()
|
||||
}
|
||||
const handleRowDelete = (row: CommentContentReplaceRow) => {
|
||||
deleteValue(rows, it => it === row)
|
||||
saveSettings()
|
||||
}
|
||||
const handleRowAdd = () => {
|
||||
rows.push(new CommentContentReplaceRow())
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
/* eslint-disable yoda */
|
||||
import { defineComponentMetadata } from '@/components/define'
|
||||
import { CommentItem, CommentReplyItem } from '@/components/utils/comment-apis'
|
||||
import type { CommentItem, CommentReplyItem } from '@/components/utils/comment-apis'
|
||||
import { select } from '@/core/spin-query'
|
||||
|
||||
// 新版评论区IP属地获取
|
||||
@ -15,212 +15,6 @@ let bbComment: any
|
||||
|
||||
const marginLeft = 15
|
||||
|
||||
// 带IP属地显示的评论创建
|
||||
const createListCon = function listCon(item, i, pos) {
|
||||
const blCon = this._parentBlacklistDom(item, i, pos)
|
||||
const con = [
|
||||
`<div class="con ${pos === i ? 'no-border' : ''}">`,
|
||||
`<div class="user">${this._createNickNameDom(item)}`,
|
||||
this._createLevelLink(item),
|
||||
this._identity(item.mid, item.assist, item.member.fans_detail),
|
||||
`${this._createNameplate(item.member.nameplate) + this._createUserSailing(item)}</div>`,
|
||||
this._createMsgContent(item),
|
||||
this._createPerfectReply(item),
|
||||
'<div class="info">',
|
||||
this._createPlatformDom(item.content.plat),
|
||||
'<span class="time-location">',
|
||||
'<span class="reply-time">'.concat(this._formateTime(item.ctime), '</span>'),
|
||||
item?.reply_control?.location
|
||||
? `<span class="reply-location" style="margin-left:${marginLeft}px;">${
|
||||
item?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
'</span>',
|
||||
item.lottery_id
|
||||
? ''
|
||||
: `<span class="like ${item.action === 1 ? 'liked' : ''}"><i></i><span>${
|
||||
item.like ? item.like : ''
|
||||
}</span></span>`,
|
||||
item.lottery_id ? '' : `<span class="hate ${item.action === 2 ? 'hated' : ''}"><i></i></span>`,
|
||||
item.lottery_id ? '' : this._createReplyBtn(item.rcount),
|
||||
item.lottery_id && item.mid !== bbComment.userStatus.mid
|
||||
? ''
|
||||
: `<div class="operation more-operation"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canSetTop(item)
|
||||
? `<li class="set-top">${item.isUpTop ? '取消置顶' : '设为置顶'}</li>`
|
||||
: ''
|
||||
}${this._canBlackList(item.mid) ? '<li class="blacklist">加入黑名单</li>' : ''}${
|
||||
this._canReport(item.mid) ? '<li class="report">举报</li>' : ''
|
||||
}${
|
||||
this._canDel(item.mid) && !item.isTop
|
||||
? `<li class="del" data-mid="${item.mid}">删除</li>`
|
||||
: ''
|
||||
}</ul></div></div>`,
|
||||
this._createLotteryContent(item.content),
|
||||
this._createVoteContent(item.content),
|
||||
this._createTags(item),
|
||||
'</div>',
|
||||
'<div class="reply-box">',
|
||||
this._createSubReplyList(
|
||||
item.replies,
|
||||
item.rcount,
|
||||
false,
|
||||
item.rpid,
|
||||
item.folder && item.folder.has_folded,
|
||||
item.reply_control,
|
||||
),
|
||||
'</div>',
|
||||
'<div class="paging-box">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return item.state === bbComment.blacklistCode ? blCon : con
|
||||
}
|
||||
|
||||
// 带IP属地显示的回复创建
|
||||
const createSubReplyItem = function subReply(item, i) {
|
||||
const dom = [
|
||||
`<div class="reply-item reply-wrap" data-id="${item.rpid}" data-index="${i}">`,
|
||||
this._createSubReplyUserFace(item),
|
||||
'<div class="reply-con">',
|
||||
'<div class="user">',
|
||||
this._createNickNameDom(item),
|
||||
this._createLevelLink(item),
|
||||
this._identity(item.mid),
|
||||
this._createSubMsgContent(item),
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="info">',
|
||||
'<span class="time-location">',
|
||||
'<span class="reply-time">'.concat(this._formateTime(item.ctime), '</span>'),
|
||||
item?.reply_control?.location
|
||||
? `<span class="reply-location" style="margin-left:${marginLeft}px;">${
|
||||
item?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
'</span>',
|
||||
`<span class="like ${item.action === 1 ? 'liked' : ''}"><i></i><span>${
|
||||
item.like ? item.like : ''
|
||||
}</span></span>`,
|
||||
`<span class="hate ${item.action === 2 ? 'hated' : ''}"><i></i></span>`,
|
||||
'<span class="reply btn-hover">回复</span>',
|
||||
`<div class="operation btn-hover btn-hide-re"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canBlackList(item.mid) ? '<li class="blacklist">加入黑名单</li>' : ''
|
||||
}${this._canReport(item.mid) ? '<li class="report">举报</li>' : ''}${
|
||||
this._canDel(item.mid) ? `<li class="del" data-mid="${item.mid}">删除</li>` : ''
|
||||
}</ul></div></div>`,
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
|
||||
return dom
|
||||
}
|
||||
|
||||
// 小黑屋专用带IP属地显示的评论创建
|
||||
const blackroomCreateListCon = function listCon(e, n, t) {
|
||||
const r = this._parentBlacklistDom(e, n, t)
|
||||
const i = [
|
||||
`<div class="con ${t === n ? 'no-border' : ''}">`,
|
||||
`<div class="user">${this._identity(e.mid, e.assist, e.member.fans_detail)}`,
|
||||
`<a data-usercard-mid="${e.mid}" href="//space.bilibili.com/${
|
||||
e.mid
|
||||
}" target="_blank" class="name ${this._createVipClass(
|
||||
e.member.vip.vipType,
|
||||
e.member.vip.vipStatus,
|
||||
e.member.vip.themeType,
|
||||
)}">${this._unhtmlFix(
|
||||
e.member.uname,
|
||||
)}</a><a class="level-link" href="//www.bilibili.com/blackboard/help.html#%E4%BC%9A%E5%91%98%E7%AD%89%E7%BA%A7%E7%9B%B8%E5%85%B3" target="_blank"><i class="level l${
|
||||
e.member.level_info.current_level
|
||||
}"></i></a>${this._createNameplate(e.member.nameplate)}${this._createUserSailing(
|
||||
(e.member && e.member.user_sailing) || {},
|
||||
)}</div>`,
|
||||
this._createMsgContent(e),
|
||||
'<div class="info">',
|
||||
e.floor ? `<span class="floor">#${e.floor}</span>` : '',
|
||||
this._createPlatformDom(e.content.plat),
|
||||
`<span class="time">${this._formateTime(e.ctime)}</span>`,
|
||||
e?.reply_control?.location
|
||||
? `<span style="margin-left:${marginLeft - 15}px;">${e?.reply_control?.location || ''}</span>`
|
||||
: '',
|
||||
e.lottery_id
|
||||
? ''
|
||||
: `<span class="like ${1 === e.action ? 'liked' : ''}"><i></i><span>${
|
||||
e.like || ''
|
||||
}</span></span>`,
|
||||
e.lottery_id ? '' : `<span class="hate ${2 === e.action ? 'hated' : ''}"><i></i></span>`,
|
||||
e.lottery_id ? '' : this._createReplyBtn(e.rcount),
|
||||
e.lottery_id && e.mid !== this.userStatus.mid
|
||||
? ''
|
||||
: `<div class="operation more-operation"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canSetTop(e)
|
||||
? `<li class="set-top">${e.isUpTop ? '取消置顶' : '设为置顶'}</li>`
|
||||
: ''
|
||||
}${this._canBlackList(e.mid) ? '<li class="blacklist">加入黑名单</li>' : ''}${
|
||||
this._canReport(e.mid) ? '<li class="report">举报</li>' : ''
|
||||
}${
|
||||
this._canDel(e.mid) && !e.isTop ? `<li class="del" data-mid="${e.mid}">删除</li>` : ''
|
||||
}</ul></div></div>`,
|
||||
this._createLotteryContent(e.content),
|
||||
this._createVoteContent(e.content),
|
||||
this._createTags(e),
|
||||
'</div>',
|
||||
'<div class="reply-box">',
|
||||
this._createSubReplyList(e.replies, e.rcount, !1, e.rpid, e.folder && e.folder.has_folded),
|
||||
'</div>',
|
||||
'<div class="paging-box">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return e.state === this.blacklistCode ? r : i
|
||||
}
|
||||
|
||||
// 小黑屋专用带IP属地显示的回复创建
|
||||
const blackroomCreateSubReplyItem = function subReply(e, n) {
|
||||
const t = [
|
||||
`<div class="reply-item reply-wrap" data-id="${e.rpid}" data-index="${n}">`,
|
||||
`<a href="//space.bilibili.com/${e.mid}" data-usercard-mid="${e.mid}" target="_blank" class="reply-face">`,
|
||||
`<img src="${this._trimHttpFix(
|
||||
this._webpFix(e.member.avatar, {
|
||||
w: 52,
|
||||
h: 52,
|
||||
}),
|
||||
)}" alt="">`,
|
||||
'</a>',
|
||||
'<div class="reply-con">',
|
||||
'<div class="user">',
|
||||
`<a href="//space.bilibili.com/${e.mid}" target="_blank" data-usercard-mid="${
|
||||
e.mid
|
||||
}" class="name ${this._createVipClass(
|
||||
e.member.vip.vipType,
|
||||
e.member.vip.vipStatus,
|
||||
e.member.vip.themeType,
|
||||
)}">${this._unhtmlFix(e.member.uname)}</a>`,
|
||||
`<a class="level-link" href="//www.bilibili.com/blackboard/help.html#%E4%BC%9A%E5%91%98%E7%AD%89%E7%BA%A7%E7%9B%B8%E5%85%B3" target="_blank"><i class="level l${e.member.level_info.current_level}"></i></a>`,
|
||||
this._createSubMsgContent(e),
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="info">',
|
||||
`<span class="time">${this._formateTime(e.ctime)}</span>`,
|
||||
e?.reply_control?.location
|
||||
? `<span style="margin-left:${marginLeft - 15}px;">${e?.reply_control?.location || ''}</span>`
|
||||
: '',
|
||||
`<span class="like ${1 === e.action ? 'liked' : ''}"><i></i><span>${
|
||||
e.like || ''
|
||||
}</span></span>`,
|
||||
`<span class="hate ${2 === e.action ? 'hated' : ''}"><i></i></span>`,
|
||||
'<span class="reply btn-hover">回复</span>',
|
||||
`<div class="operation btn-hover btn-hide-re"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canBlackList(e.mid) ? '<li class="blacklist">加入黑名单</li>' : ''
|
||||
}${this._canReport(e.mid) ? '<li class="report">举报</li>' : ''}${
|
||||
this._canDel(e.mid) ? `<li class="del" data-mid="${e.mid}">删除</li>` : ''
|
||||
}</ul></div></div>`,
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return t
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
mutations.forEach(() => {
|
||||
// 监听旧版评论区全局变量
|
||||
@ -257,12 +51,232 @@ const observer = new MutationObserver(mutations => {
|
||||
return this.isWebp ? `${t[1] + e}.webp${n}` : `${t[1] + e}.${t[2]}${n}`
|
||||
}
|
||||
|
||||
bbComment.prototype._createListCon = blackroomCreateListCon
|
||||
bbComment.prototype._createSubReplyItem = blackroomCreateSubReplyItem
|
||||
bbComment.prototype._createListCon =
|
||||
// 小黑屋专用带IP属地显示的评论创建
|
||||
function blackRoomListCon(e, n, t) {
|
||||
const r = this._parentBlacklistDom(e, n, t)
|
||||
const i = [
|
||||
`<div class="con ${t === n ? 'no-border' : ''}">`,
|
||||
`<div class="user">${this._identity(e.mid, e.assist, e.member.fans_detail)}`,
|
||||
`<a data-usercard-mid="${e.mid}" href="//space.bilibili.com/${
|
||||
e.mid
|
||||
}" target="_blank" class="name ${this._createVipClass(
|
||||
e.member.vip.vipType,
|
||||
e.member.vip.vipStatus,
|
||||
e.member.vip.themeType,
|
||||
)}">${this._unhtmlFix(
|
||||
e.member.uname,
|
||||
)}</a><a class="level-link" href="//www.bilibili.com/blackboard/help.html#%E4%BC%9A%E5%91%98%E7%AD%89%E7%BA%A7%E7%9B%B8%E5%85%B3" target="_blank"><i class="level l${
|
||||
e.member.level_info.current_level
|
||||
}"></i></a>${this._createNameplate(e.member.nameplate)}${this._createUserSailing(
|
||||
(e.member && e.member.user_sailing) || {},
|
||||
)}</div>`,
|
||||
this._createMsgContent(e),
|
||||
'<div class="info">',
|
||||
e.floor ? `<span class="floor">#${e.floor}</span>` : '',
|
||||
this._createPlatformDom(e.content.plat),
|
||||
`<span class="time">${this._formateTime(e.ctime)}</span>`,
|
||||
e?.reply_control?.location
|
||||
? `<span style="margin-left:${marginLeft - 15}px;">${
|
||||
e?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
e.lottery_id
|
||||
? ''
|
||||
: `<span class="like ${1 === e.action ? 'liked' : ''}"><i></i><span>${
|
||||
e.like || ''
|
||||
}</span></span>`,
|
||||
e.lottery_id
|
||||
? ''
|
||||
: `<span class="hate ${2 === e.action ? 'hated' : ''}"><i></i></span>`,
|
||||
e.lottery_id ? '' : this._createReplyBtn(e.rcount),
|
||||
e.lottery_id && e.mid !== this.userStatus.mid
|
||||
? ''
|
||||
: `<div class="operation more-operation"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canSetTop(e)
|
||||
? `<li class="set-top">${e.isUpTop ? '取消置顶' : '设为置顶'}</li>`
|
||||
: ''
|
||||
}${this._canBlackList(e.mid) ? '<li class="blacklist">加入黑名单</li>' : ''}${
|
||||
this._canReport(e.mid) ? '<li class="report">举报</li>' : ''
|
||||
}${
|
||||
this._canDel(e.mid) && !e.isTop
|
||||
? `<li class="del" data-mid="${e.mid}">删除</li>`
|
||||
: ''
|
||||
}</ul></div></div>`,
|
||||
this._createLotteryContent(e.content),
|
||||
this._createVoteContent(e.content),
|
||||
this._createTags(e),
|
||||
'</div>',
|
||||
'<div class="reply-box">',
|
||||
this._createSubReplyList(
|
||||
e.replies,
|
||||
e.rcount,
|
||||
!1,
|
||||
e.rpid,
|
||||
e.folder && e.folder.has_folded,
|
||||
),
|
||||
'</div>',
|
||||
'<div class="paging-box">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return e.state === this.blacklistCode ? r : i
|
||||
}
|
||||
bbComment.prototype._createSubReplyItem =
|
||||
// 小黑屋专用带IP属地显示的回复创建
|
||||
function blackRoomSubReply(e, n) {
|
||||
const t = [
|
||||
`<div class="reply-item reply-wrap" data-id="${e.rpid}" data-index="${n}">`,
|
||||
`<a href="//space.bilibili.com/${e.mid}" data-usercard-mid="${e.mid}" target="_blank" class="reply-face">`,
|
||||
`<img src="${this._trimHttpFix(
|
||||
this._webpFix(e.member.avatar, {
|
||||
w: 52,
|
||||
h: 52,
|
||||
}),
|
||||
)}" alt="">`,
|
||||
'</a>',
|
||||
'<div class="reply-con">',
|
||||
'<div class="user">',
|
||||
`<a href="//space.bilibili.com/${e.mid}" target="_blank" data-usercard-mid="${
|
||||
e.mid
|
||||
}" class="name ${this._createVipClass(
|
||||
e.member.vip.vipType,
|
||||
e.member.vip.vipStatus,
|
||||
e.member.vip.themeType,
|
||||
)}">${this._unhtmlFix(e.member.uname)}</a>`,
|
||||
`<a class="level-link" href="//www.bilibili.com/blackboard/help.html#%E4%BC%9A%E5%91%98%E7%AD%89%E7%BA%A7%E7%9B%B8%E5%85%B3" target="_blank"><i class="level l${e.member.level_info.current_level}"></i></a>`,
|
||||
this._createSubMsgContent(e),
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="info">',
|
||||
`<span class="time">${this._formateTime(e.ctime)}</span>`,
|
||||
e?.reply_control?.location
|
||||
? `<span style="margin-left:${marginLeft - 15}px;">${
|
||||
e?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
`<span class="like ${1 === e.action ? 'liked' : ''}"><i></i><span>${
|
||||
e.like || ''
|
||||
}</span></span>`,
|
||||
`<span class="hate ${2 === e.action ? 'hated' : ''}"><i></i></span>`,
|
||||
'<span class="reply btn-hover">回复</span>',
|
||||
`<div class="operation btn-hover btn-hide-re"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canBlackList(e.mid) ? '<li class="blacklist">加入黑名单</li>' : ''
|
||||
}${this._canReport(e.mid) ? '<li class="report">举报</li>' : ''}${
|
||||
this._canDel(e.mid) ? `<li class="del" data-mid="${e.mid}">删除</li>` : ''
|
||||
}</ul></div></div>`,
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return t
|
||||
}
|
||||
} else {
|
||||
// 其他情况旧版评论区替换
|
||||
bbComment.prototype._createListCon = createListCon
|
||||
bbComment.prototype._createSubReplyItem = createSubReplyItem
|
||||
bbComment.prototype._createListCon =
|
||||
// 带IP属地显示的评论创建
|
||||
function listIcon(item, i, pos) {
|
||||
const blCon = this._parentBlacklistDom(item, i, pos)
|
||||
const con = [
|
||||
`<div class="con ${pos === i ? 'no-border' : ''}">`,
|
||||
`<div class="user">${this._createNickNameDom(item)}`,
|
||||
this._createLevelLink(item),
|
||||
this._identity(item.mid, item.assist, item.member.fans_detail),
|
||||
`${
|
||||
this._createNameplate(item.member.nameplate) + this._createUserSailing(item)
|
||||
}</div>`,
|
||||
this._createMsgContent(item),
|
||||
this._createPerfectReply(item),
|
||||
'<div class="info">',
|
||||
this._createPlatformDom(item.content.plat),
|
||||
'<span class="time-location">',
|
||||
'<span class="reply-time">'.concat(this._formateTime(item.ctime), '</span>'),
|
||||
item?.reply_control?.location
|
||||
? `<span class="reply-location" style="margin-left:${marginLeft}px;">${
|
||||
item?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
'</span>',
|
||||
item.lottery_id
|
||||
? ''
|
||||
: `<span class="like ${item.action === 1 ? 'liked' : ''}"><i></i><span>${
|
||||
item.like ? item.like : ''
|
||||
}</span></span>`,
|
||||
item.lottery_id
|
||||
? ''
|
||||
: `<span class="hate ${item.action === 2 ? 'hated' : ''}"><i></i></span>`,
|
||||
item.lottery_id ? '' : this._createReplyBtn(item.rcount),
|
||||
item.lottery_id && item.mid !== bbComment.userStatus.mid
|
||||
? ''
|
||||
: `<div class="operation more-operation"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canSetTop(item)
|
||||
? `<li class="set-top">${item.isUpTop ? '取消置顶' : '设为置顶'}</li>`
|
||||
: ''
|
||||
}${this._canBlackList(item.mid) ? '<li class="blacklist">加入黑名单</li>' : ''}${
|
||||
this._canReport(item.mid) ? '<li class="report">举报</li>' : ''
|
||||
}${
|
||||
this._canDel(item.mid) && !item.isTop
|
||||
? `<li class="del" data-mid="${item.mid}">删除</li>`
|
||||
: ''
|
||||
}</ul></div></div>`,
|
||||
this._createLotteryContent(item.content),
|
||||
this._createVoteContent(item.content),
|
||||
this._createTags(item),
|
||||
'</div>',
|
||||
'<div class="reply-box">',
|
||||
this._createSubReplyList(
|
||||
item.replies,
|
||||
item.rcount,
|
||||
false,
|
||||
item.rpid,
|
||||
item.folder && item.folder.has_folded,
|
||||
item.reply_control,
|
||||
),
|
||||
'</div>',
|
||||
'<div class="paging-box">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
return item.state === bbComment.blacklistCode ? blCon : con
|
||||
}
|
||||
bbComment.prototype._createSubReplyItem =
|
||||
// 带IP属地显示的回复创建
|
||||
function subReply(item, i) {
|
||||
const dom = [
|
||||
`<div class="reply-item reply-wrap" data-id="${item.rpid}" data-index="${i}">`,
|
||||
this._createSubReplyUserFace(item),
|
||||
'<div class="reply-con">',
|
||||
'<div class="user">',
|
||||
this._createNickNameDom(item),
|
||||
this._createLevelLink(item),
|
||||
this._identity(item.mid),
|
||||
this._createSubMsgContent(item),
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="info">',
|
||||
'<span class="time-location">',
|
||||
'<span class="reply-time">'.concat(this._formateTime(item.ctime), '</span>'),
|
||||
item?.reply_control?.location
|
||||
? `<span class="reply-location" style="margin-left:${marginLeft}px;">${
|
||||
item?.reply_control?.location || ''
|
||||
}</span>`
|
||||
: '',
|
||||
'</span>',
|
||||
`<span class="like ${item.action === 1 ? 'liked' : ''}"><i></i><span>${
|
||||
item.like ? item.like : ''
|
||||
}</span></span>`,
|
||||
`<span class="hate ${item.action === 2 ? 'hated' : ''}"><i></i></span>`,
|
||||
'<span class="reply btn-hover">回复</span>',
|
||||
`<div class="operation btn-hover btn-hide-re"><div class="spot"></div><div class="opera-list"><ul>${
|
||||
this._canBlackList(item.mid) ? '<li class="blacklist">加入黑名单</li>' : ''
|
||||
}${this._canReport(item.mid) ? '<li class="report">举报</li>' : ''}${
|
||||
this._canDel(item.mid) ? `<li class="del" data-mid="${item.mid}">删除</li>` : ''
|
||||
}</ul></div></div>`,
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')
|
||||
|
||||
return dom
|
||||
}
|
||||
}
|
||||
version = 1
|
||||
observer.disconnect()
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="download-cover-config download-video-config-section">
|
||||
<div class="download-video-config-item">
|
||||
<div class="download-video-config-title">封面:</div>
|
||||
<VDropdown v-model="type" :items="items">
|
||||
<VDropdown v-model:value="type" :items="items">
|
||||
<template #item="{ item }">
|
||||
{{ item }}
|
||||
</template>
|
||||
@ -10,37 +10,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { UnknownOptions } from '@/components/component'
|
||||
import type { UnknownOptions } from '@/components/component'
|
||||
import { VDropdown } from '@/ui'
|
||||
import { CoverDownloadType } from './types'
|
||||
import type { CoverDownloadType } from './types'
|
||||
|
||||
interface Options extends UnknownOptions {
|
||||
CoverType: CoverDownloadType | '无'
|
||||
}
|
||||
const { options } = getComponentSettings<Options>('downloadVideo')
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VDropdown,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: options.CoverType ?? '无',
|
||||
items: ['无', 'jpg'],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
enabled() {
|
||||
return this.type !== '无'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
type(newValue: CoverDownloadType) {
|
||||
options.CoverType = newValue
|
||||
},
|
||||
},
|
||||
const type = ref(options.CoverType ?? '无')
|
||||
const items = ['无', 'jpg']
|
||||
watch(type, newValue => {
|
||||
options.CoverType = newValue
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
@ -2,11 +2,11 @@ import { defineAsyncComponent } from 'vue'
|
||||
|
||||
import { defineComponentMetadata } from '@/components/define'
|
||||
import { getVideoCoverUrlByAid, getBlobByAid } from '@/components/video/video-cover'
|
||||
import { PackageEntry } from '@/core/download'
|
||||
import type { PackageEntry } from '@/core/download'
|
||||
import { videoAndBangumiUrls } from '@/core/utils/urls'
|
||||
import { Toast } from '@/core/toast'
|
||||
import { DownloadVideoAssets } from '../../video/download/types'
|
||||
import { CoverDownloadType } from './types'
|
||||
import type { DownloadVideoAssets } from '../../video/download/types'
|
||||
import type { CoverDownloadType } from './types'
|
||||
|
||||
export const component = defineComponentMetadata({
|
||||
name: 'viewCover',
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
|
||||
import type { OptionsOfMetadata } from '@/components/define'
|
||||
import { defineOptionsMetadata } from '@/components/define'
|
||||
|
||||
export const downloadDanmakuOptions = defineOptionsMetadata({
|
||||
speed: {
|
||||
|
||||
@ -9,7 +9,7 @@ import type { DanmakuType } from '../converter/danmaku-type'
|
||||
import { XmlDanmaku } from '../converter/xml-danmaku'
|
||||
import { playerAgent } from '@/components/video/player-agent'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { DownloadDanmakuOptions } from './options'
|
||||
import type { DownloadDanmakuOptions } from './options'
|
||||
|
||||
export class JsonDanmaku {
|
||||
// static SegmentSize = 6 * 60
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
class="video-default-location-extend-box"
|
||||
:class="{ 'video-default-location-extend-box-hidden': realHidden }"
|
||||
>
|
||||
<div class="video-default-location-extend-box-bar" @click="setRealHidden">
|
||||
<div class="video-default-location-extend-box-bar" @click="setRealHidden(!realHidden)">
|
||||
<div class="video-default-location-extend-box-bar-text">位置测试</div>
|
||||
<div
|
||||
class="video-default-location-extend-box-bar-btn"
|
||||
|
||||
@ -79,16 +79,16 @@
|
||||
class="run-download"
|
||||
type="primary"
|
||||
:disabled="!canStartDownload"
|
||||
@click="startDownload(outputOptions, selectedOutput)"
|
||||
@click="startDownload()"
|
||||
>
|
||||
开始
|
||||
</VButton>
|
||||
</div>
|
||||
</VPopup>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import type { Ref, ComponentPublicInstance } from 'vue'
|
||||
import { ref, defineComponent, reactive } from 'vue'
|
||||
import { ref, reactive, computed, watch, onMounted, useTemplateRef } from 'vue'
|
||||
import type { VideoQuality } from '@/components/video/video-quality'
|
||||
import { allQualities } from '@/components/video/video-quality'
|
||||
import type { TestPattern } from '@/core/common-types'
|
||||
@ -116,13 +116,13 @@ import type {
|
||||
} from './types'
|
||||
import { DownloadVideoAction } from './types'
|
||||
|
||||
const [inputs] = registerAndGetData('downloadVideo.inputs', [
|
||||
const [inputsRaw] = registerAndGetData('downloadVideo.inputs', [
|
||||
videoSingleInput,
|
||||
videoBatchInput,
|
||||
videoSeasonBatchInput,
|
||||
bangumiBatchInput,
|
||||
] as DownloadVideoInput[])
|
||||
const [apis] = registerAndGetData('downloadVideo.apis', [
|
||||
const [apisRaw] = registerAndGetData('downloadVideo.apis', [
|
||||
videoFlv,
|
||||
videoDashAvc,
|
||||
videoDashHevc,
|
||||
@ -130,7 +130,7 @@ const [apis] = registerAndGetData('downloadVideo.apis', [
|
||||
videoAudioDash,
|
||||
] as DownloadVideoApi[])
|
||||
const [assets] = registerAndGetData('downloadVideo.assets', [] as DownloadVideoAssets[])
|
||||
const [outputs] = registerAndGetData('downloadVideo.outputs', [
|
||||
const [outputsRaw] = registerAndGetData('downloadVideo.outputs', [
|
||||
streamSaverOutput,
|
||||
] as DownloadVideoOutput[])
|
||||
const { basicConfig } = getComponentSettings('downloadVideo').options as {
|
||||
@ -152,215 +152,196 @@ const getFallbackTestVideoInfo = () =>
|
||||
title: getFriendlyTitle(true),
|
||||
} as DownloadVideoInputItem)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
VPopup,
|
||||
VButton,
|
||||
VDropdown,
|
||||
VIcon,
|
||||
SwitchBox,
|
||||
},
|
||||
props: {
|
||||
triggerElement: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup: () => ({
|
||||
inputOptions: ref(null) as Ref<ComponentPublicInstance | null>,
|
||||
assetsOptions: ref(null) as Ref<ComponentPublicInstance[] | null>,
|
||||
outputOptions: ref(null) as Ref<ComponentPublicInstance | null>,
|
||||
}),
|
||||
data() {
|
||||
const lastOutput = basicConfig.output
|
||||
const lastUseBackupUrls = basicConfig.useBackupUrls
|
||||
return {
|
||||
open: false,
|
||||
busy: false,
|
||||
// 测试 videoInfo, 用于获取清晰度列表和预计大小
|
||||
testData: {
|
||||
// undefined: 无法获取; null: 获取中;
|
||||
videoInfo: null,
|
||||
// 是否有多P
|
||||
multiple: false,
|
||||
},
|
||||
assets,
|
||||
qualities: [] as VideoQuality[],
|
||||
selectedQuality: undefined,
|
||||
inputs: [] as DownloadVideoInput[],
|
||||
selectedInput: undefined,
|
||||
apis: [] as DownloadVideoApi[],
|
||||
selectedApi: undefined,
|
||||
outputs,
|
||||
selectedOutput: outputs.find(it => it.name === lastOutput) || outputs[0],
|
||||
useBackupUrls: lastUseBackupUrls || false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
assetsWithOptions(): DownloadVideoAssets[] {
|
||||
return (this.assets as DownloadVideoAssets[]).filter(a => a.component)
|
||||
},
|
||||
filteredQualities(): VideoQuality[] {
|
||||
if (this.qualities.length === 0) {
|
||||
return allQualities
|
||||
}
|
||||
return this.qualities
|
||||
},
|
||||
canStartDownload(): boolean {
|
||||
if (this.busy || !this.open) {
|
||||
return false
|
||||
}
|
||||
const isAnySelectionEmpty = [
|
||||
'selectedQuality',
|
||||
'selectedInput',
|
||||
'selectedApi',
|
||||
'selectedOutput',
|
||||
].some(prop => !this[prop])
|
||||
if (isAnySelectionEmpty) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedInput(input: DownloadVideoInput) {
|
||||
if (input === undefined) {
|
||||
return
|
||||
}
|
||||
this.updateTestVideoInfo()
|
||||
},
|
||||
selectedApi(api: DownloadVideoApi) {
|
||||
if (api === undefined) {
|
||||
return
|
||||
}
|
||||
this.updateTestVideoInfo()
|
||||
basicConfig.api = api.name
|
||||
},
|
||||
selectedOutput(output: DownloadVideoOutput) {
|
||||
if (output === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.output = output.name
|
||||
},
|
||||
useBackupUrls(useBackupUrls: boolean) {
|
||||
if (useBackupUrls === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.useBackupUrls = useBackupUrls
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
coreApis.observer.videoChange(() => {
|
||||
this.selectedInput = undefined
|
||||
this.selectedApi = undefined
|
||||
const inputOptions = useTemplateRef('inputOptions')
|
||||
const assetsOptions = useTemplateRef<ComponentPublicInstance[]>('assetsOptions')
|
||||
const outputOptions = useTemplateRef('outputOptions')
|
||||
|
||||
const matchedInputs = filterData(inputs)
|
||||
this.inputs = matchedInputs
|
||||
this.selectedInput = matchedInputs[0]
|
||||
const matchedApis = filterData(apis)
|
||||
this.apis = matchedApis
|
||||
const lastApi = matchedApis.find(api => api.name === basicConfig.api)
|
||||
if (lastApi) {
|
||||
this.selectedApi = lastApi
|
||||
} else {
|
||||
this.selectedApi = matchedApis[0]
|
||||
const { triggerElement } = defineProps<{ triggerElement: HTMLElement }>()
|
||||
|
||||
const open = ref(false)
|
||||
const busy = ref(false)
|
||||
const testData = reactive({
|
||||
// undefined: 无法获取; null: 获取中;
|
||||
videoInfo: null,
|
||||
// 是否有多P
|
||||
multiple: false,
|
||||
})
|
||||
const qualities = ref<VideoQuality[]>([])
|
||||
const selectedQuality = ref<VideoQuality | undefined>(undefined)
|
||||
const inputs = ref<DownloadVideoInput[]>([])
|
||||
const selectedInput = ref<DownloadVideoInput | undefined>(undefined)
|
||||
const apis = ref<DownloadVideoApi[]>([])
|
||||
const selectedApi = ref<DownloadVideoApi | undefined>(undefined)
|
||||
const outputs = ref<DownloadVideoOutput[]>(outputsRaw)
|
||||
const selectedOutput = ref<DownloadVideoOutput>(
|
||||
outputsRaw.find(it => it.name === basicConfig.output) || outputsRaw[0],
|
||||
)
|
||||
const useBackupUrls = ref<boolean>(basicConfig.useBackupUrls || false)
|
||||
|
||||
const assetsWithOptions = computed(() => (assets as DownloadVideoAssets[]).filter(a => a.component))
|
||||
const filteredQualities = computed(() =>
|
||||
qualities.value.length === 0 ? allQualities : qualities.value,
|
||||
)
|
||||
const canStartDownload = computed(() => {
|
||||
if (busy.value || !open.value) {
|
||||
return false
|
||||
}
|
||||
const isAnySelectionEmpty = [
|
||||
selectedQuality.value,
|
||||
selectedInput.value,
|
||||
selectedApi.value,
|
||||
selectedOutput.value,
|
||||
].some(v => !v)
|
||||
if (isAnySelectionEmpty) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const updateTestVideoInfo = async () => {
|
||||
if (!selectedInput.value || !selectedApi.value) {
|
||||
return
|
||||
}
|
||||
testData.videoInfo = null
|
||||
const input = selectedInput.value as DownloadVideoInput
|
||||
const testItem = input.getTestInput?.() ?? getFallbackTestVideoInfo()
|
||||
console.log('[updateTestVideoInfo]', testItem)
|
||||
testData.multiple = input.batch
|
||||
const api = selectedApi.value as DownloadVideoApi
|
||||
try {
|
||||
const videoInfo = await api.downloadVideoInfo(testItem)
|
||||
qualities.value = videoInfo.qualities
|
||||
const isSelectedQualityOutdated =
|
||||
!selectedQuality.value ||
|
||||
!videoInfo.qualities.some(q => q.value === selectedQuality.value?.value)
|
||||
if (isSelectedQualityOutdated) {
|
||||
selectedQuality.value = videoInfo.qualities[0]
|
||||
if (basicConfig.quality) {
|
||||
const [matchedQuality] = videoInfo.qualities.filter(q => q.value <= basicConfig.quality)
|
||||
if (matchedQuality) {
|
||||
selectedQuality.value = matchedQuality
|
||||
}
|
||||
}
|
||||
}
|
||||
// 填充 quality 后要再请求一次得到对应 quality 的统计数据
|
||||
testItem.quality = selectedQuality.value
|
||||
const qualityVideoInfo = await api.downloadVideoInfo(testItem)
|
||||
testData.videoInfo = qualityVideoInfo
|
||||
} catch (error) {
|
||||
console.error('[updateTestVideoInfo] failed', error)
|
||||
testData.videoInfo = undefined
|
||||
}
|
||||
}
|
||||
|
||||
watch(selectedInput, input => {
|
||||
if (input === undefined) {
|
||||
return
|
||||
}
|
||||
updateTestVideoInfo()
|
||||
})
|
||||
watch(selectedApi, api => {
|
||||
if (api === undefined) {
|
||||
return
|
||||
}
|
||||
updateTestVideoInfo()
|
||||
basicConfig.api = api.name
|
||||
})
|
||||
watch(selectedOutput, output => {
|
||||
if (output === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.output = output.name
|
||||
})
|
||||
watch(useBackupUrls, val => {
|
||||
if (val === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.useBackupUrls = val
|
||||
})
|
||||
|
||||
// 只有手动选择的清晰度要记录, 因此不能直接 watch
|
||||
const saveSelectedQuality = () => {
|
||||
const quality = selectedQuality.value
|
||||
if (quality === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.quality = quality.value
|
||||
updateTestVideoInfo()
|
||||
}
|
||||
|
||||
// const getVideoItems = async () => {
|
||||
// const input = selectedInput.value as DownloadVideoInput
|
||||
// const videoItems = await input.getInputs(inputOptions)
|
||||
// return videoItems
|
||||
// }
|
||||
|
||||
const startDownload = async () => {
|
||||
const instance = outputOptions.value as ComponentPublicInstance
|
||||
const output = selectedOutput.value
|
||||
try {
|
||||
busy.value = true
|
||||
const input = selectedInput.value as DownloadVideoInput
|
||||
const api = selectedApi.value as DownloadVideoApi
|
||||
const videoInputs = await input.getInputs(inputOptions)
|
||||
if (videoInputs.length === 0) {
|
||||
Toast.info('未接收到视频, 如果输入源支持批量, 请至少选择一个视频.', '下载视频', 3000)
|
||||
return
|
||||
}
|
||||
videoInputs.forEach(item => {
|
||||
item.quality = selectedQuality.value
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
formatFileSize,
|
||||
// 只有手动选择的清晰度要记录, 因此不能直接 watch
|
||||
saveSelectedQuality() {
|
||||
const quality: VideoQuality = this.selectedQuality
|
||||
if (quality === undefined) {
|
||||
return
|
||||
}
|
||||
basicConfig.quality = quality.value
|
||||
this.updateTestVideoInfo()
|
||||
},
|
||||
async getVideoItems() {
|
||||
const input = this.selectedInput as DownloadVideoInput
|
||||
const videoItems = await input.getInputs(this.inputOptions)
|
||||
return videoItems
|
||||
},
|
||||
async updateTestVideoInfo() {
|
||||
if (!this.selectedInput || !this.selectedApi) {
|
||||
return
|
||||
}
|
||||
this.testData.videoInfo = null
|
||||
const input = this.selectedInput as DownloadVideoInput
|
||||
const testItem = input.getTestInput?.() ?? getFallbackTestVideoInfo()
|
||||
console.log('[updateTestVideoInfo]', testItem)
|
||||
this.testData.multiple = input.batch
|
||||
const api = this.selectedApi as DownloadVideoApi
|
||||
try {
|
||||
const videoInfo = await api.downloadVideoInfo(testItem)
|
||||
this.qualities = videoInfo.qualities
|
||||
const isSelectedQualityOutdated =
|
||||
!this.selectedQuality ||
|
||||
!videoInfo.qualities.some(q => q.value === this.selectedQuality.value)
|
||||
if (isSelectedQualityOutdated) {
|
||||
this.selectedQuality = videoInfo.qualities[0]
|
||||
if (basicConfig.quality) {
|
||||
const [matchedQuality] = videoInfo.qualities.filter(q => q.value <= basicConfig.quality)
|
||||
if (matchedQuality) {
|
||||
this.selectedQuality = matchedQuality
|
||||
}
|
||||
}
|
||||
}
|
||||
// 填充 quality 后要再请求一次得到对应 quality 的统计数据
|
||||
testItem.quality = this.selectedQuality
|
||||
const qualityVideoInfo = await api.downloadVideoInfo(testItem)
|
||||
this.testData.videoInfo = qualityVideoInfo
|
||||
} catch (error) {
|
||||
console.error('[updateTestVideoInfo] failed', error)
|
||||
this.testData.videoInfo = undefined
|
||||
}
|
||||
},
|
||||
async startDownload(instance: ComponentPublicInstance, output: DownloadVideoOutput) {
|
||||
try {
|
||||
this.busy = true
|
||||
const input = this.selectedInput as DownloadVideoInput
|
||||
const api = this.selectedApi as DownloadVideoApi
|
||||
const videoInputs = await input.getInputs(this.inputOptions)
|
||||
if (videoInputs.length === 0) {
|
||||
Toast.info('未接收到视频, 如果输入源支持批量, 请至少选择一个视频.', '下载视频', 3000)
|
||||
return
|
||||
}
|
||||
videoInputs.forEach(item => {
|
||||
item.quality = this.selectedQuality
|
||||
const videoInfos = await Promise.all(videoInputs.map(i => api.downloadVideoInfo(i)))
|
||||
if (videoInfos.length === 0 || lodash.sumBy(videoInfos, it => it.fragments.length) === 0) {
|
||||
Toast.info('未接收到可下载数据, 请检查输入源和格式是否适用于当前视频.', '下载视频', 3000)
|
||||
return
|
||||
}
|
||||
if (useBackupUrls.value) {
|
||||
videoInfos.forEach(videoInfo => {
|
||||
videoInfo.fragments.forEach(fragment => {
|
||||
fragment.url =
|
||||
fragment.backupUrls && fragment.backupUrls.length !== 0
|
||||
? fragment.backupUrls.at(0)
|
||||
: fragment.url
|
||||
})
|
||||
const videoInfos = await Promise.all(videoInputs.map(i => api.downloadVideoInfo(i)))
|
||||
if (videoInfos.length === 0 || lodash.sumBy(videoInfos, it => it.fragments.length) === 0) {
|
||||
Toast.info('未接收到可下载数据, 请检查输入源和格式是否适用于当前视频.', '下载视频', 3000)
|
||||
return
|
||||
}
|
||||
if (this.useBackupUrls) {
|
||||
videoInfos.forEach(videoInfo => {
|
||||
videoInfo.fragments.forEach(fragment => {
|
||||
fragment.url =
|
||||
fragment.backupUrls && fragment.backupUrls.length !== 0
|
||||
? fragment.backupUrls.at(0)
|
||||
: fragment.url
|
||||
})
|
||||
})
|
||||
}
|
||||
const action = new DownloadVideoAction(videoInfos)
|
||||
assets.forEach(a => {
|
||||
const assetsType = a?.getUrls ? action.extraOnlineAssets : action.extraAssets
|
||||
assetsType.push({
|
||||
asset: a,
|
||||
instance: this.$refs.assetsOptions.find((c: any) => c.$attrs.name === a.name),
|
||||
})
|
||||
})
|
||||
await output.runAction(action, instance)
|
||||
await action.downloadExtraAssets()
|
||||
} catch (error) {
|
||||
logError(error)
|
||||
} finally {
|
||||
this.busy = false
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
const action = new DownloadVideoAction(videoInfos)
|
||||
for (const a of assets) {
|
||||
const assetsType = a?.getUrls ? action.extraOnlineAssets : action.extraAssets
|
||||
assetsType.push({
|
||||
asset: a,
|
||||
instance: assetsOptions.value.find(c => (c.$attrs.name as string) === a.name),
|
||||
})
|
||||
}
|
||||
await output.runAction(action, instance)
|
||||
await action.downloadExtraAssets()
|
||||
} catch (error) {
|
||||
logError(error)
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
coreApis.observer.videoChange(() => {
|
||||
selectedInput.value = undefined
|
||||
selectedApi.value = undefined
|
||||
|
||||
const matchedInputs = filterData(inputsRaw)
|
||||
inputs.value = matchedInputs
|
||||
selectedInput.value = matchedInputs[0]
|
||||
const matchedApis = filterData(apisRaw)
|
||||
apis.value = matchedApis
|
||||
const lastApi = matchedApis.find(api => api.name === basicConfig.api)
|
||||
if (lastApi) {
|
||||
selectedApi.value = lastApi
|
||||
} else {
|
||||
selectedApi.value = matchedApis[0]
|
||||
}
|
||||
})
|
||||
})
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
@ -9,7 +9,7 @@ import { compareQuality } from '../error'
|
||||
import type { DownloadVideoApi, DownloadVideoFragment, DownloadVideoInputItem } from '../types'
|
||||
import { DownloadVideoInfo } from '../types'
|
||||
import { bangumiApi, videoApi } from './url'
|
||||
import { Options } from '..'
|
||||
import type { Options } from '..'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
|
||||
/** dash 格式更明确的扩展名 */
|
||||
|
||||
@ -5,7 +5,8 @@ import { formatDuration, formatNumber } from '@/core/utils/formatters'
|
||||
import { logError } from '@/core/utils/log'
|
||||
import { formatTitle, getTitleVariablesFromDate } from '@/core/utils/title'
|
||||
import { videoUrls } from '@/core/utils/urls'
|
||||
|
||||
import type { BiliBiliQueryAidAndBvidResponse } from './types/aid-bvid-response'
|
||||
import type { BiliBiliQueryAidData } from './types/aid-response'
|
||||
import type { DownloadVideoInput } from '../../types'
|
||||
import type { EpisodeItem } from '../episode-item'
|
||||
import { createEpisodesPicker } from '../episode-item'
|
||||
@ -25,17 +26,17 @@ export const videoBatchInput: DownloadVideoInput = {
|
||||
logError(`获取视频选集列表失败, message = ${json.message}`)
|
||||
return []
|
||||
}
|
||||
const { pages, owner, pubdate } = json.data
|
||||
const { pages, owner, pubdate } = json.data as BiliBiliQueryAidData
|
||||
if (pages === undefined) {
|
||||
logError('获取视频选集列表失败, 没有找到选集信息.')
|
||||
return []
|
||||
}
|
||||
const date = getTitleVariablesFromDate(new Date(pubdate * 1000))
|
||||
return pages.map((page: any, index: number) => {
|
||||
const key = page.cid
|
||||
return pages.map((page, index: number) => {
|
||||
const cidString = page.cid.toString()
|
||||
const title = `P${page.page} ${page.part}`
|
||||
return {
|
||||
key,
|
||||
key: cidString,
|
||||
title,
|
||||
isChecked: index < instance.maxCheckedItems,
|
||||
durationText: formatDuration(page.duration),
|
||||
@ -43,7 +44,7 @@ export const videoBatchInput: DownloadVideoInput = {
|
||||
allowQualityDrop: true,
|
||||
title: formatTitle(getGeneralSettings().batchFilenameFormat, false, {
|
||||
n: formatNumber(page.page, pages.length),
|
||||
cid: page.cid,
|
||||
cid: cidString,
|
||||
ep: page.part,
|
||||
user: owner?.name,
|
||||
userID: owner?.mid?.toString(),
|
||||
@ -55,7 +56,7 @@ export const videoBatchInput: DownloadVideoInput = {
|
||||
publishSecond: date.second,
|
||||
publishMillisecond: date.millisecond,
|
||||
}),
|
||||
cid: page.cid,
|
||||
cid: cidString,
|
||||
aid,
|
||||
},
|
||||
} as EpisodeItem
|
||||
@ -73,13 +74,13 @@ export const videoSeasonBatchInput: DownloadVideoInput = {
|
||||
createEpisodesPicker(async instance => {
|
||||
const { aid, bvid } = unsafeWindow
|
||||
const api = `https://api.bilibili.com/x/web-interface/wbi/view/detail?bvid=${bvid}&aid=${aid}`
|
||||
const json = await getJsonWithCredentials(api)
|
||||
const json = await getJsonWithCredentials<BiliBiliQueryAidAndBvidResponse>(api)
|
||||
if (json.code !== 0) {
|
||||
logError(`获取视频合集列表失败, message = ${json.message}`)
|
||||
return []
|
||||
}
|
||||
const owner = lodash.get(json, 'data.View.owner', {})
|
||||
const sections: { episodes: any[] }[] = lodash.get(json, 'data.View.ugc_season.sections', [])
|
||||
const owner = json.data?.View?.owner || { name: '未知用户', mid: 0 }
|
||||
const sections = json.data?.View?.ugc_season?.sections || []
|
||||
if (sections.length === 0) {
|
||||
return []
|
||||
}
|
||||
@ -89,12 +90,12 @@ export const videoSeasonBatchInput: DownloadVideoInput = {
|
||||
return episodes.map((episode, episodeIndex) => {
|
||||
const currentIndex =
|
||||
episodeIndex + lodash.sumBy(sections.slice(0, sectionIndex), it => it.episodes.length)
|
||||
const key = episode.cid
|
||||
const cidString = episode.cid.toString()
|
||||
const page = currentIndex + 1
|
||||
const title = `P${page} ${episode.title}`
|
||||
const date = getTitleVariablesFromDate(new Date(episode.arc.pubdate * 1000))
|
||||
return {
|
||||
key,
|
||||
key: cidString,
|
||||
title,
|
||||
isChecked: currentIndex < instance.maxCheckedItems,
|
||||
durationText: formatDuration(episode.arc.duration),
|
||||
@ -103,9 +104,9 @@ export const videoSeasonBatchInput: DownloadVideoInput = {
|
||||
title: formatTitle(getGeneralSettings().batchFilenameFormat, false, {
|
||||
n: formatNumber(page, totalEpisodesLength),
|
||||
title: episode.page.part,
|
||||
cid: episode.cid,
|
||||
aid: episode.aid,
|
||||
bvid: episode.bvid,
|
||||
cid: cidString,
|
||||
aid: episode.aid.toString(),
|
||||
bvid: episode.bvid.toString(),
|
||||
ep: episode.title,
|
||||
user: owner.name,
|
||||
userID: owner.mid?.toString(),
|
||||
@ -117,8 +118,8 @@ export const videoSeasonBatchInput: DownloadVideoInput = {
|
||||
publishSecond: date.second,
|
||||
publishMillisecond: date.millisecond,
|
||||
}),
|
||||
cid: episode.cid,
|
||||
aid: episode.aid,
|
||||
cid: cidString,
|
||||
aid: episode.aid.toString(),
|
||||
},
|
||||
} as EpisodeItem
|
||||
})
|
||||
|
||||
@ -0,0 +1,571 @@
|
||||
export interface BiliBiliQueryAidAndBvidResponse {
|
||||
code: number
|
||||
message: string
|
||||
ttl: number
|
||||
data: BiliBiliQueryAidAndBvidData
|
||||
}
|
||||
|
||||
export interface BiliBiliQueryAidAndBvidData {
|
||||
View: View
|
||||
Card: Card2
|
||||
Tags: Tag[]
|
||||
Reply: Reply2
|
||||
Related: Related[]
|
||||
Spec: null
|
||||
hot_share: Hotshare
|
||||
elec: null
|
||||
emergency: Emergency
|
||||
view_addit: Viewaddit
|
||||
guide: null
|
||||
query_tags: null
|
||||
participle: null
|
||||
module_ctrl: null
|
||||
replace_recommend: boolean
|
||||
is_hit_labour_day_activity: boolean
|
||||
}
|
||||
|
||||
interface Viewaddit {
|
||||
'63': boolean
|
||||
'64': boolean
|
||||
'69': boolean
|
||||
'71': boolean
|
||||
'72': boolean
|
||||
}
|
||||
|
||||
interface Emergency {
|
||||
no_like: boolean
|
||||
no_coin: boolean
|
||||
no_fav: boolean
|
||||
no_share: boolean
|
||||
}
|
||||
|
||||
interface Hotshare {
|
||||
show: boolean
|
||||
list: any[]
|
||||
}
|
||||
|
||||
interface Related {
|
||||
aid: number
|
||||
videos: number
|
||||
tid: number
|
||||
tname: string
|
||||
copyright: number
|
||||
pic: string
|
||||
title: string
|
||||
pubdate: number
|
||||
ctime: number
|
||||
desc: string
|
||||
state: number
|
||||
duration: number
|
||||
rights: Rights3
|
||||
owner: Owner
|
||||
stat: Stat4
|
||||
dynamic: string
|
||||
cid: number
|
||||
dimension: Dimension
|
||||
short_link_v2: string
|
||||
first_frame: string
|
||||
pub_location: string
|
||||
cover43: string
|
||||
tidv2: number
|
||||
tnamev2: string
|
||||
pid_v2: number
|
||||
pid_name_v2: string
|
||||
bvid: string
|
||||
season_type: number
|
||||
is_ogv: boolean
|
||||
ogv_info: null
|
||||
rcmd_reason: string
|
||||
enable_vt: number
|
||||
ai_rcmd: Aircmd
|
||||
season_id?: number
|
||||
mission_id?: number
|
||||
up_from_v2?: number
|
||||
}
|
||||
|
||||
interface Aircmd {
|
||||
id: number
|
||||
goto: string
|
||||
trackid: string
|
||||
uniq_id: string
|
||||
}
|
||||
|
||||
interface Stat4 {
|
||||
aid: number
|
||||
view: number
|
||||
danmaku: number
|
||||
reply: number
|
||||
favorite: number
|
||||
coin: number
|
||||
share: number
|
||||
now_rank: number
|
||||
his_rank: number
|
||||
like: number
|
||||
dislike: number
|
||||
vt: number
|
||||
vv: number
|
||||
fav_g: number
|
||||
like_g: number
|
||||
}
|
||||
|
||||
interface Rights3 {
|
||||
bp: number
|
||||
elec: number
|
||||
download: number
|
||||
movie: number
|
||||
pay: number
|
||||
hd5: number
|
||||
no_reprint: number
|
||||
autoplay: number
|
||||
ugc_pay: number
|
||||
is_cooperation: number
|
||||
ugc_pay_preview: number
|
||||
no_background: number
|
||||
arc_pay: number
|
||||
pay_free_watch: number
|
||||
}
|
||||
|
||||
interface Reply2 {
|
||||
page: null
|
||||
replies: Reply[]
|
||||
}
|
||||
|
||||
interface Reply {
|
||||
rpid: number
|
||||
oid: number
|
||||
type: number
|
||||
mid: number
|
||||
root: number
|
||||
parent: number
|
||||
dialog: number
|
||||
count: number
|
||||
rcount: number
|
||||
state: number
|
||||
fansgrade: number
|
||||
attr: number
|
||||
ctime: number
|
||||
like: number
|
||||
action: number
|
||||
content: null
|
||||
replies: null
|
||||
assist: number
|
||||
show_follow: boolean
|
||||
}
|
||||
|
||||
interface Tag {
|
||||
tag_id: number
|
||||
tag_name: string
|
||||
music_id: string
|
||||
tag_type: string
|
||||
jump_url: string
|
||||
}
|
||||
|
||||
interface Card2 {
|
||||
card: Card
|
||||
space: Space
|
||||
following: boolean
|
||||
archive_count: number
|
||||
article_count: number
|
||||
follower: number
|
||||
like_num: number
|
||||
}
|
||||
|
||||
interface Space {
|
||||
s_img: string
|
||||
l_img: string
|
||||
}
|
||||
|
||||
interface Card {
|
||||
mid: string
|
||||
name: string
|
||||
approve: boolean
|
||||
sex: string
|
||||
rank: string
|
||||
face: string
|
||||
face_nft: number
|
||||
face_nft_type: number
|
||||
DisplayRank: string
|
||||
regtime: number
|
||||
spacesta: number
|
||||
birthday: string
|
||||
place: string
|
||||
description: string
|
||||
article: number
|
||||
attentions: any[]
|
||||
fans: number
|
||||
friend: number
|
||||
attention: number
|
||||
sign: string
|
||||
level_info: Levelinfo
|
||||
pendant: Pendant
|
||||
nameplate: Nameplate
|
||||
Official: Official
|
||||
official_verify: Officialverify
|
||||
vip: Vip
|
||||
is_senior_member: number
|
||||
name_render: null
|
||||
}
|
||||
|
||||
interface Vip {
|
||||
type: number
|
||||
status: number
|
||||
due_date: number
|
||||
vip_pay_type: number
|
||||
theme_type: number
|
||||
label: Label
|
||||
avatar_subscript: number
|
||||
nickname_color: string
|
||||
role: number
|
||||
avatar_subscript_url: string
|
||||
tv_vip_status: number
|
||||
tv_vip_pay_type: number
|
||||
tv_due_date: number
|
||||
avatar_icon: Avataricon
|
||||
vipType: number
|
||||
vipStatus: number
|
||||
}
|
||||
|
||||
interface Avataricon {
|
||||
icon_resource: Honorreply
|
||||
}
|
||||
|
||||
interface Label {
|
||||
path: string
|
||||
text: string
|
||||
label_theme: string
|
||||
text_color: string
|
||||
bg_style: number
|
||||
bg_color: string
|
||||
border_color: string
|
||||
use_img_label: boolean
|
||||
img_label_uri_hans: string
|
||||
img_label_uri_hant: string
|
||||
img_label_uri_hans_static: string
|
||||
img_label_uri_hant_static: string
|
||||
}
|
||||
|
||||
interface Officialverify {
|
||||
type: number
|
||||
desc: string
|
||||
}
|
||||
|
||||
interface Official {
|
||||
role: number
|
||||
title: string
|
||||
desc: string
|
||||
type: number
|
||||
}
|
||||
|
||||
interface Nameplate {
|
||||
nid: number
|
||||
name: string
|
||||
image: string
|
||||
image_small: string
|
||||
level: string
|
||||
condition: string
|
||||
}
|
||||
|
||||
interface Pendant {
|
||||
pid: number
|
||||
name: string
|
||||
image: string
|
||||
expire: number
|
||||
image_enhance: string
|
||||
image_enhance_frame: string
|
||||
n_pid: number
|
||||
}
|
||||
|
||||
interface Levelinfo {
|
||||
current_level: number
|
||||
current_min: number
|
||||
current_exp: number
|
||||
next_exp: number
|
||||
}
|
||||
|
||||
interface View {
|
||||
bvid: string
|
||||
aid: number
|
||||
videos: number
|
||||
tid: number
|
||||
tid_v2: number
|
||||
tname: string
|
||||
tname_v2: string
|
||||
copyright: number
|
||||
pic: string
|
||||
title: string
|
||||
pubdate: number
|
||||
ctime: number
|
||||
desc: string
|
||||
desc_v2: Descv2[]
|
||||
state: number
|
||||
duration: number
|
||||
rights: Rights
|
||||
owner: Owner
|
||||
stat: Stat
|
||||
argue_info: Argueinfo
|
||||
dynamic: string
|
||||
cid: number
|
||||
dimension: Dimension
|
||||
season_id: number
|
||||
premiere: null
|
||||
teenage_mode: number
|
||||
is_chargeable_season: boolean
|
||||
is_story: boolean
|
||||
is_upower_exclusive: boolean
|
||||
is_upower_play: boolean
|
||||
is_upower_preview: boolean
|
||||
enable_vt: number
|
||||
vt_display: string
|
||||
is_upower_exclusive_with_qa: boolean
|
||||
no_cache: boolean
|
||||
pages: Page[]
|
||||
subtitle: Subtitle
|
||||
ugc_season: Ugcseason
|
||||
is_season_display: boolean
|
||||
user_garb: Usergarb
|
||||
honor_reply: Honorreply
|
||||
like_icon: string
|
||||
need_jump_bv: boolean
|
||||
disable_show_up_info: boolean
|
||||
is_story_play: number
|
||||
is_view_self: boolean
|
||||
}
|
||||
|
||||
interface Honorreply {}
|
||||
|
||||
interface Usergarb {
|
||||
url_image_ani_cut: string
|
||||
}
|
||||
|
||||
interface Ugcseason {
|
||||
id: number
|
||||
title: string
|
||||
cover: string
|
||||
mid: number
|
||||
intro: string
|
||||
sign_state: number
|
||||
attribute: number
|
||||
sections: Section[]
|
||||
stat: Stat3
|
||||
ep_count: number
|
||||
season_type: number
|
||||
is_pay_season: boolean
|
||||
enable_vt: number
|
||||
}
|
||||
|
||||
interface Stat3 {
|
||||
season_id: number
|
||||
view: number
|
||||
danmaku: number
|
||||
reply: number
|
||||
fav: number
|
||||
coin: number
|
||||
share: number
|
||||
now_rank: number
|
||||
his_rank: number
|
||||
like: number
|
||||
vt: number
|
||||
vv: number
|
||||
}
|
||||
|
||||
interface Section {
|
||||
season_id: number
|
||||
id: number
|
||||
title: string
|
||||
type: number
|
||||
episodes: Episode[]
|
||||
}
|
||||
|
||||
interface Episode {
|
||||
season_id: number
|
||||
section_id: number
|
||||
id: number
|
||||
aid: number
|
||||
cid: number
|
||||
title: string
|
||||
attribute: number
|
||||
arc: Arc
|
||||
page: Page2
|
||||
bvid: string
|
||||
pages: Page2[]
|
||||
}
|
||||
|
||||
interface Page2 {
|
||||
cid: number
|
||||
page: number
|
||||
from: string
|
||||
part: string
|
||||
duration: number
|
||||
vid: string
|
||||
weblink: string
|
||||
dimension: Dimension
|
||||
}
|
||||
|
||||
interface Arc {
|
||||
aid: number
|
||||
videos: number
|
||||
type_id: number
|
||||
type_name: string
|
||||
copyright: number
|
||||
pic: string
|
||||
title: string
|
||||
pubdate: number
|
||||
ctime: number
|
||||
desc: string
|
||||
state: number
|
||||
duration: number
|
||||
rights: Rights2
|
||||
author: Owner
|
||||
stat: Stat2
|
||||
dynamic: string
|
||||
dimension: Dimension
|
||||
desc_v2: null
|
||||
is_chargeable_season: boolean
|
||||
is_blooper: boolean
|
||||
enable_vt: number
|
||||
vt_display: string
|
||||
type_id_v2: number
|
||||
type_name_v2: string
|
||||
is_lesson_video: number
|
||||
}
|
||||
|
||||
interface Stat2 {
|
||||
aid: number
|
||||
view: number
|
||||
danmaku: number
|
||||
reply: number
|
||||
fav: number
|
||||
coin: number
|
||||
share: number
|
||||
now_rank: number
|
||||
his_rank: number
|
||||
like: number
|
||||
dislike: number
|
||||
evaluation: string
|
||||
argue_msg: string
|
||||
vt: number
|
||||
vv: number
|
||||
}
|
||||
|
||||
interface Rights2 {
|
||||
bp: number
|
||||
elec: number
|
||||
download: number
|
||||
movie: number
|
||||
pay: number
|
||||
hd5: number
|
||||
no_reprint: number
|
||||
autoplay: number
|
||||
ugc_pay: number
|
||||
is_cooperation: number
|
||||
ugc_pay_preview: number
|
||||
arc_pay: number
|
||||
free_watch: number
|
||||
}
|
||||
|
||||
interface Subtitle {
|
||||
allow_submit: boolean
|
||||
list: List[]
|
||||
}
|
||||
|
||||
interface List {
|
||||
id: number
|
||||
lan: string
|
||||
lan_doc: string
|
||||
is_lock: boolean
|
||||
subtitle_url: string
|
||||
type: number
|
||||
id_str: string
|
||||
ai_type: number
|
||||
ai_status: number
|
||||
author: Author
|
||||
}
|
||||
|
||||
interface Author {
|
||||
mid: number
|
||||
name: string
|
||||
sex: string
|
||||
face: string
|
||||
sign: string
|
||||
rank: number
|
||||
birthday: number
|
||||
is_fake_account: number
|
||||
is_deleted: number
|
||||
in_reg_audit: number
|
||||
is_senior_member: number
|
||||
name_render: null
|
||||
}
|
||||
|
||||
interface Page {
|
||||
cid: number
|
||||
page: number
|
||||
from: string
|
||||
part: string
|
||||
duration: number
|
||||
vid: string
|
||||
weblink: string
|
||||
dimension: Dimension
|
||||
first_frame: string
|
||||
ctime: number
|
||||
}
|
||||
|
||||
interface Dimension {
|
||||
width: number
|
||||
height: number
|
||||
rotate: number
|
||||
}
|
||||
|
||||
interface Argueinfo {
|
||||
argue_msg: string
|
||||
argue_type: number
|
||||
argue_link: string
|
||||
}
|
||||
|
||||
interface Stat {
|
||||
aid: number
|
||||
view: number
|
||||
danmaku: number
|
||||
reply: number
|
||||
favorite: number
|
||||
coin: number
|
||||
share: number
|
||||
now_rank: number
|
||||
his_rank: number
|
||||
like: number
|
||||
dislike: number
|
||||
evaluation: string
|
||||
vt: number
|
||||
}
|
||||
|
||||
interface Owner {
|
||||
mid: number
|
||||
name: string
|
||||
face: string
|
||||
}
|
||||
|
||||
interface Rights {
|
||||
bp: number
|
||||
elec: number
|
||||
download: number
|
||||
movie: number
|
||||
pay: number
|
||||
hd5: number
|
||||
no_reprint: number
|
||||
autoplay: number
|
||||
ugc_pay: number
|
||||
is_cooperation: number
|
||||
ugc_pay_preview: number
|
||||
no_background: number
|
||||
clean_mode: number
|
||||
is_stein_gate: number
|
||||
is_360: number
|
||||
no_share: number
|
||||
arc_pay: number
|
||||
free_watch: number
|
||||
}
|
||||
|
||||
interface Descv2 {
|
||||
raw_text: string
|
||||
type: number
|
||||
biz_id: number
|
||||
}
|
||||
@ -0,0 +1,165 @@
|
||||
export interface BiliBiliQueryAidResponse {
|
||||
code: number
|
||||
message: string
|
||||
ttl: number
|
||||
data: BiliBiliQueryAidData
|
||||
}
|
||||
|
||||
export interface BiliBiliQueryAidData {
|
||||
bvid: string
|
||||
aid: number
|
||||
videos: number
|
||||
tid: number
|
||||
tid_v2: number
|
||||
tname: string
|
||||
tname_v2: string
|
||||
copyright: number
|
||||
pic: string
|
||||
title: string
|
||||
pubdate: number
|
||||
ctime: number
|
||||
desc: string
|
||||
desc_v2: Descv2[]
|
||||
state: number
|
||||
duration: number
|
||||
rights: Rights
|
||||
owner: Owner
|
||||
stat: Stat
|
||||
argue_info: Argueinfo
|
||||
dynamic: string
|
||||
cid: number
|
||||
dimension: Dimension
|
||||
premiere: null
|
||||
teenage_mode: number
|
||||
is_chargeable_season: boolean
|
||||
is_story: boolean
|
||||
is_upower_exclusive: boolean
|
||||
is_upower_play: boolean
|
||||
is_upower_preview: boolean
|
||||
enable_vt: number
|
||||
vt_display: string
|
||||
is_upower_exclusive_with_qa: boolean
|
||||
no_cache: boolean
|
||||
pages: Page[]
|
||||
subtitle: Subtitle
|
||||
is_season_display: boolean
|
||||
user_garb: Usergarb
|
||||
honor_reply: Honorreply
|
||||
like_icon: string
|
||||
need_jump_bv: boolean
|
||||
disable_show_up_info: boolean
|
||||
is_story_play: number
|
||||
is_view_self: boolean
|
||||
}
|
||||
|
||||
interface Honorreply {}
|
||||
|
||||
interface Usergarb {
|
||||
url_image_ani_cut: string
|
||||
}
|
||||
|
||||
interface Subtitle {
|
||||
allow_submit: boolean
|
||||
list: List[]
|
||||
}
|
||||
|
||||
interface List {
|
||||
id: number
|
||||
lan: string
|
||||
lan_doc: string
|
||||
is_lock: boolean
|
||||
subtitle_url: string
|
||||
type: number
|
||||
id_str: string
|
||||
ai_type: number
|
||||
ai_status: number
|
||||
author: Author
|
||||
}
|
||||
|
||||
interface Author {
|
||||
mid: number
|
||||
name: string
|
||||
sex: string
|
||||
face: string
|
||||
sign: string
|
||||
rank: number
|
||||
birthday: number
|
||||
is_fake_account: number
|
||||
is_deleted: number
|
||||
in_reg_audit: number
|
||||
is_senior_member: number
|
||||
name_render: null
|
||||
}
|
||||
|
||||
interface Page {
|
||||
cid: number
|
||||
page: number
|
||||
from: string
|
||||
part: string
|
||||
duration: number
|
||||
vid: string
|
||||
weblink: string
|
||||
dimension: Dimension
|
||||
ctime: number
|
||||
}
|
||||
|
||||
interface Dimension {
|
||||
width: number
|
||||
height: number
|
||||
rotate: number
|
||||
}
|
||||
|
||||
interface Argueinfo {
|
||||
argue_msg: string
|
||||
argue_type: number
|
||||
argue_link: string
|
||||
}
|
||||
|
||||
interface Stat {
|
||||
aid: number
|
||||
view: number
|
||||
danmaku: number
|
||||
reply: number
|
||||
favorite: number
|
||||
coin: number
|
||||
share: number
|
||||
now_rank: number
|
||||
his_rank: number
|
||||
like: number
|
||||
dislike: number
|
||||
evaluation: string
|
||||
vt: number
|
||||
}
|
||||
|
||||
interface Owner {
|
||||
mid: number
|
||||
name: string
|
||||
face: string
|
||||
}
|
||||
|
||||
interface Rights {
|
||||
bp: number
|
||||
elec: number
|
||||
download: number
|
||||
movie: number
|
||||
pay: number
|
||||
hd5: number
|
||||
no_reprint: number
|
||||
autoplay: number
|
||||
ugc_pay: number
|
||||
is_cooperation: number
|
||||
ugc_pay_preview: number
|
||||
no_background: number
|
||||
clean_mode: number
|
||||
is_stein_gate: number
|
||||
is_360: number
|
||||
no_share: number
|
||||
arc_pay: number
|
||||
free_watch: number
|
||||
}
|
||||
|
||||
interface Descv2 {
|
||||
raw_text: string
|
||||
type: number
|
||||
biz_id: number
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="download-video-config-section">
|
||||
<div class="download-video-config-item">
|
||||
<div>元数据:</div>
|
||||
<VDropdown v-model="type" :items="items">
|
||||
<VDropdown v-model:value="type" :items="items">
|
||||
<template #item="{ item }">
|
||||
{{ item }}
|
||||
</template>
|
||||
@ -10,35 +10,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { VDropdown } from '@/ui'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { MetadataType } from './metadata'
|
||||
import type { MetadataType } from './metadata'
|
||||
|
||||
interface Options {
|
||||
type Options = {
|
||||
metadataType: MetadataType | '无'
|
||||
}
|
||||
const options = getComponentSettings('downloadVideo').options as Options
|
||||
const { options } = getComponentSettings<Options>('downloadVideo')
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
VDropdown,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: options.metadataType ?? '无',
|
||||
items: ['无', 'ffmetadata', 'ogm'],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
enabled() {
|
||||
return this.type !== '无'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
type(value: MetadataType) {
|
||||
options.metadataType = value
|
||||
},
|
||||
},
|
||||
const type = ref(options.metadataType ?? '无')
|
||||
const items = ['无', 'ffmetadata', 'ogm']
|
||||
|
||||
watch(type, newValue => {
|
||||
options.metadataType = newValue
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -16,33 +16,23 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { DefaultWidget } from '@/ui'
|
||||
import { logError } from '@/core/utils/log'
|
||||
import { DownloadPackage } from '@/core/download'
|
||||
import { getFriendlyTitle } from '@/core/utils/title'
|
||||
import { MetadataType, generateByType } from './metadata'
|
||||
import { type MetadataType, generateByType } from './metadata'
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
DefaultWidget,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
disabled: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async run(type: MetadataType) {
|
||||
try {
|
||||
this.disabled = true
|
||||
DownloadPackage.single(`${getFriendlyTitle(true)}.${type}.txt`, await generateByType(type))
|
||||
} catch (error) {
|
||||
logError(error)
|
||||
} finally {
|
||||
this.disabled = false
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
const disabled = ref(false)
|
||||
const run = async (type: MetadataType) => {
|
||||
try {
|
||||
disabled.value = true
|
||||
DownloadPackage.single(`${getFriendlyTitle(true)}.${type}.txt`, await generateByType(type))
|
||||
} catch (error) {
|
||||
logError(error)
|
||||
} finally {
|
||||
disabled.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { defineComponentMetadata } from '@/components/define'
|
||||
import { PackageEntry } from '@/core/download'
|
||||
import type { PackageEntry } from '@/core/download'
|
||||
import { hasVideo } from '@/core/spin-query'
|
||||
import { Toast } from '@/core/toast'
|
||||
import { videoUrls } from '@/core/utils/urls'
|
||||
import { DownloadVideoAssets } from '../download/types'
|
||||
import { generateByType, MetadataType } from './metadata'
|
||||
import type { DownloadVideoAssets } from '../download/types'
|
||||
import type { MetadataType } from './metadata'
|
||||
import { generateByType } from './metadata'
|
||||
import { options } from './options'
|
||||
|
||||
export const title = '保存视频元数据'
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { VideoInfo, VideoPageInfo } from '@/components/video/video-info'
|
||||
import { VideoQuality } from '@/components/video/video-quality'
|
||||
import type { VideoPageInfo } from '@/components/video/video-info'
|
||||
import { VideoInfo } from '@/components/video/video-info'
|
||||
import type { VideoQuality } from '@/components/video/video-quality'
|
||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||
import { meta } from '@/core/meta'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { Toast } from '@/core/toast'
|
||||
import { name as componentName, title as pluginTitle } from '.'
|
||||
import { FieldsMode, Options } from './options'
|
||||
import type { Options } from './options'
|
||||
import { FieldsMode } from './options'
|
||||
|
||||
export type MetadataType = 'ffmetadata' | 'ogm'
|
||||
|
||||
function escape(s: string) {
|
||||
function mescape(s: string) {
|
||||
return s.replace(/[=;#\\\n]/g, r => `\\${r}`)
|
||||
}
|
||||
|
||||
@ -57,7 +59,7 @@ async function fetchMetadata(aid: string = unsafeWindow.aid, cid: string = unsaf
|
||||
}
|
||||
|
||||
function ff(key: string, value: any, prefix = true) {
|
||||
return `${prefix ? 'bilibili_' : ''}${key}=${escape(lodash.toString(value))}`
|
||||
return `${prefix ? 'bilibili_' : ''}${key}=${mescape(lodash.toString(value))}`
|
||||
}
|
||||
|
||||
async function generateFFMetadata(aid: string = unsafeWindow.aid, cid: string = unsafeWindow.cid) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
|
||||
import type { OptionsOfMetadata } from '@/components/define'
|
||||
import { defineOptionsMetadata } from '@/components/define'
|
||||
|
||||
export enum FieldsMode {
|
||||
ALL = '全部',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
|
||||
import { defineOptionsMetadata, type OptionsOfMetadata } from '@/components/define'
|
||||
|
||||
export enum DisplayMode {
|
||||
Auto = '自动',
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
<div class="lists">
|
||||
选择快速收藏夹:
|
||||
<VDropdown
|
||||
v-model="selectedFavoriteList"
|
||||
v-model:value="selectedFavoriteList"
|
||||
:items="list"
|
||||
:key-mapper="it => it.id"
|
||||
:key-mapper="it => (it as DisplayItem).id"
|
||||
@change="saveFavoriteList"
|
||||
/>
|
||||
</div>
|
||||
@ -40,6 +40,7 @@ import { logError } from '@/core/utils/log'
|
||||
import { VDropdown } from '@/ui'
|
||||
import { DisplayMode, type Options } from './options'
|
||||
|
||||
type DisplayItem = { displayName: string; id: number }
|
||||
const { options } = getComponentSettings('quickFavorite')
|
||||
interface RawFavoriteListItem {
|
||||
id: number
|
||||
@ -70,7 +71,7 @@ export default defineComponent({
|
||||
tipText: '',
|
||||
tipShowing: false,
|
||||
tipHandle: 0,
|
||||
list: [] as { displayName: string; id: number }[],
|
||||
list: [] as DisplayItem[],
|
||||
selectedFavoriteList: EmptyFavoriteList,
|
||||
listShowing: false,
|
||||
displayMode,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
|
||||
import { defineOptionsMetadata, type OptionsOfMetadata } from '@/components/define'
|
||||
|
||||
export enum DisplayMode {
|
||||
Auto = '自动',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { PluginMetadata } from '@/plugins/plugin'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
import type { CustomNavbarItemInit } from '../../../components/style/custom-navbar/custom-navbar-item'
|
||||
|
||||
export const plugin: PluginMetadata = {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { PluginMetadata } from '@/plugins/plugin'
|
||||
import { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
import type { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
|
||||
export const plugin: PluginMetadata = {
|
||||
name: 'downloadVideo.outputs.empty',
|
||||
|
||||
@ -10,27 +10,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { TextBox } from '@/ui'
|
||||
|
||||
const { options } = getComponentSettings<ConfigDataType>('downloadVideo')
|
||||
|
||||
export default Vue.extend<ConfigDataType>({
|
||||
components: {
|
||||
TextBox,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
...lodash.pick(options, ['api_dev_key', 'api_user_key']),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange() {
|
||||
Object.assign(options, lodash.pick(this, ['api_dev_key', 'api_user_key']))
|
||||
},
|
||||
},
|
||||
})
|
||||
const api_dev_key = ref(options.api_dev_key || '')
|
||||
const api_user_key = ref(options.api_user_key || '')
|
||||
|
||||
const onChange = () => {
|
||||
Object.assign(options, {
|
||||
api_dev_key: api_dev_key.value,
|
||||
api_user_key: api_user_key.value,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
@ -40,8 +35,6 @@ export default Vue.extend<ConfigDataType>({
|
||||
@include v-stretch(12px);
|
||||
> .config-item {
|
||||
@include h-center(8px);
|
||||
> .item-name {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { monkey } from '@/core/ajax'
|
||||
import { logError } from '@/core/utils/log'
|
||||
import { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import type { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
|
||||
const getPastebinUrl = async (str: string, config: ConfigDataType) => {
|
||||
const sp = new URLSearchParams()
|
||||
Object.entries({
|
||||
const sp = new URLSearchParams({
|
||||
api_dev_key: config.api_dev_key,
|
||||
api_user_key: config.api_user_key, // ! 必须绑定一个账号,否则链接可能被吞
|
||||
api_folder_key: 'm3u',
|
||||
@ -12,7 +11,7 @@ const getPastebinUrl = async (str: string, config: ConfigDataType) => {
|
||||
api_paste_code: str,
|
||||
api_paste_private: '1',
|
||||
api_paste_expire_date: '10M',
|
||||
}).forEach(([key, value]) => sp.append(key, value))
|
||||
})
|
||||
const response = await monkey<string>({
|
||||
url: 'https://pastebin.com/api/api_post.php',
|
||||
method: 'POST',
|
||||
@ -24,7 +23,7 @@ const getPastebinUrl = async (str: string, config: ConfigDataType) => {
|
||||
responseType: 'text',
|
||||
fetch: true,
|
||||
})
|
||||
if (/^Bad API request,/.test(response)) {
|
||||
if (response.startsWith('Bad API request,')) {
|
||||
throw response
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { PluginMetadata } from '@/plugins/plugin'
|
||||
import { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
import type { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import { MPV_Ex } from './handler'
|
||||
|
||||
export const plugin: PluginMetadata = {
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { SwitchBox } from '@/ui'
|
||||
import { isComponentEnabled, getComponentSettings } from '@/core/settings'
|
||||
|
||||
@ -20,22 +21,11 @@ const defaultOptions: Options = {
|
||||
}
|
||||
const { options: storedOptions } = getComponentSettings('downloadVideo')
|
||||
const options: Options = { ...defaultOptions, ...storedOptions }
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
SwitchBox,
|
||||
},
|
||||
data() {
|
||||
const shouldShow = isComponentEnabled('saveVideoMetadata')
|
||||
return {
|
||||
shouldShow,
|
||||
muxWithMetadata: shouldShow && options.muxWithMetadata,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveOptions() {
|
||||
options.muxWithMetadata = this.muxWithMetadata
|
||||
Object.assign(storedOptions, options)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const shouldShow = isComponentEnabled('saveVideoMetadata')
|
||||
const muxWithMetadata = ref(shouldShow && options.muxWithMetadata)
|
||||
const saveOptions = () => {
|
||||
options.muxWithMetadata = muxWithMetadata.value
|
||||
Object.assign(storedOptions, options)
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { DownloadPackage, PackageEntry } from '@/core/download'
|
||||
import { DownloadPackage, type PackageEntry } from '@/core/download'
|
||||
import { meta } from '@/core/meta'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import { Toast } from '@/core/toast'
|
||||
import { formatFileSize, formatPercent } from '@/core/utils/formatters'
|
||||
import { title as pluginTitle } from '.'
|
||||
import type { Options } from '../../../../components/video/download'
|
||||
import { DownloadVideoAction } from '../../../../components/video/download/types'
|
||||
import type { DownloadVideoAction } from '../../../../components/video/download/types'
|
||||
import { FFmpeg } from './ffmpeg'
|
||||
import { getCacheOrFetch, httpGet, toastProgress, toBlobUrl } from './utils'
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Toast } from '@/core/toast'
|
||||
import { PluginMetadata } from '@/plugins/plugin'
|
||||
import { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
import type { DownloadVideoOutput } from '../../../../components/video/download/types'
|
||||
import { run } from './handler'
|
||||
|
||||
export const title = 'WASM 混流输出'
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Toast } from '@/core/toast'
|
||||
import type { Toast } from '@/core/toast'
|
||||
import { formatFileSize, formatPercent } from '@/core/utils/formatters'
|
||||
import { getOrLoad, storeNames } from './database'
|
||||
import { RuntimeLibraryDefinition, RuntimeLibrary } from '@/core/runtime-library'
|
||||
import type { RuntimeLibraryDefinition } from '@/core/runtime-library'
|
||||
import { RuntimeLibrary } from '@/core/runtime-library'
|
||||
|
||||
type OnProgress = (received: number, total: number) => void
|
||||
|
||||
|
||||
@ -112,9 +112,7 @@ const parseCard = async (element: HTMLElement): Promise<FeedsCard> => {
|
||||
return [currentText, currentTitle].filter(it => Boolean(it)).join('\n')
|
||||
}
|
||||
const getNumber = async (selector: string) => {
|
||||
const result = Number.parseIntarseIntarseIntarseIntarseIntarseIntarseIntarseIntarseIntarseInt(
|
||||
await getSimpleText(selector),
|
||||
)
|
||||
const result = Number.parseInt(await getSimpleText(selector))
|
||||
if (isNaN(result)) {
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ export class FeedsCardsManagerV2 extends FeedsCardsManager {
|
||||
if (!isNodeValid(node)) {
|
||||
return
|
||||
}
|
||||
const vueData = getVue2Data(node)
|
||||
const vueData = getVueData(node)
|
||||
if (!vueData) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -41,11 +41,11 @@ export class BingTranslate extends MachineTranslateProvider {
|
||||
const response = await monkey({
|
||||
url: 'https://cn.bing.com/ttranslatev3',
|
||||
method: 'POST',
|
||||
data: formData({
|
||||
data: new URLSearchParams({
|
||||
fromLang: 'auto-detect',
|
||||
to: targetLanguage,
|
||||
text,
|
||||
}),
|
||||
}).toString(),
|
||||
headers: {
|
||||
'User-Agent': UserAgent,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
|
||||
@ -10,7 +10,7 @@ export interface LanguagePack {
|
||||
map?: [string, Translation][]
|
||||
regex?: RegexTranslation
|
||||
}
|
||||
export interface Options {
|
||||
export type Options = {
|
||||
language: string
|
||||
translator: string
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
@click.self="performAction($event)"
|
||||
@keydown.enter.prevent.stop="performAction($event)"
|
||||
@keydown.shift.delete.prevent.stop="performDelete($event)"
|
||||
@keydown.up.prevent.stop="$emit('previous-item', $event.currentTarget)"
|
||||
@keydown.down.prevent.stop="$emit('next-item', $event.currentTarget)"
|
||||
@keydown.up.prevent.stop="emits('previous-item')"
|
||||
@keydown.down.prevent.stop="emits('next-item')"
|
||||
>
|
||||
<div class="be-launch-bar-suggest-item-content">
|
||||
<div
|
||||
@ -47,42 +47,35 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
import type { LaunchBarAction } from '@/components/launch-bar/launch-bar-action'
|
||||
import { VIcon } from '@/ui'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
VIcon,
|
||||
},
|
||||
props: {
|
||||
action: {
|
||||
type: Object as PropType<LaunchBarAction>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
action: null as (e: KeyboardEvent | MouseEvent) => true,
|
||||
'delete-item': null as (e: KeyboardEvent | MouseEvent) => true,
|
||||
'previous-item': null as (e: KeyboardEvent) => true,
|
||||
'next-item': null as (e: KeyboardEvent) => true,
|
||||
},
|
||||
methods: {
|
||||
async performAction(event: KeyboardEvent | MouseEvent) {
|
||||
await this.action.action()
|
||||
this.$emit('action', event)
|
||||
},
|
||||
async performDelete(event: KeyboardEvent | MouseEvent) {
|
||||
if (!this.action.deleteAction) {
|
||||
return
|
||||
}
|
||||
await this.action.deleteAction()
|
||||
this.$emit('delete-item', event)
|
||||
},
|
||||
const { action } = defineProps({
|
||||
action: {
|
||||
type: Object as PropType<LaunchBarAction>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'action', event: KeyboardEvent | MouseEvent): void
|
||||
(e: 'delete-item', event: KeyboardEvent | MouseEvent): void
|
||||
(e: 'previous-item'): void
|
||||
(e: 'next-item'): void
|
||||
}>()
|
||||
const performAction = async (event: KeyboardEvent | MouseEvent) => {
|
||||
await action.action()
|
||||
emits('action', event)
|
||||
}
|
||||
const performDelete = async (event: KeyboardEvent | MouseEvent) => {
|
||||
if (!action.deleteAction) {
|
||||
return
|
||||
}
|
||||
await action.deleteAction()
|
||||
emits('delete-item', event)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -9,49 +9,36 @@
|
||||
<LaunchBar ref="launchBar" @close="close()" />
|
||||
</VPopup>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
<script lang="ts" setup>
|
||||
import { watch, onMounted, ref, useTemplateRef } from 'vue'
|
||||
import LaunchBar from './LaunchBar.vue'
|
||||
import type launchBarVue from './LaunchBar.vue'
|
||||
import VPopup from '@/ui/VPopup.vue'
|
||||
|
||||
import LaunchBar from './LaunchBar.vue'
|
||||
const launchBar = useTemplateRef<InstanceType<typeof launchBarVue>>('launchBar')
|
||||
const show = ref(true)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
LaunchBar,
|
||||
VPopup,
|
||||
},
|
||||
setup: () => ({
|
||||
launchBar: ref(null) as Ref<InstanceType<typeof LaunchBar> | null>,
|
||||
}),
|
||||
data() {
|
||||
return {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(value: boolean) {
|
||||
if (value) {
|
||||
this.focus()
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
await this.$nextTick()
|
||||
this.focus()
|
||||
},
|
||||
methods: {
|
||||
focus() {
|
||||
const input = this.launchBar?.input
|
||||
input?.focus()
|
||||
input?.select()
|
||||
},
|
||||
close() {
|
||||
this.show = false
|
||||
const input = this.launchBar?.input
|
||||
input?.blur()
|
||||
},
|
||||
},
|
||||
const focus = () => {
|
||||
const { input } = launchBar.value
|
||||
input.focus()
|
||||
input.select()
|
||||
}
|
||||
const close = () => {
|
||||
show.value = false
|
||||
const { input } = launchBar.value
|
||||
input.blur()
|
||||
}
|
||||
|
||||
watch(show, (value: boolean) => {
|
||||
if (value) {
|
||||
focus()
|
||||
}
|
||||
})
|
||||
onMounted(() => {
|
||||
focus()
|
||||
})
|
||||
defineExpose({
|
||||
show,
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
@delete-item="onDeleteItem(index)"
|
||||
@action="
|
||||
index === actions.length - 1 && onClearHistory()
|
||||
onAction(a)
|
||||
onAction()
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
@ -59,16 +59,15 @@
|
||||
@previous-item="previousItem()"
|
||||
@next-item="nextItem()"
|
||||
@delete-item="onDeleteItem(index)"
|
||||
@action="onAction(a)"
|
||||
@action="onAction()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import Fuse from 'fuse.js'
|
||||
import type { Ref } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { computed, onMounted, reactive, ref, useTemplateRef, watch } from 'vue'
|
||||
import { VIcon, VLoading, VEmpty } from '@/ui'
|
||||
import { registerAndGetData } from '@/plugins/data'
|
||||
import { select } from '@/core/spin-query'
|
||||
@ -90,8 +89,8 @@ const [actionProviders] = registerAndGetData(LaunchBarActionProviders, [
|
||||
historyProvider,
|
||||
]) as [LaunchBarActionProvider[]]
|
||||
|
||||
const sortActions = (actions: LaunchBarAction[]) => {
|
||||
return [...actions].sort(ascendingSort(it => it.order ?? Infinity))
|
||||
const sortActions = (actions: SearchAction[]) => {
|
||||
return [...actions].sort(ascendingSort(it => it.order ?? Number.POSITIVE_INFINITY))
|
||||
}
|
||||
const generateKeys = (
|
||||
provider: LaunchBarActionProvider,
|
||||
@ -108,15 +107,32 @@ const generateKeys = (
|
||||
provider,
|
||||
}
|
||||
})
|
||||
async function getOnlineActions(this: InstanceType<typeof ThisComponent>) {
|
||||
|
||||
const [recommended] = registerAndGetData('launchBar.recommended', {
|
||||
word: '搜索',
|
||||
href: 'https://search.bilibili.com/',
|
||||
})
|
||||
type SearchAction = {
|
||||
key: string
|
||||
provider: LaunchBarActionProvider
|
||||
} & LaunchBarAction
|
||||
const emits = defineEmits(['close'])
|
||||
const input = useTemplateRef('input')
|
||||
const list = useTemplateRef('list')
|
||||
const focusTarget = reactive(new FocusTarget(0))
|
||||
const keyword = ref('')
|
||||
const noActions = ref(false)
|
||||
const actions = ref<SearchAction[]>([])
|
||||
const isHistory = computed(() => keyword.value.length === 0)
|
||||
const getOnlineActions = lodash.debounce(async () => {
|
||||
const onlineActions = (
|
||||
await Promise.all(
|
||||
actionProviders.map(async provider =>
|
||||
generateKeys(provider, await provider.getActions(this.keyword)),
|
||||
generateKeys(provider, await provider.getActions(keyword.value)),
|
||||
),
|
||||
)
|
||||
).flat()
|
||||
if (this.isHistory) {
|
||||
if (isHistory.value) {
|
||||
return
|
||||
}
|
||||
const fuse = new Fuse(onlineActions, {
|
||||
@ -124,163 +140,130 @@ async function getOnlineActions(this: InstanceType<typeof ThisComponent>) {
|
||||
includeScore: true,
|
||||
threshold: 0.1,
|
||||
})
|
||||
const fuseResult = fuse.search(this.keyword)
|
||||
console.log(fuseResult)
|
||||
this.actions = sortActions(fuseResult.map(it => it.item).slice(0, 13))
|
||||
this.noActions = this.actions.length === 0
|
||||
}
|
||||
async function getActions(this: InstanceType<typeof ThisComponent>) {
|
||||
this.noActions = false
|
||||
if (this.isHistory) {
|
||||
this.actions = sortActions(
|
||||
generateKeys(historyProvider, await historyProvider.getActions(this.keyword)),
|
||||
const fuseResult = fuse.search(keyword.value)
|
||||
// console.log(fuseResult)
|
||||
actions.value = sortActions(fuseResult.map(it => it.item).slice(0, 13))
|
||||
noActions.value = actions.value.length === 0
|
||||
}, 200)
|
||||
const getActions = async () => {
|
||||
noActions.value = false
|
||||
if (isHistory.value) {
|
||||
actions.value = sortActions(
|
||||
generateKeys(historyProvider, await historyProvider.getActions(keyword.value)),
|
||||
)
|
||||
return
|
||||
}
|
||||
const actions: LaunchBarAction[] = []
|
||||
this.actions = actions
|
||||
this.getOnlineActions()
|
||||
actions.value = []
|
||||
getOnlineActions()
|
||||
}
|
||||
|
||||
const [recommended] = registerAndGetData('launchBar.recommended', {
|
||||
word: '搜索',
|
||||
href: 'https://search.bilibili.com/',
|
||||
watch(keyword, () => {
|
||||
getActions()
|
||||
})
|
||||
const ThisComponent = defineComponent({
|
||||
components: {
|
||||
VIcon,
|
||||
VLoading,
|
||||
VEmpty,
|
||||
ActionItem,
|
||||
},
|
||||
emits: ['close'],
|
||||
setup: () => ({
|
||||
input: ref(null) as Ref<HTMLInputElement | null>,
|
||||
list: ref(null) as Ref<HTMLDivElement | null>,
|
||||
}),
|
||||
data() {
|
||||
const focusTarget = new FocusTarget(0)
|
||||
return {
|
||||
recommended,
|
||||
actions: [] as LaunchBarAction[],
|
||||
keyword: '',
|
||||
focusTarget,
|
||||
noActions: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isHistory(): boolean {
|
||||
return this.keyword.length === 0
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
keyword() {
|
||||
this.getActions()
|
||||
},
|
||||
actions() {
|
||||
this.focusTarget.reset(this.actions.length)
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
await this.getActions()
|
||||
if (matchUrlPattern(/^https?:\/\/search\.bilibili\.com/)) {
|
||||
await this.setupSearchPageSync()
|
||||
}
|
||||
this.focusTarget.addEventListener('index-change', () => {
|
||||
this.handleIndexUpdate()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getOnlineActions: lodash.debounce(getOnlineActions, 200),
|
||||
getActions,
|
||||
async setupSearchPageSync() {
|
||||
const selector = '#search-keyword, .search-input-el'
|
||||
const input = (await select(selector)) as HTMLInputElement
|
||||
if (!input) {
|
||||
return
|
||||
}
|
||||
urlChange(url => {
|
||||
const params = new URLSearchParams(url)
|
||||
const keywordFromParam = params.get('keyword')
|
||||
if (keywordFromParam !== null) {
|
||||
this.keyword = params.get('keyword')
|
||||
}
|
||||
})
|
||||
await this.$nextTick()
|
||||
},
|
||||
handleSelect() {
|
||||
this.$emit('close')
|
||||
this.getActions()
|
||||
},
|
||||
async handleEnter(e: KeyboardEvent) {
|
||||
if (e.isComposing) {
|
||||
return
|
||||
}
|
||||
if (this.actions.length > 0 && !this.isHistory) {
|
||||
const [first] = this.actions as LaunchBarAction[]
|
||||
if (first.explicitSelect !== true) {
|
||||
first.action()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (this.keyword) {
|
||||
search(this.keyword)
|
||||
this.handleSelect()
|
||||
return
|
||||
}
|
||||
window.open(this.recommended.href, '_blank')
|
||||
this.handleSelect()
|
||||
},
|
||||
handleUp(e: KeyboardEvent) {
|
||||
if (e.isComposing) {
|
||||
return
|
||||
}
|
||||
this.focusTarget.previous()
|
||||
e.preventDefault()
|
||||
},
|
||||
handleDown(e: KeyboardEvent) {
|
||||
if (e.isComposing) {
|
||||
return
|
||||
}
|
||||
this.focusTarget.next()
|
||||
e.preventDefault()
|
||||
},
|
||||
async handleIndexUpdate() {
|
||||
await this.$nextTick()
|
||||
if (!this.focusTarget.hasFocus) {
|
||||
this.focusInput()
|
||||
return
|
||||
}
|
||||
this.focusSuggestItem(this.focusTarget.index + 1)
|
||||
},
|
||||
previousItem() {
|
||||
this.focusTarget.previous()
|
||||
},
|
||||
nextItem() {
|
||||
this.focusTarget.next()
|
||||
},
|
||||
search,
|
||||
onDeleteItem(index: number) {
|
||||
this.focusTarget.setFocus(index)
|
||||
this.focusTarget.previous()
|
||||
this.getActions()
|
||||
},
|
||||
onClearHistory() {
|
||||
this.focusInput()
|
||||
this.getActions()
|
||||
},
|
||||
onAction() {
|
||||
this.handleSelect()
|
||||
},
|
||||
focusInput() {
|
||||
this.input.focus()
|
||||
},
|
||||
focusSuggestItem(nth: number) {
|
||||
this.list.querySelector(`.be-launch-bar-suggest-item:nth-child(${nth})`)?.focus()
|
||||
},
|
||||
},
|
||||
watch(actions, () => {
|
||||
focusTarget.reset(actions.value.length)
|
||||
})
|
||||
|
||||
const setupSearchPageSync = async () => {
|
||||
const selector = '#search-keyword, .search-input-el'
|
||||
const searchInput = (await select(selector)) as HTMLInputElement
|
||||
if (!searchInput) {
|
||||
return
|
||||
}
|
||||
urlChange(url => {
|
||||
const params = new URLSearchParams(url)
|
||||
const keywordFromParam = params.get('keyword')
|
||||
if (keywordFromParam !== null) {
|
||||
keyword.value = keywordFromParam
|
||||
}
|
||||
})
|
||||
// await this.$nextTick()
|
||||
}
|
||||
const focusInput = () => {
|
||||
input.value.focus()
|
||||
}
|
||||
const handleSelect = () => {
|
||||
emits('close')
|
||||
getActions()
|
||||
}
|
||||
const handleEnter = async (e: KeyboardEvent | MouseEvent) => {
|
||||
if ((e as KeyboardEvent).isComposing) {
|
||||
return
|
||||
}
|
||||
if (actions.value.length > 0 && !isHistory.value) {
|
||||
const [first] = actions.value as LaunchBarAction[]
|
||||
if (first.explicitSelect !== true) {
|
||||
first.action()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (keyword.value) {
|
||||
search(keyword.value)
|
||||
handleSelect()
|
||||
return
|
||||
}
|
||||
window.open(recommended.href, '_blank')
|
||||
handleSelect()
|
||||
}
|
||||
const focusSuggestItem = (nth: number) => {
|
||||
;(
|
||||
list.value.querySelector(`.be-launch-bar-suggest-item:nth-child(${nth})`) as HTMLDivElement
|
||||
)?.focus()
|
||||
}
|
||||
const handleUp = (e: KeyboardEvent) => {
|
||||
if (e.isComposing) {
|
||||
return
|
||||
}
|
||||
focusTarget.previous()
|
||||
e.preventDefault()
|
||||
}
|
||||
const handleDown = (e: KeyboardEvent) => {
|
||||
if (e.isComposing) {
|
||||
return
|
||||
}
|
||||
focusTarget.next()
|
||||
e.preventDefault()
|
||||
}
|
||||
const handleIndexUpdate = async () => {
|
||||
// await this.$nextTick()
|
||||
if (!focusTarget.hasFocus) {
|
||||
focusInput()
|
||||
return
|
||||
}
|
||||
focusSuggestItem(focusTarget.index + 1)
|
||||
}
|
||||
const previousItem = () => {
|
||||
focusTarget.previous()
|
||||
}
|
||||
const nextItem = () => {
|
||||
focusTarget.next()
|
||||
}
|
||||
const onDeleteItem = (index: number) => {
|
||||
focusTarget.setFocus(index)
|
||||
focusTarget.previous()
|
||||
getActions()
|
||||
}
|
||||
|
||||
const onClearHistory = () => {
|
||||
focusInput()
|
||||
getActions()
|
||||
}
|
||||
const onAction = () => {
|
||||
handleSelect()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getActions()
|
||||
if (matchUrlPattern(/^https?:\/\/search\.bilibili\.com/)) {
|
||||
await setupSearchPageSync()
|
||||
}
|
||||
focusTarget.addEventListener('index-change', () => {
|
||||
handleIndexUpdate()
|
||||
})
|
||||
})
|
||||
defineExpose({
|
||||
input,
|
||||
})
|
||||
export default ThisComponent
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -224,8 +224,8 @@ export class LiveSocket extends EventTarget {
|
||||
}
|
||||
|
||||
if (
|
||||
this.webSocket &&
|
||||
[WebSocket.CONNECTING, WebSocket.OPEN].includes(this.webSocket.readyState)
|
||||
(this.webSocket && this.webSocket.readyState === WebSocket.OPEN) ||
|
||||
this.webSocket.readyState === WebSocket.CONNECTING
|
||||
) {
|
||||
this.stop()
|
||||
}
|
||||
|
||||
@ -3,7 +3,8 @@ import { childList } from '@/core/observer'
|
||||
import { CommentItem } from '../comment-item'
|
||||
import { DomCommentArea } from './dom'
|
||||
import { CommentReplyItem } from '../reply-item'
|
||||
import { HTMLElementWithVue, VNodeManager } from '../vnode-manager'
|
||||
import type { HTMLElementWithVue } from '../vnode-manager'
|
||||
import { VNodeManager } from '../vnode-manager'
|
||||
|
||||
export class CommentAreaV2 extends DomCommentArea {
|
||||
private vnodeManager: VNodeManager
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { ShadowDomObserver, shadowDomObserver, ShadowRootEvents } from '@/core/shadow-root'
|
||||
import type { ShadowDomObserver } from '@/core/shadow-root'
|
||||
import { shadowDomObserver, ShadowRootEvents } from '@/core/shadow-root'
|
||||
import { CommentReplyItem } from '../reply-item'
|
||||
import { CommentArea } from './base'
|
||||
import { ShadowDomEntry } from '@/core/shadow-root/dom-entry'
|
||||
import type { ShadowDomEntry } from '@/core/shadow-root/dom-entry'
|
||||
import { CommentItem } from '../comment-item'
|
||||
import { deleteValue } from '@/core/utils'
|
||||
import { select } from '@/core/spin-query'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { allMutations, childList } from '@/core/observer'
|
||||
import { getCommentArea } from './comment-area'
|
||||
import {
|
||||
import type {
|
||||
CommentAreaCallback,
|
||||
CommentCallbackInput,
|
||||
CommentCallbackPair,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CommentReplyItem } from './reply-item'
|
||||
import { RepliesUpdateEventCallback, RepliesUpdateEventType } from './types'
|
||||
import { type RepliesUpdateEventCallback, RepliesUpdateEventType } from './types'
|
||||
|
||||
const createRepliesUpdateEvent = (replies: CommentReplyItem[]) => {
|
||||
return new CustomEvent(RepliesUpdateEventType, {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { PlayerAgent, selectorWrap } from './base'
|
||||
import { bpxSelectors } from './bpx'
|
||||
import { AgentType, PlayerQuery, ElementQuery } from './types'
|
||||
import type { AgentType, PlayerQuery, ElementQuery } from './types'
|
||||
|
||||
export class BangumiPlayerAgent extends PlayerAgent {
|
||||
type: AgentType = 'bangumi'
|
||||
@ -11,10 +11,6 @@ export class BangumiPlayerAgent extends PlayerAgent {
|
||||
...bpxSelectors,
|
||||
}) as PlayerQuery<ElementQuery>
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
seek(time: number) {
|
||||
const seekResult = super.seek(time)
|
||||
if (seekResult === null) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { isBwpVideo } from '@/core/utils'
|
||||
import { PlayerAgent, selectorWrap } from './base'
|
||||
import { PlayerQuery, ElementQuery, AgentType } from './types'
|
||||
import type { PlayerQuery, ElementQuery, AgentType } from './types'
|
||||
import { select } from '@/core/spin-query'
|
||||
import { bpxSelectors } from './bpx'
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ export const addControlBarButton = async (button: VideoControlBarItem) => {
|
||||
if (!controlBarInstance) {
|
||||
controlBarInstance = initControlBar()
|
||||
}
|
||||
const created = (await controlBarInstance) as ControlBarComponent
|
||||
const created = await controlBarInstance
|
||||
if (!created) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { contentLoaded } from '../life-cycle'
|
||||
import { childListSubtree } from '../observer'
|
||||
import { deleteValue } from '../utils'
|
||||
import { ShadowDomCallback, ShadowDomEntry } from './dom-entry'
|
||||
import type { ShadowDomCallback } from './dom-entry'
|
||||
import { ShadowDomEntry } from './dom-entry'
|
||||
import { ShadowRootObserver } from './root-observer'
|
||||
import { ShadowRootEvents } from './types'
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ShadowRootEvents } from './types'
|
||||
import type { ShadowRootEvents } from './types'
|
||||
|
||||
export abstract class ShadowRootObserver extends EventTarget {
|
||||
static queryAllShadowRoots(
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { addComponentListener, removeComponentListener } from '../settings'
|
||||
import { deleteValue, getRandomId } from '../utils'
|
||||
import { ShadowDomEntry } from './dom-entry'
|
||||
import { ShadowDomObserver, shadowDomObserver } from './dom-observer'
|
||||
import type { ShadowDomEntry } from './dom-entry'
|
||||
import type { ShadowDomObserver } from './dom-observer'
|
||||
import { shadowDomObserver } from './dom-observer'
|
||||
|
||||
export interface ShadowRootStyleEntry {
|
||||
id: string
|
||||
|
||||
@ -4,22 +4,13 @@
|
||||
<template v-if="typeof config.content === 'string' && config.content.length > 0">
|
||||
{{ config.content }}
|
||||
</template>
|
||||
<component :is="config.content" v-if="typeof config.content !== 'string'"></component>
|
||||
<component :is="config.content as Component" v-if="typeof config.content !== 'string'" />
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { emptyContent } from './v-empty'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VEmpty',
|
||||
data() {
|
||||
return {
|
||||
config: emptyContent,
|
||||
}
|
||||
},
|
||||
})
|
||||
<script lang="ts" setup>
|
||||
import type { Component } from 'vue'
|
||||
import { emptyContent as config } from './v-empty'
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -4,22 +4,13 @@
|
||||
<template v-if="typeof config.content === 'string' && config.content.length > 0">
|
||||
{{ config.content }}
|
||||
</template>
|
||||
<component :is="config.content" v-if="typeof config.content !== 'string'"></component>
|
||||
<component :is="config.content as Component" v-if="typeof config.content !== 'string'" />
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { loadingContent } from './v-loading'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VLoading',
|
||||
data() {
|
||||
return {
|
||||
config: loadingContent,
|
||||
}
|
||||
},
|
||||
})
|
||||
<script lang="ts" setup>
|
||||
import type { Component } from 'vue'
|
||||
import { loadingContent as config } from './v-loading'
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'common';
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"compilerOptions": {
|
||||
"importsNotUsedAsValues": "remove",
|
||||
"preserveValueImports": false,
|
||||
"verbatimModuleSyntax": true,
|
||||
"strict": false,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
@ -13,7 +16,7 @@
|
||||
}
|
||||
},
|
||||
"vueCompilerOptions": {
|
||||
"target": 2.7
|
||||
"target": 3.5,
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user