File size: 3,013 Bytes
d7cfbb9
 
 
89336c2
d7cfbb9
 
 
 
89336c2
 
 
 
 
 
 
 
 
 
 
d7cfbb9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6a5c583
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
import os
import auth, storage, ai_search

app = FastAPI(title="云学习平台")

# ── 自动创建 static 目录,避免启动崩溃 ──
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, "static")
os.makedirs(STATIC_DIR, exist_ok=True)

INDEX_PATH = os.path.join(STATIC_DIR, "index.html")
if not os.path.exists(INDEX_PATH):
    with open(INDEX_PATH, "w", encoding="utf-8") as f:
        f.write("<h1>云学习平台已启动</h1><p>请访问 <a href='/docs'>/docs</a></p>")

app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
def startup():
    auth.init_db()
    storage.ensure_bucket()

# ── 用户认证 ──
@app.post("/auth/register")
def register(username: str = Form(...), password: str = Form(...)):
    conn = auth.sqlite3.connect(auth.DB_PATH)
    try:
        conn.execute(
            "INSERT INTO users (username, password_hash, created_at) VALUES (?,?,?)",
            (username, auth.hash_password(password), auth.datetime.now().isoformat())
        )
        conn.commit()
    except auth.sqlite3.IntegrityError:
        raise HTTPException(400, "用户名已存在")
    finally:
        conn.close()
    token = auth.create_access_token({"sub": username})
    return {"access_token": token, "token_type": "bearer"}

@app.post("/auth/login")
def login(username: str = Form(...), password: str = Form(...)):
    conn = auth.sqlite3.connect(auth.DB_PATH)
    row = conn.execute("SELECT password_hash FROM users WHERE username=?", (username,)).fetchone()
    conn.close()
    if not row or not auth.verify_password(password, row[0]):
        raise HTTPException(401, "用户名或密码错误")
    token = auth.create_access_token({"sub": username})
    return {"access_token": token, "token_type": "bearer"}

# ── 文件上传 ──
@app.post("/files/upload")
async def upload(file: UploadFile = File(...), user: str = Depends(auth.get_current_user)):
    content = await file.read()
    path = storage.upload_file(content, file.filename, user, file.content_type or "application/octet-stream")
    return {"path": path, "filename": file.filename}

@app.get("/files/list")
def list_files(user: str = Depends(auth.get_current_user)):
    return {"files": storage.list_user_files(user)}

# ── AI 识图搜索 ──
@app.post("/ai/search-by-image")
async def search_by_image(file: UploadFile = File(...), user: str = Depends(auth.get_current_user)):
    image_bytes = await file.read()
    description = await ai_search.analyze_image(image_bytes)
    results = await ai_search.search_in_library(description, user, storage)
    return {"ai_description": description, "results": results}

@app.get("/")
def root():
    return FileResponse("static/index.html")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860)