From 542a64a52f9867c085b9232c105be28c59470c08 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 2 Jan 2024 14:40:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20202312=E7=89=88=E6=9C=AC=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0005_certificate_培训结束日期.py | 18 +++ server/apps/edu/models.py | 9 +- server/apps/edu/services.py | 116 ++++++++++-------- 3 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 server/apps/edu/migrations/0005_certificate_培训结束日期.py diff --git a/server/apps/edu/migrations/0005_certificate_培训结束日期.py b/server/apps/edu/migrations/0005_certificate_培训结束日期.py new file mode 100644 index 0000000..6c7a551 --- /dev/null +++ b/server/apps/edu/migrations/0005_certificate_培训结束日期.py @@ -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), + ), + ] diff --git a/server/apps/edu/models.py b/server/apps/edu/models.py index 875b12e..7149455 100644 --- a/server/apps/edu/models.py +++ b/server/apps/edu/models.py @@ -2,14 +2,16 @@ from django.db import models from apps.system.models import CommonADModel, CommonAModel # Create your models here. + class Course(CommonAModel): - name = models.CharField('课程名', max_length=20) + name = models.CharField("课程名", max_length=20) + class Certificate(CommonADModel): - 证书方案 = models.CharField(max_length=20, default='202309') + 证书方案 = 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=10, default="男", null=True, blank=True) 证书编号 = models.CharField(max_length=20) 所属单位 = models.CharField(max_length=20, 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.ManyToManyField(Course, 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) diff --git a/server/apps/edu/services.py b/server/apps/edu/services.py index 6338d1c..591416d 100644 --- a/server/apps/edu/services.py +++ b/server/apps/edu/services.py @@ -2,31 +2,30 @@ 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" -} + +font_dict = {"font_1": "/media/cert/template/weibei.ttf", "font_2": "/media/cert/template/SIMLI.TTF"} def make_img_x(instance: Certificate): - if instance.证书方案 == '202309': + if instance.证书方案 == "202309": titles = [] if instance.是否内审员: - titles.append('内审员') + titles.append("内审员") if instance.是否授权签字人: - titles.append('授权签字人') + titles.append("授权签字人") if instance.是否质量负责人: - titles.append('质量负责人') + titles.append("质量负责人") if instance.是否最高管理者: - titles.append('最高管理者') - instance.证书地址 = make_img(instance.证书编号, instance.姓名, '、'.join(titles), font_dict[f'font_{instance.字体方案}']) + titles.append("最高管理者") + instance.证书地址 = make_img(instance.证书编号, instance.姓名, "、".join(titles), font_dict[f"font_{instance.字体方案}"]) instance.save() - elif instance.证书方案 == '202312': + 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.字体方案}']) + courses = ";".join(courses_list) + "。" + instance.证书地址 = make_img_2(instance.证书编号, instance.姓名, instance.培训日期, instance.培训结束日期, instance.发证日期, courses, font_dict[f"font_{instance.字体方案}"]) instance.save() + def text_wrap(draw, text, font, max_width): lines = [] @@ -34,65 +33,84 @@ def text_wrap(draw, text, font, max_width): words = list(text) # 尝试将单词拼成一行,使其宽度不要超过最大宽度 while words: - line = '' + 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): + +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) # 选择字体与大小 - 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) + font = ImageFont.truetype(settings.BASE_DIR + font_name_path, 140) + 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_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_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) + if len(name) <= 3: + position_name = (740, 840) + else: + position_name = (580, 840) + position_courses = (500, 1070) + position_note = (1990, 1600) + + 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 = (0,0,0) + color = (0, 0, 0) draw = ImageDraw.Draw(img) 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) 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) + 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) + draw.text(position_date, date_str, color, font=font_day) + draw.text(position_note, "经考试成绩合格,特发此证。", 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_issue_date, issue_date_str, color, font=font_day2) + # 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) + img.save(settings.BASE_DIR + path) return 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) # 选择字体与大小 - font = ImageFont.truetype(settings.BASE_DIR+ font_name_path, 155) - 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 = ImageFont.truetype(settings.BASE_DIR + font_name_path, 155) + 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) # print(font) # 在图片上添加文字 - # word = """ + # word = """ # 夜 归 小 朝 # 梦 鸟 舟 有 静 # 星 清 载 赤 安 @@ -103,9 +121,9 @@ def make_img(number, name, title, font_name_path): # ldc 2020-07-25 # """ - word_number = number #"CTCZL20230001" - word_name = name #"曹前明" - word_title = title #"内审员、授权签字人、质量负责人、最高管理者" + word_number = number # "CTCZL20230001" + word_name = name # "曹前明" + word_title = title # "内审员、授权签字人、质量负责人、最高管理者" # width = img.width # height = img.height # # 查看图片宽高 @@ -114,12 +132,12 @@ def make_img(number, name, title, font_name_path): position_name = (628, 860) position_title = (900, 1230) color_name = (82, 68, 19) - color = (0,0,0) + color = (0, 0, 0) draw = ImageDraw.Draw(img) draw.text(position_name, word_name, color_name, font=font) draw.text(position_title, word_title, color, font=font_title) draw.text(position_number, word_number, color_name, font=font_number) # 保存图片 path = f"/media/cert/{number}.jpg" - img.save(settings.BASE_DIR + path) - return path \ No newline at end of file + img.save(settings.BASE_DIR + path) + return path