feat: 完成项目基础框架搭建与发现页分页优化

1. 新增数据库连接池服务与命令模块结构
2. 配置自动命令收集与路由导航
3. 优化发现页分页加载与加载状态
4. 注释调试用代码与配置项
This commit is contained in:
sparksfly 2026-08-12 23:55:58 +08:00
parent a990ce2dfb
commit 605d025d12
16 changed files with 786 additions and 34 deletions

634
src-tauri/Cargo.lock generated
View File

@ -32,6 +32,12 @@ dependencies = [
"alloc-no-stdlib", "alloc-no-stdlib",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.6" version = "0.1.6"
@ -201,6 +207,15 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "atoi"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -287,6 +302,15 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "block-buffer"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
dependencies = [
"hybrid-array",
]
[[package]] [[package]]
name = "block2" name = "block2"
version = "0.6.2" version = "0.6.2"
@ -502,8 +526,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [ dependencies = [
"iana-time-zone", "iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen",
"windows-link 0.2.1", "windows-link 0.2.1",
] ]
@ -516,6 +542,12 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "cmov"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.7" version = "4.6.7"
@ -580,7 +612,7 @@ dependencies = [
"bitflags 2.13.1", "bitflags 2.13.1",
"core-foundation 0.10.1", "core-foundation 0.10.1",
"core-graphics-types", "core-graphics-types",
"foreign-types", "foreign-types 0.5.0",
"libc", "libc",
] ]
@ -613,6 +645,21 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "crc"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853"
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.5.0" version = "1.5.0"
@ -631,6 +678,34 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "crossbeam-deque"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.22" version = "0.8.22"
@ -647,6 +722,15 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "crypto-common"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"hybrid-array",
]
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.36.0" version = "0.36.0"
@ -686,6 +770,15 @@ version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1"
[[package]]
name = "ctutils"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
dependencies = [
"cmov",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.23.0" version = "0.23.0"
@ -798,8 +891,19 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [ dependencies = [
"block-buffer", "block-buffer 0.10.4",
"crypto-common", "crypto-common 0.1.7",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer 0.12.1",
"crypto-common 0.2.2",
"ctutils",
] ]
[[package]] [[package]]
@ -884,6 +988,12 @@ dependencies = [
"tendril", "tendril",
] ]
[[package]]
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]] [[package]]
name = "dpi" name = "dpi"
version = "0.1.2" version = "0.1.2"
@ -935,6 +1045,15 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "either"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "embed-resource" name = "embed-resource"
version = "3.0.11" version = "3.0.11"
@ -1018,6 +1137,16 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "etcetera"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96"
dependencies = [
"cfg-if",
"windows-sys 0.61.2",
]
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "5.4.2" version = "5.4.2"
@ -1079,6 +1208,17 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "flume"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be"
dependencies = [
"futures-core",
"futures-sink",
"spin",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -1091,6 +1231,15 @@ 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 = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]] [[package]]
name = "foreign-types" name = "foreign-types"
version = "0.5.0" version = "0.5.0"
@ -1098,7 +1247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [ dependencies = [
"foreign-types-macros", "foreign-types-macros",
"foreign-types-shared", "foreign-types-shared 0.3.1",
] ]
[[package]] [[package]]
@ -1112,6 +1261,12 @@ dependencies = [
"syn 3.0.3", "syn 3.0.3",
] ]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]] [[package]]
name = "foreign-types-shared" name = "foreign-types-shared"
version = "0.3.1" version = "0.3.1"
@ -1140,6 +1295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@ -1159,6 +1315,17 @@ dependencies = [
"futures-util", "futures-util",
] ]
[[package]]
name = "futures-intrusive"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
dependencies = [
"futures-core",
"lock_api",
"parking_lot",
]
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.33" version = "0.3.33"
@ -1538,12 +1705,32 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.17.1" version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "hashlink"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f"
dependencies = [
"hashbrown 0.16.1",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -1568,6 +1755,24 @@ 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 = "hkdf"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
dependencies = [
"digest 0.11.3",
]
[[package]] [[package]]
name = "html5ever" name = "html5ever"
version = "0.38.0" version = "0.38.0"
@ -1617,6 +1822,15 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "hybrid-array"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
dependencies = [
"typenum",
]
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.11.0" version = "1.11.0"
@ -2146,6 +2360,17 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "libsqlite3-sys"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.12.1" version = "0.12.1"
@ -2190,6 +2415,16 @@ dependencies = [
"web_atoms", "web_atoms",
] ]
[[package]]
name = "md-5"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
dependencies = [
"cfg-if",
"digest 0.11.3",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.8.3" version = "2.8.3"
@ -2253,6 +2488,23 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "native-tls"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]] [[package]]
name = "ndk" name = "ndk"
version = "0.9.0" version = "0.9.0"
@ -2532,12 +2784,49 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "openssl"
version = "0.10.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
dependencies = [
"bitflags 2.13.1",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "openssl-sys"
version = "0.9.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "option-ext" name = "option-ext"
version = "0.2.0" version = "0.2.0"
@ -2960,6 +3249,26 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rayon"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.18" version = "0.5.18"
@ -3481,6 +3790,17 @@ dependencies = [
"stable_deref_trait", "stable_deref_trait",
] ]
[[package]]
name = "sha1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
]
[[package]] [[package]]
name = "sha2" name = "sha2"
version = "0.10.9" version = "0.10.9"
@ -3489,7 +3809,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures 0.2.17", "cpufeatures 0.2.17",
"digest", "digest 0.10.7",
]
[[package]]
name = "sha2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
] ]
[[package]] [[package]]
@ -3547,6 +3878,9 @@ name = "smallvec"
version = "1.15.2" version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
@ -3606,6 +3940,191 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "spin"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
dependencies = [
"lock_api",
]
[[package]]
name = "sqlx"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "378620ccc25c62c89d8be1c819e76a88d59bdcc3304733330788948e619bfd71"
dependencies = [
"sqlx-core",
"sqlx-macros",
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
]
[[package]]
name = "sqlx-core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb"
dependencies = [
"base64 0.22.1",
"bytes",
"cfg-if",
"chrono",
"crc",
"crossbeam-queue",
"either",
"event-listener",
"futures-core",
"futures-intrusive",
"futures-io",
"futures-util",
"hashbrown 0.16.1",
"hashlink",
"indexmap 2.14.0",
"log",
"memchr",
"native-tls",
"percent-encoding",
"serde",
"serde_json",
"sha2 0.10.9",
"smallvec",
"thiserror 2.0.20",
"tokio",
"tokio-stream",
"tracing",
"url",
]
[[package]]
name = "sqlx-macros"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd2b84f2bc39a5705ef27ec785a11c934a41bbd4a24941e257927cddc26b60bf"
dependencies = [
"proc-macro2",
"quote",
"sqlx-core",
"sqlx-macros-core",
"syn 2.0.119",
]
[[package]]
name = "sqlx-macros-core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb8d96de5fdc85a5c4ec813432b523ec637e80ba98f046555f75f7908ddac7c3"
dependencies = [
"cfg-if",
"dotenvy",
"either",
"heck 0.5.0",
"hex",
"proc-macro2",
"quote",
"serde",
"serde_json",
"sha2 0.10.9",
"sqlx-core",
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"syn 2.0.119",
"thiserror 2.0.20",
"tokio",
"url",
]
[[package]]
name = "sqlx-mysql"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27"
dependencies = [
"bitflags 2.13.1",
"byteorder",
"bytes",
"chrono",
"crc",
"digest 0.11.3",
"dotenvy",
"either",
"futures-core",
"futures-util",
"generic-array",
"log",
"percent-encoding",
"serde",
"sha1",
"sha2 0.11.0",
"sqlx-core",
"thiserror 2.0.20",
"tracing",
]
[[package]]
name = "sqlx-postgres"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e"
dependencies = [
"atoi",
"base64 0.22.1",
"bitflags 2.13.1",
"byteorder",
"chrono",
"crc",
"dotenvy",
"etcetera",
"futures-channel",
"futures-core",
"futures-util",
"hex",
"hkdf",
"hmac",
"itoa",
"log",
"md-5",
"memchr",
"rand",
"serde",
"serde_json",
"sha2 0.11.0",
"smallvec",
"sqlx-core",
"stringprep",
"thiserror 2.0.20",
"tracing",
"whoami",
]
[[package]]
name = "sqlx-sqlite"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c"
dependencies = [
"atoi",
"chrono",
"flume",
"form_urlencoded",
"futures-channel",
"futures-core",
"futures-executor",
"futures-intrusive",
"futures-util",
"libsqlite3-sys",
"log",
"percent-encoding",
"serde",
"sqlx-core",
"thiserror 2.0.20",
"tracing",
"url",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.1" version = "1.2.1"
@ -3636,6 +4155,17 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "stringprep"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
dependencies = [
"unicode-bidi",
"unicode-normalization",
"unicode-properties",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@ -3891,7 +4421,7 @@ dependencies = [
"semver", "semver",
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2 0.10.9",
"syn 2.0.119", "syn 2.0.119",
"tauri-utils", "tauri-utils",
"thiserror 2.0.20", "thiserror 2.0.20",
@ -3901,6 +4431,21 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "tauri-helper"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b6ed54c4a04e658f8f1c57513abbeb5e2493c9db1d31987c9cc6db6c19a245c"
dependencies = [
"rayon",
"serde",
"syn 2.0.119",
"tauri_helper_core",
"tauri_helper_macros",
"toml 0.9.12+spec-1.1.0",
"walkdir",
]
[[package]] [[package]]
name = "tauri-macros" name = "tauri-macros"
version = "2.6.3" version = "2.6.3"
@ -4069,6 +4614,33 @@ dependencies = [
"toml 1.1.4+spec-1.1.0", "toml 1.1.4+spec-1.1.0",
] ]
[[package]]
name = "tauri_helper_core"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6da0ac433082491b94f3ba7f5087ee888608917bd371bb213ac16bc722547541"
dependencies = [
"serde",
"toml 0.9.12+spec-1.1.0",
]
[[package]]
name = "tauri_helper_macros"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d6da533f4bd8a64d991a8ebca6abc2243d12eae7190c69ccdfa3483f82080b9"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"serde",
"syn 2.0.119",
"tauri_helper_core",
"thiserror 2.0.20",
"toml 0.9.12+spec-1.1.0",
"walkdir",
]
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.27.0" version = "3.27.0"
@ -4224,6 +4796,17 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-stream"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.19" version = "0.7.19"
@ -4409,6 +4992,7 @@ version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [ dependencies = [
"log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
@ -4526,12 +5110,33 @@ dependencies = [
"unic-common", "unic-common",
] ]
[[package]]
name = "unicode-bidi"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.24" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-normalization"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-properties"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.13.3" version = "1.13.3"
@ -4587,6 +5192,12 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]] [[package]]
name = "version-compare" name = "version-compare"
version = "0.2.1" version = "0.2.1"
@ -4842,6 +5453,12 @@ dependencies = [
"windows-core 0.61.2", "windows-core 0.61.2",
] ]
[[package]]
name = "whoami"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -5289,7 +5906,7 @@ dependencies = [
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"raw-window-handle", "raw-window-handle",
"sha2", "sha2 0.10.9",
"soup3", "soup3",
"tao-macros", "tao-macros",
"thiserror 2.0.20", "thiserror 2.0.20",
@ -5351,11 +5968,14 @@ dependencies = [
name = "ywymusic" name = "ywymusic"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono",
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"sqlx",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tauri-helper",
"tauri-plugin-opener", "tauri-plugin-opener",
"tauri-plugin-store", "tauri-plugin-store",
"tokio", "tokio",

View File

@ -14,8 +14,12 @@ edition = "2021"
name = "ywymusic_lib" name = "ywymusic_lib"
crate-type = ["staticlib", "cdylib", "rlib"] crate-type = ["staticlib", "cdylib", "rlib"]
[workspace]
members = ["."]
[build-dependencies] [build-dependencies]
tauri-build = { version = "2", features = [] } tauri-build = { version = "2", features = [] }
tauri-helper = "0.2.1"
[dependencies] [dependencies]
tauri = { version = "2", features = [] } tauri = { version = "2", features = [] }
@ -25,3 +29,11 @@ serde_json = "1"
reqwest = { version = "0.13.4", features = ["json"] } reqwest = { version = "0.13.4", features = ["json"] }
tokio = { version = "1.53.1", features = ["full"] } tokio = { version = "1.53.1", features = ["full"] }
tauri-plugin-store = "2" tauri-plugin-store = "2"
tauri-helper = "0.2.1"
sqlx = { version = "0.9.0", features = [
"runtime-tokio",
"sqlite",
"tls-native-tls",
"chrono",
] }
chrono = "0.4.45"

View File

@ -1,3 +1,4 @@
fn main() { fn main() {
tauri_helper::generate_command_file(tauri_helper::TauriHelperOptions::default());
tauri_build::build() tauri_build::build()
} }

View File

View File

@ -0,0 +1,3 @@
pub mod playlist;
pub mod music;
pub mod album;

View File

View File

@ -0,0 +1,8 @@
use reqwest;
use tauri_helper::auto_collect_command;
#[tauri::command]
#[auto_collect_command]
pub async fn playlist_recommand() -> Result<String, String> {
Ok("playlist_recommand".to_string())
}

View File

@ -1,15 +1,26 @@
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ mod commands;
#[tauri::command] mod services;
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name) use commands::album::*;
} use commands::music::*;
use commands::playlist::*;
use services::db::init_pool;
use tauri::Manager;
#[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()
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.setup(|app| {
let pool = tauri::async_runtime::block_on(async {
init_pool().await.expect("sqlite数据库连接池初始化失败!")
});
app.manage(pool);
Ok(())
})
.plugin(tauri_plugin_store::Builder::default().build()) .plugin(tauri_plugin_store::Builder::default().build())
.invoke_handler(tauri::generate_handler![greet]) // .invoke_handler(tauri::generate_handler![greet])
.invoke_handler(tauri_helper::tauri_collect_commands!())
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");
} }

