new
This commit is contained in:
@@ -44,7 +44,8 @@ class ActivityAdmin(ModelAdmin):
|
||||
'classes': ('tab',)
|
||||
}),
|
||||
('报名设置', {
|
||||
'fields': ('max_participants',)
|
||||
'fields': ('max_participants', 'ask_name', 'ask_phone', 'ask_wechat', 'ask_company', 'signup_form_config'),
|
||||
'description': '勾选需要收集的信息,或者在下方“自定义报名配置”中填写高级JSON配置'
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 6.0.1 on 2026-02-12 12:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('community', '0008_activity_signup_form_config_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='activity',
|
||||
name='ask_company',
|
||||
field=models.BooleanField(default=False, verbose_name='收集公司/机构'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='activity',
|
||||
name='ask_name',
|
||||
field=models.BooleanField(default=False, verbose_name='收集姓名'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='activity',
|
||||
name='ask_phone',
|
||||
field=models.BooleanField(default=False, verbose_name='收集手机号'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='activity',
|
||||
name='ask_wechat',
|
||||
field=models.BooleanField(default=False, verbose_name='收集微信号'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='activity',
|
||||
name='signup_form_config',
|
||||
field=models.JSONField(blank=True, default=list, help_text='JSON格式的高级配置,若填写则优先于上方开关。例如:[{"name": "job", "label": "职位", "type": "text", "required": true}]', verbose_name='自定义报名配置'),
|
||||
),
|
||||
]
|
||||
@@ -14,11 +14,18 @@ class Activity(models.Model):
|
||||
location = models.CharField(max_length=100, verbose_name="活动地点")
|
||||
max_participants = models.IntegerField(default=50, verbose_name="最大报名人数")
|
||||
is_active = models.BooleanField(default=True, verbose_name="是否启用")
|
||||
|
||||
# 常用报名信息开关
|
||||
ask_name = models.BooleanField(default=False, verbose_name="收集姓名")
|
||||
ask_phone = models.BooleanField(default=False, verbose_name="收集手机号")
|
||||
ask_wechat = models.BooleanField(default=False, verbose_name="收集微信号")
|
||||
ask_company = models.BooleanField(default=False, verbose_name="收集公司/机构")
|
||||
|
||||
signup_form_config = models.JSONField(
|
||||
default=list,
|
||||
verbose_name="报名表单配置",
|
||||
verbose_name="自定义报名配置",
|
||||
blank=True,
|
||||
help_text='配置报名时需要收集的信息,JSON格式,例如:[{"name": "phone", "label": "手机号", "type": "text", "required": true}]'
|
||||
help_text='JSON格式的高级配置,若填写则优先于上方开关。例如:[{"name": "job", "label": "职位", "type": "text", "required": true}]'
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
|
||||
|
||||
|
||||
@@ -4,11 +4,30 @@ from shop.serializers import WeChatUserSerializer, ESP32ConfigSerializer, Servic
|
||||
|
||||
class ActivitySerializer(serializers.ModelSerializer):
|
||||
display_banner_url = serializers.ReadOnlyField()
|
||||
signup_form_config = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Activity
|
||||
fields = '__all__'
|
||||
|
||||
def get_signup_form_config(self, obj):
|
||||
# 1. 优先使用 JSON 配置
|
||||
if obj.signup_form_config:
|
||||
return obj.signup_form_config
|
||||
|
||||
# 2. 否则根据开关生成默认配置
|
||||
config = []
|
||||
if obj.ask_name:
|
||||
config.append({"name": "name", "label": "姓名", "type": "text", "required": True})
|
||||
if obj.ask_phone:
|
||||
config.append({"name": "phone", "label": "手机号", "type": "number", "required": True})
|
||||
if obj.ask_wechat:
|
||||
config.append({"name": "wechat", "label": "微信号", "type": "text", "required": True})
|
||||
if obj.ask_company:
|
||||
config.append({"name": "company", "label": "公司/机构", "type": "text", "required": False})
|
||||
|
||||
return config
|
||||
|
||||
class ActivitySignupSerializer(serializers.ModelSerializer):
|
||||
activity_info = ActivitySerializer(source='activity', read_only=True)
|
||||
|
||||
|
||||
@@ -41,14 +41,31 @@ class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
signup_info = request.data.get('signup_info', {})
|
||||
|
||||
# Basic validation
|
||||
if activity.signup_form_config:
|
||||
required_fields = [f['name'] for f in activity.signup_form_config if f.get('required')]
|
||||
# Re-fetch the config from the object method or serializer logic if needed,
|
||||
# but here we can just use the serializer's method to get the effective config.
|
||||
# However, accessing serializer method from view is tricky without instantiating.
|
||||
# Let's replicate the logic or rely on the fact that we can construct it.
|
||||
|
||||
effective_config = activity.signup_form_config
|
||||
if not effective_config:
|
||||
effective_config = []
|
||||
if activity.ask_name:
|
||||
effective_config.append({"name": "name", "label": "姓名", "type": "text", "required": True})
|
||||
if activity.ask_phone:
|
||||
effective_config.append({"name": "phone", "label": "手机号", "type": "number", "required": True})
|
||||
if activity.ask_wechat:
|
||||
effective_config.append({"name": "wechat", "label": "微信号", "type": "text", "required": True})
|
||||
if activity.ask_company:
|
||||
effective_config.append({"name": "company", "label": "公司/机构", "type": "text", "required": False})
|
||||
|
||||
if effective_config:
|
||||
required_fields = [f['name'] for f in effective_config if f.get('required')]
|
||||
for field in required_fields:
|
||||
# Simple check: field exists and is not empty string (if it's a string)
|
||||
val = signup_info.get(field)
|
||||
if val is None or (isinstance(val, str) and not val.strip()):
|
||||
# Try to find label for better error message
|
||||
label = next((f['label'] for f in activity.signup_form_config if f['name'] == field), field)
|
||||
label = next((f['label'] for f in effective_config if f['name'] == field), field)
|
||||
return Response({'error': f'请填写: {label}'}, status=400)
|
||||
|
||||
signup = ActivitySignup.objects.create(
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user