export
parent
30ae8b76b6
commit
2442599757
57
app.py
57
app.py
|
|
@ -1,9 +1,11 @@
|
|||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi import FastAPI, HTTPException, File, UploadFile
|
||||
from pydantic import BaseModel
|
||||
import sqlite3
|
||||
import datetime
|
||||
import csv
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
import io
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
@ -162,6 +164,57 @@ def delete_install(install_id: int):
|
|||
raise HTTPException(status_code=404, detail="Запись не найдена")
|
||||
return {"status": "success"}
|
||||
|
||||
# --- 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
|
||||
""")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
output = io.StringIO()
|
||||
writer = csv.writer(output, lineterminator='\n')
|
||||
writer.writerow(['ID подключения', 'Имя компьютера', 'Время установки', 'Папка', 'Протокол'])
|
||||
for row in rows:
|
||||
writer.writerow(row)
|
||||
|
||||
headers = {
|
||||
'Content-Disposition': 'attachment; filename="rustdesk_data.csv"',
|
||||
'Content-Type': 'text/csv'
|
||||
}
|
||||
return StreamingResponse(iter([output.getvalue()]), headers=headers)
|
||||
|
||||
@app.post("/api/import/csv")
|
||||
async def import_csv(file: UploadFile = File(...)):
|
||||
try:
|
||||
contents = await file.read()
|
||||
csv_data = io.StringIO(contents.decode('utf-8'))
|
||||
reader = csv.DictReader(csv_data)
|
||||
|
||||
for row in reader:
|
||||
rust_id = row['ID подключения']
|
||||
computer_name = row['Имя компьютера']
|
||||
install_time = row['Время установки']
|
||||
folder_name = row['Папка']
|
||||
protocol = row['Протокол'] or 'rustdesk'
|
||||
|
||||
# Получаем или создаем ID папки
|
||||
cursor.execute("SELECT id FROM folders WHERE name = ?", (folder_name,))
|
||||
folder = cursor.fetchone()
|
||||
folder_id = folder[0] if folder else unsorted_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))
|
||||
|
||||
conn.commit()
|
||||
return {"status": "success", "message": "Данные успешно импортированы"}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=f"Ошибка импорта: {str(e)}")
|
||||
|
||||
# CORS
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
app.add_middleware(
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
.sort-arrow { font-size: 12px; margin-left: 5px; }
|
||||
.protocol-icon { margin-right: 5px; height: 16px; width: 16px; vertical-align: middle; }
|
||||
.connection-link { color: blue; text-decoration: underline; cursor: pointer; }
|
||||
#import-form { margin-top: 10px; }
|
||||
#import-file { display: none; }
|
||||
#import-label { cursor: pointer; background: #007bff; color: white; padding: 5px 10px; border-radius: 5px; }
|
||||
#import-label:hover { background: #0056b3; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -41,6 +45,13 @@
|
|||
<input type="radio" id="search-all" name="search-scope" value="all">
|
||||
<label for="search-all">Все папки</label>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<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])">
|
||||
<label for="import-file" id="import-label">Импорт CSV</label>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<h2>Добавить запись</h2>
|
||||
|
|
@ -344,6 +355,32 @@
|
|||
window.location.href = link;
|
||||
}
|
||||
}
|
||||
|
||||
function exportCSV() {
|
||||
window.location.href = `${API_URL}/export/csv`;
|
||||
}
|
||||
|
||||
function importCSV(file) {
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
$.ajax({
|
||||
url: `${API_URL}/import/csv`,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (response) {
|
||||
alert(response.message);
|
||||
loadInstalls(selectedFolderId);
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
alert(`Ошибка импорта: ${xhr.responseJSON.detail || error}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue