Files
sam-api/public/tenant/product/bending.php
hskwon cc206fdbed style: Laravel Pint 코드 포맷팅 적용
- PSR-12 스타일 가이드 준수
- 302개 파일 스타일 이슈 자동 수정
- 코드 로직 변경 없음 (포맷팅만)
2025-11-06 17:45:49 +09:00

290 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
$CURRENT_SECTION = 'item';
include '../inc/header.php';
?>
<div class="container" style="max-width:1280px; margin-top:24px;">
<form id="bendForm">
<!-- 기본정보 -->
<details open class="mb-3">
<summary class="fw-semibold">기본정보 입력</summary>
<div class="row g-2 mt-2">
<div class="col-md-2">
<label class="form-label">분류</label>
<select class="form-select" id="bfCategory">
<option>스크린</option><option>철재</option><option>기타</option>
</select>
</div>
<div class="col-md-5">
<label class="form-label">품목명</label>
<input class="form-control" id="bfName" placeholder="품목명">
</div>
<div class="col-md-2">
<label class="form-label">단위</label>
<select class="form-select" id="bfUnit"><option>EA</option><option>mm</option></select>
</div>
<div class="col-md-3">
<label class="form-label">검색태그</label>
<input class="form-control" id="bfTags" placeholder="쉼표로 구분">
</div>
</div>
</details>
<!-- 고정 규격 -->
<details open class="mb-3">
<summary class="fw-semibold">고정 규격정보 입력</summary>
<div class="row g-2 mt-2">
<div class="col-md-3">
<label class="form-label">폭</label>
<input class="form-control" id="fxWidth" type="number" min="0" placeholder="폭(mm)">
</div>
<div class="col-md-3">
<label class="form-label">규격(가로×세로)</label>
<div class="input-group">
<input class="form-control" id="fxW" type="number" min="0" placeholder="가로">
<span class="input-group-text">×</span>
<input class="form-control" id="fxH" type="number" min="0" placeholder="세로">
</div>
</div>
<div class="col-md-3">
<label class="form-label">재질</label>
<select class="form-select" id="fxMaterial">
<option>선택</option><option>EGI</option><option>SUS</option><option>AL</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label">레이일폭</label>
<input class="form-control" id="fxRail" type="number" min="0" placeholder="mm">
</div>
</div>
</details>
<!-- 기타정보 (+) -->
<details class="mb-3">
<summary class="fw-semibold d-flex align-items-center">기타정보 입력
<button type="button" class="btn btn-sm btn-outline-primary ms-2" id="btnAddMeta"></button>
</summary>
<div id="metaRows" class="mt-2"></div>
</details>
<!-- 절곡 이미지/스텝 -->
<details open class="mb-4">
<summary class="fw-semibold">절곡 이미지 & 스텝</summary>
<div class="row g-3 mt-2">
<!-- 스텝 테이블 -->
<div class="col-md-7">
<div class="table-responsive">
<table class="table table-bordered align-middle">
<thead class="table-light">
<tr>
<th style="width:60px;">번호</th>
<th>입력 길이</th>
<th>연신율(%)</th>
<th>연신 후</th>
<th>합계</th>
<th style="width:90px;">A각</th>
<th style="width:110px;">옵션</th>
</tr>
</thead>
<tbody id="stepBody"></tbody>
</table>
</div>
<div class="d-flex gap-2">
<button type="button" class="btn btn-outline-secondary btn-sm" id="btnAddCol">마지막 열 추가</button>
<button type="button" class="btn btn-outline-secondary btn-sm" id="btnDelCol">마지막 열 삭제</button>
<button type="button" class="btn btn-outline-danger btn-sm" id="btnClear">모든칸 비우기</button>
</div>
</div>
<!-- 캔버스 -->
<div class="col-md-5">
<div class="d-flex justify-content-between align-items-center mb-2">
<strong>도면 캔버스</strong>
<div class="d-flex gap-2">
<input type="file" id="bgImage" accept="image/*" class="form-control form-control-sm">
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnDrawLine">선</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnDrawRect">사각</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnClearCanvas">지우기</button>
</div>
</div>
<div class="border rounded p-1">
<canvas id="cv" width="420" height="300" style="display:block; background:#fff;"></canvas>
</div>
<small class="text-muted">이미지를 올리면 배경으로 표시됩니다. 간단한 선/사각 도구 제공.</small>
</div>
</div>
</details>
<div class="d-flex justify-content-end gap-2">
<button class="btn btn-outline-secondary" type="button" id="btnPreview">미리보기</button>
<button class="btn btn-primary" type="submit">저장</button>
</div>
<textarea id="preview" class="form-control mt-3" rows="8" style="display:none;"></textarea>
</form>
</div>
<style>
.meta-row .btn{ --bs-btn-padding-y:.15rem; --bs-btn-padding-x:.4rem; --bs-btn-font-size:.75rem; }
td input[type=number]{ width: 90px; }
</style>
<script>
(function($){
// ===== 기타정보 행 =====
function metaRowTpl(key='', val='', unit=''){
return `<div class="row g-2 align-items-center meta-row mb-2">
<div class="col-4"><input class="form-control form-control-sm meta-key" placeholder="규격"></div>
<div class="col-5"><input class="form-control form-control-sm meta-val" placeholder="값"></div>
<div class="col-2"><input class="form-control form-control-sm meta-unit" placeholder="단위"></div>
<div class="col-1 text-end"><button type="button" class="btn btn-outline-danger btn-sm btnMetaDel"></button></div>
</div>`;
}
$('#btnAddMeta').on('click', ()=> $('#metaRows').append(metaRowTpl()));
$('#metaRows').on('click','.btnMetaDel', function(){ $(this).closest('.meta-row').remove(); });
// ===== 절곡 스텝 테이블 =====
let COLS = 2; // 기본 2열
function drawTable(){
const rows=[];
const headers=['번호','입력','연신율','연신후','합계','A각','옵션']; // 설명용
for(let r=0;r<7;r++){
const cells=[];
if (r===0){ // 번호
for(let c=0;c<COLS;c++) cells.push(`<input class="form-control form-control-sm step-no" type="number" min="1" value="${c+1}">`);
}else if(r===1){ // 입력
for(let c=0;c<COLS;c++) cells.push(`<input class="form-control form-control-sm step-in" type="number" min="0" value="0">`);
}else if(r===2){ // 연신율
for(let c=0;c<COLS;c++) cells.push(`<input class="form-control form-control-sm step-strain" type="number" step="0.01" value="0">`);
}else if(r===3){ // 연신율계산 후 (= 입력 × (1 + 연신율/100))
for(let c=0;c<COLS;c++) cells.push(`<input class="form-control form-control-sm step-after" type="number" readonly value="0">`);
}else if(r===4){ // 합계 (누적)
for(let c=0;c<COLS;c++) cells.push(`<input class="form-control form-control-sm step-sum" type="number" readonly value="0">`);
}else if(r===5){ // 음영
for(let c=0;c<COLS;c++) cells.push(`<input class="form-check-input step-dark" type="checkbox">`);
}else if(r===6){ // A각 표시
for(let c=0;c<COLS;c++) cells.push(`<input class="form-check-input step-a" type="checkbox">`);
}
rows.push(`<tr>${r===0?'<th>번호</th>': r===1?'<th>입력</th>': r===2?'<th>연신율(%)</th>': r===3?'<th>연신 후</th>': r===4?'<th>합계</th>': r===5?'<th>음영</th>':'<th>A각 표시</th>'}
${cells.map(td=>`<td>${td}</td>`).join('')}
</tr>`);
}
$('#stepBody').html(rows.join(''));
recalc();
}
function recalc(){
let running = 0;
$('#stepBody tr').each(function(idx,tr){
if (idx<3){ /* 입력·연신율 줄 계산은 아래에서 */ }
if (idx===3 || idx===4){ // 연신후 / 합계 재계산
const row = $(tr);
row.find('td').each(function(col){
const $in = $('#stepBody .step-in').eq(col);
const $st = $('#stepBody .step-strain').eq(col);
const after = (+$in.val()||0) * (1 + (+$st.val()||0)/100);
if (idx===3){
row.find('.step-after').eq(col).val(after.toFixed(2));
}
});
}
});
// 합계(누적)
const afters = $('#stepBody .step-after');
const sums = $('#stepBody .step-sum');
let acc=0;
afters.each(function(i){
acc += +($(this).val()||0);
sums.eq(i).val(acc.toFixed(2));
});
}
$('#stepBody').on('input', '.step-in, .step-strain', recalc);
$('#btnAddCol').on('click', ()=>{ COLS++; drawTable(); });
$('#btnDelCol').on('click', ()=>{ COLS=Math.max(1,COLS-1); drawTable(); });
$('#btnClear').on('click', ()=>{
$('#stepBody input[type=number]').val(0);
$('#stepBody input[type=checkbox]').prop('checked',false);
recalc();
});
// ===== 캔버스 (아주 간단한 드로잉) =====
const cv = document.getElementById('cv');
const ctx = cv.getContext('2d');
let bgImg = null;
function clearCanvas(){
ctx.clearRect(0,0,cv.width,cv.height);
if (bgImg){ ctx.drawImage(bgImg, 0,0, cv.width, cv.height); }
}
$('#bgImage').on('change', function(){
const f=this.files[0]; if(!f) return;
const img=new Image();
img.onload=function(){ bgImg=img; clearCanvas(); };
img.src=URL.createObjectURL(f);
});
let mode='line', drawing=false, sx=0, sy=0;
$('#btnDrawLine').on('click', ()=> mode='line');
$('#btnDrawRect').on('click', ()=> mode='rect');
$('#btnClearCanvas').on('click', ()=>{ bgImg=null; clearCanvas(); });
cv.addEventListener('mousedown', e=>{ drawing=true; const r=cv.getBoundingClientRect(); sx=e.clientX-r.left; sy=e.clientY-r.top; });
cv.addEventListener('mouseup', e=>{
if(!drawing) return; drawing=false;
const r=cv.getBoundingClientRect(); const x=e.clientX-r.left, y=e.clientY-r.top;
ctx.strokeStyle='#333'; ctx.lineWidth=2; clearCanvas();
if(mode==='line'){ ctx.beginPath(); ctx.moveTo(sx,sy); ctx.lineTo(x,y); ctx.stroke(); }
else{ const w=x-sx, h=y-sy; ctx.strokeRect(sx,sy,w,h); }
});
// ===== 미리보기/저장 =====
function collect(){
// 메타
const metas=[]; $('#metaRows .meta-row').each(function(){
metas.push({
key: $(this).find('.meta-key').val().trim(),
value: $(this).find('.meta-val').val().trim(),
unit: $(this).find('.meta-unit').val().trim(),
});
});
// 스텝
const no = $('#stepBody .step-no').map((i,e)=>+e.value||0).get();
const inp = $('#stepBody .step-in').map((i,e)=>+e.value||0).get();
const str = $('#stepBody .step-strain').map((i,e)=>+e.value||0).get();
const aft = $('#stepBody .step-after').map((i,e)=>+e.value||0).get();
const sum = $('#stepBody .step-sum').map((i,e)=>+e.value||0).get();
const dark = $('#stepBody .step-dark').map((i,e)=>e.checked).get();
const a = $('#stepBody .step-a').map((i,e)=>e.checked).get();
const steps = no.map((_,i)=>({ no:no[i], length:inp[i], strain:str[i], after:aft[i], acc:sum[i], shade:dark[i], a_mark:a[i] }));
// 캔버스 스냅샷
const snapshot = cv.toDataURL('image/png');
return {
base:{ category:$('#bfCategory').val(), name:$('#bfName').val(), unit:$('#bfUnit').val(), tags:$('#bfTags').val() },
fixed:{ width:+$('#fxWidth').val()||0, w:+$('#fxW').val()||0, h:+$('#fxH').val()||0, material:$('#fxMaterial').val(), rail:+$('#fxRail').val()||0 },
metas, steps, cols: COLS, snapshot
};
}
$('#btnPreview').on('click', ()=>{
const txt = JSON.stringify(collect(), null, 2);
$('#preview').val(txt).show().focus();
});
$('#bendForm').on('submit', function(e){
e.preventDefault();
const payload = collect();
console.log('[BENDING SAVE]', payload);
alert('절곡 저장(모의). 콘솔을 확인하세요.');
// 실제는 $.post('/tenant/api/product/save_bending.php', payload)
});
// 초기
$('#metaRows').append(metaRowTpl());
drawTable();
clearCanvas();
})(jQuery);
</script>
<?php include '../inc/footer.php'; ?>