工单导入及下载

This commit is contained in:
赵杰 Jie Zhao (雄狮汽车科技)
2025-09-19 19:58:54 +01:00
parent 45beca7f94
commit a884eafc64

View File

@@ -7,6 +7,8 @@
import os import os
import pandas as pd import pandas as pd
import logging import logging
import uuid
import time
from datetime import datetime from datetime import datetime
from flask import Blueprint, request, jsonify, send_file from flask import Blueprint, request, jsonify, send_file
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
@@ -52,29 +54,48 @@ def get_assistant():
def _ensure_workorder_template_file() -> str: def _ensure_workorder_template_file() -> str:
"""返回已有的模板xlsx路径不做动态生成避免运行时依赖问题""" """返回已有的模板xlsx路径不做动态生成避免运行时依赖问题"""
template_path = os.path.join('uploads', 'workorder_template.xlsx') # 获取项目根目录
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(current_dir, '..', '..', '..'))
# 模板文件路径项目根目录下的uploads
template_path = os.path.join(project_root, 'uploads', 'workorder_template.xlsx')
# 确保目录存在 # 确保目录存在
os.makedirs('uploads', exist_ok=True) uploads_dir = os.path.join(project_root, 'uploads')
os.makedirs(uploads_dir, exist_ok=True)
if not os.path.exists(template_path): if not os.path.exists(template_path):
# 优先从项目根目录的 uploads 拷贝(仓库自带模板 # 尝试从其他可能的位置复制模板
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) possible_locations = [
repo_template = os.path.join(project_root, 'uploads', 'workorder_template.xlsx') os.path.join(project_root, 'uploads', 'workorder_template.xlsx'),
os.path.join(current_dir, 'uploads', 'workorder_template.xlsx'),
os.path.join(os.getcwd(), 'uploads', 'workorder_template.xlsx')
]
source_found = False
for source_path in possible_locations:
if os.path.exists(source_path):
try: try:
if os.path.exists(repo_template):
import shutil import shutil
shutil.copyfile(repo_template, template_path) shutil.copyfile(source_path, template_path)
else: source_found = True
# 仓库模板不存在时,自动生成一个最小可用模板 break
except Exception as e:
logger.warning(f"复制模板文件失败: {e}")
if not source_found:
# 自动生成一个最小可用模板
try: try:
import pandas as pd import pandas as pd
from pandas import DataFrame from pandas import DataFrame
columns = ['标题', '描述', '分类', '优先级', '状态', '解决方案', '满意度'] columns = ['标题', '描述', '分类', '优先级', '状态', '解决方案', '满意度']
df: DataFrame = pd.DataFrame(columns=columns) df: DataFrame = pd.DataFrame(columns=columns)
df.to_excel(template_path, index=False) df.to_excel(template_path, index=False)
logger.info(f"自动生成模板文件: {template_path}")
except Exception as gen_err: except Exception as gen_err:
raise FileNotFoundError('模板文件缺失且自动生成失败请检查依赖openpyxl/pandas') from gen_err raise FileNotFoundError('模板文件缺失且自动生成失败请检查依赖openpyxl/pandas') from gen_err
except Exception as copy_err:
raise copy_err
return template_path return template_path
@workorders_bp.route('') @workorders_bp.route('')
@@ -411,9 +432,16 @@ def import_workorders():
if not title or title.strip() == '': if not title or title.strip() == '':
continue continue
# 生成唯一的工单ID
timestamp = int(time.time())
unique_id = str(uuid.uuid4())[:8]
order_id = f"IMP_{timestamp}_{unique_id}"
# 创建工单到数据库 # 创建工单到数据库
try:
with db_manager.get_session() as session: with db_manager.get_session() as session:
workorder = WorkOrder( workorder = WorkOrder(
order_id=order_id,
title=title, title=title,
description=description, description=description,
category=category, category=category,
@@ -436,6 +464,12 @@ def import_workorders():
session.add(workorder) session.add(workorder)
session.commit() session.commit()
logger.info(f"成功导入工单: {order_id} - {title}")
except Exception as db_error:
logger.error(f"导入工单到数据库失败: {db_error}")
continue
# 添加到返回列表 # 添加到返回列表
imported_workorders.append({ imported_workorders.append({
"id": workorder.id, "id": workorder.id,
@@ -488,11 +522,27 @@ def download_import_template_file():
"""直接返回工单导入模板文件(下载)""" """直接返回工单导入模板文件(下载)"""
try: try:
template_path = _ensure_workorder_template_file() template_path = _ensure_workorder_template_file()
# 检查文件是否存在
if not os.path.exists(template_path):
logger.error(f"模板文件不存在: {template_path}")
return jsonify({"error": "模板文件不存在"}), 404
# 检查文件大小
file_size = os.path.getsize(template_path)
if file_size == 0:
logger.error(f"模板文件为空: {template_path}")
return jsonify({"error": "模板文件为空"}), 500
logger.info(f"准备下载模板文件: {template_path}, 大小: {file_size} bytes")
try: try:
# Flask>=2 使用 download_name # Flask>=2 使用 download_name
return send_file(template_path, as_attachment=True, download_name='工单导入模板.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') return send_file(template_path, as_attachment=True, download_name='工单导入模板.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
except TypeError: except TypeError:
# 兼容 Flask<2 的 attachment_filename # 兼容 Flask<2 的 attachment_filename
return send_file(template_path, as_attachment=True, attachment_filename='工单导入模板.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') return send_file(template_path, as_attachment=True, attachment_filename='工单导入模板.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
except Exception as e: except Exception as e:
return jsonify({"error": str(e)}), 500 logger.error(f"下载模板文件失败: {e}")
return jsonify({"error": f"下载失败: {str(e)}"}), 500