feat: 移除轮播图管理,系列活动改卡片布局,课程描述限10行,首页配置优化
All checks were successful
Deploy to Server / deploy (push) Successful in 2m4s

This commit is contained in:
爽哒哒
2026-03-22 00:10:34 +08:00
parent b24bba3753
commit 21f892fdf6
11 changed files with 188 additions and 417 deletions

View File

@@ -2,28 +2,20 @@ from django.contrib import admin
from django.utils.html import format_html
from unfold.admin import ModelAdmin
from unfold.decorators import display
from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment, HomePageConfig, CarouselItem
class CarouselItemInline(admin.TabularInline):
model = CarouselItem
extra = 1
tab = True
fields = ('carousel_type', 'image', 'image_url', 'title', 'subtitle', 'status', 'status_color', 'date', 'location', 'order', 'is_active')
autocomplete_fields = []
from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment, HomePageConfig
@admin.register(HomePageConfig)
class HomePageConfigAdmin(ModelAdmin):
list_display = ['id', 'main_title', 'carousel1_title', 'carousel2_title', 'organizer', 'undertaker', 'is_active']
list_editable = ['main_title', 'carousel1_title', 'carousel2_title', 'organizer', 'undertaker', 'is_active']
list_display = ['id', 'main_title', 'organizer', 'undertaker', 'is_active']
list_editable = ['main_title', 'organizer', 'undertaker', 'is_active']
fieldsets = (
('首页Banner', {
('封面图', {
'fields': ('banner_image', 'banner_image_url'),
'description': '首页顶部Banner图片,可上传本地图片或填写URL'
'description': '首页标题下方的封面图可上传本地图片或填写URL'
}),
('标题设置', {
'fields': ('main_title', 'carousel1_title', 'carousel2_title')
'fields': ('main_title',)
}),
('主办单位', {
'fields': ('organizer', 'undertaker')
@@ -34,37 +26,6 @@ class HomePageConfigAdmin(ModelAdmin):
)
@admin.register(CarouselItem)
class CarouselItemAdmin(ModelAdmin):
list_display = ['title', 'carousel_type', 'status', 'location', 'order', 'is_active', 'created_at']
list_filter = ['carousel_type', 'status', 'is_active']
search_fields = ['title', 'subtitle', 'location']
readonly_fields = ['image_preview']
fieldsets = (
('轮播图类型', {
'fields': ('carousel_type',)
}),
('图片设置', {
'fields': ('image', 'image_preview', 'image_url'),
'description': '优先使用本地上传的图片,上传后可预览'
}),
('内容设置', {
'fields': ('title', 'subtitle', 'status', 'status_color', 'date', 'location')
}),
('显示设置', {
'fields': ('order', 'is_active')
}),
)
@display(description='图片预览')
def image_preview(self, obj):
if obj.image:
return format_html('<img src="{}" style="max-width: 400px; max-height: 200px; border-radius: 8px;" />', obj.image.url)
elif obj.image_url:
return format_html('<img src="{}" style="max-width: 400px; max-height: 200px; border-radius: 8px;" />', obj.image_url)
return "暂无图片"
class ScoreDimensionInline(admin.TabularInline):
model = ScoreDimension
extra = 1

View File

@@ -0,0 +1,19 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('competition', '0009_alter_carouselitem_id_alter_comment_id_and_more'),
]
operations = [
migrations.RemoveField(
model_name='homepageconfig',
name='carousel1_title',
),
migrations.RemoveField(
model_name='homepageconfig',
name='carousel2_title',
),
]

View File

@@ -9,9 +9,6 @@ class HomePageConfig(models.Model):
main_title = models.CharField(max_length=200, default='"创赢未来"云南2026创业大赛', verbose_name="主标题")
carousel1_title = models.CharField(max_length=200, default='"创赢未来"云南2026创业大赛', verbose_name="轮播图1标题")
carousel2_title = models.CharField(max_length=200, default='"七彩云南创业福地"创业主题系列活动', verbose_name="轮播图2标题")
organizer = models.CharField(max_length=200, default='云南省人力资源和社会保障厅', verbose_name="主办单位")
undertaker = models.CharField(max_length=200, default='云南省就业局', verbose_name="承办单位")

View File

@@ -1,6 +1,6 @@
from rest_framework import serializers
from django.conf import settings
from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment, HomePageConfig, CarouselItem
from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment, HomePageConfig
from shop.serializers import WeChatUserSerializer
@@ -11,41 +11,16 @@ def _media_url(file_field):
return None
class CarouselItemSerializer(serializers.ModelSerializer):
display_image = serializers.SerializerMethodField()
class Meta:
model = CarouselItem
fields = ['id', 'carousel_type', 'image', 'image_url', 'display_image',
'title', 'subtitle', 'status', 'status_color', 'date', 'location',
'order', 'is_active']
def get_display_image(self, obj):
return _media_url(obj.image) or obj.image_url
class HomePageConfigSerializer(serializers.ModelSerializer):
display_banner = serializers.SerializerMethodField()
carousel1_items = serializers.SerializerMethodField()
carousel2_items = serializers.SerializerMethodField()
class Meta:
model = HomePageConfig
fields = ['id', 'banner_image', 'banner_image_url', 'display_banner',
'main_title', 'carousel1_title', 'carousel2_title',
'organizer', 'undertaker', 'carousel1_items', 'carousel2_items']
'main_title', 'organizer', 'undertaker']
def get_display_banner(self, obj):
return _media_url(obj.banner_image) or obj.banner_image_url
def get_carousel1_items(self, obj):
items = CarouselItem.objects.filter(carousel_type='carousel1', is_active=True)
return CarouselItemSerializer(items, many=True, context=self.context).data
def get_carousel2_items(self, obj):
items = CarouselItem.objects.filter(carousel_type='carousel2', is_active=True)
return CarouselItemSerializer(items, many=True, context=self.context).data
class ScoreDimensionSerializer(serializers.ModelSerializer):
class Meta:

View File

@@ -2,7 +2,7 @@ from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import (
CompetitionViewSet, ProjectViewSet, ProjectFileViewSet,
ScoreViewSet, CommentViewSet, CarouselItemViewSet, get_homepage_config
ScoreViewSet, CommentViewSet, get_homepage_config
)
from . import judge_views
@@ -12,7 +12,6 @@ router.register(r'projects', ProjectViewSet, basename='project')
router.register(r'files', ProjectFileViewSet, basename='projectfile')
router.register(r'scores', ScoreViewSet, basename='score')
router.register(r'comments', CommentViewSet, basename='comment')
router.register(r'carousel-items', CarouselItemViewSet, basename='carouselitem')
urlpatterns = [
# 首页配置

View File

@@ -3,12 +3,12 @@ from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.response import Response
from django.db.models import Q
from shop.utils import get_current_wechat_user
from .models import Competition, CompetitionEnrollment, Project, ProjectFile, Score, Comment, ScoreDimension, HomePageConfig, CarouselItem
from .models import Competition, CompetitionEnrollment, Project, ProjectFile, Score, Comment, ScoreDimension, HomePageConfig
from .serializers import (
CompetitionSerializer, CompetitionEnrollmentSerializer,
ProjectSerializer, ProjectFileSerializer,
ScoreSerializer, CommentSerializer, ScoreDimensionSerializer,
HomePageConfigSerializer, CarouselItemSerializer
HomePageConfigSerializer
)
from rest_framework.pagination import PageNumberPagination
@@ -28,22 +28,6 @@ def get_homepage_config(request):
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class CarouselItemViewSet(viewsets.ModelViewSet):
"""轮播图项目管理"""
queryset = CarouselItem.objects.all()
serializer_class = CarouselItemSerializer
permission_classes = [permissions.AllowAny]
filter_backends = [filters.SearchFilter]
search_fields = ['title']
def get_queryset(self):
queryset = CarouselItem.objects.all()
carousel_type = self.request.query_params.get('carousel_type')
if carousel_type:
queryset = queryset.filter(carousel_type=carousel_type)
return queryset
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'

View File

@@ -255,11 +255,6 @@ UNFOLD = {
"icon": "home",
"link": reverse_lazy("admin:competition_homepageconfig_changelist"),
},
{
"title": "轮播图管理",
"icon": "image",
"link": reverse_lazy("admin:competition_carouselitem_changelist"),
},
],
},
{