Можно смотреть бесконечно на три вещи

По цене двух
master
Алексей Алексей 2026-05-22 10:44:20 +10:00
parent fe0c9ff86c
commit b44669e3ac
3 changed files with 133 additions and 76 deletions

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use egui::mutex::RwLock; use egui::mutex::RwLock;
use egui_dock::{DockArea, Style, TabViewer}; use egui_dock::{DockArea, Style, TabViewer};
use sqlx::{Connection, MySqlConnection, MySqlPool}; use sqlx::{Connection, MySqlConnection, MySqlPool};
use crate::{database::DBOperator, models::{self, Position, Salary, Worker}}; use crate::{database::DBOperator, models::{self, Equipment, Position, Salary, Worker}};
static TABS_CAN_BE_WINDOWS: bool = false; static TABS_CAN_BE_WINDOWS: bool = false;
@ -85,7 +85,7 @@ impl eframe::App for App{
struct MainTabViewer { struct MainTabViewer {
positions: Arc<RwLock<Option<Vec<Position>>>>, positions: Arc<RwLock<Option<Vec<Position>>>>,
workers: Arc<RwLock<Option<Vec<Worker>>>>, workers: Arc<RwLock<Option<Vec<Worker>>>>,
equipment: std::vec::Vec<crate::models::Equipment>, equipment: Arc<RwLock<Option<Vec<Equipment>>>>,
db_oper: DBOperator, db_oper: DBOperator,
worker_tabs: WorkerTabViewer, worker_tabs: WorkerTabViewer,
worker_tree: egui_dock::DockState<Tab>, worker_tree: egui_dock::DockState<Tab>,
@ -94,21 +94,24 @@ struct MainTabViewer {
impl Default for MainTabViewer{ impl Default for MainTabViewer{
fn default() -> Self { fn default() -> Self {
let db_oper = DBOperator::new();
let rt = tokio::runtime::Runtime::new().unwrap(); let rt = tokio::runtime::Runtime::new().unwrap();
let db_oper = rt.block_on(async{
DBOperator::new().await
});
Self{ Self{
positions: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_position().await.unwrap()})))), positions: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_position().await.unwrap()})))),
workers: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_workers().await.unwrap()})))), workers: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_workers().await.unwrap()})))),
equipment: vec![models::Equipment::default()], equipment: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_equipment().await.unwrap()})))),
db_oper, db_oper,
worker_tabs: WorkerTabViewer::default(), worker_tabs: WorkerTabViewer::default(),
worker_tree: egui_dock::DockState::new(vec![ worker_tree: egui_dock::DockState::new(vec![
Tab{ Tab{
title:"ГойдаЗов".to_owned(), title:"Работники".to_owned(),
tab_type:TabTypes::WorkerList, tab_type:TabTypes::WorkerList,
}, },
Tab{ Tab{
title:"Еееееее".to_owned(), title:"Должности".to_owned(),
tab_type:TabTypes::WorkerPosition, tab_type:TabTypes::WorkerPosition,
} }
]), ]),
@ -139,13 +142,21 @@ impl MainTabViewer{
// table = table.sense(egui::Sense::click()); // table = table.sense(egui::Sense::click());
//Это таблицы, с ними надо разобраться! //Это таблицы, с ними надо разобраться!
for eq in self.equipment.clone() { for eq in self.equipment.read().clone().unwrap().iter() {
ui.push_id(&eq.name, |ui|{ let id = ui.make_persistent_id(format!("{}:{}", eq.id, eq.name));
ui.push_id(&id, |ui|{
egui::CollapsingHeader::new(&eq.name) egui::CollapsingHeader::new(&eq.name)
.default_open(false) .default_open(false)
.show(ui, |ui|{ .show(ui, |ui|{
ui.label(eq.inv_number); ui.horizontal(|ui|{
ui.label(eq.worker.full_name); ui.monospace("Инвентарный номер: ");
ui.label(&eq.inv_number);
});
ui.horizontal(|ui|{
ui.monospace("Ответственный: ");
ui.label(&eq.worker.full_name);
});
}); });
}); });
@ -153,6 +164,68 @@ impl MainTabViewer{
} }
fn show_worker(&mut self, ui: &mut egui::Ui){
let id = ui.make_persistent_id("WorkerMenu");
DockArea::new(&mut self.worker_tree)
.style(Style::from_egui(ui.style().as_ref()))
.id(id)
.show_inside(ui, &mut self.worker_tabs);
}
fn show_material(&mut self, ui: &mut egui::Ui){
ui.label("Сырьё короче да");
}
fn show_salary(&mut self, ui: &mut egui::Ui){
}
}
impl egui_dock::TabViewer for MainTabViewer{
type Tab = Tab;
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText{
(&*tab.title).into()
}
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab){
match &tab.tab_type{
TabTypes::Equipment => {
&self.show_equipment(ui);
},
TabTypes::Worker => {
&self.show_worker(ui);
},
TabTypes::Salary => {
&self.show_salary(ui);
},
TabTypes::Material => {
&self.show_material(ui);
},
_ =>{
ui.label("This is not");
}
}
}
fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool {
TABS_CAN_BE_WINDOWS
}
fn is_closeable(&self, _tab: &Self::Tab) -> bool {
false
}
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
egui::Id::new(&tab.title)
}
}
struct WorkerTabViewer{
workers: Arc<RwLock<Option<Vec<Worker>>>>,
positions: Arc<RwLock<Option<Vec<Position>>>>,
}
impl WorkerTabViewer{
fn show_worker(&mut self, ui: &mut egui::Ui){ fn show_worker(&mut self, ui: &mut egui::Ui){
ui.horizontal(|ui|{ ui.horizontal(|ui|{
if ui.button("Добавить").clicked() { if ui.button("Добавить").clicked() {
@ -187,8 +260,6 @@ impl MainTabViewer{
}); });
} }
} }
fn show_position(&mut self, ui: &mut egui::Ui){ fn show_position(&mut self, ui: &mut egui::Ui){
for eq in self.positions.read().clone().unwrap().iter(){ for eq in self.positions.read().clone().unwrap().iter(){
@ -202,61 +273,6 @@ impl MainTabViewer{
}); });
} }
} }
fn show_salary(&mut self, ui: &mut egui::Ui){
let id = ui.make_persistent_id("BotMenu");
DockArea::new(&mut self.worker_tree)
.style(Style::from_egui(ui.style().as_ref()))
.id(id)
.show_inside(ui, &mut self.worker_tabs);
}
fn show_material(&mut self, ui: &mut egui::Ui){
ui.label("Сырьё короче да");
}
}
impl egui_dock::TabViewer for MainTabViewer{
type Tab = Tab;
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText{
(&*tab.title).into()
}
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab){
match &tab.tab_type{
TabTypes::Equipment => {
&self.show_equipment(ui);
},
TabTypes::Worker => {
&self.show_worker(ui);
},
TabTypes::Salary => {
&self.show_salary(ui);
},
TabTypes::Material => {
&self.show_material(ui);
},
TabTypes::Position =>{
&self.show_position(ui);
}
_ =>{
ui.label("This is not");
}
}
}
fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool {
TABS_CAN_BE_WINDOWS
}
fn is_closeable(&self, _tab: &Self::Tab) -> bool {
false
}
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
egui::Id::new(&tab.title)
}
}
#[derive(Default)]
struct WorkerTabViewer{
} }
impl egui_dock::TabViewer for WorkerTabViewer{ impl egui_dock::TabViewer for WorkerTabViewer{
@ -265,9 +281,28 @@ impl egui_dock::TabViewer for WorkerTabViewer{
(&*tab.title).into() (&*tab.title).into()
} }
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) { fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
match &tab.tab_type{
TabTypes::WorkerList => self.show_worker(ui),
TabTypes::WorkerPosition => self.show_position(ui),
_ => {ui.label("Nope");},
}
} }
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id { fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
egui::Id::new(&tab.title) egui::Id::new(&tab.title)
} }
fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool {
TABS_CAN_BE_WINDOWS
}
fn is_closeable(&self, _tab: &Self::Tab) -> bool {
false
}
}
impl Default for WorkerTabViewer{
fn default() -> Self {
let rt = tokio::runtime::Runtime::new().unwrap();
let db_oper = rt.block_on(async{DBOperator::new().await});
Self { workers: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_workers().await.unwrap()})))) ,
positions: Arc::new(RwLock::new(Option::Some(rt.block_on(async{db_oper.get_position().await.unwrap()})))),
}
}
} }

