use std::collections::BTreeMap; use std::fs::File; use std::io::Write; use std::str::FromStr; use chrono::NaiveDateTime; use handlebars::Handlebars; use rust_decimal::Decimal; use rust_decimal::prelude::{FromPrimitive, ToPrimitive}; use rust_decimal_macros::dec; use serde_json::json; use tracing::info; use crate::utils::utils::{BalanceConfigInfo}; pub fn export_html(config: BalanceConfigInfo, acc_name_all: &Vec, x_time: &Vec, data_list: &Vec>, statistic_result: String) { info!("正在生成网页,请稍后!"); let export_path = if config.export_path == "" { "./" } else { config.export_path.as_str() }; let export_name = if config.export_name == "" { "export_balance" } else { config.export_name.as_str() }; let path = format!("{}/{}.html", export_path, export_name).replace("//", "/"); // 创建 Handlebars 实例 let mut handlebars = Handlebars::new(); //时间片数据组装 let mut time_str_x = vec![]; for time in x_time { let time_str = NaiveDateTime::from_timestamp_millis((time + 8 * 3600) * 1000).unwrap().format("%Y-%m-%d %H:%M:%S%.3f").to_string(); time_str_x.push(time_str); } //每个账号的数据 let mut map: BTreeMap> = BTreeMap::new(); let mut capital_info: BTreeMap = Default::default(); for acc_name in acc_name_all.clone() { capital_info.insert(acc_name.parse().unwrap(), dec!(0)); } for acc_name in acc_name_all.clone() { let mut pr_data: Vec = vec![]; let z = acc_name.clone(); let key = z.as_str(); if map.contains_key(key) { pr_data = map.get(key).unwrap().clone(); } let mut income = dec!(0); let mut earnings = dec!(0); for data in data_list.clone() { if data[0].clone().as_str() == key { let pr = Decimal::from_str(&data[4]).unwrap(); if capital_info[key] == dec!(0) || data[5] == "transfer" { earnings = income; capital_info.insert(key.parse().unwrap(), pr); } income = if capital_info[key] == dec!(0) { dec!(0) } else { ((pr - capital_info[key]) / capital_info[key] * dec!(100.0) + earnings).round_dp(2) }; pr_data.push(f64::try_from(income).unwrap()); } } map.insert(key.to_string(), pr_data); } let mut series_all = Vec::new(); for (key, val) in map { let series = json!({"name": key.to_string(), "type": "line", "smooth": true, "data": val}); series_all.push(series); } let series_array = if config.is_total { [series_all[series_all.len() - 1].clone()].to_vec() } else { series_all }; let json = json!({ "data":series_array }); let series_str = format!("{}", json["data"]); let data = serde_json::json!({ "chart_title": format!("账户合约余额变更历史"), "acc_name_all": acc_name_all.clone(), "statistic_result": statistic_result.clone() }); // HTML 模板 let template = r#" {{chart_title}}
{{{statistic_result}}}
"#; // 编译模板 handlebars .register_template_string("page", template) .expect("编译模版失败!"); // 渲染模板 let output = handlebars .render("page", &data) .expect("渲染模版失败!"); // 将 HTML 写入文件 let mut file = File::create(&path).expect("创建文件失败!"); file.write_all(output.as_bytes()).expect("写入文件到本地失败!"); info!("Balance信息网页生成成功!路径:{:?}\n\n", path); }