Загрузка данных


DB.CS

using MySql.Data.MySqlClient;
using System;
using System.Data;

namespace demo
{
    public static class Db
    {
        public static string ConnStr = "server=localhost;user=root;password=;database=demo;charset=utf8;";

        public static DataTable Select(string sql, params MySqlParameter[] parameters)
        {
            MySqlConnection conn = new MySqlConnection(ConnStr);
            MySqlDataAdapter adapter = new MySqlDataAdapter(sql, conn);

            foreach (MySqlParameter p in parameters)
                adapter.SelectCommand.Parameters.Add(p);

            DataTable table = new DataTable();
            adapter.Fill(table);
            return table;
        }

        public static int Execute(string sql, params MySqlParameter[] parameters)
        {
            MySqlConnection conn = new MySqlConnection(ConnStr);
            MySqlCommand cmd = new MySqlCommand(sql, conn);

            foreach (MySqlParameter p in parameters)
                cmd.Parameters.Add(p);

            conn.Open();
            int result = cmd.ExecuteNonQuery();
            conn.Close();
            return result;
        }

        public static object Scalar(string sql)
        {
            MySqlConnection conn = new MySqlConnection(ConnStr);
            MySqlCommand cmd = new MySqlCommand(sql, conn);
            conn.Open();
            object result = cmd.ExecuteScalar();
            conn.Close();
            return result;
        }

        public static MySqlParameter P(string name, object value)
        {
            return new MySqlParameter(name, value ?? DBNull.Value);
        }
    }
}


FORM1.CS

using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace demo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.Text = Program.AppTitle;

            Label lblTitle = new Label
            {
                Text = Program.AppTitle,
                Font = new Font("Segoe UI", 24, FontStyle.Bold),
                ForeColor = Color.DarkBlue,
                AutoSize = true,
                Location = new Point(50, 30)
            };
            this.Controls.Add(lblTitle);

            // ---- НАСТРОЙКА ЦВЕТОВ (закомментировано) ----
            // this.BackColor = Color.FromArgb(240, 248, 255); // #F0F8FF (AliceBlue)
            // lblTitle.ForeColor = Color.FromArgb(25, 25, 112); // #191970 (MidnightBlue)
            // btnLogin.BackColor = Color.FromArgb(255, 215, 0); // #FFD700 (Gold)

            // -------------------------------------------

            Button btnGuest = new Button
            {
                Text = "Войти как гость",
                Location = new Point(btnLogin.Location.X, btnLogin.Location.Y + btnLogin.Height + 10),
                Size = btnLogin.Size,
                BackColor = Color.LightGray,
                FlatStyle = FlatStyle.Flat
            };
            btnGuest.Click += BtnGuest_Click;
            this.Controls.Add(btnGuest);
            // btnGuest.BackColor = Color.FromArgb(189, 042, 171); // #D3D3D3 (LightGray)

            AcceptButton = btnLogin;
        }

        private void BtnGuest_Click(object sender, EventArgs e)
        {
            string role = "Client";
            string fio = "Гость";
            MainForm f = new MainForm(role, fio);
            f.FormClosed += delegate { Close(); };
            f.Show();
            Hide();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            if (txtLogin.Text == "" || txtPassword.Text == "")
            {
                MessageBox.Show("Введите логин и пароль");
                return;
            }

            try
            {
                string sql = "SELECT `Роль` AS role_id, `ФИО` AS fio FROM import_users " +
                             "WHERE `Логин`=@login AND `Пароль`=@pass LIMIT 1";

                DataTable users = Db.Select(sql,
                    Db.P("@login", txtLogin.Text.Trim()),
                    Db.P("@pass", txtPassword.Text.Trim()));

                if (users.Rows.Count == 0)
                {
                    MessageBox.Show("Неверный логин или пароль");
                    return;
                }

                string role = users.Rows[0]["role_id"].ToString();
                string fio = users.Rows[0]["fio"].ToString();

                MainForm f = new MainForm(role, fio);
                f.FormClosed += delegate { Close(); };
                f.Show();
                Hide();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка подключения к базе:\n" + ex.Message);
            }
        }

        private void Form1_Load(object sender, EventArgs e) { }
    }
}

