libushang 8 месяцев назад
Родитель
Сommit
4d27d4b5f0

+ 2 - 0
common/db/__init__.py

@@ -0,0 +1,2 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-

+ 13 - 0
common/db/db_area.py

@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from sqlalchemy.orm import Session
+from sqlalchemy import text, exists, and_, or_, not_
+from sqlalchemy.sql import func
+from database import get_db
+from models import *
+from extensions import logger
+from utils import *
+
+# 根据经纬度获取地区代码
+def get_region_code_by_gps(db: Session, lng: str, lat: str):
+    return "4409"

+ 16 - 0
common/db/db_emergency_plan.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from sqlalchemy.orm import Session
+from sqlalchemy import text, exists, and_, or_, not_
+from sqlalchemy.sql import func
+from database import get_db
+from models import *
+from extensions import logger
+from utils import *
+
+def get_plan_name_by_id(db: Session, plan_id: int) -> str:
+    row = db.query(EmergencyPlan).filter(EmergencyPlan.id == plan_id).first()
+    if row is not None:
+        return row.plan_name
+    
+    return None

+ 84 - 0
common/db/db_event_management.py

@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from sqlalchemy.orm import Session
+from sqlalchemy import text, exists, and_, or_, not_
+from sqlalchemy.sql import func
+from database import get_db
+from models import *
+from extensions import logger
+from utils import *
+import random
+from . import db_user
+import copy
+
+EVENT_TRACK_LIST = [
+        {"title": "事件登记", "event_status": "0", "tracking_time": "", "event_level": "", "recorded_by": ""}, 
+        {"title": "进入指挥", "event_status": "1", "tracking_time": "", "event_level": "", "recorded_by": ""}, 
+        {"title": "结束指挥", "event_status": "2", "tracking_time": "", "event_level": "", "recorded_by": ""}, 
+        {"title": "关闭事件", "event_status": "3", "tracking_time": "", "event_level": "", "recorded_by": ""} 
+    ]
+
+def get_next_event_id(db: Session):
+    while True:
+        random_10_digit_number = random.randint(1000000000, 9999999999)
+        eventId = 'YJSJ' + str(random_10_digit_number)
+        
+        it_exists = db.query(
+            exists().where( EventBase.event_code == eventId )
+        ).scalar()
+
+        if it_exists == False:
+            return eventId
+        
+def get_event_status_track(db: Session, event_id: int):
+    print(event_id)
+    trace_list = copy.deepcopy(EVENT_TRACK_LIST)
+    for n in trace_list:
+        row = db.query(EventTracking).filter(and_(EventTracking.del_flag == '0', EventTracking.event_id == event_id, EventTracking.event_status == n['event_status'])).first()
+        if row is not None:
+            n['tracking_time'] = row.tracking_time.strftime("%m月%d日 %H:%M")
+            n['event_level'] = row.event_level
+
+    row = db.query(EventBase).filter(EventBase.id == event_id).first()
+    active = int(row.event_status) + 1
+    data = [
+        {
+            "title": n['title'],
+            "description": n['tracking_time']
+        }
+        for n in trace_list
+    ]
+    return {
+        "active": active,
+        "items" : data
+    }
+
+def get_event_level_track(db: Session, event_id: int):
+    trace_list = copy.deepcopy(EVENT_TRACK_LIST)
+    for n in trace_list:
+        row = db.query(EventTracking).filter(and_(EventTracking.del_flag == '0', EventTracking.event_id == event_id, EventTracking.event_status == n['event_status'])).first()
+        if row is not None:
+            n['tracking_time'] = row.tracking_time.strftime("%Y/%m/%d %H:%M:%S")
+            n['event_level'] = row.event_level
+            n['recorded_by'] = row.recorded_by
+
+    data = []
+    for n in trace_list:
+        if n['tracking_time'] != "":
+            data.append({
+                "name": db_user.get_nick_name_by_id(db, n['recorded_by']),
+                "timestamp": n['tracking_time'],
+                "level": n['event_level']
+            })
+    return data
+
+def get_summary_file_list(db: Session, event_id: int):
+    rows = db.query(EventFile).filter(and_(EventFile.del_flag == '0', EventFile.event_id == event_id)).all()
+    data = [
+        {
+            "file_name": row.file_name,
+            "url": "/api/event_management/event/download_file?file_id="+str(row.id)+"&event_id="+str(row.event_id)
+        }
+        for row in rows
+    ]
+    return data

