pmc 7c79b72544 feat(affinity-P2): admin API — Rule/Level CRUD + Setting + Logs + Stats + Devices + Adjust (P2-06~P2-12)
新增 admin 管理端完整 API,挂载在 /api/v1/admin/affinity/ 路径下:

- serializers.py:9 个序列化器
  - AffinityRuleSerializer / AffinityLevelSerializer / AffinitySettingSerializer
    含跨字段 validate(min/max 关系、区间重叠、衰减区间、companion_time 字段必填等)
  - AffinityLogSerializer 只读 + 关联字段展开(user_username/device_code/rule_name)
  - UserDeviceAffinitySerializer 含 device_code/mac/status/level_name
  - AffinityAdjust + AffinityAdjustBatch 用 Serializer 而非 ModelSerializer
  - permissions.py 中 IsAdminUserStaff 复用,所有 view 默认 RedisTokenAuthentication + IsAdminUserStaff

- views.py:7 个视图
  - AffinityRuleAdminViewSet (P2-06):ModelViewSet + 软删 (is_deleted+is_enabled=False) + restore action;?include_deleted=true 返回全集
  - AffinityLevelAdminViewSet (P2-07):同上软删;serializer 跨字段校验区间重叠
  - AffinitySettingView (P2-08):APIView 单例 GET/PUT/PATCH;pk=1 硬约束
  - AffinityLogListView (P2-09):过滤 user_id/device_id/rule_key/source/date_from/date_to;分页 page_size 上限 200;select_related 防 N+1
  - AffinityStatsView (P2-10):avg/max/top_count/active_7d/total_devices/today_interactions/today_change_sum/rule_freq_top/level_distribution;全部基于 UserDevice.active 聚合;今日按 AffinitySetting.timezone 取 local date
  - UserAffinityDevicesView (P2-11):?user_id= 必传 + 404 校验;?include_unbound=true 含历史;默认仅 is_bound=True
  - AffinityAdjustView + AffinityAdjustBatchView (P2-12):委托 AffinityService.admin_adjust;批量遍历 UserDevice.active 逐台调用,返回 per-device 结果数组

- urls.py:DRF DefaultRouter 注册 rules/levels CRUD + 5 个独立 path 挂 settings/logs/stats/devices/adjust*
- admin_urls.py:引入 include 并新增 path('affinity/', include('userapp.affinity.urls'))

Django check 通过,6 URL reverse 全部解析正确:
  /api/v1/admin/affinity/settings/
  /api/v1/admin/affinity/logs/
  /api/v1/admin/affinity/stats/
  /api/v1/admin/affinity/devices/
  /api/v1/admin/affinity/adjust/
  /api/v1/admin/affinity/adjust-batch/

旧的 /api/user/affinity-rules/ 与 /affinity-levels/ 暂保留兼容,前端切到 admin 后即可清理。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 09:36:11 +08:00

39 lines
1.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""好感度系统 admin 端 URL 路由
挂载位置:`/api/v1/admin/affinity/...`(由 userapp/admin_urls.py include
"""
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import (
AffinityAdjustBatchView,
AffinityAdjustView,
AffinityLevelAdminViewSet,
AffinityLogListView,
AffinityRuleAdminViewSet,
AffinitySettingView,
AffinityStatsView,
UserAffinityDevicesView,
)
router = DefaultRouter()
router.register('rules', AffinityRuleAdminViewSet, basename='admin-affinity-rule')
router.register('levels', AffinityLevelAdminViewSet, basename='admin-affinity-level')
urlpatterns = [
# P2-08 单例 settings
path('settings/', AffinitySettingView.as_view(), name='admin_affinity_settings'),
# P2-09 变更日志
path('logs/', AffinityLogListView.as_view(), name='admin_affinity_logs'),
# P2-10 统计
path('stats/', AffinityStatsView.as_view(), name='admin_affinity_stats'),
# P2-11 按用户列出设备
path('devices/', UserAffinityDevicesView.as_view(), name='admin_affinity_devices'),
# P2-12 手动调整
path('adjust/', AffinityAdjustView.as_view(), name='admin_affinity_adjust'),
path('adjust-batch/', AffinityAdjustBatchView.as_view(), name='admin_affinity_adjust_batch'),
# P2-06 / P2-07 router-driven CRUD
path('', include(router.urls)),
]