feat: add i18n(zh、en)

This commit is contained in:
putyy
2025-05-12 17:44:48 +08:00
parent a37bde428d
commit f0495c6858
24 changed files with 560 additions and 671 deletions

View File

@@ -17,6 +17,7 @@ type MimeInfo struct {
type Config struct {
storage *Storage
Theme string `json:"Theme"`
Locale string `json:"Locale"`
Host string `json:"Host"`
Port string `json:"Port"`
Quality int `json:"Quality"`
@@ -152,6 +153,7 @@ func (c *Config) setConfig(config Config) {
c.Host = config.Host
c.Port = config.Port
c.Theme = config.Theme
c.Locale = config.Locale
c.Quality = config.Quality
c.SaveDirectory = config.SaveDirectory
c.FilenameLen = config.FilenameLen

View File

@@ -13,7 +13,9 @@
"flv.js": "^1.6.2",
"naive-ui": "^2.38.2",
"pinia": "^2.1.7",
"video.js": "^8.22.0",
"vue": "^3.2.37",
"vue-i18n": "^11.1.3",
"vue-router": "^4.3.3"
},
"devDependencies": {
@@ -23,14 +25,12 @@
"@vitejs/plugin-vue": "^3.0.3",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"pug": "^3.0.3",
"sass": "^1.77.6",
"sass-loader": "^14.2.1",
"tailwindcss": "^3.4.4",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.18.3",
"unplugin-vue-components": "^0.27.4",
"video.js": "^8.19.1",
"vite": "^3.0.7",
"vue-tsc": "^1.8.27"
}
@@ -95,7 +95,6 @@
"version": "7.26.0",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.0.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"dev": true,
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -198,6 +197,50 @@
"vue": ">=3"
}
},
"node_modules/@intlify/core-base": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.1.3.tgz",
"integrity": "sha512-cMuHunYO7LE80azTitcvEbs1KJmtd6g7I5pxlApV3Jo547zdO3h31/0uXpqHc+Y3RKt1wo2y68RGSx77Z1klyA==",
"license": "MIT",
"dependencies": {
"@intlify/message-compiler": "11.1.3",
"@intlify/shared": "11.1.3"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/message-compiler": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.1.3.tgz",
"integrity": "sha512-7rbqqpo2f5+tIcwZTAG/Ooy9C8NDVwfDkvSeDPWUPQW+Dyzfw2o9H103N5lKBxO7wxX9dgCDjQ8Umz73uYw3hw==",
"license": "MIT",
"dependencies": {
"@intlify/shared": "11.1.3",
"source-map-js": "^1.0.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/shared": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.1.3.tgz",
"integrity": "sha512-pTFBgqa/99JRA2H1qfyqv97MKWJrYngXBA/I0elZcYxvJgcCw3mApAoPW3mJ7vx3j+Ti0FyKUFZ4hWxdjKaxvA==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -714,10 +757,9 @@
"license": "MIT"
},
"node_modules/@videojs/http-streaming": {
"version": "3.16.2",
"resolved": "https://registry.npmmirror.com/@videojs/http-streaming/-/http-streaming-3.16.2.tgz",
"integrity": "sha512-fvt4ko7FknxiT9FnjyNQt6q2px+awrkM+Orv7IB/4gldvj94u4fowGfmNHynnvNTPgPkdxHklGmFLGfclYw8HA==",
"dev": true,
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.17.0.tgz",
"integrity": "sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw==",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -739,9 +781,8 @@
},
"node_modules/@videojs/vhs-utils": {
"version": "4.1.1",
"resolved": "https://registry.npmmirror.com/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
"integrity": "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -756,7 +797,6 @@
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/@videojs/xhr/-/xhr-2.7.0.tgz",
"integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.5.5",
@@ -943,32 +983,17 @@
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.10",
"resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/aes-decrypter": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
"integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -1031,20 +1056,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmmirror.com/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"dev": true,
"license": "MIT"
},
"node_modules/assert-never": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/assert-never/-/assert-never-1.4.0.tgz",
"integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==",
"dev": true,
"license": "MIT"
},
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
@@ -1106,19 +1117,6 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-walk": {
"version": "3.0.0-canary-5",
"resolved": "https://registry.npmmirror.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz",
"integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.9.6"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -1195,37 +1193,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.3.tgz",
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"get-intrinsic": "^1.2.6"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -1257,16 +1224,6 @@
],
"license": "CC-BY-4.0"
},
"node_modules/character-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/character-parser/-/character-parser-2.2.0.tgz",
"integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-regex": "^1.0.3"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
@@ -1339,17 +1296,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/constantinople": {
"version": "4.0.1",
"resolved": "https://registry.npmmirror.com/constantinople/-/constantinople-4.0.1.tgz",
"integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.6.0",
"@babel/types": "^7.6.1"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -1481,33 +1427,10 @@
"dev": true,
"license": "MIT"
},
"node_modules/doctypes": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/doctypes/-/doctypes-1.1.0.tgz",
"integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==",
"dev": true,
"license": "MIT"
},
"node_modules/dom-walk": {
"version": "0.1.2",
"resolved": "https://registry.npmmirror.com/dom-walk/-/dom-walk-0.1.2.tgz",
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==",
"dev": true
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
@@ -1542,39 +1465,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
@@ -2147,31 +2037,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.6",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
"integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"dunder-proto": "^1.0.0",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0",
"function-bind": "^1.1.2",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz",
@@ -2210,55 +2075,12 @@
"version": "4.4.0",
"resolved": "https://registry.npmmirror.com/global/-/global-4.4.0.tgz",
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
"dev": true,
"license": "MIT",
"dependencies": {
"min-document": "^2.19.0",
"process": "^0.11.10"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
@@ -2327,17 +2149,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-expression": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/is-expression/-/is-expression-4.0.0.tgz",
"integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==",
"dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^7.1.1",
"object-assign": "^4.1.1"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2362,7 +2173,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/is-function/-/is-function-1.0.2.tgz",
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
"dev": true,
"license": "MIT"
},
"node_modules/is-glob": {
@@ -2388,32 +2198,6 @@
"node": ">=0.12.0"
}
},
"node_modules/is-promise": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-2.2.2.tgz",
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
"dev": true,
"license": "MIT"
},
"node_modules/is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
@@ -2447,13 +2231,6 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-stringify": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/js-stringify/-/js-stringify-1.0.2.tgz",
"integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==",
"dev": true,
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "9.0.1",
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz",
@@ -2461,17 +2238,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/jstransformer": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/jstransformer/-/jstransformer-1.0.0.tgz",
"integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-promise": "^2.0.0",
"promise": "^7.0.1"
}
},
"node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz",
@@ -2530,9 +2296,8 @@
},
"node_modules/m3u8-parser": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
"integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -2549,16 +2314,6 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
@@ -2608,7 +2363,6 @@
"version": "2.19.0",
"resolved": "https://registry.npmmirror.com/min-document/-/min-document-2.19.0.tgz",
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
"dev": true,
"dependencies": {
"dom-walk": "^0.1.0"
}
@@ -2667,9 +2421,8 @@
},
"node_modules/mpd-parser": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/mpd-parser/-/mpd-parser-1.3.1.tgz",
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.1.tgz",
"integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -2697,9 +2450,8 @@
},
"node_modules/mux.js": {
"version": "7.1.0",
"resolved": "https://registry.npmmirror.com/mux.js/-/mux.js-7.1.0.tgz",
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.1.0.tgz",
"integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.11.2",
@@ -2953,9 +2705,8 @@
},
"node_modules/pkcs7": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/pkcs7/-/pkcs7-1.0.4.tgz",
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.5.5"
@@ -3129,164 +2880,17 @@
"version": "0.11.10",
"resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/promise": {
"version": "7.3.1",
"resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"dev": true,
"license": "MIT",
"dependencies": {
"asap": "~2.0.3"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/pug": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/pug/-/pug-3.0.3.tgz",
"integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==",
"dev": true,
"license": "MIT",
"dependencies": {
"pug-code-gen": "^3.0.3",
"pug-filters": "^4.0.0",
"pug-lexer": "^5.0.1",
"pug-linker": "^4.0.0",
"pug-load": "^3.0.0",
"pug-parser": "^6.0.0",
"pug-runtime": "^3.0.1",
"pug-strip-comments": "^2.0.0"
}
},
"node_modules/pug-attrs": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/pug-attrs/-/pug-attrs-3.0.0.tgz",
"integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==",
"dev": true,
"license": "MIT",
"dependencies": {
"constantinople": "^4.0.1",
"js-stringify": "^1.0.2",
"pug-runtime": "^3.0.0"
}
},
"node_modules/pug-code-gen": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/pug-code-gen/-/pug-code-gen-3.0.3.tgz",
"integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==",
"dev": true,
"license": "MIT",
"dependencies": {
"constantinople": "^4.0.1",
"doctypes": "^1.1.0",
"js-stringify": "^1.0.2",
"pug-attrs": "^3.0.0",
"pug-error": "^2.1.0",
"pug-runtime": "^3.0.1",
"void-elements": "^3.1.0",
"with": "^7.0.0"
}
},
"node_modules/pug-error": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/pug-error/-/pug-error-2.1.0.tgz",
"integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==",
"dev": true,
"license": "MIT"
},
"node_modules/pug-filters": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/pug-filters/-/pug-filters-4.0.0.tgz",
"integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==",
"dev": true,
"license": "MIT",
"dependencies": {
"constantinople": "^4.0.1",
"jstransformer": "1.0.0",
"pug-error": "^2.0.0",
"pug-walk": "^2.0.0",
"resolve": "^1.15.1"
}
},
"node_modules/pug-lexer": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/pug-lexer/-/pug-lexer-5.0.1.tgz",
"integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==",
"dev": true,
"license": "MIT",
"dependencies": {
"character-parser": "^2.2.0",
"is-expression": "^4.0.0",
"pug-error": "^2.0.0"
}
},
"node_modules/pug-linker": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/pug-linker/-/pug-linker-4.0.0.tgz",
"integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==",
"dev": true,
"license": "MIT",
"dependencies": {
"pug-error": "^2.0.0",
"pug-walk": "^2.0.0"
}
},
"node_modules/pug-load": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/pug-load/-/pug-load-3.0.0.tgz",
"integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"object-assign": "^4.1.1",
"pug-walk": "^2.0.0"
}
},
"node_modules/pug-parser": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/pug-parser/-/pug-parser-6.0.0.tgz",
"integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==",
"dev": true,
"license": "MIT",
"dependencies": {
"pug-error": "^2.0.0",
"token-stream": "1.0.0"
}
},
"node_modules/pug-runtime": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/pug-runtime/-/pug-runtime-3.0.1.tgz",
"integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==",
"dev": true,
"license": "MIT"
},
"node_modules/pug-strip-comments": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz",
"integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"pug-error": "^2.0.0"
}
},
"node_modules/pug-walk": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/pug-walk/-/pug-walk-2.0.0.tgz",
"integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==",
"dev": true,
"license": "MIT"
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -3336,7 +2940,6 @@
"version": "0.14.1",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true,
"license": "MIT"
},
"node_modules/resolve": {
@@ -3822,13 +3425,6 @@
"node": ">=8.0"
}
},
"node_modules/token-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/token-stream/-/token-stream-1.0.0.tgz",
"integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==",
"dev": true,
"license": "MIT"
},
"node_modules/treemate": {
"version": "0.3.11",
"resolved": "https://registry.npmmirror.com/treemate/-/treemate-0.3.11.tgz",
@@ -4131,14 +3727,13 @@
}
},
"node_modules/video.js": {
"version": "8.21.0",
"resolved": "https://registry.npmmirror.com/video.js/-/video.js-8.21.0.tgz",
"integrity": "sha512-zcwerRb257QAuWfi8NH9yEX7vrGKFthjfcONmOQ4lxFRpDAbAi+u5LAjCjMWqhJda6zEmxkgdDpOMW3Y21QpXA==",
"dev": true,
"version": "8.22.0",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-8.22.0.tgz",
"integrity": "sha512-xge2kpjsvC0zgFJ1cqt+wTqsi21+huFswlonPFh7qiplypsb4FN/D2Rz6bWdG/S9eQaPHfWHsarmJL/7D3DHoA==",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/http-streaming": "^3.16.2",
"@videojs/http-streaming": "^3.17.0",
"@videojs/vhs-utils": "^4.1.1",
"@videojs/xhr": "2.7.0",
"aes-decrypter": "^4.0.2",
@@ -4155,7 +3750,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
"integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"global": "^4.4.0"
@@ -4172,14 +3766,12 @@
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/videojs-font/-/videojs-font-4.2.0.tgz",
"integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/videojs-vtt.js": {
"version": "0.15.5",
"resolved": "https://registry.npmmirror.com/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
"integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"global": "^4.3.1"
@@ -4235,16 +3827,6 @@
}
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/vooks": {
"version": "0.2.12",
"resolved": "https://registry.npmmirror.com/vooks/-/vooks-0.2.12.tgz",
@@ -4304,6 +3886,26 @@
}
}
},
"node_modules/vue-i18n": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.3.tgz",
"integrity": "sha512-Pcylh9z9S5+CJAqgbRZ3EKxFIBIrtY5YUppU722GIT65+Nukm0TCqiQegZnNLCZkXGthxe0cpqj0AoM51H+6Gw==",
"license": "MIT",
"dependencies": {
"@intlify/core-base": "11.1.3",
"@intlify/shared": "11.1.3",
"@vue/devtools-api": "^6.5.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-router": {
"version": "4.5.0",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.0.tgz",
@@ -4395,22 +3997,6 @@
"node": ">= 8"
}
},
"node_modules/with": {
"version": "7.0.2",
"resolved": "https://registry.npmmirror.com/with/-/with-7.0.2.tgz",
"integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.9.6",
"@babel/types": "^7.9.6",
"assert-never": "^1.2.1",
"babel-walk": "3.0.0-canary-5"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz",

View File

@@ -14,7 +14,9 @@
"flv.js": "^1.6.2",
"naive-ui": "^2.38.2",
"pinia": "^2.1.7",
"video.js": "^8.22.0",
"vue": "^3.2.37",
"vue-i18n": "^11.1.3",
"vue-router": "^4.3.3"
},
"devDependencies": {
@@ -24,14 +26,12 @@
"@vitejs/plugin-vue": "^3.0.3",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"pug": "^3.0.3",
"sass": "^1.77.6",
"sass-loader": "^14.2.1",
"tailwindcss": "^3.4.4",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.18.3",
"unplugin-vue-components": "^0.27.4",
"video.js": "^8.19.1",
"vite": "^3.0.7",
"vue-tsc": "^1.8.27"
}

