feat: 修改考试和 新增证书字段

This commit is contained in:
zty 2025-03-04 09:12:51 +08:00
parent 779855ea62
commit 5638574339
4 changed files with 138 additions and 4 deletions

View File

@ -69,6 +69,8 @@ class CompanyInfo(CommonModel):
edu_points = models.FloatField('教育积分', null=True, blank=True) edu_points = models.FloatField('教育积分', null=True, blank=True)
co_sponsor_points = models.FloatField('协办大赛积分', null=True, blank=True) co_sponsor_points = models.FloatField('协办大赛积分', null=True, blank=True)
sum_points = models.FloatField('总积分', null=True, blank=True) sum_points = models.FloatField('总积分', null=True, blank=True)
photo = models.ImageField('公司图片', upload_to='photo', null=True, blank=True)
remark = models.TextField('备注', null=True, blank=True, max_length=500)
def __str__(self): def __str__(self):
return self.company_name return self.company_name

View File

@ -4,7 +4,8 @@ from .models import Candidate, Company, Consumer, PaySubject, ConsumerPerm, Cons
from question.models import Question, Questioncat from question.models import Question, Questioncat
from .permission import get_consumerperm_list from .permission import get_consumerperm_list
from rbac.serializers.user_serializer import UserListSerializer from rbac.serializers.user_serializer import UserListSerializer
from examtest.services import make_img
from server import settings
class ConsumerPermSerializer(serializers.ModelSerializer): class ConsumerPermSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -43,7 +44,7 @@ class ConsumerSerializer(serializers.ModelSerializer):
create_admin_name = serializers.StringRelatedField(source='create_admin', read_only=True) create_admin_name = serializers.StringRelatedField(source='create_admin', read_only=True)
class Meta: class Meta:
model = Consumer model = Consumer
exclude = ('avatar','collects', 'process') exclude = ('collects', 'process')
@staticmethod @staticmethod
def setup_eager_loading(queryset): def setup_eager_loading(queryset):
@ -83,6 +84,7 @@ class ConsumerDetailSerializer(serializers.ModelSerializer):
class CandidateSerializer(serializers.ModelSerializer): class CandidateSerializer(serializers.ModelSerializer):
create_admin_username = serializers.StringRelatedField(source='create_admin', read_only=True) create_admin_username = serializers.StringRelatedField(source='create_admin', read_only=True)
cert_template = serializers.StringRelatedField(source='examtest.exam.cert_template', read_only=True)
class Meta: class Meta:
model = Candidate model = Candidate
fields = '__all__' fields = '__all__'
@ -97,6 +99,16 @@ class CandidateCreateSerializer(serializers.ModelSerializer):
validated_data['create_admin'] = self.context['request'].user validated_data['create_admin'] = self.context['request'].user
return super().create(validated_data) return super().create(validated_data)
def update(self, instance, validated_data):
validated_data['is_manual'] = True
validated_data['create_admin'] = self.context['request'].user
issue_date = validated_data.get('issue_date', None)
exp_date = validated_data.get('end_date', None)
header_photo = settings.BASE_DIR + validated_data.get('photo', None)
path = make_img(validated_data["consumer_name"], str(issue_date.year), str(issue_date.month), str(exp_date.year), str(exp_date.month), str(exp_date.day), validated_data["number"], header_photo)
validated_data['path'] = path
return super().update(instance,validated_data)
class MsgSerializer(serializers.ModelSerializer): class MsgSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = SendCode model = SendCode

View File

@ -27,7 +27,7 @@ class Exam(CommonModel):
qdimgs = JSONField('签到图片', default=list) qdimgs = JSONField('签到图片', default=list)
xcimgs = JSONField('现场图片', default=list) xcimgs = JSONField('现场图片', default=list)
only_vip = models.BooleanField('仅允许培训班学员', default=False) only_vip = models.BooleanField('仅允许培训班学员', default=False)
cert_template = models.PositiveSmallIntegerField('证书模板', null=True, blank=True, help_text='1,2') cert_template = models.PositiveSmallIntegerField('证书模板', null=True, blank=True, help_text='1,2,3')
auto_issue = models.BooleanField('是否自动发证', default=False) auto_issue = models.BooleanField('是否自动发证', default=False)
def __str__(self): def __str__(self):

View File

