init: 管理会计OS初始代码
包含前后端完整代码: - 前端:Vue3+Vite+ElementPlus - 后端:FastAPI+SQLAlchemy - 模块:驾驶舱/KPI/战略地图/预警/预算/成本/预测/改善行动 - 当前版本:v1.0.0
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""组织层级 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}
|
||||
|
||||
Reference in New Issue
Block a user