feat:E-Sign 필드 에디터에 폰트 크기 속성 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
김보곤
2026-02-13 07:20:41 +09:00
parent 631287e75e
commit b206eeeb2d
5 changed files with 48 additions and 12 deletions

View File

@@ -383,6 +383,7 @@ public function configureFields(Request $request, int $id): JsonResponse
'fields.*.height' => 'required|numeric',
'fields.*.field_type' => 'required|in:signature,stamp,text,date,checkbox',
'fields.*.field_label' => 'nullable|string|max:100',
'fields.*.font_size' => 'nullable|integer|min:6|max:72',
'fields.*.is_required' => 'nullable|boolean',
]);
@@ -404,6 +405,7 @@ public function configureFields(Request $request, int $id): JsonResponse
'height' => $field['height'],
'field_type' => $field['field_type'],
'field_label' => $field['field_label'] ?? null,
'font_size' => $field['font_size'] ?? null,
'is_required' => $field['is_required'] ?? true,
'sort_order' => $i,
]);
@@ -621,6 +623,7 @@ public function storeTemplate(Request $request): JsonResponse
'items.*.height' => 'required|numeric',
'items.*.field_type' => 'required|in:signature,stamp,text,date,checkbox',
'items.*.field_label' => 'nullable|string|max:100',
'items.*.font_size' => 'nullable|integer|min:6|max:72',
'items.*.is_required' => 'nullable|boolean',
]);
@@ -680,6 +683,7 @@ public function storeTemplate(Request $request): JsonResponse
'height' => $item['height'],
'field_type' => $item['field_type'],
'field_label' => $item['field_label'] ?? null,
'font_size' => $item['font_size'] ?? null,
'is_required' => $item['is_required'] ?? true,
'sort_order' => $i,
]);
@@ -833,6 +837,7 @@ public function updateTemplateItems(Request $request, int $templateId): JsonResp
'items.*.height' => 'required|numeric',
'items.*.field_type' => 'required|in:signature,stamp,text,date,checkbox',
'items.*.field_label' => 'nullable|string|max:100',
'items.*.font_size' => 'nullable|integer|min:6|max:72',
'items.*.is_required' => 'nullable|boolean',
]);
@@ -857,6 +862,7 @@ public function updateTemplateItems(Request $request, int $templateId): JsonResp
'height' => round($itemData['height'], 2),
'field_type' => $itemData['field_type'],
'field_label' => $itemData['field_label'] ?? '',
'font_size' => $itemData['font_size'] ?? null,
'is_required' => $itemData['is_required'] ?? true,
'sort_order' => $i,
]);
@@ -922,6 +928,7 @@ public function duplicateTemplate(int $id): JsonResponse
'height' => $item->height,
'field_type' => $item->field_type,
'field_label' => $item->field_label,
'font_size' => $item->font_size,
'is_required' => $item->is_required,
'sort_order' => $item->sort_order,
]);
@@ -1001,6 +1008,7 @@ public function applyTemplate(Request $request, int $id): JsonResponse
'height' => $item->height,
'field_type' => $item->field_type,
'field_label' => $item->field_label,
'font_size' => $item->font_size,
'is_required' => $item->is_required,
'sort_order' => $item->sort_order,
]);
@@ -1065,6 +1073,7 @@ public function copyFieldsFromContract(Request $request, int $id, int $sourceId)
'height' => $field->height,
'field_type' => $field->field_type,
'field_label' => $field->field_label,
'font_size' => $field->font_size,
'is_required' => $field->is_required,
'sort_order' => $field->sort_order,
]);

View File

@@ -19,6 +19,7 @@ class EsignFieldTemplateItem extends Model
'height',
'field_type',
'field_label',
'font_size',
'is_required',
'sort_order',
];
@@ -30,6 +31,7 @@ class EsignFieldTemplateItem extends Model
'position_y' => 'decimal:2',
'width' => 'decimal:2',
'height' => 'decimal:2',
'font_size' => 'integer',
'is_required' => 'boolean',
'sort_order' => 'integer',
];

View File

@@ -20,6 +20,7 @@ class EsignSignField extends Model
'height',
'field_type',
'field_label',
'font_size',
'field_value',
'is_required',
'sort_order',
@@ -31,6 +32,7 @@ class EsignSignField extends Model
'position_y' => 'decimal:4',
'width' => 'decimal:4',
'height' => 'decimal:4',
'font_size' => 'integer',
'is_required' => 'boolean',
'sort_order' => 'integer',
];

View File

