hardware_toolkit/src/utils/step_downloader.rs
z_lenovo f32c856097 to remove the winsparkle module?
winsparkle好像有点不好调,再试一下吧,如果今晚搞定了就发初版,搞不定就改用gitea发布新版
2025-07-02 21:26:19 +08:00

207 lines
6.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use anyhow::Result;
use image::EncodableLayout;
#[allow(unused_imports)]
use tracing::{error, info, warn};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct SearchResultItem {
name: String,
code: String,
has_device: String,
img_urls: Vec<String>,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct FetchResultItem {
pub imgs: Vec<iced::widget::image::Handle>,
pub name: String,
pub model:String,
pub code :String,
pub model_id: String,
pub datasheet:String,
}
/// 访问一次api得到需要的部分数据
pub async fn search_keyword(
keyword: String,
cur_page: u32,
page_size: u32,
) -> Result<Vec<SearchResultItem>> {
let mut form_maps = std::collections::HashMap::new();
form_maps.insert("keyword", keyword);
let cur_page = format!("{cur_page}");
let page_size = format!("{page_size}");
form_maps.insert("curPage", cur_page);
form_maps.insert("pageSize", page_size);
let resp = reqwest::Client::new()
.post("https://pro.lceda.cn/api/eda/product/search")
.form(&form_maps)
.send()
.await?;
let text = resp.text().await?;
let j: KeywordSearchRoot = serde_json::from_str(&text)?;
let mut r = Vec::new();
for i in j.result.productList.iter() {
if let Some(has) = i.hasDevice.clone() {
let mut imgs = Vec::new();
if let Some(s) = i.image.clone() {
for img in s.imgs() {
imgs.push(img.clone());
}
}
let ii = SearchResultItem {
name: i.model.clone(),
code:i.code.clone(),
has_device: has,
img_urls: imgs,
};
r.push(ii);
}
}
Ok(r)
}
pub async fn download_step(id: String) -> Result<String> {
let url = format!("https://modules.lceda.cn/qAxj6KHrDKw4blvCG8QJPs7Y/{id}");
let url = url.as_str();
let resp = reqwest::get(url).await?;
let text = resp.text().await?;
Ok(text)
}
pub async fn fetch_item(item: SearchResultItem) -> Result<FetchResultItem> {
let h = search_has_device(&item.has_device).await?;
let mut has_device = String::new();
let v: serde_json::Value = serde_json::from_str(h.as_str())?;
let id = v["result"][0]["attributes"]["3D Model"].clone();
if let serde_json::Value::String(id) = id {
has_device = id.clone();
}
let mut title = String::new();
let mut footprint = String::new();
let mut datasheet = String::new();
if let serde_json::Value::String(t) = v["result"][0]["title"].clone(){
title = t;
}
if let serde_json::Value::String(t) = v["result"][0]["attributes"]["Supplier Footprint"].clone(){
footprint = t;
}
if let serde_json::Value::String(t) = v["result"][0]["attributes"]["Datasheet"].clone(){
datasheet = t;
}
let mut step_id = String::new();
let resp = search_model_id(has_device.as_str()).await?;
let mut model = String::new();
let v: serde_json::Value = serde_json::from_str(resp.as_str())?;
info!("In search_model_id: The v is : {v:#?}");
let data_str: serde_json::Value = v["result"][0]["dataStr"].clone();
if let serde_json::Value::String(data_str) = data_str {
let data_str: DataStr = serde_json::from_str(data_str.as_str())?;
if let Some(m) = data_str.model {
step_id = m;
}else{
return Err(anyhow::Error::msg("Failed to get model"));
}
}
let mut imgs = Vec::new();
for img_url in item.img_urls {
info!("Fetching img url: {}", img_url);
let img = reqwest::get(img_url).await?.bytes().await?;
// let img = image::load_from_memory(&img)?;
let img = iced::widget::image::Handle::from_bytes(img.clone());
imgs.push(img);
}
let rst = FetchResultItem {
name: item.name.clone(),
model_id: step_id,
model:footprint,
code:item.code,
imgs,
datasheet,
};
Ok(rst)
}
async fn search_has_device(has_device: &str) -> Result<String> {
let mut form_maps = std::collections::HashMap::new();
form_maps.insert("uuids[]", has_device);
let url = "https://pro.lceda.cn/api/devices/searchByIds";
let resp = reqwest::Client::new()
.post(url)
.form(&form_maps)
.send()
.await?;
let text = resp.text().await?;
Ok(text)
}
async fn search_model_id(uuid: &str) -> Result<String> {
let mut form_maps = std::collections::HashMap::new();
form_maps.insert("uuids[]", uuid);
form_maps.insert("dataStr", "yes");
let url = "https://pro.lceda.cn/api/components/searchByIds?forceOnline=1";
let resp = reqwest::Client::new()
.post(url)
.form(&form_maps)
.send()
.await?;
let text = resp.text().await?;
info!("In search_model_id: The v is : {}",text.clone());
return Ok(text)
}
#[derive(Clone, Default, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
struct KeywordSearchRoot {
code: u32,
success: bool,
result: KeywordSearchResult,
}
#[allow(non_snake_case)]
#[derive(Default, Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq)]
struct KeywordSearchResult {
total: u32,
productList: Vec<KeywordSearchListItem>,
}
#[allow(non_snake_case)]
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq)]
struct KeywordSearchListItem {
id: u32,
code: String,
image: Option<KeywordChipImages>,
model: String,
hasDevice: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq)]
struct KeywordChipImages(String);
#[allow(dead_code)]
impl KeywordChipImages {
pub fn imgs(&self) -> Vec<String> {
let urls = self.0.clone();
let list = urls.split("<$>");
let mut rst = Vec::new();
for i in list {
rst.push(i.to_string());
}
rst
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct KeywordDevInfo {
uuid: String,
description: String,
title: String,
images: Vec<String>,
attributes: KeywordAttributes,
}
#[allow(non_snake_case)]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct KeywordAttributes {
Datasheet: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct DataStr {
model: Option<String>,
src: Option<String>,
_type: Option<String>,
}