抓取生产工单,赚取发料异常

This commit is contained in:
hjq
2026-06-11 15:58:56 +08:00
parent 66eecd0daa
commit 5b19790037
40 changed files with 4942 additions and 54 deletions

View File

@@ -44,13 +44,31 @@ BROWSER_LOGIN_DIR = BASE_DIR / "browser_login"
browser_lock = threading.Lock()
is_browser_busy = False
current_task_name = ""
task_logs = []
class WebLogger:
def __init__(self, orig):
self.orig = orig
def write(self, text):
self.orig.write(text)
msg = text.strip()
if msg and is_browser_busy:
task_logs.append(msg)
if len(task_logs) > 500:
task_logs.pop(0)
def flush(self):
self.orig.flush()
sys.stdout = WebLogger(sys.stdout)
sys.stderr = WebLogger(sys.stderr)
def set_browser_busy(task_name):
"""设置浏览器为忙碌状态"""
global is_browser_busy, current_task_name
global is_browser_busy, current_task_name, task_logs
with browser_lock:
is_browser_busy = True
current_task_name = task_name
task_logs.clear()
def release_browser():
"""释放浏览器控制权"""
@@ -127,6 +145,16 @@ def receipts_page():
"""渲染收货明细数据看板"""
return render_template('index.html')
@app.route('/work_orders')
def work_orders_page():
"""渲染生产工单数据看板"""
return render_template('work_orders.html')
@app.route('/abnormal_report')
def abnormal_report_page():
"""渲染发料异常检查数据看板"""
return render_template('abnormal_report.html')
@app.route('/api/receipts')
def get_receipts():
"""获取收货明细数据(支持分页和多条件搜索)"""
@@ -175,6 +203,102 @@ def get_receipts():
"rows": [dict(ix) for ix in receipts]
})
@app.route('/api/work_orders')
def get_work_orders():
"""获取生产工单数据(支持分页和多条件搜索)"""
page = int(request.args.get('page', 1))
limit = int(request.args.get('limit', 50))
offset = (page - 1) * limit
# 获取搜索参数
wo_number = request.args.get('work_orders_number', '').strip()
material_name = request.args.get('material_name', '').strip()
material_code = request.args.get('material_code', '').strip()
conn = get_db_connection()
# 构建动态 SQL 查询
query_conditions = []
params = []
if wo_number:
query_conditions.append("work_orders_number LIKE ?")
params.append(f"%{wo_number}%")
if material_name:
query_conditions.append("material_name LIKE ?")
params.append(f"%{material_name}%")
if material_code:
query_conditions.append("material_code LIKE ?")
params.append(f"%{material_code}%")
where_clause = ""
if query_conditions:
where_clause = " WHERE " + " AND ".join(query_conditions)
# 获取总数
count_query = f"SELECT COUNT(*) FROM work_orders{where_clause}"
total = conn.execute(count_query, params).fetchone()[0]
# 获取分页数据
data_query = f"SELECT * FROM work_orders{where_clause} ORDER BY execution_time DESC LIMIT ? OFFSET ?"
params.extend([limit, offset])
orders = conn.execute(data_query, params).fetchall()
conn.close()
return jsonify({
"total": total,
"rows": [dict(ix) for ix in orders]
})
@app.route('/api/abnormal_report')
def get_abnormal_report():
"""获取发料异常报表数据(支持分页和多条件搜索)"""
page = int(request.args.get('page', 1))
limit = int(request.args.get('limit', 50))
offset = (page - 1) * limit
# 获取搜索参数
wo_number = request.args.get('work_orders_number', '').strip()
material_code = request.args.get('material_code', '').strip()
issue_status = request.args.get('issue_status', '').strip()
conn = get_db_connection()
# 构建动态 SQL 查询
query_conditions = []
params = []
if wo_number:
query_conditions.append("work_orders_number LIKE ?")
params.append(f"%{wo_number}%")
if material_code:
query_conditions.append("material_code LIKE ?")
params.append(f"%{material_code}%")
if issue_status:
query_conditions.append("issue_status = ?")
params.append(issue_status)
where_clause = ""
if query_conditions:
where_clause = " WHERE " + " AND ".join(query_conditions)
# 获取总数
count_query = f"SELECT COUNT(*) FROM abnormal_report{where_clause}"
total = conn.execute(count_query, params).fetchone()[0]
# 获取分页数据 (默认按工单号倒序排列)
data_query = f"SELECT * FROM abnormal_report{where_clause} ORDER BY work_orders_number DESC LIMIT ? OFFSET ?"
params.extend([limit, offset])
orders = conn.execute(data_query, params).fetchall()
conn.close()
return jsonify({
"total": total,
"rows": [dict(ix) for ix in orders]
})
@app.route('/api/task_status')
def get_task_status():
"""获取当前浏览器控制任务的状态"""
@@ -183,6 +307,11 @@ def get_task_status():
"task_name": current_task_name
})
@app.route('/api/task_logs')
def get_task_logs():
"""获取实时日志"""
return jsonify({"logs": task_logs})
@app.route('/api/sync_receipts', methods=['POST'])
def sync_receipts():
"""触发后台运行收货明细增量抓取脚本(修复跨机器路径问题)"""
@@ -222,6 +351,85 @@ def sync_receipts():
except Exception as e:
return jsonify({"success": False, "message": f"系统错误: {str(e)}"}), 500
@app.route('/api/sync_work_orders', methods=['POST'])
def sync_work_orders():
"""触发后台运行生产工单增量抓取脚本"""
global is_browser_busy
import sys
if is_browser_busy:
return jsonify({
"success": False,
"message": f"系统忙碌:当前正在执行 '{current_task_name}',请稍后再试。"
}), 409
if str(BROWSER_LOGIN_DIR) not in sys.path:
sys.path.insert(0, str(BROWSER_LOGIN_DIR))
def run_work_orders_sync():
set_browser_busy("手动生产工单增量同步")
try:
from fetch_work_orders_incremental import fetch_work_orders_incremental
fetch_work_orders_incremental()
except Exception as e:
print(f"手动生产工单同步失败: {e}")
finally:
release_browser()
try:
threading.Thread(target=run_work_orders_sync, daemon=True).start()
return jsonify({
"success": True,
"message": "工单增量同步任务已在后台启动!请观察黑框控制台的运行日志。",
"logs": "任务已在后台运行..."
})
except ImportError:
return jsonify({"success": False, "message": "找不到增量抓取脚本或导入失败"}), 404
except Exception as e:
return jsonify({"success": False, "message": f"系统错误: {str(e)}"}), 500
@app.route('/api/sync_abnormal_report', methods=['POST'])
def sync_abnormal_report():
"""触发后台运行异常报表抓取脚本"""
global is_browser_busy
import sys
if is_browser_busy:
return jsonify({
"success": False,
"message": f"系统忙碌:当前正在执行 '{current_task_name}',请稍后再试。"
}), 409
if str(BROWSER_LOGIN_DIR) not in sys.path:
sys.path.insert(0, str(BROWSER_LOGIN_DIR))
def run_abnormal_report_sync():
set_browser_busy("手动发料异常报表抓取")
try:
import auto_fetch_abnormal_report
page = auto_fetch_abnormal_report.get_page(port=9222)
success = auto_fetch_abnormal_report.navigate_to_report(page)
if success:
auto_fetch_abnormal_report.fetch_report_data(page)
except Exception as e:
print(f"手动发料异常报表抓取失败: {e}")
finally:
release_browser()
try:
threading.Thread(target=run_abnormal_report_sync, daemon=True).start()
return jsonify({
"success": True,
"message": "发料异常报表抓取任务已在后台启动!请观察黑框控制台的运行日志。",
"logs": "任务已在后台运行..."
})
except ImportError:
return jsonify({"success": False, "message": "找不到异常报表抓取脚本或导入失败"}), 404
except Exception as e:
return jsonify({"success": False, "message": f"系统错误: {str(e)}"}), 500
@app.route('/api/sync_bom', methods=['POST'])
def sync_bom():
"""触发后台运行 BOM 成本全量抓取脚本(修复跨机器路径问题)"""