+ 23 - 0
common/db/db_user.py

@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from sqlalchemy.orm import Session
+from sqlalchemy import text, exists, and_, or_, not_
+from sqlalchemy.sql import func
+from database import get_db
+from models import *
+from extensions import logger
+from utils import *
+
+def get_user_name_by_id(db: Session, user_id: int) -> str:
+    row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
+    if row is not None:
+        return row.user_name
+    
+    return ""
+
+def get_nick_name_by_id(db: Session, user_id: int) -> str:
+    row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
+    if row is not None:
+        return row.nick_name
+    
+    return ""

+ 1 - 1
models/__init__.py

@@ -8,4 +8,4 @@ from .oneshare_base import *
 from .ry_sys_base import *
 from .knowledge_base import *
 from .yjya_base import *
-from .Incident_base import *
+from .event_base import *

+ 27 - 22
models/Incident_base.py → models/event_base.py

@@ -4,50 +4,55 @@ from datetime import datetime
 
 
 
-class Incident(Base):
-    __tablename__ = 'incidents'
+class EventBase(Base):
+    __tablename__ = 'event_base'
 
     id = Column(Integer, autoincrement=True, primary_key=True)
-    code = Column(String(50), nullable=False, comment='事件编号')
-    title = Column(String(255), nullable=False, comment='事件标题')
-    incident_type = Column(String(100), nullable=False, comment='事件类型')
-    incident_level = Column(String(50), comment='事件等级')
-    status = Column(String(50), default='active', comment='事件状态')
-    occurrence_time = Column(DateTime, comment='事发时间')
+    event_code = Column(String(50), nullable=False, comment='事件编号')
+    event_title = Column(String(255), nullable=False, comment='事件标题')
+    event_type = Column(String(100), nullable=False, comment='事件类型')
+    event_level = Column(String(50), comment='事件等级')
+    event_status = Column(String(50), default='active', comment='事件状态')
+    event_time = Column(DateTime, comment='事发时间')
     report_time = Column(DateTime, default=datetime.now, comment='上报时间')
-    fatalities = Column(Integer, default=0, comment='死亡人数')
+    deaths = Column(Integer, default=0, comment='死亡人数')
     injuries = Column(Integer, default=0, comment='受伤人数')
     missing = Column(Integer, default=0, comment='失联人数')
-    source = Column(String(255), comment='事件来源')
-    location = Column(String(255), comment='事发地点')
-    longitude = Column(Float, comment='经度')
-    latitude = Column(Float, comment='纬度')
-    summary = Column(Text, comment='事件概要')
-    recorded_by = Column(String(50), comment='记录用户ID')
+    event_source = Column(String(255), comment='事件来源')
+    address = Column(String(255), comment='事发地点')
+    longitude = Column(String(20), default='', comment='经度')
+    latitude = Column(String(20), default='', comment='纬度')
+    event_description = Column(Text, comment='事件概要')
+    recorded_by = Column(Integer, nullable=False, comment='记录用户ID')
     del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')
     contact = Column(String(50), comment='联系人')
+    region_code = Column(String(50), comment='地区代码')
+    plan_id = Column(Integer, comment='匹配预案ID')
+    casualties = Column(String(1), default='0', comment='伤亡情况上报(0未上报 1已上报)')
 
     class Config:
         orm_mode = True
 
-class IncidentTracking(Base):
-    __tablename__ = 'incident_tracking'
+class EventTracking(Base):
+    __tablename__ = 'event_tracking'
 
     id = Column(Integer, autoincrement=True, primary_key=True)
-    incident_id = Column(Integer, nullable=False, comment='事件ID')
-    tracking_status = Column(String(100), nullable=False, comment='事件跟踪状态')
+    event_id = Column(Integer, nullable=False, comment='事件ID')
+    event_status = Column(String(10), nullable=False, comment='事件状态')
+    event_level = Column(String(10), nullable=False, comment='事件等级')
     tracking_time = Column(DateTime, default=datetime.now, comment='事件跟踪时间')
-    notes = Column(String(500), default='', comment='备注')
+    notes = Column(String(50), default='', comment='备注')
     recorded_by = Column(Integer, nullable=False, comment='记录用户ID')
     del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')
 
     class Config:
         orm_mode = True
 
