Files
pickling-mes/backend/app/main.py
wangyu 9fb3dcb785 feat(linkage): 计划-鞍座-实绩-停机联动 + 成本管理页
后端:
- 计划录入即「准备好」,队首(最早)自动「在线」(唯一)
- 新增上卷鞍座联动引擎 line_service:移动→鞍座→(有速度/投入生产)→生产中
  →带头达2000m→生产完成并自动产生实绩、持久化运行数据
- 停机自动检测:线速度为0持续>10min 自动新增待补充停机记录,恢复后自动结束
- /plan/start=移动到鞍座, 新增 /plan/{id}/commit 投入生产, /plan/saddle/current,
  /plan/seed 批量插入(轧制力模式);后台引擎循环自动推进
- 新增成本管理:CostRecord 模型 + /cost CRUD + 9 类成本项(乳化液/盐酸/碱/电/水/蒸汽…)

前端:
- 入口跟踪重构为单个上卷鞍座工位(实时速度/带头长度进度/投入生产)+待上卷卡片+队列,
  计划列表/卡片/队列均可「移动」
- 新增成本管理页(成本项切换 + 柱+线图 + 明细表 + 时间筛选 + 新增),布局参考乳化液耗量统计

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 13:57:59 +08:00

94 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger
from app.config import settings
from app.database import init_db
from app.api import router
@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("启动推拉酸洗线二级系统...")
await init_db()
await _create_default_admin()
await _ensure_line_state()
# 启动L1报文接收服务UDP
from app.services.message_parser import l1_server
import app.services.material_service # noqa: 注册报文处理器
await l1_server.start()
# 启动产线联动引擎(计划上线/上卷鞍座/实绩/停机自动检测)
from app.services.line_service import run_engine_loop
engine_task = asyncio.create_task(run_engine_loop())
logger.info("系统启动完成")
yield
engine_task.cancel()
l1_server.stop()
logger.info("系统已停止")
async def _create_default_admin():
"""首次启动时创建默认管理员"""
from app.database import AsyncSessionLocal
from sqlalchemy import select
from app.models.user import User
from app.services.auth_service import hash_password
async with AsyncSessionLocal() as db:
result = await db.execute(select(User).where(User.username == "admin"))
if not result.scalar_one_or_none():
admin = User(
username="admin",
full_name="系统管理员",
hashed_password=hash_password("admin123"),
role="admin",
)
db.add(admin)
await db.commit()
logger.info("默认管理员已创建: admin / admin123")
async def _ensure_line_state():
"""确保产线状态单例行存在(避免并发首建竞争)。"""
from app.database import AsyncSessionLocal
from app.models.line_state import LineState
async with AsyncSessionLocal() as db:
if not await db.get(LineState, 1):
db.add(LineState(id=1, speed=0))
await db.commit()
app = FastAPI(
title="推拉酸洗线二级系统",
description="Pickling Line Level-2 MES System",
version="1.0.0",
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(router, prefix="/api")
@app.get("/health")
async def health():
return {"status": "ok", "service": "pickling-mes"}
if __name__ == "__main__":
import uvicorn
uvicorn.run("app.main:app", host=settings.APP_HOST, port=settings.APP_PORT, reload=settings.DEBUG)