@ -4,6 +4,10 @@ from django.utils import timezone
from datetime import timedelta from datetime import timedelta
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from rbac.models import UserProfile from rbac.models import UserProfile
from PIL import Image, ImageDraw, ImageFont
import settings, datetime
from server import settings
def issue(obj: ExamTest, create_admin: UserProfile = None): def issue(obj: ExamTest, create_admin: UserProfile = None):
if create_admin is None: if create_admin is None:
create_admin = obj.exam.create_admin create_admin = obj.exam.create_admin
@ -35,8 +39,124 @@ def issue(obj: ExamTest, create_admin: UserProfile = None):
if cert_template == 2: if cert_template == 2:
count = Candidate.objects.filter(create_admin=create_admin, issue_date__year=now.year, issue_date__month=now.month).count() count = Candidate.objects.filter(create_admin=create_admin, issue_date__year=now.year, issue_date__month=now.month).count()
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4) candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
elif cert_template == 3:
cer_path = make_img(candidate.consumer_name, str(candidate.start_date.year), str(candidate.start_date.month), str(candidate.end_date.year), str(candidate.end_date.month), str(candidate.end_date.day), candidate.number, header_path=candidate.photo, mode=True)
candidate.path = cer_path
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
elif cert_template == 4:
cer_path = make_img(candidate.consumer_name, str(candidate.start_date.year), str(candidate.start_date.month), str(candidate.end_date.year), str(candidate.end_date.month), str(candidate.end_date.day), candidate.number, header_path=candidate.photo, mode=False)
candidate.path = cer_path
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
else: else:
candidate.number='SL'+ str(now.year)[-2:] + str(candidate.pk).zfill(6) candidate.number='SL'+ str(now.year)[-2:] + str(candidate.pk).zfill(6)
candidate.create_admin = create_admin candidate.create_admin = create_admin
candidate.save() candidate.save()
return {"id":candidate.pk, "number":candidate.number, "path":None} return {"id":candidate.pk, "number":candidate.number, "path":None}
def make_img(name:str, year:str, month:str, expiry_year:str, expiry_month:str, expiry_day:str, certificate_number:str, header_path=None, mode=None):
now = datetime.datetime.now()
font_path = settings.BASE_DIR + "/media/cert/template/STKAITI.TTF"
if mode:
demo_image_path = settings.BASE_DIR + "/media/cert/template/assess.png"
# demo_image_path = r"C:\code\cma_search\server\media\test.png"
img = Image.open(demo_image_path)
if img.mode == 'RGBA':
img = img.convert('RGB')
# Initialize ImageDraw
draw = ImageDraw.Draw(img)
# Set font paths and sizes
# font_path = r"C:/code/cma_search/server/media/font/SIMLI.TTF" # Update this to the correct font path
font_name = ImageFont.truetype(font_path, 20) # Font size for the name
font_text = ImageFont.truetype(font_path, 20) # Font size for the other text
font_number = ImageFont.truetype(font_path, 15) # Font size for the other text
# uoload header image
# header_path = "C:\code\cma_search\server\media\OIP.jpg"
if header_path:
header_img = Image.open(header_path)
# 指定粘贴的位置
header_position = (210, 235) # 粘贴图像的左上角位置
header_img = header_img.resize((140, 150))
img.paste(header_img, header_position)
if len(name) <= 3:
position_name = (105, 395)
else:
position_name = (100, 395)
position_year = (220, 395)
position_month = (280, 395)
position_exp_day = (310, 490)
position_exp_month = (270, 490)
position_exp_year = (210, 490)
position_cert_number = (180, 530)
# Define colors
color = (0, 0, 0) # Black color
# Draw the text on the image
draw.text(position_name, name, fill=color, font=font_name)
draw.text(position_year, year, fill=color, font=font_text)
draw.text(position_month, month, fill=color, font=font_text)
draw.text(position_exp_year, expiry_year, fill=color, font=font_text)
draw.text(position_exp_month, expiry_month, fill=color, font=font_text)
draw.text(position_exp_day, expiry_day, fill=color, font=font_text)
draw.text(position_cert_number, certificate_number, fill=color, font=font_number)
# Save the edited image
output_path = f"/media/cert/template/certificate/{now}.jpg"# Update this to the desired output path
img.save(settings.BASE_DIR + output_path, format='JPEG')
else:
demo_image_path = settings.BASE_DIR + "/media/cert/template/inspect.jpg"
# font_path = r"C:/code/cma_search/server/media/font/SIMLI.TTF" # Update this to the correct font path
img = Image.open(demo_image_path)
if img.mode == 'RGBA':
img = img.convert('RGB')
# Initialize ImageDraw
draw = ImageDraw.Draw(img)
# Set font paths and sizes
font_name = ImageFont.truetype(font_path, 20) # Font size for the name
font_text = ImageFont.truetype(font_path, 20) # Font size for the other text
font_number = ImageFont.truetype(font_path, 15) # Font size for the other text
# uoload header image
if header_path:
header_img = Image.open(header_path)
# 指定粘贴的位置
header_position = (240, 250) # 粘贴图像的左上角位置
header_img = header_img.resize((120, 150))
img.paste(header_img, header_position)
# Define text positions (X, Y) based on your image
if len(name) <= 3:
position_name = (130, 430)
else:
position_name = (140, 430)
position_year = (245, 430)
position_month = (308, 430)
position_exp_day = (430, 525)
position_exp_month = (390, 525)
position_exp_year = (330, 525)
position_cert_number = (200, 565)
# Define colors
color = (0, 0, 0) # Black color
# Draw the text on the image
draw.text(position_name, name, fill=color, font=font_name)
draw.text(position_year, year, fill=color, font=font_text)
draw.text(position_month, month, fill=color, font=font_text)
draw.text(position_exp_year, expiry_year, fill=color, font=font_text)
draw.text(position_exp_month, expiry_month, fill=color, font=font_text)
draw.text(position_exp_day, expiry_day, fill=color, font=font_text)
draw.text(position_cert_number, certificate_number, fill=color, font=font_number)
# Save the edited image
output_path = f"/media/cert/template/certificate/{now}.jpg"# Update this to the desired output path # Update this to the desired output path
img.save(settings.BASE_DIR + output_path, format='JPEG')
return output_path