-class IncidentFile(Base):
-    __tablename__ = 'incident_file'
+class EventFile(Base):
+    __tablename__ = 'event_file'
 
     id = Column(Integer, autoincrement=True, primary_key=True)
+    event_id = Column(Integer, nullable=False, comment='事件ID')
     file_name = Column(String(255), nullable=False, comment='文件名称')
     file_name_desc = Column(String(255), nullable=False, comment='文件名称原名')
     file_path = Column(String(255), nullable=False, comment='文件存储路径')

+ 4 - 2
routers/api/__init__.py

@@ -3,6 +3,7 @@
 from fastapi import APIRouter, Depends
 from common.security import valid_access_token
 from .login import router as login_router
+
 from . import gateway
 from . import dataAnalysis
 from . import resourceMonitoring
@@ -12,7 +13,7 @@ from . import upload_file
 from . import videoResource
 from . import Knowledge
 from . import emergencyPlans
-from . import event
+from . import eventManagement
 
 router = APIRouter()
 
@@ -27,4 +28,5 @@ router.include_router(upload_file.router, prefix="/file")
 router.include_router(videoResource.router, prefix="/videoResource")
 router.include_router(Knowledge.router, prefix="/knowledge")
 router.include_router(emergencyPlans.router, prefix="/emergency_plan")
-router.include_router(event.router, prefix="/event")
+
+router.include_router(eventManagement.router, prefix="/event_management", tags=["事件管理"])

+ 0 - 198
routers/api/event/__init__.py

