import json from flask import Flask, request, jsonify from database import DatabaseConfig, init_database from dao import ContentTypeDAO, ContentDAO import logging from datetime import datetime from flask_cors import CORS # 设置日志记录 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # 加载配置 with open("config.json") as f: config = json.load(f) app = Flask(__name__) CORS(app) # 初始化数据库 db_config = DatabaseConfig() init_database() # 初始化数据库和表(如果不存在) # 新的API端点:ContentType相关 @app.route("/api/v1/type/save", methods=["POST"]) def save_contenttype(): """保存ContentType的API端点""" connection = None try: # 从请求中获取JSON数据 data = request.get_json() if not data: return jsonify({"error": "未提供数据"}), 400 # 检查是否是单个对象还是列表 if isinstance(data, list): # 处理多个记录 - 使用单个连接和事务 connection = db_config.get_connection() if not connection: return jsonify({"error": "数据库连接失败"}), 500 results = [] errors = [] try: for i, item in enumerate(data): # 为每个项目创建一个包含数据库连接的配置 class TempDbConfig: def get_connection(self): return connection result, error = ContentTypeDAO.save_contenttype( item, TempDbConfig() ) if error: errors.append({"index": i, "error": error, "data": item}) else: results.append(result) connection.commit() # 提交所有更改 response_data = { "saved": results, "errors": errors, "total_saved": len(results), } if errors: # 如果有错误,返回400状态码 status_code = ( 400 if any( err["error"] in ["代码已存在", "代码和名称是必需的"] for err in errors ) else 500 ) return jsonify(response_data), status_code else: # 如果没有错误,检查是否有更新的记录 has_updates = any("更新" in r["message"] for r in results) return jsonify(response_data), 200 if has_updates else 201 except Exception as e: if connection: connection.rollback() logger.error(f"批量保存ContentType时出错: {e}") return jsonify({"error": "批量保存操作失败"}), 500 finally: if connection: connection.close() else: # 处理单个记录 result, error = ContentTypeDAO.save_contenttype(data, db_config) if error: if error == "代码已存在" or error == "代码和名称是必需的": return jsonify({"error": error}), 400 else: return jsonify({"error": error}), 500 return jsonify(result), 200 if "更新" in result["message"] else 201 except Exception as e: if connection: try: connection.rollback() connection.close() except Exception as close_error: logger.error(f"关闭连接时出错: {close_error}") logger.error(f"save_contenttype中的意外错误: {e}") return jsonify({"error": "无效的请求格式"}), 400 @app.route("/api/v1/type/get", methods=["GET"]) def get_contenttype(): """从数据库检索ContentType的API端点""" try: # 获取查询参数 code = request.args.get("code", "").strip() record_id = request.args.get("id") limit = request.args.get("limit", type=int) # 验证参数 if record_id and not record_id.isdigit(): return jsonify({"error": "无效的ID参数"}), 400 if limit and limit <= 0: return jsonify({"error": "限制必须是正整数"}), 400 # 使用DAO进行数据库操作 result, error = ContentTypeDAO.get_contenttype( contenttype=record_id, code=code, limit=limit, db_config=db_config ) if error: return jsonify({"error": error}), 500 result["timestamp"] = datetime.now().isoformat() return jsonify(result), 200 except Exception as e: logger.error(f"get_contenttype中的意外错误: {e}") return jsonify({"error": "无效的请求参数"}), 400 # 新的API端点:Content相关 @app.route("/api/v1/content/save", methods=["POST"]) def save_content(): """保存Content的API端点""" connection = None try: # 从请求中获取JSON数据 data = request.get_json() if not data: return jsonify({"error": "未提供数据"}), 400 # 检查是否是单个对象还是列表 if isinstance(data, list): # 处理多个记录 - 使用单个连接和事务 connection = db_config.get_connection() if not connection: return jsonify({"error": "数据库连接失败"}), 500 results = [] errors = [] try: for i, item in enumerate(data): # 为每个项目创建一个包含数据库连接的配置 class TempDbConfig: def get_connection(self): return connection result, error = ContentDAO.save_content(item, TempDbConfig()) if error: errors.append({"index": i, "error": error, "data": item}) else: results.append(result) connection.commit() # 提交所有更改 response_data = { "saved": results, "errors": errors, "total_saved": len(results), } if errors: # 如果有错误,返回400状态码 status_code = ( 400 if any( err["error"] in ["类型、问题和答案是必需的", "指定的类型ID不存在"] for err in errors ) else 500 ) return jsonify(response_data), status_code else: return jsonify(response_data), 201 except Exception as e: if connection: connection.rollback() logger.error(f"批量保存Content时出错: {e}") return jsonify({"error": "批量保存操作失败"}), 500 finally: if connection: connection.close() else: # 处理单个记录 result, error = ContentDAO.save_content(data, db_config) if error: if error in ["类型、问题和答案是必需的", "指定的类型ID不存在"]: return jsonify({"error": error}), 400 else: return jsonify({"error": error}), 500 return jsonify(result), 201 if "更新" not in result["message"] else 200 except Exception as e: if connection: try: connection.rollback() connection.close() except Exception as close_error: logger.error(f"关闭连接时出错: {close_error}") logger.error(f"save_content中的意外错误: {e}") return jsonify({"error": "无效的请求格式"}), 400 @app.route("/api/v1/content/get", methods=["GET"]) def get_content(): """从数据库检索Content的API端点""" try: # 获取查询参数 content_type = request.args.get("type", type=int) record_id = request.args.get("id", type=int) limit = request.args.get("limit", type=int) # 验证参数 if record_id and record_id <= 0: return jsonify({"error": "无效的ID参数"}), 400 if limit and limit <= 0: return jsonify({"error": "限制必须是正整数"}), 400 # 使用DAO进行数据库操作 result, error = ContentDAO.get_content( content_id=record_id, content_type=content_type, limit=limit, db_config=db_config, ) if error: return jsonify({"error": error}), 500 result["timestamp"] = datetime.now().isoformat() return jsonify(result), 200 except Exception as e: logger.error(f"get_content中的意外错误: {e}") return jsonify({"error": "无效的请求参数"}), 400 @app.route("/api/v1/content/delete", methods=["DELETE"]) def delete_content(): """根据ID删除Content的API端点""" try: # 从请求中获取JSON数据 data = request.get_json() if not data: # 也可以从URL参数获取ID content_id = request.args.get("id", type=int) if content_id is None: return jsonify({"error": "未提供数据或ID参数"}), 400 else: # 从JSON数据中获取ID content_id = data.get("id") if content_id is None or not isinstance(content_id, int) or content_id <= 0: return jsonify({"error": "ID是必需的,且必须是正整数"}), 400 # 使用DAO进行删除操作 result, error = ContentDAO.delete_content(content_id, db_config) if error: if error == "指定的ID不存在": return jsonify({"error": error}), 404 else: return jsonify({"error": error}), 500 return jsonify(result), 200 except Exception as e: logger.error(f"delete_content中的意外错误: {e}") return jsonify({"error": "无效的请求格式"}), 400 # 健康检查端点 @app.route("/health", methods=["GET"]) def health_check(): """健康检查端点,验证服务是否正在运行""" return ( jsonify( { "status": "OK", "message": "服务正在运行", "timestamp": datetime.now().isoformat(), } ), 200, ) if __name__ == "__main__": # 获取服务器配置 server_config = config["server"] logger.info(f"在 {server_config['host']}:{server_config['port']} 上启动服务器") app.run( host=server_config["host"], port=server_config["port"], debug=server_config["debug"], )