|
|
@@ -1,6 +1,6 @@
|
|
|
<template>
|
|
|
<!-- 生成参赛证对话框 -->
|
|
|
- <el-dialog v-model="bibDialog.visible" title="生成参赛证" width="900px" append-to-body @close="handleCloseBibDialog">
|
|
|
+ <el-dialog v-model="bibDialog.visible" title="生成参赛证" width="1100px" append-to-body @close="handleCloseBibDialog">
|
|
|
<div class="bib-generator">
|
|
|
<!-- 预览面板 - 占满宽度 -->
|
|
|
<div class="preview-container" ref="previewContainer">
|
|
|
@@ -124,7 +124,7 @@
|
|
|
{{'上传背景图片' }}
|
|
|
</el-button>
|
|
|
</el-upload>
|
|
|
- <span class="upload-tip">建议尺寸:600×400px</span>
|
|
|
+ <span class="upload-tip">建议尺寸:2948×2079px</span>
|
|
|
</div>
|
|
|
<div v-if="bgImageFile" class="file-info">
|
|
|
<span class="file-name">{{ bgImageFile.name }}</span>
|
|
|
@@ -266,8 +266,14 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
const router = useRouter();
|
|
|
|
|
|
// 预览框尺寸常量(与后端保持一致)
|
|
|
-const PREVIEW_WIDTH = 600;
|
|
|
-const PREVIEW_HEIGHT = 400;
|
|
|
+// 实际输出尺寸
|
|
|
+const ACTUAL_WIDTH = 2948;
|
|
|
+const ACTUAL_HEIGHT = 2079;
|
|
|
+// 预览缩放比例
|
|
|
+const PREVIEW_SCALE = 3;
|
|
|
+// 预览尺寸(实际尺寸除以3,四舍五入)
|
|
|
+const PREVIEW_WIDTH = Math.round(ACTUAL_WIDTH / PREVIEW_SCALE); // 983
|
|
|
+const PREVIEW_HEIGHT = Math.round(ACTUAL_HEIGHT / PREVIEW_SCALE); // 693
|
|
|
|
|
|
// 响应式数据定义
|
|
|
const bibDialog = reactive({
|
|
|
@@ -599,9 +605,9 @@ const convertCoordinatesWithScale = (x: number, y: number): { x: number; y: numb
|
|
|
const previewWidth = container?.clientWidth || container?.offsetWidth || PREVIEW_WIDTH;
|
|
|
const previewHeight = container?.clientHeight || container?.offsetHeight || PREVIEW_HEIGHT;
|
|
|
|
|
|
- // 使用实际背景图片尺寸,如果没有则使用默认尺寸(600×400px)
|
|
|
- const actualWidth = bgImageDimensions.value?.width || 600;
|
|
|
- const actualHeight = bgImageDimensions.value?.height || 400;
|
|
|
+ // 使用固定的实际输出尺寸(2948×2079px)
|
|
|
+ const actualWidth = ACTUAL_WIDTH;
|
|
|
+ const actualHeight = ACTUAL_HEIGHT;
|
|
|
|
|
|
// 计算实际比例
|
|
|
const scaleX = actualWidth / previewWidth;
|
|
|
@@ -664,9 +670,9 @@ const handleCreateTask = async () => {
|
|
|
// 等待一帧确保所有尺寸都已计算完成
|
|
|
await nextTick();
|
|
|
|
|
|
- // 计算画布的实际尺寸(不考虑预览缩放)
|
|
|
- const originalWidth = bgImageDimensions.value?.width || 600;
|
|
|
- const originalHeight = bgImageDimensions.value?.height || 400;
|
|
|
+ // 计算画布的实际尺寸(使用固定的实际输出尺寸)
|
|
|
+ const originalWidth = ACTUAL_WIDTH;
|
|
|
+ const originalHeight = ACTUAL_HEIGHT;
|
|
|
|
|
|
// 将百分比坐标转换为像素坐标
|
|
|
const convertPercentToPixel = (percent: number, dimension: number): number => {
|
|
|
@@ -677,13 +683,13 @@ const handleCreateTask = async () => {
|
|
|
const logoPixelX = convertPercentToPixel(bibForm.logoX || 4.17, originalWidth);
|
|
|
const logoPixelY = convertPercentToPixel(bibForm.logoY || 6.25, originalHeight);
|
|
|
|
|
|
- // 计算Logo尺寸(前端统一处理,避免后端重复计算)
|
|
|
+ // 计算Logo尺寸(需要乘以缩放比例,保证与预览效果一致)
|
|
|
const logoOriginalWidth = logoImageDimensions.value?.width || 80;
|
|
|
const logoOriginalHeight = logoImageDimensions.value?.height || 80;
|
|
|
const logoPreviewSize = 80; // 前端预览时的最大尺寸
|
|
|
const logoScale = Math.min(1.0, logoPreviewSize / Math.max(logoOriginalWidth, logoOriginalHeight));
|
|
|
- const logoFinalWidth = Math.round(logoOriginalWidth * logoScale * bibForm.logoScale);
|
|
|
- const logoFinalHeight = Math.round(logoOriginalHeight * logoScale * bibForm.logoScale);
|
|
|
+ const logoFinalWidth = Math.round(logoOriginalWidth * logoScale * bibForm.logoScale * PREVIEW_SCALE);
|
|
|
+ const logoFinalHeight = Math.round(logoOriginalHeight * logoScale * bibForm.logoScale * PREVIEW_SCALE);
|
|
|
|
|
|
// 二维码像素坐标
|
|
|
const validQRCodeX = (qRCodeX !== null && qRCodeX !== undefined && !isNaN(qRCodeX)) ? qRCodeX : 11.67;
|
|
|
@@ -691,24 +697,24 @@ const handleCreateTask = async () => {
|
|
|
const qrPixelX = convertPercentToPixel(validQRCodeX, originalWidth);
|
|
|
const qrPixelY = convertPercentToPixel(validQRCodeY, originalHeight);
|
|
|
|
|
|
- // 计算二维码尺寸(与前端预览一致:32px * 缩放比例)
|
|
|
+ // 计算二维码尺寸(需要乘以缩放比例,保证与预览效果一致)
|
|
|
const qrInitialSize = 32;
|
|
|
- const qrFinalWidth = Math.round(qrInitialSize * bibForm.barcodeScale);
|
|
|
- const qrFinalHeight = Math.round(qrInitialSize * bibForm.barcodeScale);
|
|
|
+ const qrFinalWidth = Math.round(qrInitialSize * bibForm.barcodeScale * PREVIEW_SCALE);
|
|
|
+ const qrFinalHeight = Math.round(qrInitialSize * bibForm.barcodeScale * PREVIEW_SCALE);
|
|
|
|
|
|
// 号码像素坐标
|
|
|
const numberPixelX = convertPercentToPixel(bibForm.numberX || 50, originalWidth);
|
|
|
const numberPixelY = convertPercentToPixel(bibForm.numberY || 50, originalHeight);
|
|
|
|
|
|
- // 计算号码字体大小(应用缩放)
|
|
|
- const numberPixelFontSize = Math.round((bibForm.fontSize || 36) * bibForm.numberScale);
|
|
|
+ // 计算号码字体大小(需要乘以缩放比例,保证与预览效果一致)
|
|
|
+ const numberPixelFontSize = Math.round((bibForm.fontSize || 36) * bibForm.numberScale * PREVIEW_SCALE);
|
|
|
|
|
|
// 赛事名称像素坐标
|
|
|
const eventPixelX = convertPercentToPixel(bibForm.eventX || 50, originalWidth);
|
|
|
const eventPixelY = convertPercentToPixel(bibForm.eventY || 5, originalHeight);
|
|
|
|
|
|
- // 计算赛事名称字体大小(与前端预览一致:Math.min(28, Math.max(18, fontSize * 0.7)))
|
|
|
- const eventPixelFontSize = Math.round((bibForm.fontSize || 36) * bibForm.eventScale);
|
|
|
+ // 计算赛事名称字体大小(需要乘以缩放比例,保证与预览效果一致)
|
|
|
+ const eventPixelFontSize = Math.round((bibForm.fontSize || 36) * bibForm.eventScale * PREVIEW_SCALE);
|
|
|
|
|
|
const bibParams = {
|
|
|
// 画布实际尺寸
|
|
|
@@ -802,12 +808,12 @@ defineExpose({
|
|
|
align-items: center; // 让内容居中
|
|
|
}
|
|
|
|
|
|
-/* 预览容器 - 占满宽度 */
|
|
|
+/* 预览容器 - 固定尺寸 983x693 */
|
|
|
.preview-container {
|
|
|
border: 2px dashed #ddd;
|
|
|
border-radius: 8px;
|
|
|
- width: 600px !important;
|
|
|
- height: 400px !important;
|
|
|
+ width: 983px !important;
|
|
|
+ height: 693px !important;
|
|
|
position: relative;
|
|
|
overflow: auto;
|
|
|
display: flex;
|
|
|
@@ -847,8 +853,8 @@ defineExpose({
|
|
|
}
|
|
|
|
|
|
.preview-canvas {
|
|
|
- width: 600px;
|
|
|
- height: 400px;
|
|
|
+ width: 983px;
|
|
|
+ height: 693px;
|
|
|
position: relative;
|
|
|
background-color: #f5f5f5;
|
|
|
display: flex;
|