|
@@ -37,6 +37,40 @@
|
|
|
<el-color-picker v-model="bibForm.fontColor" @change="handleFontColorChange"></el-color-picker>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
+ <!-- 在字体设置表单项后添加缩放控制 -->
|
|
|
+ <el-form-item label="选中元素">
|
|
|
+ <div style="display: flex; gap: 10px; align-items: center">
|
|
|
+ <el-select v-model="selectedElement" placeholder="选择元素" style="width: 120px">
|
|
|
+ <el-option label="Logo" value="logo"></el-option>
|
|
|
+ <el-option label="二维码" value="barcode"></el-option>
|
|
|
+ <el-option label="号码" value="number"></el-option>
|
|
|
+ <el-option label="赛事名称" value="event"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-button
|
|
|
+ v-if="selectedElement"
|
|
|
+ @click="scaleElement(0.9)"
|
|
|
+ :disabled="!selectedElement"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ 缩小
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ v-if="selectedElement"
|
|
|
+ @click="scaleElement(1.1)"
|
|
|
+ :disabled="!selectedElement"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ 放大
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ v-if="selectedElement"
|
|
|
+ @click="resetElementScale"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ 重置
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="赛事名称">
|
|
|
<el-input v-model="bibForm.eventName" placeholder="请输入赛事名称" maxlength="50" show-word-limit />
|
|
|
</el-form-item>
|
|
@@ -53,9 +87,13 @@
|
|
|
class="draggable-element logo-element"
|
|
|
:style="{
|
|
|
left: bibForm.logoX + 'px',
|
|
|
- top: bibForm.logoY + 'px'
|
|
|
+ top: bibForm.logoY + 'px',
|
|
|
+ transform: `translateX(-50%) scale(${bibForm.logoScale})`,
|
|
|
+ transformOrigin: 'top left'
|
|
|
}"
|
|
|
@mousedown="startDrag($event, 'logo')"
|
|
|
+ @click="selectedElement = 'logo'"
|
|
|
+ :class="{ selected: selectedElement === 'logo' }"
|
|
|
>
|
|
|
<img :src="logoImageUrl" alt="Logo" style="max-width: 80px; max-height: 80px" />
|
|
|
</div>
|
|
@@ -65,9 +103,13 @@
|
|
|
class="draggable-element barcode-element"
|
|
|
:style="{
|
|
|
left: bibForm.qRCodeX + 'px',
|
|
|
- top: bibForm.qRCodeY + 'px'
|
|
|
+ top: bibForm.qRCodeY + 'px',
|
|
|
+ transform: `translateX(-50%) scale(${bibForm.barcodeScale})`,
|
|
|
+ transformOrigin: 'top left',
|
|
|
}"
|
|
|
@mousedown="startDrag($event, 'barcode')"
|
|
|
+ @click="selectedElement = 'barcode'"
|
|
|
+ :class="{ selected: selectedElement === 'barcode' }"
|
|
|
>
|
|
|
<svg
|
|
|
t="1755833734016"
|
|
@@ -101,27 +143,38 @@
|
|
|
<!-- 赛事名称预览 -->
|
|
|
<div
|
|
|
v-if="bibForm.eventName"
|
|
|
- class="event-name-preview"
|
|
|
+ class="event-name-preview draggable-element"
|
|
|
:style="{
|
|
|
fontSize: Math.min(28, Math.max(18, bibForm.fontSize * 0.7)) + 'px',
|
|
|
color: 'black',
|
|
|
- fontFamily: '黑体'
|
|
|
+ fontFamily: '黑体',
|
|
|
+ left: bibForm.eventX + '%',
|
|
|
+ top: bibForm.eventY + '%',
|
|
|
+ transform: `translateX(-50%) scale(${bibForm.eventScale})`,
|
|
|
+ transformOrigin: 'top center'
|
|
|
}"
|
|
|
+ @mousedown="startDrag($event, 'event')"
|
|
|
+ @click="selectedElement = 'event'"
|
|
|
+ :class="{ selected: selectedElement === 'event' }"
|
|
|
>
|
|
|
{{ bibForm.eventName }}
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
|
|
|
<!-- 示例数字 1234 -->
|
|
|
<div
|
|
|
class="draggable-element number-element"
|
|
|
:style="{
|
|
|
- left: '50%',
|
|
|
- top: '50%',
|
|
|
- transform: 'translate(-50%, -50%)',
|
|
|
+ left: bibForm.numberX + '%',
|
|
|
+ top: bibForm.numberY + '%',
|
|
|
+ transform: `translate(-50%, -50%) scale(${bibForm.numberScale})`,
|
|
|
fontSize: Math.min(bibForm.fontSize, 56) + 'px',
|
|
|
color: bibForm.fontColorHex,
|
|
|
- fontFamily: bibForm.fontName
|
|
|
+ fontFamily: bibForm.fontName,
|
|
|
+ transformOrigin: 'center'
|
|
|
}"
|
|
|
+ @mousedown="startDrag($event, 'number')"
|
|
|
+ @click="selectedElement = 'number'"
|
|
|
+ :class="{ selected: selectedElement === 'number' }"
|
|
|
>
|
|
|
1234
|
|
|
</div>
|
|
@@ -165,6 +218,8 @@ const bibDialog = reactive({
|
|
|
loading: false
|
|
|
});
|
|
|
|
|
|
+const selectedElement = ref<string>(''); // 当前选中的元素
|
|
|
+
|
|
|
const bibForm = reactive({
|
|
|
logoX: 25,
|
|
|
logoY: 25,
|
|
@@ -175,6 +230,16 @@ const bibForm = reactive({
|
|
|
fontColor: '#000000',
|
|
|
fontColorHex: '#000000',
|
|
|
eventName: '',
|
|
|
+ // 添加位置字段
|
|
|
+ numberX: 50, // 百分比位置
|
|
|
+ numberY: 50, // 百分比位置
|
|
|
+ eventX: 50, // 百分比位置
|
|
|
+ eventY: 5, // 百分比位置
|
|
|
+ // 添加元素尺寸控制字段
|
|
|
+ logoScale: 1,
|
|
|
+ barcodeScale: 1,
|
|
|
+ numberScale: 1,
|
|
|
+ eventScale: 1,
|
|
|
});
|
|
|
|
|
|
const bgImageFile = ref<File | null>(null);
|
|
@@ -210,6 +275,46 @@ const handleCloseBibDialog = () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 添加元素缩放方法
|
|
|
+const scaleElement = (factor: number) => {
|
|
|
+ if (!selectedElement.value) return;
|
|
|
+
|
|
|
+ switch (selectedElement.value) {
|
|
|
+ case 'logo':
|
|
|
+ bibForm.logoScale = Math.max(0.1, bibForm.logoScale * factor);
|
|
|
+ break;
|
|
|
+ case 'barcode':
|
|
|
+ bibForm.barcodeScale = Math.max(0.1, bibForm.barcodeScale * factor);
|
|
|
+ break;
|
|
|
+ case 'number':
|
|
|
+ bibForm.numberScale = Math.max(0.1, bibForm.numberScale * factor);
|
|
|
+ break;
|
|
|
+ case 'event':
|
|
|
+ bibForm.eventScale = Math.max(0.1, bibForm.eventScale * factor);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 重置元素缩放
|
|
|
+const resetElementScale = () => {
|
|
|
+ if (!selectedElement.value) return;
|
|
|
+
|
|
|
+ switch (selectedElement.value) {
|
|
|
+ case 'logo':
|
|
|
+ bibForm.logoScale = 1;
|
|
|
+ break;
|
|
|
+ case 'barcode':
|
|
|
+ bibForm.barcodeScale = 1;
|
|
|
+ break;
|
|
|
+ case 'number':
|
|
|
+ bibForm.numberScale = 1;
|
|
|
+ break;
|
|
|
+ case 'event':
|
|
|
+ bibForm.eventScale = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
// 重置表单
|
|
|
const resetBibForm = () => {
|
|
|
// 设置默认值(像素单位)- 适配2:3横屏比例
|
|
@@ -222,11 +327,26 @@ const resetBibForm = () => {
|
|
|
bibForm.fontColor = '#000000';
|
|
|
bibForm.fontColorHex = '#000000';
|
|
|
bibForm.eventName = '';
|
|
|
+
|
|
|
+ // 添加位置重置
|
|
|
+ bibForm.numberX = 50;
|
|
|
+ bibForm.numberY = 50;
|
|
|
+ bibForm.eventX = 50;
|
|
|
+ bibForm.eventY = 5;
|
|
|
+
|
|
|
bgImageFile.value = null;
|
|
|
logoImageFile.value = null;
|
|
|
bgImageUrl.value = '';
|
|
|
logoImageUrl.value = '';
|
|
|
|
|
|
+ // 重置缩放
|
|
|
+ bibForm.logoScale = 1;
|
|
|
+ bibForm.barcodeScale = 1;
|
|
|
+ bibForm.numberScale = 1;
|
|
|
+ bibForm.eventScale = 1;
|
|
|
+ // 重置选中元素
|
|
|
+ selectedElement.value = '';
|
|
|
+
|
|
|
// 清除上传的文件
|
|
|
if (bgUploadRef.value) {
|
|
|
bgUploadRef.value.clearFiles();
|
|
@@ -291,12 +411,22 @@ const startDrag = (event: MouseEvent, target: string) => {
|
|
|
dragState.startX = event.clientX;
|
|
|
dragState.startY = event.clientY;
|
|
|
|
|
|
+ selectedElement.value = target;
|
|
|
+
|
|
|
if (target === 'logo') {
|
|
|
dragState.startLeft = bibForm.logoX;
|
|
|
dragState.startTop = bibForm.logoY;
|
|
|
} else if (target === 'barcode') {
|
|
|
dragState.startLeft = bibForm.qRCodeX;
|
|
|
dragState.startTop = bibForm.qRCodeY;
|
|
|
+ } else if (target === 'number') {
|
|
|
+ // 修复:使用存储的位置数据
|
|
|
+ dragState.startLeft = bibForm.numberX;
|
|
|
+ dragState.startTop = bibForm.numberY;
|
|
|
+ } else if (target === 'event') {
|
|
|
+ // 修复:使用存储的位置数据
|
|
|
+ dragState.startLeft = bibForm.eventX;
|
|
|
+ dragState.startTop = bibForm.eventY;
|
|
|
}
|
|
|
|
|
|
document.addEventListener('mousemove', handleDrag);
|
|
@@ -310,12 +440,28 @@ const handleDrag = (event: MouseEvent) => {
|
|
|
const deltaX = event.clientX - dragState.startX;
|
|
|
const deltaY = event.clientY - dragState.startY;
|
|
|
|
|
|
+ const container = previewContainer.value;
|
|
|
+ const previewWidth = container?.clientWidth || container?.offsetWidth || 600;
|
|
|
+ const previewHeight = container?.clientHeight || container?.offsetHeight || 400;
|
|
|
+
|
|
|
if (dragState.dragTarget === 'logo') {
|
|
|
bibForm.logoX = Math.max(0, dragState.startLeft + deltaX);
|
|
|
bibForm.logoY = Math.max(0, dragState.startTop + deltaY);
|
|
|
} else if (dragState.dragTarget === 'barcode') {
|
|
|
bibForm.qRCodeX = Math.max(0, dragState.startLeft + deltaX);
|
|
|
bibForm.qRCodeY = Math.max(0, dragState.startTop + deltaY);
|
|
|
+ } else if (dragState.dragTarget === 'number') {
|
|
|
+ // 修复:实际更新位置数据
|
|
|
+ const newX = Math.max(0, Math.min(100, dragState.startLeft + (deltaX / previewWidth) * 100));
|
|
|
+ const newY = Math.max(0, Math.min(100, dragState.startTop + (deltaY / previewHeight) * 100));
|
|
|
+ bibForm.numberX = newX;
|
|
|
+ bibForm.numberY = newY;
|
|
|
+ } else if (dragState.dragTarget === 'event') {
|
|
|
+ // 修复:实际更新位置数据
|
|
|
+ const newX = Math.max(0, Math.min(100, dragState.startLeft + (deltaX / previewWidth) * 100));
|
|
|
+ const newY = Math.max(0, Math.min(100, dragState.startTop + (deltaY / previewHeight) * 100));
|
|
|
+ bibForm.eventX = newX;
|
|
|
+ bibForm.eventY = newY;
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -475,9 +621,14 @@ const handleGenerateBibFile = async () => {
|
|
|
qRCodeX: qrCoords.x,
|
|
|
qRCodeY: qrCoords.y,
|
|
|
fontName: bibForm.fontName || 'simhei',
|
|
|
- fontSize: Math.round((bibForm.fontSize || 36) * 0.75), // 字体大小转换为PDF点并四舍五入为整数
|
|
|
+ fontSize: Math.round((bibForm.fontSize || 36) * 0.75),
|
|
|
fontColor: parseInt((bibForm.fontColor || '#000000').replace('#', ''), 16),
|
|
|
eventName: bibForm.eventName || '',
|
|
|
+ // 缩放参数
|
|
|
+ logoScale: bibForm.logoScale,
|
|
|
+ barcodeScale: bibForm.barcodeScale,
|
|
|
+ numberScale: bibForm.numberScale,
|
|
|
+ eventScale: bibForm.eventScale,
|
|
|
};
|
|
|
|
|
|
// 显示进度提示
|
|
@@ -660,20 +811,20 @@ defineExpose({
|
|
|
padding: 4px;
|
|
|
white-space: nowrap;
|
|
|
user-select: none;
|
|
|
- pointer-events: none;
|
|
|
+ /* pointer-events: none; */
|
|
|
text-align: center;
|
|
|
min-width: 80px;
|
|
|
}
|
|
|
|
|
|
.event-name-preview {
|
|
|
position: absolute;
|
|
|
- top: 5%;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
+ // top: 5%;
|
|
|
+ // left: 50%;
|
|
|
+ // transform: translateX(-50%);
|
|
|
font-weight: bold;
|
|
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
|
|
user-select: none;
|
|
|
- pointer-events: none;
|
|
|
+ // pointer-events: none;
|
|
|
z-index: 5;
|
|
|
text-align: center;
|
|
|
white-space: nowrap;
|
|
@@ -681,4 +832,10 @@ defineExpose({
|
|
|
overflow: hidden;
|
|
|
text-overflow: ellipsis;
|
|
|
}
|
|
|
+
|
|
|
+/* 选中元素样式 */
|
|
|
+.draggable-element.selected {
|
|
|
+ outline: 2px solid #409eff;
|
|
|
+ outline-offset: 2px;
|
|
|
+}
|
|
|
</style>
|