包含前后端完整代码: - 前端:Vue3+Vite+ElementPlus - 后端:FastAPI+SQLAlchemy - 模块:驾驶舱/KPI/战略地图/预警/预算/成本/预测/改善行动 - 当前版本:v1.0.0
102 lines
3.3 KiB
Python
102 lines
3.3 KiB
Python
"""组织层级 API"""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from app.database import get_db, init_db
|
|
from app.auth_middleware import require_auth, require_role
|
|
from app.models import OrgNode, User
|
|
|
|
router = APIRouter(prefix="/api/cma/org", tags=["组织管理"],
|
|
dependencies=[Depends(require_role("ceo", "it"))],
|
|
)
|
|
|
|
|
|
@router.get("/tree")
|
|
def get_org_tree(db: Session = Depends(get_db)):
|
|
"""返回全量树结构: [{id, label, children}]"""
|
|
nodes = db.query(OrgNode).order_by(OrgNode.sort_order).all()
|
|
return {"data": _build_tree(nodes)}
|
|
|
|
|
|
@router.get("/nodes")
|
|
def list_org_nodes(db: Session = Depends(get_db)):
|
|
"""平铺列表"""
|
|
nodes = db.query(OrgNode).order_by(OrgNode.level, OrgNode.sort_order).all()
|
|
return {"data": [_node_to_dict(n) for n in nodes]}
|
|
|
|
|
|
@router.post("/nodes")
|
|
def create_org_node(data: dict, db: Session = Depends(get_db)):
|
|
"""新增节点"""
|
|
node = OrgNode(
|
|
parent_id=data.get("parent_id"),
|
|
name=data["name"],
|
|
code=data.get("code"),
|
|
level=data["level"],
|
|
sort_order=data.get("sort_order", 0),
|
|
enabled=data.get("enabled", 1),
|
|
remark=data.get("remark"),
|
|
)
|
|
db.add(node)
|
|
db.commit()
|
|
db.refresh(node)
|
|
return _node_to_dict(node)
|
|
|
|
|
|
@router.put("/nodes/{node_id}")
|
|
def update_org_node(node_id: int, data: dict, db: Session = Depends(get_db)):
|
|
"""修改节点"""
|
|
node = db.query(OrgNode).filter(OrgNode.id == node_id).first()
|
|
if not node:
|
|
raise HTTPException(404, "节点不存在")
|
|
for k, v in data.items():
|
|
if hasattr(node, k) and v is not None:
|
|
setattr(node, k, v)
|
|
db.commit()
|
|
return _node_to_dict(node)
|
|
|
|
|
|
@router.delete("/nodes/{node_id}")
|
|
def delete_org_node(node_id: int, db: Session = Depends(get_db)):
|
|
"""删除节点(有子节点则阻止)"""
|
|
node = db.query(OrgNode).filter(OrgNode.id == node_id).first()
|
|
if not node:
|
|
raise HTTPException(404, "节点不存在")
|
|
# 检查是否有子节点
|
|
children = db.query(OrgNode).filter(OrgNode.parent_id == node_id).count()
|
|
if children > 0:
|
|
raise HTTPException(400, f"该节点有 {children} 个子节点,请先删除子节点")
|
|
db.delete(node)
|
|
db.commit()
|
|
return {"message": "已删除"}
|
|
|
|
|
|
@router.put("/nodes/{node_id}/toggle")
|
|
def toggle_org_node(node_id: int, db: Session = Depends(get_db)):
|
|
"""切换启用/禁用"""
|
|
node = db.query(OrgNode).filter(OrgNode.id == node_id).first()
|
|
if not node:
|
|
raise HTTPException(404, "节点不存在")
|
|
node.enabled = 0 if node.enabled else 1
|
|
db.commit()
|
|
return _node_to_dict(node)
|
|
|
|
|
|
# ── 工具 ─────────────────────────────────
|
|
|
|
def _build_tree(nodes: list) -> list:
|
|
"""将平铺节点列表转为树结构"""
|
|
node_map = {n.id: {"id": n.id, "label": n.name, "level": n.level, "enabled": bool(n.enabled), "code": n.code, "children": []} for n in nodes}
|
|
tree = []
|
|
for n in nodes:
|
|
item = node_map[n.id]
|
|
if n.parent_id and n.parent_id in node_map:
|
|
node_map[n.parent_id]["children"].append(item)
|
|
else:
|
|
tree.append(item)
|
|
return tree
|
|
|
|
|
|
def _node_to_dict(n):
|
|
return {c.name: getattr(n, c.name) for c in n.__table__.columns}
|
|
|