@@ -364,11 +364,19 @@ className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
</div>
<div>
<label className="text-[10px] text-gray-500">페이지</label>
<input type="number" value={selectedField.page_number} min="1"
onChange={e => onUpdateField(selectedFieldIndex, { page_number: parseInt(e.target.value) || 1 })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
<div className="grid grid-cols-2 gap-1.5">
<div>
<label className="text-[10px] text-gray-500">페이지</label>
<input type="number" value={selectedField.page_number} min="1"
onChange={e => onUpdateField(selectedFieldIndex, { page_number: parseInt(e.target.value) || 1 })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
<div>
<label className="text-[10px] text-gray-500">폰트 크기 (pt)</label>
<input type="number" value={selectedField.font_size || ''} min="6" max="72" placeholder="자동"
onChange={e => onUpdateField(selectedFieldIndex, { font_size: e.target.value ? parseInt(e.target.value) : null })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
</div>
<div className="flex items-center gap-2 pt-1">
<label className="flex items-center gap-1.5 text-xs cursor-pointer">
@@ -717,6 +725,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
position_x: parseFloat(f.position_x), position_y: parseFloat(f.position_y),
width: parseFloat(f.width), height: parseFloat(f.height),
field_type: f.field_type, field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
}));
setFields(loadedFields);
@@ -816,7 +825,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
const newField = {
signer_id: signerId, page_number: currentPage,
position_x: 25, position_y: 40, width: 20, height: 5,
field_type: fieldType, field_label: '', is_required: true,
field_type: fieldType, field_label: '', font_size: null, is_required: true,
};
const newFields = [...fields, newField];
setFields(newFields);
@@ -865,6 +874,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
height: round2(f.height),
field_type: f.field_type,
field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
sort_order: i,
})),
@@ -898,6 +908,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
height: round2(f.height),
field_type: f.field_type,
field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
}));
@@ -937,6 +948,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
position_x: parseFloat(f.position_x), position_y: parseFloat(f.position_y),
width: parseFloat(f.width), height: parseFloat(f.height),
field_type: f.field_type, field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
}));
setFields(newFields);
@@ -963,6 +975,7 @@ className="px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-7
position_x: parseFloat(f.position_x), position_y: parseFloat(f.position_y),
width: parseFloat(f.width), height: parseFloat(f.height),
field_type: f.field_type, field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
}));
setFields(newFields);

View File

@@ -337,11 +337,19 @@ className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
</div>
<div>
<label className="text-[10px] text-gray-500">페이지</label>
<input type="number" value={selectedField.page_number} min="1"
onChange={e => onUpdateField(selectedFieldIndex, { page_number: parseInt(e.target.value) || 1 })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
<div className="grid grid-cols-2 gap-1.5">
<div>
<label className="text-[10px] text-gray-500">페이지</label>
<input type="number" value={selectedField.page_number} min="1"
onChange={e => onUpdateField(selectedFieldIndex, { page_number: parseInt(e.target.value) || 1 })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
<div>
<label className="text-[10px] text-gray-500">폰트 크기 (pt)</label>
<input type="number" value={selectedField.font_size || ''} min="6" max="72" placeholder="자동"
onChange={e => onUpdateField(selectedFieldIndex, { font_size: e.target.value ? parseInt(e.target.value) : null })}
className="w-full border rounded px-2 py-1 text-xs mt-0.5" />
</div>
</div>
<div className="flex items-center gap-2 pt-1">
<label className="flex items-center gap-1.5 text-xs cursor-pointer">
@@ -469,6 +477,7 @@ className="text-gray-300 hover:text-red-500 flex-shrink-0 ml-1">&times;</button>
height: parseFloat(f.height),
field_type: f.field_type,
field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
}));
setFields(loadedFields);
@@ -534,7 +543,7 @@ className="text-gray-300 hover:text-red-500 flex-shrink-0 ml-1">&times;</button>
const newField = {
signer_order: signerOrder, page_number: currentPage,
position_x: 25, position_y: 40, width: 20, height: 5,
field_type: fieldType, field_label: '', is_required: true,
field_type: fieldType, field_label: '', font_size: null, is_required: true,
};
const newFields = [...fields, newField];
setFields(newFields);
@@ -599,6 +608,7 @@ className="text-gray-300 hover:text-red-500 flex-shrink-0 ml-1">&times;</button>
height: round2(f.height),
field_type: f.field_type,
field_label: f.field_label || '',
font_size: f.font_size || null,
is_required: f.is_required !== false,
})),
}),