feat: 202312版本证书功能

This commit is contained in:
caoqianming 2024-01-02 14:40:24 +08:00
parent 301130d4bf
commit 542a64a52f
3 changed files with 91 additions and 52 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-12-28 09:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('edu', '0004_auto_20231226_1517'),
]
operations = [
migrations.AddField(
model_name='certificate',
name='培训结束日期',
field=models.DateField(blank=True, null=True),
),
]

View File

@ -2,14 +2,16 @@ from django.db import models
from apps.system.models import CommonADModel, CommonAModel from apps.system.models import CommonADModel, CommonAModel
# Create your models here. # Create your models here.
class Course(CommonAModel): class Course(CommonAModel):
name = models.CharField('课程名', max_length=20) name = models.CharField("课程名", max_length=20)
class Certificate(CommonADModel): class Certificate(CommonADModel):
证书方案 = models.CharField(max_length=20, default='202309') 证书方案 = models.CharField(max_length=20, default="202309")
字体方案 = models.PositiveSmallIntegerField(default=1) 字体方案 = models.PositiveSmallIntegerField(default=1)
姓名 = models.CharField(max_length=20) 姓名 = models.CharField(max_length=20)
性别 = models.CharField(max_length=10, default='', null=True, blank=True) 性别 = models.CharField(max_length=10, default="", null=True, blank=True)
证书编号 = models.CharField(max_length=20) 证书编号 = models.CharField(max_length=20)
所属单位 = models.CharField(max_length=20, null=True, blank=True) 所属单位 = models.CharField(max_length=20, null=True, blank=True)
单位名称 = models.CharField(max_length=30, null=True, blank=True) 单位名称 = models.CharField(max_length=30, null=True, blank=True)
@ -23,5 +25,6 @@ class Certificate(CommonADModel):
是否需要北京标研培训合格 = models.BooleanField(default=False) 是否需要北京标研培训合格 = models.BooleanField(default=False)
课程列表 = models.ManyToManyField(Course, blank=True) 课程列表 = models.ManyToManyField(Course, blank=True)
培训日期 = models.DateField(null=True, blank=True) 培训日期 = models.DateField(null=True, blank=True)
培训结束日期 = models.DateField(null=True, blank=True)
发证日期 = models.DateField(null=True, blank=True) 发证日期 = models.DateField(null=True, blank=True)
证书地址 = models.CharField(max_length=100, null=True, blank=True) 证书地址 = models.CharField(max_length=100, null=True, blank=True)

View File

