Files
sam-api/public/tenant/product/bending.php

290 lines
15 KiB
PHP
Raw Normal View History

2025-08-10 02:36:50 +09:00
<?php
$CURRENT_SECTION = 'item';
2025-08-10 02:36:50 +09:00
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'; ?>