皓月归尘 92a57fa5d0 feat(models): 添加海关税率管理相关模型和接口
- 在 models 中新增 Version、HtsClass 和 HtsItem 三个模型
- 在 api 中新增 hts 路由和相关接口
- 更新 app.py 和 code.py 以支持海关税率管理功能
2025-03-31 04:25:09 +08:00

582 lines
16 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 _*_
# @Time : 2025/01/17 22:18
# @UpdateTime : 2025/01/17 22:18
# @Author : sonder
# @File : env.py
# @Software : PyCharm
# @Comment : 本程序
import argparse
import os
import sys
from functools import lru_cache
from dotenv import load_dotenv
from pydantic_settings import BaseSettings
class AppSettings(BaseSettings):
"""
应用配置类,用于管理 FastAPI 应用的基本设置。
"""
app_env: str = 'dev'
"""
应用环境,默认为 'dev'
可选值:
- 'dev': 开发环境
- 'prod': 生产环境
"""
app_name: str = 'FasAPI'
"""
应用名称,默认为 'FasAPI'
用于标识当前应用的名称。
"""
app_root_path: str = '/dev-api'
"""
应用的根路径,默认为 '/dev-api'
用于设置 API 的根路径前缀。
"""
app_host: str = '0.0.0.0'
"""
应用绑定的主机地址,默认为 '0.0.0.0'
- '0.0.0.0' 表示监听所有网络接口。
- '127.0.0.1' 表示仅监听本地回环地址。
"""
app_port: int = 9090
"""
应用绑定的端口号,默认为 9090。
确保端口号未被其他服务占用。
"""
app_version: str = '1.0.0'
"""
应用版本号,默认为 '1.0.0'
用于标识当前应用的版本。
"""
app_reload: bool = True
"""
是否启用自动重载,默认为 True。
- True: 启用自动重载,适合开发环境。
- False: 禁用自动重载,适合生产环境。
"""
app_ip_location_query: bool = True
"""
是否启用 IP 地址地理位置查询,默认为 True。
- True: 启用 IP 地址地理位置查询功能。
- False: 禁用 IP 地址地理位置查询功能。
"""
app_same_time_login: bool = True
"""
是否允许同一用户同时登录多个设备,默认为 True。
- True: 允许同一用户同时登录多个设备。
- False: 禁止同一用户同时登录多个设备。
"""
class Config:
env_file_encoding = "utf-8" # 指定文件编码
class JwtSettings(BaseSettings):
"""
JWT 配置类,用于管理 JWTJSON Web Token相关的设置。
"""
jwt_secret_key: str = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55'
"""
JWT 签名密钥,默认为一个随机生成的字符串。
- 用于加密和解密 JWT 令牌。
- 生产环境中应使用更安全的密钥,并妥善保管。
"""
jwt_algorithm: str = 'HS256'
"""
JWT 签名算法,默认为 'HS256'
- 支持的算法包括:
- 'HS256': HMAC + SHA-256
- 'HS384': HMAC + SHA-384
- 'HS512': HMAC + SHA-512
- 'RS256': RSA + SHA-256
- 其他算法请参考 PyJWT 文档。
"""
jwt_salt: str = 'jwt_salt'
"""
JWT 盐值,默认为 'jwt_salt'
- 用于进一步增强 JWT 的安全性,防止彩虹表攻击。
- 生产环境中应使用更复杂的盐值。
"""
jwt_expire_minutes: int = 1440
"""
JWT 令牌的有效期(以分钟为单位),默认为 1440 分钟24 小时)。
- 超过有效期后,令牌将自动失效。
- 可以根据需求调整有效期。
"""
jwt_redis_expire_minutes: int = 30
"""
JWT 令牌在 Redis 中的缓存有效期(以分钟为单位),默认为 30 分钟。
- 用于存储已签发的 JWT 令牌,以便快速验证和吊销。
- 可以根据需求调整缓存有效期。
"""
class Config:
env_file_encoding = "utf-8" # 指定文件编码
class DataBaseSettings(BaseSettings):
"""
数据库配置类,用于管理数据库连接相关的设置。
"""
db_type: str = 'mysql'
"""
数据库类型,默认为 'mysql'
- 支持的数据库类型包括:
- 'mysql': MySQL 数据库
- 'postgresql': PostgreSQL 数据库
- 'sqlite': SQLite 数据库
"""
db_host: str = '127.0.0.1'
"""
数据库主机地址,默认为 '127.0.0.1'
- 如果数据库运行在本地,可以使用 'localhost''127.0.0.1'
- 如果数据库运行在远程服务器,请填写服务器的 IP 地址或域名。
"""
db_port: int = 3306
"""
数据库端口号,默认为 3306。
- MySQL 默认端口号为 3306。
- PostgreSQL 默认端口号为 5432。
- 根据实际数据库类型和配置调整端口号。
"""
db_username: str = 'root'
"""
数据库用户名,默认为 'root'
- 用于连接数据库的用户名。
- 生产环境中应使用具有最小权限的用户。
"""
db_password: str = 'mysqlroot'
"""
数据库密码,默认为 'mysqlroot'
- 用于连接数据库的密码。
- 生产环境中应使用强密码,并妥善保管。
"""
db_database: str = 'fastapi'
"""
数据库名称,默认为 'fastapi'
- 用于指定连接的数据库名称。
- 确保数据库已创建并具有相应的权限。
"""
db_echo: bool = True
"""
是否打印 SQL 语句,默认为 True。
- True: 打印所有执行的 SQL 语句,适合开发和调试。
- False: 不打印 SQL 语句,适合生产环境。
"""
db_max_overflow: int = 10
"""
连接池最大溢出连接数,默认为 10。
- 当连接池中的连接数达到最大值时,允许额外创建的连接数。
- 根据实际负载调整该值。
"""
db_log_level: int = 10
"""
数据库日志级别,默认为 10DEBUG
- 用于控制数据库日志的输出级别。
- 10: DEBUG
- 20: INFO
- 30: WARNING
- 40: ERROR
- 50: CRITICAL
- 根据实际需求调整日志级别。
"""
db_pool_size: int = 50
"""
连接池大小,默认为 50。
- 连接池中保持的最大连接数。
- 根据实际并发需求调整该值。
"""
db_pool_recycle: int = 3600
"""
连接池回收时间(秒),默认为 3600 秒1 小时)。
- 超过该时间的连接会被回收并重新创建。
- 用于避免数据库连接超时问题。
"""
db_pool_timeout: int = 30
"""
连接池超时时间(秒),默认为 30 秒。
- 从连接池获取连接的超时时间。
- 如果超时未获取到连接,会抛出异常。
"""
class Config:
env_file_encoding = "utf-8" # 指定文件编码
class RedisSettings(BaseSettings):
"""
Redis 配置类,用于管理 Redis 连接相关的设置。
"""
redis_host: str = '127.0.0.1'
"""
Redis 主机地址,默认为 '127.0.0.1'
- 如果 Redis 运行在本地,可以使用 'localhost''127.0.0.1'
- 如果 Redis 运行在远程服务器,请填写服务器的 IP 地址或域名。
"""
redis_port: int = 6379
"""
Redis 端口号,默认为 6379。
- Redis 默认端口号为 6379。
- 根据实际 Redis 配置调整端口号。
"""
redis_username: str = ''
"""
Redis 用户名,默认为空。
- 如果 Redis 启用了身份验证,请填写用户名。
- 如果未启用身份验证,可以留空。
"""
redis_password: str = ''
"""
Redis 密码,默认为空。
- 如果 Redis 启用了身份验证,请填写密码。
- 如果未启用身份验证,可以留空。
"""
redis_database: int = 2
"""
Redis 数据库索引,默认为 2。
- Redis 支持多个数据库,索引从 0 开始。
- 根据实际需求选择合适的数据库索引。
"""
class Config:
env_file_encoding = "utf-8" # 指定文件编码
class UploadSettings:
"""
上传配置类,用于管理文件上传和下载的相关设置。
"""
UPLOAD_PREFIX = '/profile'
"""
文件上传的 URL 前缀,默认为 '/profile'
- 用于在访问上传文件时添加到 URL 的前缀。
- 例如:`/profile/example.jpg`。
"""
UPLOAD_PATH = 'data/upload_path'
"""
文件上传的存储路径,默认为 'data/upload_path'
- 上传的文件将存储在此目录中。
- 如果目录不存在,会自动创建。
"""
UPLOAD_MACHINE = 'A'
"""
上传机器的标识,默认为 'A'
- 用于区分不同的上传机器或节点。
- 在多机部署时可以使用此字段。
"""
DEFAULT_ALLOWED_EXTENSION = [
# 图片
'bmp',
'gif',
'jpg',
'jpeg',
'png',
# word excel powerpoint
'doc',
'docx',
'xls',
'csv',
'xlsx',
'ppt',
'pptx',
'html',
'htm',
'txt',
# 压缩文件
'rar',
'zip',
'gz',
'bz2',
# 视频格式
'mp4',
'avi',
'rmvb',
# pdf
'pdf',
'json'
]
"""
默认允许上传的文件扩展名列表。
- 包含常见的图片、文档、压缩文件、视频和 PDF 格式。
- 可以根据需求扩展或修改此列表。
"""
DOWNLOAD_PATH = 'data/download_path'
"""
文件下载的存储路径,默认为 'data/download_path'
- 下载的文件将存储在此目录中。
- 如果目录不存在,会自动创建。
"""
def __init__(self):
"""
初始化方法,确保上传和下载路径存在。
- 如果路径不存在,会自动创建。
"""
if not os.path.exists(self.UPLOAD_PATH):
os.makedirs(self.UPLOAD_PATH)
if not os.path.exists(self.DOWNLOAD_PATH):
os.makedirs(self.DOWNLOAD_PATH)
class EmailSettings(BaseSettings):
"""
邮件配置类,用于管理邮件发送相关的设置。
"""
email_username: str = ""
"""
邮件发送者的用户名,默认为空。
"""
email_password: str = ""
"""
邮件发送者的密码,默认为空。
"""
email_host: str = "smtp.qq.com"
"""
邮件服务器地址,默认为 "smtp.qq.com"
"""
email_port: int = 465
"""
邮件服务器端口,默认为 465。
"""
class Config:
env_file_encoding = "utf-8" # 指定文件编码
class MapSettings(BaseSettings):
"""
地图配置类,用于管理地图相关的设置。
"""
ak: str = ""
"""
控制台-应用管理-创建应用后获取的AK
"""
sk: str = ""
"""
控制台-应用管理-创建应用时校验方式选择sn校验后生成的SK
"""
class CachePathConfig:
"""
缓存目录配置
"""
PATH = os.path.join(os.path.abspath(os.getcwd()), 'caches')
PATHSTR = 'caches'
class ElasticSearchSettings(BaseSettings):
"""
ElasticSearch配置
"""
ES_HOST: str = '127.0.0.1'
"""
ElasticSearch 连接路径
"""
ES_PORT: int = 9200
"""
ElasticSearch 连接端口
"""
ES_USER: str = 'elastic'
"""
ElasticSearch 连接用户名
"""
ES_PASSWORD: str = 'changeme'
"""
ElasticSearch 连接密码
"""
ES_INDEX: str = 'test'
"""
ElasticSearch 索引名称
"""
class GetConfig:
"""
获取配置类,用于集中管理和获取应用的所有配置。
"""
def __init__(self):
"""
初始化方法,解析命令行参数并加载环境变量。
"""
self.parse_cli_args()
@lru_cache()
def get_app_config(self) -> BaseSettings:
"""
获取应用配置。
- 返回 AppSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化应用配置模型
return AppSettings()
@lru_cache()
def get_jwt_config(self) -> BaseSettings:
"""
获取 JWT 配置。
- 返回 JwtSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化 JWT 配置模型
return JwtSettings()
@lru_cache()
def get_database_config(self) -> BaseSettings:
"""
获取数据库配置。
- 返回 DataBaseSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化数据库配置模型
return DataBaseSettings()
@lru_cache()
def get_redis_config(self) -> BaseSettings:
"""
获取 Redis 配置。
- 返回 RedisSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化 Redis 配置模型
return RedisSettings()
@lru_cache()
def get_upload_config(self) -> 'UploadSettings':
"""
获取上传配置。
- 返回 UploadSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化上传配置
return UploadSettings()
@lru_cache()
def get_email_config(self) -> 'EmailSettings':
"""
获取邮件配置。
- 返回 EmailSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化邮件配置
return EmailSettings()
@lru_cache()
def get_map_config(self) -> 'MapSettings':
"""
获取地图配置。
- 返回 MapSettings 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化地图配置
return MapSettings()
@lru_cache()
def get_elasticsearch_config(self) -> 'ElasticSearchSettings':
"""
获取 ElasticSearch 配置。
- 返回 ElasticSearchConfig 的实例。
- 使用 lru_cache 缓存结果,避免重复实例化。
"""
# 实例化 ElasticSearch 配置
return ElasticSearchSettings()
@staticmethod
def parse_cli_args():
"""
解析命令行参数。
- 如果使用 uvicorn 启动,命令行参数无法自定义。
- 否则,使用 argparse 解析自定义命令行参数。
- 根据命令行参数设置环境变量,并加载对应的 .env 文件。
"""
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()
# 上传配置
UploadConfig = get_config.get_upload_config()
# 邮件配置
EmailConfig = get_config.get_email_config()
# 地图配置
MapConfig = get_config.get_map_config()
# ElasticSearch 配置
ElasticSearchConfig = get_config.get_elasticsearch_config()