Files
boss_dp/server/api/followup.py

188 lines
6.5 KiB
Python
Raw Normal View History

2026-03-05 10:27:28 +08:00
# -*- coding: utf-8 -*-
"""
复聊配置 API需要登录
- GET /api/followup-configs -> 查询复聊配置列表
- POST /api/followup-configs -> 创建复聊配置
- GET /api/followup-configs/{id} -> 查询单个配置
- PUT /api/followup-configs/{id} -> 更新配置
- DELETE /api/followup-configs/{id} -> 删除配置
- GET /api/followup-scripts -> 查询话术列表
- POST /api/followup-scripts -> 创建话术
- GET /api/followup-scripts/{id} -> 查询单个话术
- PUT /api/followup-scripts/{id} -> 更新话术
- DELETE /api/followup-scripts/{id} -> 删除话术
- GET /api/followup-records -> 查询复聊记录
- POST /api/followup-records/send -> 手动发送复聊消息
"""
from rest_framework import status
from rest_framework.decorators import api_view
from server.core.response import api_success, api_error
from server.models import FollowUpConfig, FollowUpScript, FollowUpRecord, ContactRecord
from server.serializers import (
FollowUpConfigSerializer,
FollowUpScriptSerializer,
FollowUpRecordSerializer
)
# ────────────────────────── 复聊配置 ──────────────────────────
@api_view(["GET", "POST"])
def followup_config_list(request):
"""复聊配置列表。"""
if request.method == "GET":
position = request.query_params.get("position")
is_active = request.query_params.get("is_active")
qs = FollowUpConfig.objects.all()
if position:
qs = qs.filter(position__icontains=position)
if is_active is not None:
qs = qs.filter(is_active=is_active.lower() in ("true", "1"))
configs = qs.order_by("-created_at")
return api_success(FollowUpConfigSerializer(configs, many=True).data)
# POST
ser = FollowUpConfigSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
return api_success(ser.data, http_status=status.HTTP_201_CREATED)
@api_view(["GET", "PUT", "DELETE"])
def followup_config_detail(request, pk):
"""复聊配置详情。"""
try:
obj = FollowUpConfig.objects.get(pk=pk)
except FollowUpConfig.DoesNotExist:
return api_error(status.HTTP_404_NOT_FOUND, "复聊配置不存在")
if request.method == "GET":
return api_success(FollowUpConfigSerializer(obj).data)
if request.method == "PUT":
ser = FollowUpConfigSerializer(obj, data=request.data, partial=True)
ser.is_valid(raise_exception=True)
ser.save()
return api_success(ser.data)
# DELETE
obj.delete()
return api_success(msg="复聊配置已删除")
# ────────────────────────── 复聊话术 ──────────────────────────
@api_view(["GET", "POST"])
def followup_script_list(request):
"""复聊话术列表。"""
if request.method == "GET":
config_id = request.query_params.get("config_id")
day_number = request.query_params.get("day_number")
qs = FollowUpScript.objects.all()
if config_id:
qs = qs.filter(config_id=config_id)
if day_number is not None:
qs = qs.filter(day_number=day_number)
scripts = qs.order_by("config_id", "day_number", "order")
return api_success(FollowUpScriptSerializer(scripts, many=True).data)
# POST
ser = FollowUpScriptSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
return api_success(ser.data, http_status=status.HTTP_201_CREATED)
@api_view(["GET", "PUT", "DELETE"])
def followup_script_detail(request, pk):
"""复聊话术详情。"""
try:
obj = FollowUpScript.objects.get(pk=pk)
except FollowUpScript.DoesNotExist:
return api_error(status.HTTP_404_NOT_FOUND, "复聊话术不存在")
if request.method == "GET":
return api_success(FollowUpScriptSerializer(obj).data)
if request.method == "PUT":
ser = FollowUpScriptSerializer(obj, data=request.data, partial=True)
ser.is_valid(raise_exception=True)
ser.save()
return api_success(ser.data)
# DELETE
obj.delete()
return api_success(msg="复聊话术已删除")
# ────────────────────────── 复聊记录 ──────────────────────────
@api_view(["GET"])
def followup_record_list(request):
"""复聊记录列表。"""
contact_id = request.query_params.get("contact_id")
config_id = request.query_params.get("config_id")
got_reply = request.query_params.get("got_reply")
page = int(request.query_params.get("page", 1))
page_size = int(request.query_params.get("page_size", 20))
qs = FollowUpRecord.objects.all()
if contact_id:
qs = qs.filter(contact_id=contact_id)
if config_id:
qs = qs.filter(config_id=config_id)
if got_reply is not None:
qs = qs.filter(got_reply=got_reply.lower() in ("true", "1"))
total = qs.count()
start = (page - 1) * page_size
end = start + page_size
records = qs[start:end]
return api_success({
"total": total,
"page": page,
"page_size": page_size,
"results": FollowUpRecordSerializer(records, many=True).data,
})
@api_view(["POST"])
def followup_send_manual(request):
"""手动发送复聊消息。"""
contact_id = request.data.get("contact_id")
content = request.data.get("content", "").strip()
if not contact_id:
return api_error(status.HTTP_400_BAD_REQUEST, "请提供 contact_id")
if not content:
return api_error(status.HTTP_400_BAD_REQUEST, "请提供发送内容")
try:
contact = ContactRecord.objects.get(pk=contact_id)
except ContactRecord.DoesNotExist:
return api_error(status.HTTP_404_NOT_FOUND, "联系人不存在")
# TODO: 这里需要调用浏览器自动化发送消息
# 暂时只记录到数据库
record = FollowUpRecord.objects.create(
contact_id=contact_id,
config_id=0, # 手动发送
script_id=0, # 手动发送
day_number=0,
content=content,
)
return api_success({
"record": FollowUpRecordSerializer(record).data,
"message": "复聊消息已发送"
})