Files
boss_dp/server/serializers.py

201 lines
8.1 KiB
Python
Raw Normal View History

2026-02-14 16:50:02 +08:00
# -*- coding: utf-8 -*-
"""
DRF 序列化器
"""
from rest_framework import serializers
2026-03-05 10:27:28 +08:00
from server.models import (
2026-03-06 10:05:49 +08:00
BossAccount, TaskLog, FilterConfig, RecruitFilterSnapshot, ChatScript, ContactRecord, SystemConfig,
2026-03-05 10:27:28 +08:00
FollowUpConfig, FollowUpScript, FollowUpRecord
)
2026-02-14 16:50:02 +08:00
# ────────────────────────── 账号 ──────────────────────────
class BossAccountSerializer(serializers.ModelSerializer):
"""账号序列化器(读取用)。"""
# 运行时补充的字段(非数据库字段)
worker_name = serializers.CharField(read_only=True, default="")
worker_online = serializers.BooleanField(read_only=True, default=False)
class Meta:
model = BossAccount
fields = [
"id", "worker_id", "browser_id", "browser_name",
2026-02-27 13:56:15 +08:00
"boss_username", "boss_id", "is_logged_in",
2026-02-14 16:50:02 +08:00
"current_task_id", "current_task_status",
"checked_at", "created_at", "updated_at",
"worker_name", "worker_online",
]
class AccountBindSerializer(serializers.Serializer):
"""添加账号请求。"""
browser_name = serializers.CharField(max_length=128)
worker_id = serializers.CharField(max_length=64)
# ────────────────────────── 任务 ──────────────────────────
class TaskCreateSerializer(serializers.Serializer):
"""提交任务请求。"""
task_type = serializers.CharField(max_length=64)
2026-02-27 15:42:13 +08:00
id = serializers.IntegerField(required=False, allow_null=True, default=None) # 账号 ID
account_id = serializers.IntegerField(required=False, allow_null=True, default=None) # 同上,别名
2026-02-27 21:08:30 +08:00
boss_id = serializers.CharField(max_length=64, required=False, allow_blank=True, default="") # 即 /api/accounts 返回的 id账号主键
2026-02-14 16:50:02 +08:00
worker_id = serializers.CharField(max_length=64, required=False, allow_blank=True, default="")
account_name = serializers.CharField(max_length=128, required=False, allow_blank=True, default="")
params = serializers.JSONField(required=False, default=dict)
class TaskOutSerializer(serializers.Serializer):
"""任务信息响应。"""
task_id = serializers.CharField()
task_type = serializers.CharField()
status = serializers.CharField()
worker_id = serializers.CharField(allow_null=True)
account_name = serializers.CharField(allow_null=True)
params = serializers.DictField()
progress = serializers.CharField(allow_null=True)
result = serializers.JSONField(allow_null=True)
error = serializers.CharField(allow_null=True)
2026-03-01 23:18:23 +08:00
created_at = serializers.CharField()
updated_at = serializers.CharField()
2026-02-14 16:50:02 +08:00
# ────────────────────────── Worker ──────────────────────────
class BrowserProfileSerializer(serializers.Serializer):
"""浏览器窗口信息。"""
id = serializers.CharField()
name = serializers.CharField()
remark = serializers.CharField()
class WorkerOutSerializer(serializers.Serializer):
"""Worker 信息响应。"""
worker_id = serializers.CharField()
worker_name = serializers.CharField()
browsers = BrowserProfileSerializer(many=True)
online = serializers.BooleanField()
current_task_id = serializers.CharField(allow_null=True)
# ────────────────────────── 认证 ──────────────────────────
class LoginSerializer(serializers.Serializer):
"""登录请求。"""
username = serializers.CharField(max_length=64)
password = serializers.CharField(max_length=128)
2026-02-14 17:58:29 +08:00
# ────────────────────────── 筛选配置 ──────────────────────────
2026-03-05 22:53:19 +08:00
# 请求中可能出现的“金额”字段别名,统一映射为 min_amount / max_amount保证请求与响应字段名一致
FILTER_AMOUNT_ALIASES = {
"minAmount": "min_amount",
"maxAmount": "max_amount",
"最小金额": "min_amount",
"最大金额": "max_amount",
}
2026-02-14 17:58:29 +08:00
class FilterConfigSerializer(serializers.ModelSerializer):
2026-03-05 23:04:32 +08:00
"""筛选配置:列表/详情返回 name, position_keywords, city, salary_min, salary_max, experience, education, is_active 等。"""
2026-02-14 17:58:29 +08:00
class Meta:
model = FilterConfig
fields = "__all__"
read_only_fields = ["id", "created_at", "updated_at"]
2026-03-05 22:53:19 +08:00
def to_internal_value(self, data):
2026-03-05 23:40:49 +08:00
"""请求中兼容 minAmount/maxAmount 等别名;支持 multipart/form-dataQueryDict/多值列表)。"""
if data is None:
data = {}
else:
data = dict(data)
# multipart 解析后字段值可能是 list如 ["测试配置"]),需展平为标量
for key in list(data.keys()):
val = data[key]
if isinstance(val, (list, tuple)):
data[key] = val[0] if len(val) > 0 else ""
2026-03-05 23:39:20 +08:00
for alias, canonical in FILTER_AMOUNT_ALIASES.items():
if alias in data and canonical not in data:
data[canonical] = data.pop(alias)
2026-03-05 23:40:49 +08:00
# 请求里 is_active 可能是字符串 "true"/"false" 或单元素列表
raw = data.get("is_active")
if raw is not None:
if isinstance(raw, (list, tuple)):
raw = raw[0] if raw else ""
if isinstance(raw, str):
data["is_active"] = raw.lower() in ("true", "1", "yes", "")
2026-03-05 22:53:19 +08:00
return super().to_internal_value(data)
2026-02-14 17:58:29 +08:00
# ────────────────────────── 话术 ──────────────────────────
2026-03-06 10:05:49 +08:00
class RecruitFilterSnapshotSerializer(serializers.ModelSerializer):
class Meta:
model = RecruitFilterSnapshot
fields = "__all__"
read_only_fields = ["id", "synced_at", "created_at"]
2026-02-14 17:58:29 +08:00
class ChatScriptSerializer(serializers.ModelSerializer):
script_type_display = serializers.CharField(source="get_script_type_display", read_only=True)
class Meta:
model = ChatScript
fields = "__all__"
read_only_fields = ["id", "created_at", "updated_at"]
# ────────────────────────── 联系记录 ──────────────────────────
class ContactRecordSerializer(serializers.ModelSerializer):
class Meta:
model = ContactRecord
fields = "__all__"
read_only_fields = ["id", "created_at"]
# ────────────────────────── 系统配置 ──────────────────────────
class SystemConfigSerializer(serializers.ModelSerializer):
class Meta:
model = SystemConfig
fields = "__all__"
read_only_fields = ["updated_at"]
2026-03-05 10:27:28 +08:00
# ────────────────────────── 复聊配置 ──────────────────────────
class FollowUpScriptSerializer(serializers.ModelSerializer):
"""复聊话术序列化器。"""
class Meta:
model = FollowUpScript
fields = "__all__"
read_only_fields = ["id", "created_at"]
class FollowUpConfigSerializer(serializers.ModelSerializer):
"""复聊配置序列化器(包含关联的话术列表)。"""
scripts = serializers.SerializerMethodField()
class Meta:
model = FollowUpConfig
fields = "__all__"
read_only_fields = ["id", "created_at", "updated_at"]
def get_scripts(self, obj):
"""获取该配置下的所有话术。"""
scripts = FollowUpScript.objects.filter(config_id=obj.id, is_active=True).order_by('day_number', 'order')
return FollowUpScriptSerializer(scripts, many=True).data
class FollowUpRecordSerializer(serializers.ModelSerializer):
"""复聊记录序列化器。"""
class Meta:
model = FollowUpRecord
fields = "__all__"
read_only_fields = ["id", "sent_at"]