@ -2,31 +2,30 @@ from PIL import ImageFont, ImageDraw, Image
from django.conf import settings from django.conf import settings
from apps.edu.models import Certificate from apps.edu.models import Certificate
from datetime import date from datetime import date
font_dict = {
'font_1': "/media/cert/template/weibei.ttf", font_dict = {"font_1": "/media/cert/template/weibei.ttf", "font_2": "/media/cert/template/SIMLI.TTF"}
'font_2': "/media/cert/template/SIMLI.TTF"
}
def make_img_x(instance: Certificate): def make_img_x(instance: Certificate):
if instance.证书方案 == '202309': if instance.证书方案 == "202309":
titles = [] titles = []
if instance.是否内审员: if instance.是否内审员:
titles.append('内审员') titles.append("内审员")
if instance.是否授权签字人: if instance.是否授权签字人:
titles.append('授权签字人') titles.append("授权签字人")
if instance.是否质量负责人: if instance.是否质量负责人:
titles.append('质量负责人') titles.append("质量负责人")
if instance.是否最高管理者: if instance.是否最高管理者:
titles.append('最高管理者') titles.append("最高管理者")
instance.证书地址 = make_img(instance.证书编号, instance.姓名, ''.join(titles), font_dict[f'font_{instance.字体方案}']) instance.证书地址 = make_img(instance.证书编号, instance.姓名, "".join(titles), font_dict[f"font_{instance.字体方案}"])
instance.save() instance.save()
elif instance.证书方案 == '202312': elif instance.证书方案 == "202312":
courses_list = [i.name for i in instance.课程列表.all()] courses_list = [i.name for i in instance.课程列表.all()]
courses = ''.join(courses_list) + '' courses = "".join(courses_list) + ""
instance.证书地址 = make_img_2(instance.证书编号, instance.姓名, instance.培训日期, instance.发证日期, courses, font_dict[f'font_{instance.字体方案}']) instance.证书地址 = make_img_2(instance.证书编号, instance.姓名, instance.培训日期, instance.培训结束日期, instance.发证日期, courses, font_dict[f"font_{instance.字体方案}"])
instance.save() instance.save()
def text_wrap(draw, text, font, max_width): def text_wrap(draw, text, font, max_width):
lines = [] lines = []
@ -34,65 +33,84 @@ def text_wrap(draw, text, font, max_width):
words = list(text) words = list(text)
# 尝试将单词拼成一行,使其宽度不要超过最大宽度 # 尝试将单词拼成一行,使其宽度不要超过最大宽度
while words: while words:
line = '' line = ""
# 当加上一个新单词不会让行宽超出最大宽度时就加上它 # 当加上一个新单词不会让行宽超出最大宽度时就加上它
while words and draw.textlength(line + words[0], font=font) <= max_width: while words and draw.textlength(line + words[0], font=font) <= max_width:
line += words.pop(0) line += words.pop(0)
lines.append(line.strip()) # 移除多余的空格 lines.append(line.strip()) # 移除多余的空格
return lines return lines
def make_img_2(number, name, att_date: date, issue_date: date, courses, font_name_path):
def make_img_2(number, name, att_date: date, att_date2: date, issue_date: date, courses, font_name_path):
# 打开底版图片 # 打开底版图片
imageFile = settings.BASE_DIR + '/media/cert/template/background2.jpg' imageFile = settings.BASE_DIR + "/media/cert/template/background2.jpg"
img = Image.open(imageFile) img = Image.open(imageFile)
# 选择字体与大小 # 选择字体与大小
font = ImageFont.truetype(settings.BASE_DIR+ font_name_path, 155) font = ImageFont.truetype(settings.BASE_DIR + font_name_path, 140)
font_courses = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/simkai.ttf", 100) font_courses = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/simkai.ttf", 90)
font_number = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/timesbd.ttf", 58) 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) font_day = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/siyuan.otf", 68)
font_day2 = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/siyuan.otf", 58)
position_number = (1730, 606) position_number = (1730, 606)
position_name = (720, 840) if len(name) <= 3:
position_courses = (490, 1070) position_name = (740, 840)
position_a_y = (1530, 900) else:
position_a_m = (1870, 900) position_name = (580, 840)
position_a_d = (2170, 900) position_courses = (500, 1070)
position_i_y = (2010, 1910) position_note = (1990, 1600)
position_i_m = (2254, 1910)
position_i_d = (2446, 1910) att_date_str = att_date.strftime("%Y年%m月%d")
issue_date_str = issue_date.strftime("%Y年%m月%d")
if att_date == att_date2:
date_str = f"同志于{att_date_str}参加了以下培训课程:"
else:
att_date2_str = att_date2.strftime("%Y年%m月%d")
date_str = f"同志于{att_date_str}-{att_date2_str}参加了以下培训课程:"
position_date = (1170, 900)
position_issue_date = (1990, 1910)
# 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_name = (82, 68, 19)
color = (0,0,0) color = (0, 0, 0)
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
draw.text(position_name, name, color_name, font=font) draw.text(position_name, name, color_name, font=font)
max_width = 2800 # 根据实际证书的内容区域来设置最大宽度 max_width = 2600 # 根据实际证书的内容区域来设置最大宽度
wrapped_courses = text_wrap(draw, courses, font_courses, max_width) wrapped_courses = text_wrap(draw, courses, font_courses, max_width)
y_offset = 0 y_offset = 0
for line in wrapped_courses: for line in wrapped_courses:
draw.text((position_courses[0], position_courses[1] + y_offset), line, (0,0,0), font=font_courses) draw.text((position_courses[0], position_courses[1] + y_offset), line, (0, 0, 0), font=font_courses)
y_offset = y_offset + 180 y_offset = y_offset + 180
draw.text(position_number, number, color_name, font=font_number) 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_date, date_str, color, font=font_day)
draw.text(position_a_m, str(att_date.month), color, font=font_day) draw.text(position_note, "经考试成绩合格,特发此证。", color, font=font_day)
draw.text(position_a_d, str(att_date.day), color, font=font_day) # draw.text(position_a_m, str(att_date.month), color, font=font_day)
draw.text(position_i_y, str(issue_date.year), color, font=font_day) # draw.text(position_a_d, str(att_date.day), color, font=font_day)
draw.text(position_i_m, str(issue_date.month), color, font=font_day) draw.text(position_issue_date, issue_date_str, color, font=font_day2)
draw.text(position_i_d, str(issue_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" path = f"/media/cert/{number}.jpg"
img.save(settings.BASE_DIR + path) img.save(settings.BASE_DIR + path)
return path return path
def make_img(number, name, title, font_name_path): def make_img(number, name, title, font_name_path):
# 打开底版图片 # 打开底版图片
imageFile = settings.BASE_DIR + '/media/cert/template/background.jpg' imageFile = settings.BASE_DIR + "/media/cert/template/background.jpg"
img = Image.open(imageFile) img = Image.open(imageFile)
# 选择字体与大小 # 选择字体与大小
font = ImageFont.truetype(settings.BASE_DIR+ font_name_path, 155) font = ImageFont.truetype(settings.BASE_DIR + font_name_path, 155)
font_title = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/siyuan.otf", 76) font_title = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/siyuan.otf", 76)
font_number = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/timesbd.ttf", 58) font_number = ImageFont.truetype(settings.BASE_DIR + "/media/cert/template/timesbd.ttf", 58)
# print(font) # print(font)
# 在图片上添加文字 # 在图片上添加文字
# word = """ # word = """
# 夜 归 小 朝 # 夜 归 小 朝
# 梦 鸟 舟 有 静 # 梦 鸟 舟 有 静
# 星 清 载 赤 安 # 星 清 载 赤 安
@ -103,9 +121,9 @@ def make_img(number, name, title, font_name_path):
# ldc 2020-07-25 # ldc 2020-07-25
# """ # """
word_number = number #"CTCZL20230001" word_number = number # "CTCZL20230001"
word_name = name #"曹前明" word_name = name # "曹前明"
word_title = title #"内审员、授权签字人、质量负责人、最高管理者" word_title = title # "内审员、授权签字人、质量负责人、最高管理者"
# width = img.width # width = img.width
# height = img.height # height = img.height
# # 查看图片宽高 # # 查看图片宽高
@ -114,12 +132,12 @@ def make_img(number, name, title, font_name_path):
position_name = (628, 860) position_name = (628, 860)
position_title = (900, 1230) position_title = (900, 1230)
color_name = (82, 68, 19) color_name = (82, 68, 19)
color = (0,0,0) color = (0, 0, 0)
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
draw.text(position_name, word_name, color_name, font=font) draw.text(position_name, word_name, color_name, font=font)
draw.text(position_title, word_title, color, font=font_title) draw.text(position_title, word_title, color, font=font_title)
draw.text(position_number, word_number, color_name, font=font_number) draw.text(position_number, word_number, color_name, font=font_number)
# 保存图片 # 保存图片
path = f"/media/cert/{number}.jpg" path = f"/media/cert/{number}.jpg"
img.save(settings.BASE_DIR + path) img.save(settings.BASE_DIR + path)
return path return path