移除发证单位并修正证书字体字重

This commit is contained in:
Certificate System
2026-08-13 18:21:24 +08:00
parent abbefc4b48
commit c66aa07efa
19 changed files with 69 additions and 55 deletions

View File

@@ -91,7 +91,6 @@ def create_certificate(
course_start_date=payload.course_start_date,
course_end_date=payload.course_end_date,
issue_date=payload.issue_date,
issuer_name=project.default_issuer_name,
template_code=template_code,
remark=payload.remark,
)
@@ -178,7 +177,6 @@ def _certificate_payload(certificate: Certificate, learner: Learner | None = Non
"course_start_date": certificate.course_start_date,
"course_end_date": certificate.course_end_date,
"issue_date": certificate.issue_date,
"issuer_name": certificate.issuer_name,
"template_code": certificate.template_code,
"status": certificate.status,
"pdf_status": certificate.pdf_status,
@@ -249,7 +247,6 @@ def preview_certificate(
"course_start_date": certificate.course_start_date.isoformat() if certificate.course_start_date else None,
"course_end_date": certificate.course_end_date.isoformat() if certificate.course_end_date else None,
"issue_date": certificate.issue_date.isoformat(),
"issuer_name": certificate.issuer_name,
"template_code": certificate.template_code,
"status": certificate.status,
"public_url": f"/cert/{public_token.token_value}" if public_token else "",

View File

@@ -220,7 +220,6 @@ def confirm_import_batch(
course_start_date=course_start_date,
course_end_date=course_end_date,
issue_date=issue_date,
issuer_name=project.default_issuer_name,
template_code=batch.template_code,
remark=None,
)

View File

@@ -37,7 +37,6 @@ def create_project(
default_certificate_name=payload.name,
default_course_name=payload.default_course_name,
default_stage_name=payload.default_stage_name,
default_issuer_name=payload.default_issuer_name,
default_template_code=template_code,
)
db.add(project)
@@ -61,7 +60,6 @@ def update_project(
"name": project.name,
"default_course_name": project.default_course_name,
"default_stage_name": project.default_stage_name,
"default_issuer_name": project.default_issuer_name,
"default_template_code": project.default_template_code,
"status": project.status,
}
@@ -72,8 +70,6 @@ def update_project(
project.default_course_name = payload.default_course_name
if payload.default_stage_name is not None:
project.default_stage_name = payload.default_stage_name
if payload.default_issuer_name is not None:
project.default_issuer_name = payload.default_issuer_name
if payload.default_template_code is not None:
try:
template_code = get_certificate_template(payload.default_template_code).code
@@ -86,7 +82,6 @@ def update_project(
"name": project.name,
"default_course_name": project.default_course_name,
"default_stage_name": project.default_stage_name,
"default_issuer_name": project.default_issuer_name,
"default_template_code": project.default_template_code,
"status": project.status,
}

View File

@@ -179,7 +179,6 @@ def public_certificate_payload(db: Session, certificate: Certificate, learner: L
"course_start_date": certificate.course_start_date.isoformat() if certificate.course_start_date else None,
"course_end_date": certificate.course_end_date.isoformat() if certificate.course_end_date else None,
"issue_date": certificate.issue_date.isoformat(),
"issuer_name": certificate.issuer_name,
"template_code": certificate.template_code,
"status": certificate.status,
"pdf_status": certificate.pdf_status,

View File

@@ -36,7 +36,6 @@ def seed_defaults(db: Session, admin_username: str, admin_password: str) -> None
default_certificate_name="培训结业证书",
default_course_name=name,
default_stage_name=None,
default_issuer_name="本公司",
default_template_code="classic",
)
)

View File

@@ -15,7 +15,6 @@ class ProjectCourse(Base):
default_certificate_name: Mapped[str] = mapped_column(String(128), default="培训结业证书")
default_course_name: Mapped[str | None] = mapped_column(String(128), nullable=True)
default_stage_name: Mapped[str | None] = mapped_column(String(128), nullable=True)
default_issuer_name: Mapped[str] = mapped_column(String(128), default="本公司")
default_template_code: Mapped[str] = mapped_column(String(32), default="classic")
status: Mapped[str] = mapped_column(String(32), default="active")
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
@@ -37,7 +36,6 @@ class Certificate(Base):
course_start_date: Mapped[date | None] = mapped_column(Date, nullable=True)
course_end_date: Mapped[date | None] = mapped_column(Date, nullable=True)
issue_date: Mapped[date] = mapped_column(Date)
issuer_name: Mapped[str] = mapped_column(String(128))
template_code: Mapped[str] = mapped_column(String(32), default="classic", index=True)
status: Mapped[str] = mapped_column(String(32), default="valid")
pdf_status: Mapped[str] = mapped_column(String(32), default="not_generated")

View File

@@ -44,7 +44,6 @@ class CertificateOut(BaseModel):
course_start_date: date | None
course_end_date: date | None
issue_date: date
issuer_name: str
template_code: str
status: str
pdf_status: str

View File

@@ -9,7 +9,6 @@ class ProjectCourseCreate(BaseModel):
default_certificate_name: str | None = Field(default=None, max_length=128)
default_course_name: str | None = Field(default=None, max_length=128)
default_stage_name: str | None = Field(default=None, max_length=128)
default_issuer_name: str = Field(default="本公司", min_length=1, max_length=128)
default_template_code: str = Field(default="classic", min_length=1, max_length=32)
@field_validator("code")
@@ -31,7 +30,6 @@ class ProjectCourseUpdate(BaseModel):
default_certificate_name: str | None = Field(default=None, max_length=128)
default_course_name: str | None = Field(default=None, max_length=128)
default_stage_name: str | None = Field(default=None, max_length=128)
default_issuer_name: str | None = Field(default=None, min_length=1, max_length=128)
default_template_code: str | None = Field(default=None, min_length=1, max_length=32)
status: str | None = Field(default=None, pattern="^(active|disabled)$")
@@ -51,7 +49,6 @@ class ProjectCourseOut(BaseModel):
default_certificate_name: str
default_course_name: str | None
default_stage_name: str | None
default_issuer_name: str
default_template_code: str
status: str
created_at: datetime

View File

@@ -269,15 +269,32 @@ def font(size: int, kind: str = "song", bold: bool = False, scale: float = 1.0)
("/System/Library/Fonts/STHeiti Light.ttc", 1),
],
}
paths = choices.get(kind, choices["song"])
if bold and kind == "song":
paths = [
bold_choices = {
"kai": [
r"C:\Windows\Fonts\msyhbd.ttc",
r"C:\Windows\Fonts\simhei.ttf",
"/usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc",
("/System/Library/Fonts/Supplemental/Songti.ttc", 0),
("/System/Library/Fonts/STHeiti Medium.ttc", 1),
],
"hei": [
r"C:\Windows\Fonts\msyhbd.ttc",
r"C:\Windows\Fonts\simhei.ttf",
"/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc",
("/System/Library/Fonts/STHeiti Medium.ttc", 1),
("/System/Library/Fonts/Hiragino Sans GB.ttc", 2),
] + paths
],
"song": [
r"C:\Windows\Fonts\msyhbd.ttc",
r"C:\Windows\Fonts\simhei.ttf",
"/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc",
("/System/Library/Fonts/STHeiti Medium.ttc", 1),
("/System/Library/Fonts/Hiragino Sans GB.ttc", 2),
],
}
paths = choices.get(kind, choices["song"])
if bold:
paths = bold_choices.get(kind, bold_choices["song"]) + paths
for item in paths:
path, index = item if isinstance(item, tuple) else (item, 0)
if Path(path).exists():
@@ -344,7 +361,7 @@ def draw_issue_date_numbers(
x_scale: float,
y_scale: float,
) -> None:
text_font = font(13, "song", True, scale)
text_font = font(13, "song", False, scale)
y = 688 * y_scale
for value, x in [(issue_year, 500), (issue_month, 535), (issue_day, 566)]:
draw.text((x * x_scale, y), value, fill="#111111", font=text_font, anchor="mm")
@@ -364,8 +381,6 @@ def draw_inline(
) -> float:
text_font = font(size, kind, bold, scale)
draw.text((x, y), value, fill="#111111", font=text_font, anchor="ls")
if bold:
draw.text((x + 0.45 * x_scale, y), value, fill="#111111", font=text_font, anchor="ls")
return x + draw.textlength(value, font=text_font) + gap * x_scale
@@ -374,7 +389,6 @@ def draw_course_name(draw: ImageDraw.ImageDraw, value: str, x: float, y: int) ->
text_font = font(27, "kai", True)
if draw.textlength(value, font=text_font) <= max_width:
draw.text((x, y), value, fill="#111111", font=text_font)
draw.text((x + 0.45, y), value, fill="#111111", font=text_font)
return y
start_y = y + 34
@@ -382,7 +396,6 @@ def draw_course_name(draw: ImageDraw.ImageDraw, value: str, x: float, y: int) ->
for index, line in enumerate(lines):
line_y = start_y + index * 34
draw.text((185, line_y), line, fill="#111111", font=text_font)
draw.text((185.45, line_y), line, fill="#111111", font=text_font)
return start_y + (len(lines) - 1) * 34
@@ -409,8 +422,6 @@ def draw_inline_flow(
x = line_start
y += line_height
draw.text((x, y), char, fill="#111111", font=text_font, anchor="ls")
if style == "course":
draw.text((x + 0.45 * x_scale, y), char, fill="#111111", font=text_font, anchor="ls")
x += width

View File

@@ -25,7 +25,6 @@
<div class="meta">
<div>证书编号:{{ certificate_no }}</div>
<div>发证日期:{{ issue_date }}</div>
<div>发证单位:{{ issuer_name }}</div>
</div>
{% if qr_code_data_url %}<img class="qr" src="{{ qr_code_data_url }}" alt="二维码" />{% endif %}
<div class="disclaimer">