View File

@ -9,23 +9,21 @@ use std::env;
use crate::models::*; use crate::models::*;
pub struct DBOperator{ pub struct DBOperator{
connection_string: String, pool: MySqlPool,
} }
impl DBOperator{ impl DBOperator{
pub fn new() -> Self{ pub async fn new() -> Self{
dotenv_override().ok(); dotenv_override().ok();
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!"); let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!");
Self{connection_string:db_url} Self{pool: MySqlPool::connect(&db_url).await.unwrap()}
} }
pub async fn get_position(&self) -> Result<Vec<Position>, sqlx::Error>{ pub async fn get_position(&self) -> Result<Vec<Position>, sqlx::Error>{
let pool = MySqlPool::connect(&self.connection_string).await?; let rets: Vec<Position> = sqlx::query_as:: <_, Position>("SELECT * FROM `position`").fetch_all(&self.pool).await?;
let rets: Vec<Position> = sqlx::query_as:: <_, Position>("SELECT * FROM `position`").fetch_all(&pool).await?;
Ok(rets) Ok(rets)
} }
pub async fn get_workers(&self) -> Result<Vec<Worker>, sqlx::Error>{ pub async fn get_workers(&self) -> Result<Vec<Worker>, sqlx::Error>{
let pool = MySqlPool::connect(&self.connection_string).await?; let pre_rets: Vec<WorkerRow> = sqlx::query_as::<_, WorkerRow>("SELECT * FROM `worker`").fetch_all(&self.pool).await?;
let pre_rets: Vec<WorkerRow> = sqlx::query_as::<_, WorkerRow>("SELECT * FROM `worker`").fetch_all(&pool).await?;
let mut rets:Vec<Worker> = Vec::new(); let mut rets:Vec<Worker> = Vec::new();
let pos = self.get_position().await.unwrap(); let pos = self.get_position().await.unwrap();
for worker in pre_rets{ for worker in pre_rets{
@ -40,6 +38,22 @@ impl DBOperator{
} }
Ok(rets) Ok(rets)
} }
pub async fn get_equipment(&self) -> Result<Vec<Equipment>,sqlx::Error>{
let pre_rets = sqlx::query_as::<_, EquipmentRow>("SELECT * FROM `equipment`").fetch_all(&self.pool).await?;
let mut rets: Vec<Equipment> = Vec::new();
let workers = self.get_workers().await?;
for eq in pre_rets{
let mut pworker = Worker::default();
for worker in workers.clone(){
if worker.id == eq.worker_id{
pworker = worker.clone();
break;
}
}
rets.push(Equipment { id: eq.id, name: eq.name, inv_number: eq.inv_number, maintenance_date: eq.maintenance_date, worker: pworker });
}
Ok(rets)
}
} }

View File

@ -38,6 +38,14 @@ pub struct Equipment{
pub maintenance_date: chrono::DateTime<chrono::Local>, pub maintenance_date: chrono::DateTime<chrono::Local>,
pub worker: Worker, pub worker: Worker,
} }
#[derive(sqlx::FromRow)]
pub struct EquipmentRow{
pub id: i32,
pub name: String,
pub inv_number: String,
pub maintenance_date: chrono::DateTime<chrono::Local>,
pub worker_id: i32,
}
pub struct Material{ pub struct Material{
id: i32, id: i32,
name: String, name: String,