打印服务

This commit is contained in:
2026-08-04 18:54:22 +08:00
parent b7d36d4766
commit dc2f844467
44 changed files with 2576 additions and 110 deletions
@@ -1,6 +0,0 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${PRINT_DB_URL:jdbc:mysql://127.0.0.1:3306/baiyue_print?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true}
username: ${PRINT_DB_USERNAME:root}
password: ${PRINT_DB_PASSWORD:123456}
@@ -1,6 +0,0 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${PRINT_TEST_DB_URL:jdbc:mysql://${TEST_DB_HOST:8.163.30.128}:${TEST_DB_PORT:3306}/baiyue_print?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true}
username: ${PRINT_TEST_DB_USERNAME:${TEST_DB_USERNAME:root}}
password: ${PRINT_TEST_DB_PASSWORD:${TEST_DB_PASSWORD}}
+12
View File
@@ -23,6 +23,18 @@ spring:
baiyue:
security:
jwt-secret: ${JWT_SECRET:change-me-to-at-least-32-bytes-long-before-start}
internal-service-token: ${INTERNAL_SERVICE_TOKEN:}
print:
pdf:
max-pages: ${PRINT_PDF_MAX_PAGES:2000}
max-request-bytes: ${PRINT_PDF_MAX_REQUEST_BYTES:2097152}
max-output-bytes: ${PRINT_PDF_MAX_OUTPUT_BYTES:33554432}
max-concurrent-generations: ${PRINT_PDF_MAX_CONCURRENT_GENERATIONS:4}
acquire-timeout: ${PRINT_PDF_ACQUIRE_TIMEOUT:1s}
template-code: INBOUND_MARK_V1
supported-width-mm: 100
supported-height-mm: 100
font-resource: fonts/NotoSansSC-Bold.ttf
management.endpoints.web.exposure.include: health,info,prometheus
logging:
-62
View File
@@ -1,62 +0,0 @@
-- 打印服务独占数据库,业务服务只保存打印任务逻辑ID。
CREATE DATABASE IF NOT EXISTS baiyue_print
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
USE baiyue_print;
CREATE TABLE IF NOT EXISTS print_template (
id BIGINT UNSIGNED NOT NULL COMMENT '模板ID(雪花ID)',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID,平台模板使用平台租户ID',
template_code VARCHAR(64) NOT NULL COMMENT '模板编码',
template_name VARCHAR(128) NOT NULL COMMENT '模板名称',
template_type VARCHAR(32) NOT NULL COMMENT '模板类型',
content TEXT NOT NULL COMMENT '模板内容',
version_no INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '模板版本号',
status VARCHAR(24) NOT NULL DEFAULT 'ACTIVE' COMMENT '模板状态',
created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_by BIGINT UNSIGNED NOT NULL COMMENT '最后修改人ID',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_print_template_code (tenant_id, template_code, version_no),
KEY idx_print_template_status (tenant_id, status)
) ENGINE=InnoDB COMMENT='打印模板表';
CREATE TABLE IF NOT EXISTS print_job (
id BIGINT UNSIGNED NOT NULL COMMENT '打印任务ID(雪花ID)',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
job_no VARCHAR(40) NOT NULL COMMENT '打印任务编号',
template_id BIGINT UNSIGNED NOT NULL COMMENT '打印模板逻辑ID',
business_type VARCHAR(32) NULL COMMENT '关联业务类型',
business_id VARCHAR(64) NULL COMMENT '关联业务逻辑ID',
printer_code VARCHAR(64) NULL COMMENT '目标打印机编码',
copies INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '打印份数',
payload_json JSON NOT NULL COMMENT '模板数据快照',
status VARCHAR(24) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态',
output_file_id BIGINT UNSIGNED NULL COMMENT '生成文件的逻辑ID',
error_message VARCHAR(1000) NULL COMMENT '失败原因',
requested_by BIGINT UNSIGNED NOT NULL COMMENT '申请人ID',
requested_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '申请时间',
started_at DATETIME(3) NULL COMMENT '开始时间',
completed_at DATETIME(3) NULL COMMENT '完成时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_print_job_no (tenant_id, job_no),
KEY idx_print_job_status (tenant_id, status, requested_at),
KEY idx_print_job_business (tenant_id, business_type, business_id)
) ENGINE=InnoDB COMMENT='打印任务表';
CREATE TABLE IF NOT EXISTS print_job_history (
id BIGINT UNSIGNED NOT NULL COMMENT '任务历史ID',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
print_job_id BIGINT UNSIGNED NOT NULL COMMENT '打印任务逻辑ID',
from_status VARCHAR(24) NULL COMMENT '变更前状态',
to_status VARCHAR(24) NOT NULL COMMENT '变更后状态',
message VARCHAR(500) NULL COMMENT '状态说明',
operator_id BIGINT UNSIGNED NULL COMMENT '操作人ID',
occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '发生时间',
PRIMARY KEY (id),
KEY idx_print_history_job (tenant_id, print_job_id, occurred_at)
) ENGINE=InnoDB COMMENT='打印任务状态历史表';
Binary file not shown.
+93
View File
@@ -0,0 +1,93 @@
Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,131 @@
openapi: 3.0.3
info:
title: Baiyue Print Internal API
version: 1.0.0
description: Internal stateless PDF rendering API. This path must not be exposed through Gateway.
paths:
/internal/print/v1/pdfs/inbound-marks:
post:
summary: Generate an inbound-mark PDF
operationId: generateInboundMarkPdf
security:
- internalServiceToken: []
parameters:
- $ref: '#/components/parameters/RequestId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/InboundMarkPdfRequest'
responses:
'200':
description: PDF generation succeeded, or a business error was returned as ApiResponse JSON.
headers:
Content-Disposition:
description: UTF-8 attachment filename. Present only for a successful PDF.
schema:
type: string
Cache-Control:
schema:
type: string
example: no-store
X-Print-Page-Count:
schema:
type: integer
minimum: 1
maximum: 2000
X-Request-Id:
schema:
type: string
content:
application/pdf:
schema:
type: string
format: binary
application/json:
schema:
$ref: '#/components/schemas/ApiError'
'413':
description: Request body exceeds the configured limit.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
components:
securitySchemes:
internalServiceToken:
type: apiKey
in: header
name: X-Internal-Service-Token
parameters:
RequestId:
name: X-Request-Id
in: header
required: false
schema:
type: string
schemas:
InboundMarkPdfRequest:
type: object
required: [templateCode, pageSpec, labels]
properties:
templateCode:
type: string
enum: [INBOUND_MARK_V1]
pageSpec:
$ref: '#/components/schemas/PageSpec'
downloadFileName:
type: string
maxLength: 120
example: PCHK2608040174-19件-MCC1.pdf
labels:
type: array
minItems: 1
maxItems: 2000
items:
$ref: '#/components/schemas/InboundMarkLabel'
PageSpec:
type: object
required: [widthMm, heightMm]
properties:
widthMm:
type: number
enum: [100]
heightMm:
type: number
enum: [100]
InboundMarkLabel:
type: object
required: [topCode, warehouseText, cartonText, routeText, qrContent]
properties:
topCode:
type: string
warehouseText:
type: string
cartonText:
type: string
routeText:
type: string
qrContent:
type: string
minLength: 1
maxLength: 34
pattern: '^[\\x20-\\x7E]+$'
ApiError:
type: object
required: [code, message]
properties:
code:
type: string
enum: [A0400, A0403, A0422, A0429, S0500]
message:
type: string
data:
nullable: true
requestId:
type: string
nullable: true
traceId:
type: string
nullable: true