完成同步功能
This commit is contained in:
@@ -16,7 +16,8 @@
|
|||||||
"no-multiple-empty-lines": [1, {"max": 2}],
|
"no-multiple-empty-lines": [1, {"max": 2}],
|
||||||
"comma-dangle": [2, "always-multiline"],
|
"comma-dangle": [2, "always-multiline"],
|
||||||
"standard/no-callback-literal": "off",
|
"standard/no-callback-literal": "off",
|
||||||
"prefer-const": "off"
|
"prefer-const": "off",
|
||||||
|
"no-labels": "off"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"html/html-extensions": [".html", ".vue"]
|
"html/html-extensions": [".html", ".vue"]
|
||||||
|
|||||||
Generated
+428
-54
@@ -3093,6 +3093,21 @@
|
|||||||
"integrity": "sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==",
|
"integrity": "sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/component-emitter": {
|
||||||
|
"version": "1.2.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
|
||||||
|
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
|
||||||
|
},
|
||||||
|
"@types/cookie": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
|
||||||
|
},
|
||||||
|
"@types/cors": {
|
||||||
|
"version": "2.8.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
|
||||||
|
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
|
||||||
|
},
|
||||||
"@types/debug": {
|
"@types/debug": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
|
||||||
@@ -3171,8 +3186,7 @@
|
|||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "13.11.0",
|
"version": "13.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
|
||||||
"integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==",
|
"integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@types/parse-json": {
|
"@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@@ -3441,7 +3455,6 @@
|
|||||||
"version": "1.3.7",
|
"version": "1.3.7",
|
||||||
"resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
|
"resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
|
||||||
"integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
|
"integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-types": "~2.1.24",
|
"mime-types": "~2.1.24",
|
||||||
"negotiator": "0.6.2"
|
"negotiator": "0.6.2"
|
||||||
@@ -3594,6 +3607,11 @@
|
|||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"any-promise": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||||
|
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
|
||||||
|
},
|
||||||
"app-builder-bin": {
|
"app-builder-bin": {
|
||||||
"version": "3.5.13",
|
"version": "3.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.13.tgz",
|
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.13.tgz",
|
||||||
@@ -4343,6 +4361,11 @@
|
|||||||
"pascalcase": "^0.1.1"
|
"pascalcase": "^0.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"base64-arraybuffer": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
|
||||||
|
},
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
@@ -4350,6 +4373,11 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"base64id": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||||
|
},
|
||||||
"batch": {
|
"batch": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
|
||||||
@@ -4474,9 +4502,7 @@
|
|||||||
"boolean": {
|
"boolean": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz",
|
||||||
"integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw==",
|
"integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw=="
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"boxen": {
|
"boxen": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
@@ -4583,6 +4609,14 @@
|
|||||||
"integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=",
|
"integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bufferutil": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==",
|
||||||
|
"requires": {
|
||||||
|
"node-gyp-build": "^4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"builder-util": {
|
"builder-util": {
|
||||||
"version": "22.11.7",
|
"version": "22.11.7",
|
||||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.11.7.tgz",
|
||||||
@@ -4726,6 +4760,15 @@
|
|||||||
"unset-value": "^1.0.0"
|
"unset-value": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cache-content-type": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
|
||||||
|
"requires": {
|
||||||
|
"mime-types": "^2.1.18",
|
||||||
|
"ylru": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cacheable-request": {
|
"cacheable-request": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/cacheable-request/download/cacheable-request-6.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/cacheable-request/download/cacheable-request-6.1.0.tgz",
|
||||||
@@ -5136,6 +5179,11 @@
|
|||||||
"mimic-response": "^1.0.0"
|
"mimic-response": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"co": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
|
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||||
|
},
|
||||||
"collection-visit": {
|
"collection-visit": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||||
@@ -5202,8 +5250,7 @@
|
|||||||
"component-emitter": {
|
"component-emitter": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||||
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
|
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"compressible": {
|
"compressible": {
|
||||||
"version": "2.0.18",
|
"version": "2.0.18",
|
||||||
@@ -5388,7 +5435,6 @@
|
|||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
|
||||||
"integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
|
"integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.2"
|
"safe-buffer": "5.1.2"
|
||||||
},
|
},
|
||||||
@@ -5396,16 +5442,14 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=",
|
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"content-type": {
|
"content-type": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz",
|
"resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz",
|
||||||
"integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
|
"integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"convert-source-map": {
|
"convert-source-map": {
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
@@ -5436,6 +5480,22 @@
|
|||||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
|
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"cookies": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
|
||||||
|
"requires": {
|
||||||
|
"depd": "~2.0.0",
|
||||||
|
"keygrip": "~1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"depd": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"copy-anything": {
|
"copy-anything": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz",
|
||||||
@@ -5610,6 +5670,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||||
},
|
},
|
||||||
|
"cors": {
|
||||||
|
"version": "2.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
|
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cosmiconfig": {
|
"cosmiconfig": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
|
||||||
@@ -6010,6 +6079,11 @@
|
|||||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"deepmerge": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
|
||||||
|
},
|
||||||
"default-gateway": {
|
"default-gateway": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1598471816842&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1598471816842&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz",
|
||||||
@@ -6030,7 +6104,6 @@
|
|||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"object-keys": "^1.0.12"
|
"object-keys": "^1.0.12"
|
||||||
}
|
}
|
||||||
@@ -6074,22 +6147,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"delay": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw=="
|
||||||
|
},
|
||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||||
},
|
},
|
||||||
|
"delegates": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||||
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"destroy": {
|
"destroy": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"detect-node": {
|
"detect-node": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
@@ -6368,8 +6449,12 @@
|
|||||||
"ee-first": {
|
"ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
|
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||||
"dev": true
|
},
|
||||||
|
"eiows": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eiows/-/eiows-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-B2A6GXQ153/XVwecF2mkMNa108TJWGBXTBfHSmW2hf86D26cp3+lAhwizgEsV1mhcuZYgNQNeddgh4J5kYi7ng=="
|
||||||
},
|
},
|
||||||
"ejs": {
|
"ejs": {
|
||||||
"version": "3.1.6",
|
"version": "3.1.6",
|
||||||
@@ -6708,8 +6793,7 @@
|
|||||||
"encodeurl": {
|
"encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
|
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"end-of-stream": {
|
"end-of-stream": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
@@ -6720,6 +6804,48 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"engine.io": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==",
|
||||||
|
"requires": {
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "2.0.0",
|
||||||
|
"cookie": "~0.4.1",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~4.0.0",
|
||||||
|
"ws": "~7.4.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "7.4.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||||
|
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==",
|
||||||
|
"requires": {
|
||||||
|
"base64-arraybuffer": "0.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"enhanced-resolve": {
|
"enhanced-resolve": {
|
||||||
"version": "5.8.2",
|
"version": "5.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz",
|
||||||
@@ -6884,8 +7010,7 @@
|
|||||||
"escape-html": {
|
"escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
|
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"escape-string-regexp": {
|
"escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
@@ -8031,12 +8156,31 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||||
},
|
},
|
||||||
|
"fast-json-stringify": {
|
||||||
|
"version": "2.7.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.7.tgz",
|
||||||
|
"integrity": "sha512-2kiwC/hBlK7QiGALsvj0QxtYwaReLOmAwOWJIxt5WHBB9EwXsqbsu8LCel47yh8NV8CEcFmnZYcXh4BionJcwQ==",
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.11.0",
|
||||||
|
"deepmerge": "^4.2.2",
|
||||||
|
"rfdc": "^1.2.0",
|
||||||
|
"string-similarity": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fast-levenshtein": {
|
"fast-levenshtein": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fast-printf": {
|
||||||
|
"version": "1.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.6.tgz",
|
||||||
|
"integrity": "sha512-Uz/uW6R1Fd8YqCGeoQosRIfB4dBbr8uMbFVdEci2AyXYcfucFqhpSMAGs8skRRdZd+MGCDBu48+B8Zmu7Pta5A==",
|
||||||
|
"requires": {
|
||||||
|
"boolean": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fastest-levenshtein": {
|
"fastest-levenshtein": {
|
||||||
"version": "1.0.12",
|
"version": "1.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
|
||||||
@@ -8257,8 +8401,7 @@
|
|||||||
"fresh": {
|
"fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
|
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"friendly-errors-webpack-plugin": {
|
"friendly-errors-webpack-plugin": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
@@ -8497,8 +8640,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
|
||||||
"integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
|
"integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-properties": "^1.1.3"
|
"define-properties": "^1.1.3"
|
||||||
}
|
}
|
||||||
@@ -8760,6 +8901,22 @@
|
|||||||
"entities": "^2.0.0"
|
"entities": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"http-assert": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==",
|
||||||
|
"requires": {
|
||||||
|
"deep-equal": "~1.0.1",
|
||||||
|
"http-errors": "~1.7.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"deep-equal": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"http-cache-semantics": {
|
"http-cache-semantics": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/http-cache-semantics/download/http-cache-semantics-4.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/http-cache-semantics/download/http-cache-semantics-4.1.0.tgz",
|
||||||
@@ -8776,7 +8933,6 @@
|
|||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz?cache=0&sync_timestamp=1593407647372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz?cache=0&sync_timestamp=1593407647372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.2.tgz",
|
||||||
"integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=",
|
"integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"depd": "~1.1.2",
|
"depd": "~1.1.2",
|
||||||
"inherits": "2.0.3",
|
"inherits": "2.0.3",
|
||||||
@@ -8788,8 +8944,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -8927,6 +9082,43 @@
|
|||||||
"sshpk": "^1.7.0"
|
"sshpk": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"http-terminator": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-YdNsDQgsHuxBSOWWhkQHMgOD7c5CU3e9u+pokp9tI6BwJ8LjUhJYBO+k2a3NXoDXbToSm7OQk4RzNTooPQP5IQ==",
|
||||||
|
"requires": {
|
||||||
|
"delay": "^5.0.0",
|
||||||
|
"roarr": "^4.0.10",
|
||||||
|
"type-fest": "^0.20.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"detect-node": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
|
||||||
|
},
|
||||||
|
"roarr": {
|
||||||
|
"version": "4.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/roarr/-/roarr-4.2.5.tgz",
|
||||||
|
"integrity": "sha512-ZSs1hr2gyWickWDr2Yw0qcuef+EJKwZtNxUj7poxvIDxVq+ZvQreVNdPVLHonWpavBeZaOcAGVFV5xM/HqRR8g==",
|
||||||
|
"requires": {
|
||||||
|
"boolean": "^3.0.2",
|
||||||
|
"detect-node": "^2.0.5",
|
||||||
|
"fast-json-stringify": "^2.5.2",
|
||||||
|
"fast-printf": "^1.6.4",
|
||||||
|
"globalthis": "^1.0.2",
|
||||||
|
"is-circular": "^1.0.2",
|
||||||
|
"json-stringify-safe": "^5.0.1",
|
||||||
|
"semver-compare": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type-fest": {
|
||||||
|
"version": "0.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
|
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"human-signals": {
|
"human-signals": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
@@ -9150,6 +9342,11 @@
|
|||||||
"ci-info": "^3.1.1"
|
"ci-info": "^3.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-circular": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-circular/-/is-circular-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-YttjnrswnUYRVJvxCvu8z+PGMUSzC2JttP0OEXezlAEdp3EXzhf7IZ3j0gRAybJBQupedIZFhY61Tga6E0qASA=="
|
||||||
|
},
|
||||||
"is-color-stop": {
|
"is-color-stop": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
|
||||||
@@ -9235,6 +9432,11 @@
|
|||||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-generator-function": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A=="
|
||||||
|
},
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
||||||
@@ -9651,6 +9853,14 @@
|
|||||||
"integrity": "sha1-iBkexzjOn3WRwl6QVt6Si0AncZQ=",
|
"integrity": "sha1-iBkexzjOn3WRwl6QVt6Si0AncZQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"keygrip": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
|
||||||
|
"requires": {
|
||||||
|
"tsscmp": "1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"keyv": {
|
"keyv": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/keyv/download/keyv-3.1.0.tgz?cache=0&sync_timestamp=1600337463601&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkeyv%2Fdownload%2Fkeyv-3.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/keyv/download/keyv-3.1.0.tgz?cache=0&sync_timestamp=1600337463601&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkeyv%2Fdownload%2Fkeyv-3.1.0.tgz",
|
||||||
@@ -9678,6 +9888,80 @@
|
|||||||
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
|
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"koa": {
|
||||||
|
"version": "2.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz",
|
||||||
|
"integrity": "sha512-Lb2Dloc72auj5vK4X4qqL7B5jyDPQaZucc9sR/71byg7ryoD1NCaCm63CShk9ID9quQvDEi1bGR/iGjCG7As3w==",
|
||||||
|
"requires": {
|
||||||
|
"accepts": "^1.3.5",
|
||||||
|
"cache-content-type": "^1.0.0",
|
||||||
|
"content-disposition": "~0.5.2",
|
||||||
|
"content-type": "^1.0.4",
|
||||||
|
"cookies": "~0.8.0",
|
||||||
|
"debug": "~3.1.0",
|
||||||
|
"delegates": "^1.0.0",
|
||||||
|
"depd": "^2.0.0",
|
||||||
|
"destroy": "^1.0.4",
|
||||||
|
"encodeurl": "^1.0.2",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"fresh": "~0.5.2",
|
||||||
|
"http-assert": "^1.3.0",
|
||||||
|
"http-errors": "^1.6.3",
|
||||||
|
"is-generator-function": "^1.0.7",
|
||||||
|
"koa-compose": "^4.1.0",
|
||||||
|
"koa-convert": "^1.2.0",
|
||||||
|
"on-finished": "^2.3.0",
|
||||||
|
"only": "~0.0.2",
|
||||||
|
"parseurl": "^1.3.2",
|
||||||
|
"statuses": "^1.5.0",
|
||||||
|
"type-is": "^1.6.16",
|
||||||
|
"vary": "^1.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depd": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"koa-compose": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
|
||||||
|
},
|
||||||
|
"koa-convert": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
|
||||||
|
"requires": {
|
||||||
|
"co": "^4.6.0",
|
||||||
|
"koa-compose": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"koa-compose": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
|
||||||
|
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
|
||||||
|
"requires": {
|
||||||
|
"any-promise": "^1.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"latest-version": {
|
"latest-version": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
|
||||||
@@ -9946,6 +10230,20 @@
|
|||||||
"integrity": "sha1-AF/eL15uRwaPk1/yhXPhJe9y8Zc=",
|
"integrity": "sha1-AF/eL15uRwaPk1/yhXPhJe9y8Zc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"long": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
|
},
|
||||||
|
"loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lower-case": {
|
"lower-case": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||||
@@ -10067,8 +10365,7 @@
|
|||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"memory-fs": {
|
"memory-fs": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
@@ -10360,8 +10657,7 @@
|
|||||||
"negotiator": {
|
"negotiator": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
|
||||||
"integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=",
|
"integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"neo-async": {
|
"neo-async": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
@@ -10406,6 +10702,11 @@
|
|||||||
"integrity": "sha1-Mt6ir7Ppkm8C7lzoeUkCaRpna/M=",
|
"integrity": "sha1-Mt6ir7Ppkm8C7lzoeUkCaRpna/M=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node-gyp-build": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
|
||||||
|
},
|
||||||
"node-id3": {
|
"node-id3": {
|
||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/node-id3/-/node-id3-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/node-id3/-/node-id3-0.2.3.tgz",
|
||||||
@@ -10513,8 +10814,7 @@
|
|||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"object-copy": {
|
"object-copy": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
@@ -10609,8 +10909,7 @@
|
|||||||
"object-keys": {
|
"object-keys": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"object-visit": {
|
"object-visit": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -10663,7 +10962,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ee-first": "1.1.1"
|
"ee-first": "1.1.1"
|
||||||
}
|
}
|
||||||
@@ -10692,6 +10990,11 @@
|
|||||||
"mimic-fn": "^2.1.0"
|
"mimic-fn": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"only": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
|
||||||
|
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
|
||||||
|
},
|
||||||
"opn": {
|
"opn": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz",
|
||||||
@@ -10839,8 +11142,7 @@
|
|||||||
"parseurl": {
|
"parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz",
|
||||||
"integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=",
|
"integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"pascal-case": {
|
"pascal-case": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
@@ -12257,6 +12559,11 @@
|
|||||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"rfdc": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
|
||||||
|
},
|
||||||
"rgb-regex": {
|
"rgb-regex": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
|
||||||
@@ -12366,9 +12673,7 @@
|
|||||||
"semver-compare": {
|
"semver-compare": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"semver-diff": {
|
"semver-diff": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
@@ -12559,8 +12864,7 @@
|
|||||||
"setprototypeof": {
|
"setprototypeof": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
|
||||||
"integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=",
|
"integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"shallow-clone": {
|
"shallow-clone": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -12781,6 +13085,57 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"socket.io": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-tLkaY13RcO4nIRh1K2hT5iuotfTaIQw7cVIe0FUykN3SuQi0cm7ALxuyT5/CtDswOMWUzMGTibxYNx/gU7In+Q==",
|
||||||
|
"requires": {
|
||||||
|
"@types/cookie": "^0.4.0",
|
||||||
|
"@types/cors": "^2.8.10",
|
||||||
|
"@types/node": ">=10.0.0",
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "~2.0.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io": "~5.1.1",
|
||||||
|
"socket.io-adapter": "~2.3.1",
|
||||||
|
"socket.io-parser": "~4.0.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-adapter": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw=="
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==",
|
||||||
|
"requires": {
|
||||||
|
"@types/component-emitter": "^1.2.10",
|
||||||
|
"component-emitter": "~1.3.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sockjs": {
|
"sockjs": {
|
||||||
"version": "0.3.21",
|
"version": "0.3.21",
|
||||||
"resolved": "https://registry.npm.taobao.org/sockjs/download/sockjs-0.3.21.tgz?cache=0&sync_timestamp=1596167355358&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsockjs%2Fdownload%2Fsockjs-0.3.21.tgz",
|
"resolved": "https://registry.npm.taobao.org/sockjs/download/sockjs-0.3.21.tgz?cache=0&sync_timestamp=1596167355358&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsockjs%2Fdownload%2Fsockjs-0.3.21.tgz",
|
||||||
@@ -13090,8 +13445,12 @@
|
|||||||
"statuses": {
|
"statuses": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||||
"dev": true
|
},
|
||||||
|
"string-similarity": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ=="
|
||||||
},
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
@@ -13683,8 +14042,7 @@
|
|||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz",
|
||||||
"integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=",
|
"integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"token-stream": {
|
"token-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -13739,6 +14097,11 @@
|
|||||||
"integrity": "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=",
|
"integrity": "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"tsscmp": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
|
||||||
|
},
|
||||||
"tunnel": {
|
"tunnel": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
@@ -13777,7 +14140,6 @@
|
|||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz",
|
"resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz",
|
||||||
"integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
|
"integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"media-typer": "0.3.0",
|
"media-typer": "0.3.0",
|
||||||
"mime-types": "~2.1.24"
|
"mime-types": "~2.1.24"
|
||||||
@@ -14127,6 +14489,14 @@
|
|||||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==",
|
||||||
|
"requires": {
|
||||||
|
"node-gyp-build": "^4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"utf8-byte-length": {
|
"utf8-byte-length": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
|
||||||
@@ -14175,8 +14545,7 @@
|
|||||||
"vary": {
|
"vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"vendors": {
|
"vendors": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@@ -15293,6 +15662,11 @@
|
|||||||
"fd-slicer": "~1.1.0"
|
"fd-slicer": "~1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ylru": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ=="
|
||||||
|
},
|
||||||
"yocto-queue": {
|
"yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
|
|||||||
@@ -229,14 +229,21 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"electron-log": "^4.4.1",
|
"electron-log": "^4.4.1",
|
||||||
|
"bufferutil": "^4.0.3",
|
||||||
|
"eiows": "^3.6.0",
|
||||||
"electron-store": "^8.0.0",
|
"electron-store": "^8.0.0",
|
||||||
"electron-updater": "^4.3.9",
|
"electron-updater": "^4.3.9",
|
||||||
|
"http-terminator": "^3.0.0",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"image-size": "^1.0.0",
|
"image-size": "^1.0.0",
|
||||||
|
"koa": "^2.13.1",
|
||||||
|
"long": "^4.0.0",
|
||||||
"lrc-file-parser": "^1.1.0",
|
"lrc-file-parser": "^1.1.0",
|
||||||
"needle": "^2.8.0",
|
"needle": "^2.8.0",
|
||||||
"node-id3": "^0.2.3",
|
"node-id3": "^0.2.3",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
"socket.io": "^4.1.2",
|
||||||
|
"utf-8-validate": "^5.0.5",
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-i18n": "^8.25.0",
|
"vue-i18n": "^8.25.0",
|
||||||
"vue-router": "^3.5.2",
|
"vue-router": "^3.5.2",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const path = require('path')
|
|||||||
const os = require('os')
|
const os = require('os')
|
||||||
|
|
||||||
const defaultSetting = {
|
const defaultSetting = {
|
||||||
version: '1.0.42',
|
version: '1.0.43',
|
||||||
player: {
|
player: {
|
||||||
togglePlayMethod: 'listLoop',
|
togglePlayMethod: 'listLoop',
|
||||||
highQuality: false,
|
highQuality: false,
|
||||||
@@ -85,6 +85,10 @@ const defaultSetting = {
|
|||||||
isToTray: false,
|
isToTray: false,
|
||||||
themeId: 0,
|
themeId: 0,
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
enable: false,
|
||||||
|
port: 23332,
|
||||||
|
},
|
||||||
windowSizeId: 2,
|
windowSizeId: 2,
|
||||||
themeId: 0,
|
themeId: 0,
|
||||||
langId: null,
|
langId: null,
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ const names = {
|
|||||||
get_music_url: 'get_music_url',
|
get_music_url: 'get_music_url',
|
||||||
save_music_url: 'save_music_url',
|
save_music_url: 'save_music_url',
|
||||||
clear_music_url: 'clear_music_url',
|
clear_music_url: 'clear_music_url',
|
||||||
|
|
||||||
|
sync_enable: 'sync_enable',
|
||||||
|
sync_status: 'sync_status',
|
||||||
|
sync_get_status: 'sync_get_status',
|
||||||
|
sync_generate_code: 'sync_generate_code',
|
||||||
|
sync_action_list: 'sync_action_list',
|
||||||
|
sync_list: 'sync_list',
|
||||||
},
|
},
|
||||||
winLyric: {
|
winLyric: {
|
||||||
close: 'close',
|
close: 'close',
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ class Common extends EventEmitter {
|
|||||||
configStatus(name) {
|
configStatus(name) {
|
||||||
this.emit(COMMON_EVENT_NAME.configStatus, name)
|
this.emit(COMMON_EVENT_NAME.configStatus, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveMyList(data) {
|
||||||
|
this.emit(COMMON_EVENT_NAME.saveMyList, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Common
|
module.exports = Common
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
exports.common = {
|
exports.common = {
|
||||||
initConfig: 'initConfig',
|
initConfig: 'initConfig',
|
||||||
configStatus: 'config',
|
configStatus: 'config',
|
||||||
|
saveMyList: 'saveMyList',
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.mainWindow = {
|
exports.mainWindow = {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const WinLyric = require('./WinLyric')
|
|||||||
const HotKey = require('./HotKey')
|
const HotKey = require('./HotKey')
|
||||||
|
|
||||||
const { Event: UserApi } = require('../modules/userApi')
|
const { Event: UserApi } = require('../modules/userApi')
|
||||||
|
const { Event: Sync } = require('../modules/sync')
|
||||||
|
|
||||||
if (!global.lx_event.common) global.lx_event.common = new Common()
|
if (!global.lx_event.common) global.lx_event.common = new Common()
|
||||||
if (!global.lx_event.mainWindow) global.lx_event.mainWindow = new MainWindow()
|
if (!global.lx_event.mainWindow) global.lx_event.mainWindow = new MainWindow()
|
||||||
@@ -15,3 +16,4 @@ if (!global.lx_event.winLyric) global.lx_event.winLyric = new WinLyric()
|
|||||||
if (!global.lx_event.hotKey) global.lx_event.hotKey = new HotKey()
|
if (!global.lx_event.hotKey) global.lx_event.hotKey = new HotKey()
|
||||||
|
|
||||||
if (!global.lx_event.userApi) global.lx_event.userApi = new UserApi()
|
if (!global.lx_event.userApi) global.lx_event.userApi = new UserApi()
|
||||||
|
if (!global.lx_event.sync) global.lx_event.sync = new Sync()
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const { EventEmitter } = require('events')
|
||||||
|
const SYNC_EVENT_NAME = require('./name')
|
||||||
|
|
||||||
|
class Sync extends EventEmitter {
|
||||||
|
status(status) {
|
||||||
|
this.emit(SYNC_EVENT_NAME.status, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_list(data) {
|
||||||
|
this.emit(SYNC_EVENT_NAME.sync_list, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_handle_list(data) {
|
||||||
|
this.emit(SYNC_EVENT_NAME.sync_handle_list, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
action_list(data) {
|
||||||
|
this.emit(SYNC_EVENT_NAME.sync_action_list, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Sync
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
sync_action_list: 'sync_action_list',
|
||||||
|
sync_list: 'sync_list',
|
||||||
|
sync_handle_list: 'sync_handle_list',
|
||||||
|
status: 'status',
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const Event = require('./event/event')
|
||||||
|
const eventNames = require('./event/name')
|
||||||
|
const modules = require('./modules')
|
||||||
|
const { startServer, stopServer, getStatus, generateCode } = require('./server/server')
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
startServer,
|
||||||
|
stopServer,
|
||||||
|
getStatus,
|
||||||
|
generateCode,
|
||||||
|
Event,
|
||||||
|
eventNames,
|
||||||
|
modules,
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
exports.list = require('./list')
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
const { encryptMsg, decryptMsg } = require('../server/utils')
|
||||||
|
let io
|
||||||
|
|
||||||
|
const handleListAction = ({ action, data }) => {
|
||||||
|
// console.log(action, data)
|
||||||
|
global.lx_event.sync.action_list({ action, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// const addMusic = (orderId, callback) => {
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
|
||||||
|
const broadcast = async(action, data, excludeIds = []) => {
|
||||||
|
if (!io) return
|
||||||
|
const sockets = await io.fetchSockets()
|
||||||
|
for (const socket of sockets) {
|
||||||
|
if (excludeIds.includes(socket.data.keyInfo.clientId)) continue
|
||||||
|
socket.emit(action, encryptMsg(socket.data.keyInfo, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.sendListAction = (action, data) => {
|
||||||
|
// io.sockets
|
||||||
|
return broadcast('list:action', JSON.stringify({ action, data }))
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.registerListHandler = (_io, socket) => {
|
||||||
|
io = _io
|
||||||
|
socket.on('list:action', msg => {
|
||||||
|
// console.log(msg)
|
||||||
|
msg = decryptMsg(socket.data.keyInfo, msg)
|
||||||
|
if (!msg) return
|
||||||
|
handleListAction(JSON.parse(msg))
|
||||||
|
broadcast('list:action', msg, [socket.data.keyInfo.clientId])
|
||||||
|
// socket.broadcast.emit('list:action', { action: 'list_remove', data: { id: 'default', index: 0 } })
|
||||||
|
})
|
||||||
|
// socket.on('list:add', addMusic)
|
||||||
|
}
|
||||||
|
exports.unregisterListHandler = () => {
|
||||||
|
io = null
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
const { aesEncrypt, aesDecrypt, createClientKeyInfo, getClientKeyInfo, setClientKeyInfo } = require('./utils')
|
||||||
|
|
||||||
|
const authMsg = 'lx-music auth::'
|
||||||
|
const helloMsg = 'Hello~::^-^::'
|
||||||
|
|
||||||
|
exports.authCode = async(req, res, authCode) => {
|
||||||
|
let code = 401
|
||||||
|
let msg = 'Forbidden'
|
||||||
|
// console.log(req.headers)
|
||||||
|
if (req.headers.m) {
|
||||||
|
label:
|
||||||
|
if (req.headers.i) {
|
||||||
|
const keyInfo = getClientKeyInfo(req.headers.i)
|
||||||
|
if (!keyInfo) break label
|
||||||
|
let text
|
||||||
|
try {
|
||||||
|
text = aesDecrypt(req.headers.m, keyInfo.key, keyInfo.iv)
|
||||||
|
} catch (err) {
|
||||||
|
break label
|
||||||
|
}
|
||||||
|
console.log(text)
|
||||||
|
if (text.startsWith(authMsg)) {
|
||||||
|
code = 200
|
||||||
|
const deviceName = text.replace(authMsg, '') || 'Unknown'
|
||||||
|
if (deviceName != keyInfo.deviceName) {
|
||||||
|
keyInfo.deviceName = deviceName
|
||||||
|
setClientKeyInfo(keyInfo)
|
||||||
|
}
|
||||||
|
msg = aesEncrypt(helloMsg, keyInfo.key, keyInfo.iv)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let key = ''.padStart(16, Buffer.from(authCode).toString('hex'))
|
||||||
|
const iv = Buffer.from(key.split('').reverse().join('')).toString('base64')
|
||||||
|
key = Buffer.from(key).toString('base64')
|
||||||
|
// console.log(authCode, key, iv)
|
||||||
|
let text
|
||||||
|
try {
|
||||||
|
text = aesDecrypt(req.headers.m, key, iv)
|
||||||
|
} catch (err) {
|
||||||
|
break label
|
||||||
|
}
|
||||||
|
console.log(text)
|
||||||
|
if (text.startsWith(authMsg)) {
|
||||||
|
code = 200
|
||||||
|
const deviceName = text.replace(authMsg, '') || 'Unknown'
|
||||||
|
msg = aesEncrypt(JSON.stringify(createClientKeyInfo(deviceName)), key, iv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.writeHead(code)
|
||||||
|
res.end(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.authConnect = async req => {
|
||||||
|
const { i, t } = req._query
|
||||||
|
label:
|
||||||
|
if (i && t) {
|
||||||
|
const keyInfo = getClientKeyInfo(i)
|
||||||
|
if (!keyInfo) break label
|
||||||
|
let text
|
||||||
|
try {
|
||||||
|
text = aesDecrypt(t, keyInfo.key, keyInfo.iv)
|
||||||
|
} catch (err) {
|
||||||
|
break label
|
||||||
|
}
|
||||||
|
if (text == 'lx-music connect') return
|
||||||
|
}
|
||||||
|
throw new Error('failed')
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const { startServer, stopServer, getStatus } = require('./server')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
startServer,
|
||||||
|
stopServer,
|
||||||
|
getStatus,
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
const http = require('http')
|
||||||
|
const sio = require('socket.io')
|
||||||
|
const { createHttpTerminator } = require('http-terminator')
|
||||||
|
const modules = require('../modules')
|
||||||
|
const { authCode, authConnect } = require('./auth')
|
||||||
|
const { getAddress, getServerId, generateCode, getClientKeyInfo } = require('./utils')
|
||||||
|
const syncList = require('./syncList')
|
||||||
|
|
||||||
|
|
||||||
|
let status = {
|
||||||
|
status: false,
|
||||||
|
message: '',
|
||||||
|
address: [],
|
||||||
|
code: '',
|
||||||
|
devices: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConnection = (io, socket) => {
|
||||||
|
console.log('connection')
|
||||||
|
// console.log(socket.handshake.query)
|
||||||
|
for (const module of Object.values(modules)) {
|
||||||
|
module.registerListHandler(io, socket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const authConnection = (req, callback) => {
|
||||||
|
// console.log(req.headers)
|
||||||
|
// // console.log(req.auth)
|
||||||
|
// console.log(req._query.authCode)
|
||||||
|
authConnect(req).then(() => {
|
||||||
|
callback(null, true)
|
||||||
|
}).catch(err => {
|
||||||
|
callback(err, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let httpTerminator = null
|
||||||
|
let io = null
|
||||||
|
|
||||||
|
const handleStartServer = (port = 9527) => new Promise((resolve, reject) => {
|
||||||
|
const httpServer = http.createServer((req, res) => {
|
||||||
|
// console.log(req.url)
|
||||||
|
let code
|
||||||
|
let msg
|
||||||
|
switch (req.url) {
|
||||||
|
case '/hello':
|
||||||
|
code = 200
|
||||||
|
msg = 'Hello~::^-^::'
|
||||||
|
break
|
||||||
|
case '/id':
|
||||||
|
code = 200
|
||||||
|
msg = 'OjppZDo6' + getServerId()
|
||||||
|
break
|
||||||
|
case '/ah':
|
||||||
|
authCode(req, res, status.code)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
code = 401
|
||||||
|
msg = 'Forbidden'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (!code) return
|
||||||
|
res.writeHead(code)
|
||||||
|
res.end(msg)
|
||||||
|
})
|
||||||
|
httpTerminator = createHttpTerminator({
|
||||||
|
server: httpServer,
|
||||||
|
})
|
||||||
|
io = sio(httpServer, {
|
||||||
|
path: '/sync',
|
||||||
|
serveClient: false,
|
||||||
|
connectTimeout: 10000,
|
||||||
|
pingTimeout: 30000,
|
||||||
|
maxHttpBufferSize: 3e6,
|
||||||
|
allowRequest: authConnection,
|
||||||
|
transports: ['websocket'],
|
||||||
|
})
|
||||||
|
|
||||||
|
io.on('connection', async socket => {
|
||||||
|
socket.on('disconnect', reason => {
|
||||||
|
console.log('disconnect', reason)
|
||||||
|
status.devices.splice(status.devices.findIndex(k => k.clientId == keyInfo.clientId), 1)
|
||||||
|
global.lx_event.sync.status(status)
|
||||||
|
})
|
||||||
|
const keyInfo = getClientKeyInfo(socket.handshake.query.i)
|
||||||
|
// socket.lx_keyInfo = keyInfo
|
||||||
|
socket.data.keyInfo = keyInfo
|
||||||
|
try {
|
||||||
|
await syncList(io, socket)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
status.devices.push(keyInfo)
|
||||||
|
handleConnection(io, socket, keyInfo)
|
||||||
|
global.lx_event.sync.status(status)
|
||||||
|
})
|
||||||
|
|
||||||
|
httpServer.on('error', error => {
|
||||||
|
console.log(error)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
|
||||||
|
httpServer.on('listening', () => {
|
||||||
|
const addr = httpServer.address()
|
||||||
|
const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port
|
||||||
|
console.info(`Listening on ${bind}`)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
httpServer.listen(port)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleStopServer = async() => {
|
||||||
|
if (!httpTerminator) return
|
||||||
|
await io.close()
|
||||||
|
await httpTerminator.terminate().catch(() => {})
|
||||||
|
io = null
|
||||||
|
httpTerminator = null
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.stopServer = async() => {
|
||||||
|
if (!status.status) return
|
||||||
|
console.log('stoping sync server...')
|
||||||
|
return handleStopServer().then(() => {
|
||||||
|
console.log('sync server stoped')
|
||||||
|
status.status = false
|
||||||
|
status.message = ''
|
||||||
|
status.address = []
|
||||||
|
status.code = ''
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
status.message = err.message
|
||||||
|
}).finally(() => {
|
||||||
|
global.lx_event.sync.status(status)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
exports.startServer = async port => {
|
||||||
|
if (status.status) await handleStopServer()
|
||||||
|
|
||||||
|
console.log('starting sync server...')
|
||||||
|
return handleStartServer(port).then(() => {
|
||||||
|
console.log('sync server started')
|
||||||
|
status.status = true
|
||||||
|
status.message = ''
|
||||||
|
status.address = getAddress()
|
||||||
|
status.code = generateCode()
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
status.status = false
|
||||||
|
status.message = err.message
|
||||||
|
status.address = []
|
||||||
|
status.code = ''
|
||||||
|
}).finally(() => {
|
||||||
|
global.lx_event.sync.status(status)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getStatus = () => status
|
||||||
|
|
||||||
|
exports.generateCode = async() => {
|
||||||
|
status.code = generateCode()
|
||||||
|
global.lx_event.sync.status(status)
|
||||||
|
return status.code
|
||||||
|
}
|
||||||
@@ -0,0 +1,388 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const fsPromises = fs.promises
|
||||||
|
const { app } = require('electron')
|
||||||
|
const { encryptMsg, decryptMsg } = require('./utils')
|
||||||
|
const SYNC_EVENT_NAMES = require('../event/name')
|
||||||
|
const { common: COMMON_EVENT_NAME } = require('@main/events/_name')
|
||||||
|
const { throttle } = require('@common/utils')
|
||||||
|
|
||||||
|
let io
|
||||||
|
// const checkFile = path => {
|
||||||
|
// fsPromises.access(path, fs.constants.R_OK | fs.constants.W_OK)
|
||||||
|
// .then(() => console.log('can access'))
|
||||||
|
// .catch(() => console.error('cannot access'))
|
||||||
|
// }
|
||||||
|
|
||||||
|
const getRemoteListData = socket => new Promise((resolve, reject) => {
|
||||||
|
console.log('getRemoteListData')
|
||||||
|
const handleError = reason => {
|
||||||
|
reject(new Error(reason))
|
||||||
|
}
|
||||||
|
const handleSuccess = enData => {
|
||||||
|
socket.removeListener('disconnect', handleError)
|
||||||
|
socket.removeListener('list:sync', handleSuccess)
|
||||||
|
console.log('getRemoteListData', 'handleSuccess')
|
||||||
|
const data = JSON.parse(decryptMsg(socket.data.keyInfo, enData))
|
||||||
|
if (!data) return reject(new Error('Get remote list data failed'))
|
||||||
|
if (data.action != 'getData') return
|
||||||
|
resolve(data.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('disconnect', handleError)
|
||||||
|
socket.on('list:sync', handleSuccess)
|
||||||
|
socket.emit('list:sync', encryptMsg(socket.data.keyInfo, JSON.stringify({ action: 'getData', data: 'all' })))
|
||||||
|
})
|
||||||
|
|
||||||
|
const getLocalListData = () => new Promise((resolve, reject) => {
|
||||||
|
const handleSuccess = ({ action, data }) => {
|
||||||
|
if (action !== 'getData') return
|
||||||
|
global.lx_event.sync.off(SYNC_EVENT_NAMES.sync_handle_list, handleSuccess)
|
||||||
|
resolve(data)
|
||||||
|
}
|
||||||
|
global.lx_event.sync.on(SYNC_EVENT_NAMES.sync_handle_list, handleSuccess)
|
||||||
|
global.lx_event.sync.sync_list({
|
||||||
|
action: 'getData',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const getSyncMode = keyInfo => new Promise((resolve, reject) => {
|
||||||
|
const handleSuccess = ({ action, data }) => {
|
||||||
|
if (action !== 'selectMode') return
|
||||||
|
global.lx_event.sync.off(SYNC_EVENT_NAMES.sync_handle_list, handleSuccess)
|
||||||
|
resolve(data)
|
||||||
|
}
|
||||||
|
global.lx_event.sync.on(SYNC_EVENT_NAMES.sync_handle_list, handleSuccess)
|
||||||
|
global.lx_event.sync.sync_list({
|
||||||
|
action: 'selectMode',
|
||||||
|
data: keyInfo,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const finishedSync = socket => {
|
||||||
|
return socket.emit('list:sync', encryptMsg(socket.data.keyInfo, JSON.stringify({
|
||||||
|
action: 'finished',
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
const setLocalList = listData => {
|
||||||
|
global.lx_event.sync.sync_list({
|
||||||
|
action: 'setData',
|
||||||
|
data: listData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const setRemotelList = async(socket, listData) => {
|
||||||
|
if (!io) return
|
||||||
|
const sockets = await io.fetchSockets()
|
||||||
|
for (const socket of sockets) {
|
||||||
|
// if (excludeIds.includes(socket.data.keyInfo.clientId)) continue
|
||||||
|
socket.emit('list:sync', encryptMsg(socket.data.keyInfo, JSON.stringify({ action: 'setData', data: listData })))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let writeFilePromises = {}
|
||||||
|
const updateSnapshot = (path, data) => {
|
||||||
|
console.log('updateSnapshot', path)
|
||||||
|
let writeFilePromise = writeFilePromises[path] || Promise.resolve()
|
||||||
|
return writeFilePromise.then(() => {
|
||||||
|
writeFilePromise = writeFilePromises[path] = fsPromises.writeFile(path, data)
|
||||||
|
return writeFilePromise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const createListDataObj = listData => {
|
||||||
|
const listDataObj = {}
|
||||||
|
for (const list of listData.userList) listDataObj[list.id] = list
|
||||||
|
return listDataObj
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMergeList = (sourceList, targetList, addMusicLocationType) => {
|
||||||
|
let newList
|
||||||
|
switch (addMusicLocationType) {
|
||||||
|
case 'top':
|
||||||
|
newList = [...targetList.list, ...sourceList.list]
|
||||||
|
break
|
||||||
|
case 'bottom':
|
||||||
|
default:
|
||||||
|
newList = [...sourceList.list, ...targetList.list]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const map = {}
|
||||||
|
const ids = []
|
||||||
|
switch (addMusicLocationType) {
|
||||||
|
case 'top':
|
||||||
|
newList = [...targetList.list, ...sourceList.list]
|
||||||
|
for (let i = newList.length - 1; i > -1; i--) {
|
||||||
|
const item = newList[i]
|
||||||
|
if (map[item.songmid]) continue
|
||||||
|
ids.unshift(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'bottom':
|
||||||
|
default:
|
||||||
|
newList = [...sourceList.list, ...targetList.list]
|
||||||
|
for (const item of newList) {
|
||||||
|
if (map[item.songmid]) continue
|
||||||
|
ids.push(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...sourceList,
|
||||||
|
list: ids.map(id => map[id]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mergeList = (sourceListData, targetListData) => {
|
||||||
|
const addMusicLocationType = global.appSetting.list.addMusicLocationType
|
||||||
|
const newListData = {}
|
||||||
|
newListData.defaultList = handleMergeList(sourceListData.defaultList, targetListData.defaultList, addMusicLocationType)
|
||||||
|
newListData.loveList = handleMergeList(sourceListData.loveList, targetListData.loveList, addMusicLocationType)
|
||||||
|
|
||||||
|
const listDataObj = createListDataObj(sourceListData)
|
||||||
|
newListData.userList = [...sourceListData.userList]
|
||||||
|
|
||||||
|
for (const list of targetListData.userList) {
|
||||||
|
const targetList = listDataObj[list.id]
|
||||||
|
if (targetList) {
|
||||||
|
targetList.list = handleMergeList(targetList, list, addMusicLocationType).list
|
||||||
|
} else {
|
||||||
|
newListData.userList.push(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newListData
|
||||||
|
}
|
||||||
|
const overwriteList = (sourceListData, targetListData) => {
|
||||||
|
const newListData = {}
|
||||||
|
newListData.defaultList = sourceListData.defaultList
|
||||||
|
newListData.loveList = sourceListData.loveList
|
||||||
|
|
||||||
|
const listDataObj = createListDataObj(sourceListData)
|
||||||
|
newListData.userList = [...sourceListData.userList]
|
||||||
|
|
||||||
|
for (const list of targetListData.userList) {
|
||||||
|
const targetList = listDataObj[list.id]
|
||||||
|
if (targetList) continue
|
||||||
|
newListData.userList.push(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newListData
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMergeListData = async socket => {
|
||||||
|
let isSelectingMode = false
|
||||||
|
const handleDisconnect = () => {
|
||||||
|
if (!isSelectingMode) return
|
||||||
|
global.lx_event.sync.sync_list({
|
||||||
|
action: 'closeSelectMode',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
socket.on('disconnect', handleDisconnect)
|
||||||
|
isSelectingMode = true
|
||||||
|
const mode = await getSyncMode(socket.data.keyInfo)
|
||||||
|
isSelectingMode = false
|
||||||
|
const [remoteListData, localListData] = await Promise.all([getRemoteListData(socket), getLocalListData()])
|
||||||
|
console.log('handleMergeListData', 'remoteListData, localListData')
|
||||||
|
let listData
|
||||||
|
switch (mode) {
|
||||||
|
case 'merge_local_remote':
|
||||||
|
listData = mergeList(localListData, remoteListData)
|
||||||
|
break
|
||||||
|
case 'merge_remote_local':
|
||||||
|
listData = mergeList(remoteListData, localListData)
|
||||||
|
break
|
||||||
|
case 'overwrite_local_remote':
|
||||||
|
listData = overwriteList(localListData, remoteListData)
|
||||||
|
break
|
||||||
|
case 'overwrite_remote_local':
|
||||||
|
listData = overwriteList(remoteListData, localListData)
|
||||||
|
break
|
||||||
|
case 'overwrite_local_remote_full':
|
||||||
|
listData = localListData
|
||||||
|
break
|
||||||
|
case 'overwrite_remote_local_full':
|
||||||
|
listData = remoteListData
|
||||||
|
break
|
||||||
|
case 'none': return
|
||||||
|
case 'cancel':
|
||||||
|
socket.disconnect(true)
|
||||||
|
throw new Error('cancel')
|
||||||
|
}
|
||||||
|
return listData
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSyncList = async socket => {
|
||||||
|
const [remoteListData, localListData] = await Promise.all([getRemoteListData(socket), getLocalListData()])
|
||||||
|
console.log('handleSyncList', 'remoteListData, localListData')
|
||||||
|
const listData = {}
|
||||||
|
if (localListData.defaultList.list.length || localListData.loveList.list.length || localListData.userList.length) {
|
||||||
|
if (remoteListData.defaultList.list.length || remoteListData.loveList.list.length || remoteListData.userList.length) {
|
||||||
|
const mergedList = await handleMergeListData(socket)
|
||||||
|
console.log('handleMergeListData', 'mergedList')
|
||||||
|
console.log(mergedList)
|
||||||
|
if (!mergedList) return
|
||||||
|
listData.defaultList = mergedList.defaultList
|
||||||
|
listData.loveList = mergedList.loveList
|
||||||
|
listData.userList = mergedList.userList
|
||||||
|
setLocalList(mergedList)
|
||||||
|
setRemotelList(socket, mergedList)
|
||||||
|
} else {
|
||||||
|
setRemotelList(socket, localListData)
|
||||||
|
listData.defaultList = localListData.defaultList
|
||||||
|
listData.loveList = localListData.loveList
|
||||||
|
listData.userList = localListData.userList
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (remoteListData.defaultList.list.length || remoteListData.loveList.list.length || remoteListData.userList.length) {
|
||||||
|
setLocalList(remoteListData)
|
||||||
|
listData.defaultList = remoteListData.defaultList
|
||||||
|
listData.loveList = remoteListData.loveList
|
||||||
|
listData.userList = remoteListData.userList
|
||||||
|
} else {
|
||||||
|
listData.defaultList = localListData.defaultList
|
||||||
|
listData.loveList = localListData.loveList
|
||||||
|
listData.userList = localListData.userList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updateSnapshot(socket.data.snapshotFilePath, JSON.stringify({
|
||||||
|
defaultList: listData.defaultList,
|
||||||
|
loveList: listData.loveList,
|
||||||
|
userList: listData.userList,
|
||||||
|
})).then(() => {
|
||||||
|
socket.data.isCreatedSnapshot = true
|
||||||
|
return listData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergeListDataFromSnapshot = (sourceList, targetList, snapshotList, addMusicLocationType) => {
|
||||||
|
const removedListIds = new Set()
|
||||||
|
const sourceListItemIds = new Set()
|
||||||
|
const targetListItemIds = new Set()
|
||||||
|
for (const m of sourceList.list) sourceListItemIds.add(m.songmid)
|
||||||
|
for (const m of targetList.list) targetListItemIds.add(m.songmid)
|
||||||
|
for (const m of snapshotList.list) {
|
||||||
|
if (!sourceListItemIds.has(m.songmid)) removedListIds.add(m.songmid)
|
||||||
|
}
|
||||||
|
for (const m of snapshotList.list) {
|
||||||
|
if (!targetListItemIds.has(m.songmid)) removedListIds.add(m.songmid)
|
||||||
|
}
|
||||||
|
|
||||||
|
let newList
|
||||||
|
const map = {}
|
||||||
|
const ids = []
|
||||||
|
switch (addMusicLocationType) {
|
||||||
|
case 'top':
|
||||||
|
newList = [...targetList.list, ...sourceList.list]
|
||||||
|
for (let i = newList.length - 1; i > -1; i--) {
|
||||||
|
const item = newList[i]
|
||||||
|
if (map[item.songmid] || removedListIds.has(item.songmid)) continue
|
||||||
|
ids.unshift(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'bottom':
|
||||||
|
default:
|
||||||
|
newList = [...sourceList.list, ...targetList.list]
|
||||||
|
for (const item of newList) {
|
||||||
|
if (map[item.songmid] || removedListIds.has(item.songmid)) continue
|
||||||
|
ids.push(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...sourceList,
|
||||||
|
list: ids.map(id => map[id]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleMergeListDataFromSnapshot = async(socket, snapshot) => {
|
||||||
|
const addMusicLocationType = global.appSetting.list.addMusicLocationType
|
||||||
|
const [remoteListData, localListData] = await Promise.all([getRemoteListData(socket), getLocalListData()])
|
||||||
|
console.log('handleMergeListDataFromSnapshot', 'remoteListData, localListData')
|
||||||
|
const newListData = {}
|
||||||
|
newListData.defaultList = mergeListDataFromSnapshot(localListData.defaultList, remoteListData.defaultList, snapshot.defaultList, addMusicLocationType)
|
||||||
|
newListData.loveList = mergeListDataFromSnapshot(localListData.loveList, remoteListData.loveList, snapshot.loveList, addMusicLocationType)
|
||||||
|
const localUserListData = createListDataObj(localListData)
|
||||||
|
const remoteUserListData = createListDataObj(remoteListData)
|
||||||
|
const snapshotUserListData = createListDataObj(snapshot)
|
||||||
|
const removedListIds = new Set()
|
||||||
|
const localUserListIds = new Set()
|
||||||
|
const remoteUserListIds = new Set()
|
||||||
|
for (const l of localListData.userList) localUserListIds.add(l.id)
|
||||||
|
for (const l of remoteListData.userList) remoteUserListIds.add(l.id)
|
||||||
|
|
||||||
|
for (const l of snapshot.userList) {
|
||||||
|
if (!localUserListIds.has(l.id)) removedListIds.add(l.id)
|
||||||
|
}
|
||||||
|
for (const l of snapshot.userList) {
|
||||||
|
if (!remoteUserListIds.has(l.id)) removedListIds.add(l.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
let newUserList = []
|
||||||
|
for (const list of localListData.userList) {
|
||||||
|
if (removedListIds.has(list.id)) continue
|
||||||
|
const remoteList = remoteUserListData[list.id]
|
||||||
|
let newList
|
||||||
|
if (remoteList) {
|
||||||
|
newList = mergeListDataFromSnapshot(list, remoteList, snapshotUserListData[list.id], addMusicLocationType)
|
||||||
|
} else {
|
||||||
|
newList = { ...list }
|
||||||
|
}
|
||||||
|
newUserList.push(newList)
|
||||||
|
}
|
||||||
|
for (const list of remoteListData.userList) {
|
||||||
|
if (removedListIds.has(list.id) || localUserListData[list.id]) continue
|
||||||
|
newUserList.push({ ...list })
|
||||||
|
}
|
||||||
|
newListData.userList = newUserList
|
||||||
|
setLocalList(newListData)
|
||||||
|
setRemotelList(socket, newListData)
|
||||||
|
return updateSnapshot(socket.data.snapshotFilePath, JSON.stringify({
|
||||||
|
defaultList: newListData.defaultList,
|
||||||
|
loveList: newListData.loveList,
|
||||||
|
userList: newListData.userList,
|
||||||
|
})).then(() => {
|
||||||
|
socket.data.isCreatedSnapshot = true
|
||||||
|
return newListData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerUpdateSnapshotTask = (socket, snapshot) => {
|
||||||
|
if (!socket.data.isCreatedSnapshot) return
|
||||||
|
const handleUpdateSnapshot = throttle(({ defaultList, loveList, userList }) => {
|
||||||
|
if (defaultList != null) snapshot.defaultList = defaultList
|
||||||
|
if (loveList != null) snapshot.loveList = loveList
|
||||||
|
if (userList != null) snapshot.userList = userList
|
||||||
|
updateSnapshot(socket.data.snapshotFilePath, JSON.stringify(snapshot))
|
||||||
|
}, 10000)
|
||||||
|
global.lx_event.common.on(COMMON_EVENT_NAME.saveMyList, handleUpdateSnapshot)
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
global.lx_event.common.off(COMMON_EVENT_NAME.saveMyList, handleUpdateSnapshot)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const syncList = async socket => {
|
||||||
|
socket.data.snapshotFilePath = path.join(app.getPath('userData'), `snapshot-${Buffer.from(socket.data.keyInfo.clientId).toString('hex').substring(0, 10)}.json`)
|
||||||
|
let fileData
|
||||||
|
let isSyncRequired = false
|
||||||
|
try {
|
||||||
|
fileData = await fsPromises.readFile(socket.data.snapshotFilePath)
|
||||||
|
fileData = JSON.parse(fileData)
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code !== 'ENOENT') throw err
|
||||||
|
isSyncRequired = true
|
||||||
|
}
|
||||||
|
console.log('isSyncRequired', isSyncRequired)
|
||||||
|
if (isSyncRequired) return handleSyncList(socket)
|
||||||
|
return handleMergeListDataFromSnapshot(socket, fileData)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = (_io, socket) => {
|
||||||
|
io = _io
|
||||||
|
return syncList(socket).then(newListData => {
|
||||||
|
registerUpdateSnapshotTask(socket, { ...newListData })
|
||||||
|
return finishedSync(socket)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
const { networkInterfaces } = require('os')
|
||||||
|
const { randomBytes, createCipheriv, createDecipheriv } = require('crypto')
|
||||||
|
const getStore = require('@common/store')
|
||||||
|
const STORE_NAME = 'sync'
|
||||||
|
|
||||||
|
exports.getAddress = () => {
|
||||||
|
const nets = networkInterfaces()
|
||||||
|
const results = []
|
||||||
|
// console.log(nets)
|
||||||
|
|
||||||
|
for (const name of Object.keys(nets)) {
|
||||||
|
for (const net of nets[name]) {
|
||||||
|
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
||||||
|
if (net.family === 'IPv4' && !net.internal) {
|
||||||
|
results.push(net.address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
let serverId
|
||||||
|
exports.getServerId = () => {
|
||||||
|
if (serverId) return serverId
|
||||||
|
const store = getStore(STORE_NAME)
|
||||||
|
serverId = store.get('serverId')
|
||||||
|
if (!serverId) {
|
||||||
|
serverId = randomBytes(4 * 4).toString('base64')
|
||||||
|
store.set('serverId', serverId)
|
||||||
|
}
|
||||||
|
return serverId
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyInfos
|
||||||
|
exports.createClientKeyInfo = deviceName => {
|
||||||
|
const keyInfo = {
|
||||||
|
clientId: randomBytes(4 * 4).toString('base64'),
|
||||||
|
key: randomBytes(16).toString('base64'),
|
||||||
|
iv: randomBytes(16).toString('base64'),
|
||||||
|
deviceName,
|
||||||
|
}
|
||||||
|
const store = getStore(STORE_NAME)
|
||||||
|
if (!keyInfos) keyInfos = store.get('keys') || {}
|
||||||
|
if (Object.keys(keyInfos).length > 101) throw new Error('max keys')
|
||||||
|
|
||||||
|
keyInfos[keyInfo.clientId] = keyInfo
|
||||||
|
store.set('keys', keyInfos)
|
||||||
|
return keyInfo
|
||||||
|
}
|
||||||
|
exports.setClientKeyInfo = keyInfo => {
|
||||||
|
keyInfos[keyInfo.clientId] = keyInfo
|
||||||
|
const store = getStore(STORE_NAME)
|
||||||
|
store.set('keys', keyInfos)
|
||||||
|
}
|
||||||
|
exports.getClientKeyInfo = clientId => {
|
||||||
|
if (!keyInfos) {
|
||||||
|
const store = getStore(STORE_NAME)
|
||||||
|
keyInfos = store.get('keys') || {}
|
||||||
|
}
|
||||||
|
return keyInfos[clientId] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.generateCode = () => {
|
||||||
|
return Math.random().toString().substring(2, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.aesEncrypt = (buffer, key, iv) => {
|
||||||
|
const cipher = createCipheriv('aes-128-cbc', Buffer.from(key, 'base64'), Buffer.from(iv, 'base64'))
|
||||||
|
return Buffer.concat([cipher.update(buffer), cipher.final()]).toString('base64')
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.aesDecrypt = (text, key, iv) => {
|
||||||
|
const decipher = createDecipheriv('aes-128-cbc', Buffer.from(key, 'base64'), Buffer.from(iv, 'base64'))
|
||||||
|
return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.encryptMsg = (keyInfo, msg) => {
|
||||||
|
return msg
|
||||||
|
// if (!keyInfo) return ''
|
||||||
|
// return exports.aesEncrypt(msg, keyInfo.key, keyInfo.iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.decryptMsg = (keyInfo, enMsg) => {
|
||||||
|
return enMsg
|
||||||
|
// if (!keyInfo) return ''
|
||||||
|
// let msg = ''
|
||||||
|
// try {
|
||||||
|
// msg = exports.aesDecrypt(enMsg, keyInfo.key, keyInfo.iv)
|
||||||
|
// } catch (err) {
|
||||||
|
// console.log(err)
|
||||||
|
// }
|
||||||
|
// return msg
|
||||||
|
}
|
||||||
@@ -23,3 +23,4 @@ require('./musicUrl')
|
|||||||
require('./kw_decodeLyric')
|
require('./kw_decodeLyric')
|
||||||
|
|
||||||
require('./userApi')
|
require('./userApi')
|
||||||
|
require('./sync')
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ mainOn(ipcMainWindowNames.save_playlist, (event, { type, data }) => {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'myList':
|
case 'myList':
|
||||||
handleSaveList(data)
|
handleSaveList(data)
|
||||||
|
global.lx_event.common.saveMyList(data)
|
||||||
break
|
break
|
||||||
case 'downloadList':
|
case 'downloadList':
|
||||||
getStore('downloadList').set('list', data)
|
getStore('downloadList').set('list', data)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
const { mainSend, NAMES: { mainWindow: ipcMainWindowNames }, mainOn, mainHandle } = require('@common/ipc')
|
||||||
|
const { eventNames, modules, startServer, stopServer, getStatus, generateCode } = require('../modules/sync')
|
||||||
|
|
||||||
|
|
||||||
|
mainOn(ipcMainWindowNames.sync_action_list, (event, { action, data }) => {
|
||||||
|
modules.list.sendListAction(action, data)
|
||||||
|
})
|
||||||
|
|
||||||
|
mainHandle(ipcMainWindowNames.sync_enable, (event, { enable, port }) => {
|
||||||
|
return enable ? startServer(port) : stopServer()
|
||||||
|
})
|
||||||
|
|
||||||
|
mainHandle(ipcMainWindowNames.sync_get_status, () => {
|
||||||
|
return getStatus()
|
||||||
|
})
|
||||||
|
|
||||||
|
mainHandle(ipcMainWindowNames.sync_generate_code, () => {
|
||||||
|
return generateCode()
|
||||||
|
})
|
||||||
|
|
||||||
|
mainOn(ipcMainWindowNames.sync_list, (event, { action, data }) => {
|
||||||
|
global.lx_event.sync.sync_handle_list({ action, data })
|
||||||
|
})
|
||||||
|
|
||||||
|
global.lx_event.sync.on(eventNames.sync_action_list, ({ action, data }) => {
|
||||||
|
mainSend(global.modules.mainWindow, ipcMainWindowNames.sync_action_list, { action, data })
|
||||||
|
})
|
||||||
|
global.lx_event.sync.on(eventNames.status, status => {
|
||||||
|
mainSend(global.modules.mainWindow, ipcMainWindowNames.sync_status, status)
|
||||||
|
})
|
||||||
|
global.lx_event.sync.on(eventNames.sync_list, ({ action, data }) => {
|
||||||
|
mainSend(global.modules.mainWindow, ipcMainWindowNames.sync_list, { action, data })
|
||||||
|
})
|
||||||
+115
-3
@@ -8,6 +8,7 @@
|
|||||||
core-icons
|
core-icons
|
||||||
material-version-modal(v-show="version.showModal")
|
material-version-modal(v-show="version.showModal")
|
||||||
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
||||||
|
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
|
||||||
#container(v-else :class="theme")
|
#container(v-else :class="theme")
|
||||||
core-aside#left
|
core-aside#left
|
||||||
#right
|
#right
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
core-icons
|
core-icons
|
||||||
material-version-modal(v-show="version.showModal")
|
material-version-modal(v-show="version.showModal")
|
||||||
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
material-pact-modal(v-show="!setting.isAgreePact || globalObj.isShowPact")
|
||||||
|
material-sync-mode-modal(v-show="globalObj.sync.isShowSyncMode")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -25,7 +27,7 @@ import { rendererOn, rendererSend, rendererInvoke, NAMES } from '../common/ipc'
|
|||||||
import { isLinux } from '../common/utils'
|
import { isLinux } from '../common/utils'
|
||||||
import music from './utils/music'
|
import music from './utils/music'
|
||||||
import { throttle, openUrl, compareVer, getPlayList, parseUrlParams, saveSetting } from './utils'
|
import { throttle, openUrl, compareVer, getPlayList, parseUrlParams, saveSetting } from './utils'
|
||||||
import { base as eventBaseName } from './event/names'
|
import { base as eventBaseName, sync as eventSyncName } from './event/names'
|
||||||
import apiSourceInfo from './utils/music/api-source-info'
|
import apiSourceInfo from './utils/music/api-source-info'
|
||||||
|
|
||||||
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
|
window.ELECTRON_DISABLE_SECURITY_WARNINGS = process.env.ELECTRON_DISABLE_SECURITY_WARNINGS
|
||||||
@@ -61,6 +63,11 @@ export default {
|
|||||||
message: 'initing',
|
message: 'initing',
|
||||||
apis: {},
|
apis: {},
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
enable: false,
|
||||||
|
isShowSyncMode: false,
|
||||||
|
deviceName: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
updateTimeout: null,
|
updateTimeout: null,
|
||||||
envParams: {
|
envParams: {
|
||||||
@@ -103,6 +110,14 @@ export default {
|
|||||||
document.body.classList.add(this.isDT ? 'disableTransparent' : 'transparent')
|
document.body.classList.add(this.isDT ? 'disableTransparent' : 'transparent')
|
||||||
window.eventHub.$emit(eventBaseName.bindKey)
|
window.eventHub.$emit(eventBaseName.bindKey)
|
||||||
this.init()
|
this.init()
|
||||||
|
window.eventHub.$on(eventSyncName.handle_action_list, this.handleSyncAction)
|
||||||
|
window.eventHub.$on(eventSyncName.handle_sync_list, this.handleSyncList)
|
||||||
|
if (this.setting.sync.enable && this.setting.sync.port) {
|
||||||
|
rendererInvoke(NAMES.mainWindow.sync_enable, {
|
||||||
|
enable: this.setting.sync.enable,
|
||||||
|
port: this.setting.sync.port,
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
setting: {
|
setting: {
|
||||||
@@ -193,7 +208,25 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapActions(['getVersionInfo']),
|
...mapActions(['getVersionInfo']),
|
||||||
...mapMutations(['setNewVersion', 'setVersionModalVisible', 'setDownloadProgress', 'setSetting', 'setDesktopLyricConfig']),
|
...mapMutations(['setNewVersion', 'setVersionModalVisible', 'setDownloadProgress', 'setSetting', 'setDesktopLyricConfig']),
|
||||||
...mapMutations('list', ['initList']),
|
...mapMutations('list', {
|
||||||
|
list_initList: 'initList',
|
||||||
|
list_setList: 'setList',
|
||||||
|
list_listAdd: 'listAdd',
|
||||||
|
list_listMove: 'listMove',
|
||||||
|
list_listAddMultiple: 'listAddMultiple',
|
||||||
|
list_listMoveMultiple: 'listMoveMultiple',
|
||||||
|
list_listRemove: 'listRemove',
|
||||||
|
list_listRemoveMultiple: 'listRemoveMultiple',
|
||||||
|
list_listClear: 'listClear',
|
||||||
|
list_updateMusicInfo: 'updateMusicInfo',
|
||||||
|
list_createUserList: 'createUserList',
|
||||||
|
list_removeUserList: 'removeUserList',
|
||||||
|
list_setUserListName: 'setUserListName',
|
||||||
|
list_moveupUserList: 'moveupUserList',
|
||||||
|
list_movedownUserList: 'movedownUserList',
|
||||||
|
list_setMusicPosition: 'setMusicPosition',
|
||||||
|
list_setSyncListData: 'setSyncListData',
|
||||||
|
}),
|
||||||
...mapMutations('download', ['updateDownloadList']),
|
...mapMutations('download', ['updateDownloadList']),
|
||||||
...mapMutations('search', {
|
...mapMutations('search', {
|
||||||
setSearchHistoryList: 'setHistory',
|
setSearchHistoryList: 'setHistory',
|
||||||
@@ -272,6 +305,7 @@ export default {
|
|||||||
this.listenEvent()
|
this.listenEvent()
|
||||||
asyncTask.push(this.initData())
|
asyncTask.push(this.initData())
|
||||||
asyncTask.push(this.initUserApi())
|
asyncTask.push(this.initUserApi())
|
||||||
|
this.globalObj.sync.enable = this.setting.sync.enable
|
||||||
this.globalObj.apiSource = this.setting.apiSource
|
this.globalObj.apiSource = this.setting.apiSource
|
||||||
if (/^user_api/.test(this.setting.apiSource)) {
|
if (/^user_api/.test(this.setting.apiSource)) {
|
||||||
rendererInvoke(NAMES.mainWindow.set_user_api, this.setting.apiSource)
|
rendererInvoke(NAMES.mainWindow.set_user_api, this.setting.apiSource)
|
||||||
@@ -328,7 +362,7 @@ export default {
|
|||||||
|
|
||||||
if (!defaultList.list) defaultList.list = []
|
if (!defaultList.list) defaultList.list = []
|
||||||
if (!loveList.list) loveList.list = []
|
if (!loveList.list) loveList.list = []
|
||||||
this.initList({ defaultList, loveList, userList })
|
this.list_initList({ defaultList, loveList, userList })
|
||||||
this.initDownloadList(downloadList) // 初始化下载列表
|
this.initDownloadList(downloadList) // 初始化下载列表
|
||||||
this.initPlayInfo()
|
this.initPlayInfo()
|
||||||
})
|
})
|
||||||
@@ -590,6 +624,84 @@ export default {
|
|||||||
event.target.value = ''
|
event.target.value = ''
|
||||||
event.target.blur()
|
event.target.blur()
|
||||||
},
|
},
|
||||||
|
handleSyncAction({ action, data }) {
|
||||||
|
if (typeof data == 'object') data.isSync = true
|
||||||
|
// console.log(action, data)
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'set_list':
|
||||||
|
this.list_setList(data)
|
||||||
|
break
|
||||||
|
case 'list_add':
|
||||||
|
this.list_listAdd(data)
|
||||||
|
break
|
||||||
|
case 'list_move':
|
||||||
|
this.list_listMove(data)
|
||||||
|
break
|
||||||
|
case 'list_add_multiple':
|
||||||
|
this.list_listAddMultiple(data)
|
||||||
|
break
|
||||||
|
case 'list_move_multiple':
|
||||||
|
this.list_listMoveMultiple(data)
|
||||||
|
break
|
||||||
|
case 'list_remove':
|
||||||
|
this.list_listRemove(data)
|
||||||
|
break
|
||||||
|
case 'list_remove_multiple':
|
||||||
|
this.list_listRemoveMultiple(data)
|
||||||
|
break
|
||||||
|
case 'list_clear':
|
||||||
|
this.list_listClear(data)
|
||||||
|
break
|
||||||
|
case 'update_music_info':
|
||||||
|
this.list_updateMusicInfo(data)
|
||||||
|
break
|
||||||
|
case 'create_user_list':
|
||||||
|
this.list_createUserList(data)
|
||||||
|
break
|
||||||
|
case 'remove_user_list':
|
||||||
|
this.list_removeUserList(data)
|
||||||
|
break
|
||||||
|
case 'set_user_list_name':
|
||||||
|
this.list_setUserListName(data)
|
||||||
|
break
|
||||||
|
case 'moveup_user_list':
|
||||||
|
this.list_moveupUserList(data)
|
||||||
|
break
|
||||||
|
case 'movedown_user_list':
|
||||||
|
this.list_movedownUserList(data)
|
||||||
|
break
|
||||||
|
case 'set_music_position':
|
||||||
|
this.list_setMusicPosition(data)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSyncList({ action, data }) {
|
||||||
|
switch (action) {
|
||||||
|
case 'getData':
|
||||||
|
global.eventHub.$emit(eventSyncName.send_sync_list, {
|
||||||
|
action: 'getData',
|
||||||
|
data: {
|
||||||
|
defaultList: this.defaultList,
|
||||||
|
loveList: this.loveList,
|
||||||
|
userList: this.userList,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'setData':
|
||||||
|
this.list_setSyncListData(data)
|
||||||
|
break
|
||||||
|
case 'selectMode':
|
||||||
|
this.globalObj.sync.deviceName = data.deviceName
|
||||||
|
this.globalObj.sync.isShowSyncMode = true
|
||||||
|
break
|
||||||
|
case 'closeSelectMode':
|
||||||
|
this.globalObj.sync.isShowSyncMode = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.clearUpdateTimeout()
|
this.clearUpdateTimeout()
|
||||||
|
|||||||
@@ -123,6 +123,9 @@ small {
|
|||||||
.small {
|
.small {
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
}
|
}
|
||||||
|
.tip {
|
||||||
|
color: @color-theme_2-font-label;
|
||||||
|
}
|
||||||
strong {
|
strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@@ -192,6 +195,9 @@ each(@themes, {
|
|||||||
button, input, textarea, a {
|
button, input, textarea, a {
|
||||||
color: ~'@{color-@{value}-theme_2-font}';
|
color: ~'@{color-@{value}-theme_2-font}';
|
||||||
}
|
}
|
||||||
|
.tip {
|
||||||
|
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||||
|
}
|
||||||
|
|
||||||
.hover, a {
|
.hover, a {
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ export default {
|
|||||||
this.restorePlayTime = 0
|
this.restorePlayTime = 0
|
||||||
}
|
}
|
||||||
if (!this.targetSong.interval && this.listId != 'download') {
|
if (!this.targetSong.interval && this.listId != 'download') {
|
||||||
this.updateMusicInfo({ id: this.listId, index: this.playIndex, data: { interval: formatPlayTime2(this.maxPlayTime) }, musicInfo: this.targetSong })
|
this.updateMusicInfo({ listId: this.listId, id: this.targetSong.songmid, musicInfo: this.targetSong, data: { interval: formatPlayTime2(this.maxPlayTime) } })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
audio.addEventListener('loadstart', () => {
|
audio.addEventListener('loadstart', () => {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export default {
|
|||||||
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
|
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
max-width: 70%;
|
max-width: 76%;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
material-modal(:show="globalObj.sync.isShowSyncMode" @close="handleClose(false)" :bgClose="false" :close-btn="false")
|
||||||
|
main(:class="$style.main")
|
||||||
|
h2 {{$t('material.sync_mode_modal.title', { name: globalObj.sync.deviceName })}}
|
||||||
|
div.scroll(:class="$style.content")
|
||||||
|
dl(:class="$style.btnGroup")
|
||||||
|
dt(:class="$style.label") {{$t('material.sync_mode_modal.merge_label')}}
|
||||||
|
dd(:class="$style.btns")
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('merge_local_remote')") {{$t('material.sync_mode_modal.merge_btn_local_remote')}}
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('merge_remote_local')") {{$t('material.sync_mode_modal.merge_btn_remote_local')}}
|
||||||
|
dl(:class="$style.btnGroup")
|
||||||
|
dt(:class="$style.label") {{$t('material.sync_mode_modal.overwrite_label')}}
|
||||||
|
dd(:class="$style.btns")
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('overwrite_local_remote')") {{$t('material.sync_mode_modal.overwrite_btn_local_remote')}}
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('overwrite_remote_local')") {{$t('material.sync_mode_modal.overwrite_btn_remote_local')}}
|
||||||
|
dd(style="font-size: 14px; margin-top: 5px;")
|
||||||
|
material-checkbox(id="sync_mode_modal_isOverwrite" v-model="isOverwrite" :label="$t('material.sync_mode_modal.overwrite')")
|
||||||
|
|
||||||
|
dl(:class="$style.btnGroup")
|
||||||
|
dt(:class="$style.label") {{$t('material.sync_mode_modal.other_label')}}
|
||||||
|
dd(:class="$style.btns")
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('none')") {{$t('material.sync_mode_modal.overwrite_btn_none')}}
|
||||||
|
material-btn(:class="$style.btn" @click="handleSelectMode('cancel')") {{$t('material.sync_mode_modal.overwrite_btn_cancel')}}
|
||||||
|
dl(:class="$style.btnGroup")
|
||||||
|
dd
|
||||||
|
section(:class="$style.tipGroup")
|
||||||
|
h3(:class="$style.title") {{$t('material.sync_mode_modal.merge_tip')}}
|
||||||
|
p(:class="$style.tip") {{$t('material.sync_mode_modal.merge_tip_desc')}}
|
||||||
|
section(:class="$style.tipGroup")
|
||||||
|
h3(:class="$style.title") {{$t('material.sync_mode_modal.overwrite_tip')}}
|
||||||
|
p(:class="$style.tip") {{$t('material.sync_mode_modal.overwrite_tip_desc')}}
|
||||||
|
section(:class="$style.tipGroup")
|
||||||
|
h3(:class="$style.title") {{$t('material.sync_mode_modal.other_tip')}}
|
||||||
|
p(:class="$style.tip") {{$t('material.sync_mode_modal.other_tip_desc')}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { sync as eventSyncName } from '@renderer/event/names'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isOverwrite: false,
|
||||||
|
globalObj: {
|
||||||
|
sync: {
|
||||||
|
isShowSyncMode: false,
|
||||||
|
deviceName: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.globalObj = window.globalObj
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSelectMode(mode) {
|
||||||
|
if (mode.startsWith('overwrite') && this.isOverwrite) mode += '_full'
|
||||||
|
window.eventHub.$emit(eventSyncName.send_sync_list, {
|
||||||
|
action: 'selectMode',
|
||||||
|
data: mode,
|
||||||
|
})
|
||||||
|
this.handleClose()
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
this.globalObj.sync.isShowSyncMode = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="less" module>
|
||||||
|
@import '../../assets/styles/layout.less';
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding: 15px;
|
||||||
|
max-width: 700px;
|
||||||
|
min-width: 200px;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: @color-theme_2-font;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: auto;
|
||||||
|
padding: 15px 0 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
.btnGroup + .btnGroup {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
color: @color-theme_2-font-label;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tipGroup {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
+ .tipGroup {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btns {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
+.btn {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
each(@themes, {
|
||||||
|
:global(#container.@{value}) {
|
||||||
|
.main {
|
||||||
|
h2 {
|
||||||
|
color: ~'@{color-@{value}-theme_2-font}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
color: ~'@{color-@{value}-theme}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import keyBind from '../utils/keyBind'
|
import keyBind from '../utils/keyBind'
|
||||||
import { rendererOn, rendererSend, NAMES, rendererInvoke } from '../../common/ipc'
|
import { rendererOn, rendererSend, NAMES, rendererInvoke } from '../../common/ipc'
|
||||||
import { base as baseName } from './names'
|
import { base as baseName, sync as syncName } from './names'
|
||||||
import { common as hotKeyNamesCommon } from '../../common/hotKey'
|
import { common as hotKeyNamesCommon } from '../../common/hotKey'
|
||||||
|
|
||||||
const eventHub = window.eventHub = new Vue()
|
const eventHub = window.eventHub = new Vue()
|
||||||
@@ -77,3 +77,18 @@ rendererOn(NAMES.mainWindow.set_hot_key_config, (event, config) => {
|
|||||||
}
|
}
|
||||||
window.eventHub.$emit(baseName.set_hot_key_config, config)
|
window.eventHub.$emit(baseName.set_hot_key_config, config)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
rendererOn(NAMES.mainWindow.sync_action_list, (event, { action, data }) => {
|
||||||
|
window.eventHub.$emit(syncName.handle_action_list, { action, data })
|
||||||
|
})
|
||||||
|
eventHub.$on(syncName.send_action_list, ({ action, data }) => {
|
||||||
|
if (!window.globalObj.sync.enable) return
|
||||||
|
rendererSend(NAMES.mainWindow.sync_action_list, { action, data })
|
||||||
|
})
|
||||||
|
rendererOn(NAMES.mainWindow.sync_list, (event, { action, data }) => {
|
||||||
|
window.eventHub.$emit(syncName.handle_sync_list, { action, data })
|
||||||
|
})
|
||||||
|
eventHub.$on(syncName.send_sync_list, ({ action, data }) => {
|
||||||
|
if (!window.globalObj.sync.enable) return
|
||||||
|
rendererSend(NAMES.mainWindow.sync_list, { action, data })
|
||||||
|
})
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ const names = {
|
|||||||
set_config: 'set_config',
|
set_config: 'set_config',
|
||||||
set_hot_key_config: 'set_hot_key_config',
|
set_hot_key_config: 'set_hot_key_config',
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
send_action_list: 'send_action_list',
|
||||||
|
handle_action_list: 'handle_action_list',
|
||||||
|
send_sync_list: 'send_sync_list',
|
||||||
|
handle_sync_list: 'handle_sync_list',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of Object.keys(names)) {
|
for (const item of Object.keys(names)) {
|
||||||
@@ -20,3 +26,4 @@ for (const item of Object.keys(names)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const base = names.base
|
export const base = names.base
|
||||||
|
export const sync = names.sync
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"merge_btn_local_remote": "Local list merge remote list",
|
||||||
|
"merge_btn_remote_local": "Remote list merge local list",
|
||||||
|
"merge_label": "Merge",
|
||||||
|
"merge_tip": "Merge:",
|
||||||
|
"merge_tip_desc": "Merge the two lists together, the same song will be removed (the song of the merged person is removed), and different songs will be added.",
|
||||||
|
"other_label": "Other",
|
||||||
|
"other_tip": "Other: ",
|
||||||
|
"other_tip_desc": "\"Only use real-time synchronization function\" will not modify the lists of both parties, only real-time synchronization operations; \"Cancel synchronization\" will directly disconnect the two parties.",
|
||||||
|
"overwrite": "Full coverage",
|
||||||
|
"overwrite_btn_cancel": "Cancel sync",
|
||||||
|
"overwrite_btn_local_remote": "Local list Overwrite remote list",
|
||||||
|
"overwrite_btn_none": "Only use real-time synchronization",
|
||||||
|
"overwrite_btn_remote_local": "Remote list Overwrite local list",
|
||||||
|
"overwrite_label": "Cover",
|
||||||
|
"overwrite_tip": "Cover: ",
|
||||||
|
"overwrite_tip_desc": "The list with the same ID of the covered person and the covered list will be deleted and replaced with the list of the covered person (lists with different list IDs will be merged together). If you check Complete coverage, all lists of the covered person will be moved. \nDivide, and then replace with a list of overriders.",
|
||||||
|
"title": "Choose how to synchronize the list with {name}"
|
||||||
|
}
|
||||||
@@ -130,6 +130,14 @@
|
|||||||
"search_focus_search_box": "Automatically focus the search box on startup",
|
"search_focus_search_box": "Automatically focus the search box on startup",
|
||||||
"search_history": "Search history",
|
"search_history": "Search history",
|
||||||
"search_hot": "Top Searches",
|
"search_hot": "Top Searches",
|
||||||
|
"sync": "Data synchronization [This is a test function, it is recommended to back up the playlist before using it for the first time]",
|
||||||
|
"sync_address": "Synchronization service address: {address}",
|
||||||
|
"sync_auth_code": "Connection code: {code}",
|
||||||
|
"sync_device": "Connected devices: {devices}",
|
||||||
|
"sync_enable": "Enable synchronization",
|
||||||
|
"sync_port": "Sync port settings",
|
||||||
|
"sync_port_tip": "Please enter the synchronization service port number",
|
||||||
|
"sync_refresh_code": "Refresh the connection code",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
"update_checking": "Checking for updates...",
|
"update_checking": "Checking for updates...",
|
||||||
"update_current_label": "Current version: ",
|
"update_current_label": "Current version: ",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"merge_btn_local_remote": "本机列表 合并 远程列表",
|
||||||
|
"merge_btn_remote_local": "远程列表 合并 本机列表",
|
||||||
|
"merge_label": "合并",
|
||||||
|
"merge_tip": "合并:",
|
||||||
|
"merge_tip_desc": "将两边的列表合并到一起,相同的歌曲将被去掉(去掉的是被合并者的歌曲),不同的歌曲将被添加。",
|
||||||
|
"other_label": "其他",
|
||||||
|
"other_tip": "其他:",
|
||||||
|
"other_tip_desc": "“仅使用实时同步功能”将不修改双方的列表,仅实时同步操作;“取消同步”将直接断开双方的连接。",
|
||||||
|
"overwrite": "完全覆盖",
|
||||||
|
"overwrite_btn_cancel": "取消同步",
|
||||||
|
"overwrite_btn_local_remote": "本机列表 覆盖 远程列表",
|
||||||
|
"overwrite_btn_none": "仅使用实时同步功能",
|
||||||
|
"overwrite_btn_remote_local": "远程列表 覆盖 本机列表",
|
||||||
|
"overwrite_label": "覆盖",
|
||||||
|
"overwrite_tip": "覆盖:",
|
||||||
|
"overwrite_tip_desc": "被覆盖者与覆盖者列表ID相同的列表将被删除后替换成覆盖者的列表(列表ID不同的列表将被合并到一起),若勾选完全覆盖,则被覆盖者的所有列表将被移除,然后替换成覆盖者的列表。",
|
||||||
|
"title": "选择与 {name} 的列表同步方式"
|
||||||
|
}
|
||||||
@@ -130,6 +130,14 @@
|
|||||||
"search_focus_search_box": "启动时自动聚焦搜索框",
|
"search_focus_search_box": "启动时自动聚焦搜索框",
|
||||||
"search_history": "显示历史搜索记录",
|
"search_history": "显示历史搜索记录",
|
||||||
"search_hot": "显示热门搜索",
|
"search_hot": "显示热门搜索",
|
||||||
|
"sync": "数据同步 [此为测试功能,首次使用前建议先备份一次歌单]",
|
||||||
|
"sync_address": "同步服务地址:{address}",
|
||||||
|
"sync_auth_code": "连接码:{code}",
|
||||||
|
"sync_device": "已连接的设备:{devices}",
|
||||||
|
"sync_enable": "启用同步功能",
|
||||||
|
"sync_port": "同步端口设置",
|
||||||
|
"sync_port_tip": "请输入同步服务端口号",
|
||||||
|
"sync_refresh_code": "刷新连接码",
|
||||||
"update": "软件更新",
|
"update": "软件更新",
|
||||||
"update_checking": "检查更新中...",
|
"update_checking": "检查更新中...",
|
||||||
"update_current_label": "当前版本:",
|
"update_current_label": "当前版本:",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"merge_btn_local_remote": "本機列表 合併 遠程列表",
|
||||||
|
"merge_btn_remote_local": "遠程列表 合併 本機列表",
|
||||||
|
"merge_label": "合併",
|
||||||
|
"merge_tip": "合併:",
|
||||||
|
"merge_tip_desc": "將兩邊的列表合併到一起,相同的歌曲將被去掉(去掉的是被合併者的歌曲),不同的歌曲將被添加。",
|
||||||
|
"other_label": "其他",
|
||||||
|
"other_tip": "其他:",
|
||||||
|
"other_tip_desc": "“僅使用實時同步功能”將不修改雙方的列表,僅實時同步操作;“取消同步”將直接斷開雙方的連接。",
|
||||||
|
"overwrite": "完全覆蓋",
|
||||||
|
"overwrite_btn_cancel": "取消同步",
|
||||||
|
"overwrite_btn_local_remote": "本機列表 覆蓋 遠程列表",
|
||||||
|
"overwrite_btn_none": "僅使用實時同步功能",
|
||||||
|
"overwrite_btn_remote_local": "遠程列表 覆蓋 本機列表",
|
||||||
|
"overwrite_label": "覆蓋",
|
||||||
|
"overwrite_tip": "覆蓋:",
|
||||||
|
"overwrite_tip_desc": "被覆蓋者與覆蓋者列表ID相同的列表將被刪除後替換成覆蓋者的列表(列表ID不同的列表將被合併到一起),若勾選完全覆蓋,則被覆蓋者的所有列表將被移除,然後替換成覆蓋者的列表。",
|
||||||
|
"title": "選擇與 {name} 的列表同步方式"
|
||||||
|
}
|
||||||
@@ -130,6 +130,14 @@
|
|||||||
"search_focus_search_box": "啟動時自動聚焦搜索框",
|
"search_focus_search_box": "啟動時自動聚焦搜索框",
|
||||||
"search_history": "顯示歷史搜索記錄",
|
"search_history": "顯示歷史搜索記錄",
|
||||||
"search_hot": "顯示熱門搜索",
|
"search_hot": "顯示熱門搜索",
|
||||||
|
"sync": "數據同步 [此為測試功能,首次使用前建議先備份一次歌單]",
|
||||||
|
"sync_address": "同步服務地址:{address}",
|
||||||
|
"sync_auth_code": "連接碼:{code}",
|
||||||
|
"sync_device": "已連接的設備:{devices}",
|
||||||
|
"sync_enable": "啟用同步功能",
|
||||||
|
"sync_port": "同步端口設置",
|
||||||
|
"sync_port_tip": "請輸入同步服務端口號",
|
||||||
|
"sync_refresh_code": "刷新連接碼",
|
||||||
"update": "軟件更新",
|
"update": "軟件更新",
|
||||||
"update_checking": "檢查更新中...",
|
"update_checking": "檢查更新中...",
|
||||||
"update_current_label": "當前版本:",
|
"update_current_label": "當前版本:",
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import musicSdk from '../../utils/music'
|
import musicSdk from '../../utils/music'
|
||||||
import { clearLyric, clearMusicUrl } from '../../utils'
|
import { clearLyric, clearMusicUrl } from '../../utils'
|
||||||
|
import { sync as eventSyncName } from '@renderer/event/names'
|
||||||
|
|
||||||
let allList = {}
|
let allList = {}
|
||||||
window.allList = allList
|
window.allList = allList
|
||||||
|
|
||||||
const allListInit = (defaultList, loveList, userList) => {
|
const allListInit = (defaultList, loveList, userList) => {
|
||||||
|
for (const id of Object.keys(allList)) {
|
||||||
|
delete allList[id]
|
||||||
|
}
|
||||||
allList[defaultList.id] = defaultList
|
allList[defaultList.id] = defaultList
|
||||||
allList[loveList.id] = loveList
|
allList[loveList.id] = loveList
|
||||||
for (const list of userList) allList[list.id] = list
|
for (const list of userList) allList[list.id] = list
|
||||||
@@ -67,8 +71,28 @@ const mutations = {
|
|||||||
if (userList != null) state.userList = userList
|
if (userList != null) state.userList = userList
|
||||||
allListInit(state.defaultList, state.loveList, state.userList)
|
allListInit(state.defaultList, state.loveList, state.userList)
|
||||||
state.isInitedList = true
|
state.isInitedList = true
|
||||||
|
|
||||||
|
// if (!isSync) {
|
||||||
|
// window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
// action: 'init_list',
|
||||||
|
// data: { defaultList, loveList, userList },
|
||||||
|
// })
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
setList(state, { id, list, name, location, source, sourceListId }) {
|
setSyncListData(state, { defaultList, loveList, userList }) {
|
||||||
|
state.defaultList.list.splice(0, state.defaultList.list.length, ...defaultList.list)
|
||||||
|
state.loveList.list.splice(0, state.loveList.list.length, ...loveList.list)
|
||||||
|
state.userList = userList
|
||||||
|
allListInit(state.defaultList, state.loveList, state.userList)
|
||||||
|
},
|
||||||
|
setList(state, { id, list, name, location, source, sourceListId, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'set_list',
|
||||||
|
data: { id, list, name, location, source, sourceListId },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const targetList = allList[id]
|
const targetList = allList[id]
|
||||||
if (targetList) {
|
if (targetList) {
|
||||||
if (name && targetList.name === name) {
|
if (name && targetList.name === name) {
|
||||||
@@ -90,11 +114,20 @@ const mutations = {
|
|||||||
state.userList.push(newList)
|
state.userList.push(newList)
|
||||||
allListUpdate(newList)
|
allListUpdate(newList)
|
||||||
},
|
},
|
||||||
listAdd(state, { id, musicInfo }) {
|
listAdd(state, { id, musicInfo, addMusicLocationType, isSync }) {
|
||||||
|
if (!addMusicLocationType) addMusicLocationType = this.state.setting.list.addMusicLocationType
|
||||||
|
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_add',
|
||||||
|
data: { id, musicInfo, addMusicLocationType },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const targetList = allList[id]
|
const targetList = allList[id]
|
||||||
if (!targetList) return
|
if (!targetList) return
|
||||||
if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return
|
if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return
|
||||||
switch (this.state.setting.list.addMusicLocationType) {
|
switch (addMusicLocationType) {
|
||||||
case 'top':
|
case 'top':
|
||||||
targetList.list.unshift(musicInfo)
|
targetList.list.unshift(musicInfo)
|
||||||
break
|
break
|
||||||
@@ -104,11 +137,18 @@ const mutations = {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
listMove(state, { fromId, musicInfo, toId }) {
|
listMove(state, { fromId, musicInfo, toId, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_move',
|
||||||
|
data: { fromId, musicInfo, toId },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const fromList = allList[fromId]
|
const fromList = allList[fromId]
|
||||||
const toList = allList[toId]
|
const toList = allList[toId]
|
||||||
if (!fromList || !toList) return
|
if (!fromList || !toList) return
|
||||||
fromList.list.splice(fromList.list.indexOf(musicInfo), 1)
|
fromList.list.splice(fromList.list.findIndex(s => s.songmid === musicInfo.songmid), 1)
|
||||||
let index = toList.list.findIndex(s => s.songmid === musicInfo.songmid)
|
let index = toList.list.findIndex(s => s.songmid === musicInfo.songmid)
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
switch (this.state.setting.list.addMusicLocationType) {
|
switch (this.state.setting.list.addMusicLocationType) {
|
||||||
@@ -122,41 +162,79 @@ const mutations = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
listAddMultiple(state, { id, list }) {
|
listAddMultiple(state, { id, list, addMusicLocationType, isSync }) {
|
||||||
|
if (!addMusicLocationType) addMusicLocationType = this.state.setting.list.addMusicLocationType
|
||||||
|
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_add_multiple',
|
||||||
|
data: { id, list, addMusicLocationType },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let targetList = allList[id]
|
let targetList = allList[id]
|
||||||
if (!targetList) return
|
if (!targetList) return
|
||||||
let newList
|
let newList
|
||||||
switch (this.state.setting.list.addMusicLocationType) {
|
const map = {}
|
||||||
|
const ids = []
|
||||||
|
switch (addMusicLocationType) {
|
||||||
case 'top':
|
case 'top':
|
||||||
newList = [...list, ...targetList.list]
|
newList = [...list, ...targetList.list]
|
||||||
|
for (let i = newList.length - 1; i > -1; i--) {
|
||||||
|
const item = newList[i]
|
||||||
|
if (map[item.songmid]) continue
|
||||||
|
ids.unshift(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
default:
|
default:
|
||||||
newList = [...targetList.list, ...list]
|
newList = [...targetList.list, ...list]
|
||||||
|
for (const item of newList) {
|
||||||
|
if (map[item.songmid]) continue
|
||||||
|
ids.push(item.songmid)
|
||||||
|
map[item.songmid] = item
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
let map = {}
|
|
||||||
let ids = []
|
|
||||||
for (const item of newList) {
|
|
||||||
if (map[item.songmid]) continue
|
|
||||||
ids.push(item.songmid)
|
|
||||||
map[item.songmid] = item
|
|
||||||
}
|
|
||||||
targetList.list.splice(0, targetList.list.length, ...ids.map(id => map[id]))
|
targetList.list.splice(0, targetList.list.length, ...ids.map(id => map[id]))
|
||||||
},
|
},
|
||||||
// { fromId, toId, list }
|
// { fromId, toId, list }
|
||||||
listMoveMultiple(state, { fromId, toId, list }) {
|
listMoveMultiple(state, { fromId, toId, list, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_move_multiple',
|
||||||
|
data: { fromId, toId, list },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// console.log(state.commit)
|
// console.log(state.commit)
|
||||||
this.commit('list/listRemoveMultiple', { id: fromId, list })
|
this.commit('list/listRemoveMultiple', { listId: fromId, ids: list.map(s => s.songmid), isSync: true })
|
||||||
this.commit('list/listAddMultiple', { id: toId, list })
|
this.commit('list/listAddMultiple', { id: toId, list, isSync: true })
|
||||||
},
|
},
|
||||||
listRemove(state, { id, index }) {
|
listRemove(state, { listId, id, isSync }) {
|
||||||
let targetList = allList[id]
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_remove',
|
||||||
|
data: { listId, id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetList = allList[listId]
|
||||||
if (!targetList) return
|
if (!targetList) return
|
||||||
|
const index = targetList.list.findIndex(item => item.songmid == id)
|
||||||
|
if (index < 0) return
|
||||||
targetList.list.splice(index, 1)
|
targetList.list.splice(index, 1)
|
||||||
},
|
},
|
||||||
listRemoveMultiple(state, { id, list }) {
|
listRemoveMultiple(state, { listId, ids: musicIds, isSync }) {
|
||||||
let targetList = allList[id]
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_remove_multiple',
|
||||||
|
data: { listId, ids: musicIds },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetList = allList[listId]
|
||||||
if (!targetList) return
|
if (!targetList) return
|
||||||
let map = {}
|
let map = {}
|
||||||
let ids = []
|
let ids = []
|
||||||
@@ -164,25 +242,50 @@ const mutations = {
|
|||||||
ids.push(item.songmid)
|
ids.push(item.songmid)
|
||||||
map[item.songmid] = item
|
map[item.songmid] = item
|
||||||
}
|
}
|
||||||
for (const item of list) {
|
for (const songmid of musicIds) {
|
||||||
if (map[item.songmid]) delete map[item.songmid]
|
if (map[songmid]) delete map[songmid]
|
||||||
}
|
}
|
||||||
let newList = []
|
let newList = []
|
||||||
for (const id of ids) if (map[id]) newList.push(map[id])
|
for (const id of ids) if (map[id]) newList.push(map[id])
|
||||||
|
|
||||||
targetList.list.splice(0, targetList.list.length, ...newList)
|
targetList.list.splice(0, targetList.list.length, ...newList)
|
||||||
},
|
},
|
||||||
listClear(state, id) {
|
listClear(state, { id, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'list_clear',
|
||||||
|
data: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let targetList = allList[id]
|
let targetList = allList[id]
|
||||||
if (!targetList) return
|
if (!targetList) return
|
||||||
targetList.list.splice(0, targetList.list.length)
|
targetList.list.splice(0, targetList.list.length)
|
||||||
},
|
},
|
||||||
updateMusicInfo(state, { id, index, data, musicInfo = {} }) {
|
updateMusicInfo(state, { listId, id, data, musicInfo, isSync }) {
|
||||||
let targetList = allList[id]
|
if (!isSync) {
|
||||||
if (!targetList) return Object.assign(musicInfo, data)
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
Object.assign(targetList.list[index], data)
|
action: 'update_music_info',
|
||||||
|
data: { listId, id, data, musicInfo },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetList = allList[listId]
|
||||||
|
if (!targetList) {
|
||||||
|
if (musicInfo) Object.assign(musicInfo, data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const targetMusicInfo = targetList.list.find(item => item.songmid == id)
|
||||||
|
if (targetMusicInfo) Object.assign(targetMusicInfo, data)
|
||||||
},
|
},
|
||||||
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [], source, sourceListId }) {
|
createUserList(state, { name, id = `userlist_${Date.now()}`, list = [], source, sourceListId, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'create_user_list',
|
||||||
|
data: { name, id, list, source, sourceListId },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let newList = state.userList.find(item => item.id === id)
|
let newList = state.userList.find(item => item.id === id)
|
||||||
if (!newList) {
|
if (!newList) {
|
||||||
newList = {
|
newList = {
|
||||||
@@ -196,35 +299,75 @@ const mutations = {
|
|||||||
state.userList.push(newList)
|
state.userList.push(newList)
|
||||||
allListUpdate(newList)
|
allListUpdate(newList)
|
||||||
}
|
}
|
||||||
this.commit('list/listAddMultiple', { id, list })
|
this.commit('list/listAddMultiple', { id, list, isSync: true })
|
||||||
},
|
},
|
||||||
removeUserList(state, index) {
|
removeUserList(state, { id, isSync }) {
|
||||||
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'remove_user_list',
|
||||||
|
data: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = state.userList.findIndex(l => l.id === id)
|
||||||
|
if (index < 0) return
|
||||||
let list = state.userList.splice(index, 1)[0]
|
let list = state.userList.splice(index, 1)[0]
|
||||||
allListRemove(list)
|
allListRemove(list)
|
||||||
},
|
},
|
||||||
setUserListName(state, { index, name }) {
|
setUserListName(state, { id, name, isSync }) {
|
||||||
let list = state.userList[index]
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'set_user_list_name',
|
||||||
|
data: { id, name },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = allList[id]
|
||||||
if (!list) return
|
if (!list) return
|
||||||
list.name = name
|
list.name = name
|
||||||
},
|
},
|
||||||
moveupUserList(state, index) {
|
moveupUserList(state, { id, isSync }) {
|
||||||
let targetList = state.userList[index]
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'moveup_user_list',
|
||||||
|
data: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = state.userList.findIndex(l => l.id == id)
|
||||||
|
if (index < 0) return
|
||||||
|
let targetList = allList[id]
|
||||||
state.userList.splice(index, 1)
|
state.userList.splice(index, 1)
|
||||||
state.userList.splice(index - 1, 0, targetList)
|
state.userList.splice(index - 1, 0, targetList)
|
||||||
},
|
},
|
||||||
movedownUserList(state, index) {
|
movedownUserList(state, { id, isSync }) {
|
||||||
let targetList = state.userList[index]
|
if (!isSync) {
|
||||||
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'movedown_user_list',
|
||||||
|
data: { id },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const index = state.userList.findIndex(l => l.id == id)
|
||||||
|
if (index < 0) return
|
||||||
|
let targetList = allList[id]
|
||||||
state.userList.splice(index, 1)
|
state.userList.splice(index, 1)
|
||||||
state.userList.splice(index + 1, 0, targetList)
|
state.userList.splice(index + 1, 0, targetList)
|
||||||
},
|
},
|
||||||
setListScroll(state, { id, location }) {
|
setListScroll(state, { id, location }) {
|
||||||
if (allList[id]) allList[id].location = location
|
if (allList[id]) allList[id].location = location
|
||||||
},
|
},
|
||||||
sortList(state, { id, sortNum, musicInfos }) {
|
setMusicPosition(state, { id, position, list, isSync }) {
|
||||||
let targetList = allList[id]
|
if (!isSync) {
|
||||||
this.commit('list/listRemoveMultiple', { id, list: musicInfos })
|
window.eventHub.$emit(eventSyncName.send_action_list, {
|
||||||
|
action: 'set_music_position',
|
||||||
|
data: { id, position, list },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
targetList.list.splice(sortNum - 1, 0, ...musicInfos)
|
let targetList = allList[id]
|
||||||
|
this.commit('list/listRemoveMultiple', { listId: id, ids: list.map(m => m.songmid), isSync: true })
|
||||||
|
|
||||||
|
targetList.list.splice(position - 1, 0, ...list)
|
||||||
},
|
},
|
||||||
clearCache() {
|
clearCache() {
|
||||||
const lists = Object.values(allList)
|
const lists = Object.values(allList)
|
||||||
|
|||||||
@@ -156,11 +156,11 @@ const getters = {
|
|||||||
|
|
||||||
if (listId != '__temp__') {
|
if (listId != '__temp__') {
|
||||||
if (isPlayList) {
|
if (isPlayList) {
|
||||||
playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo)
|
playIndex = state.listInfo.list.findIndex(m => m.songmid == state.playMusicInfo.musicInfo.songmid)
|
||||||
if (!isTempPlay) listPlayIndex = playIndex
|
if (!isTempPlay) listPlayIndex = playIndex
|
||||||
} else {
|
} else {
|
||||||
let list = window.allList[listId]
|
let list = window.allList[listId]
|
||||||
if (list) playIndex = list.list.indexOf(state.playMusicInfo.musicInfo)
|
if (list) playIndex = list.list.findIndex(m => m.songmid == state.playMusicInfo.musicInfo.songmid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log({
|
// console.log({
|
||||||
@@ -273,7 +273,8 @@ const actions = {
|
|||||||
})
|
})
|
||||||
if (!filteredList.length) return commit('setPlayMusicInfo', null)
|
if (!filteredList.length) return commit('setPlayMusicInfo', null)
|
||||||
const playInfo = getters.playInfo
|
const playInfo = getters.playInfo
|
||||||
let currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
|
const currentMusic = currentList[playInfo.listPlayIndex]
|
||||||
|
let currentIndex = filteredList.findIndex(m => m.songmid == currentMusic.songmid)
|
||||||
if (currentIndex == -1) currentIndex = 0
|
if (currentIndex == -1) currentIndex = 0
|
||||||
let nextIndex = currentIndex
|
let nextIndex = currentIndex
|
||||||
if (!playInfo.isTempPlay) {
|
if (!playInfo.isTempPlay) {
|
||||||
@@ -334,7 +335,8 @@ const actions = {
|
|||||||
|
|
||||||
if (!filteredList.length) return commit('setPlayMusicInfo', null)
|
if (!filteredList.length) return commit('setPlayMusicInfo', null)
|
||||||
const playInfo = getters.playInfo
|
const playInfo = getters.playInfo
|
||||||
const currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
|
const currentMusic = currentList[playInfo.listPlayIndex]
|
||||||
|
let currentIndex = filteredList.findIndex(m => m.songmid == currentMusic.songmid)
|
||||||
let nextIndex = currentIndex
|
let nextIndex = currentIndex
|
||||||
switch (rootState.setting.player.togglePlayMethod) {
|
switch (rootState.setting.player.togglePlayMethod) {
|
||||||
case 'listLoop':
|
case 'listLoop':
|
||||||
@@ -433,7 +435,7 @@ const mutations = {
|
|||||||
playIndex = -1
|
playIndex = -1
|
||||||
} else {
|
} else {
|
||||||
let listId = playMusicInfo.listId
|
let listId = playMusicInfo.listId
|
||||||
if (listId != '__temp__' && !playMusicInfo.isTempPlay && listId === state.listInfo.id) playIndex = state.listInfo.list.indexOf(playMusicInfo.musicInfo)
|
if (listId != '__temp__' && !playMusicInfo.isTempPlay && listId === state.listInfo.id) playIndex = state.listInfo.list.findIndex(m => m.songmid == playMusicInfo.musicInfo.songmid)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.playMusicInfo = playMusicInfo
|
state.playMusicInfo = playMusicInfo
|
||||||
|
|||||||
+12
-11
@@ -355,7 +355,7 @@ export default {
|
|||||||
'removeUserList',
|
'removeUserList',
|
||||||
'setListScroll',
|
'setListScroll',
|
||||||
'setList',
|
'setList',
|
||||||
'sortList',
|
'setMusicPosition',
|
||||||
]),
|
]),
|
||||||
...mapActions('songList', ['getListDetailAll']),
|
...mapActions('songList', ['getListDetailAll']),
|
||||||
...mapActions('leaderboard', {
|
...mapActions('leaderboard', {
|
||||||
@@ -576,7 +576,7 @@ export default {
|
|||||||
this.setPlayList({ list: this.listData, index })
|
this.setPlayList({ list: this.listData, index })
|
||||||
},
|
},
|
||||||
handleRemove(index) {
|
handleRemove(index) {
|
||||||
this.listRemove({ id: this.listId, index })
|
this.listRemove({ listId: this.listId, id: this.list[index].songmid })
|
||||||
},
|
},
|
||||||
handleListBtnClick(info) {
|
handleListBtnClick(info) {
|
||||||
switch (info.action) {
|
switch (info.action) {
|
||||||
@@ -677,8 +677,9 @@ export default {
|
|||||||
let dom_target = this.$refs.dom_lists_list.querySelector('.' + this.$style.editing)
|
let dom_target = this.$refs.dom_lists_list.querySelector('.' + this.$style.editing)
|
||||||
if (dom_target) dom_target.classList.remove(this.$style.editing)
|
if (dom_target) dom_target.classList.remove(this.$style.editing)
|
||||||
let name = event.target.value.trim()
|
let name = event.target.value.trim()
|
||||||
if (name.length) return this.setUserListName({ index, name })
|
const targetList = this.userList[index]
|
||||||
event.target.value = this.userList[index].name
|
if (name.length) return this.setUserListName({ id: targetList.id, name })
|
||||||
|
event.target.value = targetList.name
|
||||||
},
|
},
|
||||||
handleListsCreate(event) {
|
handleListsCreate(event) {
|
||||||
if (event.target.readonly) return
|
if (event.target.readonly) return
|
||||||
@@ -774,13 +775,13 @@ export default {
|
|||||||
this.handleSyncSourceList(index)
|
this.handleSyncSourceList(index)
|
||||||
break
|
break
|
||||||
case 'moveup':
|
case 'moveup':
|
||||||
this.moveupUserList(index)
|
this.moveupUserList({ id: this.userList[index].id })
|
||||||
break
|
break
|
||||||
case 'movedown':
|
case 'movedown':
|
||||||
this.movedownUserList(index)
|
this.movedownUserList({ id: this.userList[index].id })
|
||||||
break
|
break
|
||||||
case 'remove':
|
case 'remove':
|
||||||
this.removeUserList(index)
|
this.removeUserList({ id: this.userList[index].id })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -870,7 +871,7 @@ export default {
|
|||||||
break
|
break
|
||||||
case 'remove':
|
case 'remove':
|
||||||
if (this.selectdListDetailData.length) {
|
if (this.selectdListDetailData.length) {
|
||||||
this.listRemoveMultiple({ id: this.listId, list: this.selectdListDetailData })
|
this.listRemoveMultiple({ listId: this.listId, ids: this.selectdListDetailData.map(m => m.songmid) })
|
||||||
this.removeAllSelectListDetail()
|
this.removeAllSelectListDetail()
|
||||||
} else {
|
} else {
|
||||||
this.handleRemove(index)
|
this.handleRemove(index)
|
||||||
@@ -929,10 +930,10 @@ export default {
|
|||||||
},
|
},
|
||||||
handleSortMusicInfo(num) {
|
handleSortMusicInfo(num) {
|
||||||
num = Math.min(num, this.list.length)
|
num = Math.min(num, this.list.length)
|
||||||
this.sortList({
|
this.setMusicPosition({
|
||||||
id: this.listId,
|
id: this.listId,
|
||||||
sortNum: num,
|
position: num,
|
||||||
musicInfos: this.selectdListDetailData.length ? [...this.selectdListDetailData] : [this.musicInfo],
|
list: this.selectdListDetailData.length ? [...this.selectdListDetailData] : [this.musicInfo],
|
||||||
})
|
})
|
||||||
this.removeAllSelectListDetail()
|
this.removeAllSelectListDetail()
|
||||||
this.isShowListSortModal = false
|
this.isShowListSortModal = false
|
||||||
|
|||||||
@@ -150,6 +150,21 @@ div(:class="$style.main")
|
|||||||
div
|
div
|
||||||
material-checkbox(id="setting_download_isDownloadLrc" v-model="current_setting.download.isDownloadLrc" :label="$t('view.setting.is_enable')")
|
material-checkbox(id="setting_download_isDownloadLrc" v-model="current_setting.download.isDownloadLrc" :label="$t('view.setting.is_enable')")
|
||||||
|
|
||||||
|
dt#sync {{$t('view.setting.sync')}}
|
||||||
|
dd
|
||||||
|
material-checkbox(id="setting_sync_enable" v-model="current_setting.sync.enable" @change="handleSyncChange('enable')" :label="syncEnableTitle")
|
||||||
|
div
|
||||||
|
p.small {{$t('view.setting.sync_auth_code', { code: sync.status.code || '' })}}
|
||||||
|
p.small {{$t('view.setting.sync_address', { address: sync.status.address.join(', ') || '' })}}
|
||||||
|
p.small {{$t('view.setting.sync_device', { devices: syncDevices })}}
|
||||||
|
p
|
||||||
|
material-btn(:class="$style.btn" min :disabled="!current_setting.sync.enable" @click="handleRefreshSyncCode") {{$t('view.setting.sync_refresh_code')}}
|
||||||
|
dd
|
||||||
|
h3#sync_port {{$t('view.setting.sync_port')}}
|
||||||
|
div
|
||||||
|
p
|
||||||
|
material-input(:class="$style.gapLeft" v-model.trim="current_setting.sync.port" @change="handleSyncChange('port')" :placeholder="$t('view.setting.sync_port_tip')")
|
||||||
|
|
||||||
dt#hot_key {{$t('view.setting.hot_key')}}
|
dt#hot_key {{$t('view.setting.hot_key')}}
|
||||||
dd
|
dd
|
||||||
h3#hot_key_local_title {{$t('view.setting.hot_key_local_title')}}
|
h3#hot_key_local_title {{$t('view.setting.hot_key_local_title')}}
|
||||||
@@ -295,7 +310,7 @@ import {
|
|||||||
getSetting,
|
getSetting,
|
||||||
saveSetting,
|
saveSetting,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { rendererSend, rendererInvoke, NAMES } from '@common/ipc'
|
import { rendererSend, rendererInvoke, rendererOn, NAMES, rendererOff } from '@common/ipc'
|
||||||
import { mergeSetting, isMac } from '../../common/utils'
|
import { mergeSetting, isMac } from '../../common/utils'
|
||||||
import apiSourceInfo from '../utils/music/api-source-info'
|
import apiSourceInfo from '../utils/music/api-source-info'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
@@ -410,6 +425,21 @@ export default {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
syncEnableTitle() {
|
||||||
|
let title = this.$t('view.setting.sync_enable')
|
||||||
|
if (this.sync.status.message) {
|
||||||
|
title += ` [${this.sync.status.message}]`
|
||||||
|
}
|
||||||
|
// else if (this.sync.status.address.length) {
|
||||||
|
// // title += ` [${this.sync.status.address.join(', ')}]`
|
||||||
|
// }
|
||||||
|
return title
|
||||||
|
},
|
||||||
|
syncDevices() {
|
||||||
|
return this.sync.status.devices.length
|
||||||
|
? this.sync.status.devices.map(d => `${d.deviceName} (${d.clientId.substring(0, 5)})`).join(', ')
|
||||||
|
: ''
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -474,6 +504,10 @@ export default {
|
|||||||
isToTray: false,
|
isToTray: false,
|
||||||
themeId: 0,
|
themeId: 0,
|
||||||
},
|
},
|
||||||
|
sync: {
|
||||||
|
enable: false,
|
||||||
|
port: '23332',
|
||||||
|
},
|
||||||
windowSizeId: 1,
|
windowSizeId: 1,
|
||||||
langId: 'cns',
|
langId: 'cns',
|
||||||
themeId: 0,
|
themeId: 0,
|
||||||
@@ -608,6 +642,15 @@ export default {
|
|||||||
},
|
},
|
||||||
isDisabledResourceCacheClear: false,
|
isDisabledResourceCacheClear: false,
|
||||||
isDisabledListCacheClear: false,
|
isDisabledListCacheClear: false,
|
||||||
|
sync: {
|
||||||
|
status: {
|
||||||
|
status: false,
|
||||||
|
message: '',
|
||||||
|
address: [],
|
||||||
|
code: '',
|
||||||
|
devices: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -665,6 +708,7 @@ export default {
|
|||||||
window.eventHub.$off(eventBaseName.set_config, this.handleUpdateSetting)
|
window.eventHub.$off(eventBaseName.set_config, this.handleUpdateSetting)
|
||||||
window.eventHub.$off(eventBaseName.key_down, this.handleKeyDown)
|
window.eventHub.$off(eventBaseName.key_down, this.handleKeyDown)
|
||||||
window.eventHub.$off(eventBaseName.set_hot_key_config, this.handleUpdateHotKeyConfig)
|
window.eventHub.$off(eventBaseName.set_hot_key_config, this.handleUpdateHotKeyConfig)
|
||||||
|
this.syncUnInit()
|
||||||
|
|
||||||
if (this.current_setting.network.proxy.enable && !this.current_setting.network.proxy.host) window.globalObj.proxy.enable = false
|
if (this.current_setting.network.proxy.enable && !this.current_setting.network.proxy.host) window.globalObj.proxy.enable = false
|
||||||
},
|
},
|
||||||
@@ -684,6 +728,7 @@ export default {
|
|||||||
this.current_hot_key = window.appHotKeyConfig
|
this.current_hot_key = window.appHotKeyConfig
|
||||||
this.initHotKeyConfig()
|
this.initHotKeyConfig()
|
||||||
this.getHotKeyStatus()
|
this.getHotKeyStatus()
|
||||||
|
this.syncInit()
|
||||||
},
|
},
|
||||||
// initTOC() {
|
// initTOC() {
|
||||||
// const list = this.$refs.dom_setting_list.children
|
// const list = this.$refs.dom_setting_list.children
|
||||||
@@ -1151,6 +1196,42 @@ export default {
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
},
|
},
|
||||||
|
setStatus(e, status) {
|
||||||
|
this.sync.status.status = status.status
|
||||||
|
this.sync.status.message = status.message
|
||||||
|
this.sync.status.address = status.address
|
||||||
|
this.sync.status.code = status.code
|
||||||
|
this.sync.status.devices = status.devices
|
||||||
|
},
|
||||||
|
syncInit() {
|
||||||
|
rendererInvoke(NAMES.mainWindow.sync_get_status).then(status => {
|
||||||
|
this.sync.status.status = status.status
|
||||||
|
this.sync.status.message = status.message
|
||||||
|
this.sync.status.address = status.address
|
||||||
|
this.sync.status.code = status.code
|
||||||
|
this.sync.status.devices = status.devices
|
||||||
|
})
|
||||||
|
rendererOn(NAMES.mainWindow.sync_status, this.setStatus)
|
||||||
|
},
|
||||||
|
syncUnInit() {
|
||||||
|
rendererOff(NAMES.mainWindow.sync_status, this.setStatus)
|
||||||
|
},
|
||||||
|
handleSyncChange(action) {
|
||||||
|
switch (action) {
|
||||||
|
case 'port':
|
||||||
|
if (!this.current_setting.sync.enable) return
|
||||||
|
case 'enable':
|
||||||
|
rendererInvoke(NAMES.mainWindow.sync_enable, {
|
||||||
|
enable: this.current_setting.sync.enable,
|
||||||
|
port: this.current_setting.sync.port,
|
||||||
|
})
|
||||||
|
window.globalObj.sync.enable = this.current_setting.sync.enable
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleRefreshSyncCode() {
|
||||||
|
rendererInvoke(NAMES.mainWindow.sync_generate_code)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user