Explorar el Código

基础验证完毕

zii hace 3 meses
commit
60dc18c3be
Se han modificado 12 ficheros con 1539 adiciones y 0 borrados
  1. 3 0
      .cargo/config.toml
  2. 3 0
      .gitignore
  3. 1055 0
      Cargo.lock
  4. 15 0
      Cargo.toml
  5. 26 0
      data_init.py
  6. 42 0
      src/api/code_helper.rs
  7. 0 0
      src/api/device.rs
  8. 74 0
      src/api/mod.rs
  9. 169 0
      src/api/user.rs
  10. 19 0
      src/datasource/mod.rs
  11. 102 0
      src/datasource/sqlite.rs
  12. 31 0
      src/main.rs

+ 3 - 0
.cargo/config.toml

@@ -0,0 +1,3 @@
+[target.armv7-unknown-linux-musleabihf]
+linker = "/cross/armv7l-linux-musleabihf-native/bin/armv7l-linux-musleabihf-gcc"
+rustflags = ["-C", "target-feature=+crt-static"]

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/target
+*.sqlite
+*.db

+ 1055 - 0
Cargo.lock

@@ -0,0 +1,1055 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "axum"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425"
+dependencies = [
+ "axum-core",
+ "axum-macros",
+ "bytes",
+ "form_urlencoded",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde_core",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-macros"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "bb8"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "457d7ed3f888dfd2c7af56d4975cade43c622f74bdcddfed6d4352f57acc6310"
+dependencies = [
+ "futures-util",
+ "parking_lot",
+ "portable-atomic",
+ "tokio",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+
+[[package]]
+name = "bumpalo"
+version = "3.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
+
+[[package]]
+name = "bytes"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
+
+[[package]]
+name = "cc"
+version = "1.2.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "chrono"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+
+[[package]]
+name = "futures-util"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
+dependencies = [
+ "hashbrown",
+]
+
+[[package]]
+name = "http"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
+dependencies = [
+ "bytes",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "pin-utils",
+ "smallvec",
+ "tokio",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "iotplatform_lite"
+version = "0.1.0"
+dependencies = [
+ "axum",
+ "bb8",
+ "chrono",
+ "md5",
+ "rand",
+ "rusqlite",
+ "serde",
+ "serde_json",
+ "tokio",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "js-sys"
+version = "0.3.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.178"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.35.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "matchit"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
+
+[[package]]
+name = "md5"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
+
+[[package]]
+name = "memchr"
+version = "2.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "mio"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "portable-atomic"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rusqlite"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f"
+dependencies = [
+ "bitflags",
+ "chrono",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "smallvec",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
+dependencies = [
+ "itoa",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+
+[[package]]
+name = "tokio"
+version = "1.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
+dependencies = [
+ "bytes",
+ "libc",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tower"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
+[[package]]
+name = "tracing"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-result"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]

+ 15 - 0
Cargo.toml

@@ -0,0 +1,15 @@
+[package]
+name = "iotplatform_lite"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+rusqlite = { version = "0.37.0", features = ["bundled", "chrono"] }
+tokio = { version = "1.28.0", features = ["full"] }
+chrono = "0.4.42" 
+serde = { version = "1.0.228", features = ["derive"] }
+serde_json = "1.0.145"
+axum = { version = "0.8.7", features = ["macros"] }
+bb8 = "0.9.0"
+rand = "0.9.2"
+md5 = "0.8.0"

+ 26 - 0
data_init.py

@@ -0,0 +1,26 @@
+import sqlite3
+
+curs = (conn:=sqlite3.connect('db.sqlite')).cursor()
+
+curs.execute('''
+create table if not exists user (
+id integer PRIMARY KEY,
+uname text not null,
+passwd text not null,
+nickname text not null,
+token text not null default '',
+createtime timestamp not null default current_timestamp,
+lastlogin timestamp,
+isdelete integer not null default 0
+)
+''').fetchall()
+
+curs.execute('''
+insert into user (uname,passwd,nickname) values ('root', 'e10adc3949ba59abbe56e057f20f883e', 'admin')
+''').fetchall()
+curs.execute('''
+insert into user (uname,passwd,nickname) values ('admin', 'e10adc3949ba59abbe56e057f20f883e', 'test')
+''').fetchall()
+curs.execute('''
+select * from user
+''').fetchall()

+ 42 - 0
src/api/code_helper.rs

@@ -0,0 +1,42 @@
+use crate::datasource::Datasource;
+
+// 更实用的示例:展示如何处理多种数据类型参数的插入操作
+#[allow(dead_code)]
+async fn example_insert_multiple_types(state: &crate::AppState, id: i32, name: String, binary_data: Vec<u8>, created_at: String) -> Result<(), String> {
+    // 使用数组形式传递不同类型的参数,避免使用 params! 宏
+    state.db_lite.execute(
+        "INSERT INTO users (id, name, binary_data, created_at) VALUES (?, ?, ?, ?)",
+        // 显式转换为 &dyn rusqlite::ToSql 类型
+        [&id as &dyn rusqlite::ToSql, 
+         &name as &dyn rusqlite::ToSql, 
+         &binary_data as &dyn rusqlite::ToSql, 
+         &created_at as &dyn rusqlite::ToSql]
+    ).await.map(|_| ())
+}
+
+// 另一种更简洁的方法:使用元组形式
+#[allow(dead_code)]
+async fn example_insert_tuple(state: &crate::AppState, id: i32, name: String, binary_data: Vec<u8>, created_at: String) -> Result<(), String> {
+    // 使用元组形式传递参数,这是最简洁的方式
+    state.db_lite.execute(
+        "INSERT INTO users (id, name, binary_data, created_at) VALUES (?, ?, ?, ?)",
+        (id, name, binary_data, created_at)
+    ).await.map(|_| ())
+}
+
+// 使用 params_from_iter 的方式(适用于动态参数数量)
+#[allow(dead_code)]
+async fn example_insert_params_from_iter(state: &crate::AppState, id: i32, name: String, binary_data: Vec<u8>, created_at: String) -> Result<(), String> {
+    // 构造参数向量
+    let params: Vec<Box<dyn rusqlite::ToSql>> = vec![
+        Box::new(id),
+        Box::new(name),
+        Box::new(binary_data),
+        Box::new(created_at),
+    ];
+    
+    state.db_lite.execute(
+        "INSERT INTO users (id, name, binary_data, created_at) VALUES (?, ?, ?, ?)",
+        rusqlite::params_from_iter(params)
+    ).await.map(|_| ())
+}

+ 0 - 0
src/api/device.rs


+ 74 - 0
src/api/mod.rs

@@ -0,0 +1,74 @@
+pub mod user;
+pub mod device;
+#[cfg(target_arch = "x86_64")]
+#[cfg(target_os = "windows")]
+mod code_helper;
+
+use rand::Rng;
+use crate::datasource::Datasource;
+
+#[derive(serde::Serialize)]
+pub struct JsonBack{
+    pub errcode: i16,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub errmsg: Option<String>
+}
+
+#[derive(serde::Serialize)]
+pub struct DataBack<T>{
+    pub errcode: i16,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub errmsg: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub data: Option<T>
+}
+
+#[derive(serde::Deserialize)]
+pub struct Page{
+    page: usize,
+    size: usize
+}
+
+pub fn token_fail() ->axum::Json<JsonBack> {axum::Json(JsonBack{
+    errcode: 0,
+    errmsg: Some("鉴权失败: token无效".to_string())
+})}
+
+#[allow(dead_code)]
+pub async fn example(axum::extract::State(_): axum::extract::State<crate::AppState>) -> axum::Json<JsonBack> {
+    axum::Json(JsonBack{
+        errcode: 0,
+        errmsg: None
+    })
+}
+
+pub async fn check_login(state: &crate::AppState, token: String) -> Result<i64,()>{
+    state.db_lite.query(
+        "select id from user where token=? and isdelete=0", 
+        [token],  // 这里不能写作 rusqlite::params![token] 
+        |r|{r.get::<usize,i64>(0)}).await.map_err(|e| println!("{e}"))
+}
+
+pub fn token() -> String{
+    rand::rng().sample_iter(&rand::distr::Alphanumeric).take(32).map(char::from).collect()
+}
+
+
+pub fn md5(payload: String) -> String{
+    format!("{:x}",md5::compute(payload))
+}
+
+#[cfg(test)]
+mod tests{
+    #[test]
+    fn test_token(){
+        use super::token;
+        println!("{}",token());
+    }
+     #[test]
+    fn test_md5(){
+        use super::md5;
+        println!("{}",md5("123456".to_string()));
+    }
+} 
+

+ 169 - 0
src/api/user.rs

@@ -0,0 +1,169 @@
+use crate::{AppState, api::{JsonBack, DataBack, Page}, datasource::{Datasource,SqliteParams}};
+use crate::api::{check_login,token,md5,token_fail};
+use serde::{Deserialize,Serialize};
+use axum::{Json, extract::State};
+
+#[derive(Deserialize)]
+pub struct Uloggin{
+    uname: String,
+    passwd: String,
+}
+
+#[derive(serde::Serialize)]
+pub struct UTokenBack{
+    pub errcode: i16,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub errmsg: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub token: Option<String>
+}
+
+pub async fn u_loggin(
+    State(state): State<AppState>,
+    Json(u): axum::extract::Json<Uloggin>
+) -> Json<UTokenBack> {
+
+    let uid = match state.db_lite.query(
+        "select id from user where uname=? and passwd=? and isdelete=0", 
+        [u.uname,md5(u.passwd)],
+        |r| {r.get::<usize,i64>(0)}).await{
+            Ok(ans) => ans,
+            Err(e) => {
+                if e != ""{
+                    println!("error when loggin {e}");
+                }
+                return Json(UTokenBack{
+                    errcode: 2000,
+                    errmsg: Some(format!("登录失败")),
+                    token: None,
+                })
+            }
+        };
+    let token = token();
+    if let Err(e) = state.db_lite.execute("update user set lastlogin=current_timestamp,token=? where id=?", (token.clone(), uid)).await{
+        println!("error when loggin {e}")
+    }
+    Json(UTokenBack{
+        errcode: 0,
+        errmsg: None,
+        token: Some(token),
+    })
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct Uedit{
+    token: Option<String>,  // 为空时判断uname-passwd创建账户
+    id: Option<u64>,  // 不为空时为编辑该用户的uname-passwd,若uname-passwd为空则删除用户
+    // 以下为可编辑项
+    uname: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    passwd: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    group: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    nickname: Option<String>,
+    lastlogin: Option<u64>,
+    createtime: Option<u64>
+}
+
+pub async fn u_edit(
+    State(state): State<AppState>,
+    Json(u): axum::extract::Json<Uedit>
+) -> Json<JsonBack> {
+    if u.token.is_none() {
+        // 新建用户
+        return axum::Json(JsonBack{
+        errcode: 3000,
+        errmsg: Some(format!("不允许创建用户"))
+    });
+    }
+    let uid = match check_login(&state, u.token.unwrap()).await{
+        Ok(uid)=> uid,
+        Err(()) => return token_fail()
+    };
+    if let Some(_) = u.id {
+        // 删除对应uid的用户
+        return Json(JsonBack{
+            errcode: 0,
+            errmsg: Some(format!("无效的操作"))
+        })
+    }
+        
+    let mut param:SqliteParams = vec![];
+    
+    if let Err(e) = state.db_lite.execute(format!("update user set isdelete=0{}{}{}{} where id=?",
+        if let Some(filter)=u.uname {param.push(Box::new (filter.clone()));",uname=?"} else {""},
+        if let Some(filter)=u.passwd {param.push(Box::new (filter.clone()));",passwd=?"} else {""},
+        if let Some(filter)=u.group {param.push(Box::new (filter.clone()));",group=?"} else {""},
+        if let Some(filter)=u.nickname {param.push(Box::new (filter.clone()));",group=?"} else {""},
+    ).as_str(), rusqlite::params_from_iter({param.push(Box::new(uid));param})).await{
+        return  Json(JsonBack{
+            errcode: 0,
+            errmsg: Some(format!("数据库操作失败: {e}"))
+        });
+    }
+
+    Json(JsonBack{
+        errcode: 0,
+        errmsg: None
+    })
+}
+
+
+#[derive(Deserialize)]
+pub struct Ulist{
+    token: String,
+    #[serde(flatten)]
+    page: Option<Page>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    nickname: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    group: Option<String>
+}
+
+
+pub async fn u_list(
+    State(state): State<AppState>,
+    Json(u): axum::extract::Json<Ulist>
+) -> Json<DataBack<Vec<Uedit>>> {
+    // 在这里实现用户列表查询逻辑
+    // 可以使用 u.page.page, u.page.size, u.nickname, u.group
+    let _ = match check_login(&state, u.token).await{
+        Ok(uid) => uid,
+        Err(_) => return Json(DataBack { errcode: 2000, errmsg: Some("鉴权失败: token失效".to_string()), data: None })
+    };
+    
+    let (page,size) = if let Some(p)=u.page {(p.page,p.size)} else {(1,20)};
+    let mut params: SqliteParams = vec![];
+    
+    match state.db_lite.query_rows(
+        format!("select u.id, u.uname, u.nickname, strftime('%s',  u.lastlogin)*1000, strftime('%s', u.createtime)*1000 from user u where isdelete=0{}{} limit ? offset ?",
+        if let Some(ref filter) = u.nickname {params.push(Box::new(filter.clone())); " and u.nickname like ?"} else {""},
+        if let Some(ref filter) = u.group {params.push(Box::new(filter.clone())); " and u.group like ?"} else {""}
+    ).as_str(),
+     rusqlite::params_from_iter({params.push(Box::new(size));params.push(Box::new(size*(page-1)));params}) , |r| {
+            Ok(Uedit{
+                token: None,
+                id: r.get(0)?,
+                uname: r.get(1)?,
+                passwd: None,
+                group: None,
+                nickname: r.get(2)?,
+                lastlogin: r.get(3)?,
+                createtime: r.get(4)?
+            })
+        }).await{
+            Ok(ans) => Json(DataBack{
+                errcode: 0,
+                errmsg:None,
+                data: Some(ans)
+            }),
+            Err(e) => {
+                Json(DataBack { 
+                    errcode: 0,
+                    errmsg: Some(format!("查询失败: {e}")),
+                    data: None
+                })
+            }
+        }
+}

+ 19 - 0
src/datasource/mod.rs

@@ -0,0 +1,19 @@
+pub mod sqlite;
+
+pub type SqliteParams = Vec<Box<dyn rusqlite::ToSql + Send>>;
+
+pub trait Datasource {
+    async fn query<P, T, F>(&self, query: &str, params:P, f:F) -> Result<T, String>
+    where
+        P: rusqlite::Params,
+        F: FnOnce(&rusqlite::Row<'_>) -> rusqlite::Result<T>;
+
+    async fn query_rows<P, T, F>(&self, query: &str, params: P, f: F) -> Result<Vec<T>, String>
+    where
+        P: rusqlite::Params,
+        F: FnMut(&rusqlite::Row<'_>) -> rusqlite::Result<T>;
+
+    async fn execute<P>(&self, query: &str, params:P) -> Result<usize, String>
+    where
+        P: rusqlite::Params;
+}

+ 102 - 0
src/datasource/sqlite.rs

@@ -0,0 +1,102 @@
+
+use bb8::Pool;
+/// SQLite连接池类型
+pub type SqlitePool = bb8::Pool<SqliteConnectionManager>;
+/// SQLite连接管理器
+#[derive(Clone)]
+pub struct SqliteConnectionManager {
+    url: String,
+}
+
+impl SqliteConnectionManager {
+    /// 创建新的SQLite连接管理器
+    pub fn new(url: String) -> Self {
+        Self { url }
+    }
+}
+
+impl bb8::ManageConnection for SqliteConnectionManager {
+    type Connection = rusqlite::Connection;
+    type Error = rusqlite::Error;
+
+    fn connect(&self) -> impl Future<Output = Result<Self::Connection, Self::Error>> + Send {
+        let url = self.url.clone();
+        async move {
+            let conn = tokio::task::spawn_blocking(move || rusqlite::Connection::open(&url))
+                .await
+                .unwrap();
+            conn
+        }
+    }
+
+    fn is_valid(&self, _conn: &mut Self::Connection) -> impl Future<Output = Result<(), Self::Error>> + Send {
+        // 对于SQLite,我们暂时跳过验证
+        async move {
+            Ok(())
+        }
+    }
+
+    fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
+        // 暂时假设连接未损坏
+        false
+    }
+}
+
+/// 初始化SQLite连接池
+pub async fn init_sqlite_pool(url: &str, max_size: u32) -> Result<SqlitePool, Box<dyn std::error::Error>> {
+    let manager = SqliteConnectionManager::new(url.to_string());
+    let pool = Pool::builder()
+        .max_size(max_size)
+        .build(manager)
+        .await?;
+    Ok(pool)
+}
+impl crate::datasource::Datasource for SqlitePool{
+    async fn query<P, T, F>(&self, sql: &str, params: P,f: F) -> Result<T, String> 
+    where
+        P: rusqlite::Params,
+        F: FnOnce(&rusqlite::Row<'_>) -> rusqlite::Result<T>,
+    {
+        match tokio::time::timeout(std::time::Duration::from_secs(5), self.get()).await {
+             Ok(Ok(conn)) => conn,
+            Ok(Err(e)) => return Err(format!("connection err: {}",e.to_string())),
+            Err(_) => return Err("Timeout".to_string())
+        }.query_row(sql, params, f).map_err(|e| if e == rusqlite::Error::QueryReturnedNoRows { String::new() } else{ e.to_string()})
+    }
+    
+    async fn query_rows<P, T, F>(&self, sql: &str, params: P, mut f: F) -> Result<Vec<T>, String>
+    where
+        P: rusqlite::Params,
+        F: FnMut(&rusqlite::Row<'_>) -> rusqlite::Result<T>,
+    {
+        match tokio::time::timeout(std::time::Duration::from_secs(5), self.get()).await {
+             Ok(Ok(conn)) => conn,
+            Ok(Err(e)) => return Err(format!("connection err: {}",e.to_string())),
+            Err(_) => return Err("Timeout".to_string())
+        }.prepare(sql)
+        .map_err(|e| e.to_string())
+        .and_then(|mut stmt| {
+            let mut results = Vec::new();
+            let mut rows = stmt.query(params).map_err(|e| e.to_string())?;
+            
+            while let Some(row) = rows.next().map_err(|e| e.to_string())? {
+                match f(row) {
+                    Ok(item) => results.push(item),
+                    Err(e) => return Err(e.to_string()),
+                }
+            }
+            
+            Ok(results)
+        })
+    }
+    
+    async fn execute<P>(&self, sql: &str, params:P) -> Result<usize, String>
+        where
+            P: rusqlite::Params {
+        match tokio::time::timeout(std::time::Duration::from_secs(5), self.get()).await {
+             Ok(Ok(conn)) => conn,
+            Ok(Err(e)) => return Err(format!("connection err: {}",e.to_string())),
+            Err(_) => return Err("Timeout".to_string())
+        }.execute(sql, params).map_err(|e| e.to_string())
+    }
+}

+ 31 - 0
src/main.rs

@@ -0,0 +1,31 @@
+mod datasource;
+mod api;
+use datasource::sqlite;
+
+#[derive(Clone)]
+struct AppState{
+    db_lite: sqlite::SqlitePool
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
+
+    let appstat = AppState{db_lite: sqlite::init_sqlite_pool("./db.sqlite", 10).await?};
+
+    use axum::routing::{post};
+    let app =  axum::Router::new()
+        .nest("/api", axum::Router::new()
+            .route("/loggin", post(api::user::u_loggin))
+            .route("/user/edit", post(api::user::u_edit))
+            .route("/user/list", post(api::user::u_list))
+            // .route("/device/edit", post(api::user::d_edit))
+            // .route("/device/save", post(api::user::d_save))
+            // .route("/device/burn", post(api::user::d_save))
+        )
+        // .route("/hello", get(api::example))
+        .with_state(appstat)
+    ;
+    axum::serve(listener, app).await?;
+    Ok(())
+}