diff --git a/app.py b/app.py index 2c26ecb..95fd0f1 100644 --- a/app.py +++ b/app.py @@ -3,6 +3,7 @@ from pydantic import BaseModel import sqlite3 import datetime import csv +import markdown from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse, StreamingResponse import io @@ -19,8 +20,11 @@ columns = [row[1] for row in cursor.fetchall()] if 'protocol' not in columns: cursor.execute("ALTER TABLE installs ADD COLUMN protocol TEXT DEFAULT 'rustdesk'") conn.commit() +if 'note' not in columns: + cursor.execute("ALTER TABLE installs ADD COLUMN note TEXT DEFAULT ''") + conn.commit() -# Создаем таблицы (добавляем поле protocol, если таблицы нет) +# Создаем таблицы (добавляем поле protocol и note, если таблицы нет) cursor.execute(""" CREATE TABLE IF NOT EXISTS folders ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -37,6 +41,7 @@ CREATE TABLE IF NOT EXISTS installs ( install_time TEXT, folder_id INTEGER, protocol TEXT DEFAULT 'rustdesk', + note TEXT DEFAULT '', FOREIGN KEY (folder_id) REFERENCES folders(id) ) """) @@ -66,6 +71,7 @@ class InstallData(BaseModel): install_time: str | None = None # Принимаем строку в формате YYYY-MM-DD HH:MM:SS folder_id: int | None = None protocol: str | None = 'rustdesk' # По умолчанию RustDesk + note: str | None = '' # Новая заметка, по умолчанию пустая # Монтируем папки templates и icons как статические файлы app.mount("/templates", StaticFiles(directory="templates"), name="templates") @@ -116,7 +122,7 @@ def delete_folder(folder_id: int): @app.get("/api/installs") def get_installs(): cursor.execute(""" - SELECT i.id, i.rust_id, i.computer_name, i.install_time, i.folder_id, f.name as folder_name, i.protocol + SELECT i.id, i.rust_id, i.computer_name, i.install_time, i.folder_id, f.name as folder_name, i.protocol, i.note FROM installs i LEFT JOIN folders f ON i.folder_id = f.id """) @@ -139,7 +145,7 @@ def get_installs(): return [{"id": row[0], "rust_id": row[1], "computer_name": row[2], "install_time": format_time(row[3]), - "folder_id": row[4], "folder_name": row[5], "protocol": row[6]} + "folder_id": row[4], "folder_name": row[5], "protocol": row[6], "note": row[7]} for row in rows] @app.post("/api/install") @@ -147,14 +153,15 @@ def add_install(data: InstallData): install_time = data.install_time or datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Форматируем в читаемый формат folder_id = data.folder_id if data.folder_id is not None else unsorted_folder_id protocol = data.protocol or 'rustdesk' # По умолчанию RustDesk для POST-запросов - cursor.execute("INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol) VALUES (?, ?, ?, ?, ?)", - (data.rust_id, data.computer_name, install_time, folder_id, protocol)) + note = data.note or '' # Новая заметка, по умолчанию пустая + cursor.execute("INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol, note) VALUES (?, ?, ?, ?, ?, ?)", + (data.rust_id, data.computer_name, install_time, folder_id, protocol, note)) conn.commit() return {"status": "success"} @app.put("/api/install/{install_id}") def update_install(install_id: int, data: InstallData): - cursor.execute("SELECT rust_id, computer_name, install_time, folder_id, protocol FROM installs WHERE id = ?", (install_id,)) + cursor.execute("SELECT rust_id, computer_name, install_time, folder_id, protocol, note FROM installs WHERE id = ?", (install_id,)) current = cursor.fetchone() if not current: raise HTTPException(status_code=404, detail="Запись не найдена") @@ -164,6 +171,7 @@ def update_install(install_id: int, data: InstallData): new_install_time = data.install_time if data.install_time is not None else current[2] new_folder_id = data.folder_id if data.folder_id is not None else current[3] new_protocol = data.protocol if data.protocol is not None else current[4] + new_note = data.note if data.note is not None else current[5] # Форматируем время, если оно предоставлено в запросе if new_install_time: @@ -177,9 +185,9 @@ def update_install(install_id: int, data: InstallData): cursor.execute(""" UPDATE installs - SET rust_id = ?, computer_name = ?, install_time = ?, folder_id = ?, protocol = ? + SET rust_id = ?, computer_name = ?, install_time = ?, folder_id = ?, protocol = ?, note = ? WHERE id = ? - """, (new_rust_id, new_computer_name, new_install_time, new_folder_id, new_protocol, install_id)) + """, (new_rust_id, new_computer_name, new_install_time, new_folder_id, new_protocol, new_note, install_id)) conn.commit() return {"status": "success"} @@ -196,14 +204,14 @@ def delete_install(install_id: int): async def export_csv(folder_id: int | None = Query(None, description="ID папки для экспорта, если None - экспортировать все папки")): if folder_id: cursor.execute(""" - SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol + SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol, i.note FROM installs i LEFT JOIN folders f ON i.folder_id = f.id WHERE i.folder_id = ? """, (folder_id,)) else: cursor.execute(""" - SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol + SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol, i.note FROM installs i LEFT JOIN folders f ON i.folder_id = f.id """) @@ -211,11 +219,11 @@ async def export_csv(folder_id: int | None = Query(None, description="ID пап output = io.StringIO() writer = csv.writer(output, lineterminator='\n') - writer.writerow(['ID подключения', 'Имя компьютера', 'Время установки', 'Папка', 'Протокол']) + writer.writerow(['ID подключения', 'Имя компьютера', 'Время установки', 'Папка', 'Протокол', 'Заметка']) for row in rows: # Обработка времени в разных форматах install_time = format_time(row[2]) if row[2] else "" - writer.writerow([row[0], row[1], install_time, row[3], row[4]]) + writer.writerow([row[0], row[1], install_time, row[3], row[4], row[5]]) headers = { 'Content-Disposition': 'attachment; filename="rustdesk_data.csv"', @@ -253,6 +261,7 @@ async def import_csv(file: UploadFile = File(...), folder_id: int | None = Query install_time = row['Время установки'] folder_name = row.get('Папка', None) protocol = row.get('Протокол', 'rustdesk') + note = row.get('Заметка', '') # Проверяем, существует ли запись с таким rust_id cursor.execute("SELECT id FROM installs WHERE rust_id = ?", (rust_id,)) @@ -282,9 +291,9 @@ async def import_csv(file: UploadFile = File(...), folder_id: int | None = Query folder_id = target_folder_id cursor.execute(""" - INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol) - VALUES (?, ?, ?, ?, ?) - """, (rust_id, computer_name, install_time, folder_id, protocol)) + INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol, note) + VALUES (?, ?, ?, ?, ?, ?) + """, (rust_id, computer_name, install_time, folder_id, protocol, note)) conn.commit() return {"status": "success", "message": "Данные успешно импортированы"} diff --git a/templates/index.html b/templates/index.html index 32b0dcb..c287b98 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,6 +5,7 @@