feat(install): 实现带进度条的游戏安装功能
- 添加进度条组件和相关状态管理 - 实现 Rust 后端解压过程的实时进度上报 - 增加安装路径中文字符校验 -优化日志显示支持时间戳开关- 引入 zip 解压库及异步运行时依赖 - 修复安装流程中的事件通信机制 - 调整 UI 布局适配新增进度条显示
This commit is contained in:
265
src-tauri/Cargo.lock
generated
265
src-tauri/Cargo.lock
generated
@@ -8,6 +8,17 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
@@ -79,6 +90,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|||||||
name = "app"
|
name = "app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-runtime",
|
||||||
"log",
|
"log",
|
||||||
"network-interface",
|
"network-interface",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -88,6 +100,18 @@ dependencies = [
|
|||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
"tauri-plugin-fs",
|
"tauri-plugin-fs",
|
||||||
"tauri-plugin-log",
|
"tauri-plugin-log",
|
||||||
|
"thiserror 2.0.17",
|
||||||
|
"tokio",
|
||||||
|
"zip",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arbitrary"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
dependencies = [
|
||||||
|
"derive_arbitrary",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -140,6 +164,12 @@ dependencies = [
|
|||||||
"syn 2.0.108",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-runtime"
|
||||||
|
version = "0.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47480253cb834453b5c18d7a1fa50afdc6eb330cc90f7788c79368e7d0f61ec9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.89"
|
version = "0.1.89"
|
||||||
@@ -356,6 +386,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
|
||||||
|
dependencies = [
|
||||||
|
"libbz2-rs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
@@ -430,6 +469,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
|
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -484,6 +525,16 @@ dependencies = [
|
|||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
@@ -503,6 +554,12 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -674,6 +731,12 @@ dependencies = [
|
|||||||
"syn 2.0.108",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate64"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26bf8fc351c5ed29b5c2f0cbbac1b209b74f60ecd62e675a998df72c49af5204"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
@@ -684,6 +747,17 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_arbitrary"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.108",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.20"
|
version = "0.99.20"
|
||||||
@@ -705,6 +779,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -983,6 +1058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
"libz-rs-sys",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1462,6 +1538,15 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html5ever"
|
name = "html5ever"
|
||||||
version = "0.29.1"
|
version = "0.29.1"
|
||||||
@@ -1733,6 +1818,15 @@ dependencies = [
|
|||||||
"cfb",
|
"cfb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
@@ -1800,6 +1894,16 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.82"
|
version = "0.3.82"
|
||||||
@@ -1885,6 +1989,12 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libbz2-rs-sys"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.177"
|
version = "0.2.177"
|
||||||
@@ -1901,6 +2011,26 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "liblzma"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73c36d08cad03a3fbe2c4e7bb3a9e84c57e4ee4135ed0b065cade3d98480c648"
|
||||||
|
dependencies = [
|
||||||
|
"liblzma-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "liblzma-sys"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01b9596486f6d60c3bbe644c0e1be1aa6ccc472ad630fe8927b456973d7cb736"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@@ -1911,6 +2041,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libz-rs-sys"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd"
|
||||||
|
dependencies = [
|
||||||
|
"zlib-rs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@@ -2494,6 +2633,16 @@ dependencies = [
|
|||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
@@ -2693,6 +2842,12 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppmd-rust"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d558c559f0450f16f2a27a1f017ef38468c1090c9ce63c8e51366232d53717b4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@@ -3444,6 +3599,17 @@ dependencies = [
|
|||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.9"
|
version = "0.10.9"
|
||||||
@@ -3607,6 +3773,12 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swift-rs"
|
name = "swift-rs"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@@ -5469,6 +5641,26 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize_derive"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.108",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerotrie"
|
name = "zerotrie"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -5502,6 +5694,79 @@ dependencies = [
|
|||||||
"syn 2.0.108",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "4.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"arbitrary",
|
||||||
|
"bzip2",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate64",
|
||||||
|
"flate2",
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"hmac",
|
||||||
|
"indexmap 2.12.0",
|
||||||
|
"liblzma",
|
||||||
|
"memchr",
|
||||||
|
"pbkdf2",
|
||||||
|
"ppmd-rust",
|
||||||
|
"sha1",
|
||||||
|
"time",
|
||||||
|
"zeroize",
|
||||||
|
"zopfli",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zlib-rs"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zopfli"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"crc32fast",
|
||||||
|
"log",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.16+zstd.1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "5.8.0"
|
version = "5.8.0"
|
||||||
|
|||||||
@@ -26,3 +26,7 @@ tauri-plugin-log = "2"
|
|||||||
network-interface = "2.0.3"
|
network-interface = "2.0.3"
|
||||||
tauri-plugin-fs = "2"
|
tauri-plugin-fs = "2"
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
|
thiserror = "2.0.17"
|
||||||
|
zip = "4.2.0"
|
||||||
|
async-runtime = "0.0.0"
|
||||||
|
tokio = { version = "1.48.0", features = ["time"] }
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
// 只在 Windows 编译
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
// --- 1. 导入所需模块 ---
|
||||||
|
use thiserror::Error;
|
||||||
|
use zip::ZipArchive;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use serde::Serialize;
|
||||||
|
use tauri::Emitter;
|
||||||
|
use tokio::time::{sleep, Duration};
|
||||||
|
|
||||||
|
// --- 2. (新增) 定义事件的有效负载 (Payload) ---
|
||||||
|
// 这个结构体将作为事件发送给 Svelte
|
||||||
|
#[derive(Clone, serde::Serialize)]
|
||||||
|
struct InstallProgress {
|
||||||
|
message: String,
|
||||||
|
percentage: f32, // 0.0 到 100.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 3. 错误定义 ---
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum InstallError {
|
||||||
|
#[error("IO 错误: {0}")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
|
#[error("Zip 解压错误: {0}")]
|
||||||
|
Zip(#[from] zip::result::ZipError),
|
||||||
|
|
||||||
|
#[error("找不到 data.bin 文件: {0}")]
|
||||||
|
DataFileNotFound(String),
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Serialize for InstallError {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(self.to_string().as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
// --- 5. (修改) 添加 window 参数 ---
|
||||||
|
pub async fn install_game(window: tauri::Window, target_dir: String) -> Result<String, InstallError> {
|
||||||
|
|
||||||
|
println!("Rust 后端收到命令:目标目录 {}", target_dir);
|
||||||
|
|
||||||
|
// --- 6. 核心改动:从文件系统读取 data.bin ---
|
||||||
|
|
||||||
|
// --- 6a. (新增) 发送启动事件 ---
|
||||||
|
window.emit("install_progress", InstallProgress {
|
||||||
|
message: "安装开始...".into(),
|
||||||
|
percentage: 0.0
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
// 1. 获取 app.exe 所在的目录
|
||||||
|
let exe_path = std::env::current_exe()?;
|
||||||
|
let exe_dir = exe_path.parent()
|
||||||
|
.ok_or_else(|| InstallError::Io(io::Error::new(io::ErrorKind::NotFound, "无法获取执行文件所在目录")))?;
|
||||||
|
|
||||||
|
// 2. 构造 data.bin 的路径
|
||||||
|
let data_bin_path = exe_dir.join("data.bin");
|
||||||
|
|
||||||
|
println!("正在查找数据文件: {:?}", data_bin_path);
|
||||||
|
window.emit("install_progress", InstallProgress {
|
||||||
|
message: format!("正在查找数据文件: {:?}", data_bin_path),
|
||||||
|
percentage: 1.0 // 1%
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
|
||||||
|
if !data_bin_path.exists() {
|
||||||
|
// 返回错误,Svelte 的 catch 块会捕获它
|
||||||
|
return Err(InstallError::DataFileNotFound(
|
||||||
|
format!("未在 {:?} 找到 data.bin", data_bin_path)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 从硬盘打开文件
|
||||||
|
let archive_file = File::open(&data_bin_path)?;
|
||||||
|
println!("成功打开 data.bin。");
|
||||||
|
window.emit("install_progress", InstallProgress {
|
||||||
|
message: "成功打开 data.bin。".into(),
|
||||||
|
percentage: 5.0 // 5%
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
|
||||||
|
// 4. ZipArchive 现在读取文件
|
||||||
|
let mut archive = ZipArchive::new(archive_file)?;
|
||||||
|
|
||||||
|
let total_files = archive.len() as f32;
|
||||||
|
println!("在压缩包中找到 {} 个文件。", total_files);
|
||||||
|
window.emit("install_progress", InstallProgress {
|
||||||
|
message: format!("包中找到 {} 个文件。", total_files),
|
||||||
|
percentage: 10.0 // 10%
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
|
||||||
|
// --- 7. 解压循环 (核心改动: 添加 emit) ---
|
||||||
|
let install_path = PathBuf::from(target_dir);
|
||||||
|
fs::create_dir_all(&install_path)?;
|
||||||
|
|
||||||
|
for i in 0..archive.len() {
|
||||||
|
let mut file = archive.by_index(i)?;
|
||||||
|
|
||||||
|
let outpath = match file.enclosed_name() {
|
||||||
|
Some(path) => install_path.join(path),
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- 7a. (核心) 计算百分比并发送事件 ---
|
||||||
|
let current_file_index = i as f32;
|
||||||
|
let percentage = 10.0 + (current_file_index / total_files) * 85.0; // (10% + 85% = 95%)
|
||||||
|
let message = format!("安装中 [{}/{}]: {}", i + 1, total_files as u32, file.name());
|
||||||
|
|
||||||
|
window.emit("install_progress", InstallProgress { message, percentage })
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
// --- 2. (新增) 关键修复 ---
|
||||||
|
// 释放线程 1 毫秒,给 Svelte 留出渲染时间
|
||||||
|
sleep(Duration::from_millis(1)).await;
|
||||||
|
|
||||||
|
if (&*file.name()).ends_with('/') {
|
||||||
|
fs::create_dir_all(&outpath)?;
|
||||||
|
} else {
|
||||||
|
if let Some(p) = outpath.parent() {
|
||||||
|
if !p.exists() {
|
||||||
|
fs::create_dir_all(p)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut outfile = File::create(&outpath)?;
|
||||||
|
io::copy(&mut file, &mut outfile)?;
|
||||||
|
}
|
||||||
|
} // --- 循环结束 ---
|
||||||
|
|
||||||
|
println!("Rust 后端:解压成功。");
|
||||||
|
window.emit("install_progress", InstallProgress {
|
||||||
|
message: "✅ 解压完成。".into(),
|
||||||
|
percentage: 100.0 // 100%
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
Ok(format!("成功解压 {} 个文件到指定目录!", total_files as u32))
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
mod network;
|
mod network;
|
||||||
mod gameins;
|
mod gameins;
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
@@ -15,7 +16,10 @@ pub fn run() {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![network::get_network_interfaces])
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
network::get_network_interfaces,
|
||||||
|
gameins::install_game
|
||||||
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,47 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { open } from '@tauri-apps/plugin-dialog';
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
let installPath = '未选择安装路径';
|
// --- 1. 导入 Svelte 和 Tauri API ---
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
|
||||||
|
let installPath = '';
|
||||||
let isInstalling = false;
|
let isInstalling = false;
|
||||||
let logContent = '';
|
let logContent = '';
|
||||||
let logOutputElement: HTMLPreElement;
|
let logOutputElement: HTMLPreElement;
|
||||||
|
|
||||||
|
// --- 2. 为进度条添加新变量 ---
|
||||||
|
let progressPercent = 0;
|
||||||
|
|
||||||
|
// --- 3. 定义 Rust 发送的事件结构 (可选, 但推荐) ---
|
||||||
|
interface InstallProgress {
|
||||||
|
message: string;
|
||||||
|
percentage: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. 启动事件监听器 ---
|
||||||
|
onMount(() => {
|
||||||
|
// 监听 'install_progress' 事件
|
||||||
|
const unlisten = listen<InstallProgress>('install_progress', (event) => {
|
||||||
|
// 使用 Rust 发来的消息更新日志
|
||||||
|
log(event.payload.message, false); // false = 不要添加新时间戳
|
||||||
|
// 更新进度条
|
||||||
|
progressPercent = event.payload.percentage;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 组件销毁时停止监听
|
||||||
|
return () => {
|
||||||
|
unlisten();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// 1. 打开目录选择对话框
|
// 1. 打开目录选择对话框
|
||||||
async function selectInstallDir() {
|
async function selectInstallDir() {
|
||||||
|
|
||||||
const defaultPath = 'C:\\Program Files';
|
const defaultPath = 'C:\\Program Files';
|
||||||
if (installPath !== '未选择安装路径'){
|
if (installPath !== '未选择安装路径'){
|
||||||
log("重新选择安装目录");
|
log("开始选择安装目录");
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = await open({
|
const selected = await open({
|
||||||
@@ -22,8 +52,15 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (typeof selected === 'string') {
|
if (typeof selected === 'string') {
|
||||||
installPath = selected;
|
//判断安装路径是否有中文字符
|
||||||
log('已选择安装目录:'+selected+",点击开始安装即可开始自动安装");
|
if (selected.match(/[\u4e00-\u9fa5]/)) {
|
||||||
|
alert("安装目录不能包含中文字符");
|
||||||
|
log("安装目录不能包含中文字符");
|
||||||
|
installPath = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
installPath = selected + '\\DK'; // 您的逻辑
|
||||||
|
log('已选择安装目录:'+ installPath +",点击开始安装即可开始自动安装");
|
||||||
}else if (selected === null) {
|
}else if (selected === null) {
|
||||||
log("未选择安装目录");
|
log("未选择安装目录");
|
||||||
}else{
|
}else{
|
||||||
@@ -33,45 +70,53 @@
|
|||||||
|
|
||||||
// 2. 调用 Rust 后端命令开始安装
|
// 2. 调用 Rust 后端命令开始安装
|
||||||
async function startInstallation() {
|
async function startInstallation() {
|
||||||
if (installPath === '未选择安装路径') {
|
if (installPath === '') {
|
||||||
alert('请先选择安装路径!');
|
alert('请先选择安装路径!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
isInstalling = true;
|
isInstalling = true;
|
||||||
|
// --- 5. 重置 UI ---
|
||||||
|
logContent = ''; // 清空日志
|
||||||
|
progressPercent = 0; // 重置进度条
|
||||||
|
log("安装程序启动...");
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用我们在 Rust 中定义的 `install_game` 命令
|
// 我们仍然调用 invoke,但现在它只负责启动
|
||||||
// Tauri 会自动处理前端和后端的数据传输
|
// 真正的日志将通过 'install_progress' 事件传来
|
||||||
const result: string = await invoke('install_game', {
|
const result: string = await invoke('install_game', {
|
||||||
targetDir: installPath
|
targetDir: installPath
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 仅在最后显示成功弹窗
|
||||||
alert(`安装完成!\n${result}`);
|
alert(`安装完成!\n${result}`);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('安装失败:', error);
|
console.error('安装失败:', error);
|
||||||
|
log(`❌ 安装失败: ${error}`); // 将错误也记录到日志中
|
||||||
alert(`安装失败:${error}`);
|
alert(`安装失败:${error}`);
|
||||||
} finally {
|
} finally {
|
||||||
isInstalling = false;
|
isInstalling = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Svelte 版本的日志函数
|
* Svelte 版本的日志函数
|
||||||
* 它只更新 logContent 变量,Svelte 会自动更新 DOM
|
* (修改) 添加一个选项来决定是否显示时间戳
|
||||||
*/
|
*/
|
||||||
const log = (message: string) => {
|
const log = (message: string, showTimestamp = false) => {
|
||||||
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
|
let prefix = '';
|
||||||
|
if (showTimestamp) {
|
||||||
|
const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false });
|
||||||
|
prefix = `[${timestamp}] `;
|
||||||
|
}
|
||||||
// 更新变量,而不是直接操作 DOM
|
// 更新变量,而不是直接操作 DOM
|
||||||
logContent += `[${timestamp}] ${message}\n`;
|
logContent += `${prefix}${message}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2. Svelte 响应式语句 (自动滚动)
|
* 2. Svelte 响应式语句 (自动滚动)
|
||||||
* * 这行代码 ( $: ... ) 意味着:
|
|
||||||
* "每当它依赖的变量(这里是 logContent)发生变化,
|
|
||||||
* Svelte 更新 DOM 之后,就执行这里的代码。"
|
|
||||||
*/
|
*/
|
||||||
$: if (logOutputElement && logContent) {
|
$: if (logOutputElement && logContent) {
|
||||||
// 自动滚动到底部
|
// 自动滚动到底部
|
||||||
@@ -86,24 +131,42 @@
|
|||||||
<div class="flex-1 pt-10 px-5 overflow-hidden relative ">
|
<div class="flex-1 pt-10 px-5 overflow-hidden relative ">
|
||||||
<h1 class="textarea-xl font-bold absolute">选择目标安装位置</h1>
|
<h1 class="textarea-xl font-bold absolute">选择目标安装位置</h1>
|
||||||
<div class="h-full pt-10">
|
<div class="h-full pt-10">
|
||||||
<pre
|
<pre
|
||||||
class=" overflow-y-auto h-full whitespace-pre-wrap wrap-break-word "
|
class=" overflow-y-auto h-full whitespace-pre-wrap wrap-break-word "
|
||||||
bind:this={logOutputElement}
|
bind:this={logOutputElement}
|
||||||
>
|
>
|
||||||
{logContent}
|
{logContent}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="h-32 shrink-0 p-4 border-base ">
|
<!-- --- 6. 增加底部高度以容纳进度条 --- -->
|
||||||
|
<div class="h-40 shrink-0 p-4 border-base ">
|
||||||
|
|
||||||
|
{#if isInstalling}
|
||||||
|
|
||||||
|
<div class="w-full bg-neutral-600 rounded-full h-2.5 mb-2">
|
||||||
|
<div
|
||||||
|
class="bg-blue-600 h-2.5 rounded-full transition-all duration-150"
|
||||||
|
style="width: {progressPercent}%"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center text-sm mb-2">{Math.round(progressPercent)}%</div>
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
<input class="input flex-1" bind:value={installPath} placeholder="请选择安装路径" />
|
||||||
|
|
||||||
|
<button class="btn" on:click={selectInstallDir} disabled={isInstalling}>
|
||||||
|
选择安装目录
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="flex items-center">
|
|
||||||
<input class="input flex-1" value={installPath} />
|
|
||||||
|
|
||||||
<button class="btn " on:click={selectInstallDir} disabled={isInstalling}>
|
|
||||||
选择安装目录
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="pt-4 text-center btn-primary">
|
<div class="pt-4 text-center btn-primary">
|
||||||
<button class="btn btn-block" on:click={startInstallation} disabled={isInstalling}>
|
<button class="btn btn-block" on:click={startInstallation} disabled={isInstalling}>
|
||||||
{isInstalling ? '正在安装...' : '开始安装'}
|
{isInstalling ? '正在安装...' : '开始安装'}
|
||||||
@@ -113,23 +176,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
<!-- <h1>游戏安装程序</h1>-->
|
|
||||||
|
|
||||||
<!-- <div class="path-display">-->
|
|
||||||
<!-- <p>目标安装路径: <strong>{installPath}</strong></p>-->
|
|
||||||
<!-- <button on:click={selectInstallDir} disabled={isInstalling}>-->
|
|
||||||
<!-- 选择安装目录-->
|
|
||||||
<!-- </button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <button class="btn">Default</button>-->
|
|
||||||
<!-- <button-->
|
|
||||||
<!-- on:click={startInstallation}-->
|
|
||||||
<!-- disabled={isInstalling || installPath === '未选择安装路径'}>-->
|
|
||||||
<!-- {isInstalling ? '正在安装...' : '开始安装'}-->
|
|
||||||
<!-- </button>-->
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* 您的样式 (无需更改) */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
/*滚动条整体样式*/
|
/*滚动条整体样式*/
|
||||||
width:5px;
|
width:5px;
|
||||||
@@ -144,7 +193,4 @@
|
|||||||
/*滚动条里面轨道*/
|
/*滚动条里面轨道*/
|
||||||
background:#e8ecf3;
|
background:#e8ecf3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user