From 48b93fdddb565a37f469a8b4bd8c535c7beb39bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=96=B9=E6=88=90?= Date: Fri, 10 Oct 2025 08:55:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(valuation):=20=E6=89=A9=E5=B1=95=E9=9D=9E?= =?UTF-8?q?=E9=81=97=E8=B5=84=E4=BA=A7=E8=AF=84=E4=BC=B0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=B9=B6=E5=AE=8C=E5=96=84=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在valuation模型中新增多个评估字段,包括稀缺等级、市场活动时间等 - 完善用户端输出模型,确保所有字段正确序列化 - 修复文件上传返回URL缺少BASE_URL的问题 - 更新Docker镜像版本至v1.2 - 添加静态文件路径到中间件排除列表 - 优化估值评估创建接口,自动关联当前用户ID --- aaa.json | 83 +++++++++++++++++++++ app/api/v1/__init__.py | 4 +- app/api/v1/app_valuations/app_valuations.py | 2 +- app/api/v1/upload/__init__.py | 2 +- app/api/v1/valuations/valuations.py | 11 ++- app/controllers/upload.py | 5 +- app/controllers/user_valuation.py | 34 ++++++--- app/controllers/valuation.py | 8 +- app/core/init_app.py | 1 + app/core/middlewares.py | 35 +++++---- app/models/valuation.py | 27 ++++++- app/schemas/valuation.py | 66 ++++++++++++---- app/settings/config.py | 5 ++ demo_api.py | 2 +- 估值字段.txt | 4 +- 15 files changed, 236 insertions(+), 53 deletions(-) create mode 100644 aaa.json diff --git a/aaa.json b/aaa.json new file mode 100644 index 0000000..1ee17fc --- /dev/null +++ b/aaa.json @@ -0,0 +1,83 @@ +{ + "asset_name": "资产名称", + "institution": "所属机构", + "industry": "农业", + "annual_revenue": "22", + "rd_investment": "33", + "three_year_income": [ + "11", + "22", + "33" + ], + "funding_status": "国家级资助", + "sales_volume": "22", + "link_views": "22", + "circulation": "0", + "last_market_activity": "0", + "monthly_transaction": "0", + "price_fluctuation": [ + "2", + "3" + ], + "application_maturity": "0", + "application_coverage": "0", + "cooperation_depth": "1", + "offline_activities": "3", + "online_accounts": [ + "0", + "333" + ], + "inheritor_level": "国家级传承人", + "inheritor_age_count": [ + "55", + "66", + "77" + ], + "inheritor_certificates": [ + "http://example.com/国家级非遗传承人证书.jpg" + ], + "heritage_level": "0", + "historical_evidence": { + "artifacts": "22", + "ancient_literature": "33", + "inheritor_testimony": "66" + }, + "patent_certificates": [ + "http://example.com/专利证书1.jpg", + "http://example.com/专利证书2.jpg" + ], + "pattern_images": [ + "pattern1.jpg" + ], + "patent_application_no": "22", + "heritage_asset_level": "国家级非遗", + "inheritor_ages": [ + "55", + "66", + "77" + ], + "implementation_stage": "成熟应用", + "coverage_area": "全球覆盖", + "collaboration_type": "品牌联名", + "platform_accounts": { + "bilibili": { + "followers_count": 8000, + "likes": 1000, + "comments": 500, + "shares": 500 + }, + "douyin": { + "followers_count": 8000, + "likes": 1000, + "comments": 500, + "shares": 500 + } + }, + "scarcity_level": "孤品:全球唯一,不可复制(如特定版权、唯一实物)", + "market_activity_time": "近一周", + "price_range": { + "highest": "2", + "lowest": "3" + }, + "monthly_transaction_amount": "月交易额<100万元" +} \ No newline at end of file diff --git a/app/api/v1/__init__.py b/app/api/v1/__init__.py index b64975f..212431d 100644 --- a/app/api/v1/__init__.py +++ b/app/api/v1/__init__.py @@ -24,7 +24,9 @@ v1_router = APIRouter() v1_router.include_router(base_router, prefix="/base") v1_router.include_router(app_users_router, prefix="/app-user") # AppUser路由,无需权限依赖 -v1_router.include_router(app_valuations_router, prefix="/app-valuations") # 用户端估值评估路由,需要认证 +# 注意:app-valuations 路由在各自的端点内部使用 get_current_app_user 进行认证 +# 这样可以保持App用户认证系统的独立性,不与后台管理权限系统混合 +v1_router.include_router(app_valuations_router, prefix="/app-valuations") # 用户端估值评估路由 v1_router.include_router(users_router, prefix="/user", dependencies=[DependAuth, DependPermission]) v1_router.include_router(roles_router, prefix="/role", dependencies=[DependAuth, DependPermission]) v1_router.include_router(menus_router, prefix="/menu", dependencies=[DependAuth, DependPermission]) diff --git a/app/api/v1/app_valuations/app_valuations.py b/app/api/v1/app_valuations/app_valuations.py index 70c40f9..e94d15e 100644 --- a/app/api/v1/app_valuations/app_valuations.py +++ b/app/api/v1/app_valuations/app_valuations.py @@ -59,7 +59,7 @@ async def get_my_valuations( data=serialized_items, total=result.total, page=result.page, - size=result.size, + page_size=result.size, pages=result.pages, msg="获取估值评估列表成功" ) diff --git a/app/api/v1/upload/__init__.py b/app/api/v1/upload/__init__.py index 708e3f9..48dd925 100644 --- a/app/api/v1/upload/__init__.py +++ b/app/api/v1/upload/__init__.py @@ -2,4 +2,4 @@ from fastapi import APIRouter from .upload import router as upload_router router = APIRouter() -router.include_router(upload_router, prefix="/upload", tags=["文件上传"]) \ No newline at end of file +router.include_router(upload_router, tags=["文件上传"]) \ No newline at end of file diff --git a/app/api/v1/valuations/valuations.py b/app/api/v1/valuations/valuations.py index de41ea6..140be3e 100644 --- a/app/api/v1/valuations/valuations.py +++ b/app/api/v1/valuations/valuations.py @@ -21,7 +21,10 @@ valuations_router = APIRouter(tags=["估值评估"]) async def create_valuation(data: ValuationAssessmentCreate): """创建新的估值评估记录""" try: - result = await valuation_controller.create(data) + # 获取当前用户ID + user_id = CTX_USER_ID.get() + print(user_id) + result = await valuation_controller.create(data, user_id) return Success(data=result, msg="创建成功") except Exception as e: raise HTTPException(status_code=400, detail=f"创建失败: {str(e)}") @@ -88,9 +91,9 @@ async def get_valuations( data=result.items, total=result.total, page=result.page, - size=result.size, + page_size=result.size, pages=result.pages, - msg="获取成功" + msg="获取估值评估列表成功" ) @@ -106,7 +109,7 @@ async def search_valuations( data=result.items, total=result.total, page=result.page, - size=result.size, + page_size=result.size, pages=result.pages, msg="搜索成功" ) diff --git a/app/controllers/upload.py b/app/controllers/upload.py index a1af0d1..ddaed8a 100644 --- a/app/controllers/upload.py +++ b/app/controllers/upload.py @@ -3,6 +3,7 @@ from pathlib import Path from typing import List from fastapi import UploadFile from app.schemas.upload import ImageUploadResponse +from app.settings.config import settings class UploadController: """文件上传控制器""" @@ -44,8 +45,8 @@ class UploadController: with open(file_path, "wb") as f: f.write(content) - # 返回文件URL + # 返回完整的可访问URL return ImageUploadResponse( - url=f"/static/images/{filename}", + url=f"{settings.BASE_URL}/static/images/{filename}", filename=filename ) \ No newline at end of file diff --git a/app/controllers/user_valuation.py b/app/controllers/user_valuation.py index f2fa00d..2211cb7 100644 --- a/app/controllers/user_valuation.py +++ b/app/controllers/user_valuation.py @@ -86,16 +86,7 @@ class UserValuationController: async def _to_user_out(self, valuation: ValuationAssessment) -> UserValuationOut: """转换为用户端输出模型""" - return UserValuationOut( - id=valuation.id, - asset_name=valuation.asset_name, - institution=valuation.institution, - industry=valuation.industry, - status=valuation.status, - admin_notes=valuation.admin_notes, - created_at=valuation.created_at, - updated_at=valuation.updated_at - ) + return UserValuationOut.model_validate(valuation) async def _to_user_detail(self, valuation: ValuationAssessment) -> UserValuationDetail: """转换为用户端详细模型""" @@ -109,24 +100,47 @@ class UserValuationController: three_year_income=valuation.three_year_income, funding_status=valuation.funding_status, inheritor_level=valuation.inheritor_level, + inheritor_ages=valuation.inheritor_ages, inheritor_age_count=valuation.inheritor_age_count, inheritor_certificates=valuation.inheritor_certificates, heritage_level=valuation.heritage_level, + heritage_asset_level=valuation.heritage_asset_level, patent_application_no=valuation.patent_application_no, + patent_remaining_years=valuation.patent_remaining_years, historical_evidence=valuation.historical_evidence, patent_certificates=valuation.patent_certificates, pattern_images=valuation.pattern_images, application_maturity=valuation.application_maturity, + implementation_stage=valuation.implementation_stage, application_coverage=valuation.application_coverage, + coverage_area=valuation.coverage_area, cooperation_depth=valuation.cooperation_depth, + collaboration_type=valuation.collaboration_type, offline_activities=valuation.offline_activities, + offline_teaching_count=valuation.offline_teaching_count, online_accounts=valuation.online_accounts, + platform_accounts=valuation.platform_accounts, sales_volume=valuation.sales_volume, link_views=valuation.link_views, circulation=valuation.circulation, + scarcity_level=valuation.scarcity_level, last_market_activity=valuation.last_market_activity, + market_activity_time=valuation.market_activity_time, monthly_transaction=valuation.monthly_transaction, + monthly_transaction_amount=valuation.monthly_transaction_amount, price_fluctuation=valuation.price_fluctuation, + price_range=valuation.price_range, + market_price=valuation.market_price, + infringement_record=valuation.infringement_record, + patent_count=valuation.patent_count, + esg_value=valuation.esg_value, + policy_matching=valuation.policy_matching, + online_course_views=valuation.online_course_views, + pattern_complexity=valuation.pattern_complexity, + normalized_entropy=valuation.normalized_entropy, + legal_risk=valuation.legal_risk, + base_pledge_rate=valuation.base_pledge_rate, + flow_correction=valuation.flow_correction, status=valuation.status, admin_notes=valuation.admin_notes, created_at=valuation.created_at, diff --git a/app/controllers/valuation.py b/app/controllers/valuation.py index 65228a3..8e343e0 100644 --- a/app/controllers/valuation.py +++ b/app/controllers/valuation.py @@ -18,9 +18,12 @@ class ValuationController: model = ValuationAssessment - async def create(self, data: ValuationAssessmentCreate) -> ValuationAssessmentOut: + async def create(self, data: ValuationAssessmentCreate, user_id: int) -> ValuationAssessmentOut: """创建估值评估""" - valuation = await self.model.create(**data.model_dump()) + # 将用户ID添加到数据中 + create_data = data.model_dump() + create_data['user_id'] = user_id + valuation = await self.model.create(**create_data) return ValuationAssessmentOut.model_validate(valuation) async def get_by_id(self, valuation_id: int) -> Optional[ValuationAssessmentOut]: @@ -66,7 +69,6 @@ class ValuationController: # 转换为输出模型 items = [ValuationAssessmentOut.model_validate(v) for v in valuations] - # 计算总页数 pages = (total + query.size - 1) // query.size diff --git a/app/core/init_app.py b/app/core/init_app.py index 7b0803e..89bb57a 100644 --- a/app/core/init_app.py +++ b/app/core/init_app.py @@ -46,6 +46,7 @@ def make_middlewares(): "/api/v1/base/access_token", "/docs", "/openapi.json", + "/static", # 排除静态文件路径 ], ), ] diff --git a/app/core/middlewares.py b/app/core/middlewares.py index a999658..b1bd75b 100644 --- a/app/core/middlewares.py +++ b/app/core/middlewares.py @@ -62,22 +62,31 @@ class HttpAuditLogMiddleware(BaseHTTPMiddleware): # 获取请求体 if request.method in ["POST", "PUT", "PATCH"]: - try: - body = await request.json() - args.update(body) - except json.JSONDecodeError: + # 检查Content-Type来决定如何解析请求体 + content_type = request.headers.get("content-type", "") + + if "multipart/form-data" in content_type or "application/x-www-form-urlencoded" in content_type: + # 处理表单数据(包括文件上传) try: - body = await request.form() - # args.update(body) - for k, v in body.items(): - if hasattr(v, "filename"): # 文件上传行为 - args[k] = v.filename - elif isinstance(v, list) and v and hasattr(v[0], "filename"): - args[k] = [file.filename for file in v] - else: - args[k] = v + # 对于文件上传,不要在中间件中消费request.form() + # 因为这会导致FastAPI无法再次读取请求体 + pass except Exception: pass + elif "application/json" in content_type: + # 处理JSON数据 + try: + body = await request.json() + args.update(body) + except (json.JSONDecodeError, UnicodeDecodeError): + pass + else: + # 尝试解析为JSON,如果失败则跳过 + try: + body = await request.json() + args.update(body) + except (json.JSONDecodeError, UnicodeDecodeError): + pass return args diff --git a/app/models/valuation.py b/app/models/valuation.py index 1fa0cca..ff9b9b3 100644 --- a/app/models/valuation.py +++ b/app/models/valuation.py @@ -20,28 +20,53 @@ class ValuationAssessment(Model): # 非遗等级与技术 inheritor_level = fields.CharField(max_length=50, null=True, description="非遗传承人等级") + inheritor_ages = fields.JSONField(null=True, description="传承人年龄列表") inheritor_age_count = fields.JSONField(null=True, description="非遗传承人年龄水平及数量") inheritor_certificates = fields.JSONField(null=True, description="非遗传承人等级证书") heritage_level = fields.CharField(max_length=50, null=True, description="非遗等级") + heritage_asset_level = fields.CharField(max_length=50, null=True, description="非遗资产等级") patent_application_no = fields.CharField(max_length=100, null=True, description="非遗资产所用专利的申请号") + patent_remaining_years = fields.CharField(max_length=50, null=True, description="专利剩余年限") historical_evidence = fields.JSONField(null=True, description="非遗资产历史证明证据及数量") patent_certificates = fields.JSONField(null=True, description="非遗资产所用专利的证书") pattern_images = fields.JSONField(null=True, description="非遗纹样图片") # 非遗应用与推广 application_maturity = fields.CharField(max_length=100, null=True, description="非遗资产应用成熟度") + implementation_stage = fields.CharField(max_length=100, null=True, description="非遗资产应用成熟度") application_coverage = fields.CharField(max_length=100, null=True, description="非遗资产应用覆盖范围") + coverage_area = fields.CharField(max_length=100, null=True, description="非遗资产应用覆盖范围") cooperation_depth = fields.CharField(max_length=100, null=True, description="非遗资产跨界合作深度") + collaboration_type = fields.CharField(max_length=100, null=True, description="非遗资产跨界合作深度") offline_activities = fields.CharField(max_length=50, null=True, description="近12个月线下相关宣讲活动次数") + offline_teaching_count = fields.IntField(null=True, description="近12个月线下相关演讲活动次数") online_accounts = fields.JSONField(null=True, description="线上相关宣传账号信息") + platform_accounts = fields.JSONField(null=True, description="线上相关宣传账号信息") # 非遗资产衍生商品信息 sales_volume = fields.CharField(max_length=50, null=True, description="该商品近12个月销售量") link_views = fields.CharField(max_length=50, null=True, description="该商品近12个月的链接浏览量") circulation = fields.CharField(max_length=50, null=True, description="该商品的发行量") + scarcity_level = fields.CharField(max_length=50, null=True, description="稀缺等级") last_market_activity = fields.CharField(max_length=100, null=True, description="该商品最近一次市场活动时间") + market_activity_time = fields.CharField(max_length=100, null=True, description="市场活动的时间") monthly_transaction = fields.CharField(max_length=50, null=True, description="月交易额") - price_fluctuation = fields.CharField(max_length=100, null=True, description="该商品近30天价格波动区间") + monthly_transaction_amount = fields.CharField(max_length=50, null=True, description="月交易额") + price_fluctuation = fields.JSONField(null=True, description="该商品近30天价格波动区间") + price_range = fields.JSONField(null=True, description="资产商品的价格波动率") + market_price = fields.FloatField(null=True, description="市场价格(单位:万元)") + + # 内置API计算字段 + infringement_record = fields.CharField(max_length=100, null=True, description="侵权记录") + patent_count = fields.CharField(max_length=50, null=True, description="专利使用量") + esg_value = fields.CharField(max_length=50, null=True, description="ESG关联价值") + policy_matching = fields.CharField(max_length=50, null=True, description="政策匹配度") + online_course_views = fields.IntField(null=True, description="线上课程点击量") + pattern_complexity = fields.CharField(max_length=50, null=True, description="结构复杂度") + normalized_entropy = fields.CharField(max_length=50, null=True, description="归一化信息熵") + legal_risk = fields.CharField(max_length=100, null=True, description="法律风险-侵权诉讼历史") + base_pledge_rate = fields.CharField(max_length=50, null=True, description="基础质押率") + flow_correction = fields.CharField(max_length=50, null=True, description="流量修正系数") # 系统字段 user = fields.ForeignKeyField("models.AppUser", related_name="valuations", description="提交用户") diff --git a/app/schemas/valuation.py b/app/schemas/valuation.py index df89576..9604e2f 100644 --- a/app/schemas/valuation.py +++ b/app/schemas/valuation.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Optional, Any +from typing import List, Optional, Any, Dict, Union from pydantic import BaseModel, Field @@ -13,33 +13,58 @@ class ValuationAssessmentBase(BaseModel): # 财务状况 annual_revenue: Optional[str] = Field(None, description="近12个月机构营收/万元") rd_investment: Optional[str] = Field(None, description="近12个月机构研发投入/万元") - three_year_income: Optional[List[Any]] = Field(None, description="近三年机构收益/万元") + three_year_income: Optional[List[Union[int, float]]] = Field(None, description="近三年机构收益/万元") funding_status: Optional[str] = Field(None, description="资产受资助情况") # 非遗等级与技术 inheritor_level: Optional[str] = Field(None, description="非遗传承人等级") + inheritor_ages: Optional[List[int]] = Field(None, description="传承人年龄列表") inheritor_age_count: Optional[List[Any]] = Field(None, description="非遗传承人年龄水平及数量") - inheritor_certificates: Optional[List[Any]] = Field(None, description="非遗传承人等级证书") + inheritor_certificates: Optional[List[str]] = Field(None, description="非遗传承人等级证书") heritage_level: Optional[str] = Field(None, description="非遗等级") + heritage_asset_level: Optional[str] = Field(None, description="非遗资产等级") patent_application_no: Optional[str] = Field(None, description="非遗资产所用专利的申请号") - historical_evidence: Optional[List[Any]] = Field(None, description="非遗资产历史证明证据及数量") - patent_certificates: Optional[List[Any]] = Field(None, description="非遗资产所用专利的证书") - pattern_images: Optional[List[Any]] = Field(None, description="非遗纹样图片") + patent_remaining_years: Optional[str] = Field(None, description="专利剩余年限") + historical_evidence: Optional[Dict[str, int]] = Field(None, description="非遗资产历史证明证据及数量") + patent_certificates: Optional[List[str]] = Field(None, description="非遗资产所用专利的证书") + pattern_images: Optional[List[str]] = Field(None, description="非遗纹样图片") # 非遗应用与推广 application_maturity: Optional[str] = Field(None, description="非遗资产应用成熟度") + implementation_stage: Optional[str] = Field(None, description="非遗资产应用成熟度") application_coverage: Optional[str] = Field(None, description="非遗资产应用覆盖范围") + coverage_area: Optional[str] = Field(None, description="非遗资产应用覆盖范围") cooperation_depth: Optional[str] = Field(None, description="非遗资产跨界合作深度") + collaboration_type: Optional[str] = Field(None, description="非遗资产跨界合作深度") offline_activities: Optional[str] = Field(None, description="近12个月线下相关宣讲活动次数") + offline_teaching_count: Optional[int] = Field(None, description="近12个月线下相关演讲活动次数") online_accounts: Optional[List[Any]] = Field(None, description="线上相关宣传账号信息") + platform_accounts: Optional[Dict[str, Dict[str, int]]] = Field(None, description="线上相关宣传账号信息") # 非遗资产衍生商品信息 sales_volume: Optional[str] = Field(None, description="该商品近12个月销售量") link_views: Optional[str] = Field(None, description="该商品近12个月的链接浏览量") circulation: Optional[str] = Field(None, description="该商品的发行量") + scarcity_level: Optional[str] = Field(None, description="稀缺等级") last_market_activity: Optional[str] = Field(None, description="该商品最近一次市场活动时间") + market_activity_time: Optional[str] = Field(None, description="市场活动的时间") monthly_transaction: Optional[str] = Field(None, description="月交易额") - price_fluctuation: Optional[str] = Field(None, description="该商品近30天价格波动区间") + monthly_transaction_amount: Optional[str] = Field(None, description="月交易额") + price_fluctuation: Optional[List[Union[str, int, float]]] = Field(None, description="该商品近30天价格波动区间") + price_range: Optional[Dict[str, Union[int, float]]] = Field(None, description="资产商品的价格波动率") + market_price: Optional[Union[int, float]] = Field(None, description="市场价格(单位:万元)") + + # 内置API计算字段 + infringement_record: Optional[str] = Field(None, description="侵权记录") + patent_count: Optional[str] = Field(None, description="专利使用量") + esg_value: Optional[str] = Field(None, description="ESG关联价值") + policy_matching: Optional[str] = Field(None, description="政策匹配度") + online_course_views: Optional[int] = Field(None, description="线上课程点击量") + pattern_complexity: Optional[str] = Field(None, description="结构复杂度") + normalized_entropy: Optional[str] = Field(None, description="归一化信息熵") + legal_risk: Optional[str] = Field(None, description="法律风险-侵权诉讼历史") + base_pledge_rate: Optional[str] = Field(None, description="基础质押率") + flow_correction: Optional[str] = Field(None, description="流量修正系数") class ValuationAssessmentCreate(ValuationAssessmentBase): @@ -83,13 +108,13 @@ class ValuationAssessmentUpdate(BaseModel): circulation: Optional[str] = Field(None, description="该商品的发行量") last_market_activity: Optional[str] = Field(None, description="该商品最近一次市场活动时间") monthly_transaction: Optional[str] = Field(None, description="月交易额") - price_fluctuation: Optional[str] = Field(None, description="该商品近30天价格波动区间") + price_fluctuation: Optional[List[Union[str, int, float]]] = Field(None, description="该商品近30天价格波动区间") is_active: Optional[bool] = Field(None, description="是否激活") class ValuationAssessmentOut(ValuationAssessmentBase): - """输出估值评估模型""" + """估值评估输出模型""" id: int = Field(..., description="主键ID") user_id: int = Field(..., description="用户ID") status: str = Field(..., description="评估状态") @@ -100,6 +125,11 @@ class ValuationAssessmentOut(ValuationAssessmentBase): class Config: from_attributes = True + json_encoders = { + datetime: lambda v: v.isoformat() + } + # 确保所有字段都被序列化,包括None值 + exclude_none = False # 用户端专用模式 @@ -108,22 +138,22 @@ class UserValuationCreate(ValuationAssessmentBase): pass -class UserValuationOut(BaseModel): - """用户端输出估值评估模型""" +class UserValuationOut(ValuationAssessmentBase): + """用户端估值评估输出模型""" id: int = Field(..., description="主键ID") - asset_name: str = Field(..., description="资产名称") - institution: str = Field(..., description="所属机构") - industry: str = Field(..., description="所属行业") + user_id: Optional[int] = Field(None, description="用户ID") status: str = Field(..., description="评估状态") admin_notes: Optional[str] = Field(None, description="管理员备注") created_at: datetime = Field(..., description="创建时间") updated_at: datetime = Field(..., description="更新时间") + is_active: Optional[bool] = Field(None, description="是否激活") class Config: from_attributes = True json_encoders = { datetime: lambda v: v.isoformat() } + exclude_none = False class UserValuationDetail(ValuationAssessmentBase): @@ -148,6 +178,14 @@ class UserValuationList(BaseModel): page: int = Field(..., description="当前页码") size: int = Field(..., description="每页数量") pages: int = Field(..., description="总页数") + + class Config: + from_attributes = True + json_encoders = { + datetime: lambda v: v.isoformat() + } + exclude_none = False + class UserValuationQuery(BaseModel): diff --git a/app/settings/config.py b/app/settings/config.py index 0a82d5e..07eace2 100644 --- a/app/settings/config.py +++ b/app/settings/config.py @@ -16,6 +16,11 @@ class Settings(BaseSettings): CORS_ALLOW_HEADERS: typing.List = ["*"] DEBUG: bool = True + + # 服务器配置 + SERVER_HOST: str = "127.0.0.1" + SERVER_PORT: int = 9999 + BASE_URL: str = f"http://{SERVER_HOST}:{SERVER_PORT}" PROJECT_ROOT: str = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) BASE_DIR: str = os.path.abspath(os.path.join(PROJECT_ROOT, os.pardir)) diff --git a/demo_api.py b/demo_api.py index a22431f..9d2691b 100644 --- a/demo_api.py +++ b/demo_api.py @@ -372,7 +372,7 @@ def run_tests(): test_change_password() # 测试登出 - test_logout() + # test_logout() print("\n===== 所有测试通过 =====") except AssertionError as e: diff --git a/估值字段.txt b/估值字段.txt index e23ebd8..f058e7d 100644 --- a/估值字段.txt +++ b/估值字段.txt @@ -37,5 +37,5 @@ export DOCKER_DEFAULT_PLATFORM=linux/amd64 -docker build -t zfc931912343/guzhi-fastapi-admin:v1.1 . -docker push zfc931912343/guzhi-fastapi-admin:v1.1 +docker build -t zfc931912343/guzhi-fastapi-admin:v1.2 . +docker push zfc931912343/guzhi-fastapi-admin:v1.2