View File

@ -0,0 +1,10 @@
use sqlx::pool::PoolOptions;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions};
pub async fn init_pool() -> Result<SqlitePool, sqlx::Error> {
SqlitePoolOptions::new()
.max_connections(5)
.min_connections(1)
.connect("sqlite::memory:")
.await
}

View File

@ -0,0 +1 @@
pub mod db;

View File

@ -63,6 +63,7 @@ const navItems = [
{ path: "/library", label: "我的音乐", icon: "music" }, { path: "/library", label: "我的音乐", icon: "music" },
{ path: "/search", label: "搜索", icon: "search" }, { path: "/search", label: "搜索", icon: "search" },
{ path: "/settings", label: "设置", icon: "settings" }, { path: "/settings", label: "设置", icon: "settings" },
{ path: "/demo", label: "演示", icon: "play" },
] as const; ] as const;
function isActive(path: string) { function isActive(path: string) {

View File

@ -6,6 +6,7 @@ import PlaylistDetailView from "@/views/PlaylistDetailView.vue";
import RankingView from "@/views/RankingView.vue"; import RankingView from "@/views/RankingView.vue";
import SearchView from "@/views/SearchView.vue"; import SearchView from "@/views/SearchView.vue";
import SettingsView from "@/views/SettingsView.vue"; import SettingsView from "@/views/SettingsView.vue";
import PlayMusic from "@/views/PlayMusic.vue";
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
@ -25,6 +26,7 @@ const router = createRouter({
}, },
{ path: "search", name: "search", component: SearchView }, { path: "search", name: "search", component: SearchView },
{ path: "settings", name: "settings", component: SettingsView }, { path: "settings", name: "settings", component: SettingsView },
{ path: "demo", name: "demo", component: PlayMusic },
], ],
}, },
], ],

