fache 0.1.351

发车工具箱
Documentation
use super::{
    adcode_or_jwd_to_weather::WeatherResponse,
    adds_jwd_type::AddressResponse,
    ip_to_info_type::IpLocationResponse,
    jwd_adds_type::AddressReference,
    jwd_to_qmap::{CoordinateResponse, JwdType},
};
use crate::{all::mapqq::ReverseGeocodeResponse, json, url};

use reqwest::Client;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JwdToAdds {
    pub jd: f64, //lng<经度>
    pub wd: f64, //lat<纬度>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AddsToJwd {
    pub address: String,
}

/// 天气查询类型枚举
#[derive(Debug, Serialize, Default, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum WeatherQueryType {
    /// 实时天气预报
    #[serde(alias = "now")]
    #[default]
    Now,
    /// 未来天气预报(默认获取当天和未来3天的天气信息)
    #[serde(alias = "future")]
    Future,
}

#[derive(Serialize, Deserialize, Default, Debug, Clone)]
pub struct TMap {
    #[serde(default)]
    pub key: String, // 腾讯地图的 key

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(flatten, default)] // 将 JwdToAdds 的字段展开到顶层
    pub jwd: Option<JwdToAdds>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(flatten, default)] // 将 AddsToJwd 的字段展开到顶层
    pub adds: Option<AddsToJwd>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(flatten, default)]
    pub ip: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub adcode: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    /// 查询天气类型,取值:
    /// now[默认] 实时天气预报
    /// future 未来天气预报(默认获取当天和未来3天的天气信息)
    pub r#type: Option<String>,
}
// impl Default for TMap {
//     fn default() -> Self {
//         Self {
//             key: "".to_owned(),
//             jwd: None,
//             adds: None,
//             ip: None,
//             r#type: None,
//             adcode: None,
//         }
//     }
// }
impl TMap {
    /// 通过经纬度查询地址
    pub async fn jwd_to_adds(&self) -> ReverseGeocodeResponse {
        let url = format!(
            "https://apis.map.qq.com/ws/geocoder/v1/?location={},{}&key={}",
            &self.jwd.clone().unwrap().wd,
            &self.jwd.clone().unwrap().jd,
            &self.key
        );
        let response = Client::new().get(url).send().await.unwrap();
        if !response.status().is_success() {
            panic!("请求失败,状态码: {}", response.status());
        }

        response
            .json::<ReverseGeocodeResponse>()
            .await
            .map_err(|e| {
                println!("解析数据 ReverseGeocodeResponse 失败: {:#?}", &self);
                println!("解析 经纬度 数据 ReverseGeocodeResponse 失败: {}", e);
            })
            .unwrap()
    }
    /// 通过地址查询经纬度
    pub async fn adds_to_jwd(&self) -> AddressResponse {
        let url = format!(
            "https://apis.map.qq.com/ws/geocoder/v1/?address={}&key={}",
            // 需要将地址 encode 一下。否则 # 号地址会报错
            url::encode(&self.adds.clone().unwrap().address),
            &self.key
        );
        let response = Client::new().get(url).send().await.unwrap();
        if !response.status().is_success() {
            panic!("请求失败,状态码: {}", response.status());
        }
        response
            .json::<AddressResponse>()
            .await
            .map_err(|e| {
                println!("解析数据 AddressResponse 失败: {:#?}", &self);
                println!("解析数据 AddressResponse 失败: {}", e);
            })
            .unwrap()
    }
    /// 通过行政区划编码或者经纬度,查询对应城市的实时天气或预报天气。
    pub async fn adcode_or_jwd_to_weather(&self) -> WeatherResponse {
        let mut url = format!(
            "https://apis.map.qq.com/ws/weather/v1/?key={}&output=json",
            self.key
        );
        if let Some(adcode) = &self.adcode {
            url.push_str(&format!("&adcode={}", adcode));
        }
        if let Some(query_type) = &self.r#type {
            url.push_str(&format!("&type={}", query_type));
        }
        if let Some(coord) = &self.jwd {
            url.push_str(&format!("&location={},{}", coord.wd, coord.jd));
        }
        let res = Client::new().get(url).send().await.unwrap();
        if res.status().is_success() {
            // println!("解析数据 : {:#?}", res);
            res.json::<WeatherResponse>()
                .await
                .map_err(|e| {
                    println!("解析 天气 数据 WeatherResponse 失败:  {:#?}", &self);
                    println!("解析 天气 数据 WeatherResponse 失败: {}", e);
                })
                .unwrap()
        } else {
            panic!("请求失败,状态码: {}", res.status());
        }
    }
    ///通过 ip 查询经纬度与地址信息
    pub async fn ip_to_info(&self) -> IpLocationResponse {
        let url = format!(
            " https://apis.map.qq.com/ws/location/v1/ip?ip={}&key={}",
            &self.ip.clone().unwrap(),
            &self.key
        );
        let response = Client::new().get(url).send().await.unwrap();
        if !response.status().is_success() {
            panic!("请求失败,状态码: {}", response.status());
        }
        response
            .json::<IpLocationResponse>()
            .await
            .map_err(|e| {
                println!("解析数据 IpLocationResponse 失败: {:#?}", &self);
                println!("解析数据 IpLocationResponse 失败: {}", e);
            })
            .unwrap()
    }
    /// 实现从其它地图供应商坐标系或标准GPS坐标系,批量转换到腾讯地图坐标系。
    pub async fn jwd_to_qmap(&self, e: Vec<JwdType>) -> CoordinateResponse {
        let first_type = e[0].coord_type;
        // 构建locations参数字符串
        let locations = e
            .iter()
            .map(|c| format!("{},{}", c.latitude, c.longitude))
            .collect::<Vec<_>>()
            .join(";");
        // 构建请求URL
        let url = format!(
            "https://apis.map.qq.com/ws/coord/v1/translate?key={}&locations={}&type={}&output=json",
            &self.key, locations, first_type as i32
        );
        let response = Client::new().get(url).send().await.unwrap();
        if !response.status().is_success() {
            panic!("请求失败,状态码: {}", response.status());
        }
        response
            .json::<CoordinateResponse>()
            .await
            .map_err(|e| {
                println!("解析数据 CoordinateResponse 失败:  {:#?}", &self);
                println!("解析数据 CoordinateResponse 失败: {}", e);
            })
            .unwrap()
    }
}