View File

@@ -1 +1 @@
4b201370b63f9befd97a0e875507a444
853e4a476a4f41b58875469cfb541133

View File

@@ -1,5 +1,5 @@
<template>
<NConfigProvider class="h-full" :theme="theme" :locale="zhCN">
<NConfigProvider class="h-full" :theme="theme" :locale="uiLocale">
<NaiveProvider>
<RouterView/>
<ShowLoading :isLoading="loading"/>
@@ -12,7 +12,7 @@
<script setup lang="ts">
import NaiveProvider from '@/components/NaiveProvider.vue'
import {darkTheme, lightTheme, zhCN} from 'naive-ui'
import {darkTheme, lightTheme, zhCN, enUS} from 'naive-ui'
import {useIndexStore} from "@/stores"
import {computed, onMounted, ref} from "vue"
import {useEventStore} from "@/stores/event"
@@ -20,11 +20,13 @@ import type {appType} from "@/types/app"
import appApi from "@/api/app"
import ShowLoading from "@/components/ShowLoading.vue"
import Password from "@/components/Password.vue"
import {useI18n} from 'vue-i18n'
const store = useIndexStore()
const eventStore = useEventStore()
const loading = ref(false)
const showPassword = ref(false)
const {t, locale} = useI18n()
const theme = computed(() => {
if (store.globalConfig.Theme === "darkTheme") {
@@ -35,6 +37,14 @@ const theme = computed(() => {
return lightTheme
})
const uiLocale = computed(() => {
locale.value = store.globalConfig.Locale
if (store.globalConfig.Locale === "zh") {
return zhCN
}
return enUS
})
onMounted(async () => {
await store.init()
loading.value = true
@@ -88,7 +98,4 @@ const handlePassword = async (password: string, isCache: boolean) => {
}
})
}
</script>
<style scoped>
</style>
</script>

View File

@@ -5,20 +5,20 @@
style="--wails-draggable:no-drag"
preset="card"
class="w-[640px]"
title="关于"
:title="t('footer.title')"
>
<div class="rounded p-5">
<div class="flex flex-col">
<div class="flex flex-row">
<div>
<div class="flex flex-row items-center">
<div class="text-4xl font-bold">{{ store.appInfo.AppName }}</div>
<div class="text-4xl font-bold">{{ store.appInfo.AppName.charAt(0).toUpperCase() + store.appInfo.AppName.slice(1) }}</div>
<div class="text-xs pl-5 text-slate-400">
Version {{ store.appInfo.Version }}
</div>
</div>
<div class="text-slate-400 w-80 pt-2 pb-4">
{{ store.appInfo.Description }}
{{ t('footer.description') }}
</div>
</div>
<div class="pl-8">
@@ -28,29 +28,20 @@
</div>
<div class="flex flex-col">
<div class="text-2xl font-bold text-emerald-600">
支持市面上几乎所有的网络应用
{{ t('footer.support') }}
</div>
<div class="grid grid-cols-5 gap-2 text-sm m-4 text-slate-400">
<span>抖音</span>
<span>快手</span>
<span>小红书</span>
<span>视频号</span>
<span>小程序</span>
<span>公众号</span>
<span>酷狗音乐</span>
<span>QQ音乐</span>
<span>QQ微视</span>
<span>......</span>
<span v-for="item in t('footer.application').split(',')">{{ item }}</span>
</div>
</div>
<div class="flex w-full text-sm justify-between pt-8 text-slate-400">
<div>{{ store.appInfo.Copyright }}</div>
<div class="flex">
<button class="pl-4" @click="toWebsite('https://s.gowas.cn/d/4089')">论坛</button>
<button class="pl-4" @click="toWebsite(certUrl)">证书</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader')">软件源码</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader/issues')">帮助支持</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader/releases')">更新日志</button>
<button class="pl-4" @click="toWebsite('https://s.gowas.cn/d/4089')">{{ t('footer.forum') }}</button>
<button class="pl-4" @click="toWebsite(certUrl)">{{ t('footer.cert') }}</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader')">{{ t('footer.source_code') }}</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader/issues')">{{ t('footer.help') }}</button>
<button class="pl-4" @click="toWebsite('https://github.com/putyy/res-downloader/releases')">{{ t('footer.update_log') }}</button>
</div>
</div>
</div>
@@ -60,8 +51,10 @@
<script lang="ts" setup>
import {useIndexStore} from "@/stores"
import {BrowserOpenURL} from "../../wailsjs/runtime"
import {computed} from "vue";
import {computed} from "vue"
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const store = useIndexStore()
const props = defineProps(["showModal"])
const emits = defineEmits(["update:showModal"])

