진료유형관리 5뎁스로 변경

This commit is contained in:
pjs
2026-02-24 00:53:54 +09:00
parent ac43b2757f
commit 04de663693
6 changed files with 133 additions and 31 deletions

View File

@@ -42,6 +42,9 @@ public class MedicalCategoryDTO {
// 단가
private Double kindCost;
// 할인가
private Double dcCost;
// 제품설명
private String kindMsg1;

View File

@@ -16,6 +16,7 @@
a.divi_sort,
a.cust_list_pid,
a.kind_cost,
a.dc_cost,
a.kind_msg1,
a.kind_msg2,
a.kind_unit,
@@ -60,6 +61,7 @@
a.divi_sort,
a.cust_list_pid,
a.kind_cost,
a.dc_cost,
a.kind_msg1,
a.kind_msg2,
a.kind_unit,
@@ -102,6 +104,7 @@
divi_sort,
cust_list_pid,
kind_cost,
dc_cost,
kind_msg1,
kind_msg2,
kind_unit,
@@ -130,6 +133,7 @@
IFNULL(#{diviSort}, 0),
IFNULL(#{custListPid}, 0),
IFNULL(#{kindCost}, 0),
IFNULL(#{dcCost}, 0),
IFNULL(#{kindMsg1}, ''),
IFNULL(#{kindMsg2}, ''),
IFNULL(#{kindUnit}, ''),
@@ -184,6 +188,9 @@
<if test='kindCost != null'>
kind_cost = #{kindCost},
</if>
<if test='dcCost != null'>
dc_cost = #{dcCost},
</if>
<if test='kindMsg1 != null'>
kind_msg1 = #{kindMsg1},
</if>

View File

@@ -1,7 +1,7 @@
/**
* 통합 진료유형 관리 (medicalCategoryList.js)
* - medical_divi_list 테이블 기반
* - Depth 1(진료과목 select) → Depth 2/3/4 (Tabulator 그리드)
* - Depth 1(진료과목 select) → Depth 2/3/4/5 (Tabulator 그리드)
*/
$(document).ready(function () {
let globalTreeData = [];
@@ -9,6 +9,7 @@ $(document).ready(function () {
let table2 = null;
let table3 = null;
let table4 = null;
let table5 = null;
let tableOverview = null;
let overviewInitialized = false;
@@ -139,29 +140,45 @@ $(document).ready(function () {
{ title: "명칭", field: "divi_name", formatter: categoryNameFormatter, tooltip: true },
{ title: "순서", field: "divi_sort", width: 38, hozAlign: "center", cssClass: "col-sm" },
{ title: "하위", width: 50, hozAlign: "center", headerSort: false, formatter: function (c) { return addDescendantFormatter(c, 2); }, cellClick: function (e, cell) { e.stopPropagation(); var d = cell.getRow().getData(); addChildCategory(d.pid, 3, d.divi_name); } }
]
],
placeholder: "진료유형을 선택하세요."
}));
// Depth 3 Grid - 순번, 명칭, 거래처, 담당자(연락처), 단가, 순서, 하위
// Depth 3 Grid (제품) - 순번, 명칭, 거래처, 담당자(연락처), 단가, 순서, 하위
table3 = new Tabulator("#gridDepth3", Object.assign({}, commonOpts, {
columns: [
{ title: "순번", formatter: "rownum", width: 38, hozAlign: "center", headerSort: false, cssClass: "col-sm" },
{ title: "명칭", field: "divi_name", formatter: categoryNameFormatter, tooltip: true },
{ title: "거래처", field: "cust_name", width: 90, hozAlign: "center", tooltip: true },
{ title: "담당자(연락처)", field: "cust_contact", width: 110, hozAlign: "center", tooltip: true },
{ title: "단가", field: "kind_cost", width: 80, hozAlign: "right", formatter: costFormatter },
// { title: "거래처", field: "cust_name", width: 90, hozAlign: "center", tooltip: true },
// { title: "담당자(연락처)", field: "cust_contact", width: 110, hozAlign: "center", tooltip: true },
// { title: "단가", field: "kind_cost", width: 80, hozAlign: "right", formatter: costFormatter },
{ title: "순서", field: "divi_sort", width: 38, hozAlign: "center", cssClass: "col-sm" },
{ title: "하위", width: 50, hozAlign: "center", headerSort: false, formatter: function (c) { return addDescendantFormatter(c, 3); }, cellClick: function (e, cell) { e.stopPropagation(); var d = cell.getRow().getData(); addChildCategory(d.pid, 4, d.divi_name); } }
]
],
placeholder: "진료유형을 선택하세요."
}));
// Depth 4 Grid - 순번, 명칭, 순서 (하위 없음)
// Depth 4 Grid (용량/출력) - 순번, 명칭, 단가, 할인가, 순서, 하위
table4 = new Tabulator("#gridDepth4", Object.assign({}, commonOpts, {
columns: [
{ title: "순번", formatter: "rownum", width: 38, hozAlign: "center", headerSort: false, cssClass: "col-sm" },
{ title: "명칭", field: "divi_name", formatter: categoryNameFormatter, tooltip: true },
{ title: "단가", field: "kind_cost", width: 80, hozAlign: "right", formatter: costFormatter },
{ title: "할인가", field: "dc_cost", width: 80, hozAlign: "right", formatter: costFormatter },
{ title: "순서", field: "divi_sort", width: 38, hozAlign: "center", cssClass: "col-sm" },
{ title: "하위", width: 50, hozAlign: "center", headerSort: false, formatter: function (c) { return addDescendantFormatter(c, 4); }, cellClick: function (e, cell) { e.stopPropagation(); var d = cell.getRow().getData(); addChildCategory(d.pid, 5, d.divi_name); } }
],
placeholder: "제품/시술을 선택하세요."
}));
// Depth 5 Grid (부위) - 순번, 명칭, 순서 (최하위, 하위 없음)
table5 = new Tabulator("#gridDepth5", Object.assign({}, commonOpts, {
columns: [
{ title: "순번", formatter: "rownum", width: 38, hozAlign: "center", headerSort: false, cssClass: "col-sm" },
{ title: "명칭", field: "divi_name", formatter: categoryNameFormatter, tooltip: true },
{ title: "순서", field: "divi_sort", width: 38, hozAlign: "center", cssClass: "col-sm" }
]
],
placeholder: "용량을 선택하세요."
}));
// Shift+Click 범위 선택을 위한 마지막 클릭 행 추적
@@ -200,6 +217,7 @@ $(document).ready(function () {
table2.on("rowClick", function (e, row) { handleRowClick(e, row, table2, 2); });
table3.on("rowClick", function (e, row) { handleRowClick(e, row, table3, 3); });
table4.on("rowClick", function (e, row) { handleRowClick(e, row, table4, 4); });
table5.on("rowClick", function (e, row) { handleRowClick(e, row, table5, 5); });
function onCellDblClick(e, cell) {
@@ -210,10 +228,12 @@ $(document).ready(function () {
table2.on("cellDblClick", onCellDblClick);
table3.on("cellDblClick", onCellDblClick);
table4.on("cellDblClick", onCellDblClick);
table5.on("cellDblClick", onCellDblClick);
table2.on("rowContext", onRowContextMenu);
table3.on("rowContext", onRowContextMenu);
table4.on("rowContext", onRowContextMenu);
table5.on("rowContext", onRowContextMenu);
window.loadData();
}
@@ -277,15 +297,30 @@ $(document).ready(function () {
}
});
table4.setData([]);
table5.setData([]);
$("#btnArea3").html('<button class="put_btn" onclick="addChildCategory(\'' + data.pid + '\', \'3\', \'' + (data.divi_name || '').replace(/'/g, "\\'") + '\')"><img src="/image/web/notice_btn_icon.svg" alt="추가" style="width:12px; height:12px; margin:0; position:static !important;">추가</button>');
$("#btnArea4").empty();
$("#btnArea5").empty();
} else if (depth === 3) {
table4.setData(children).then(function () {
if (currentState && currentState.depth4) {
table4.selectRow(currentState.depth4);
let selectedRows = table4.getSelectedRows();
if (selectedRows && selectedRows.length > 0) {
clickRow(selectedRows[0], 4, currentState);
}
}
});
table5.setData([]);
$("#btnArea4").html('<button class="put_btn" onclick="addChildCategory(\'' + data.pid + '\', \'4\', \'' + (data.divi_name || '').replace(/'/g, "\\'") + '\')"><img src="/image/web/notice_btn_icon.svg" alt="추가" style="width:12px; height:12px; margin:0; position:static !important;">추가</button>');
$("#btnArea5").empty();
} else if (depth === 4) {
table5.setData(children).then(function () {
if (currentState && currentState.depth5) {
table5.selectRow(currentState.depth5);
}
});
$("#btnArea5").html('<button class="put_btn" onclick="addChildCategory(\'' + data.pid + '\', \'5\', \'' + (data.divi_name || '').replace(/'/g, "\\'") + '\')"><img src="/image/web/notice_btn_icon.svg" alt="추가" style="width:12px; height:12px; margin:0; position:static !important;">추가</button>');
}
}
@@ -312,10 +347,12 @@ $(document).ready(function () {
let selected2 = table2.getSelectedData()[0];
let selected3 = table3.getSelectedData()[0];
let selected4 = table4.getSelectedData()[0];
let selected5 = table5.getSelectedData()[0];
if (selected2) currentState.depth2 = selected2.pid;
if (selected3) currentState.depth3 = selected3.pid;
if (selected4) currentState.depth4 = selected4.pid;
if (selected5) currentState.depth5 = selected5.pid;
}
$.ajax({
@@ -370,9 +407,11 @@ $(document).ready(function () {
table2.setData([]);
table3.setData([]);
table4.setData([]);
table5.setData([]);
$("#btnArea2").empty();
$("#btnArea3").empty();
$("#btnArea4").empty();
$("#btnArea5").empty();
if (tableOverview) tableOverview.setData([]);
return;
@@ -460,9 +499,11 @@ $(document).ready(function () {
table2.setData([]);
table3.setData([]);
table4.setData([]);
table5.setData([]);
$("#btnArea2").empty();
$("#btnArea3").empty();
$("#btnArea4").empty();
$("#btnArea5").empty();
return;
}
@@ -471,8 +512,10 @@ $(document).ready(function () {
table3.setData([]);
table4.setData([]);
table5.setData([]);
$("#btnArea3").empty();
$("#btnArea4").empty();
$("#btnArea5").empty();
if (node && node._children) {
table2.setData(node._children).then(function () {

View File

@@ -14,8 +14,8 @@ $(document).ready(function () {
bindEvents();
// 뎁스3이면 거래처 목록을 로드한 뒤 폼 초기화를 진행
if (diviDept === '3' || mode === 'edit') {
// 뎁스3 또는 4이면 거래처 목록을 로드한 뒤 폼 초기화를 진행
if (diviDept === '3' || diviDept === '4' || mode === 'edit') {
loadCustList().then(function () {
initForm();
applyDepthUI();
@@ -35,6 +35,7 @@ $(document).ready(function () {
$("#trNoTax1").hide();
}
// Depth 3: 제품/시술 정보 (거래처, 제품설명, 기타설명)
if (currentDept == '3') {
$("#productInfoTitle").show();
$("#productInfoTable").show();
@@ -42,6 +43,15 @@ $(document).ready(function () {
$("#productInfoTitle").hide();
$("#productInfoTable").hide();
}
// Depth 4: 용량/출력 정보 (단가, 할인가, 단위, 비율)
if (currentDept == '4') {
$("#volumeInfoTitle").show();
$("#volumeInfoTable").show();
} else {
$("#volumeInfoTitle").hide();
$("#volumeInfoTable").hide();
}
}
// 거래처 셀렉트 박스 세팅
@@ -68,9 +78,22 @@ $(document).ready(function () {
});
}
// Depth별 타이틀 매핑
var depthTitleMap = {
'1': '진료과목',
'2': '진료유형',
'3': '제품/시술',
'4': '용량/출력',
'5': '부위'
};
function getDepthTitle(dept) {
return depthTitleMap[dept] || '진료유형';
}
function initForm() {
if (mode === 'add') {
$("#popTitle").text((diviDept == '1' ? '최상위 ' : '') + '진료유형 신규 등록');
$("#popTitle").text(getDepthTitle(diviDept) + ' 신규 등록');
$("#pid").val('');
$("#diviDept").val(diviDept);
$("#diviParent").val(diviParent);
@@ -81,7 +104,7 @@ $(document).ready(function () {
$("#parentNameTxt").text(parentName);
}
} else if (mode === 'edit') {
$("#popTitle").text('진료유형 정보 수정');
$("#popTitle").text(getDepthTitle(diviDept) + ' 정보 수정');
$("#pid").val(pid);
$("#btn_delete").show();
loadDetail(pid);
@@ -107,6 +130,7 @@ $(document).ready(function () {
$("#custListPid").val(data.cust_list_pid);
}
$("#kindCost").val(data.kind_cost || 0);
$("#dcCost").val(data.dc_cost || 0);
$("#kindUnit").val(data.kind_unit || '');
$("#kindUnitVol").val(data.kind_unit_vol || 0);
$("#kindUnit2").val(data.kind_unit2 || '');
@@ -207,6 +231,7 @@ $(document).ready(function () {
// 단가/제품 정보
custListPid: parseInt($("#custListPid").val() || "0", 10),
kindCost: parseFloat($("#kindCost").val() || "0"),
dcCost: parseFloat($("#dcCost").val() || "0"),
kindUnit: $("#kindUnit").val(),
kindUnitVol: parseFloat($("#kindUnitVol").val() || "0"),
kindUnit2: $("#kindUnit2").val(),

View File

@@ -84,10 +84,10 @@
</div>
</div>
<!-- 2depth | 3depth | 4depth 가로 배치 -->
<!-- 2depth | 3depth | 4depth | 5depth 가로 배치 -->
<div class="category-tree-layout">
<!-- Depth 2 -->
<div class="category-tree-panel" style="flex:25; width:auto; min-width:0;">
<!-- Depth 2: 진료유형 -->
<div class="category-tree-panel" style="flex:20; width:auto; min-width:0;">
<div class="tree-panel-header">
<span class="tree-panel-title">진료유형</span>
<div class="tree-panel-actions" id="btnArea2"></div>
@@ -95,8 +95,8 @@
<div id="gridDepth2" class="category-tree-container"></div>
</div>
<!-- Depth 3 -->
<div class="category-tree-panel" style="flex:55; width:auto; min-width:0;">
<!-- Depth 3: 제품 -->
<div class="category-tree-panel" style="flex:20; width:auto; min-width:0;">
<div class="tree-panel-header">
<span class="tree-panel-title">제품/시술</span>
<div class="tree-panel-actions" id="btnArea3"></div>
@@ -104,14 +104,23 @@
<div id="gridDepth3" class="category-tree-container"></div>
</div>
<!-- Depth 4 -->
<div class="category-tree-panel" style="flex:20; width:auto; min-width:0;">
<!-- Depth 4: 용량 -->
<div class="category-tree-panel" style="flex:35; width:auto; min-width:0;">
<div class="tree-panel-header">
<span class="tree-panel-title">부위</span>
<span class="tree-panel-title">용량/출력</span>
<div class="tree-panel-actions" id="btnArea4"></div>
</div>
<div id="gridDepth4" class="category-tree-container"></div>
</div>
<!-- Depth 5: 부위 -->
<div class="category-tree-panel" style="flex:25; width:auto; min-width:0;">
<div class="tree-panel-header">
<span class="tree-panel-title">부위</span>
<div class="tree-panel-actions" id="btnArea5"></div>
</div>
<div id="gridDepth5" class="category-tree-container"></div>
</div>
</div>
</div>

View File

@@ -224,8 +224,8 @@
</tbody>
</table>
<!-- 단가/제품 정보 -->
<div class="section-title" id="productInfoTitle">단가/제품 정보</div>
<!-- 제품/시술 정보 (Depth 3 전용) -->
<div class="section-title" id="productInfoTitle">제품/시술 정보</div>
<table class="board_write" id="productInfoTable">
<colgroup>
<col width="120px">
@@ -241,10 +241,33 @@
</select>
</td>
</tr>
<tr>
<th>제품설명</th>
<td><input type="text" id="kindMsg1" class="w100p" placeholder="제품설명을 입력하세요"></td>
</tr>
<tr>
<th>기타설명</th>
<td><input type="text" id="kindMsg2" class="w100p" placeholder="기타설명을 입력하세요"></td>
</tr>
</tbody>
</table>
<!-- 용량/출력 정보 (Depth 4 전용) -->
<div class="section-title" id="volumeInfoTitle">용량/출력 정보</div>
<table class="board_write" id="volumeInfoTable">
<colgroup>
<col width="120px">
<col width="*">
</colgroup>
<tbody>
<tr>
<th>단가</th>
<td><input type="number" id="kindCost" class="w120" value="0"></td>
</tr>
<tr>
<th>할인가</th>
<td><input type="number" id="dcCost" class="w120" value="0"></td>
</tr>
<tr>
<th>단위</th>
<td>
@@ -254,14 +277,6 @@
<input type="text" id="kindUnit2" style="width:60px;" placeholder="단위">
</td>
</tr>
<tr>
<th>제품설명</th>
<td><input type="text" id="kindMsg1" class="w100p" placeholder="제품설명을 입력하세요"></td>
</tr>
<tr>
<th>기타설명</th>
<td><input type="text" id="kindMsg2" class="w100p" placeholder="기타설명을 입력하세요"></td>
</tr>
<tr>
<th>비율</th>
<td><input type="text" id="ccRate" class="w120" placeholder="비율"></td>