use std::collections::HashMap;
use br_db::{Db};
use json::{array, JsonValue, object};
use crate::model::Model;
#[derive(Clone)]
pub struct Tables {
pub table: String,
pub header: JsonValue,
pub request: JsonValue,
pub db: Db,
pub search_fields: HashMap<String, Vec<String>>,
pub query_fields: HashMap<String, Vec<String>>,
pub hidden_fields: HashMap<String, Vec<String>>,
pub main_field: HashMap<String, String>,
pub right_field: HashMap<String, String>,
pub tables: Vec<(String, JsonValue)>,
pub fields: HashMap<String, Vec<String>>,
pub columns: JsonValue,
}
impl Tables {
pub fn set_table(&mut self, table: &str) {
self.table = table.to_string();
self.db.table(table);
}
#[allow(clippy::too_many_arguments)]
pub fn set_join_fields(&mut self, mut model: Box<dyn Model>, main_field: &str, right_field: &str, search_fields: Vec<&str>, query_fields: Vec<&str>, hidden_fields: Vec<&str>, show_fields: Vec<&str>) {
let table = model.table().to_string();
let fields = model.fields();
let mut tables_field = object! {};
let mut field_list = vec![];
for (name, list) in fields.entries() {
if show_fields.is_empty() {
if !hidden_fields.contains(&&*name.to_string()) {
field_list.push(name);
tables_field[name] = list.clone();
}
} else if show_fields.contains(&&*name.to_string()) {
field_list.push(name);
tables_field[name] = list.clone();
}
}
self.tables.push((table.clone(), tables_field));
self.fields.insert(table.clone(), field_list.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
self.search_fields.insert(table.clone(), search_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
self.query_fields.insert(table.clone(), query_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
self.hidden_fields.insert(table.clone(), hidden_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
self.main_field.insert(table.clone(), main_field.to_string());
self.right_field.insert(table.clone(), right_field.to_string());
}
pub fn get_columns(&mut self) -> JsonValue {
let mut data = object! {};
for (_, fields) in self.tables.clone() {
for (name, field) in fields.entries() {
let mut row = field.clone();
row["name"] = field["field"].clone();
row["label"] = field["title"].clone();
row["align"] = "center".into();
row["sortable"] = match field["mode"].as_str().unwrap() {
"int" | "float" | "switch" | "datetime" | "date" | "time" | "year" | "timestamp" => {
true.into()
}
_ => {
false.into()
}
};
if data[name].is_null() {
data[name] = row.clone();
self.columns.push(row.clone()).unwrap();
}
}
}
self.columns.clone()
}
fn search_title(&mut self) -> String {
let mut data = vec![];
for (table, fields) in self.tables.iter_mut() {
let search_fields = self.search_fields.get(&*table.clone()).unwrap().clone();
for (name, field) in fields.entries() {
if search_fields.contains(&name.to_string()) {
data.push(field["title"].as_str().unwrap());
}
}
}
format!("搜索 {}", data.join(" "))
}
fn query_fields(&mut self) -> JsonValue {
let mut data = array![];
for (table, fields) in self.tables.iter_mut() {
let query_fields = self.query_fields.get(&*table.clone()).unwrap().clone();
for (name, field) in fields.entries() {
if query_fields.contains(&name.to_string()) {
let mut row = field.clone();
row["require"] = JsonValue::from(false);
data.push(row.clone()).unwrap();
}
}
}
data
}
fn select(&mut self) -> (i32, JsonValue) {
let page = self.request["page"].as_i32().unwrap();
let limit = self.request["limit"].as_i32().unwrap();
let wheres = self.request["where"].clone();
let order = self.request["order"].clone();
let filter = self.request["filter"].to_string();
let mut data = {
let mut db = self.db.clone();
db.table(self.table.as_str());
for (table, fields) in self.tables.clone() {
if self.table == table {
db.change_table(&table.to_string().clone());
} else {
db.join(&table, &self.main_field.get(&*table).unwrap().clone(), &self.right_field.get(&*table).unwrap().clone());
}
if !self.search_fields.get(&*table.clone()).unwrap().is_empty() && !filter.is_empty() {
let search_fields = self.search_fields.get(&*table.clone()).unwrap().join("|");
db.where_and(search_fields.as_str(), "like", format!("%{}%", filter).into());
}
for item in wheres.members() {
let field = item[0].as_str().unwrap_or("");
if !fields[field].is_empty() {
db.where_and(item[0].as_str().unwrap_or(""), item[1].as_str().unwrap_or(""), item[2].clone());
}
}
if !order.is_empty() && self.fields.get(&*table.clone()).unwrap().contains(&order[0].to_string()) {
db.order(order[0].as_str().unwrap(), order[1].as_bool().unwrap());
}
if !self.fields.get(&*table.clone()).unwrap().is_empty() {
db.field(self.fields.get(&*table.clone()).unwrap().join(",").as_str());
}
}
db.page(page, limit).select()
};
let total = {
let mut db = self.db.clone();
db.table(self.table.as_str());
for (table, fields) in self.tables.clone() {
if self.table == table {
db.change_table(&table.to_string().clone());
} else {
db.join(&table, &self.main_field.get(&*table).unwrap().clone(), &self.right_field.get(&*table).unwrap().clone());
}
if !self.search_fields.get(&*table.clone()).unwrap().is_empty() && !filter.is_empty() {
let search_fields = self.search_fields.get(&*table.clone()).unwrap().join("|");
db.where_and(search_fields.as_str(), "like", format!("%{}%", filter).into());
}
for item in wheres.members() {
let field = item[0].as_str().unwrap_or("");
if !fields[field].is_empty() {
db.where_and(item[0].as_str().unwrap_or(""), item[1].as_str().unwrap_or(""), item[2].clone());
}
}
}
db.count().as_i32().unwrap_or(0)
};
let mut fields_table = false;
let mut fields_list = object! {};
for (_, fields) in self.tables.iter_mut() {
for (_key, field) in fields.entries() {
fields_list[field["field"].as_str().unwrap()] = field.clone();
if field["mode"].as_str().unwrap() == "table" {
fields_table = true;
}
}
}
if fields_table {
let mut fields_table_ids = object! {};
for item in data.members_mut() {
for (key, field) in fields_list.entries() {
if field["mode"].as_str().unwrap() == "table" {
let id = item[key].clone();
if id.is_empty() {
continue;
}
if id.contains(",") {
item[key] = array![];
let ids = id.to_string();
let ids = ids.split(",").collect::<Vec<&str>>();
for id in ids.iter() {
if fields_table_ids[id.to_string()].is_null() {
let table = field["table"].as_str().unwrap();
let fields_list: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
let find = self.db.table(table)
.where_and("id", "=", id.to_string().into())
.field(format!("id,{}", fields_list.join(",")).as_str())
.find();
let mut row = object! {};
if !find.is_empty() {
row["id"] = find["id"].clone();
for field in fields_list.iter() {
if row["value"].is_null() {
row["value"] = format!("{}", find[field.to_string()]).into();
} else {
row["value"] = format!("{} | {}", row["value"], find[field.to_string()]).into();
}
}
fields_table_ids[id.to_string()] = row.clone();
} else {
fields_table_ids[id.to_string()] = object! {};
}
}
if !fields_table_ids[id.to_string()].clone().is_empty() {
item[key].push(fields_table_ids[id.to_string()].clone()).unwrap();
}
}
} else {
item[key] = object! {};
if fields_table_ids[id.as_str().unwrap()].is_null() {
let table = field["table"].as_str().unwrap();
let fields_list: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
let find = self.db.table(table)
.where_and("id", "=", id.clone())
.field(format!("id,{}", fields_list.join(",")).as_str())
.find();
let mut row = object! {};
if !find.is_empty() {
row["id"] = find["id"].clone();
for field in fields_list.iter() {
if row["value"].is_null() {
row["value"] = format!("{}", find[field.to_string()]).into();
} else {
row["value"] = format!("{} | {}", row["value"], find[field.to_string()]).into();
}
}
fields_table_ids[id.as_str().unwrap()] = row;
} else {
fields_table_ids[id.as_str().unwrap()] = object! {};
}
}
if !fields_table_ids[id.as_str().unwrap()].clone().is_empty() {
item[key] = fields_table_ids[id.as_str().unwrap()].clone();
}
}
}
}
}
}
(total, data)
}
pub fn table_join(&mut self) -> JsonValue {
let load = self.request["load"].as_str().unwrap();
let limit = self.request["limit"].as_i32().unwrap();
let (total, data) = self.clone().select();
let mut table = object! {};
table["total_page"] = JsonValue::from((total as f64 / limit as f64).ceil() as i64);
table["total_data"] = total.into();
table["data"] = data.clone();
if load == "col" {
table["col"] = self.clone().get_columns();
table["query_fields"] = self.query_fields();
table["filter_title"] = self.search_title().into();
}
table
}
}