baodan/api/insurance/app.py

169 lines
6.0 KiB
Python
Raw Normal View History

2026-07-23 17:40:12 +08:00
"""淇濆崟鏅鸿兘瀹㈡湇绯荤粺 鈥?鐙珛鍚庣鍏ュ彛
2026-07-23 17:40:12 +08:00
珛閮ㄧ讲鏃朵娇鐢ㄧ殑 Flask 搴旂敤锛屼笉渚濊禆 Dify 睍銆?"""
import os
2026-07-12 14:17:18 +08:00
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
from flask_cors import CORS
from dotenv import load_dotenv
2026-07-23 17:40:12 +08:00
# 鍔犺浇鐜鍙橀噺
load_dotenv()
2026-07-12 14:17:18 +08:00
def setup_logging(app: Flask) -> None:
2026-07-23 17:40:12 +08:00
"""閰嶇疆缁熶竴鐨勬棩蹇楃郴缁熴€?""
2026-07-12 14:17:18 +08:00
log_level = app.config.get('LOG_LEVEL', 'INFO')
log_file = app.config.get('LOG_FILE', 'logs/insurance.log')
2026-07-23 17:40:12 +08:00
# 鍒涘缓鏃ュ織鐩綍
2026-07-12 14:17:18 +08:00
log_dir = os.path.dirname(log_file)
if log_dir and not os.path.exists(log_dir):
os.makedirs(log_dir, exist_ok=True)
2026-07-23 17:40:12 +08:00
# 閰嶇疆鏍规棩蹇楄褰曞櫒
2026-07-12 14:17:18 +08:00
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, log_level.upper(), logging.INFO))
2026-07-23 17:40:12 +08:00
# 鎺у埗鍙拌緭鍑? console_handler = logging.StreamHandler()
2026-07-12 14:17:18 +08:00
console_handler.setLevel(logging.INFO)
console_format = logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
console_handler.setFormatter(console_format)
root_logger.addHandler(console_handler)
2026-07-23 17:40:12 +08:00
# 鏂囦欢杈撳嚭锛堝甫杞浆锛? try:
2026-07-12 14:17:18 +08:00
file_handler = RotatingFileHandler(
log_file,
maxBytes=10 * 1024 * 1024, # 10MB
backupCount=5,
encoding='utf-8'
)
file_handler.setLevel(logging.DEBUG)
file_format = logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s [%(filename)s:%(lineno)d]: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler.setFormatter(file_format)
root_logger.addHandler(file_handler)
except Exception as e:
2026-07-23 17:40:12 +08:00
print(f"[logging] 鏂囦欢鏃ュ織閰嶇疆澶辫触: {e}")
2026-07-12 14:17:18 +08:00
2026-07-23 17:40:12 +08:00
# 灏?print 鏇挎崲涓?logging
2026-07-12 14:17:18 +08:00
import builtins
original_print = builtins.print
def logging_print(*args, **kwargs):
msg = ' '.join(str(arg) for arg in args)
logging.info(msg)
builtins.print = logging_print
def create_app() -> Flask:
2026-07-23 17:40:12 +08:00
"""鍒涘缓 Flask 搴旂敤銆?""
app = Flask(__name__)
2026-07-23 17:40:12 +08:00
# 閰嶇疆
app.config['SECRET_KEY'] = os.getenv('JWT_SECRET', 'baodan-jwt-secret-2026')
app.config['JWT_SECRET'] = os.getenv('JWT_SECRET', 'baodan-jwt-secret-2026')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['REDIS_URL'] = os.getenv('REDIS_URL')
2026-07-23 17:40:12 +08:00
# 閰嶇疆鏃ュ織
2026-07-12 14:17:18 +08:00
setup_logging(app)
2026-07-23 17:40:12 +08:00
# 鏁版嵁搴擄細浼樺厛 DATABASE_URL锛屽叾娆?DB_* 鍙橀噺鏋勫缓 PostgreSQL URL锛屾渶鍚庡洖閫€鍒?SQLite
db_url = os.getenv('DATABASE_URL', '')
if not db_url:
2026-07-23 17:40:12 +08:00
# 浠?DB_* 鐜鍙橀噺鏋勫缓 PostgreSQL URL
db_host = os.getenv('DB_HOST', '')
db_port = os.getenv('DB_PORT', '5432')
db_user = os.getenv('DB_USERNAME', '')
db_pass = os.getenv('DB_PASSWORD', '')
db_name = os.getenv('DB_DATABASE', '')
if db_host and db_user and db_name:
db_url = f"postgresql://{db_user}:{db_pass}@{db_host}:{db_port}/{db_name}"
if db_url and 'postgresql' in db_url:
2026-07-23 17:40:12 +08:00
# 妫€鏌?psycopg2 鏄惁鍙敤
try:
import psycopg2
app.config['SQLALCHEMY_DATABASE_URI'] = db_url
except ImportError:
2026-07-23 17:40:12 +08:00
print("[warning] psycopg2 鏈畨瑁咃紝鍥為€€鍒?SQLite")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///baodan.db'
else:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///baodan.db'
app.config['MIGRATION_ENABLED'] = True
2026-07-23 17:40:12 +08:00
# Dify 閰嶇疆
app.config['BAODAN_API_URL'] = os.getenv('DIFY_BASE_URL', 'http://localhost:5001')
app.config['BAODAN_CHAT_API_KEY'] = os.getenv('DIFY_CHAT_APP_API_KEY', '')
app.config['BAODAN_WORKFLOW_API_KEY'] = os.getenv('DIFY_WORKFLOW_APP_API_KEY', '')
2026-07-23 17:40:12 +08:00
# 浼佷笟寰俊閰嶇疆
app.config['WECOM_CORP_ID'] = os.getenv('WECOM_CORP_ID', '')
app.config['WECOM_SECRET'] = os.getenv('WECOM_SECRET', '')
app.config['WECOM_TOKEN'] = os.getenv('WECOM_TOKEN', '')
app.config['WECOM_AES_KEY'] = os.getenv('WECOM_AES_KEY', '')
app.config['WECOM_WEBHOOK_URL'] = os.getenv('WECOM_WEBHOOK_URL', '')
2026-07-23 17:40:12 +08:00
# 璁垮妯″紡
app.config['GUEST_MODE'] = os.getenv('GUEST_MODE', 'true').lower() == 'true'
2026-07-23 17:40:12 +08:00
# 鍩熷悕锛堝垎浜摼鎺ョ敤锛? app.config['DOMAIN'] = os.getenv('DOMAIN', 'localhost')
# CORS
CORS(app, resources={r"/*": {"origins": "*"}})
2026-07-23 17:40:12 +08:00
# 鍒濆鍖栨暟鎹簱
from insurance.db.database import init_db
init_db(app)
2026-07-23 17:40:12 +08:00
# 鍒濆鍖?Redis
from insurance.db.redis import init_redis
init_redis(app)
2026-07-23 17:40:12 +08:00
# 娉ㄥ唽璺敱
from insurance.routes import register_insurance_routes
register_insurance_routes(app)
2026-07-23 17:40:12 +08:00
# 娉ㄥ唽閿欒澶勭悊鍣? from insurance.utils.error_handler import register_error_handlers
register_error_handlers(app)
2026-07-23 17:40:12 +08:00
# 鍋ュ悍妫€鏌ワ紙妫€鏌ュ疄闄呬緷璧栵級
@app.route('/health')
def health():
2026-07-12 14:17:18 +08:00
checks = {'status': 'ok', 'service': 'baodanagent-api'}
try:
from insurance.db.compat import db
db.session.execute(db.text('SELECT 1'))
checks['database'] = 'ok'
except Exception as e:
checks['database'] = f'error: {str(e)[:100]}'
checks['status'] = 'degraded'
try:
from insurance.db.compat import redis_client
if redis_client:
redis_client.ping()
checks['redis'] = 'ok'
else:
checks['redis'] = 'not configured'
except Exception as e:
checks['redis'] = f'error: {str(e)[:100]}'
checks['status'] = 'degraded'
return checks
return app
2026-07-23 17:40:12 +08:00
# 鍒涘缓搴旂敤瀹炰緥
app = create_app()
if __name__ == '__main__':
port = int(os.getenv('PORT', 5001))
debug = os.getenv('FLASK_DEBUG', 'false').lower() == 'true'
app.run(host='0.0.0.0', port=port, debug=debug)
2026-07-23 17:40:12 +08:00