@@ -1,198 +0,0 @@
-from fastapi import APIRouter, Request, Depends, HTTPException, Query
-from sqlalchemy.exc import IntegrityError
-
-from fastapi.responses import JSONResponse
-from database import get_db
-from sqlalchemy.orm import Session
-from models import *
-import json
-import random
-from sqlalchemy import create_engine, select
-from typing import Optional
-from utils.StripTagsHTMLParser import *
-
-router = APIRouter()
-
-@router.post('/create')
-async def create_event(request: Request, db: Session = Depends(get_db), body = Depends(remove_xss_json)):
-    try:
-        # 验证必需的字段
-        required_fields = ['eventTitle', 'eventType', 'eventLevel', 'eventStatus', 'eventTime', 'reportTime',
-                           'deaths', 'injuries', "missing", "eventSource", "longitude", "latitude", "eventDescription", "address"]
-        missing_fields = [field for field in required_fields if field not in body]
-        print('missing_fields',missing_fields)
-        if missing_fields:
-            raise HTTPException(status_code=401, detail=f"Missing required fields: {', '.join(missing_fields)}")
-        
-        random_10_digit_number = random.randint(1000000000, 9999999999)
-        eventId = 'YJSJ' + str(random_10_digit_number)
-        username = "..."
-
-        # 创建 事件 实例
-        incident_base = Incident(
-            code = eventId,
-            title = body["eventTitle"],
-            incident_type = body["eventType"],
-            incident_level = body["eventLevel"],
-            status = body["eventStatus"],
-            occurrence_time = body["eventTime"],
-            report_time = body["reportTime"],
-            fatalities = body["deaths"],
-            injuries = body["injuries"],
-            missing = body["missing"],
-            source = body["eventSource"],
-            location = body["address"],
-            longitude = body["longitude"],
-            latitude = body["latitude"],
-            summary = body["eventDescription"],
-            recorded_by = username,
-            del_flag = "0"
-        )
-        db.add(incident_base)
-        return {
-            "code": 200,
-            "msg": "事件创建成功",
-            "status": "success",
-            "data": eventId
-        }
-        
-    except json.JSONDecodeError:
-        raise HTTPException(status_code=400, detail="Invalid JSON data")
-    except IntegrityError as e:
-        db.rollback()
-        raise HTTPException(status_code=409, detail=f"Database error: {str(e)}")
-    except Exception as e:
-        db.rollback()
-        print(e)
-        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
-
-@router.get('/list')
-async def get_event_list(
-    eventType: str = Query(None, description='事件类型的字典键值'),
-    eventLevel: str = Query(None, description='事件等级的字典键值'),
-    eventStatus: str = Query(None, description='事件状态的字典键值'),
-    eventTime: str = Query(None, description='事发时间'),
-    regionCode: str = Query(None, description='行政区划代码'),
-    searchTerm: str = Query(None, description='根据事件标题或描述中的关键字进行模糊搜索'),
-    
-    sortBy: str = Query(None, description='排序字段'),
-    sortOrder: str = Query("asc", description='排序方式'),
-    page: int = Query(1, gt=0, description='页码'),
-    pageSize: int = Query(10, gt=0, description='pageSize'),
-    db: Session = Depends(get_db)
-):
-    try:
-        # 构建查询
-        query = db.query(Incident)
-        query = query.filter(Incident.del_flag != '2')
-        # 应用查询条件
-
-        # 计算总条目数
-        total_items = query.count()
-        # 执行分页查询
-        rows = query.offset((page - 1) * pageSize).limit(pageSize).all()
-        data = [
-            {
-                "eventId": row.code,
-                "eventTitle": row.title,
-                "eventType": row.incident_type,
-                "eventLevel": row.incident_level,
-                "eventStatus": row.status,
-                "latitude": row.latitude,
-                "longitude": row.longitude,
-                "address": row.location,
-                "eventTime": row.occurrence_time.strftime("%Y-%m-%d %H:%M")
-            }
-            for row in rows
-        ]
-
-        # 返回结果
-        return {
-            "code": 200,
-            "msg": "成功",
-            "data": data,
-            "total": total_items,
-            "currentPage": page,
-            "pageSize": pageSize,
-            "totalPages": (total_items + pageSize - 1) // pageSize
-        }
-
-    except Exception as e:
-        # 处理异常
-        raise HTTPException(status_code=500, detail=str(e))
-
-
-@router.get('/detail')
-async def get_event_detail(
-    request: Request, 
-    eventId: str, 
-    db: Session = Depends(get_db)):
-    
-    try: 
-        # 构建查询
-        query = db.query(Incident)
-        query = query.filter(Incident.code == eventId)
-
-        # 执行查询
-        row = query.first()
-        if row is not None:
-            eventTimeline = []
-            commandRecords = []
-            return {
-                "code": 200,
-                "msg": "查询成功",
-                "data": {
-                    "eventId": row.code,
-                    "eventTitle": row.title,
-                    "eventType": row.incident_type,
-                    "eventLevel": row.incident_level,
-                    "eventStatus": row.status,
-                    "eventSource": row.source,
-                    "eventTime": row.occurrence_time.strftime("%Y-%m-%d %H:%M"),
-                    "reportTime": row.report_time.strftime("%Y-%m-%d %H:%M"),
-                    "deaths": row.fatalities,
-                    "injuries": row.injuries,
-                    "missing": row.missing,
-                    "reportedBy": row.recorded_by,
-                    "contact": row.contact,
-                    "eventDescription": row.summary,
-                    "latitude": row.latitude,
-                    "longitude": row.longitude,
-                    "address": row.location,
-                    "eventTimeline": eventTimeline,
-                    "commandRecords": commandRecords
-                }
-            }
-        else:
-            return {
-                "code": 500,
-                "msg": "查询失败"
-            }
-
-    except Exception as e:
-        # 处理异常
-        raise HTTPException(status_code=500, detail=str(e))
-    
-
-@router.post('/close')
-async def close_event(
-    request: Request,  
-    db: Session = Depends(get_db), 
-    body = Depends(remove_xss_json)):
-
-    try:
-        # 验证必需的字段
-        required_fields = ['eventId', 'eventStatus', 'deaths', 'injuries', 'missing', 'fileNames']
-        missing_fields = [field for field in required_fields if field not in body]
-        print('missing_fields', missing_fields)
-        if missing_fields:
-            raise HTTPException(status_code=401, detail=f"Missing required fields: {', '.join(missing_fields)}")
-
-        return {
-            "code": 200,
-            "msg": "总结报告创建成功"
-        }
-
-    except Exception as e:
-        # 处理异常
-        raise HTTPException(status_code=500, detail=str(e))

+ 6 - 0
routers/api/eventManagement/__init__.py

@@ -0,0 +1,6 @@
+from fastapi import APIRouter
+from . import event
+
+router = APIRouter()
+
+router.include_router(event.router, prefix="/event", tags=["事件增删改"])

