Files
v6ole 5aadbc78c6 feat: v0.9.0 新增记录日志、设备更换记录及IMC服务集成
- 新增 RecordsLog.vue 操作记录日志页面
- 新增 ReplacementRecords.vue 设备更换记录页面
- 新增 imc_service.py IMC网管系统集成服务
- 新增 datetime.js 前端日期时间工具函数
- 新增 OLT时间同步.md 文档
- 扩展 devices.py API:设备更换记录、批量操作等
- 扩展 ssh_service.py:OLT时间同步功能
- 扩展 olt.py:新增时间同步相关接口
- 更新 DeviceList.vue:增强设备列表功能
- 更新路由和导航菜单
- 将 .claude/ 和 .mcp.json 加入 .gitignore

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 10:36:06 +08:00

83 lines
2.6 KiB
Python
Raw Permalink 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.
"""数据导入 API"""
from fastapi import APIRouter, UploadFile, File, Depends, Response
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.middleware.permission_middleware import require_permission
from app.services.import_service import ImportService
import shutil
import io
from openpyxl import Workbook
router = APIRouter(prefix="/api/import", tags=["数据导入"])
@router.get("/template")
def download_template():
"""下载导入数据模板"""
wb = Workbook()
ws = wb.active
ws.title = "ONU设备导入模板"
# 表头:序号|区域|学校名称|楼宇|场所类型|房间号|MAC地址|备注
headers = ["mac_address", "region", "school_name", "building", "place_type", "room_number", "notes"]
ws.append(headers)
# 示例数据
example_data = [
["AA:BB:CC:DD:EE:01", "区域1", "学校1", "1号楼", "教室", "101", ""],
["AA:BB:CC:DD:EE:02", "区域1", "学校1", "1号楼", "办公室", "102", ""],
]
for row in example_data:
ws.append(row)
# 设置列宽
ws.column_dimensions['A'].width = 20 # mac_address
ws.column_dimensions['B'].width = 12 # region
ws.column_dimensions['C'].width = 18 # school_name
ws.column_dimensions['D'].width = 12 # building
ws.column_dimensions['E'].width = 12 # place_type
ws.column_dimensions['F'].width = 12 # room_number
ws.column_dimensions['G'].width = 20 # notes
# 保存到内存
output = io.BytesIO()
wb.save(output)
output.seek(0)
return Response(
content=output.getvalue(),
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
headers={"Content-Disposition": "attachment; filename=onu_import_template.xlsx"}
)
@router.post("/upload")
async def upload_excel(
file: UploadFile = File(...),
olt_id: int = None,
db: Session = Depends(get_db),
_: dict = Depends(require_permission('device.import')),
):
"""上传并导入 Excel 文件(仅导入 MAC 信息,不关联 OLT"""
file_path = f"/tmp/{file.filename}"
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
service = ImportService(db)
records = service.parse_excel(file_path)
validation = service.validate_data(records)
created = updated = 0
if validation['valid']:
result = service.import_devices(validation['valid'], olt_id)
created = result['created']
updated = result['updated']
return {
"success": created + updated,
"created": created,
"updated": updated,
"failed": validation['invalid']
}