From 0005967a133dc5adf7494b5421d3f3b39d44c2ee Mon Sep 17 00:00:00 2001 From: aaron <> Date: Fri, 7 Feb 2025 22:13:38 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=98=E5=8C=96=E5=9B=BE?= =?UTF-8?q?=E7=89=87=20=E4=BF=AE=E5=A4=8D=E7=A7=AF=E5=88=86=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/point.py | 23 ++++++++++--- app/core/imageprocessor.py | 62 ++++++++++++++++++++++++++++++++++ app/core/utils.py | 21 ------------ app/models/merchant.py | 3 +- app/models/merchant_product.py | 4 +-- app/models/order.py | 4 +-- app/models/user.py | 6 +++- 7 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 app/core/imageprocessor.py diff --git a/app/api/endpoints/point.py b/app/api/endpoints/point.py index 2b90550..948ff02 100644 --- a/app/api/endpoints/point.py +++ b/app/api/endpoints/point.py @@ -43,16 +43,31 @@ async def add_points( @router.get("/records", response_model=ResponseModel) async def get_point_records( + skip: int = 0, + limit: int = 20, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """获取积分明细""" + # 获取总记录数 + total = db.query(PointRecordDB).filter( + PointRecordDB.user_id == current_user.userid + ).count() + + # 获取分页数据 records = db.query(PointRecordDB).filter( PointRecordDB.user_id == current_user.userid ).order_by( PointRecordDB.create_time.desc() - ).all() + ).offset(skip).limit(limit).all() - return success_response(data=[ - PointRecordInfo.model_validate(r) for r in records - ]) \ No newline at end of file + # 获取用户当前总积分 + total_points = db.query(UserDB.points).filter( + UserDB.userid == current_user.userid + ).scalar() + + return success_response(data={ + "total": total, # 总记录数 + "total_points": float(total_points), # 当前总积分 + "items": [PointRecordInfo.model_validate(r) for r in records] # 积分记录列表 + }) \ No newline at end of file diff --git a/app/core/imageprocessor.py b/app/core/imageprocessor.py new file mode 100644 index 0000000..9c0edad --- /dev/null +++ b/app/core/imageprocessor.py @@ -0,0 +1,62 @@ +from enum import Enum +from typing import Optional, List +from urllib.parse import urlparse, urlencode + +class ImageFormat(Enum): + ORIGINAL = "original" + WEBP = "webp" + HEIC = "heic" + TPG = "tpg" + AVIF = "avif" + +class ImageProcessor: + def __init__(self, url: Optional[str]): + self.url = url + self.params = [] + + def thumbnail(self, width: int, height: int) -> 'ImageProcessor': + """缩略图,按比例缩放""" + self.params.append(f"thumbnail/{width}x{height}") + return self + + def crop(self, width: int, height: int) -> 'ImageProcessor': + """居中裁剪""" + self.params.append(f"crop/{width}x{height}") + return self + + def quality(self, value: int) -> 'ImageProcessor': + """设置图片质量 1-100""" + self.params.append(f"quality/{max(1, min(100, value))}") + return self + + def format(self, fmt: ImageFormat) -> 'ImageProcessor': + """转换图片格式""" + if fmt != ImageFormat.ORIGINAL: + self.params.append(f"format/{fmt.value}") + return self + + def blur(self, radius: int = 10) -> 'ImageProcessor': + """高斯模糊""" + self.params.append(f"blur/radius/{radius}") + return self + + def watermark(self, text: str) -> 'ImageProcessor': + """文字水印""" + self.params.append(f"watermark/2/text/{text}") + return self + + def build(self) -> Optional[str]: + """生成最终的图片 URL""" + if not self.url: + return None + + if not self.params: + return self.url + + # 拼接处理参数 + rules = "/".join(self.params) + return f"{self.url}?imageMogr2/{rules}" + +def process_image(url: Optional[str]) -> ImageProcessor: + """创建图片处理器""" + return ImageProcessor(url) \ No newline at end of file diff --git a/app/core/utils.py b/app/core/utils.py index 9abbdb9..96a6ad3 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -28,24 +28,3 @@ class CommonUtils: date_str = now.strftime('%Y%m%d') timestamp = str(int(time.time() * 1000))[-8:] return f"{date_str}{timestamp}" - - @staticmethod - def optimized_image_url(url: Optional[str], quality: int = 60) -> Optional[str]: - """ - 为图片URL添加腾讯云图片处理参数 - :param url: 原始图片URL - :param quality: 图片质量,范围1-100,默认80 - :return: 处理后的URL - """ - if not url: - return url - - # 确保quality在有效范围内 - quality = max(1, min(100, quality)) - - # 如果URL已经包含图片处理参数,则不重复添加 - if "?imageMogr2/quality/" in url: - return url - - # 添加图片处理参数 - return f"{url}?imageMogr2/quality/{quality}" \ No newline at end of file diff --git a/app/models/merchant.py b/app/models/merchant.py index 8d8d441..01f33e5 100644 --- a/app/models/merchant.py +++ b/app/models/merchant.py @@ -6,6 +6,7 @@ from typing import Optional, List from datetime import datetime from .database import Base from app.core.utils import CommonUtils +from app.core.imageprocessor import process_image, ImageFormat # 数据库模型 class MerchantDB(Base): @@ -28,7 +29,7 @@ class MerchantDB(Base): @property def optimized_brand_image_url(self): - return CommonUtils.optimized_image_url(self.brand_image_url) + return process_image(self.brand_image_url).quality(80).thumbnail(width=450, height=450).format(ImageFormat.WEBP).build() class MerchantCreate(BaseModel): user_id: int diff --git a/app/models/merchant_product.py b/app/models/merchant_product.py index a725121..492520e 100644 --- a/app/models/merchant_product.py +++ b/app/models/merchant_product.py @@ -7,7 +7,7 @@ from datetime import datetime from .database import Base import enum from app.core.utils import CommonUtils - +from app.core.imageprocessor import process_image, ImageFormat class ProductStatus(str, enum.Enum): LISTING = "LISTING" # 上架 @@ -33,7 +33,7 @@ class MerchantProductDB(Base): @property def optimized_image_url(self): - return CommonUtils.optimized_image_url(self.image_url) + return process_image(self.image_url).quality(80).thumbnail(width=450, height=450).format(ImageFormat.WEBP).build() # Pydantic 模型 class MerchantProductCreate(BaseModel): diff --git a/app/models/order.py b/app/models/order.py index 874631f..b493dc2 100644 --- a/app/models/order.py +++ b/app/models/order.py @@ -5,7 +5,7 @@ from sqlalchemy.sql import func from pydantic import BaseModel, Field from .database import Base import enum -from app.core.utils import CommonUtils +from app.core.imageprocessor import process_image, ImageFormat class OrderStatus(str, enum.Enum): CREATED = "CREATED" # 已创建 @@ -51,7 +51,7 @@ class ShippingOrderDB(Base): @property def optimized_complete_images(self): if self.complete_images: - return [CommonUtils.optimized_image_url(image) for image in self.complete_images.split(",")] + return [process_image(image).quality(80).thumbnail(width=450, height=450).format(ImageFormat.WEBP).build() for image in self.complete_images.split(",")] return [] class ShippingOrderPackageDB(Base): diff --git a/app/models/user.py b/app/models/user.py index 40e3dd6..be1e426 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -8,7 +8,7 @@ from datetime import datetime import enum import random import string - +from app.core.imageprocessor import process_image, ImageFormat class UserRole(str, enum.Enum): USER = "user" DELIVERYMAN = "deliveryman" @@ -40,6 +40,10 @@ class UserDB(Base): community_id = Column(Integer, ForeignKey("communities.id"), nullable=True) # 归属小区 is_auth = Column(Boolean, nullable=False, default=False) + @property + def optimized_avatar(self): + return process_image(self.avatar).quality(80).thumbnail(width=450, height=450).format(ImageFormat.WEBP).build() + # Pydantic 模型 class UserLogin(BaseModel): phone: str = Field(..., pattern="^1[3-9]\d{9}$")