View File

@ -20,9 +20,19 @@
<n-radio-button v-for="category in categories" :key="category.id" :value="category.id" :label="category.name" /> <n-radio-button v-for="category in categories" :key="category.id" :value="category.id" :label="category.name" />
</n-radio-group> </n-radio-group>
</n-scrollbar> </n-scrollbar>
<div class="card-grid"> <n-spin :show="loading" class="card-spin">
<MusicCard v-for="playlist in recommendedPlaylists" :key="playlist.id" :playlist="playlist" /> <div class="card-grid">
</div> <MusicCard v-for="playlist in recommendedPlaylists" :key="playlist.id" :playlist="playlist" />
</div>
</n-spin>
<n-pagination
v-if="itemCount > pageSize"
v-model:page="page"
:page-size="pageSize"
:item-count="itemCount"
class="pagination"
@update:page="onPageChange"
/>
</section> </section>
<section class="section"> <section class="section">
@ -95,7 +105,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { NCarousel, useMessage } from "naive-ui" import { NCarousel, NPagination, NSpin, useMessage } from "naive-ui"
import { useRouter } from "vue-router" import { useRouter } from "vue-router"
import AppIcon from "@/components/AppIcon.vue" import AppIcon from "@/components/AppIcon.vue"
import MusicCard from "@/components/MusicCard.vue" import MusicCard from "@/components/MusicCard.vue"
@ -114,6 +124,13 @@ const router = useRouter()
const categories = ref<PlayListCategory[]>([]) const categories = ref<PlayListCategory[]>([])
const activeCategory = ref<string>("") const activeCategory = ref<string>("")
const recommendedPlaylists = ref<Playlist[]>([]) const recommendedPlaylists = ref<Playlist[]>([])
const page = ref(1)
const pageSize = 30
const itemCount = ref(pageSize)
const loading = ref(false)
/** 防止快速翻页时旧响应覆盖新响应 */
let loadSeq = 0
const banners = [ const banners = [
{ {
@ -144,24 +161,67 @@ const list = async () => {
categories.value = res[0].categories categories.value = res[0].categories
if (categories.value.length > 0) { if (categories.value.length > 0) {
activeCategory.value = categories.value[1].id activeCategory.value = categories.value[1].id
await playList(activeCategory.value) playList(activeCategory.value)
} }
} }
const playList = async (categoryId: string) => { async function loadCategoryPlayList(categoryId: string, p: number) {
const res = await PlayListApi.categoryPlayList(categoryId, settingsState.defaultSource, 1, 30) const seq = ++loadSeq
recommendedPlaylists.value = res.playlists.map((p) => { loading.value = true
cachePlayListSummary(p) try {
return { const res = await PlayListApi.categoryPlayList(categoryId, settingsState.defaultSource, p, pageSize)
id: p.id, if (seq !== loadSeq) return
name: p.name, const items = res.playlists
desc: p.description, recommendedPlaylists.value = items.map((item) => {
cover: proxyCover(p.cover), cachePlayListSummary(item)
tags: [], return {
playCount: formatPlayCount(p.play_count), id: item.id,
songs: [], name: item.name,
desc: item.description,
cover: proxyCover(item.cover),
tags: [],
playCount: formatPlayCount(item.play_count),
songs: [],
}
})
const n = items.length
if (n === pageSize) {
//
itemCount.value = Math.max(itemCount.value, p * pageSize + pageSize)
} else if (n > 0) {
//
itemCount.value = Math.max(itemCount.value, (p - 1) * pageSize + n)
} else {
//
const last = Math.max(1, p - 1)
itemCount.value = Math.max(pageSize, last * pageSize)
if (page.value !== last) {
page.value = last
await loadCategoryPlayList(categoryId, last)
}
} }
}) } catch {
if (seq !== loadSeq) return
// 500
const last = Math.max(1, p - 1)
itemCount.value = Math.max(pageSize, last * pageSize)
if (page.value !== last) {
page.value = last
await loadCategoryPlayList(categoryId, last)
}
} finally {
if (seq === loadSeq) loading.value = false
}
}
function playList(categoryId: string) {
page.value = 1
itemCount.value = pageSize
loadCategoryPlayList(categoryId, 1)
}
function onPageChange(p: number) {
loadCategoryPlayList(activeCategory.value, p)
} }
onMounted(() => { onMounted(() => {
@ -239,6 +299,10 @@ onMounted(() => {
padding-bottom: 8px; padding-bottom: 8px;
} }
.card-spin {
min-height: 120px;
}
.card-grid { .card-grid {
display: grid; display: grid;
margin-top: 20px; margin-top: 20px;
@ -246,6 +310,12 @@ onMounted(() => {
gap: 20px 18px; gap: 20px 18px;
} }
.pagination {
display: flex;
justify-content: center;
margin-top: 24px;
}
.new-song-row { .new-song-row {
display: grid; display: grid;
grid-auto-flow: column; grid-auto-flow: column;

13
src/views/PlayMusic.vue Normal file
View File

@ -0,0 +1,13 @@
<template>
<div>
<audio :src="url" controls autoplay />
</div>
</template>
<script setup lang="ts">
const url = ref("http://localhost:81/api?server=kugou&type=url&id=A2893B3ED8A63DD3BE73ABA509F8116A&auth=ac5193c14df7d136fbc3f8e9f67ae8fb83f098e4");
</script>
<style scoped>
</style>

View File

@ -166,7 +166,7 @@ async function playSearchSong(song: Song) {
// MusicApi.stream // MusicApi.stream
playSong(song, songResults.value) playSong(song, songResults.value)
} }
message.success(`正在播放:${song.title}`) // message.success(`${song.title}`)
} }
async function submitSearch() { async function submitSearch() {

View File

@ -20,7 +20,7 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"ignoreDeprecations": "6.0", // "ignoreDeprecations": "6.0",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["src/*"] "@/*": ["src/*"]