From 2e21a963d557030e27de91fccfb903a68be626a6 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Tue, 6 Feb 2024 18:38:08 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E8=BF=90=E8=A1=8C=E7=8E=AF=E5=A2=83=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E6=94=AF=E6=8C=81=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E8=BF=90=E8=A1=8C=E5=BA=94?= =?UTF-8?q?=E7=94=A8=20#I91AE9=20#3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dash-fastapi-backend/.env.dev | 50 +++++++ dash-fastapi-backend/.env.prod | 50 +++++++ dash-fastapi-backend/app.py | 19 ++- dash-fastapi-backend/config/database.py | 4 +- dash-fastapi-backend/config/env.py | 131 +++++++++++++++--- dash-fastapi-backend/config/get_redis.py | 10 +- dash-fastapi-backend/config/get_scheduler.py | 10 +- .../controller/login_controller.py | 8 +- .../module_admin/service/login_service.py | 8 +- .../module_admin/service/online_service.py | 2 +- dash-fastapi-frontend/.env.dev | 22 +++ dash-fastapi-frontend/.env.prod | 22 +++ dash-fastapi-frontend/app.py | 3 +- dash-fastapi-frontend/config/env.py | 67 +++++++++ dash-fastapi-frontend/config/global_config.py | 3 +- dash-fastapi-frontend/server.py | 14 +- dash-fastapi-frontend/utils/request.py | 6 +- dash-fastapi-frontend/wsgi.py | 5 +- 18 files changed, 378 insertions(+), 56 deletions(-) create mode 100644 dash-fastapi-backend/.env.dev create mode 100644 dash-fastapi-backend/.env.prod create mode 100644 dash-fastapi-frontend/.env.dev create mode 100644 dash-fastapi-frontend/.env.prod create mode 100644 dash-fastapi-frontend/config/env.py diff --git a/dash-fastapi-backend/.env.dev b/dash-fastapi-backend/.env.dev new file mode 100644 index 0000000..1689376 --- /dev/null +++ b/dash-fastapi-backend/.env.dev @@ -0,0 +1,50 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'dev' +# 应用名称 +APP_NAME = 'Dash-FasAPI-Admin' +# 应用代理路径 +APP_ROOT_PATH = '' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 9099 +# 应用版本 +APP_VERSION= '1.2.0' +# 应用是否开启热重载 +APP_RELOAD = true + +# -------- Jwt配置 -------- +# Jwt秘钥 +JWT_SECRET_KEY = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55' +# Jwt算法 +JWT_ALGORITHM = 'HS256' +# 令牌过期时间 +JWT_EXPIRE_MINUTES = 1440 +# redis中令牌过期时间 +JWT_REDIS_EXPIRE_MINUTES = 30 + + +# -------- 数据库配置 -------- +# 数据库主机 +DB_HOST = '127.0.0.1' +# 数据库端口 +DB_PORT = 3306 +# 数据库用户名 +DB_USERNAME = 'root' +# 数据库密码 +DB_PASSWORD = 'mysqlroot' +# 数据库名称 +DB_DATABASE = 'dash-fastapi' + +# -------- Redis配置 -------- +# Redis主机 +REDIS_HOST = '127.0.0.1' +# Redis端口 +REDIS_PORT = 6379 +# Redis用户名 +REDIS_USERNAME = '' +# Redis密码 +REDIS_PASSWORD = '' +# Redis数据库 +REDIS_DATABASE = 2 \ No newline at end of file diff --git a/dash-fastapi-backend/.env.prod b/dash-fastapi-backend/.env.prod new file mode 100644 index 0000000..bc743e9 --- /dev/null +++ b/dash-fastapi-backend/.env.prod @@ -0,0 +1,50 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'prod' +# 应用名称 +APP_NAME = 'Dash-FasAPI' +# 应用代理路径 +APP_ROOT_PATH = '/prod-api' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 9099 +# 应用版本 +APP_VERSION= '1.2.0' +# 应用是否开启热重载 +APP_RELOAD = false + +# -------- Jwt配置 -------- +# Jwt秘钥 +JWT_SECRET_KEY = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55' +# Jwt算法 +JWT_ALGORITHM = 'HS256' +# 令牌过期时间 +JWT_EXPIRE_MINUTES = 1440 +# redis中令牌过期时间 +JWT_REDIS_EXPIRE_MINUTES = 30 + + +# -------- 数据库配置 -------- +# 数据库主机 +DB_HOST = '127.0.0.1' +# 数据库端口 +DB_PORT = 3306 +# 数据库用户名 +DB_USERNAME = 'root' +# 数据库密码 +DB_PASSWORD = 'mysqlroot' +# 数据库名称 +DB_DATABASE = 'dash-fastapi' + +# -------- Redis配置 -------- +# Redis主机 +REDIS_HOST = '127.0.0.1' +# Redis端口 +REDIS_PORT = 6379 +# Redis用户名 +REDIS_USERNAME = '' +# Redis密码 +REDIS_PASSWORD = '' +# Redis数据库 +REDIS_DATABASE = 2 \ No newline at end of file diff --git a/dash-fastapi-backend/app.py b/dash-fastapi-backend/app.py index 93a8c2a..81d0bce 100644 --- a/dash-fastapi-backend/app.py +++ b/dash-fastapi-backend/app.py @@ -18,6 +18,7 @@ from module_admin.controller.job_controller import jobController from module_admin.controller.server_controller import serverController from module_admin.controller.cache_controller import cacheController from module_admin.controller.common_controller import commonController +from config.env import AppConfig from config.get_redis import RedisUtil from config.get_db import init_create_table from config.get_scheduler import SchedulerUtil @@ -26,9 +27,10 @@ from utils.log_util import logger from utils.common_util import worship app = FastAPI( - title='Dash-FastAPI', - description='Dash-FastAPI接口文档', - version='1.0.0', + title=AppConfig.app_name, + description=f'{AppConfig.app_name}接口文档', + version=AppConfig.app_version, + root_path=AppConfig.app_root_path, ) # 前端页面url @@ -49,14 +51,14 @@ app.add_middleware( @app.on_event("startup") async def startup_event(): - logger.info("Dash-FastAPI开始启动") + logger.info(f"{AppConfig.app_name}开始启动") worship() await init_create_table() app.state.redis = await RedisUtil.create_redis_pool() await RedisUtil.init_sys_dict(app.state.redis) await RedisUtil.init_sys_config(app.state.redis) await SchedulerUtil.init_system_scheduler() - logger.info("Dash-FastAPI启动成功") + logger.info(f"{AppConfig.app_name}启动成功") @app.on_event("shutdown") @@ -103,4 +105,9 @@ app.include_router(cacheController, prefix="/monitor", tags=['系统监控-缓 app.include_router(commonController, prefix="/common", tags=['通用模块']) if __name__ == '__main__': - uvicorn.run(app='app:app', host="0.0.0.0", port=9099, reload=True) + uvicorn.run( + app='app:app', + host=AppConfig.app_host, + port=AppConfig.app_port, + reload=AppConfig.app_reload + ) diff --git a/dash-fastapi-backend/config/database.py b/dash-fastapi-backend/config/database.py index a9acc4c..8d2012f 100644 --- a/dash-fastapi-backend/config/database.py +++ b/dash-fastapi-backend/config/database.py @@ -4,8 +4,8 @@ from sqlalchemy.orm import sessionmaker from urllib.parse import quote_plus from config.env import DataBaseConfig -SQLALCHEMY_DATABASE_URL = f"mysql+pymysql://{DataBaseConfig.USERNAME}:{quote_plus(DataBaseConfig.PASSWORD)}@" \ - f"{DataBaseConfig.HOST}:{DataBaseConfig.PORT}/{DataBaseConfig.DB}" +SQLALCHEMY_DATABASE_URL = f"mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@" \ + f"{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}" engine = create_engine( SQLALCHEMY_DATABASE_URL, echo=True diff --git a/dash-fastapi-backend/config/env.py b/dash-fastapi-backend/config/env.py index be50c11..ce63d17 100644 --- a/dash-fastapi-backend/config/env.py +++ b/dash-fastapi-backend/config/env.py @@ -1,36 +1,54 @@ import os +import sys +import argparse +from pydantic import BaseSettings +from functools import lru_cache +from dotenv import load_dotenv -class JwtConfig: +class AppSettings(BaseSettings): + """ + 应用配置 + """ + app_env: str = 'dev' + app_name: str = 'RuoYi-FasAPI' + app_root_path: str = '/dev-api' + app_host: str = '0.0.0.0' + app_port: int = 9099 + app_version: str = '1.0.0' + app_reload: bool = True + + +class JwtSettings(BaseSettings): """ Jwt配置 """ - SECRET_KEY = "b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55" - ALGORITHM = "HS256" - ACCESS_TOKEN_EXPIRE_MINUTES = 1440 - REDIS_TOKEN_EXPIRE_MINUTES = 30 + jwt_secret_key: str = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55' + jwt_algorithm: str = 'HS256' + jwt_expire_minutes: int = 1440 + jwt_redis_expire_minutes: int = 30 -class DataBaseConfig: +class DataBaseSettings(BaseSettings): """ 数据库配置 """ - HOST = "127.0.0.1" - PORT = 3306 - USERNAME = 'root' - PASSWORD = 'mysqlroot' - DB = 'dash-fastapi' + db_host: str = '127.0.0.1' + db_port: int = 3306 + db_username: str = 'root' + db_password: str = 'mysqlroot' + db_database: str = 'ruoyi-fastapi' -class RedisConfig: +class RedisSettings(BaseSettings): """ Redis配置 """ - HOST = "127.0.0.1" - PORT = 6379 - USERNAME = '' - PASSWORD = '' - DB = 2 + redis_host: str = '127.0.0.1' + redis_port: int = 6379 + redis_username: str = '' + redis_password: str = '' + redis_database: int = 2 class CachePathConfig: @@ -52,3 +70,82 @@ class RedisInitKeyConfig: ACCOUNT_LOCK = {'key': 'account_lock', 'remark': '用户锁定'} PASSWORD_ERROR_COUNT = {'key': 'password_error_count', 'remark': '密码错误次数'} SMS_CODE = {'key': 'sms_code', 'remark': '短信验证码'} + + +class GetConfig: + """ + 获取配置 + """ + + def __init__(self): + self.parse_cli_args() + + @lru_cache() + def get_app_config(self): + """ + 获取应用配置 + """ + # 实例化应用配置模型 + return AppSettings() + + @lru_cache() + def get_jwt_config(self): + """ + 获取Jwt配置 + """ + # 实例化Jwt配置模型 + return JwtSettings() + + @lru_cache() + def get_database_config(self): + """ + 获取数据库配置 + """ + # 实例化数据库配置模型 + return DataBaseSettings() + + @lru_cache() + def get_redis_config(self): + """ + 获取Redis配置 + """ + # 实例化Redis配置模型 + return RedisSettings() + + @staticmethod + def parse_cli_args(): + """ + 解析命令行参数 + """ + if 'uvicorn' in sys.argv[0]: + # 使用uvicorn启动时,命令行参数需要按照uvicorn的文档进行配置,无法自定义参数 + pass + else: + # 使用argparse定义命令行参数 + parser = argparse.ArgumentParser(description='命令行参数') + parser.add_argument('--env', type=str, default='', help='运行环境') + # 解析命令行参数 + args = parser.parse_args() + # 设置环境变量,如果未设置命令行参数,默认APP_ENV为dev + os.environ['APP_ENV'] = args.env if args.env else 'dev' + # 读取运行环境 + run_env = os.environ.get('APP_ENV', '') + # 运行环境未指定时默认加载.env.dev + env_file = '.env.dev' + # 运行环境不为空时按命令行参数加载对应.env文件 + if run_env != '': + env_file = f'.env.{run_env}' + # 加载配置 + load_dotenv(env_file) + + +# 实例化获取配置类 +get_config = GetConfig() +# 应用配置 +AppConfig = get_config.get_app_config() +# Jwt配置 +JwtConfig = get_config.get_jwt_config() +# 数据库配置 +DataBaseConfig = get_config.get_database_config() +# Redis配置 +RedisConfig = get_config.get_redis_config() diff --git a/dash-fastapi-backend/config/get_redis.py b/dash-fastapi-backend/config/get_redis.py index 2890d63..4c3ef80 100644 --- a/dash-fastapi-backend/config/get_redis.py +++ b/dash-fastapi-backend/config/get_redis.py @@ -20,11 +20,11 @@ class RedisUtil: """ logger.info("开始连接redis...") redis = await aioredis.from_url( - url=f"redis://{RedisConfig.HOST}", - port=RedisConfig.PORT, - username=RedisConfig.USERNAME, - password=RedisConfig.PASSWORD, - db=RedisConfig.DB, + url=f"redis://{RedisConfig.redis_host}", + port=RedisConfig.redis_port, + username=RedisConfig.redis_username, + password=RedisConfig.redis_password, + db=RedisConfig.redis_database, encoding="utf-8", decode_responses=True ) diff --git a/dash-fastapi-backend/config/get_scheduler.py b/dash-fastapi-backend/config/get_scheduler.py index af1c633..2e51af4 100644 --- a/dash-fastapi-backend/config/get_scheduler.py +++ b/dash-fastapi-backend/config/get_scheduler.py @@ -70,11 +70,11 @@ job_stores = { 'sqlalchemy': SQLAlchemyJobStore(url=SQLALCHEMY_DATABASE_URL, engine=engine), 'redis': RedisJobStore( **dict( - host=RedisConfig.HOST, - port=RedisConfig.PORT, - username=RedisConfig.USERNAME, - password=RedisConfig.PASSWORD, - db=RedisConfig.DB + host=RedisConfig.redis_host, + port=RedisConfig.redis_port, + username=RedisConfig.redis_username, + password=RedisConfig.redis_password, + db=RedisConfig.redis_database ) ) } diff --git a/dash-fastapi-backend/module_admin/controller/login_controller.py b/dash-fastapi-backend/module_admin/controller/login_controller.py index 19ff188..191d871 100644 --- a/dash-fastapi-backend/module_admin/controller/login_controller.py +++ b/dash-fastapi-backend/module_admin/controller/login_controller.py @@ -32,7 +32,7 @@ async def login(request: Request, form_data: CustomOAuth2PasswordRequestForm = D except LoginException as e: return response_400(data="", message=e.message) try: - access_token_expires = timedelta(minutes=JwtConfig.ACCESS_TOKEN_EXPIRE_MINUTES) + access_token_expires = timedelta(minutes=JwtConfig.jwt_expire_minutes) session_id = str(uuid.uuid4()) access_token = create_access_token( data={ @@ -45,10 +45,10 @@ async def login(request: Request, form_data: CustomOAuth2PasswordRequestForm = D expires_delta=access_token_expires ) await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", access_token, - ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES)) + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) # 此方法可实现同一账号同一时间只能登录一次 # await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{result[0].user_id}", access_token, - # ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES)) + # ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) logger.info('登录成功') # 判断请求是否来自于api文档,如果是返回指定格式的结果,用于修复api文档认证成功后token显示undefined的bug request_from_swagger = request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False @@ -107,7 +107,7 @@ async def get_login_user_info(request: Request, current_user: CurrentUserInfoSer @loginController.post("/logout", dependencies=[Depends(get_current_user), Depends(CheckUserInterfaceAuth('common'))]) async def logout(request: Request, token: Optional[str] = Depends(oauth2_scheme), query_db: Session = Depends(get_db)): try: - payload = jwt.decode(token, JwtConfig.SECRET_KEY, algorithms=[JwtConfig.ALGORITHM]) + payload = jwt.decode(token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) session_id: str = payload.get("session_id") await logout_services(request, session_id) logger.info('退出成功') diff --git a/dash-fastapi-backend/module_admin/service/login_service.py b/dash-fastapi-backend/module_admin/service/login_service.py index ca6f8db..53b133a 100644 --- a/dash-fastapi-backend/module_admin/service/login_service.py +++ b/dash-fastapi-backend/module_admin/service/login_service.py @@ -59,7 +59,7 @@ async def get_current_user(request: Request = Request, token: str = Depends(oaut try: if token.startswith('Bearer'): token = token.split(' ')[1] - payload = jwt.decode(token, JwtConfig.SECRET_KEY, algorithms=[JwtConfig.ALGORITHM]) + payload = jwt.decode(token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) user_id: str = payload.get("user_id") session_id: str = payload.get("session_id") if user_id is None: @@ -78,9 +78,9 @@ async def get_current_user(request: Request = Request, token: str = Depends(oaut # redis_token = await request.app.state.redis.get(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{user.user_basic_info.user_id}") if token == redis_token: await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", redis_token, - ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES)) + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) # await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{user.user_basic_info.user_id}", redis_token, - # ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES)) + # ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) return CurrentUserInfoServiceResponse( user=user.user_basic_info, @@ -227,7 +227,7 @@ def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None else: expire = datetime.utcnow() + timedelta(minutes=15) to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, JwtConfig.SECRET_KEY, algorithm=JwtConfig.ALGORITHM) + encoded_jwt = jwt.encode(to_encode, JwtConfig.jwt_secret_key, algorithm=JwtConfig.jwt_algorithm) return encoded_jwt diff --git a/dash-fastapi-backend/module_admin/service/online_service.py b/dash-fastapi-backend/module_admin/service/online_service.py index 47277ea..6ef9080 100644 --- a/dash-fastapi-backend/module_admin/service/online_service.py +++ b/dash-fastapi-backend/module_admin/service/online_service.py @@ -23,7 +23,7 @@ class OnlineService: access_token_values_list = [await request.app.state.redis.get(key) for key in access_token_keys] online_info_list = [] for item in access_token_values_list: - payload = jwt.decode(item, JwtConfig.SECRET_KEY, algorithms=[JwtConfig.ALGORITHM]) + payload = jwt.decode(item, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) online_dict = dict( session_id=payload.get('session_id'), user_name=payload.get('user_name'), diff --git a/dash-fastapi-frontend/.env.dev b/dash-fastapi-frontend/.env.dev new file mode 100644 index 0000000..6f36848 --- /dev/null +++ b/dash-fastapi-frontend/.env.dev @@ -0,0 +1,22 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'dev' +# 应用名称 +APP_NAME = '通用后台管理系统' +# 应用请求后端url +APP_BASE_URL = 'http://127.0.0.1:9099' +# 后端是否使用代理模式 +APP_IS_PROXY = false +# 应用代理路径 +APP_PROXY_PATH = '' +# 应用秘钥 +APP_SECRET_KEY = 'Dash-FastAPI-Admin' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 8088 +# 应用是否开启debug模式 +APP_DEBUG = true +# flask-compress压缩配置 +APP_COMPRESS_ALGORITHM = 'br' +APP_COMPRESS_BR_LEVEL = 11 \ No newline at end of file diff --git a/dash-fastapi-frontend/.env.prod b/dash-fastapi-frontend/.env.prod new file mode 100644 index 0000000..72685a3 --- /dev/null +++ b/dash-fastapi-frontend/.env.prod @@ -0,0 +1,22 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'prod' +# 应用名称 +APP_NAME = '通用后台管理系统' +# 应用请求后端url +APP_BASE_URL = 'http://127.0.0.1:9099' +# 后端是否使用代理模式 +APP_IS_PROXY = true +# 应用代理路径 +APP_PROXY_PATH = '/prod-api' +# 应用秘钥 +APP_SECRET_KEY = 'Dash-FastAPI-Admin' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 8088 +# 应用是否开启debug模式 +APP_DEBUG = false +# flask-compress压缩配置 +APP_COMPRESS_ALGORITHM = 'br' +APP_COMPRESS_BR_LEVEL = 11 \ No newline at end of file diff --git a/dash-fastapi-frontend/app.py b/dash-fastapi-frontend/app.py index 029167c..e1d840d 100644 --- a/dash-fastapi-frontend/app.py +++ b/dash-fastapi-frontend/app.py @@ -8,6 +8,7 @@ from flask import session from operator import itemgetter from server import app +from config.env import AppConfig from config.global_config import RouterConfig from store.store import render_store_container @@ -256,4 +257,4 @@ def router(pathname, url_trigger, session_token): if __name__ == '__main__': - app.run(host='0.0.0.0', port=8088, debug=True) + app.run(host=AppConfig.app_host, port=AppConfig.app_port, debug=AppConfig.app_debug) diff --git a/dash-fastapi-frontend/config/env.py b/dash-fastapi-frontend/config/env.py new file mode 100644 index 0000000..afa30bb --- /dev/null +++ b/dash-fastapi-frontend/config/env.py @@ -0,0 +1,67 @@ +import os +import argparse +from pydantic import BaseSettings +from functools import lru_cache +from dotenv import load_dotenv + + +class AppSettings(BaseSettings): + """ + 应用配置 + """ + app_env: str = 'dev' + app_name: str = '通用后台管理系统' + app_base_url: str = 'http://127.0.0.1:9099' + app_proxy_path: str = '/dev-api' + app_is_proxy: bool = False + app_secret_key: str = 'Dash-FastAPI-Admin' + app_host: str = '0.0.0.0' + app_port: int = 8088 + app_debug: bool = True + app_compress_algorithm = 'br' + app_compress_br_level = 11 + + +class GetConfig: + """ + 获取配置 + """ + + def __init__(self): + self.parse_cli_args() + + @lru_cache() + def get_app_config(self): + """ + 获取应用配置 + """ + # 实例化应用配置模型 + return AppSettings() + + @staticmethod + def parse_cli_args(): + """ + 解析命令行参数 + """ + # 使用argparse定义命令行参数 + parser = argparse.ArgumentParser(description='命令行参数') + parser.add_argument('--env', type=str, default='', help='运行环境') + # 解析命令行参数 + args = parser.parse_args() + # 设置环境变量,如果未设置命令行参数,默认APP_ENV为dev + os.environ['APP_ENV'] = args.env if args.env else 'dev' + # 读取运行环境 + run_env = os.environ.get('APP_ENV', '') + # 运行环境未指定时默认加载.env.dev + env_file = '.env.dev' + # 运行环境不为空时按命令行参数加载对应.env文件 + if run_env != '': + env_file = f'.env.{run_env}' + # 加载配置 + load_dotenv(env_file) + + +# 实例化获取配置类 +get_config = GetConfig() +# 应用配置 +AppConfig = get_config.get_app_config() diff --git a/dash-fastapi-frontend/config/global_config.py b/dash-fastapi-frontend/config/global_config.py index 3103078..2485a4f 100644 --- a/dash-fastapi-frontend/config/global_config.py +++ b/dash-fastapi-frontend/config/global_config.py @@ -1,4 +1,5 @@ import os +from config.env import AppConfig class PathConfig: @@ -21,7 +22,7 @@ class RouterConfig: class ApiBaseUrlConfig: # api基本url - BaseUrl = 'http://127.0.0.1:9099' + BaseUrl = AppConfig.app_base_url + AppConfig.app_proxy_path if AppConfig.app_is_proxy else AppConfig.app_base_url class IconConfig: diff --git a/dash-fastapi-frontend/server.py b/dash-fastapi-frontend/server.py index d1fc8ea..ada6f7b 100644 --- a/dash-fastapi-frontend/server.py +++ b/dash-fastapi-frontend/server.py @@ -4,6 +4,7 @@ import time from loguru import logger from flask import request, session from user_agents import parse +from config.env import AppConfig from config.global_config import PathConfig app = dash.Dash( @@ -15,12 +16,12 @@ app = dash.Dash( server = app.server -app.title = '通用后台管理系统' +app.title = AppConfig.app_name # 配置密钥 -app.server.secret_key = 'Dash-FastAPI' -app.server.config['COMPRESS_ALGORITHM'] = 'br' -app.server.config['COMPRESS_BR_LEVEL'] = 8 +app.server.secret_key = AppConfig.app_secret_key +app.server.config['COMPRESS_ALGORITHM'] = AppConfig.app_compress_algorithm +app.server.config['COMPRESS_BR_LEVEL'] = AppConfig.app_compress_br_level log_time = time.strftime("%Y%m%d", time.localtime()) # sys_log_file_path = os.path.join(PathConfig.ABS_ROOT_PATH, 'log', 'sys_log', f'sys_request_log_{log_time}.log') @@ -34,17 +35,18 @@ logger.add(api_log_file_path, filter=lambda x: '[api]' in x['message'], # 获取用户浏览器信息 @server.before_request def get_user_agent_info(): + request_addr = request.headers.get("X-Forwarded-For") if AppConfig.app_env == 'prod' else request.remote_addr user_string = str(request.user_agent) user_agent = parse(user_string) bw = user_agent.browser.family bw_version = user_agent.browser.version[0] if bw == 'IE': logger.warning("[sys]请求人:{}||请求IP:{}||请求方法:{}||请求Data:{}", - session.get('name'), request.remote_addr, request.method, '用户使用IE内核') + session.get('name'), request_addr, request.method, '用户使用IE内核') return "
-
+
@@ -97,7 +97,7 @@ Dash-FastAPI-Admin是一套全部开源的快速开发平台,毫无保留给
- *密码:admin123*
- 演示地址:dfadmin管理系统
-## 项目运行相关
+## 项目开发及发布
```bash
# 克隆项目
@@ -110,30 +110,94 @@ cd dash-fastapi-admin
pip3 install -r requirements.txt
```
-### 前端
+### 开发
+
+#### 前端
+```bash
+# 进入前端目录
+cd dash-fastapi-frontend
+
+# 配置应用信息
+在.env.dev文件中配置应用开发模式的相关信息
+
+# 运行前端
+python3 app.py --env=dev
+```
+
+#### 后端
+```bash
+# 进入后端目录
+cd dash-fastapi-backend
+
+# 配置环境
+1.在.env.dev文件中配置开发模式的数据库环境
+2.在.env.dev文件中配置开发模式的redis环境
+
+# 运行sql文件
+1.新建数据库dash-fastapi(默认,可修改)
+2.使用命令或数据库连接工具运行sql文件夹下的dash-fastapi.sql
+
+# 运行后端
+python3 app.py --env=dev
+```
+
+### 发布
+
+本应用发布建议使用nginx部署,nginx代理配置参考如下:
+
+```bash
+server {
+ location / {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://127.0.0.1:8088/;
+ }
+
+ location /prod-api {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://127.0.0.1:9099/;
+ rewrite ^/prod-api/(.*)$ /$1 break;
+ }
+
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root html;
+ }
+}
+```
+
+#### 前端
```bash
# 进入前端目录
cd dash-fastapi-frontend
+# 配置应用信息
+在.env.prod文件中配置应用发布的相关信息,注意:APP_BASE_URL需要配置为nginx代理的地址,例如上面的nginx代理监听的是8000端口,则APP_BASE_URL需要配置为http://127.0.0.1:8000
+
# 运行前端
-python3 wsgi.py
+python3 wsgi.py --env=prod
```
-### 后端
+#### 后端
```bash
# 进入后端目录
cd dash-fastapi-backend
# 配置环境
-1.在config/env.py的DataBaseConfig类中配置数据库环境
-2.在config/env.py的RedisConfig类中配置redis环境
+1.在.env.prod文件中配置生产模式的数据库环境
+2.在.env.prod文件中配置生产模式的redis环境
# 运行sql文件
1.新建数据库dash-fastapi(默认,可修改)
2.使用命令或数据库连接工具运行sql文件夹下的dash-fastapi.sql
# 运行后端
-python3 app.py
+python3 app.py --env=prod
```
### 访问
--
Gitee