MAINFORM.CS

using MySql.Data.MySqlClient;
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace demo
{
    public partial class MainForm : Form
    {
        string role;
        string fio;
        string mode = "products";

        public MainForm(string userRole, string userFio)
        {
            InitializeComponent();

            this.Text = Program.AppTitle;

            role = userRole;
            fio = userFio;
            lblUser.Text = fio + " (" + role + ")";

            Label lblMainTitle = new Label
            {
                Text = Program.AppTitle,
                Font = new Font("Segoe UI", 18, FontStyle.Bold),
                ForeColor = Color.DarkGreen,
                AutoSize = true,
                Location = new Point(10, 5)
            };
            topPanel.Controls.Add(lblMainTitle);
            lblUser.Location = new Point(this.Width - lblUser.Width - 20, 5);
            lblUser.Anchor = AnchorStyles.Top | AnchorStyles.Right;

            // ---- НАСТРОЙКА ЦВЕТОВ (закомментировано) ----
            // this.BackColor = Color.LightYellow;
            // topPanel.BackColor = Color.LightBlue;
            // grid.BackgroundColor = Color.WhiteSmoke;
            // btnTovar.BackColor = Color.LightGreen;
            // btnUsers.BackColor = Color.LightCoral;
            // -------------------------------------------

            btnZakaz.Visible = false;
            btnAdres.Visible = false;

            topPanel.Dock = DockStyle.None;
            grid.Dock = DockStyle.None;
            panelProduct.Dock = DockStyle.None;

            topPanel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
            grid.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            panelProduct.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

            Resize += delegate { FixLayout(); };

            btnUsers.Visible = IsAdmin();
            panelProduct.Visible = CanEditProducts();
            LoadProducts();
            FixLayout();

            grid.RowPrePaint += Grid_RowPrePaint;
        }

        private void Grid_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            // Применяем раскраску только в режиме товаров
            if (mode != "products") return;

            if (grid.Rows[e.RowIndex].IsNewRow) return;

            // Проверяем, существуют ли нужные колонки (защита от ошибок в других таблицах)
            if (!grid.Columns.Contains("Количество на складе") || !grid.Columns.Contains("Скидка"))
                return;

            DataGridViewRow row = grid.Rows[e.RowIndex];

            // Получаем количество на складе
            object qtyObj = row.Cells["Количество на складе"].Value;
            int quantity = (qtyObj != DBNull.Value && qtyObj != null) ? Convert.ToInt32(qtyObj) : 0;

            // Получаем скидку
            object discountObj = row.Cells["Скидка"].Value;
            int discount = (discountObj != DBNull.Value && discountObj != null) ? Convert.ToInt32(discountObj) : 0;

            if (quantity == 0)
            {
                // Нет в наличии – красная строка
                row.DefaultCellStyle.BackColor = Color.LightCoral;
                row.DefaultCellStyle.ForeColor = Color.Black;
            }
            else if (discount > 20)
            {
                // Скидка больше 20% – зелёная строка
                row.DefaultCellStyle.BackColor = Color.LightGreen;
                row.DefaultCellStyle.ForeColor = Color.Black;
            }
            else
            {
                // Обычный цвет
                row.DefaultCellStyle.BackColor = grid.DefaultCellStyle.BackColor;
                row.DefaultCellStyle.ForeColor = grid.DefaultCellStyle.ForeColor;
            }
        }

        bool IsAdmin() => role == "Admin";
        bool IsManager() => role == "Manager";
        bool IsClient() => role == "Client";
        bool CanEditProducts() => IsAdmin() || IsManager();

        void FixLayout()
        {
            int bottom = panelProduct.Visible ? panelProduct.Height : 0;

            topPanel.Location = new Point(0, 0);
            topPanel.Width = ClientSize.Width;

            grid.Location = new Point(0, topPanel.Height);
            grid.Size = new Size(ClientSize.Width, ClientSize.Height - topPanel.Height - bottom);

            panelProduct.Location = new Point(0, ClientSize.Height - panelProduct.Height);
            panelProduct.Width = ClientSize.Width;

            lblUser.Location = new Point(this.ClientSize.Width - lblUser.Width - 20, 5);
        }

        void LoadGrid(string sql, params MySqlParameter[] parameters)
        {
            DataTable table = Db.Select(sql, parameters);
            grid.DataSource = table;
            grid.AllowUserToAddRows = false;
            grid.AllowUserToDeleteRows = false;
            grid.ReadOnly = true;
            grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
            lblCount.Text = "Строк: " + table.Rows.Count;
        }

        string SearchText() => "%" + txtSearch.Text.Trim() + "%";

        void LoadProducts()
        {
            mode = "products";
            panelProduct.Visible = CanEditProducts();
            FixLayout();

            string sql = @"SELECT 
    b.ID,
    b.`Название`,
    b.`Год издания`,
    b.`Цена`,
    b.`Количество на складе`,
    b.`Скидка`,
    b.`ISBN`,
    b.`Путь к обложке`,
    b.`Количество страниц`,
    b.`Описание`,
    a.`ФИО автора` AS Автор,
    g.`Наименование жанра` AS Жанр,
    p.`Наименование издательства` AS Издательство
FROM import_books b
LEFT JOIN import_authors a ON b.`АвторID` = a.ID
LEFT JOIN import_genres g ON b.`ЖанрID` = g.ID
LEFT JOIN import_publishers p ON b.`ИздательствоID` = p.ID
WHERE b.`Название` IS NOT NULL";

            if (txtSearch.Text.Trim() != "")
            {
                sql += " AND (b.`Название` LIKE @q OR b.`ISBN` LIKE @q OR b.`Описание` LIKE @q OR a.`ФИО автора` LIKE @q OR g.`Наименование жанра` LIKE @q)";
                LoadGrid(sql, Db.P("@q", SearchText()));
            }
            else
            {
                LoadGrid(sql);
            }
        }

        void LoadUsers()
        {
            if (!IsAdmin())
            {
                MessageBox.Show("Пользователей может смотреть только администратор");
                return;
            }

            mode = "users";
            panelProduct.Visible = false;
            FixLayout();

            string sql = "SELECT ID, `Роль`, `ФИО`, `Логин`, `Пароль` FROM import_users";
            if (txtSearch.Text.Trim() != "")
            {
                sql += " WHERE `Роль` LIKE @q OR `ФИО` LIKE @q OR `Логин` LIKE @q";
                LoadGrid(sql, Db.P("@q", SearchText()));
            }
            else
            {
                LoadGrid(sql);
            }
        }

        void Reload()
        {
            if (mode == "products") LoadProducts();
            if (mode == "users") LoadUsers();
        }

        int SelectedProductId()
        {
            if (grid.CurrentRow == null)
                throw new Exception("Выберите товар в таблице");

            return Convert.ToInt32(grid.CurrentRow.Cells["ID"].Value);
        }

        bool ProductFieldsOk()
        {
            if (txtName.Text == "" || txtPrice.Text == "" || txtQty.Text == "")
            {
                MessageBox.Show("Заполните название, цену и количество");
                return false;
            }
            return true;
        }

        void ClearProductFields()
        {
            txtArticle.Clear();
            txtName.Clear();
            txtPrice.Clear();
            txtQty.Clear();
            txtSupplier.Clear();
            txtCategory.Clear();
            txtDescription.Clear();
        }

        private void btnTovar_Click(object sender, EventArgs e)
        {
            txtSearch.Clear();
            LoadProducts();
        }

        private void btnZakaz_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Функционал заказов недоступен");
        }

        private void btnAdres_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Функционал адресов недоступен");
        }

        private void btnUsers_Click(object sender, EventArgs e)
        {
            txtSearch.Clear();
            LoadUsers();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            Reload();
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            txtSearch.Clear();
            Reload();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        string Cell(string column)
        {
            if (grid.CurrentRow == null || !grid.Columns.Contains(column))
                return "";
            object value = grid.CurrentRow.Cells[column].Value;
            return value == null ? "" : value.ToString();
        }

        private void grid_SelectionChanged(object sender, EventArgs e)
        {
            if (mode != "products" || grid.CurrentRow == null || grid.CurrentRow.IsNewRow)
                return;

            txtName.Text = Cell("Название");
            txtPrice.Text = Cell("Цена");
            txtQty.Text = Cell("Количество на складе");
            txtDescription.Text = Cell("Описание");
            txtArticle.Text = Cell("ISBN");
            txtSupplier.Text = Cell("Издательство");
            txtCategory.Text = Cell("Жанр");
        }

        private void btnClearProduct_Click(object sender, EventArgs e)
        {
            ClearProductFields();
        }

        private void btnAddProduct_Click(object sender, EventArgs e)
        {
            if (!ProductFieldsOk()) return;

            try
            {
                int newId = Convert.ToInt32(Db.Scalar("SELECT IFNULL(MAX(ID),0)+1 FROM import_books"));
                string sql = @"INSERT INTO import_books 
                    (ID, `Название`, `АвторID`, `ЖанрID`, `ИздательствоID`, `Год издания`, `Цена`, 
                     `Количество на складе`, `Скидка`, `ISBN`, `Путь к обложке`, `Количество страниц`, `Описание`) 
                    VALUES (@id, @name, 1, 1, 1, 2023, @price, @qty, 0, @isbn, '', 0, @desc)";

                Db.Execute(sql,
                    Db.P("@id", newId),
                    Db.P("@name", txtName.Text),
                    Db.P("@price", txtPrice.Text),
                    Db.P("@qty", txtQty.Text),
                    Db.P("@isbn", txtArticle.Text),
                    Db.P("@desc", txtDescription.Text));

                MessageBox.Show("Книга добавлена (автор, жанр, издательство установлены по умолчанию)");
                LoadProducts();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка добавления:\n" + ex.Message);
            }
        }

        private void btnUpdateProduct_Click(object sender, EventArgs e)
        {
            if (!ProductFieldsOk()) return;

            try
            {
                string sql = @"UPDATE import_books SET 
                    `Название` = @name,
                    `Цена` = @price,
                    `Количество на складе` = @qty,
                    `ISBN` = @isbn,
                    `Описание` = @desc
                    WHERE ID = @id";

                Db.Execute(sql,
                    Db.P("@id", SelectedProductId()),
                    Db.P("@name", txtName.Text),
                    Db.P("@price", txtPrice.Text),
                    Db.P("@qty", txtQty.Text),
                    Db.P("@isbn", txtArticle.Text),
                    Db.P("@desc", txtDescription.Text));

                MessageBox.Show("Книга обновлена");
                LoadProducts();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка обновления:\n" + ex.Message);
            }
        }

        private void btnDeleteProduct_Click(object sender, EventArgs e)
        {
            try
            {
                DialogResult result = MessageBox.Show("Удалить выбранную книгу?", "Подтверждение",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (result != DialogResult.Yes) return;

                Db.Execute("DELETE FROM import_books WHERE ID=@id", Db.P("@id", SelectedProductId()));
                MessageBox.Show("Книга удалена");
                ClearProductFields();
                LoadProducts();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ошибка удаления:\n" + ex.Message);
            }
        }

        private void MainForm_Load(object sender, EventArgs e) { }

        private void txtSupplier_TextChanged(object sender, EventArgs e)
        {

        }
    }
}

PROGRAM.CS

using System;
using System.Windows.Forms;

namespace demo
{
    internal static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

        // Общее название приложения – измените здесь один раз для всех форм
        public static string AppTitle = "Книжный мир";
    }
}