export check
parent
270fa3ace5
commit
9360a1a671
44
app.py
44
app.py
|
|
@ -1,4 +1,4 @@
|
|||
from fastapi import FastAPI, HTTPException, File, UploadFile
|
||||
from fastapi import FastAPI, HTTPException, File, UploadFile, Query
|
||||
from pydantic import BaseModel
|
||||
import sqlite3
|
||||
import datetime
|
||||
|
|
@ -166,12 +166,20 @@ def delete_install(install_id: int):
|
|||
|
||||
# --- CSV Export/Import API ---
|
||||
@app.get("/api/export/csv")
|
||||
async def export_csv():
|
||||
cursor.execute("""
|
||||
SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol
|
||||
FROM installs i
|
||||
LEFT JOIN folders f ON i.folder_id = f.id
|
||||
""")
|
||||
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
|
||||
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
|
||||
FROM installs i
|
||||
LEFT JOIN folders f ON i.folder_id = f.id
|
||||
""")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
output = io.StringIO()
|
||||
|
|
@ -187,23 +195,33 @@ async def export_csv():
|
|||
return StreamingResponse(iter([output.getvalue()]), headers=headers)
|
||||
|
||||
@app.post("/api/import/csv")
|
||||
async def import_csv(file: UploadFile = File(...)):
|
||||
async def import_csv(file: UploadFile = File(...), folder_id: int | None = Query(None, description="ID папки для импорта, если None - использовать 'Несортированные'")):
|
||||
try:
|
||||
contents = await file.read()
|
||||
csv_data = io.StringIO(contents.decode('utf-8'))
|
||||
reader = csv.DictReader(csv_data)
|
||||
|
||||
target_folder_id = folder_id if folder_id is not None else unsorted_folder_id
|
||||
|
||||
for row in reader:
|
||||
rust_id = row['ID подключения']
|
||||
computer_name = row['Имя компьютера']
|
||||
install_time = row['Время установки']
|
||||
folder_name = row['Папка']
|
||||
protocol = row['Протокол'] or 'rustdesk'
|
||||
folder_name = row.get('Папка', None)
|
||||
protocol = row.get('Протокол', 'rustdesk')
|
||||
|
||||
# Проверяем, существует ли запись с таким rust_id
|
||||
cursor.execute("SELECT id FROM installs WHERE rust_id = ?", (rust_id,))
|
||||
if cursor.fetchone():
|
||||
continue # Пропускаем дублирующуюся запись
|
||||
|
||||
# Получаем или создаем ID папки
|
||||
cursor.execute("SELECT id FROM folders WHERE name = ?", (folder_name,))
|
||||
folder = cursor.fetchone()
|
||||
folder_id = folder[0] if folder else unsorted_folder_id
|
||||
if folder_name:
|
||||
cursor.execute("SELECT id FROM folders WHERE name = ?", (folder_name,))
|
||||
folder = cursor.fetchone()
|
||||
folder_id = folder[0] if folder else unsorted_folder_id
|
||||
else:
|
||||
folder_id = target_folder_id
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#import-file { display: none; }
|
||||
#import-label { cursor: pointer; background: #007bff; color: white; padding: 5px 10px; border-radius: 5px; }
|
||||
#import-label:hover { background: #0056b3; }
|
||||
.folder-select { margin: 5px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -46,6 +47,9 @@
|
|||
<label for="search-all">Все папки</label>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<select id="folder-select" class="folder-select">
|
||||
<option value="">Все папки</option>
|
||||
</select>
|
||||
<button onclick="exportCSV()">Экспорт CSV</button>
|
||||
<form id="import-form" enctype="multipart/form-data">
|
||||
<input type="file" id="import-file" accept=".csv" onchange="importCSV(this.files[0])">
|
||||
|
|
@ -108,6 +112,13 @@
|
|||
const unsortedFolder = folders.find(f => f.name === 'Несортированные');
|
||||
const unsortedFolderId = unsortedFolder ? unsortedFolder.id : null;
|
||||
|
||||
// Заполняем выпадающий список папок
|
||||
const $folderSelect = $('#folder-select');
|
||||
$folderSelect.append('<option value="">Все папки</option>');
|
||||
folders.forEach(folder => {
|
||||
$folderSelect.append(`<option value="${folder.id}">${folder.name}</option>`);
|
||||
});
|
||||
|
||||
// Инициализация дерева папок
|
||||
$('#folder-tree').jstree({
|
||||
'core': {
|
||||
|
|
@ -357,14 +368,19 @@
|
|||
}
|
||||
|
||||
function exportCSV() {
|
||||
window.location.href = `${API_URL}/export/csv`;
|
||||
const folderId = $('#folder-select').val() || '';
|
||||
window.location.href = `${API_URL}/export/csv?folder_id=${folderId}`;
|
||||
}
|
||||
|
||||
function importCSV(file) {
|
||||
if (!file) return;
|
||||
|
||||
const folderId = $('#folder-select').val() || '';
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
if (folderId) {
|
||||
formData.append('folder_id', folderId);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: `${API_URL}/import/csv`,
|
||||
|
|
|
|||
Loading…
Reference in New Issue