比赛
All checks were successful
Deploy to Server / deploy (push) Successful in 28s

This commit is contained in:
jeremygan2021
2026-03-10 14:25:04 +08:00
parent 03297f3d07
commit 6361b7a522
12 changed files with 414 additions and 108 deletions

View File

@@ -28,7 +28,7 @@ class CompetitionAdmin(ModelAdmin):
'description': '封面图可以上传本地图片,也可以填写外部链接,优先显示本地上传的图片'
}),
('时间和状态', {
'fields': ('start_time', 'end_time', 'status', 'is_active')
'fields': ('start_time', 'end_time', 'status', 'project_visibility', 'is_active')
}),
)

View File

@@ -0,0 +1,18 @@
# Generated by Django 6.0.1 on 2026-03-10 06:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('competition', '0002_competition_cover_image_url_project_cover_image_url'),
]
operations = [
migrations.AddField(
model_name='competition',
name='project_visibility',
field=models.CharField(choices=[('public', '公开可见'), ('contestant', '选手及以上可见'), ('guest', '嘉宾及评委可见'), ('judge', '仅评委可见')], default='public', max_length=20, verbose_name='项目可见性'),
),
]

View File

@@ -14,6 +14,13 @@ class Competition(models.Model):
('ended', '已结束'),
)
PROJECT_VISIBILITY_CHOICES = (
('public', '公开可见'),
('contestant', '选手及以上可见'),
('guest', '嘉宾及评委可见'),
('judge', '仅评委可见'),
)
title = models.CharField(max_length=200, verbose_name="比赛名称")
description = models.TextField(verbose_name="比赛简介")
rule_description = models.TextField(verbose_name="规则说明")
@@ -26,6 +33,7 @@ class Competition(models.Model):
end_time = models.DateTimeField(verbose_name="结束时间")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft', verbose_name="状态")
project_visibility = models.CharField(max_length=20, choices=PROJECT_VISIBILITY_CHOICES, default='public', verbose_name="项目可见性")
is_active = models.BooleanField(default=True, verbose_name="是否启用")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

View File

@@ -16,7 +16,7 @@ class CompetitionSerializer(serializers.ModelSerializer):
model = Competition
fields = ['id', 'title', 'description', 'rule_description', 'condition_description',
'cover_image', 'cover_image_url', 'display_cover_image',
'start_time', 'end_time', 'status', 'status_display', 'is_active',
'start_time', 'end_time', 'status', 'project_visibility', 'status_display', 'is_active',
'score_dimensions', 'created_at']
def get_display_cover_image(self, obj):

View File

@@ -112,30 +112,39 @@ class ProjectViewSet(viewsets.ModelViewSet):
if contestant_id:
queryset = queryset.filter(contestant_id=contestant_id)
# 如果是普通用户,只能看到已提交的项目,或者自己草稿的项目
user = get_current_wechat_user(self.request)
# 1. 基础条件:公开可见且已提交的项目
q = Q(competition__project_visibility='public', status='submitted')
if user:
# 查找用户在这个比赛中的角色
# 如果是评委,可以看到所有项目(包括草稿吗?通常评委只看提交的)
# 这里简化评委看所有submitted用户看所有submitted + 自己的draft
# 找到用户参与的所有比赛角色
enrollments = CompetitionEnrollment.objects.filter(user=user)
judge_competitions = enrollments.filter(role='judge').values_list('competition_id', flat=True)
# 基本查询:所有已提交的项目
q = Q(status='submitted')
# 加上自己创建的项目 (即使是draft)
# 2. 用户自己的项目(始终可见,包括草稿)
q |= Q(contestant__user=user)
# 加上自己是评委的比赛的所有项目 (通常评委只看submitted但如果需要预审可以看draft这里假设只看submitted)
# q |= Q(competition__in=judge_competitions)
# 3. 基于角色的可见性
# 获取用户已通过审核的报名信息
enrollments = CompetitionEnrollment.objects.filter(user=user, status='approved')
queryset = queryset.filter(q)
else:
# 未登录用户只能看已提交
queryset = queryset.filter(status='submitted')
# 获取各角色的比赛ID集合
judge_comp_ids = set(enrollments.filter(role='judge').values_list('competition_id', flat=True))
guest_comp_ids = set(enrollments.filter(role='guest').values_list('competition_id', flat=True))
contestant_comp_ids = set(enrollments.filter(role='contestant').values_list('competition_id', flat=True))
# 'judge' 可见性:仅评委可见
if judge_comp_ids:
q |= Q(competition__project_visibility='judge', competition__in=judge_comp_ids, status='submitted')
# 'guest' 可见性:嘉宾及评委可见
guest_access_ids = judge_comp_ids | guest_comp_ids
if guest_access_ids:
q |= Q(competition__project_visibility='guest', competition__in=guest_access_ids, status='submitted')
# 'contestant' 可见性:选手及以上可见(包括评委、嘉宾)
contestant_access_ids = judge_comp_ids | guest_comp_ids | contestant_comp_ids
if contestant_access_ids:
q |= Q(competition__project_visibility='contestant', competition__in=contestant_access_ids, status='submitted')
queryset = queryset.filter(q)
return queryset.order_by('-final_score', '-created_at')