Files
assist/src/web/blueprints/feishu_sync.py
赵杰 Jie Zhao (雄狮汽车科技) 79cf316c63 修复AI建议逻辑和字段映射问题
- 修复AI建议基于问题描述而不是处理过程生成
- 修复工单详情页面显示逻辑
- 修复飞书时间字段处理(毫秒时间戳转换)
- 优化字段映射和转换逻辑
- 添加飞书集成功能
- 改进对话历史合并功能
- 优化系统优化反馈机制
2025-09-19 17:29:33 +01:00

305 lines
10 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.
# -*- coding: utf-8 -*-
"""
飞书同步蓝图
处理飞书多维表格与工单系统的同步
"""
from flask import Blueprint, request, jsonify
from src.integrations.feishu_client import FeishuClient
from src.integrations.workorder_sync import WorkOrderSyncService
from src.integrations.config_manager import config_manager
import logging
logger = logging.getLogger(__name__)
feishu_sync_bp = Blueprint('feishu_sync', __name__, url_prefix='/api/feishu-sync')
# 全局同步服务实例
sync_service = None
def get_sync_service():
"""获取同步服务实例"""
global sync_service
if sync_service is None:
# 从配置管理器读取飞书配置
feishu_config = config_manager.get_feishu_config()
if not all([feishu_config.get("app_id"), feishu_config.get("app_secret"),
feishu_config.get("app_token"), feishu_config.get("table_id")]):
raise Exception("飞书配置不完整,请先配置飞书应用信息")
feishu_client = FeishuClient(feishu_config["app_id"], feishu_config["app_secret"])
sync_service = WorkOrderSyncService(feishu_client, feishu_config["app_token"], feishu_config["table_id"])
return sync_service
@feishu_sync_bp.route('/config', methods=['GET', 'POST'])
def manage_config():
"""管理飞书同步配置"""
if request.method == 'GET':
# 返回当前配置
try:
config_summary = config_manager.get_config_summary()
return jsonify({
"success": True,
"config": config_summary
})
except Exception as e:
logger.error(f"获取配置失败: {e}")
return jsonify({"error": str(e)}), 500
elif request.method == 'POST':
# 更新配置
try:
data = request.get_json()
app_id = data.get('app_id')
app_secret = data.get('app_secret')
app_token = data.get('app_token')
table_id = data.get('table_id')
if not all([app_id, app_secret, app_token, table_id]):
return jsonify({"error": "缺少必要配置参数"}), 400
# 更新配置管理器
success = config_manager.update_feishu_config(
app_id=app_id,
app_secret=app_secret,
app_token=app_token,
table_id=table_id
)
if success:
# 重新初始化同步服务
global sync_service
sync_service = None # 强制重新创建
return jsonify({
"success": True,
"message": "配置更新成功"
})
else:
return jsonify({"error": "配置更新失败"}), 500
except Exception as e:
logger.error(f"更新飞书配置失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/sync-from-feishu', methods=['POST'])
def sync_from_feishu():
"""从飞书同步数据到本地"""
try:
data = request.get_json() or {}
generate_ai = data.get('generate_ai_suggestions', True)
limit = data.get('limit', 10)
sync_service = get_sync_service()
result = sync_service.sync_from_feishu(generate_ai_suggestions=generate_ai, limit=limit)
if result.get("success"):
message = f"同步完成:创建 {result['created_count']} 条,更新 {result['updated_count']}"
if result.get('ai_suggestions_generated'):
message += "AI建议已生成并更新到飞书表格"
return jsonify({
"success": True,
"message": message,
"details": result
})
else:
return jsonify({"error": result.get("error")}), 500
except Exception as e:
logger.error(f"从飞书同步失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/sync-to-feishu/<int:workorder_id>', methods=['POST'])
def sync_to_feishu(workorder_id):
"""将本地工单同步到飞书"""
try:
sync_service = get_sync_service()
result = sync_service.sync_to_feishu(workorder_id)
if result.get("success"):
return jsonify({
"success": True,
"message": "同步到飞书成功"
})
else:
return jsonify({"error": result.get("error")}), 500
except Exception as e:
logger.error(f"同步到飞书失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/status')
def get_sync_status():
"""获取同步状态"""
try:
sync_service = get_sync_service()
status = sync_service.get_sync_status()
return jsonify({
"success": True,
"status": status
})
except Exception as e:
logger.error(f"获取同步状态失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/test-connection')
def test_connection():
"""测试飞书连接"""
try:
# 使用配置管理器测试连接
result = config_manager.test_feishu_connection()
if result.get("success"):
# 如果连接成功,尝试获取表格字段信息
try:
sync_service = get_sync_service()
# 使用新的测试连接方法
connection_test = sync_service.feishu_client.test_connection()
if not connection_test.get("success"):
return jsonify({
"success": False,
"message": f"飞书连接测试失败: {connection_test.get('message')}"
}), 400
fields_info = sync_service.feishu_client.get_table_fields(
sync_service.app_token, sync_service.table_id
)
if fields_info.get("code") == 0:
result["fields"] = fields_info.get("data", {}).get("items", [])
except Exception as e:
logger.warning(f"获取表格字段信息失败: {e}")
return jsonify(result)
except Exception as e:
logger.error(f"测试飞书连接失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/create-workorder', methods=['POST'])
def create_workorder_from_feishu():
"""从飞书记录创建工单"""
try:
data = request.get_json()
record_id = data.get('record_id')
if not record_id:
return jsonify({"success": False, "message": "缺少记录ID"}), 400
sync_service = get_sync_service()
result = sync_service.create_workorder_from_feishu_record(record_id)
if result.get("success"):
return jsonify(result)
else:
return jsonify(result), 400
except Exception as e:
logger.error(f"创建工单失败: {e}")
return jsonify({"success": False, "message": str(e)}), 500
@feishu_sync_bp.route('/preview-feishu-data')
def preview_feishu_data():
"""预览飞书数据"""
try:
sync_service = get_sync_service()
# 获取前10条记录进行预览
records = sync_service.feishu_client.get_table_records(
sync_service.app_token, sync_service.table_id, page_size=10
)
if records.get("code") == 0:
items = records.get("data", {}).get("items", [])
preview_data = []
for record in items:
parsed_fields = sync_service.feishu_client.parse_record_fields(record)
preview_data.append({
"record_id": record.get("record_id"),
"fields": parsed_fields
})
return jsonify({
"success": True,
"preview_data": preview_data,
"total_count": len(preview_data)
})
else:
return jsonify({
"success": False,
"error": records.get("msg", "获取数据失败")
}), 500
except Exception as e:
logger.error(f"预览飞书数据失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/config/export', methods=['GET'])
def export_config():
"""导出配置"""
try:
config_json = config_manager.export_config()
return jsonify({
"success": True,
"config": config_json
})
except Exception as e:
logger.error(f"导出配置失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/config/import', methods=['POST'])
def import_config():
"""导入配置"""
try:
data = request.get_json()
config_json = data.get('config')
if not config_json:
return jsonify({"error": "缺少配置数据"}), 400
success = config_manager.import_config(config_json)
if success:
# 重新初始化同步服务
global sync_service
sync_service = None
return jsonify({
"success": True,
"message": "配置导入成功"
})
else:
return jsonify({"error": "配置导入失败"}), 500
except Exception as e:
logger.error(f"导入配置失败: {e}")
return jsonify({"error": str(e)}), 500
@feishu_sync_bp.route('/config/reset', methods=['POST'])
def reset_config():
"""重置配置"""
try:
success = config_manager.reset_config()
if success:
# 重新初始化同步服务
global sync_service
sync_service = None
return jsonify({
"success": True,
"message": "配置重置成功"
})
else:
return jsonify({"error": "配置重置失败"}), 500
except Exception as e:
logger.error(f"重置配置失败: {e}")
return jsonify({"error": str(e)}), 500