Files
Hermes CI Fix 3dddd36866 init: 管理会计OS初始代码
包含前后端完整代码:
- 前端:Vue3+Vite+ElementPlus
- 后端:FastAPI+SQLAlchemy
- 模块:驾驶舱/KPI/战略地图/预警/预算/成本/预测/改善行动
- 当前版本:v1.0.0
2026-05-28 17:32:22 +08:00

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}