feat: 新版证书发放初步完成

This commit is contained in:
caoqianming 2023-12-26 17:49:52 +08:00
parent a4c5058a26
commit 301130d4bf
7 changed files with 172 additions and 21 deletions

View File

@ -1,3 +1,5 @@
from django.contrib import admin
from .models import Course
# Register your models here.
admin.site.register(Course)

View File

@ -0,0 +1,62 @@
# Generated by Django 3.2.12 on 2023-12-26 07:17
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('edu', '0003_certificate_字体方案'),
]
operations = [
migrations.AddField(
model_name='certificate',
name='发证日期',
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name='certificate',
name='培训日期',
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name='certificate',
name='证书方案',
field=models.CharField(default='202309', max_length=20),
),
migrations.AlterField(
model_name='certificate',
name='单位名称',
field=models.CharField(blank=True, max_length=30, null=True),
),
migrations.AlterField(
model_name='certificate',
name='所属单位',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.CreateModel(
name='Course',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=20, verbose_name='课程名')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='certificate',
name='课程列表',
field=models.ManyToManyField(blank=True, to='edu.Course'),
),
]

View File

@ -1,13 +1,18 @@
from django.db import models
from apps.system.models import CommonADModel
from apps.system.models import CommonADModel, CommonAModel
# Create your models here.
class Course(CommonAModel):
name = models.CharField('课程名', max_length=20)
class Certificate(CommonADModel):
证书方案 = models.CharField(max_length=20, default='202309')
字体方案 = models.PositiveSmallIntegerField(default=1)
姓名 = models.CharField(max_length=20)
性别 = models.CharField(max_length=10, default='', null=True, blank=True)
证书编号 = models.CharField(max_length=20)
所属单位 = models.CharField(max_length=20)
单位名称 = models.CharField(max_length=30)
所属单位 = models.CharField(max_length=20, null=True, blank=True)
单位名称 = models.CharField(max_length=30, null=True, blank=True)
职务 = models.CharField(max_length=20, null=True, blank=True)
手机号 = models.CharField(max_length=11, null=True, blank=True)
是否内审员 = models.BooleanField(default=False)
@ -16,5 +21,7 @@ class Certificate(CommonADModel):
是否最高管理者 = models.BooleanField(default=False)
是否需要集团证书 = models.BooleanField(default=False)
是否需要北京标研培训合格 = models.BooleanField(default=False)
课程列表 = models.ManyToManyField(Course, blank=True)
培训日期 = models.DateField(null=True, blank=True)
发证日期 = models.DateField(null=True, blank=True)
证书地址 = models.CharField(max_length=100, null=True, blank=True)
字体方案 = models.PositiveSmallIntegerField(default=1)

View File

@ -1,5 +1,5 @@
from rest_framework import serializers
from apps.edu.models import Certificate
from apps.edu.models import Certificate, Course
from apps.edu.services import make_img_x
class CertificateSerializer(serializers.ModelSerializer):
@ -12,3 +12,10 @@ class CertificateSerializer(serializers.ModelSerializer):
instance = super().save(**kwargs)
make_img_x(instance)
return instance
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = '__all__'
read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'is_deleted']

View File

