feat(admin): Phase 4 质量词 Admin(平台单层) — QualityWord + 生成侧读配置(无配置回落) + 质量词页

后端:apps/ai QualityWord(stage/slot/text/sort/enabled)+ migration;services.py quality_words/quality_suffix,
4 个 builder 接入(person/model_tryon/storyboard/video)无配置回落原写死值零回归;adminpanel CRUD + 审计。
前端:adminApi quality 系列;Admin 质量词页(按 stage 分组卡 + 编辑模式开关 + 行内增改删 chip)。
测试:adminpanel 23 + accounts 22 = 45 单测过(CRUD/权限/生成读配置+回落/停用词不取);
无头 e2e _admin-p4.mjs 4 断言过 + 0 console error + live 库零残留;tsc+build 绿。
注:apps.ai 3 个 image_edit 路由测试失败为进场前既有(已 stash 比对 HEAD 同样失败),非本 Phase 引入。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 21:52:41 +08:00
co-authored by Claude Opus 4.8
parent 6560633959
commit 01d4f235ed
14 changed files with 535 additions and 5 deletions
+64 -1
View File
@@ -10,9 +10,15 @@ from apps.accounts.audit import log_admin_action
from apps.accounts.models import Invitation, Team, User
from apps.accounts.permissions import IsPlatformAdmin
from apps.accounts.serializers import InvitationSerializer
from apps.ai.models import QualityWord
from apps.common.pagination import DefaultPagination
from .serializers import AdminTeamMemberSerializer, AdminTeamSerializer, AdminUserSerializer
from .serializers import (
AdminTeamMemberSerializer,
AdminTeamSerializer,
AdminUserSerializer,
QualityWordSerializer,
)
def _team_qs():
@@ -199,3 +205,60 @@ def admin_user_reset_password(request, user_id):
target_name=user.username,
)
return Response(status=status.HTTP_204_NO_CONTENT)
# ─────────────────────────── 质量词(平台单层)───────────────────────────
@api_view(["GET", "POST"])
@permission_classes([IsPlatformAdmin])
def admin_quality_words(request):
"""GET 列全部质量词(配置量小,不分页,前端按 stage 分组);POST 新增一条。"""
if request.method == "GET":
qs = QualityWord.objects.all().order_by("stage", "sort", "created_at")
return Response(QualityWordSerializer(qs, many=True).data)
serializer = QualityWordSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
obj = serializer.save()
log_admin_action(
request,
"quality_word.create",
target_type="quality_word",
target_id=obj.id,
target_name=f"{obj.stage}:{obj.text}",
after={"stage": obj.stage, "text": obj.text},
)
return Response(QualityWordSerializer(obj).data, status=status.HTTP_201_CREATED)
@api_view(["PATCH", "DELETE"])
@permission_classes([IsPlatformAdmin])
def admin_quality_word_detail(request, word_id):
obj = QualityWord.objects.filter(id=word_id).first()
if obj is None:
return Response({"detail": "not found"}, status=status.HTTP_404_NOT_FOUND)
if request.method == "DELETE":
log_admin_action(
request,
"quality_word.delete",
target_type="quality_word",
target_id=obj.id,
target_name=f"{obj.stage}:{obj.text}",
before={"stage": obj.stage, "text": obj.text},
)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
before_text = obj.text
serializer = QualityWordSerializer(obj, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
log_admin_action(
request,
"quality_word.update",
target_type="quality_word",
target_id=obj.id,
target_name=f"{obj.stage}:{obj.text}",
before={"text": before_text},
after={"text": obj.text},
)
return Response(QualityWordSerializer(obj).data)