feat:cms relation hospital bug fix

This commit is contained in:
2026-06-17 10:22:51 +08:00
parent 2bb9ff50d8
commit 89ab844343
5 changed files with 274 additions and 39 deletions
+16 -3
View File
@@ -9,10 +9,15 @@ class CmsInstitutionSerializer(serializers.ModelSerializer):
"""CMS 机构(医院)序列化器。
- `code` 显式声明以去掉默认 UniqueValidator,改用自定义错误码校验唯一性。
- `banner_url` 返回可访问的完整 URL(未配置时为空串,便于管理端识别「未设图」)。
- `banner_url` **可写**(新增/编辑可传,可选):入参可为静态相对路径(如
`institutions/xxx.png`)或完整 `http(s)` URL**输出**统一转为可访问的完整 URL
(未配置时为空串,便于管理端识别「未设图」)。传空串则清空。
"""
code = serializers.CharField(max_length=100)
banner_url = serializers.SerializerMethodField()
banner_url = serializers.CharField(
max_length=500, required=False, allow_blank=True,
help_text='机构 Banner 图:相对静态路径或完整 http(s) URL;可选,传空串清空',
)
class Meta:
model = Institution
@@ -22,7 +27,12 @@ class CmsInstitutionSerializer(serializers.ModelSerializer):
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_banner_url(self, obj):
def to_representation(self, instance):
data = super().to_representation(instance)
data['banner_url'] = self._full_banner_url(instance)
return data
def _full_banner_url(self, obj):
if not obj.banner_url:
return ''
value = obj.banner_url
@@ -33,6 +43,9 @@ class CmsInstitutionSerializer(serializers.ModelSerializer):
path = prefix + '/' + settings.STATIC_URL.strip('/') + '/' + value.lstrip('/')
return request.build_absolute_uri(path) if request else path
def validate_banner_url(self, value):
return (value or '').strip()
def validate_code(self, value):
value = (value or '').strip()
if not value:
+23 -3
View File
@@ -11,7 +11,7 @@ from drf_spectacular.utils import extend_schema, extend_schema_view
from config.exceptions import AppError
from apps.user.models import Institution, Department
from apps.cms.permissions import IsSuperAdmin
from apps.cms.permissions import IsSuperAdmin, IsSuperOrHospitalAdmin, is_super
from apps.common.excel import xlsx_response, rows_from_xlsx
from .serializers import CmsInstitutionSerializer, CmsDepartmentSerializer
@@ -50,11 +50,25 @@ class CmsInstitutionViewSet(viewsets.ModelViewSet):
# 仅 GET / POST:查=GET,增删改=POST(编辑→{id}/update/,停用→{id}/disable/
http_method_names = ['get', 'post', 'head', 'options']
def get_permissions(self):
# 编辑机构 / 上传 Banner:超管 + 医院管理员(医院管理员仅限本院,在动作内收口);
# 其余动作(列表/新增/停用/导入导出等)仍仅超级管理员。
if getattr(self, 'action', None) in ('update_inst', 'banner'):
return [IsAuthenticated(), IsSuperOrHospitalAdmin()]
return [IsAuthenticated(), IsSuperAdmin()]
@extend_schema(summary='CMS-INST-3 编辑机构', tags=['CMS-机构'])
@action(detail=True, methods=['post'], url_path='update')
def update_inst(self, request, pk=None):
"""编辑机构(POST 局部更新,等价旧 PATCH /{id}/)。"""
"""编辑机构(POST 局部更新,等价旧 PATCH /{id}/)。
- 超级管理员:可编辑任意机构。
- 医院管理员:仅能编辑**本院**机构(非本院 → 403),可改除机构 ID 外的信息;
不能停用/删除机构(停用动作仍仅超管)。
"""
instance = self.get_object()
if not is_super(request.user) and instance.id != request.user.institution_id:
raise AppError('CMS_PERMISSION_DENIED', '医院管理员只能修改本机构信息', status_code=403)
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
@@ -71,8 +85,14 @@ class CmsInstitutionViewSet(viewsets.ModelViewSet):
@action(detail=True, methods=['post'], url_path='banner',
parser_classes=[MultiPartParser, FormParser])
def banner(self, request, pk=None):
"""上传机构 Banner 图(multipart/form-data,字段名 file)。"""
"""上传机构 Banner 图(multipart/form-data,字段名 file)。
- 超级管理员:可为任意机构上传。
- 医院管理员:仅可为**本院**机构上传(非本院 → 403)。
"""
inst = self.get_object()
if not is_super(request.user) and inst.id != request.user.institution_id:
raise AppError('CMS_PERMISSION_DENIED', '医院管理员只能上传本机构 Banner 图', status_code=403)
file = request.FILES.get('file')
if not file:
raise AppError('CMS_BANNER_FILE_REQUIRED', '请上传图片文件(字段名 file', status_code=400)