From 3e683e9708d5e3a9ebf7da0c58d5f599fb306549 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Fri, 28 Feb 2025 23:14:53 +0800 Subject: [PATCH] add feedback --- app/api/endpoints/feedback.py | 142 ++++++++++++++++++++++++++++++++++ app/core/config.py | 2 + app/main.py | 5 +- app/models/feedback.py | 74 ++++++++++++++++++ 4 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 app/api/endpoints/feedback.py create mode 100644 app/models/feedback.py diff --git a/app/api/endpoints/feedback.py b/app/api/endpoints/feedback.py new file mode 100644 index 0000000..07ec268 --- /dev/null +++ b/app/api/endpoints/feedback.py @@ -0,0 +1,142 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from app.models.database import get_db +from app.models.user import UserDB +from app.api.deps import get_current_user +from app.core.response import success_response, error_response, ResponseModel +from app.models.feedback import ( + FeedbackCommunityApplyDB, + FeedbackPartnerApplyDB, + CommunityApplyCreate, + CommunityApplyInfo, + PartnerApplyCreate, + PartnerApplyInfo +) +from typing import List +import logging +from app.core.config import settings + +router = APIRouter() + +@router.post("/community-apply", response_model=ResponseModel) +async def apply_community( + apply_data: CommunityApplyCreate, + db: Session = Depends(get_db) +): + """申请小区开通""" + try: + + if apply_data.user_id>0: + current_user = db.query(UserDB).filter(UserDB.userid == apply_data.user_id).first() + else: + current_user = get_current_user(db) + + # 创建申请记录 + new_apply = FeedbackCommunityApplyDB( + user_id=current_user.userid, + community_name=apply_data.community_name, + community_address=apply_data.community_address + ) + + db.add(new_apply) + db.commit() + db.refresh(new_apply) + + # 发送企业微信通知 + try: + from app.core.wecombot import WecomBot + wecom_bot = WecomBot() + message = f"""📢 新的小区开通申请 + +> 申请人: {current_user.nickname} +> 联系电话: {current_user.phone} +> 小区名称: {apply_data.community_name} +> 小区地址: {apply_data.community_address} +> 申请时间: {new_apply.create_time} + """ + await wecom_bot.send_markdown(message,webhook_url=settings.FEEDBACK_NEED_WECOM_BOT_WEBHOOK_URL) + except Exception as e: + logging.error(f"发送企业微信通知失败: {str(e)}") + + return success_response(message="申请提交成功,我们会尽快处理", data=CommunityApplyInfo.model_validate(new_apply)) + + except Exception as e: + db.rollback() + logging.exception(f"申请小区开通失败: {str(e)}") + return error_response(code=500, message="申请提交失败,请稍后重试") + +@router.post("/partner-apply", response_model=ResponseModel) +async def apply_partner( + apply_data: PartnerApplyCreate, + db: Session = Depends(get_db), +): + """申请成为合伙人""" + if apply_data.user_id>0: + current_user = db.query(UserDB).filter(UserDB.userid == apply_data.user_id).first() + else: + current_user = get_current_user(db) + + try: + # 创建申请记录 + new_apply = FeedbackPartnerApplyDB( + user_id=current_user.userid, + name=apply_data.name, + phone=apply_data.phone, + type=apply_data.type, + service_target=apply_data.service_target + ) + + db.add(new_apply) + db.commit() + db.refresh(new_apply) + + # 发送企业微信通知 + try: + from app.core.wecombot import WecomBot + wecom_bot = WecomBot() + message = f"""📢 新的合伙人申请 + +> 申请类型: {apply_data.type} +> 申请人: {apply_data.name} +> 联系电话: {apply_data.phone} +> 服务对象/区域: {apply_data.service_target} +> 申请时间: {new_apply.create_time} + """ + await wecom_bot.send_markdown(message,webhook_url=settings.FEEDBACK_NEED_WECOM_BOT_WEBHOOK_URL) + except Exception as e: + logging.error(f"发送企业微信通知失败: {str(e)}") + + return success_response(message="申请提交成功,我们会尽快联系您", data=PartnerApplyInfo.model_validate(new_apply)) + + except Exception as e: + db.rollback() + logging.exception(f"申请合伙人失败: {str(e)}") + return error_response(code=500, message="申请提交失败,请稍后重试") + +@router.get("/my-community-applies", response_model=ResponseModel) +async def get_my_community_applies( + db: Session = Depends(get_db), + current_user: UserDB = Depends(get_current_user) +): + """获取我的小区开通申请列表""" + applies = db.query(FeedbackCommunityApplyDB).filter( + FeedbackCommunityApplyDB.user_id == current_user.userid + ).order_by(FeedbackCommunityApplyDB.create_time.desc()).all() + + return success_response(data={ + "items": [CommunityApplyInfo.model_validate(apply) for apply in applies] + }) + +@router.get("/my-partner-applies", response_model=ResponseModel) +async def get_my_partner_applies( + db: Session = Depends(get_db), + current_user: UserDB = Depends(get_current_user) +): + """获取我的合伙人申请列表""" + applies = db.query(FeedbackPartnerApplyDB).filter( + FeedbackPartnerApplyDB.user_id == current_user.userid + ).order_by(FeedbackPartnerApplyDB.create_time.desc()).all() + + return success_response(data={ + "items": [PartnerApplyInfo.model_validate(apply) for apply in applies] + }) \ No newline at end of file diff --git a/app/core/config.py b/app/core/config.py index 790ddb3..ece0fcc 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -104,6 +104,8 @@ class Settings(BaseSettings): #配送订单取消 DELIVERY_ORDER_CANCELLED_TEMPLATE_ID: str = "iGR0rPtOFC_u8Xj5-R730zoDD_4Kbswkf_jSTnSSd6E" + # 反馈需求企业微信 + FEEDBACK_NEED_WECOM_BOT_WEBHOOK_URL: str = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=ccd6e8d4-4c8a-45b4-9b6b-dd4cae563176" class Config: case_sensitive = True env_file = ".env" diff --git a/app/main.py b/app/main.py index 50fce6b..3b78c6f 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, ocr, dashboard +from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card, withdraw, mp, point_product, point_product_order, coupon_activity, ocr, dashboard, wecom from app.models.database import Base, engine from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse @@ -12,6 +12,7 @@ import logging from app.core.config import settings from app.core.wecombot import WecomBot from app.api.endpoints import wecom +from app.api.endpoints import feedback # 创建数据库表 Base.metadata.create_all(bind=engine) @@ -74,7 +75,7 @@ app.include_router(upload.router, prefix="/api/upload", tags=["文件上传"]) app.include_router(config.router, prefix="/api/config", tags=["系统配置"]) app.include_router(log.router, prefix="/api/logs", tags=["系统日志"]) app.include_router(ocr.router, prefix="/api/ai/ocr", tags=["图像识别"]) - +app.include_router(feedback.router, prefix="/api/feedback", tags=["反馈"]) @app.get("/") async def root(): diff --git a/app/models/feedback.py b/app/models/feedback.py new file mode 100644 index 0000000..7b2989a --- /dev/null +++ b/app/models/feedback.py @@ -0,0 +1,74 @@ +from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text, Enum +from sqlalchemy.sql import func +from pydantic import BaseModel, Field +from typing import Optional +from datetime import datetime +from .database import Base +import enum + +class FeedbackCommunityApplyDB(Base): + """小区开通申请表""" + __tablename__ = "feedback_community_apply" + + id = Column(Integer, primary_key=True, autoincrement=True) + user_id = Column(Integer, ForeignKey("users.userid"), nullable=False) + community_name = Column(String(100), nullable=False) # 小区名称 + community_address = Column(String(200), nullable=False) # 小区地址 + create_time = Column(DateTime(timezone=True), server_default=func.now()) + update_time = Column(DateTime(timezone=True), onupdate=func.now()) + +class PartnerType(str, enum.Enum): + """合伙人类型""" + COMMUNITY = "社区合伙人" # 社区合伙人 + BUSINESS = "商家合伙人" # 商家合伙人 + DELIVERY = "配送合伙人" # 配送合伙人 + +class FeedbackPartnerApplyDB(Base): + """合伙人申请表""" + __tablename__ = "feedback_partner_apply" + + id = Column(Integer, primary_key=True, autoincrement=True) + user_id = Column(Integer, ForeignKey("users.userid"), nullable=False) + name = Column(String(50), nullable=False) # 姓名 + phone = Column(String(20), nullable=False) # 联系电话 + type = Column(String(50), nullable=False) # 合伙人类型 + service_target = Column(String(200), nullable=False) # 服务对象/区域 + create_time = Column(DateTime(timezone=True), server_default=func.now()) + update_time = Column(DateTime(timezone=True), onupdate=func.now()) + +# Pydantic 模型 +class CommunityApplyCreate(BaseModel): + user_id: int = Field(..., description="用户ID") + community_name: str = Field(..., max_length=100, description="小区名称") + community_address: str = Field(..., max_length=200, description="小区地址") + +class CommunityApplyInfo(BaseModel): + id: int + user_id: int + community_name: str + community_address: str + create_time: datetime + update_time: Optional[datetime] = None + + class Config: + from_attributes = True + +class PartnerApplyCreate(BaseModel): + user_id: int = Field(..., description="用户ID") + name: str = Field(..., max_length=50, description="姓名") + phone: str = Field(..., max_length=20, description="联系电话") + type: str = Field(..., max_length=50, description="合伙人类型") + service_target: str = Field(..., max_length=200, description="服务对象/区域") + +class PartnerApplyInfo(BaseModel): + id: int + user_id: int + name: str + phone: str + type: str + service_target: str + create_time: datetime + update_time: Optional[datetime] = None + + class Config: + from_attributes = True \ No newline at end of file