View File

@@ -5,7 +5,7 @@
style="--wails-draggable:no-drag"
preset="card"
class="w-[640px]"
title="导入数据"
:title="t('index.batch_import')"
>
<NForm
size="medium"
@@ -15,17 +15,19 @@
style="--wails-draggable:no-drag"
>
<NFormItem>
<NInput type="textarea" v-model:value="content" rows="8" :autosize="false" placeholder="添加多个时,请确保每行只有一个(每个链接回车换行)"></NInput>
<NInput type="textarea" v-model:value="content" rows="8" :autosize="false" :placeholder="t('index.import_placeholder')"></NInput>
</NFormItem>
<NFormItem>
<NButton strong secondary type="success" @click="emits('submit', content)" class="w-20">提交</NButton>
<NButton strong secondary type="success" @click="emits('submit', content)" class="w-20">{{ t('common.submit') }}</NButton>
</NFormItem>
</NForm>
</NModal>
</template>
<script setup lang="ts">
import {ref} from "vue"
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const content = ref("")
const props = defineProps<{
showModal: boolean

View File

@@ -19,7 +19,6 @@ import {
useNotification,
} from "naive-ui"
function registerNaiveTools() {
window.$loadingBar = useLoadingBar()
window.$dialog = useDialog()

View File

@@ -4,7 +4,7 @@
:on-update:show="changeShow"
style="--wails-draggable:no-drag"
preset="dialog"
title="管理员授权"
:title="t('components.password_title')"
content=""
:show-icon="false"
:mask-closable="false"
@@ -13,23 +13,23 @@
>
<div>
<div class="text-red-500 text-base">
本次输入的密码仅在本次运行期间有效用于安装证书或设置系统代理
{{ t("components.password_tip") }}
</div>
<div class="mt-3">
<n-input
v-model:value="formValue.password"
type="password"
placeholder="请输入你的电脑密码"
:placeholder="t('components.password_placeholder')"
class="w-full"
/>
</div>
<div class="mt-3 text-base">
<label>是否缓存</label>
<NSwitch class="pl-1" v-model:value="formValue.cache" aria-placeholder="是否缓存"/>
<label>{{ t("components.password_cache") }}</label>
<NSwitch class="pl-1" v-model:value="formValue.cache" :aria-placeholder="t('components.password_cache')"/>
</div>
</div>
<template #action>
<n-button type="primary" @click="submit">确认</n-button>
<n-button type="primary" @click="submit">{{ t("common.submit") }}</n-button>
</template>
</n-modal>
</template>
@@ -37,6 +37,9 @@
<script setup lang="ts">
import {reactive} from 'vue'
import {NButton, NInput, NModal} from 'naive-ui'
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
defineProps({
showModal: Boolean,
@@ -52,7 +55,7 @@ const changeShow = (value: boolean) => emits("update:showModal", value)
const submit = () => {
if (!formValue.password) {
window.$message?.error("密码不能为空")
window.$message?.error(t("components.password_empty"))
return
}
emits('submit', formValue.password, formValue.cache)

View File

@@ -5,7 +5,7 @@
:on-update:show="changeShow"
preset="card"
class="w-[540px] h-auto"
title="预览"
:title="t('index.preview')"
display-directive="show"
:on-after-enter="onAfterEnter"
:on-after-leave="onAfterLeave"
@@ -30,7 +30,9 @@ import axios from "axios"
// @ts-ignore
import { getDecryptionArray } from '@/assets/js/decrypt.js'
import type Player from "video.js/dist/types/player"
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const videoPlayer = ref<HTMLElement | any>(null)
let player: Player | null = null
let flvPlayer: flvjs.Player | null = null

View File

@@ -1,27 +1,30 @@
<template>
<NSpace style="--wails-draggable:no-drag">
<NButton v-if="row.Classify != 'live' && row.Classify != 'm3u8'" type="success" :tertiary="true" size="small" @click="action('down')">
直接下载
{{ t("index.direct_download") }}
</NButton>
<NButton type="info" :tertiary="true" size="small" @click="action('copy')">
复制链接
{{ t("index.copy_link") }}
</NButton>
<NButton v-if="row.Classify != 'live' && row.Classify != 'm3u8'" type="info" :tertiary="true" size="small" @click="action('open')">
打开浏览
{{ t("index.open_link") }}
</NButton>
<NButton v-if="row.DecodeKey" type="warning" :tertiary="true" size="small" @click="action('decode')">
视频解密
{{ t("index.video_decode") }}
</NButton>
<NButton type="info" :tertiary="true" size="small" @click="action('json')">
复制数据
{{ t("index.copy_data") }}
</NButton>
<NButton type="error" :tertiary="true" size="small" @click="action('delete')">
删除
{{ t("common.delete") }}
</NButton>
</NSpace>
</template>
<script setup lang="ts">
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const props = defineProps<{
row: any,
index: number,

View File

@@ -26,7 +26,7 @@
import {ref} from "vue"
import {Quit, WindowFullscreen, WindowMinimise, WindowUnfullscreen} from "../../wailsjs/runtime"
const isMaximized = ref(false);
const isMaximized = ref(false)
const closeWindow = () => {
Quit()

View File

@@ -1,10 +1,10 @@
<template>
<div class="flex pb-2 flex-col h-full min-w-[80px] border-r border-slate-100 dark:border-slate-900">
<Screen v-if="envInfo.platform!=='darwin'"></Screen>
<div class="w-full flex flex-row items-center justify-center pt-5 ml-[-5px]" :class="envInfo.platform==='darwin' ? 'pt-8' : 'pt-2'">
<img class="w-12 h-12 cursor-pointer" src="@/assets/image/logo.png" alt="res-downloader logo" @click="handleFooterUpdate('github')"/>
<div class="w-full flex flex-row items-center justify-center pt-5" :class="envInfo.platform==='darwin' ? 'pt-8' : 'pt-2'">
<img class="w-12 h-12 cursor-pointer" src="@/assets/image/logo.png" alt="res-downloader logo" @click="handleFooterUpdate('github')"/>
</div>
<main class="flex-1 flex-grow-1 mb-5 overflow-auto flex flex-col pt-1 items-center h-full">
<main class="flex-1 flex-grow-1 mb-5 overflow-auto flex flex-col pt-1 items-center h-full" v-if="is">
<NScrollbar :size="1">
<NLayout has-sider>
<NLayoutSider
@@ -14,10 +14,11 @@
:on-after-enter="() => { showAppName = true }"
:on-after-leave="() => { showAppName = false }"
:collapsed-width="70"
:default-collapsed="true"
:width="120"
:collapsed="collapsed"
:width="140"
:native-scrollbar="false"
:inverted="inverted"
:on-update:collapsed="collapsedChange"
class="bg-inherit"
>
<NMenu
@@ -43,32 +44,39 @@
</NScrollbar>
</main>
</div>
<Footer v-model:showModal="showAppInfo" />
<Footer v-model:showModal="showAppInfo"/>
</template>
<script lang="ts" setup>
import {MenuOption} from "naive-ui"
import {NIcon} from "naive-ui"
import {computed, h, ref, watch} from "vue"
import {computed, h, onMounted, ref, watch} from "vue"
import {useRoute, useRouter} from "vue-router"
import {
CloudOutline,
SettingsOutline,
HelpCircleOutline,
MoonOutline, SunnyOutline, LogoGithub
MoonOutline,
SunnyOutline,
LanguageSharp,
LogoGithub
} from "@vicons/ionicons5"
import {useIndexStore} from "@/stores"
import Footer from "@/components/Footer.vue"
import Screen from "@/components/Screen.vue"
import {BrowserOpenURL} from "../../../wailsjs/runtime"
import {useI18n} from "vue-i18n"
const {t} = useI18n()
const route = useRoute()
const router = useRouter()
const inverted = ref(false)
const collapsed = ref(false)
const showAppName = ref(false)
const showAppInfo = ref(false)
const menuValue = ref(route.fullPath.substring(1))
const store = useIndexStore()
const is = ref(false)
const envInfo = store.envInfo
@@ -82,7 +90,16 @@ const theme = computed(() => {
watch(() => route.path, (newPath, oldPath) => {
menuValue.value = route.fullPath.substring(1)
});
})
onMounted(()=>{
let collapsedTemp = localStorage.getItem("collapsed");
console.log("collapsedTemp:", collapsedTemp)
if (collapsedTemp) {
collapsed.value = JSON.parse(collapsedTemp).collapsed
is.value = true
}
})
const renderIcon = (icon: any) => {
return () => h(NIcon, null, {default: () => h(icon)})
@@ -90,30 +107,35 @@ const renderIcon = (icon: any) => {
const menuOptions = ref([
{
label: "拦截",
label: computed(() => t("menu.index")),
key: 'index',
icon: renderIcon(CloudOutline),
},
{
label: "设置",
label: computed(() => t("menu.setting")),
key: 'setting',
icon: renderIcon(SettingsOutline),
},
])
const footerOptions = ref([
{
label: "主题",
key: 'theme',
icon: theme,
},
{
label: "github",
key: 'github',
icon: renderIcon(LogoGithub),
},
{
label: "关于",
label: computed(() => t("menu.locale")),
key: 'locale',
icon: renderIcon(LanguageSharp),
},
{
label: computed(() => t("menu.theme")),
key: 'theme',
icon: theme,
},
{
label: computed(() => t("menu.about")),
key: 'about',
icon: renderIcon(HelpCircleOutline),
},
@@ -133,6 +155,7 @@ const handleFooterUpdate = (key: string, item?: MenuOption) => {
BrowserOpenURL("https://github.com/putyy/res-downloader")
return
}
if (key === "theme") {
if (globalConfig.value.Theme === "darkTheme") {
store.setConfig({Theme: "lightTheme"})
@@ -142,8 +165,23 @@ const handleFooterUpdate = (key: string, item?: MenuOption) => {
return
}
if (key === "locale") {
if (globalConfig.value.Locale === "zh") {
store.setConfig({Locale: "en"})
return
}
store.setConfig({Locale: "zh"})
return
}
menuValue.value = key
return router.push({path: "/" + key})
}
const collapsedChange = (value: boolean)=>{
console.log("collapsedChange",value)
collapsed.value = value
localStorage.setItem("collapsed", JSON.stringify({collapsed: value}))
}
</script>

14
frontend/src/i18n.ts Normal file
View File

@@ -0,0 +1,14 @@
import {createI18n} from 'vue-i18n'
import en from './locales/en.json'
import zh from './locales/zh.json'
const i18n = createI18n({
locale: 'zh',
fallbackLocale: 'en',
messages: {
en,
zh
}
})
export default i18n

View File

@@ -0,0 +1,109 @@
{
"common": {
"copy_success": "Copy Success",
"copy_fail": "Copy Failed",
"file_path": "File Path",
"loading": "Loading",
"select": "Select",
"submit": "Submit",
"delete": "Delete",
"yes": "Yes",
"no": "No"
},
"components": {
"password_title": "Admin Authorization",
"password_tip": "The password entered this time is only valid during this session, used for installing certificates or setting system proxy!",
"password_placeholder": "Please enter your computer password",
"password_cache": "Cache Password",
"password_empty": "Password cannot be empty"
},
"menu": {
"index": "Intercept",
"setting": "Setting",
"locale": "中文",
"theme": "Theme",
"about": "About"
},
"index": {
"open_grab": "Start Grabbing",
"close_grab": "Stop Grabbing",
"grab_type": "Grab Type",
"clear_list": "Clear List",
"batch_download": "Batch Download",
"batch_export": "Batch Export",
"batch_import": "Batch Import",
"import_success": "Export Success",
"all": "All",
"image": "Image",
"audio": "Audio",
"video": "Video",
"m3u8": "M3U8",
"live": "Live Stream",
"xls": "Spreadsheet",
"doc": "Document",
"pdf": "PDF",
"font": "Font",
"domain": "Domain",
"type": "Type",
"preview": "Preview",
"preview_tip": "Preview not supported",
"status": "Status",
"description": "Description",
"resource_size": "Resource Size",
"save_path": "Save Path",
"save_path_empty": "Please set save location",
"operation": "Operation",
"ready": "Ready",
"running": "Running",
"error": "Error",
"done": "Done",
"handle": "Post Processing",
"direct_download": "Download",
"download_success": "Download Success",
"copy_link": "Copy Link",
"copy_data": "Copy Data",
"open_link": "Open Link",
"open_file": "Open File",
"video_decode": "WxDecrypt",
"video_decode_loading": "Decrypting",
"video_decode_no": "Cannot Decrypt",
"video_decode_success": "Decrypt Success",
"use_data": "Please select required data",
"import_placeholder": "When adding multiple items, ensure each line contains only one (each link on a new line)",
"import_empty": "Please enter data to import"
},
"setting": {
"restart_tip": "Keep default if unsure, please restart software after modification",
"save_dir": "Save Directory",
"filename_rules": "Filename Rules",
"filename_rules_tip": "Input controls filename length (excluding timestamp, 0 means invalid, effective when description exists), switch controls whether to add timestamp at filename end",
"auto_proxy": "Auto Intercept",
"auto_proxy_tip": "Enable intercept when software starts",
"quality": "Quality",
"quality_value": "Default(Recommended),Ultra HD,High Quality,Medium Quality,Low Quality",
"quality_tip": "Effective for video accounts",
"full_intercept": "Full Intercept",
"full_intercept_tip": "Whether to fully intercept WeChat video accounts, No: only intercept video details",
"upstream_proxy": "Upstream Proxy",
"upstream_proxy_tip": "For combining with other proxy tools, format: http://username:password@your.proxy.server:port",
"download_proxy": "Download Proxy",
"download_proxy_tip": "Whether to use upstream proxy for downloads",
"user_agent_tip": "Keep default if unsure",
"connections": "Connections",
"connections_tip": "Keep default if unsure, usually CPU cores * 2, for faster downloads",
"use_headers_tip": "Define headers for downloads, comma separated",
"mime_map": "Intercept Rules",
"mime_map_tip": "JSON format, keep default if unsure"
},
"footer": {
"title": "About Us",
"description": "A software combining network resource sniffing + high-speed download functions, with high aesthetics, performance and diversity, providing personal users with the ability to download their own resources uploaded to various platforms!",
"support": "Supports almost all network applications on the market",
"application": "Douyin,Kuaishou,Xiaohongshu,Wechat,Mini Programs,Youtube,Kugou Music,QQ Music,QQ Weishi,......",
"forum": "Forum",
"cert": "Certificate",
"source_code": "Source Code",
"help": "Issues",
"update_log": "Update Log"
}
}

View File

@@ -0,0 +1,109 @@
{
"common": {
"copy_success": "复制成功",
"copy_fail": "复制失败",
"file_path": "文件路径",
"loading": "loading",
"select": "选择",
"submit": "提交",
"delete": "删除",
"yes": "是",
"no": "否"
},
"components": {
"password_title": "管理员授权",
"password_tip": "本次输入的密码仅在本次运行期间有效,用于安装证书或设置系统代理!",
"password_placeholder": "请输入你的电脑密码",
"password_cache": "是否缓存",
"password_empty": "密码不能为空"
},
"menu": {
"index": "获取资源",
"setting": "系统设置",
"locale": "English",
"theme": "主题更换",
"about": "关于我们"
},
"index": {
"open_grab": "开启抓取",
"close_grab": "关闭抓取",
"grab_type": "抓取类型",
"clear_list": "清空列表",
"batch_download": "批量下载",
"batch_export": "批量导出",
"batch_import": "批量导入",
"import_success": "导出成功",
"all": "全部",
"image": "图片",
"audio": "音频",
"video": "视频",
"m3u8": "m3u8",
"live": "直播流",
"xls": "表格",
"doc": "文档",
"pdf": "pdf",
"font": "字体",
"domain": "域",
"type": "类型",
"preview": "预览",
"preview_tip": "暂不支持预览",
"status": "状态",
"description": "描述",
"resource_size": "资源大小",
"save_path": "保存路径",
"save_path_empty": "请设置保存位置",
"operation": "操作",
"ready": "就绪",
"running": "运行中",
"error": "错误",
"done": "完成",
"handle": "后续处理",
"direct_download": "直接下载",
"download_success": "下载成功",
"copy_link": "复制链接",
"copy_data": "复制数据",
"open_link": "打开链接",
"open_file": "打开文件",
"video_decode": "视频解密",
"video_decode_loading": "解密中",
"video_decode_no": "无法解密",
"video_decode_success": "解密成功",
"use_data": "请选择需要的数据",
"import_placeholder": "添加多个时,请确保每行只有一个(每个链接回车换行)",
"import_empty": "请输入需要导入的数据"
},
"setting": {
"restart_tip": "如果不清楚保持默认就行,修改后请重启软件",
"save_dir": "保存目录",
"filename_rules": "文件命名",
"filename_rules_tip": "输入框控制文件命名的长度(不含时间、0为无效此选项有描述信息时有效),开关控制文件末尾是否添加时间标识",
"auto_proxy": "自动拦截",
"auto_proxy_tip": "打开软件时动启用拦截",
"quality": "清晰度",
"quality_value": "默认(推荐),超清,高画质,中画质,低画质",
"quality_tip": "视频号有效",
"full_intercept": "全量拦截",
"full_intercept_tip": "微信视频号是否全量拦截,否:只拦截视频详情",
"upstream_proxy": "上游代理",
"upstream_proxy_tip": "用于结合其他代理工具,格式: http://username:password@your.proxy.server:port",
"download_proxy": "下载代理",
"download_proxy_tip": "下载操作时是否使用上游代理",
"user_agent_tip": "如不清楚请保持默认",
"connections": "连接数",
"connections_tip": "如不清楚请保持默认通常CPU核心数*2用于加速下载",
"use_headers_tip": "定义下载时可使用的header参数逗号分割",
"mime_map": "拦截规则",
"mime_map_tip": "json格式如果不清楚保持默认就行"
},
"footer": {
"title": "关于我们",
"description": "一款集网络资源嗅探 + 高速下载功能于一体的软件,高颜值、高性能和多样化,提供个人用户下载自己上传到各大平台的网络资源功能!",
"support": "支持市面上几乎所有的网络应用",
"application": "抖音,快手,小红书,视频号,小程序,公众号,酷狗音乐,QQ音乐,QQ微视,......",
"forum": "论坛",
"cert": "证书",
"source_code": "软件源码",
"help": "帮助支持",
"update_log": "更新日志"
}
}

View File

@@ -2,13 +2,13 @@ import './assets/css/main.css'
import {createApp} from 'vue'
import {createPinia} from 'pinia'
import i18n from './i18n'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
createApp(App)
.use(router)
.use(i18n)
.use(createPinia())
.mount('#app')

View File

@@ -16,6 +16,7 @@ export const useIndexStore = defineStore("index-store", () => {
const globalConfig = ref<appType.Config>({
Theme: "lightTheme",
Locale: "zh",
Host: "0.0.0.0",
Port: "8899",
Quality: 0,

View File

@@ -13,6 +13,7 @@ export namespace appType {
interface Config {
Theme: string
Locale: string
Host: string
Port: string
Quality: number

View File

@@ -3,7 +3,6 @@ interface Window {
$dialog?: import('naive-ui').DialogProviderInst
$message?: import('naive-ui').MessageProviderInst
$notification?: import('naive-ui').NotificationProviderInst
$ws?: WebSocket
$baseUrl?: string
}

View File

@@ -1,14 +1,27 @@
<template>
<div class="flex flex-col p-5">
<div class="h-full flex flex-col p-5 overflow-y-auto [&::-webkit-scrollbar]:hidden">
<div class="pb-2 z-40">
<NSpace>
<NButton v-if="isProxy" secondary type="primary" @click.stop="close" style="--wails-draggable:no-drag">关闭代理</NButton>
<NButton v-else tertiary type="tertiary" @click.stop="open" style="--wails-draggable:no-drag">开启代理</NButton>
<NButton tertiary type="error" @click.stop="clear" style="--wails-draggable:no-drag">清空列表</NButton>
<NSelect style="min-width: 100px;--wails-draggable:no-drag" placeholder="拦截类型" v-model:value="resourcesType" multiple clearable :max-tag-count="3" :options="classify"></NSelect>
<NButton tertiary type="info" @click.stop="batchDown" style="--wails-draggable:no-drag">批量下载</NButton>
<NButton tertiary type="info" @click.stop="batchImport" style="--wails-draggable:no-drag">批量导出</NButton>
<NButton tertiary type="info" @click.stop="showImport=true" style="--wails-draggable:no-drag">批量导入</NButton>
<NButton v-if="isProxy" secondary type="primary" @click.stop="close" style="--wails-draggable:no-drag">
{{ t("index.close_grab") }}
</NButton>
<NButton v-else tertiary type="tertiary" @click.stop="open" style="--wails-draggable:no-drag">
{{ t("index.open_grab") }}
</NButton>
<NButton tertiary type="error" @click.stop="clear" style="--wails-draggable:no-drag">
{{ t("index.clear_list") }}
</NButton>
<NSelect style="min-width: 100px;--wails-draggable:no-drag" :placeholder="t('index.grab_type')"
v-model:value="resourcesType" multiple clearable :max-tag-count="3" :options="classify"></NSelect>
<NButton tertiary type="info" @click.stop="batchDown" style="--wails-draggable:no-drag">
{{ t("index.batch_download") }}
</NButton>
<NButton tertiary type="info" @click.stop="batchImport" style="--wails-draggable:no-drag">
{{ t("index.batch_export") }}
</NButton>
<NButton tertiary type="info" @click.stop="showImport=true" style="--wails-draggable:no-drag">
{{ t("index.batch_import") }}
</NButton>
</NSpace>
</div>
<div class="flex-1">
@@ -23,6 +36,7 @@
:height-for-row="()=> 48"
:checked-row-keys="checkedRowKeysValue"
@update:checked-row-keys="handleCheck"
style="--wails-draggable:no-drag"
/>
</div>
<Preview v-model:showModal="showPreviewRow" :previewRow="previewRow"/>
@@ -34,7 +48,7 @@
<script lang="ts" setup>
import {NButton, NImage, NTooltip} from "naive-ui"
import {computed, h, onMounted, ref, watch} from "vue"
import {computed, h, onMounted, ref, reactive, watch} from "vue"
import type {appType} from "@/types/app"
import type {DataTableRowKey, ImageRenderToolbarProps} from "naive-ui"
@@ -44,13 +58,14 @@ import ShowLoading from "@/components/ShowLoading.vue"
import {getDecryptionArray} from '@/assets/js/decrypt.js'
import {useIndexStore} from "@/stores"
import appApi from "@/api/app"
import {DwStatus} from "@/const"
import ResAction from "@/components/ResAction.vue"
import ImportJson from "@/components/ImportJson.vue"
import {useEventStore} from "@/stores/event"
import {BrowserOpenURL, ClipboardSetText} from "../../wailsjs/runtime"
import Password from "@/components/Password.vue"
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const eventStore = useEventStore()
const isProxy = computed(() => {
return store.isProxy
@@ -58,24 +73,36 @@ const isProxy = computed(() => {
const data = ref<any[]>([])
const store = useIndexStore()
const tableHeight = computed(() => {
return store.tableHeight - 132
return store.globalConfig.Locale === "zh" ? store.tableHeight - 130 : store.tableHeight - 151
})
const resourcesType = ref<string[]>(["all"])
const classifyAlias: { [key: string]: string } = {
image: "图片",
audio: "音频",
video: "视频",
m3u8: "m3u8",
live: "直播流",
xls: "表格",
doc: "文档",
pdf: "pdf",
font: "字体"
const classifyAlias: { [key: string]: any } = {
image: computed(() => t("index.image")),
audio: computed(() => t("index.audio")),
video: computed(() => t("index.video")),
m3u8: computed(() => t("index.m3u8")),
live: computed(() => t("index.live")),
xls: computed(() => t("index.xls")),
doc: computed(() => t("index.pdf")),
pdf: computed(() => t("index.pdf")),
font: computed(() => t("index.font"))
}
const dwStatus = computed<any>(() => {
return {
ready: t("common.ready"),
running: t("common.running"),
error: t("common.error"),
done: t("common.done"),
handle: t("common.handle")
}
})
const classify = ref([
{
value: "all",
label: "全部",
label: computed(() => t("index.all")),
},
])
@@ -84,13 +111,13 @@ const columns = ref<any[]>([
type: "selection",
},
{
title: "",
title: computed(() => t("index.domain")),
key: "Domain",
},
{
title: "类型",
title: computed(() => t("index.type")),
key: "Classify",
filterOptions: Array.from(classify.value).slice(1),
filterOptions: computed(() => Array.from(classify.value).slice(1)),
filterMultiple: true,
filter: (value: string, row: appType.MediaInfo) => {
return !!~row.Classify.indexOf(String(value))
@@ -105,7 +132,7 @@ const columns = ref<any[]>([
}
},
{
title: "预览",
title: computed(() => t("index.preview")),
key: "Url",
width: 120,
render: (row: appType.MediaInfo) => {
@@ -138,9 +165,9 @@ const columns = ref<any[]>([
{
default: () => {
if (row.Classify === "audio" || row.Classify === "video" || row.Classify === "m3u8" || row.Classify === "live") {
return "预览"
return t("index.preview")
}
return "暂不支持预览"
return t("index.preview_tip")
}
}
),
@@ -148,14 +175,14 @@ const columns = ref<any[]>([
}
},
{
title: "状态",
title: computed(() => t("index.status")),
key: "Status",
render: (row: appType.MediaInfo) => {
return DwStatus[row.Status as keyof typeof DwStatus]
return dwStatus[row.Status as keyof typeof dwStatus]
}
},
{
title: "描述",
title: computed(() => t("index.description")),
key: "Description",
width: 150,
render: (row: appType.MediaInfo, index: number) => {
@@ -172,11 +199,11 @@ const columns = ref<any[]>([
}
},
{
title: "资源大小",
title: computed(() => t("index.resource_size")),
key: "Size"
},
{
title: "保存路径",
title: computed(() => t("index.save_path")),
key: "SavePath",
render(row: appType.MediaInfo, index: number) {
return h("a",
@@ -196,7 +223,7 @@ const columns = ref<any[]>([
}
},
{
title: "操作",
title: computed(() => t("index.operation")),
key: "actions",
render(row: appType.MediaInfo, index: number) {
return h(ResAction, {key: index, row: row, index: index, onAction: dataAction})
@@ -258,7 +285,7 @@ onMounted(() => {
}
}
localStorage.setItem("resources-data", JSON.stringify(data.value))
window?.$message?.success("下载成功")
window?.$message?.success(t("index.download_success"))
break;
case "error":
loading.value = false
@@ -284,7 +311,7 @@ const buildClassify = () => {
const mimeMap = store.globalConfig.MimeMap ?? {}
const seen = new Set()
classify.value = [
{value: "all", label: "全部"},
{value: "all", label: computed(() => t("index.all"))},
...Object.values(mimeMap)
.filter(({Type}) => {
if (seen.has(Type)) return false;
@@ -306,18 +333,18 @@ const dataAction = (row: appType.MediaInfo, index: number, type: string) => {
case "copy":
ClipboardSetText(row.Url).then((is: boolean) => {
if (is) {
window?.$message?.success("复制成功")
window?.$message?.success(t("common.copy_success"))
} else {
window?.$message?.error("复制失败")
window?.$message?.error(t("common.copy_fail"))
}
})
break
case "json":
ClipboardSetText(encodeURIComponent(JSON.stringify(row))).then((is: boolean) => {
if (is) {
window?.$message?.success("复制成功")
window?.$message?.success(t("common.copy_success"))
} else {
window?.$message?.error("复制失败")
window?.$message?.error(t("common.copy_fail"))
}
})
break
@@ -362,7 +389,7 @@ const batchDown = async () => {
return
}
if (!store.globalConfig.SaveDirectory) {
window?.$message?.error("请设置保存位置")
window?.$message?.error(t("index.save_path_empty"))
return
}
for (let i = 0; i < data.value.length; i++) {
@@ -375,14 +402,14 @@ const batchDown = async () => {
const batchImport = () => {
if (checkedRowKeysValue.value.length <= 0) {
window?.$message?.error('请选择需要导出的数据')
window?.$message?.error(t("index.use_data"))
return
}
if (!store.globalConfig.SaveDirectory) {
window?.$message?.error("请设置保存目录")
window?.$message?.error(t("index.save_path_empty"))
return
}
loadingText.value = "导出中"
loadingText.value = t("common.loading")
loading.value = true
let jsonData = []
for (let i = 0; i < data.value.length; i++) {
@@ -394,8 +421,8 @@ const batchImport = () => {
window?.$message?.error(res.message)
return
}
window?.$message?.success("导出成功")
window?.$message?.info("文件路径" + res.data?.file_name, {
window?.$message?.success(t("index.import_success"))
window?.$message?.info(t("index.save_path") + "" + res.data?.file_name, {
duration: 5000
})
})
@@ -424,7 +451,7 @@ async function checkVariable() {
const download = (row: appType.MediaInfo, index: number) => {
if (!store.globalConfig.SaveDirectory) {
window?.$message?.error("请设置保存位置")
window?.$message?.error(t("index.save_path_empty"))
return
}
loadingText.value = "ready"
@@ -473,7 +500,7 @@ const clear = () => {
const decodeWxFile = (row: appType.MediaInfo, index: number) => {
if (!row.DecodeKey) {
window?.$message?.error("无法解密")
window?.$message?.error(t("index.video_decode_no"))
return
}
appApi.openFileDialog().then((res: appType.Res) => {
@@ -482,7 +509,7 @@ const decodeWxFile = (row: appType.MediaInfo, index: number) => {
return
}
if (res.data.file) {
loadingText.value = "解密中"
loadingText.value = t("index.video_decode_loading")
loading.value = true
appApi.wxFileDecode({
...row,
@@ -497,13 +524,17 @@ const decodeWxFile = (row: appType.MediaInfo, index: number) => {
data.value[index].SavePath = res.data.save_path
data.value[index].Status = "done"
localStorage.setItem("resources-data", JSON.stringify(data.value))
window?.$message?.success("解密成功")
window?.$message?.success(t("index.video_decode_success"))
})
}
})
}
const handleImport = (content: string) => {
if (!content) {
// window?.$message?.error(t("view_index.import_empty"))
return
}
content.split("\n").forEach((line, index) => {
try {
let res = JSON.parse(decodeURIComponent(line))

View File

@@ -1,5 +1,5 @@
<template>
<div class="h-full relative p-5 overflow-y-auto [&::-webkit-scrollbar]:hidden">
<div class="h-full relative p-5 overflow-y-auto [&::-webkit-scrollbar]:hidden" :key="renderKey">
<NForm
:model="formValue"
size="medium"
@@ -7,7 +7,7 @@
label-width="auto"
require-mark-placement="right-hanging"
style="--wails-draggable:no-drag"
class="w-[500px]"
class="w-[700px]"
>
<NFormItem label="Host" path="Host">
<NInput v-model:value="formValue.Host" placeholder="127.0.0.1"/>
@@ -17,7 +17,7 @@
<HelpCircleOutline/>
</NIcon>
</template>
如果不清楚请保持默认修改后请重启软件
{{ t("setting.restart_tip") }}
</NTooltip>
</NFormItem>
@@ -29,12 +29,12 @@
<HelpCircleOutline/>
</NIcon>
</template>
如果不清楚保持默认修改后请重启软件
{{ t("setting.restart_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="上游代理" path="UpstreamProxy">
<NInput v-model:value="formValue.UpstreamProxy" placeholder="例如: http://127.0.0.1:7890"/>
<NFormItem :label="t('setting.upstream_proxy')" path="UpstreamProxy">
<NInput v-model:value="formValue.UpstreamProxy" placeholder="http://127.0.0.1:7890"/>
<NSwitch v-model:value="formValue.OpenProxy" class="ml-1"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -42,17 +42,17 @@
<HelpCircleOutline/>
</NIcon>
</template>
可结合其他代理工具用于访问国外网站以及正常网络无法访问的资源
{{ t("setting.upstream_proxy_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="保存位置" path="SaveDirectory">
<NInput :value="formValue.SaveDirectory" placeholder="保存位置"/>
<NButton strong secondary type="primary" @click="selectDir" class="ml-1">选择</NButton>
<NFormItem :label="t('setting.save_dir')" path="SaveDirectory">
<NInput :value="formValue.SaveDirectory" :placeholder="t('setting.save_dir')"/>
<NButton strong secondary type="primary" @click="selectDir" class="ml-1">{{ t('common.select') }}</NButton>
</NFormItem>
<div class="grid grid-cols-2">
<NFormItem label="文件命名" path="FilenameLen">
<NFormItem :label="t('setting.filename_rules')" path="FilenameLen">
<NInputNumber v-model:value="formValue.FilenameLen" :min="0" :max="9999" placeholder="0"/>
<NSwitch v-model:value="formValue.FilenameTime" class="ml-1"></NSwitch>
<NTooltip trigger="hover">
@@ -61,11 +61,11 @@
<HelpCircleOutline/>
</NIcon>
</template>
输入框控制文件命名的长度(不含时间0为无效)开关控制文件末尾是否添加时间标识
{{ t("setting.filename_rules_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="清晰度" path="Quality">
<NFormItem :label="t('setting.quality')" path="Quality">
<NSelect v-model:value="formValue.Quality" :options="options"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -73,13 +73,13 @@
<HelpCircleOutline/>
</NIcon>
</template>
视频号有效
{{ t("setting.quality_tip") }}
</NTooltip>
</NFormItem>
</div>
<div class="grid grid-cols-2 gap-4">
<NFormItem label="自动拦截" path="AutoProxy">
<NFormItem :label="t('setting.auto_proxy')" path="AutoProxy">
<NSwitch v-model:value="formValue.AutoProxy"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -87,11 +87,11 @@
<HelpCircleOutline/>
</NIcon>
</template>
打开软件时自动启用拦截
{{ t("setting.auto_proxy_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="全量拦截" path="WxAction">
<NFormItem :label="t('setting.full_intercept')" path="WxAction">
<NSwitch v-model:value="formValue.WxAction"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -99,13 +99,13 @@
<HelpCircleOutline/>
</NIcon>
</template>
微信视频号是否全量拦截只拦截视频详情
{{ t("setting.full_intercept_tip") }}
</NTooltip>
</NFormItem>
</div>
<div class="grid grid-cols-2 gap-4">
<NFormItem label="下载代理" path="DownloadProxy">
<NFormItem :label="t('setting.download_proxy')" path="DownloadProxy">
<NSwitch v-model:value="formValue.DownloadProxy"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -113,11 +113,11 @@
<HelpCircleOutline/>
</NIcon>
</template>
进行下载时使用代理请求
{{ t("setting.download_proxy_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="连接数量" path="TaskNumber">
<NFormItem :label="t('setting.connections')" path="TaskNumber">
<NInputNumber v-model:value="formValue.TaskNumber" :min="2" :max="64"/>
<NTooltip trigger="hover">
<template #trigger>
@@ -125,10 +125,9 @@
<HelpCircleOutline/>
</NIcon>
</template>
如不清楚请保持默认通常CPU核心数*2用于分片下载
{{ t("setting.connections_tip") }}
</NTooltip>
</NFormItem>
</div>
<NFormItem label="UserAgent" path="UserAgent">
@@ -139,7 +138,7 @@
<HelpCircleOutline/>
</NIcon>
</template>
如不清楚请保持默认
{{ t("setting.user_agent_tip") }}
</NTooltip>
</NFormItem>
@@ -151,16 +150,16 @@
<HelpCircleOutline/>
</NIcon>
</template>
定义下载时可使用的header参数逗号分割
{{ t("setting.use_headers_tip") }}
</NTooltip>
</NFormItem>
<NFormItem label="拦截规则" path="MimeMap">
<NFormItem :label="t('setting.mime_map')" path="MimeMap">
<NInput
v-model:value="MimeMap"
type="textarea"
rows="11"
placeholder='{"content-type": { "Type": "分类名称","Suffix": "后缀"}}'
placeholder='{"video/mp4": { "Type": "video","Suffix": ".mp4"}}'
/>
<NTooltip trigger="hover">
<template #trigger>
@@ -168,7 +167,7 @@
<HelpCircleOutline/>
</NIcon>
</template>
拦截规则json格式不清楚请勿改动
{{ t("setting.mime_map_tip") }}
</NTooltip>
</NFormItem>
</NForm>
@@ -181,31 +180,22 @@ import {ref, watch} from "vue"
import {useIndexStore} from "@/stores"
import type {appType} from "@/types/app"
import appApi from "@/api/app"
import {computed} from "vue"
import {useI18n} from 'vue-i18n'
const {t} = useI18n()
const store = useIndexStore()
const options = [
{
value: 0,
label: "默认(推荐)"
}, {
value: 1,
label: "超清"
}, {
value: 2,
label: "高画质"
}, {
value: 3,
label: "中画质"
}, {
value: 4,
label: "低画质"
}
]
const options = computed(() =>
t("setting.quality_value")
.split(",")
.map((value, index) => ({ value: index, label: value }))
)
const formValue = ref<appType.Config>(Object.assign({}, store.globalConfig))
const MimeMap = ref(formValue.value.MimeMap ? JSON.stringify(formValue.value.MimeMap, null, 2) : "")
const renderKey = ref(999)
watch(formValue.value, () => {
store.setConfig(formValue.value)
@@ -223,6 +213,11 @@ watch(() => {
formValue.value.Theme = store.globalConfig.Theme
})
watch(() => store.globalConfig.Locale, () => {
formValue.value.Locale = store.globalConfig.Locale
renderKey.value++
})
const selectDir = () => {
appApi.openDirectoryDialog().then((res: any) => {
if (res.code === 1) {

View File

@@ -6,12 +6,7 @@ import Components from 'unplugin-vue-components/vite'
import {NaiveUiResolver} from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
// export default defineConfig({
// plugins: [vue()]
// })
export default defineConfig((env) => {
const viteEnv = loadEnv(env.mode, process.cwd())
return {
plugins: [
vue(),

View File

@@ -42,10 +42,10 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
Title: app.AppName,
Width: 1024,
Width: 1280,
MinWidth: 960,
Height: 768,
MinHeight: 640,
Height: 800,
MinHeight: 600,
Frameless: !isMac,
Menu: appMenu,
EnableDefaultContextMenu: true,