207 lines
6.3 KiB
Rust
207 lines
6.3 KiB
Rust
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>,
|
||
}
|