feat: add profile api

This commit is contained in:
2026-06-08 17:36:03 +08:00
parent ba9fb33062
commit 2b86c91edd
9 changed files with 452 additions and 4 deletions
+100
View File
@@ -1,3 +1,4 @@
from django.conf import settings
from rest_framework import viewsets, filters, status
from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, AllowAny
@@ -10,6 +11,7 @@ from .auth import TRIAL_INSTITUTION_NAME
from .models import User, Role, TeacherStudentRelation, Institution, Department
from .serializers import (
UserSerializer, UserCreateSerializer, UserUpdateSerializer,
StudentProfileConfigSerializer,
RoleSerializer,
TeacherStudentRelationSerializer, InstitutionSerializer, DepartmentSerializer
)
@@ -228,3 +230,101 @@ def institution_list(request):
for inst in institutions
]
return Response(data)
# ── 配置页相关接口(移动端,首次进入系统)─────────────────────────────────────
def _build_banner_url(request, banner_value):
"""把机构 banner 字段转成完整可访问 URL。
- 空值回退到 settings.DEFAULT_INSTITUTION_BANNER
- 已是 http(s) 完整 URL 时原样返回
- 否则视为相对 STATIC_URL 的静态路径,拼成绝对 URL
"""
value = banner_value or settings.DEFAULT_INSTITUTION_BANNER
if value.startswith(('http://', 'https://')):
return value
path = '/' + settings.STATIC_URL.strip('/') + '/' + value.lstrip('/')
return request.build_absolute_uri(path)
@extend_schema(
summary='机构信息获取接口',
description='返回当前登录学生所属机构的信息,含机构专属 Banner 图 URL(用于配置页/首页顶部)。',
responses={200: None},
tags=['机构'],
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def institution_info(request):
"""机构信息获取接口 — 当前用户所属机构 + Banner 图 URL"""
inst = request.user.institution
if inst is None:
raise AppError('USER_INSTITUTION_NOT_FOUND', '当前账号未关联机构', status_code=404)
return Response({
'id': inst.id,
'code': inst.code,
'name': inst.name,
'type': inst.type,
'level': inst.level,
'province': inst.province,
'city': inst.city,
'banner_url': _build_banner_url(request, inst.banner_url),
})
@extend_schema(
summary='所属机构科室列表接口(不分页)',
description='返回当前登录学生所属机构下的全部科室,不分页,供配置页选择执业科室。',
responses={200: None},
tags=['机构'],
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def my_departments(request):
"""所属机构科室列表接口 — 当前用户机构下全部科室、不分页"""
inst = request.user.institution
if inst is None:
raise AppError('USER_INSTITUTION_NOT_FOUND', '当前账号未关联机构', status_code=404)
departments = Department.objects.filter(institution=inst).order_by('name')
data = [
{
'id': dept.id,
'name': dept.name,
'category': dept.category,
}
for dept in departments
]
return Response(data)
@extend_schema(
summary='医学生信息配置接口',
description='首次进入系统时录入学生信息:执业科室、专业职称、执业年限。'
'机构在登录时已选定,此处不再修改。',
request=StudentProfileConfigSerializer,
responses={200: UserSerializer},
tags=['用户'],
)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def student_profile_config(request):
"""医学生信息配置接口 — 录入科室、职称、执业年限"""
serializer = StudentProfileConfigSerializer(
data=request.data, context={'request': request}
)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
user = request.user
user.department = data['department']
user.title_name = data['title_name']
user.practice_years = data['practice_years']
user.save(update_fields=['department', 'title_name', 'practice_years', 'updated_at'])
return Response({
'message': '配置成功',
'user': UserSerializer(user).data,
})