@ -1,6 +1,7 @@
from PIL import ImageFont, ImageDraw, Image
from django.conf import settings
from apps.edu.models import Certificate
from datetime import date
font_dict = {
'font_1': "/media/cert/template/weibei.ttf",
'font_2': "/media/cert/template/SIMLI.TTF"
@ -8,17 +9,78 @@ font_dict = {
def make_img_x(instance: Certificate):
titles = []
if instance.是否内审员:
titles.append('内审员')
if instance.是否授权签字人:
titles.append('授权签字人')
if instance.是否质量负责人:
titles.append('质量负责人')
if instance.是否最高管理者:
titles.append('最高管理者')
instance.证书地址 = make_img(instance.证书编号, instance.姓名, ''.join(titles), font_dict[f'font_{instance.字体方案}'])
instance.save()
if instance.证书方案 == '202309':
titles = []
if instance.是否内审员:
titles.append('内审员')
if instance.是否授权签字人:
titles.append('授权签字人')
if instance.是否质量负责人:
titles.append('质量负责人')
if instance.是否最高管理者:
titles.append('最高管理者')
instance.证书地址 = make_img(instance.证书编号, instance.姓名, ''.join(titles), font_dict[f'font_{instance.字体方案}'])
instance.save()
elif instance.证书方案 == '202312':
courses_list = [i.name for i in instance.课程列表.all()]
courses = ''.join(courses_list) + ''
instance.证书地址 = make_img_2(instance.证书编号, instance.姓名, instance.培训日期, instance.发证日期, courses, font_dict[f'font_{instance.字体方案}'])
instance.save()
def text_wrap(draw, text, font, max_width):
lines = []
# 将文本分割成单词
words = list(text)
# 尝试将单词拼成一行,使其宽度不要超过最大宽度
while words:
line = ''
# 当加上一个新单词不会让行宽超出最大宽度时就加上它
while words and draw.textlength(line + words[0], font=font) <= max_width:
line += words.pop(0)
lines.append(line.strip()) # 移除多余的空格
return lines
def make_img_2(number, name, att_date: date, issue_date: date, courses, font_name_path):
# 打开底版图片
imageFile = settings.BASE_DIR + '/media/cert/template/background2.jpg'
img = Image.open(imageFile)
# 选择字体与大小
font = ImageFont.truetype(settings.BASE_DIR+ font_name_path, 155)
font_courses = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/simkai.ttf", 100)
font_number = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/timesbd.ttf", 58)
font_day = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/Dengl.ttf", 68)
position_number = (1730, 606)
position_name = (720, 840)
position_courses = (490, 1070)
position_a_y = (1530, 900)
position_a_m = (1870, 900)
position_a_d = (2170, 900)
position_i_y = (2010, 1910)
position_i_m = (2254, 1910)
position_i_d = (2446, 1910)
color_name = (82, 68, 19)
color = (0,0,0)
draw = ImageDraw.Draw(img)
draw.text(position_name, name, color_name, font=font)
max_width = 2800 # 根据实际证书的内容区域来设置最大宽度
wrapped_courses = text_wrap(draw, courses, font_courses, max_width)
y_offset = 0
for line in wrapped_courses:
draw.text((position_courses[0], position_courses[1] + y_offset), line, (0,0,0), font=font_courses)
y_offset = y_offset + 180
draw.text(position_number, number, color_name, font=font_number)
draw.text(position_a_y, str(att_date.year), color, font=font_day)
draw.text(position_a_m, str(att_date.month), color, font=font_day)
draw.text(position_a_d, str(att_date.day), color, font=font_day)
draw.text(position_i_y, str(issue_date.year), color, font=font_day)
draw.text(position_i_m, str(issue_date.month), color, font=font_day)
draw.text(position_i_d, str(issue_date.day), color, font=font_day)
# 保存图片
path = f"/media/cert/{number}.jpg"
img.save(settings.BASE_DIR + path)
return path
def make_img(number, name, title, font_name_path):
# 打开底版图片

View File

@ -1,7 +1,7 @@
from rest_framework.viewsets import ModelViewSet
from apps.system.mixins import CreateUpdateCustomMixin
from apps.edu.serializers import CertificateSerializer
from apps.edu.models import Certificate
from apps.edu.serializers import CertificateSerializer, CourseSerializer
from apps.edu.models import Certificate, Course
from rest_framework.decorators import action
from django.conf import settings
from rest_framework.exceptions import ParseError
@ -11,6 +11,14 @@ from rest_framework.serializers import Serializer
from rest_framework.permissions import AllowAny
from apps.edu.services import make_img_x
# Create your views here.
class CourseViewSet(CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'course',
'put': 'course', 'delete': 'course'}
queryset = Course.objects.all()
serializer_class = CourseSerializer
search_fields = ['name']
ordering = ['create_time']
class CertificateViewSet(CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'certificate',
@ -18,8 +26,8 @@ class CertificateViewSet(CreateUpdateCustomMixin, ModelViewSet):
queryset = Certificate.objects.all()
serializer_class = CertificateSerializer
search_fields = ['姓名', '证书编号', '所属单位']
filterset_fields = ['是否内审员','是否授权签字人', '是否质量负责人', '是否最高管理者', '姓名', '证书编号', '所属单位', '单位名称']
ordering = ['-create_time']
filterset_fields = ['是否内审员','是否授权签字人', '是否质量负责人', '是否最高管理者', '姓名', '证书编号', '所属单位', '单位名称', '课程列表']
ordering = ['-create_time', '证书编号']
def get_authenticators(self):
if self.request.method == 'GET':

3
server/ruff.toml Normal file
View File

@ -0,0 +1,3 @@
line-length = 200
fix = true