From ace0ce629665e22708b2f3dafc02080eaf4abb05 Mon Sep 17 00:00:00 2001 From: taekyoungc Date: Mon, 6 Jul 2026 18:25:29 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A9=94=EB=89=B4=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=ED=95=98=EC=9C=84=EB=A9=94=EB=89=B4=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EC=83=81=EC=9C=84=EB=A1=9C=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20+=20=EA=B0=80=EC=9E=A5=EC=9E=90=EB=A6=AC?= =?UTF-8?q?=20=EC=9E=90=EB=8F=99=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 하위 메뉴를 다른 상위 메뉴 아래로 드래그해 재부모(상위 변경) 지원 - 순서+상위+깊이를 함께 저장하는 MenuModel::setStructure() 추가(자식수 재계산) - 드래그 중 화면 상/하단 근처에서 자동 스크롤 Co-Authored-By: Claude Opus 4.8 --- app/Controllers/Admin/Menu.php | 25 +++++++- app/Models/MenuModel.php | 54 ++++++++++++++++++ app/Views/admin/menu/index.php | 101 ++++++++++++++++++++++++++++----- 3 files changed, 164 insertions(+), 16 deletions(-) diff --git a/app/Controllers/Admin/Menu.php b/app/Controllers/Admin/Menu.php index 0307f64..fc5f125 100644 --- a/app/Controllers/Admin/Menu.php +++ b/app/Controllers/Admin/Menu.php @@ -256,8 +256,31 @@ class Menu extends BaseController return redirect()->to(base_url('admin/select-local-government')) ->with('error', '지자체를 선택하세요.'); } - $ids = $this->request->getPost('mm_idx'); $postMtIdx = (int) $this->request->getPost('mt_idx'); + + // 순서 + 상위(부모) 변경 구조가 함께 전달되면 우선 처리 (하위 메뉴의 상위 이동 지원) + $treeJson = (string) $this->request->getPost('menu_tree'); + $structure = $treeJson !== '' ? json_decode($treeJson, true) : null; + + if (is_array($structure) && $structure !== []) { + $orderedIds = array_values(array_filter(array_map( + static fn ($it): int => (int) ($it['idx'] ?? 0), + $structure + ), static fn (int $v): bool => $v > 0)); + if (empty($orderedIds)) { + return $this->menusRedirect($postMtIdx)->with('error', '순서를 적용할 메뉴가 없습니다.'); + } + $firstRow = $this->menuModel->find($orderedIds[0]); + $this->menuModel->setStructure($structure, $lgIdx); + if ($firstRow && (int) $firstRow->lg_idx === $lgIdx) { + $this->menuModel->pruneInventoryManagementMenus((int) $firstRow->mt_idx, $lgIdx); + $this->menuModel->syncTypeToAllLgs((int) $firstRow->mt_idx, $lgIdx); + } + $mtIdx = $firstRow ? (int) $firstRow->mt_idx : $postMtIdx; + return $this->menusRedirect($mtIdx)->with('success', '순서가 적용되었습니다.'); + } + + $ids = $this->request->getPost('mm_idx'); if (! is_array($ids) || empty($ids)) { return $this->menusRedirect($postMtIdx)->with('error', '순서를 적용할 메뉴가 없습니다.'); } diff --git a/app/Models/MenuModel.php b/app/Models/MenuModel.php index 0631e53..00213ca 100644 --- a/app/Models/MenuModel.php +++ b/app/Models/MenuModel.php @@ -82,6 +82,60 @@ class MenuModel extends Model } } + /** + * 순서 + 상위(부모)·깊이 변경을 함께 반영한다. + * 하위 메뉴를 다른 상위 메뉴로 옮기는 드래그를 지원하기 위한 용도. + * + * @param array $items 화면 표시 순서대로 정렬된 구조 배열 + */ + public function setStructure(array $items, int $lgIdx): void + { + $affectedTypes = []; + $i = 0; + foreach ($items as $it) { + $mmIdx = (int) ($it['idx'] ?? 0); + if ($mmIdx <= 0) { + continue; + } + $row = $this->find($mmIdx); + if (! $row || (int) $row->lg_idx !== $lgIdx) { + continue; + } + $this->update($mmIdx, [ + 'mm_num' => $i, + 'mm_pidx' => max(0, (int) ($it['pidx'] ?? 0)), + 'mm_dep' => max(0, (int) ($it['dep'] ?? 0)), + ]); + $affectedTypes[(int) $row->mt_idx] = true; + $i++; + } + // 상위가 바뀌었을 수 있으므로 종류별로 mm_cnode(자식 수)를 재계산 + foreach (array_keys($affectedTypes) as $mtIdx) { + $this->recountChildNodes((int) $mtIdx, $lgIdx); + } + } + + /** + * 특정 메뉴 종류·지자체의 각 메뉴에 대해 mm_cnode(직속 자식 수)를 실제 값으로 재계산한다. + */ + private function recountChildNodes(int $mtIdx, int $lgIdx): void + { + $rows = $this->where('mt_idx', $mtIdx)->where('lg_idx', $lgIdx)->findAll(); + $childCount = []; + foreach ($rows as $r) { + $pid = (int) $r->mm_pidx; + if ($pid > 0) { + $childCount[$pid] = ($childCount[$pid] ?? 0) + 1; + } + } + foreach ($rows as $r) { + $want = (int) ($childCount[(int) $r->mm_idx] ?? 0); + if ((int) $r->mm_cnode !== $want) { + $this->update((int) $r->mm_idx, ['mm_cnode' => $want]); + } + } + } + /** * 추가 시 같은 레벨에서 mm_num 결정 (동일 지자체·메뉴종류·부모·깊이 기준) */ diff --git a/app/Views/admin/menu/index.php b/app/Views/admin/menu/index.php index 6d12812..010e8e1 100644 --- a/app/Views/admin/menu/index.php +++ b/app/Views/admin/menu/index.php @@ -72,6 +72,7 @@ $adminMenuListResolveHref = static function (string $rawLink) use ($menuListReso