+ 397 - 0
routers/api/eventManagement/event.py

@@ -0,0 +1,397 @@
+from fastapi import APIRouter, Request, Depends, HTTPException, Query
+from sqlalchemy.exc import IntegrityError
+from fastapi.responses import HTMLResponse, FileResponse
+from fastapi.responses import JSONResponse
+from database import get_db
+from sqlalchemy import text, exists, and_, or_, not_
+from sqlalchemy.orm import Session
+from models import *
+import json
+import random
+from sqlalchemy import create_engine, select
+from typing import Optional
+from utils.StripTagsHTMLParser import *
+from common.db import db_event_management, db_user, db_area, db_emergency_plan
+from common.security import valid_access_token
+import traceback
+from utils import *
+from datetime import datetime, timedelta
+
+router = APIRouter()
+
+@router.post('/create')
+async def create_event(
+    request: Request, 
+    db: Session = Depends(get_db), 
+    body = Depends(remove_xss_json), 
+    user_id = Depends(valid_access_token)):
+    
+    try:
+        # 验证必需的字段
+        required_fields = ['event_title', 'event_type', 'event_level', 'event_status', 'event_time', 'report_time',
+                           'deaths', 'injuries', "missing", "event_source", "longitude", "latitude", "event_description", "address"]
+        missing_fields = [field for field in required_fields if field not in body]
+        if missing_fields:
+            raise HTTPException(status_code=401, detail=f"Missing required fields: {', '.join(missing_fields)}")
+        
+        eventId = db_event_management.get_next_event_id(db)
+
+        # 未上报时清空伤亡人数
+        if body['casualties'] == '0':
+            body['deaths'] = None
+            body['injuries'] = None
+            body['missing'] = None
+
+        region_code = db_area.get_region_code_by_gps(db, body['longitude'], body['latitude'])
+
+        event_base = EventBase(
+            **body,
+            event_code = eventId,
+            recorded_by = user_id,
+            region_code = region_code
+        )
+        db.add(event_base)
+        db.commit()
+        db.refresh(event_base)
+
+        # 事件跟踪表
+        event_tracking = EventTracking()
+        event_tracking.event_id = event_base.id
+        event_tracking.event_status = event_base.event_status
+        event_tracking.event_level = event_base.event_level
+        event_tracking.tracking_time = datetime.now()
+        event_tracking.recorded_by = user_id
+        event_tracking.del_flag = "0"
+        db.add(event_tracking)
+        db.commit()
+
+        return {
+            "code": 200,
+            "msg": "新建事件成功",
+            "data": eventId
+        }
+        
+    except Exception as e:
+        db.rollback()
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
+
+@router.get('/list')
+async def get_event_list(
+    event_type: str = Query('', description='事件类型的字典键值'),
+    event_level: str = Query('', description='事件等级的字典键值'),
+    event_status: str = Query('', description='事件状态的字典键值'),
+    event_time: str = Query('', description='事发时间'),
+    region_code: str = Query('', description='行政区划代码'),
+    keyword: str = Query('', description='根据事件标题或描述中的关键字进行模糊搜索'),
+    
+    sort_by: str = Query('', description='排序字段'),
+    sort_order: str = Query("asc", description='排序方式'),
+    page: int = Query(1, gt=0, description='页码'),
+    page_size: int = Query(10, gt=0, description='pageSize'),
+    db: Session = Depends(get_db)
+):
+    try:
+        # 应用查询条件
+        where = and_(EventBase.del_flag == '0')
+        if event_type != '':
+            where = and_(where, EventBase.event_type == event_type)
+        if event_level != '':
+            where = and_(where, EventBase.event_level == event_level)
+        if event_status != '':
+            where = and_(where, EventBase.event_status == event_status)
+        if event_time != '':
+            event_time = datetime.strptime(event_time, "%Y-%m-%d")
+            event_time = event_time + timedelta(days=1)
+            where = and_(where, EventBase.event_time.between(event_time, event_time + timedelta(days=1)))
+        if region_code != '':
+            where = and_(where, EventBase.region_code.like('{}%'.format(region_code)))
+        if keyword != '':
+            where = and_(where, or_(EventBase.event_title.like('%{}%'.format(keyword)), EventBase.address.like('%{}%'.format(keyword))))
+        print(where)
+        
+        # 计算总条目数
+        q = db.query(func.count(EventBase.id))
+        q = q.filter(where)
+        total = q.scalar()
+        
+        # 执行分页查询
+        q = db.query(EventBase)
+        q = q.filter(where)
+        rows = q.order_by(EventBase.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
+        data = [
+            {
+                "event_id": row.event_code,
+                "event_title": row.event_title,
+                "event_type": row.event_type,
+                "event_level": row.event_level,
+                "event_status": row.event_status,
+                "latitude": row.latitude,
+                "longitude": row.longitude,
+                "address": row.address,
+                "event_time": get_datetime_str(row.event_time)
+            }
+            for row in rows
+        ]
+
+        # 返回结果
+        return {
+            "code": 200,
+            "msg": "查询成功",
+            "data": data,
+            "total": total
+        }
+
+    except Exception as e:
+        # 处理异常
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=str(e))
+
+@router.get('/edit')
+async def get_edit_event(
+    request: Request, 
+    event_id: str = Query(None, description='事件编号'),
+    db: Session = Depends(get_db)):
+
+    row = db.query(EventBase).filter(EventBase.event_code == event_id).first()
+    data = get_model_dict(row)
+    data['eventId'] = data['event_code']
+    data['event_time'] = get_datetime_str(data['event_time'])
+    data['report_time'] = get_datetime_str(data['report_time'])
+    return {
+        "code": 200,
+        "msg": "查询成功",
+        "data": data
+    } 
+
+@router.post('/edit')
+async def post_edit_event(
+    request: Request, 
+    body = Depends(remove_xss_json), 
+    db: Session = Depends(get_db),
+    user_id = Depends(valid_access_token)):
+
+    eventId = body['eventId']
+    del body['eventId']
+    body['recorded_by'] = user_id
+
+    # 未上报时清空伤亡人数
+    if body['casualties'] == '0':
+        body['deaths'] = None
+        body['injuries'] = None
+        body['missing'] = None
+        
+    db.query(EventBase).filter(EventBase.event_code == eventId).update(body)
+    db.commit()
+
+    return {
+        "code": 200,
+        "msg": "保存事件成功"
+    }
+
+@router.post("/uploadEventCasualties")
+async def uploadEventCasualties(
+    request: Request, 
+    body = Depends(remove_xss_json), 
+    db: Session = Depends(get_db)
+):
+    eventId = body['eventId']
+    del body['eventId']
+    body['casualties'] = '1'
+    
+    db.query(EventBase).filter(EventBase.event_code == eventId).update(body)
+    db.commit()
+
+    return {
+        "code": 200,
+        "msg": "上报伤亡情况成功"
+    }
+
+
+@router.get('/detail')
+async def get_event_detail(
+    request: Request, 
+    event_id: str = Query(None, description='事件编号'),
+    db: Session = Depends(get_db)):
+    
+    print('event_id:',event_id)
+    try: 
+        # 构建查询
+        query = db.query(EventBase)
+        query = query.filter(EventBase.event_code == event_id)
+
+        # 执行查询
+        row = query.first()
+        if row is not None:
+            return {
+                "code": 200,
+                "msg": "查询成功",
+                "data": {
+                    "id": row.id,
+                    "event_id": row.event_code,
+                    "event_title": row.event_title,
+                    "event_type": row.event_type,
+                    "event_level": row.event_level,
+                    "event_status": row.event_status,
+                    "event_source": row.event_source,
+                    "event_time": get_datetime_str(row.event_time),
+                    "report_time": get_datetime_str(row.report_time),
+                    "casualties": row.casualties,
+                    "deaths": row.deaths,
+                    "injuries": row.injuries,
+                    "missing": row.missing,
+                    "reported_by": db_user.get_nick_name_by_id(db, row.recorded_by),
+                    "contact": row.contact,
+                    "event_description": row.event_description,
+                    "latitude": row.latitude,
+                    "longitude": row.longitude,
+                    "address": row.address,
+                    "plan_name": db_emergency_plan.get_plan_name_by_id(db, row.plan_id),
+                    "del_flag": row.del_flag,
+                    "summary_file": db_event_management.get_summary_file_list(db, row.id),
+
+                    # 事件跟踪
+                    "event_status_tracks": db_event_management.get_event_status_track(db, row.id),
+                    # 事件等级
+                    "event_level_tracks": db_event_management.get_event_level_track(db, row.id)
+                }
+            }
+        else:
+            return {
+                "code": 500,
+                "msg": "查询失败"
+            }
+
+    except Exception as e:
+        # 处理异常
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=str(e))
+    
+@router.post('/start')
+async def start_event(
+    request: Request, 
+    db: Session = Depends(get_db), 
+    body = Depends(remove_xss_json), 
+    user_id = Depends(valid_access_token)):
+
+    try:
+        event_base = db.query(EventBase).filter(EventBase.event_code == body['eventId']).first()
+        if event_base is not None:
+            event_base.event_status = "1" # 开始指挥
+            event_base.event_level= body['event_level']
+
+            event_tracking = EventTracking()
+            event_tracking.event_id = event_base.id
+            event_tracking.event_status = event_base.event_status
+            event_tracking.event_level = body['event_level']
+            event_tracking.tracking_time = datetime.now()
+            event_tracking.recorded_by = user_id
+            event_tracking.del_flag = "0"
+            db.add(event_tracking)
+
+            db.commit()
+
+            return {
+                "code": 200,
+                "msg": "开始指挥成功"
+            }
+
+    except Exception as e:
+        # 处理异常
+        db.rollback()
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=str(e))
+
+
+@router.post('/close')
+async def close_event(
+    request: Request,  
+    db: Session = Depends(get_db), 
+    body = Depends(remove_xss_json), 
+    user_id = Depends(valid_access_token)):
+
+    try:
+        # 验证必需的字段
+        required_fields = ['eventId', 'deaths', 'injuries', 'missing', 'fileNames']
+        missing_fields = [field for field in required_fields if field not in body]
+        print('missing_fields', missing_fields)
+        if missing_fields:
+            raise HTTPException(status_code=401, detail=f"Missing required fields: {', '.join(missing_fields)}")
+
+        eventId = body['eventId']
+
+        # 标记关闭状态
+        event_base = db.query(EventBase).filter(EventBase.event_code == eventId).first()
+        event_base.event_status = "3" 
+        db.commit()
+
+        event_tracking = EventTracking()
+        event_tracking.event_id = event_base.id
+        event_tracking.event_status = event_base.event_status
+        event_tracking.event_level = event_base.event_level
+        event_tracking.tracking_time = datetime.now()
+        event_tracking.recorded_by = user_id
+        event_tracking.del_flag = "0"
+        db.add(event_tracking)
+        db.commit()
+
+        return {
+            "code": 200,
+            "msg": '关闭事件成功'
+        }
+
+    except Exception as e:
+        # 处理异常
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=str(e))
+
+@router.post('/stop')    
+async def stop_event(
+    request: Request,  
+    db: Session = Depends(get_db), 
+    body = Depends(remove_xss_json)):
+    try:
+        eventId = body['eventId']
+        db.query(EventBase).filter(EventBase.event_code == eventId).update({"event_status": "2"})
+        db.commit()
+
+        return {
+            "code": 200,
+            "msg": '结束指挥成功'
+        }
+
+    except Exception as e:
+        traceback.print_exc()
+        # 处理异常
+        raise HTTPException(status_code=500, detail=str(e))
+    
+@router.post('/delete')
+async def delete_event(
+    request: Request,  
+    db: Session = Depends(get_db), 
+    body = Depends(remove_xss_json)):
+    try:
+        eventId = body['eventId']
+        db.query(EventBase).filter(EventBase.event_code == eventId).update({"del_flag": "2"})
+        db.commit()
+
+        return {
+            "code": 200,
+            "msg": '删除事件成功'
+        }
+
+    except Exception as e:
+        traceback.print_exc()
+        # 处理异常
+        raise HTTPException(status_code=500, detail=str(e))
+    
+@router.get("/download_file", response_class=FileResponse, summary="下载总结报告")
+async def download_file(
+    request: Request,  
+    file_id: int,
+    event_id: int,
+    db: Session = Depends(get_db)
+):
+    row = db.query(EventFile).filter(and_(EventFile.del_flag == '0', EventFile.id == file_id, EventFile.event_id == event_id)).first()
+    if row is not None:
+        return FileResponse(row.file_path)