www: 项目分类功能 - 左侧导航分类筛选(全部/未归类/分类)、编辑弹窗放大+分类下拉、右上角新建分类
This commit is contained in:
+55
-4
@@ -29,6 +29,16 @@ def init_db():
|
||||
url TEXT NOT NULL,
|
||||
desc TEXT DEFAULT '',
|
||||
icon TEXT DEFAULT '',
|
||||
category TEXT DEFAULT '',
|
||||
sort_order INTEGER DEFAULT 0
|
||||
)""")
|
||||
# 兼容迁移:旧库补充 category 列
|
||||
cols = [r[1] for r in conn.execute("PRAGMA table_info(links)").fetchall()]
|
||||
if "category" not in cols:
|
||||
conn.execute("ALTER TABLE links ADD COLUMN category TEXT DEFAULT ''")
|
||||
conn.execute("""CREATE TABLE IF NOT EXISTS categories (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
sort_order INTEGER DEFAULT 0
|
||||
)""")
|
||||
# 首次启动:如果表为空则写入默认数据
|
||||
@@ -91,23 +101,50 @@ class LinkCreate(BaseModel):
|
||||
url: str
|
||||
desc: str = ""
|
||||
icon: str = ""
|
||||
category: str = ""
|
||||
|
||||
class CategoryCreate(BaseModel):
|
||||
name: str
|
||||
|
||||
@app.get("/api/links")
|
||||
def list_links():
|
||||
with get_db() as conn:
|
||||
rows = conn.execute("SELECT id,name,url,desc,icon FROM links ORDER BY sort_order, id").fetchall()
|
||||
rows = conn.execute("SELECT id,name,url,desc,icon,category FROM links ORDER BY sort_order, id").fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
@app.get("/api/categories")
|
||||
def list_categories():
|
||||
with get_db() as conn:
|
||||
rows = conn.execute("SELECT id,name FROM categories ORDER BY sort_order, id").fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
@app.post("/api/categories")
|
||||
def add_category(cat: CategoryCreate, username: str = Depends(require_sso)):
|
||||
import time, random
|
||||
name = cat.name.strip()
|
||||
if not name:
|
||||
raise HTTPException(400, "分类名称不能为空")
|
||||
cid = f"c{int(time.time()):x}{random.randint(0,0xffffff):06x}"
|
||||
with get_db() as conn:
|
||||
try:
|
||||
max_sort = conn.execute("SELECT COALESCE(MAX(sort_order),0) FROM categories").fetchone()[0]
|
||||
conn.execute("INSERT INTO categories (id,name,sort_order) VALUES (?,?,?)",
|
||||
(cid, name, max_sort + 1))
|
||||
conn.commit()
|
||||
except sqlite3.IntegrityError:
|
||||
raise HTTPException(400, "分类已存在")
|
||||
return {"id": cid, "name": name}
|
||||
|
||||
@app.post("/api/links")
|
||||
def add_link(link: LinkCreate, username: str = Depends(require_sso)):
|
||||
import time, random
|
||||
lid = f"{int(time.time()):x}{random.randint(0,0xffffff):06x}"
|
||||
with get_db() as conn:
|
||||
max_sort = conn.execute("SELECT COALESCE(MAX(sort_order),0) FROM links").fetchone()[0]
|
||||
conn.execute("INSERT INTO links (id,name,url,desc,icon,sort_order) VALUES (?,?,?,?,?,?)",
|
||||
(lid, link.name, link.url, link.desc, link.icon, max_sort + 1))
|
||||
conn.execute("INSERT INTO links (id,name,url,desc,icon,category,sort_order) VALUES (?,?,?,?,?,?,?)",
|
||||
(lid, link.name, link.url, link.desc, link.icon, link.category, max_sort + 1))
|
||||
conn.commit()
|
||||
return {"id": lid, "name": link.name, "url": link.url, "desc": link.desc, "icon": link.icon}
|
||||
return {"id": lid, "name": link.name, "url": link.url, "desc": link.desc, "icon": link.icon, "category": link.category}
|
||||
|
||||
@app.delete("/api/links/{link_id}")
|
||||
def delete_link(link_id: str, username: str = Depends(require_sso)):
|
||||
@@ -118,6 +155,20 @@ def delete_link(link_id: str, username: str = Depends(require_sso)):
|
||||
raise HTTPException(404, "链接不存在")
|
||||
return {"success": True}
|
||||
|
||||
@app.put("/api/links/{link_id}")
|
||||
def update_link(link_id: str, link: LinkCreate, username: str = Depends(require_sso)):
|
||||
with get_db() as conn:
|
||||
row = conn.execute("SELECT * FROM links WHERE id=?", (link_id,)).fetchone()
|
||||
if not row:
|
||||
raise HTTPException(404, "链接不存在")
|
||||
# 图标不传则保留原值,避免改名称时图标被重新生成
|
||||
icon = link.icon if link.icon else row["icon"]
|
||||
# 分类始终按提交值更新(空字符串 = 未归类)
|
||||
conn.execute("UPDATE links SET name=?, url=?, desc=?, icon=?, category=? WHERE id=?",
|
||||
(link.name, link.url, link.desc, icon, link.category, link_id))
|
||||
conn.commit()
|
||||
return {"id": link_id, "name": link.name, "url": link.url, "desc": link.desc, "icon": icon, "category": link.category}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8887)
|
||||
|
||||
Reference in New Issue
Block a user