first commit 2
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
define('G5_IS_ADMIN', true);
|
||||
require_once '../../common.php';
|
||||
require_once G5_ADMIN_PATH . '/admin.lib.php';
|
||||
|
||||
// 💡 [추가] 코드 관리자 모듈 테이블 정의
|
||||
$g5['ui_manager_table'] = G5_TABLE_PREFIX.'ui_manager';
|
||||
$g5['form_category_table'] = G5_TABLE_PREFIX.'form_category';
|
||||
$g5['common_lang_table'] = G5_TABLE_PREFIX.'common_lang';
|
||||
$g5['form_option_history_table'] = G5_TABLE_PREFIX.'form_option_history';
|
||||
|
||||
if (isset($token)) {
|
||||
$token = @htmlspecialchars(strip_tags($token), ENT_QUOTES);
|
||||
}
|
||||
|
||||
run_event('admin_common');
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
// 💡 [수정] 700번대 최상위 메뉴 배열에 아이콘 클래스('fa-puzzle-piece')를 추가합니다.
|
||||
$menu['menu700'][] = array('700000', 'UI/폼 관리', G5_ADMIN_URL.'/code_manager/ui_manager_list.php', 'code_manager', 'fa-puzzle-piece');
|
||||
|
||||
// 'UI/폼 관리'의 하위 메뉴들을 정의합니다.
|
||||
$menu['menu700'][] = array('700100', 'UI 리소스 관리', G5_ADMIN_URL.'/code_manager/ui_manager_list.php', 'ui_resource_manager');
|
||||
$menu['menu700'][] = array('700900', '솔루션 설치', G5_ADMIN_URL.'/code_manager/install.php', 'ui_solution_install');
|
||||
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
$sub_menu = '700100';
|
||||
include_once('./_common.php');
|
||||
|
||||
// 💡 [추가] w 값을 먼저 정의합니다.
|
||||
$w = isset($_REQUEST['w']) ? substr(trim($_REQUEST['w']), 0, 1) : '';
|
||||
|
||||
// ==================================================================
|
||||
// 💡 [핵심 수정] 폼 제출 처리 로직 (신규/수정)
|
||||
// ==================================================================
|
||||
// POST 요청이고, w값이 넘어왔을 때 (신규='', 수정='u') 처리
|
||||
if (isset($_POST['w']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
check_admin_token();
|
||||
|
||||
$w_from_post = $_POST['w']; // POST로 받은 w값을 기준으로 처리
|
||||
$um_id = (int)$_POST['um_id'];
|
||||
$parent_id = (int)$_POST['parent_id'];
|
||||
$fc_key = trim($_POST['fc_key']);
|
||||
$cl_name = trim($_POST['cl_name']);
|
||||
$fc_order = (int)$_POST['fc_order'];
|
||||
$is_used = (int)$_POST['is_used'];
|
||||
|
||||
if (!$um_id) {
|
||||
alert('잘못된 접근입니다.');
|
||||
}
|
||||
if (!$fc_key) {
|
||||
alert('옵션 키(Key)를 입력해주세요.');
|
||||
}
|
||||
if (!$cl_name) {
|
||||
alert('옵션 이름을 입력해주세요.');
|
||||
}
|
||||
|
||||
// 1. g5_form_category 테이블에 마스터 정보 저장
|
||||
$sql_common = "
|
||||
um_id = '{$um_id}',
|
||||
parent_id = '{$parent_id}',
|
||||
fc_key = '{$fc_key}',
|
||||
fc_order = '{$fc_order}',
|
||||
is_used = '{$is_used}',
|
||||
updated_at = '" . G5_TIME_YMDHIS . "',
|
||||
updated_by = '{$member['mb_id']}'
|
||||
";
|
||||
|
||||
if ($w_from_post == 'u') { // 수정
|
||||
$fc_id = (int)$_POST['fc_id'];
|
||||
if (!$fc_id) alert('fc_id 값이 없습니다.');
|
||||
|
||||
$sql = "UPDATE {$g5['form_category_table']} SET {$sql_common} WHERE fc_id = '{$fc_id}'";
|
||||
sql_query($sql);
|
||||
} else { // 신규
|
||||
$sql_common .= ", created_at = '" . G5_TIME_YMDHIS . "', created_by = '{$member['mb_id']}'";
|
||||
$sql = "INSERT INTO {$g5['form_category_table']} SET {$sql_common}";
|
||||
sql_query($sql);
|
||||
$fc_id = sql_insert_id();
|
||||
}
|
||||
|
||||
// 2. g5_common_lang 테이블에 다국어 이름 저장 (없으면 생성, 있으면 수정)
|
||||
$sql = "SELECT cl_id FROM {$g5['common_lang_table']} WHERE target_table = '{$g5['form_category_table']}' AND target_id = '{$fc_id}' AND lang_code = 'ko'";
|
||||
$lang_row = sql_fetch($sql);
|
||||
|
||||
if (isset($lang_row['cl_id'])) {
|
||||
$sql = "UPDATE {$g5['common_lang_table']} SET cl_name = '{$cl_name}', updated_at = '" . G5_TIME_YMDHIS . "', updated_by = '{$member['mb_id']}' WHERE cl_id = '{$lang_row['cl_id']}'";
|
||||
} else {
|
||||
$sql = "INSERT INTO {$g5['common_lang_table']} SET target_table = '{$g5['form_category_table']}', target_id = '{$fc_id}', lang_code = 'ko', cl_name = '{$cl_name}', updated_at = '" . G5_TIME_YMDHIS . "', updated_by = '{$member['mb_id']}'";
|
||||
}
|
||||
sql_query($sql);
|
||||
|
||||
goto_url("./category_list.php?um_id=$um_id");
|
||||
}
|
||||
// ==================================================================
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
// 그룹 ID가 없으면 되돌려 보냄
|
||||
$um_id = isset($_GET['um_id']) ? (int)$_GET['um_id'] : 0;
|
||||
if (!$um_id) {
|
||||
alert('UI 리소스 ID가 올바르지 않습니다.', './ui_manager_list.php');
|
||||
}
|
||||
|
||||
// 현재 관리하려는 리소스의 정보를 가져옴
|
||||
$sql = "SELECT * FROM {$g5['ui_manager_table']} WHERE um_id = '{$um_id}'";
|
||||
$ui_resource = sql_fetch($sql);
|
||||
|
||||
if (!isset($ui_resource['um_id']) || $ui_resource['resource_type'] != 'DATA') {
|
||||
alert('존재하지 않거나 데이터 타입이 아닌 리소스입니다.', './ui_manager_list.php');
|
||||
}
|
||||
|
||||
// 계층형으로 정렬된 카테고리 목록을 가져오는 함수
|
||||
function get_category_view_list($um_id)
|
||||
{
|
||||
global $g5;
|
||||
$sql = "SELECT
|
||||
A.*,
|
||||
B.cl_name
|
||||
FROM
|
||||
{$g5['form_category_table']} AS A
|
||||
LEFT JOIN
|
||||
{$g5['common_lang_table']} AS B
|
||||
ON
|
||||
(A.fc_id = B.target_id AND B.target_table = '{$g5['form_category_table']}' AND B.lang_code = 'ko')
|
||||
WHERE
|
||||
A.um_id = '{$um_id}' AND A.is_deleted = 0
|
||||
ORDER BY
|
||||
A.parent_id, A.fc_order, A.fc_id";
|
||||
$result = sql_query($sql);
|
||||
$categories = [];
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$categories[] = $row;
|
||||
}
|
||||
|
||||
$view_list = [];
|
||||
// 재귀 함수를 사용하여 계층 구조를 평탄화하고 depth를 추가
|
||||
generate_category_list($categories, 0, 0, $view_list);
|
||||
return $view_list;
|
||||
}
|
||||
|
||||
function generate_category_list(&$source, $parent_id, $depth, &$result_list)
|
||||
{
|
||||
foreach ($source as $item) {
|
||||
if ($item['parent_id'] == $parent_id) {
|
||||
$item['depth'] = $depth;
|
||||
$result_list[] = $item;
|
||||
generate_category_list($source, $item['fc_id'], $depth + 1, $result_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$category_list = get_category_view_list($um_id);
|
||||
$category_list_count = count($category_list);
|
||||
|
||||
$g5['title'] = get_text($ui_resource['resource_desc']) . ' : 옵션/카테고리 관리';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
add_stylesheet('<link rel="stylesheet" href="' . G5_ADMIN_URL . '/code_manager/css/code_manager.css?ver=1.1">', 0);
|
||||
?>
|
||||
|
||||
<div class="local_desc01 local_desc">
|
||||
<p>
|
||||
<strong>'<?php echo get_text($ui_resource['resource_desc']); ?>'</strong> 리소스에 포함될 옵션 또는 카테고리를 관리합니다.<br>
|
||||
'부모 카테고리'를 지정하여 대/중/소 분류와 같은 계층 구조를 만들 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section id="code_manager">
|
||||
<div class="code-manager-header">
|
||||
<h2 class="code-manager-title">
|
||||
<a href="./ui_manager_list.php" class="btn btn_02">리소스 목록으로</a>
|
||||
<?php echo get_text($ui_resource['resource_desc']); ?>
|
||||
(<code><?php echo get_text($ui_resource['resource_code']); ?></code>)
|
||||
</h2>
|
||||
<div class="code-manager-actions">
|
||||
<button type="button" id="add-category-btn" class="btn btn_01">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i> 새 옵션 추가
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 새 옵션(카테고리) 추가 폼 -->
|
||||
<div id="category-form-container" style="display: none; margin-top: 20px;">
|
||||
<form name="fcategoryform" id="fcategoryform" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post">
|
||||
<input type="hidden" name="w" value="">
|
||||
<input type="hidden" name="um_id" value="<?php echo $um_id; ?>">
|
||||
<input type="hidden" name="fc_id" value="">
|
||||
<input type="hidden" name="token" value="<?php echo get_admin_token(); ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption>옵션/카테고리 추가/수정 폼</caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="parent_id">부모 카테고리</label></th>
|
||||
<td>
|
||||
<select name="parent_id" id="parent_id">
|
||||
<option value="0">최상위 카테고리</option>
|
||||
<?php foreach ($category_list as $cat) : ?>
|
||||
<option value="<?php echo $cat['fc_id']; ?>">
|
||||
<?php echo str_repeat(' ', $cat['depth']); ?><?php echo get_text($cat['cl_name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="fc_key">옵션 키(Key)</label></th>
|
||||
<td>
|
||||
<input type="text" name="fc_key" id="fc_key" required class="required frm_input" size="30">
|
||||
<span class="frm_info">DB에 저장될 고유한 값입니다. (영문, 숫자, _ 사용)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="cl_name">옵션 이름</label></th>
|
||||
<td>
|
||||
<input type="text" name="cl_name" id="cl_name" required class="required frm_input" size="50">
|
||||
<span class="frm_info">화면에 표시될 이름입니다.</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="fc_order">정렬순서</label></th>
|
||||
<td>
|
||||
<input type="number" name="fc_order" value="0" id="fc_order" class="frm_input" size="5">
|
||||
<span class="frm_info">숫자가 낮을수록 먼저 표시됩니다.</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">사용 여부</th>
|
||||
<td>
|
||||
<label><input type="radio" name="is_used" value="1" checked> 사용함</label>
|
||||
<label><input type="radio" name="is_used" value="0"> 사용안함</label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="btn_confirm01 btn_confirm">
|
||||
<button type="button" id="cancel-category-btn" class="btn_cancel btn">취소</button>
|
||||
<input type="submit" value="저장" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 등록된 옵션(카테고리) 목록 테이블 -->
|
||||
<div class="tbl_head01 tbl_wrap" style="margin-top: 20px;">
|
||||
<table>
|
||||
<caption>옵션/카테고리 목록</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">카테고리 이름</th>
|
||||
<th scope="col" style="width: 150px;">옵션 키 (Key)</th>
|
||||
<th scope="col" style="width: 100px;">부모 ID</th>
|
||||
<th scope="col" style="width: 60px;">순서</th>
|
||||
<th scope="col" style="width: 60px;">사용</th>
|
||||
<th scope="col" style="width: 180px;">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($category_list_count > 0) : ?>
|
||||
<?php foreach ($category_list as $cat) : ?>
|
||||
<tr>
|
||||
<td class="td_left category-name-depth-<?php echo $cat['depth']; ?>">
|
||||
<?php if ($cat['depth'] > 0) : ?>
|
||||
<span class="depth-prefix">└</span>
|
||||
<?php endif; ?>
|
||||
<?php echo get_text($cat['cl_name']); ?>
|
||||
</td>
|
||||
<td><?php echo get_text($cat['fc_key']); ?></td>
|
||||
<td><?php echo $cat['parent_id']; ?></td>
|
||||
<td><?php echo $cat['fc_order']; ?></td>
|
||||
<td><?php echo $cat['is_used'] ? 'Y' : 'N'; ?></td>
|
||||
<td class="td_mng td_mng_s">
|
||||
<button type="button" class="btn btn_02 btn_edit_category"
|
||||
data-fc_id="<?php echo $cat['fc_id']; ?>"
|
||||
data-parent_id="<?php echo $cat['parent_id']; ?>"
|
||||
data-fc_key="<?php echo get_text($cat['fc_key']); ?>"
|
||||
data-cl_name="<?php echo get_text($cat['cl_name']); ?>"
|
||||
data-fc_order="<?php echo $cat['fc_order']; ?>"
|
||||
data-is_used="<?php echo $cat['is_used']; ?>">수정
|
||||
</button>
|
||||
<a href="./lang_manager.php?target_table=<?php echo $g5['form_category_table']; ?>&target_id=<?php echo $cat['fc_id']; ?>"
|
||||
class="btn btn_01">다국어</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr class="empty_table">
|
||||
<td colspan="6">등록된 옵션이 없습니다.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="<?php echo G5_ADMIN_URL; ?>/code_manager/js/ui_manager.js?ver=1.4"></script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
$sub_menu = '100900'; // admin.menu100.php 에 정의된 메뉴 코드
|
||||
include_once('./_common.php');
|
||||
|
||||
// ==================================================================
|
||||
// 💡 [핵심] 폼 제출 처리 로직
|
||||
// ==================================================================
|
||||
if (isset($w) && $w == 'u' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
check_admin_token();
|
||||
|
||||
// 입력값 정리
|
||||
$screen_code = trim($_POST['screen_code']);
|
||||
$group_code = trim($_POST['group_code']);
|
||||
$resource_code = trim($_POST['resource_code']);
|
||||
$resource_type = trim($_POST['resource_type']);
|
||||
$resource_desc = trim($_POST['resource_desc']);
|
||||
$cl_name = isset($_POST['cl_name']) ? trim($_POST['cl_name']) : ''; // LABEL 타입일 때만 넘어옴
|
||||
|
||||
// 유효성 검사
|
||||
if (!$screen_code || !$group_code || !$resource_code || !$resource_type) {
|
||||
alert('필수 항목을 모두 입력해주세요.');
|
||||
}
|
||||
if ($resource_type == 'LABEL' && !$cl_name) {
|
||||
alert('UI 라벨 타입은 한국어 라벨명을 필수로 입력해야 합니다.');
|
||||
}
|
||||
|
||||
// 중복 검사
|
||||
$sql = "SELECT COUNT(*) as cnt FROM {$g5['ui_manager_table']} WHERE screen_code = '{$screen_code}' AND group_code = '{$group_code}' AND resource_code = '{$resource_code}'";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row['cnt']) {
|
||||
alert('이미 등록된 리소스 코드입니다.');
|
||||
}
|
||||
|
||||
// 1. g5_ui_manager 테이블에 리소스 '설계' 정보 저장
|
||||
$sql = "INSERT INTO {$g5['ui_manager_table']}
|
||||
SET screen_code = '{$screen_code}',
|
||||
group_code = '{$group_code}',
|
||||
resource_code = '{$resource_code}',
|
||||
resource_type = '{$resource_type}',
|
||||
resource_desc = '{$resource_desc}',
|
||||
is_used = '1',
|
||||
created_at = '".G5_TIME_YMDHIS."',
|
||||
created_by = '{$member['mb_id']}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
sql_query($sql);
|
||||
$um_id = sql_insert_id();
|
||||
|
||||
// 2. 리소스 타입이 'LABEL'인 경우, g5_common_lang 테이블에 실제 텍스트 저장
|
||||
if ($resource_type == 'LABEL' && $cl_name) {
|
||||
$sql = "INSERT INTO {$g5['common_lang_table']}
|
||||
SET target_table = '{$g5['ui_manager_table']}',
|
||||
target_id = '{$um_id}',
|
||||
lang_code = 'ko',
|
||||
cl_name = '{$cl_name}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
sql_query($sql);
|
||||
}
|
||||
|
||||
goto_url('./code_list.php');
|
||||
}
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
// 등록된 리소스 목록 조회
|
||||
$sql = "SELECT * FROM {$g5['ui_manager_table']} ORDER BY screen_code, group_code, resource_code";
|
||||
$result = sql_query($sql);
|
||||
$resource_list = [];
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$resource_list[] = $row;
|
||||
}
|
||||
$resource_list_count = count($resource_list);
|
||||
|
||||
$g5['title'] = 'UI 리소스 관리';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
// 솔루션 전용 CSS/JS 파일을 불러옵니다.
|
||||
add_stylesheet('<link rel="stylesheet" href="' . G5_ADMIN_URL . '/code_manager/css/code_manager.css">', 0);
|
||||
?>
|
||||
|
||||
<div class="local_desc01 local_desc">
|
||||
<p>
|
||||
웹사이트의 모든 화면에 사용되는 텍스트(라벨)와 선택 옵션(데이터)을 체계적으로 관리합니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section id="code_manager">
|
||||
<div class="code-manager-header">
|
||||
<h2 class="code-manager-title">UI 리소스 목록</h2>
|
||||
<div class="code-manager-actions">
|
||||
<button type="button" id="add-resource-btn" class="btn btn_01">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i> 새 리소스 추가
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 새 리소스 추가 폼 -->
|
||||
<div id="resource-form-container" style="display: none;">
|
||||
<form name="fresourceform" id="fresourceform" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post">
|
||||
<input type="hidden" name="w" value="u">
|
||||
<input type="hidden" name="token" value="<?php echo get_admin_token(); ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption>UI 리소스 추가 폼</caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="screen_code">화면 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="screen_code" id="screen_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">리소스가 사용될 화면의 고유 코드 (예: order_form, member_join)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="group_code">그룹 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="group_code" id="group_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">화면 내에서 리소스를 묶어줄 그룹 코드 (예: address_info, common_options)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">리소스 타입</th>
|
||||
<td>
|
||||
<label><input type="radio" name="resource_type" value="LABEL" checked> UI 라벨 (단일 텍스트)</label>
|
||||
<label><input type="radio" name="resource_type" value="DATA"> 데이터 (선택 옵션)</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="resource-type-field" id="label-field">
|
||||
<th scope="row"><label for="cl_name">한국어 라벨명</label></th>
|
||||
<td>
|
||||
<input type="text" name="cl_name" id="cl_name" class="frm_input" size="50">
|
||||
<span class="frm_info">화면에 표시될 실제 텍스트 (예: 집의 유형, 창호 재질)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_code">리소스 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_code" id="resource_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">개발자가 이 리소스를 호출할 때 사용할 고유 코드 (예: house_type_label, house_type_data)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_desc">설명</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_desc" id="resource_desc" class="frm_input" size="80">
|
||||
<span class="frm_info">이 리소스의 용도에 대한 설명 (관리자 참고용)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="btn_confirm01 btn_confirm">
|
||||
<button type="button" id="cancel-resource-btn" class="btn_cancel btn">취소</button>
|
||||
<input type="submit" value="리소스 등록" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 등록된 리소스 목록 테이블 -->
|
||||
<div class="tbl_head01 tbl_wrap">
|
||||
<table>
|
||||
<caption>UI 리소스 목록</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">화면 코드</th>
|
||||
<th scope="col">그룹 코드</th>
|
||||
<th scope="col">리소스 코드</th>
|
||||
<th scope="col">타입</th>
|
||||
<th scope="col">설명</th>
|
||||
<th scope="col">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($resource_list_count > 0) : ?>
|
||||
<?php foreach ($resource_list as $res) : ?>
|
||||
<tr>
|
||||
<td><?php echo get_text($res['screen_code']); ?></td>
|
||||
<td><?php echo get_text($res['group_code']); ?></td>
|
||||
<td><?php echo get_text($res['resource_code']); ?></td>
|
||||
<td><?php echo $res['resource_type']; ?></td>
|
||||
<td class="td_left"><?php echo get_text($res['resource_desc']); ?></td>
|
||||
<td class="td_mng">
|
||||
<?php if ($res['resource_type'] == 'DATA') : ?>
|
||||
<a href="./category_list.php?um_id=<?php echo $res['um_id']; ?>" class="btn btn_03">옵션 관리</a>
|
||||
<?php endif; ?>
|
||||
<a href="./category_list.php?w=u&um_id=<?php echo $res['um_id']; ?>" class="btn btn_02">수정</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr class="empty_table">
|
||||
<td colspan="6">등록된 리소스가 없습니다.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="<?php echo G5_ADMIN_URL; ?>/code_manager/js/code_manager.js"></script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
@@ -0,0 +1,196 @@
|
||||
/* 폼 옵션 관리 솔루션 전용 스타일 */
|
||||
#code_manager .code-manager-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
#code_manager .code-manager-title {
|
||||
margin: 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
#code_manager .code-manager-actions .btn {
|
||||
padding: 5px 12px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* 새 리소스 추가 폼 */
|
||||
#resource-form-container {
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
border: 1px solid #e0e0e0;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#resource-form-container .frm_info {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 💡 [추가] 아코디언 UI 스타일 */
|
||||
#resource-list-accordion {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.accordion-item {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.accordion-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.accordion-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
background-color: #f7f7f7;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
.accordion-header:hover {
|
||||
background-color: #efefef;
|
||||
}
|
||||
.accordion-header .screen-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
}
|
||||
.accordion-header .screen-title .fa {
|
||||
margin-right: 8px;
|
||||
color: #555;
|
||||
}
|
||||
.accordion-header .resource-count {
|
||||
font-size: 0.9em;
|
||||
color: #fff;
|
||||
background-color: #888;
|
||||
padding: 3px 8px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.accordion-header .accordion-icon {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.accordion-item.active .accordion-header .accordion-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.accordion-content {
|
||||
display: none;
|
||||
padding: 15px;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
.accordion-content .tbl_wrap {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 💡 [추가] 리소스 타입 시각적 구분 */
|
||||
.res-type-label, .res-type-data {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
font-size: 0.85em;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
.res-type-label {
|
||||
background-color: #3498db; /* 파란색 계열 */
|
||||
}
|
||||
.res-type-data {
|
||||
background-color: #2ecc71; /* 녹색 계열 */
|
||||
}
|
||||
|
||||
/* 기타 스타일 */
|
||||
.tbl_head01 .td_left {
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
/* ... 기존 CSS 코드 ... */
|
||||
|
||||
/* 💡 [추가] 카테고리 목록 들여쓰기 스타일 */
|
||||
.category-name-depth-0 { font-weight: bold; }
|
||||
.category-name-depth-1 { padding-left: 25px !important; }
|
||||
.category-name-depth-2 { padding-left: 50px !important; }
|
||||
.category-name-depth-3 { padding-left: 75px !important; }
|
||||
.category-name-depth-4 { padding-left: 100px !important; }
|
||||
|
||||
.depth-prefix {
|
||||
font-family: "Malgun Gothic", "Apple SD Gothic Neo", sans-serif;
|
||||
font-weight: normal;
|
||||
color: #aaa;
|
||||
margin-right: 5px;
|
||||
}
|
||||
/* ... 기존 CSS 코드 ... */
|
||||
|
||||
/* 💡 [추가] 삭제 버튼 스타일 */
|
||||
.btn_delete {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
height: 28px;
|
||||
line-height: 26px;
|
||||
border: 1px solid #d43f3a;
|
||||
background: #d9534f;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn_delete:hover {
|
||||
background: #c9302c;
|
||||
border-color: #ac2925;
|
||||
}
|
||||
/* ... 기존 CSS 코드 ... */
|
||||
|
||||
/* 💡 [추가] 다국어 관리 페이지 스타일 */
|
||||
.h2_frm {
|
||||
margin: 20px 0 10px;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.td_alignc {
|
||||
text-align: center;
|
||||
}
|
||||
#flangform textarea {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
}
|
||||
/* ... 기존 CSS 코드 ... */
|
||||
|
||||
/* 💡 [추가] 검색 폼 스타일 */
|
||||
#resource_search_form {
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
border: 1px solid #e9e9e9;
|
||||
background: #fcfcfc;
|
||||
}
|
||||
#resource_search_form .h2_frm {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
#resource_search_form .search-form-inner {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
#resource_search_form select,
|
||||
#resource_search_form .frm_input {
|
||||
height: 35px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
#resource_search_form .btn_submit {
|
||||
height: 35px;
|
||||
padding: 0 20px;
|
||||
font-size: 1em;
|
||||
}
|
||||
/* ... 기존 CSS 코드 ... */
|
||||
|
||||
/* 💡 [추가] 페이징 스타일 */
|
||||
.pagination_wrap {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.pagination_wrap .pg_wrap {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
$sub_menu = '700900';
|
||||
include_once('./_common.php');
|
||||
include_once(__DIR__ . '/lib/SchemaManager.class.php');
|
||||
|
||||
if ($is_admin != 'super') {
|
||||
alert('최고관리자만 접근 가능합니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL 파일에서 테이블 이름을 추출하는 함수
|
||||
*/
|
||||
function get_tables_from_sql_file($filepath) {
|
||||
$tables = [];
|
||||
if (!file_exists($filepath)) {
|
||||
return $tables;
|
||||
}
|
||||
|
||||
$lines = file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/CREATE TABLE(?: IF NOT EXISTS)? `([^`]+)`/i', $line, $matches)) {
|
||||
$tables[] = $matches[1];
|
||||
}
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
$g5['title'] = 'UI 리소스 관리 솔루션 설치';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
$install_result = null;
|
||||
$delete_result = null;
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
// 💡 [수정] SQL 파일에서 테이블 목록 동적 로드
|
||||
$tables_to_check = get_tables_from_sql_file(__DIR__ . '/install.sql');
|
||||
|
||||
if ($action === 'install') {
|
||||
check_admin_token();
|
||||
// ... (설치 로직은 기존과 동일)
|
||||
$copy_results = [];
|
||||
$solution_files = [
|
||||
['source' => __DIR__ . '/lib/ui_manager.extend.php', 'target' => G5_EXTEND_PATH . '/ui_manager.extend.php', 'desc' => '핵심 기능 파일'],
|
||||
['source' => __DIR__ . '/admin.menu700.code_manager.php', 'target' => G5_ADMIN_PATH . '/admin.menu700.code_manager.php', 'desc' => '관리자 메뉴 파일']
|
||||
];
|
||||
foreach ($solution_files as $file) {
|
||||
$key = $file['target'];
|
||||
if (file_exists($file['source']) && is_writable(dirname($file['target']))) {
|
||||
@copy($file['source'], $file['target']);
|
||||
}
|
||||
}
|
||||
$sql_file = __DIR__ . '/install.sql';
|
||||
$db_results = [];
|
||||
try {
|
||||
$schemaManager = new SchemaManager($sql_file);
|
||||
$schemaManager->execute();
|
||||
$db_results = $schemaManager->get_results();
|
||||
} catch (Exception $e) { $db_results['errors'][] = $e->getMessage(); }
|
||||
$install_result = ['db' => $db_results];
|
||||
|
||||
} else if ($action === 'delete') {
|
||||
check_admin_token();
|
||||
$delete_result = ['tables' => [], 'menu' => ''];
|
||||
// 💡 [수정] 삭제할 테이블 목록도 동적으로 가져옴
|
||||
$tables_to_delete = get_tables_from_sql_file(__DIR__ . '/install.sql');
|
||||
foreach ($tables_to_delete as $table) {
|
||||
sql_query("DROP TABLE IF EXISTS `{$table}`", false);
|
||||
$delete_result['tables'][] = $table;
|
||||
}
|
||||
// $menu_file = G5_ADMIN_PATH . '/admin.menu700.code_manager.php';
|
||||
$solution_files = [
|
||||
['source' => __DIR__ . '/lib/ui_manager.extend.php', 'target' => G5_EXTEND_PATH . '/ui_manager.extend.php', 'desc' => '핵심 기능 파일'],
|
||||
['source' => __DIR__ . '/admin.menu700.code_manager.php', 'target' => G5_ADMIN_PATH . '/admin.menu700.code_manager.php', 'desc' => '관리자 메뉴 파일']
|
||||
];
|
||||
foreach ($solution_files as $file) {
|
||||
$key = $file['target'];
|
||||
var_dump($key);
|
||||
if (file_exists($key)) {
|
||||
if (@unlink($key)) {
|
||||
$delete_result['menu'] = '메뉴 파일 삭제 성공';
|
||||
} else {
|
||||
$delete_result['menu'] = '메뉴 파일 삭제 실패 (권한 확인 필요)';
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (file_exists($menu_file)) {
|
||||
// if (@unlink($menu_file)) {
|
||||
// $delete_result['menu'] = '메뉴 파일 삭제 성공';
|
||||
// } else {
|
||||
// $delete_result['menu'] = '메뉴 파일 삭제 실패 (권한 확인 필요)';
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
$existing_tables = array();
|
||||
foreach ($tables_to_check as $table) {
|
||||
if (sql_query("SHOW TABLES LIKE '$table'", false) && sql_num_rows(sql_query("SHOW TABLES LIKE '$table'", false)) > 0) {
|
||||
$existing_tables[] = $table;
|
||||
}
|
||||
}
|
||||
$is_installed = count($existing_tables) == count($tables_to_check);
|
||||
?>
|
||||
|
||||
<style>
|
||||
.install-container { max-width: 800px; margin: 20px auto; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
|
||||
.install-header { text-align: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 2px solid #AA20FF; }
|
||||
.install-header h1 { color: #AA20FF; margin-bottom: 10px; }
|
||||
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 30px 0; }
|
||||
.feature-card { padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px; text-align: center; }
|
||||
.feature-card i { font-size: 2em; color: #AA20FF; margin-bottom: 10px; }
|
||||
.status-table { width: 100%; border-collapse: collapse; margin: 20px 0; }
|
||||
.status-table th, .status-table td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
|
||||
.status-table th { background-color: #fff; font-weight: bold; }
|
||||
.status-ok { color: #28a745; font-weight: bold; }
|
||||
.status-missing { color: #dc3545; font-weight: bold; }
|
||||
.install-btn { display: block; width: 200px; margin: 30px auto; padding: 15px 30px; background: #AA20FF; color: white; text-align: center; text-decoration: none; border-radius: 5px; font-size: 16px; font-weight: bold; border: none; cursor: pointer; transition: background-color 0.3s; }
|
||||
.install-btn:hover { background: #8A1ACC; color: white; }
|
||||
.install-btn:disabled { background: #ccc; cursor: not-allowed; }
|
||||
.alert { padding: 15px; margin: 20px 0; border-radius: 5px; }
|
||||
.alert-success { background-color: #d4edda; border: 1px solid #c3e6cb; color: #155724; }
|
||||
.alert-info { background-color: #d1ecf1; border: 1px solid #bee5eb; color: #0c5460; }
|
||||
.alert-danger { background-color: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; }
|
||||
.btn-secondary { background: #6c757d; color: white; border-color: #6c757d; padding: 5px 10px; border-radius: 4px; text-decoration: none; }
|
||||
.btn-secondary:hover { background: #5a6268; }
|
||||
.btn-danger { background: #dc3545; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; }
|
||||
.btn-danger:hover { background: #c82333; }
|
||||
.button-group { display: flex; justify-content: center; align-items: center; gap: 10px; }
|
||||
</style>
|
||||
|
||||
<div class="install-container">
|
||||
<div class="install-header">
|
||||
<h1><i class="fa fa-code"></i> UI 리소스 관리 솔루션</h1>
|
||||
<p>CSS, JS 등 UI 리소스를 효율적으로 관리하는 시스템</p>
|
||||
</div>
|
||||
|
||||
<?php if ($install_result): ?>
|
||||
<div class="alert alert-success"><h4><i class="fa fa-check-circle"></i> 설치 작업 완료</h4><p>데이터베이스 설치 작업이 완료되었습니다.</p><p><a href="./ui_manager_list.php" class="btn btn-primary">UI 리소스 관리로 이동</a></p></div>
|
||||
<?php elseif ($delete_result): ?>
|
||||
<div class="alert alert-danger"><h4><i class="fa fa-trash"></i> 삭제 작업 완료</h4><p>솔루션 관련 데이터와 파일이 삭제되었습니다.</p><ul><?php foreach($delete_result['tables'] as $tbl) echo "<li>{$tbl} 테이블 삭제됨</li>"; ?><li><?php echo $delete_result['menu']; ?></li></ul></div>
|
||||
<?php elseif ($is_installed): ?>
|
||||
<div class="alert alert-success"><h4><i class="fa fa-check-circle"></i> 설치 완료</h4><p>UI 리소스 관리 솔루션이 이미 설치되어 있습니다.</p><p><a href="./ui_manager_list.php" class="btn btn-primary">UI 리소스 관리로 이동</a></p></div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info"><h4><i class="fa fa-info-circle"></i> 설치 필요</h4><p>UI 리소스 관리 솔루션을 사용하기 위해 설치가 필요합니다.</p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3><i class="fa fa-database"></i> 설치 상태</h3>
|
||||
<table class="status-table">
|
||||
<thead><tr><th>테이블명</th><th>설명</th><th>상태</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($tables_to_check as $table): ?>
|
||||
<tr>
|
||||
<td><code><?php echo $table; ?></code></td>
|
||||
<td><?php echo array('g5_ui_manager' => 'UI 리소스 마스터', 'g5_form_category' => '계층형 폼 카테고리', 'g5_common_lang' => '공용 다국어 정보', 'g5_form_option_history' => '폼 옵션 변경 이력')[$table] ?? '데이터 테이블'; ?></td>
|
||||
<td>
|
||||
<?php if (in_array($table, $existing_tables)): ?>
|
||||
<span class="status-ok"><i class="fa fa-check"></i> 설치됨</span>
|
||||
<?php else: ?>
|
||||
<span class="status-missing"><i class="fa fa-times"></i> 미설치</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php if (!$is_installed): ?>
|
||||
<form method="post" onsubmit="return confirm('솔루션을 설치하시겠습니까?');">
|
||||
<input type="hidden" name="action" value="install">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="install-btn"><i class="fa fa-download"></i> 솔루션 설치하기</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($is_installed && !$install_result && !$delete_result): ?>
|
||||
<div class="button-group" style="text-align: center; margin-top: 20px;">
|
||||
<form method="post" onsubmit="return confirm('기존 데이터는 유지되며, 변경된 DB 구조만 업데이트 됩니다. 진행하시겠습니까?');">
|
||||
<input type="hidden" name="action" value="install">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="btn btn-secondary"><i class="fa fa-sync"></i> 재설치 (업데이트)</button>
|
||||
</form>
|
||||
<form method="post" onsubmit="return confirm('정말로 솔루션을 삭제하시겠습니까? 모든 관련 데이터와 파일이 영구적으로 삭제됩니다.');">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="token" value="<?php echo get_token(); ?>">
|
||||
<button type="submit" class="btn-danger"><i class="fa fa-trash"></i> 솔루션 삭제하기</button>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
?>
|
||||
@@ -0,0 +1,64 @@
|
||||
-- 1. [핵심] UI 리소스 마스터 테이블
|
||||
-- 이 테이블은 웹사이트의 모든 UI 요소(라벨, 데이터)의 '설계도' 역할을 합니다.
|
||||
CREATE TABLE IF NOT EXISTS `g5_ui_manager` (
|
||||
`um_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`screen_code` varchar(50) NOT NULL COMMENT '화면 코드 (e.g. order_form)',
|
||||
`group_code` varchar(50) NOT NULL COMMENT '화면 내 그룹 코드 (e.g. address_info)',
|
||||
`resource_code` varchar(50) NOT NULL COMMENT '리소스 코드 (개발자가 사용)',
|
||||
`resource_type` enum('LABEL','DATA') NOT NULL COMMENT '리소스 타입 (라벨, 데이터)',
|
||||
`resource_desc` varchar(255) DEFAULT NULL COMMENT '리소스에 대한 설명 (관리자용)',
|
||||
`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '사용 여부',
|
||||
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성일',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '생성자',
|
||||
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
PRIMARY KEY (`um_id`),
|
||||
UNIQUE KEY `resource_identifier` (`screen_code`,`group_code`,`resource_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='[솔루션] UI 리소스 관리자';
|
||||
|
||||
-- 2. 계층형 카테고리 테이블 ('DATA' 타입 리소스가 사용할 데이터)
|
||||
-- um_id를 통해 어떤 리소스에 속한 데이터인지 명시합니다.
|
||||
CREATE TABLE IF NOT EXISTS `g5_form_category` (
|
||||
`fc_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '카테고리 고유 ID',
|
||||
`um_id` int(11) NOT NULL COMMENT 'UI 리소스 ID (g5_ui_manager.um_id)',
|
||||
`parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '부모 카테고리 ID (0이면 최상위)',
|
||||
`fc_key` varchar(255) NOT NULL COMMENT 'DB에 저장될 값 (고유값)',
|
||||
`fc_order` int(11) NOT NULL DEFAULT '0' COMMENT '정렬 순서',
|
||||
`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '사용 여부',
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '삭제 여부',
|
||||
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성일',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '생성자',
|
||||
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
PRIMARY KEY (`fc_id`),
|
||||
KEY `um_id` (`um_id`),
|
||||
KEY `parent_id` (`parent_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='[솔루션] 계층형 폼 카테고리';
|
||||
|
||||
-- 3. 공용 다국어 정보 테이블
|
||||
-- 'LABEL' 타입의 실제 텍스트와 'DATA' 타입의 카테고리 이름을 모두 저장합니다.
|
||||
CREATE TABLE IF NOT EXISTS `g5_common_lang` (
|
||||
`cl_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`target_table` varchar(50) NOT NULL COMMENT '대상 테이블명',
|
||||
`target_id` int(11) NOT NULL COMMENT '대상 레코드 ID',
|
||||
`lang_code` varchar(10) NOT NULL COMMENT '언어 코드',
|
||||
`cl_name` varchar(255) NOT NULL COMMENT '화면에 표시될 이름/값',
|
||||
`cl_description` text COMMENT '부가 설명 (툴팁 등)',
|
||||
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
PRIMARY KEY (`cl_id`),
|
||||
UNIQUE KEY `target_lang` (`target_table`,`target_id`,`lang_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='[솔루션] 공용 다국어 정보';
|
||||
|
||||
-- 4. 변경 이력 테이블
|
||||
CREATE TABLE IF NOT EXISTS `g5_form_option_history` (
|
||||
`fh_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`table_name` varchar(50) NOT NULL COMMENT '변경된 테이블명',
|
||||
`record_id` int(11) NOT NULL COMMENT '변경된 레코드 ID',
|
||||
`action_type` varchar(10) NOT NULL COMMENT '작업 종류',
|
||||
`change_data` longtext COMMENT '변경된 데이터 (JSON)',
|
||||
`changed_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '변경일',
|
||||
`changed_by` varchar(20) NOT NULL COMMENT '변경자',
|
||||
PRIMARY KEY (`fh_id`),
|
||||
KEY `table_name_record_id` (`table_name`,`record_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='[솔루션] 폼 옵션 변경 이력';
|
||||
@@ -0,0 +1,90 @@
|
||||
-- 1. 마스터 테이블: 옵션 그룹 (예: '집 유형', '창호 색상')
|
||||
CREATE TABLE IF NOT EXISTS `g5_form_group` (
|
||||
`fg_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`project_code` varchar(50) NOT NULL DEFAULT 'default' COMMENT '프로젝트 코드',
|
||||
`site_code` varchar(50) NOT NULL DEFAULT 'default' COMMENT '사이트 코드',
|
||||
`fg_code` varchar(50) NOT NULL COMMENT '그룹 코드 (프로그램에서 사용)',
|
||||
`fg_order` int(11) NOT NULL DEFAULT '0' COMMENT '정렬 순서',
|
||||
`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '사용 여부 (1:사용, 0:미사용)',
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '삭제 여부 (1:삭제, 0:정상)',
|
||||
`created_at` datetime NOT NULL COMMENT '생성일',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '생성자',
|
||||
`updated_at` datetime NOT NULL COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
`fg_temp_1` varchar(255) DEFAULT NULL COMMENT '임시 필드 1',
|
||||
`fg_temp_2` varchar(255) DEFAULT NULL COMMENT '임시 필드 2',
|
||||
`fg_temp_3` varchar(255) DEFAULT NULL COMMENT '임시 필드 3',
|
||||
`fg_temp_4` text DEFAULT NULL COMMENT '임시 필드 4',
|
||||
`fg_temp_5` text DEFAULT NULL COMMENT '임시 필드 5',
|
||||
`fg_extra_1` varchar(255) DEFAULT NULL COMMENT '여분 필드 1',
|
||||
`fg_extra_2` varchar(255) DEFAULT NULL COMMENT '여분 필드 2',
|
||||
`fg_extra_3` varchar(255) DEFAULT NULL COMMENT '여분 필드 3',
|
||||
`fg_extra_4` text DEFAULT NULL COMMENT '여분 필드 4',
|
||||
`fg_extra_5` text DEFAULT NULL COMMENT '여분 필드 5',
|
||||
PRIMARY KEY (`fg_id`),
|
||||
UNIQUE KEY `project_site_fg_code` (`project_code`,`site_code`,`fg_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[솔루션] 폼 옵션 그룹';
|
||||
|
||||
-- 2. 디테일 테이블: 그룹에 속한 개별 옵션
|
||||
CREATE TABLE IF NOT EXISTS `g5_form_option` (
|
||||
`fo_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`fg_id` int(11) NOT NULL COMMENT '그룹 ID (g5_form_group.fg_id)',
|
||||
`fo_key` varchar(255) NOT NULL COMMENT 'DB에 저장될 값 (고유값)',
|
||||
`fo_order` int(11) NOT NULL DEFAULT '0' COMMENT '정렬 순서',
|
||||
`is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '기본 선택 여부 (1:기본값)',
|
||||
`is_used` tinyint(1) NOT NULL DEFAULT '1' COMMENT '사용 여부 (1:사용, 0:미사용)',
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '삭제 여부 (1:삭제, 0:정상)',
|
||||
`created_at` datetime NOT NULL COMMENT '생성일',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '생성자',
|
||||
`updated_at` datetime NOT NULL COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
`fo_temp_1` varchar(255) DEFAULT NULL COMMENT '임시 필드 1',
|
||||
`fo_temp_2` varchar(255) DEFAULT NULL COMMENT '임시 필드 2',
|
||||
`fo_temp_3` varchar(255) DEFAULT NULL COMMENT '임시 필드 3',
|
||||
`fo_temp_4` text DEFAULT NULL COMMENT '임시 필드 4',
|
||||
`fo_temp_5` text DEFAULT NULL COMMENT '임시 필드 5',
|
||||
`fo_extra_1` varchar(255) DEFAULT NULL COMMENT '여분 필드 1',
|
||||
`fo_extra_2` varchar(255) DEFAULT NULL COMMENT '여분 필드 2',
|
||||
`fo_extra_3` varchar(255) DEFAULT NULL COMMENT '여분 필드 3',
|
||||
`fo_extra_4` text DEFAULT NULL COMMENT '여분 필드 4',
|
||||
`fo_extra_5` text DEFAULT NULL COMMENT '여분 필드 5',
|
||||
PRIMARY KEY (`fo_id`),
|
||||
KEY `fg_id` (`fg_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[솔루션] 폼 옵션 항목';
|
||||
|
||||
-- 3. [통합] 서브 디테일 테이블: 그룹과 옵션의 다국어 이름/설명
|
||||
CREATE TABLE IF NOT EXISTS `g5_common_lang` (
|
||||
`cl_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`target_table` varchar(50) NOT NULL COMMENT '대상 테이블명 (예: g5_form_group)',
|
||||
`target_id` int(11) NOT NULL COMMENT '대상 레코드 ID',
|
||||
`lang_code` varchar(10) NOT NULL COMMENT '언어 코드 (ko, en, ja)',
|
||||
`cl_name` varchar(255) NOT NULL COMMENT '화면에 표시될 이름/값',
|
||||
`cl_description` text COMMENT '부가 설명 (툴팁 등)',
|
||||
`updated_at` datetime NOT NULL COMMENT '수정일',
|
||||
`updated_by` varchar(20) NOT NULL COMMENT '수정자',
|
||||
`cl_temp_1` varchar(255) DEFAULT NULL COMMENT '임시 필드 1',
|
||||
`cl_temp_2` varchar(255) DEFAULT NULL COMMENT '임시 필드 2',
|
||||
`cl_temp_3` varchar(255) DEFAULT NULL COMMENT '임시 필드 3',
|
||||
`cl_temp_4` text DEFAULT NULL COMMENT '임시 필드 4',
|
||||
`cl_temp_5` text DEFAULT NULL COMMENT '임시 필드 5',
|
||||
`cl_extra_1` varchar(255) DEFAULT NULL COMMENT '여분 필드 1',
|
||||
`cl_extra_2` varchar(255) DEFAULT NULL COMMENT '여분 필드 2',
|
||||
`cl_extra_3` varchar(255) DEFAULT NULL COMMENT '여분 필드 3',
|
||||
`cl_extra_4` text DEFAULT NULL COMMENT '여분 필드 4',
|
||||
`cl_extra_5` text DEFAULT NULL COMMENT '여분 필드 5',
|
||||
PRIMARY KEY (`cl_id`),
|
||||
UNIQUE KEY `target_lang` (`target_table`,`target_id`,`lang_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[솔루션] 공용 다국어 정보';
|
||||
|
||||
-- 4. 변경 이력 테이블
|
||||
CREATE TABLE IF NOT EXISTS `g5_form_option_history` (
|
||||
`fh_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '고유 ID',
|
||||
`table_name` varchar(50) NOT NULL COMMENT '변경된 테이블명',
|
||||
`record_id` int(11) NOT NULL COMMENT '변경된 레코드 ID',
|
||||
`action_type` varchar(10) NOT NULL COMMENT '작업 종류 (INSERT, UPDATE, DELETE)',
|
||||
`change_data` longtext COMMENT '변경된 데이터 (JSON)',
|
||||
`changed_at` datetime NOT NULL COMMENT '변경일',
|
||||
`changed_by` varchar(20) NOT NULL COMMENT '변경자',
|
||||
PRIMARY KEY (`fh_id`),
|
||||
KEY `table_name_record_id` (`table_name`,`record_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='[솔루션] 폼 옵션 변경 이력';
|
||||
@@ -0,0 +1,41 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const addResourceButton = document.getElementById('add-resource-btn');
|
||||
const resourceFormContainer = document.getElementById('resource-form-container');
|
||||
const cancelResourceButton = document.getElementById('cancel-resource-btn');
|
||||
const resourceTypeRadios = document.querySelectorAll('input[name="resource_type"]');
|
||||
const labelField = document.getElementById('label-field');
|
||||
|
||||
// '새 리소스 추가' 버튼 클릭 이벤트
|
||||
if (addResourceButton) {
|
||||
addResourceButton.addEventListener('click', function() {
|
||||
if (resourceFormContainer) resourceFormContainer.style.display = 'block';
|
||||
this.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// '취소' 버튼 클릭 이벤트
|
||||
if (cancelResourceButton) {
|
||||
cancelResourceButton.addEventListener('click', function() {
|
||||
if (resourceFormContainer) resourceFormContainer.style.display = 'none';
|
||||
if (addResourceButton) addResourceButton.style.display = 'inline-block';
|
||||
});
|
||||
}
|
||||
|
||||
// 💡 [핵심] 리소스 타입 라디오 버튼 변경 이벤트
|
||||
function toggleResourceTypeFields() {
|
||||
const selectedType = document.querySelector('input[name="resource_type"]:checked').value;
|
||||
if (selectedType === 'LABEL') {
|
||||
labelField.style.display = ''; // 테이블 행이므로 기본값으로
|
||||
} else {
|
||||
labelField.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceTypeRadios.length > 0) {
|
||||
resourceTypeRadios.forEach(radio => {
|
||||
radio.addEventListener('change', toggleResourceTypeFields);
|
||||
});
|
||||
// 페이지 로드 시 초기 상태 설정
|
||||
toggleResourceTypeFields();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,152 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// =================================================================
|
||||
// 1. UI 리소스 목록 페이지 (ui_manager_list.php)
|
||||
// =================================================================
|
||||
const addResourceButton = document.getElementById('add-resource-btn');
|
||||
const resourceFormContainer = document.getElementById('resource-form-container');
|
||||
const cancelResourceButton = document.getElementById('cancel-resource-btn');
|
||||
const resourceTypeRadios = document.querySelectorAll('input[name="resource_type"]');
|
||||
const labelField = document.getElementById('label-field');
|
||||
const accordionItems = document.querySelectorAll('.accordion-item');
|
||||
const searchForm = document.getElementById('fsearch');
|
||||
const pageRowsSelect = document.getElementById('page_rows');
|
||||
|
||||
if (addResourceButton) {
|
||||
addResourceButton.addEventListener('click', function() {
|
||||
if (resourceFormContainer) resourceFormContainer.style.display = 'block';
|
||||
this.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
if (cancelResourceButton) {
|
||||
cancelResourceButton.addEventListener('click', function() {
|
||||
if (resourceFormContainer) resourceFormContainer.style.display = 'none';
|
||||
if (addResourceButton) addResourceButton.style.display = 'inline-block';
|
||||
});
|
||||
}
|
||||
|
||||
function toggleResourceTypeFields() {
|
||||
if (!document.querySelector('input[name="resource_type"]:checked')) return;
|
||||
const selectedType = document.querySelector('input[name="resource_type"]:checked').value;
|
||||
if (labelField) {
|
||||
labelField.style.display = (selectedType === 'LABEL') ? '' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceTypeRadios.length > 0) {
|
||||
resourceTypeRadios.forEach(radio => radio.addEventListener('change', toggleResourceTypeFields));
|
||||
toggleResourceTypeFields();
|
||||
}
|
||||
|
||||
if (accordionItems.length > 0) {
|
||||
accordionItems.forEach(item => {
|
||||
const header = item.querySelector('.accordion-header');
|
||||
const content = item.querySelector('.accordion-content');
|
||||
if (header && content) {
|
||||
header.addEventListener('click', () => {
|
||||
item.classList.toggle('active');
|
||||
content.style.display = item.classList.contains('active') ? 'block' : 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (searchForm) {
|
||||
searchForm.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
// 엔터키 입력 시 기본 동작(폼 제출)을 막지 않음
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (pageRowsSelect) {
|
||||
pageRowsSelect.addEventListener('change', function() {
|
||||
if (searchForm) {
|
||||
searchForm.submit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// 💡 [핵심] 옵션/카테고리 관리 페이지 (category_list.php) 로직 추가
|
||||
// =================================================================
|
||||
const addCategoryButton = document.getElementById('add-category-btn');
|
||||
const categoryFormContainer = document.getElementById('category-form-container');
|
||||
const cancelCategoryButton = document.getElementById('cancel-category-btn');
|
||||
const categoryForm = document.getElementById('fcategoryform');
|
||||
const editCategoryButtons = document.querySelectorAll('.btn_edit_category');
|
||||
|
||||
// "새 옵션 추가" 버튼 클릭
|
||||
if (addCategoryButton && categoryFormContainer) {
|
||||
addCategoryButton.addEventListener('click', function() {
|
||||
if (categoryForm) {
|
||||
categoryForm.reset();
|
||||
categoryForm.w.value = ''; // 신규 등록 모드
|
||||
categoryForm.fc_id.value = '';
|
||||
const submitButton = categoryForm.querySelector('input[type="submit"]');
|
||||
if (submitButton) submitButton.value = '저장';
|
||||
}
|
||||
categoryFormContainer.style.display = 'block';
|
||||
this.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// "취소" 버튼 클릭
|
||||
if (cancelCategoryButton && categoryFormContainer && addCategoryButton) {
|
||||
cancelCategoryButton.addEventListener('click', function() {
|
||||
categoryFormContainer.style.display = 'none';
|
||||
addCategoryButton.style.display = 'inline-block';
|
||||
});
|
||||
}
|
||||
|
||||
// "수정" 버튼 클릭
|
||||
if (editCategoryButtons.length > 0 && categoryForm) {
|
||||
editCategoryButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const data = this.dataset;
|
||||
|
||||
// 폼에 데이터 채우기
|
||||
categoryForm.w.value = 'u'; // 수정 모드
|
||||
categoryForm.fc_id.value = data.fc_id;
|
||||
categoryForm.parent_id.value = data.parent_id;
|
||||
categoryForm.fc_key.value = data.fc_key;
|
||||
categoryForm.cl_name.value = data.cl_name;
|
||||
categoryForm.fc_order.value = data.fc_order;
|
||||
|
||||
const isUsedRadio = categoryForm.querySelector(`input[name="is_used"][value="${data.is_used}"]`);
|
||||
if (isUsedRadio) isUsedRadio.checked = true;
|
||||
|
||||
const submitButton = categoryForm.querySelector('input[type="submit"]');
|
||||
if (submitButton) submitButton.value = '수정';
|
||||
|
||||
if (categoryFormContainer) categoryFormContainer.style.display = 'block';
|
||||
if (addCategoryButton) addCategoryButton.style.display = 'none';
|
||||
|
||||
categoryFormContainer.scrollIntoView({ behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// 3. 리소스 삭제 기능
|
||||
// =================================================================
|
||||
const deleteResourceButtons = document.querySelectorAll('.btn_delete_resource');
|
||||
|
||||
if (deleteResourceButtons.length > 0) {
|
||||
deleteResourceButtons.forEach(button => {
|
||||
button.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const um_id = this.dataset.um_id;
|
||||
const resource_desc_element = this.closest('tr').querySelector('.td_left');
|
||||
const resource_desc = resource_desc_element ? resource_desc_element.textContent.trim() : `ID: ${um_id}`;
|
||||
|
||||
if (confirm(`'${resource_desc}' 리소스를 정말 삭제하시겠습니까?\n\n이 리소스와 관련된 모든 하위 옵션(카테고리) 및 언어 데이터가 함께 영구적으로 삭제됩니다.`)) {
|
||||
const qstr = new URLSearchParams(window.location.search).toString();
|
||||
location.href = `./ui_manager_list.php?mode=delete&um_id=${um_id}&token=${g5_admin_token}&${qstr}`;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
$sub_menu = '700100';
|
||||
include_once('./_common.php');
|
||||
|
||||
// ... (폼 제출 처리 로직은 변경 없음) ...
|
||||
$target_table = isset($_REQUEST['target_table']) ? preg_replace('/[^a-z0-9_]/i', '', $_REQUEST['target_table']) : '';
|
||||
$target_id = isset($_REQUEST['target_id']) ? (int)$_REQUEST['target_id'] : 0;
|
||||
|
||||
if (!$target_table || !$target_id) {
|
||||
alert('잘못된 접근입니다.');
|
||||
}
|
||||
|
||||
if (isset($w) && $w == 'u' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
check_admin_token();
|
||||
$lang_code = trim($_POST['lang_code']);
|
||||
$cl_name = trim($_POST['cl_name']);
|
||||
$cl_description = trim($_POST['cl_description']);
|
||||
if (!$lang_code) alert('언어 코드를 선택해주세요.');
|
||||
if (!$cl_name) alert('이름/값을 입력해주세요.');
|
||||
$sql = "INSERT INTO {$g5['common_lang_table']}
|
||||
SET target_table = '{$target_table}',
|
||||
target_id = '{$target_id}',
|
||||
lang_code = '{$lang_code}',
|
||||
cl_name = '{$cl_name}',
|
||||
cl_description = '{$cl_description}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'
|
||||
ON DUPLICATE KEY UPDATE
|
||||
cl_name = '{$cl_name}',
|
||||
cl_description = '{$cl_description}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
sql_query($sql);
|
||||
goto_url("./lang_manager.php?target_table=$target_table&target_id=$target_id");
|
||||
}
|
||||
if (isset($mode) && $mode == 'delete') {
|
||||
auth_check_menu($auth, $sub_menu, 'd');
|
||||
check_admin_token();
|
||||
$cl_id = isset($_GET['cl_id']) ? (int)$_GET['cl_id'] : 0;
|
||||
if (!$cl_id) alert('cl_id 값이 없습니다.');
|
||||
$sql = "DELETE FROM {$g5['common_lang_table']} WHERE cl_id = '{$cl_id}' AND target_table = '{$target_table}' AND target_id = '{$target_id}'";
|
||||
sql_query($sql);
|
||||
goto_url("./lang_manager.php?target_table=$target_table&target_id=$target_id");
|
||||
}
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
// 💡 [핵심 추가] 이전 페이지로 돌아가기 위한 링크 생성
|
||||
$back_link = './ui_manager_list.php'; // 기본 돌아가기 링크
|
||||
if ($target_table == $g5['form_category_table']) {
|
||||
// 카테고리 다국어 관리였다면, 해당 카테고리가 속한 리소스의 옵션 관리 페이지로 돌아가야 함
|
||||
$sql_back = "SELECT um_id FROM {$g5['form_category_table']} WHERE fc_id = '{$target_id}'";
|
||||
$back_row = sql_fetch($sql_back);
|
||||
if (isset($back_row['um_id'])) {
|
||||
$back_link = './category_list.php?um_id=' . $back_row['um_id'];
|
||||
}
|
||||
}
|
||||
|
||||
// UiManager 클래스를 사용하여 사용 가능한 언어 목록 가져오기
|
||||
$active_languages = ui_manager()->get_data('language_list');
|
||||
|
||||
// 현재 관리 대상의 기본 정보(한국어)를 가져옴
|
||||
$sql = "SELECT cl_name FROM {$g5['common_lang_table']} WHERE target_table = '{$target_table}' AND target_id = '{$target_id}' AND lang_code = 'ko'";
|
||||
$parent_info = sql_fetch($sql);
|
||||
$parent_name = isset($parent_info['cl_name']) ? get_text($parent_info['cl_name']) : "ID: {$target_id}";
|
||||
|
||||
// 등록된 다국어 목록 조회
|
||||
$sql = "SELECT * FROM {$g5['common_lang_table']} WHERE target_table = '{$target_table}' AND target_id = '{$target_id}' ORDER BY lang_code";
|
||||
$result = sql_query($sql);
|
||||
$lang_list = [];
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$lang_list[] = $row;
|
||||
}
|
||||
$lang_list_count = count($lang_list);
|
||||
|
||||
$g5['title'] = '다국어 관리';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
add_stylesheet('<link rel="stylesheet" href="' . G5_ADMIN_URL . '/code_manager/css/code_manager.css?ver=1.1">', 0);
|
||||
?>
|
||||
|
||||
<div class="local_desc01 local_desc">
|
||||
<p>
|
||||
<strong>'<?php echo $parent_name; ?>'</strong> 항목에 대한 다국어 이름과 설명을 관리합니다.<br>
|
||||
'언어 코드'는 중복하여 등록할 수 없습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section id="code_manager">
|
||||
<h2 class="h2_frm">다국어 등록/수정</h2>
|
||||
<form name="flangform" id="flangform" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post">
|
||||
<input type="hidden" name="w" value="u">
|
||||
<input type="hidden" name="target_table" value="<?php echo $target_table; ?>">
|
||||
<input type="hidden" name="target_id" value="<?php echo $target_id; ?>">
|
||||
<input type="hidden" name="token" value="<?php echo get_admin_token(); ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption>다국어 정보 추가/수정 폼</caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="lang_code">언어 코드</label></th>
|
||||
<td>
|
||||
<select name="lang_code" id="lang_code" required>
|
||||
<option value="">선택</option>
|
||||
<?php foreach ($active_languages as $lang_item) : ?>
|
||||
<option value="<?php echo $lang_item['fc_key']; ?>"><?php echo get_text($lang_item['cl_name']); ?> (<?php echo $lang_item['fc_key']; ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="cl_name">이름/값</label></th>
|
||||
<td>
|
||||
<input type="text" name="cl_name" id="cl_name" required class="required frm_input" size="80">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="cl_description">부가 설명</label></th>
|
||||
<td>
|
||||
<textarea name="cl_description" id="cl_description" rows="5"></textarea>
|
||||
<span class="frm_info">툴팁 등 부가적으로 사용될 설명을 입력합니다. (선택사항)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="btn_confirm01 btn_confirm">
|
||||
<!-- 💡 [핵심 수정] 목록으로 돌아가는 버튼 추가 -->
|
||||
<a href="<?php echo $back_link; ?>" class="btn_cancel btn">목록으로</a>
|
||||
<input type="submit" value="저장" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 등록된 다국어 목록 테이블 -->
|
||||
<div class="tbl_head01 tbl_wrap" style="margin-top: 20px;">
|
||||
<h2 class="h2_frm">등록된 다국어 목록</h2>
|
||||
<table>
|
||||
<caption>등록된 다국어 목록</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style="width: 100px;">언어 코드</th>
|
||||
<th scope="col">이름/값</th>
|
||||
<th scope="col">부가 설명</th>
|
||||
<th scope="col" style="width: 120px;">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($lang_list_count > 0) : ?>
|
||||
<?php foreach ($lang_list as $lang) : ?>
|
||||
<tr>
|
||||
<td class="td_alignc"><?php echo get_text($lang['lang_code']); ?></td>
|
||||
<td class="td_left"><?php echo get_text($lang['cl_name']); ?></td>
|
||||
<td class="td_left"><?php echo get_text($lang['cl_description']); ?></td>
|
||||
<td class="td_mng">
|
||||
<button type="button" class="btn btn_02 btn_edit_lang"
|
||||
data-lang_code="<?php echo get_text($lang['lang_code']); ?>"
|
||||
data-cl_name="<?php echo get_text($lang['cl_name']); ?>"
|
||||
data-cl_description="<?php echo get_text($lang['cl_description']); ?>">수정</button>
|
||||
<a href="./lang_manager.php?mode=delete&cl_id=<?php echo $lang['cl_id']; ?>&target_table=<?php echo $target_table; ?>&target_id=<?php echo $target_id; ?>&token=<?php echo get_admin_token(); ?>"
|
||||
class="btn btn_delete" onclick="return confirm('정말 삭제하시겠습니까?');">삭제</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr class="empty_table">
|
||||
<td colspan="4">등록된 다국어 정보가 없습니다.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editLangButtons = document.querySelectorAll('.btn_edit_lang');
|
||||
const langForm = document.getElementById('flangform');
|
||||
if (editLangButtons.length > 0 && langForm) {
|
||||
editLangButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const data = this.dataset;
|
||||
langForm.lang_code.value = data.lang_code;
|
||||
langForm.cl_name.value = data.cl_name;
|
||||
langForm.cl_description.value = data.cl_description;
|
||||
langForm.scrollIntoView({ behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* SQL 파일을 기반으로 데이터베이스 스키마를 관리(생성/업데이트)하는 범용 클래스
|
||||
*/
|
||||
class SchemaManager
|
||||
{
|
||||
private $sql_file_path;
|
||||
private $results;
|
||||
|
||||
/**
|
||||
* 생성자
|
||||
* @param string $sql_file_path install.sql 파일의 절대 경로
|
||||
*/
|
||||
public function __construct($sql_file_path)
|
||||
{
|
||||
if (!file_exists($sql_file_path)) {
|
||||
throw new Exception($sql_file_path . ' 파일을 찾을 수 없습니다.');
|
||||
}
|
||||
$this->sql_file_path = $sql_file_path;
|
||||
$this->results = [
|
||||
'created' => [],
|
||||
'existing' => [],
|
||||
'updated' => [],
|
||||
'failed' => [],
|
||||
'errors' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 스키마 설치/업데이트를 실행합니다.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$sql_statements = $this->parse_sql_file();
|
||||
|
||||
foreach ($sql_statements as $stmt) {
|
||||
// CREATE TABLE 문인지 확인
|
||||
if (preg_match('/^CREATE\s+TABLE/i', $stmt)) {
|
||||
$schema = $this->parse_create_table_sql($stmt);
|
||||
if ($schema && !empty($schema['name'])) {
|
||||
$this->process_table_schema($stmt, $schema);
|
||||
}
|
||||
} else {
|
||||
// CREATE TABLE 문이 아닌 다른 SQL 문 (e.g. INSERT, UPDATE)
|
||||
sql_query($stmt, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 처리 결과를 반환합니다.
|
||||
* @return array
|
||||
*/
|
||||
public function get_results()
|
||||
{
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 스키마를 처리합니다. (생성 또는 업데이트)
|
||||
* @param string $create_sql 전체 CREATE TABLE 구문
|
||||
* @param array $schema 파싱된 스키마 정보
|
||||
*/
|
||||
private function process_table_schema($create_sql, $schema)
|
||||
{
|
||||
$table_name = $schema['name'];
|
||||
|
||||
if ($this->table_exists($table_name)) {
|
||||
// 테이블이 존재하면, 컬럼 비교 및 추가
|
||||
$this->results['existing'][] = $table_name;
|
||||
$this->update_table_columns($table_name, $schema['columns']);
|
||||
} else {
|
||||
// 테이블이 존재하지 않으면, 새로 생성
|
||||
if (sql_query($create_sql, false)) {
|
||||
$this->results['created'][] = $table_name;
|
||||
} else {
|
||||
$this->results['failed'][] = $table_name;
|
||||
$this->results['errors'][] = "<strong>{$table_name} 테이블 생성 실패</strong>: " . sql_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블의 컬럼 구조를 업데이트합니다.
|
||||
* @param string $table_name
|
||||
* @param array $target_columns .sql 파일에 정의된 컬럼 목록
|
||||
*/
|
||||
private function update_table_columns($table_name, $target_columns)
|
||||
{
|
||||
$current_columns = $this->get_current_columns($table_name);
|
||||
$added_columns_in_table = [];
|
||||
|
||||
foreach ($target_columns as $col_name => $col_definition) {
|
||||
// 현재 테이블에 해당 컬럼이 없으면 추가
|
||||
if (!isset($current_columns[$col_name])) {
|
||||
$alter_sql = "ALTER TABLE `{$table_name}` ADD COLUMN `{$col_name}` {$col_definition}";
|
||||
if (sql_query($alter_sql, false)) {
|
||||
$added_columns_in_table[] = $col_name;
|
||||
} else {
|
||||
$this->results['failed'][] = "{$table_name} (컬럼: {$col_name})";
|
||||
$this->results['errors'][] = "<strong>{$table_name} 테이블에 '{$col_name}' 컬럼 추가 실패</strong>: " . sql_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($added_columns_in_table)) {
|
||||
$this->results['updated'][$table_name] = $added_columns_in_table;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL 파일을 읽고 각 구문으로 분리합니다.
|
||||
* @return array
|
||||
*/
|
||||
private function parse_sql_file()
|
||||
{
|
||||
$sql = file_get_contents($this->sql_file_path);
|
||||
// 주석 제거 (SQL 주석 '--' 와 C-style '/* ... */' 주석)
|
||||
$sql = preg_replace('/--.*/', '', $sql);
|
||||
$sql = preg_replace('!/\*.*?\*/!s', '', $sql);
|
||||
$sql = trim($sql);
|
||||
|
||||
// 세미콜론(;)을 기준으로 쿼리 분리
|
||||
return array_filter(array_map('trim', explode(';', $sql)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 테이블 존재 여부를 확인합니다.
|
||||
* @param string $table_name
|
||||
* @return bool
|
||||
*/
|
||||
private function table_exists($table_name)
|
||||
{
|
||||
$res = sql_query("SHOW TABLES LIKE '{$table_name}'", false);
|
||||
return sql_num_rows($res) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 DB에 있는 테이블의 컬럼 목록을 가져옵니다.
|
||||
* @param string $table_name
|
||||
* @return array
|
||||
*/
|
||||
private function get_current_columns($table_name)
|
||||
{
|
||||
$res = sql_query("SHOW COLUMNS FROM `{$table_name}`", false);
|
||||
$columns = [];
|
||||
while ($row = sql_fetch_array($res)) {
|
||||
$columns[$row['Field']] = true;
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* CREATE TABLE SQL 구문에서 테이블명과 컬럼 정의를 파싱합니다.
|
||||
* @param string $query CREATE TABLE 구문
|
||||
* @return array|null
|
||||
*/
|
||||
private function parse_create_table_sql($query)
|
||||
{
|
||||
$table_name = '';
|
||||
if (preg_match('/CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+`?(\w+)`?/i', $query, $matches)) {
|
||||
$table_name = $matches[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 괄호 안의 내용만 추출
|
||||
$start = strpos($query, '(');
|
||||
$end = strrpos($query, ')');
|
||||
if ($start === false || $end === false) {
|
||||
return ['name' => $table_name, 'columns' => []];
|
||||
}
|
||||
$content = substr($query, $start + 1, $end - $start - 1);
|
||||
|
||||
// 줄 단위로 분리
|
||||
$lines = explode("\n", $content);
|
||||
|
||||
$columns = [];
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line, " \t\n\r\0\x0B,"); // 양쪽 공백과 마지막 쉼표 제거
|
||||
|
||||
// 컬럼 정의 라인인지 확인 (첫 단어가 `column_name` 형태)
|
||||
if (preg_match('/^`(\w+)`\s+(.*)/i', $line, $match)) {
|
||||
$col_name = $match[1];
|
||||
$col_definition = $match[2];
|
||||
$columns[$col_name] = $col_definition;
|
||||
}
|
||||
}
|
||||
|
||||
return ['name' => $table_name, 'columns' => $columns];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* UI 리소스 관리 클래스
|
||||
* Singleton 패턴을 사용하여 인스턴스를 한 번만 생성하고,
|
||||
* 불러온 데이터를 캐시하여 DB 조회를 최소화합니다.
|
||||
*/
|
||||
class UiManager
|
||||
{
|
||||
private static $instance = null;
|
||||
private $resources = []; // 데이터를 캐시할 배열
|
||||
|
||||
// 외부에서 new 키워드로 인스턴스 생성을 막음
|
||||
private function __construct() {}
|
||||
|
||||
/**
|
||||
* 클래스의 유일한 인스턴스를 반환합니다.
|
||||
* @return UiManager
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'LABEL' 타입의 UI 텍스트를 가져옵니다.
|
||||
* @param string $resource_code 리소스 코드
|
||||
* @param string $lang 언어 코드 (기본값: 'ko')
|
||||
* @return string 라벨 텍스트 (없으면 resource_code 반환)
|
||||
*/
|
||||
public function get_label($resource_code, $lang = 'ko')
|
||||
{
|
||||
// 캐시 확인
|
||||
if (isset($this->resources['labels'][$lang][$resource_code])) {
|
||||
return $this->resources['labels'][$lang][$resource_code];
|
||||
}
|
||||
|
||||
global $g5;
|
||||
$resource_code_escaped = sql_real_escape_string($resource_code);
|
||||
$lang_escaped = sql_real_escape_string($lang);
|
||||
|
||||
$sql = "SELECT B.cl_name
|
||||
FROM {$g5['ui_manager_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.um_id = B.target_id AND B.target_table = '{$g5['ui_manager_table']}' AND B.lang_code = '{$lang_escaped}')
|
||||
WHERE A.resource_code = '{$resource_code_escaped}' AND A.resource_type = 'LABEL'";
|
||||
$row = sql_fetch($sql);
|
||||
|
||||
$label_text = $row['cl_name'] ?? $resource_code;
|
||||
|
||||
// 결과 캐시
|
||||
$this->resources['labels'][$lang][$resource_code] = $label_text;
|
||||
|
||||
return $label_text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'DATA' 타입의 옵션 목록을 배열로 가져옵니다.
|
||||
* @param string $resource_code 리소스 코드
|
||||
* @param string $lang 언어 코드 (기본값: 'ko')
|
||||
* @return array 옵션 목록 배열
|
||||
*/
|
||||
public function get_data($resource_code, $lang = 'ko')
|
||||
{
|
||||
// 캐시 확인
|
||||
if (isset($this->resources['data'][$lang][$resource_code])) {
|
||||
return $this->resources['data'][$lang][$resource_code];
|
||||
}
|
||||
|
||||
global $g5;
|
||||
$resource_code_escaped = sql_real_escape_string($resource_code);
|
||||
$lang_escaped = sql_real_escape_string($lang);
|
||||
|
||||
$sql_um = "SELECT um_id FROM {$g5['ui_manager_table']} WHERE resource_code = '{$resource_code_escaped}' AND resource_type = 'DATA'";
|
||||
$um_row = sql_fetch($sql_um);
|
||||
|
||||
if (!isset($um_row['um_id'])) {
|
||||
$this->resources['data'][$lang][$resource_code] = []; // 빈 결과도 캐시
|
||||
return [];
|
||||
}
|
||||
$um_id = $um_row['um_id'];
|
||||
|
||||
$sql = "SELECT A.fc_id, A.parent_id, A.fc_key, A.fc_order, B.cl_name
|
||||
FROM {$g5['form_category_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.fc_id = B.target_id AND B.target_table = '{$g5['form_category_table']}' AND B.lang_code = '{$lang_escaped}')
|
||||
WHERE A.um_id = '{$um_id}' AND A.is_used = 1 AND A.is_deleted = 0
|
||||
ORDER BY A.fc_order, A.fc_id";
|
||||
|
||||
$result = sql_query($sql);
|
||||
$options = [];
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$options[] = $row;
|
||||
}
|
||||
|
||||
// 결과 캐시
|
||||
$this->resources['data'][$lang][$resource_code] = $options;
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'DATA' 타입 리소스를 사용하여 HTML <select> 태그를 생성합니다.
|
||||
* @param string $resource_code 리소스 코드
|
||||
* @param string $select_name <select> 태그의 name 속성
|
||||
* @param string $selected_value 미리 선택될 옵션의 값(fc_key)
|
||||
* @param string $attributes <select> 태그에 추가할 HTML 속성 (e.g., 'id="my-id" class="my-class"')
|
||||
* @param string $lang 언어 코드 (기본값: 'ko')
|
||||
* @return string 생성된 HTML <select> 태그
|
||||
*/
|
||||
public function render_select($resource_code, $select_name, $selected_value = '', $attributes = '', $lang = 'ko')
|
||||
{
|
||||
$options = $this->get_data($resource_code, $lang);
|
||||
|
||||
if (empty($options)) {
|
||||
return "<select name=\"{$select_name}\" {$attributes}><option value=\"\">옵션 없음</option></select>";
|
||||
}
|
||||
|
||||
$html = "<select name=\"{$select_name}\" {$attributes}>";
|
||||
$html .= "<option value=\"\">선택</option>";
|
||||
foreach ($options as $option) {
|
||||
$selected = ($option['fc_key'] == $selected_value) ? ' selected' : '';
|
||||
$html .= "<option value=\"" . htmlspecialchars($option['fc_key']) . "\"{$selected}>" . htmlspecialchars($option['cl_name']) . "</option>";
|
||||
}
|
||||
$html .= "</select>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* UI 리소스 관리자 클래스 인스턴스를 반환하는 헬퍼 함수
|
||||
* @return UiManager
|
||||
*/
|
||||
function ui_manager() {
|
||||
// 클래스가 아직 로드되지 않았다면 인스턴스 생성
|
||||
if (!class_exists('UiManager')) {
|
||||
// UiManager 클래스 정의
|
||||
class UiManager
|
||||
{
|
||||
private static $instance = null;
|
||||
private $resources = []; // 데이터를 캐시할 배열
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function get_label($resource_code, $lang = 'ko')
|
||||
{
|
||||
if (isset($this->resources['labels'][$lang][$resource_code])) {
|
||||
return $this->resources['labels'][$lang][$resource_code];
|
||||
}
|
||||
|
||||
global $g5;
|
||||
$resource_code_escaped = sql_real_escape_string($resource_code);
|
||||
$lang_escaped = sql_real_escape_string($lang);
|
||||
|
||||
$sql = "SELECT B.cl_name
|
||||
FROM {$g5['ui_manager_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.um_id = B.target_id AND B.target_table = '{$g5['ui_manager_table']}' AND B.lang_code = '{$lang_escaped}')
|
||||
WHERE A.resource_code = '{$resource_code_escaped}' AND A.resource_type = 'LABEL'";
|
||||
$row = sql_fetch($sql);
|
||||
|
||||
$label_text = $row['cl_name'] ?? $resource_code;
|
||||
$this->resources['labels'][$lang][$resource_code] = $label_text;
|
||||
return $label_text;
|
||||
}
|
||||
|
||||
public function get_data($resource_code, $lang = 'ko')
|
||||
{
|
||||
if (isset($this->resources['data'][$lang][$resource_code])) {
|
||||
return $this->resources['data'][$lang][$resource_code];
|
||||
}
|
||||
|
||||
global $g5;
|
||||
$resource_code_escaped = sql_real_escape_string($resource_code);
|
||||
$lang_escaped = sql_real_escape_string($lang);
|
||||
|
||||
$sql_um = "SELECT um_id FROM {$g5['ui_manager_table']} WHERE resource_code = '{$resource_code_escaped}' AND resource_type = 'DATA'";
|
||||
$um_row = sql_fetch($sql_um);
|
||||
|
||||
if (!isset($um_row['um_id'])) {
|
||||
$this->resources['data'][$lang][$resource_code] = [];
|
||||
return [];
|
||||
}
|
||||
$um_id = $um_row['um_id'];
|
||||
|
||||
$sql = "SELECT A.fc_id, A.parent_id, A.fc_key, A.fc_order, B.cl_name
|
||||
FROM {$g5['form_category_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.fc_id = B.target_id AND B.target_table = '{$g5['form_category_table']}' AND B.lang_code = '{$lang_escaped}')
|
||||
WHERE A.um_id = '{$um_id}' AND A.is_used = 1 AND A.is_deleted = 0
|
||||
ORDER BY A.fc_order, A.fc_id";
|
||||
|
||||
$result = sql_query($sql);
|
||||
$options = [];
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$options[] = $row;
|
||||
}
|
||||
|
||||
$this->resources['data'][$lang][$resource_code] = $options;
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function render_select($resource_code, $select_name, $selected_value = '', $attributes = '', $lang = 'ko')
|
||||
{
|
||||
$options = $this->get_data($resource_code, $lang);
|
||||
|
||||
if (empty($options)) {
|
||||
return "<select name=\"".htmlspecialchars($select_name)."\" {$attributes}><option value=\"\">옵션 없음</option></select>";
|
||||
}
|
||||
|
||||
$html = "<select name=\"".htmlspecialchars($select_name)."\" {$attributes}>";
|
||||
$html .= "<option value=\"\">선택</option>";
|
||||
foreach ($options as $option) {
|
||||
$selected = ($option['fc_key'] == $selected_value) ? ' selected' : '';
|
||||
$html .= "<option value=\"" . htmlspecialchars($option['fc_key']) . "\"{$selected}>" . htmlspecialchars($option['cl_name']) . "</option>";
|
||||
}
|
||||
$html .= "</select>";
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UiManager::getInstance();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
$sub_menu = '100350';
|
||||
include_once('./_common.php');
|
||||
|
||||
$w = isset($_REQUEST['w']) ? substr(trim($_REQUEST['w']), 0, 1) : '';
|
||||
$um_id = isset($_REQUEST['um_id']) ? (int)$_REQUEST['um_id'] : 0;
|
||||
|
||||
// ==================================================================
|
||||
// 💡 [핵심] 폼 제출(수정) 처리 로직
|
||||
// ==================================================================
|
||||
if ($w == 'u' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
check_admin_token();
|
||||
|
||||
if (!$um_id) {
|
||||
alert('um_id 값이 없습니다.');
|
||||
}
|
||||
|
||||
// 입력값 정리
|
||||
$screen_code = trim($_POST['screen_code']);
|
||||
$group_code = trim($_POST['group_code']);
|
||||
$resource_code = trim($_POST['resource_code']);
|
||||
$resource_type = trim($_POST['resource_type']);
|
||||
$resource_desc = trim($_POST['resource_desc']);
|
||||
$cl_name = isset($_POST['cl_name']) ? trim($_POST['cl_name']) : '';
|
||||
|
||||
// 유효성 검사
|
||||
if (!$screen_code || !$group_code || !$resource_code || !$resource_type) {
|
||||
alert('필수 항목을 모두 입력해주세요.');
|
||||
}
|
||||
if ($resource_type == 'LABEL' && !$cl_name) {
|
||||
alert('UI 라벨 타입은 한국어 라벨명을 필수로 입력해야 합니다.');
|
||||
}
|
||||
|
||||
// 1. g5_ui_manager 테이블 정보 업데이트
|
||||
$sql = "UPDATE {$g5['ui_manager_table']}
|
||||
SET screen_code = '{$screen_code}',
|
||||
group_code = '{$group_code}',
|
||||
resource_code = '{$resource_code}',
|
||||
resource_type = '{$resource_type}',
|
||||
resource_desc = '{$resource_desc}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'
|
||||
WHERE um_id = '{$um_id}'";
|
||||
sql_query($sql);
|
||||
|
||||
// 2. 리소스 타입이 'LABEL'인 경우, g5_common_lang 테이블 정보 업데이트 (없으면 생성)
|
||||
if ($resource_type == 'LABEL') {
|
||||
$sql = "SELECT cl_id FROM {$g5['common_lang_table']} WHERE target_table = '{$g5['ui_manager_table']}' AND target_id = '{$um_id}' AND lang_code = 'ko'";
|
||||
$lang_row = sql_fetch($sql);
|
||||
|
||||
if (isset($lang_row['cl_id'])) { // 기존 데이터가 있으면 UPDATE
|
||||
$sql = "UPDATE {$g5['common_lang_table']}
|
||||
SET cl_name = '{$cl_name}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'
|
||||
WHERE cl_id = '{$lang_row['cl_id']}'";
|
||||
} else { // 기존 데이터가 없으면 INSERT
|
||||
$sql = "INSERT INTO {$g5['common_lang_table']}
|
||||
SET target_table = '{$g5['ui_manager_table']}',
|
||||
target_id = '{$um_id}',
|
||||
lang_code = 'ko',
|
||||
cl_name = '{$cl_name}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
}
|
||||
sql_query($sql);
|
||||
}
|
||||
|
||||
goto_url('./ui_manager_list.php');
|
||||
}
|
||||
// ==================================================================
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
// 수정할 리소스 데이터 조회
|
||||
if ($w == 'u') {
|
||||
if (!$um_id) {
|
||||
alert('um_id 값이 없습니다.', './ui_manager_list.php');
|
||||
}
|
||||
|
||||
$sql = "SELECT A.*, B.cl_name
|
||||
FROM {$g5['ui_manager_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.um_id = B.target_id AND B.target_table = '{$g5['ui_manager_table']}' AND B.lang_code = 'ko')
|
||||
WHERE A.um_id = '{$um_id}'";
|
||||
$ui_resource = sql_fetch($sql);
|
||||
|
||||
if (!isset($ui_resource['um_id'])) {
|
||||
alert('존재하지 않는 리소스입니다.', './ui_manager_list.php');
|
||||
}
|
||||
} else {
|
||||
alert('w 값이 올바르지 않습니다.', './ui_manager_list.php');
|
||||
}
|
||||
|
||||
$g5['title'] = 'UI 리소스 수정';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
add_stylesheet('<link rel="stylesheet" href="' . G5_ADMIN_URL . '/code_manager/css/code_manager.css?ver=1.1">', 0);
|
||||
?>
|
||||
|
||||
<section id="code_manager_form">
|
||||
<h2 class="h2_frm">UI 리소스 수정</h2>
|
||||
|
||||
<form name="fresourceform" id="fresourceform" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post">
|
||||
<input type="hidden" name="w" value="u">
|
||||
<input type="hidden" name="um_id" value="<?php echo $um_id; ?>">
|
||||
<input type="hidden" name="token" value="<?php echo get_admin_token(); ?>">
|
||||
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption>UI 리소스 수정 폼</caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="screen_code">화면 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="screen_code" id="screen_code" required class="required frm_input" size="30" value="<?php echo get_text($ui_resource['screen_code']); ?>">
|
||||
<span class="frm_info">리소스가 사용될 화면의 고유 코드 (예: order_form, member_join)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="group_code">그룹 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="group_code" id="group_code" required class="required frm_input" size="30" value="<?php echo get_text($ui_resource['group_code']); ?>">
|
||||
<span class="frm_info">화면 내에서 리소스를 묶어줄 그룹 코드 (예: address_info, common_options)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">리소스 타입</th>
|
||||
<td>
|
||||
<label><input type="radio" name="resource_type" value="LABEL" <?php echo get_checked($ui_resource['resource_type'], 'LABEL'); ?>> UI 라벨 (단일 텍스트)</label>
|
||||
<label><input type="radio" name="resource_type" value="DATA" <?php echo get_checked($ui_resource['resource_type'], 'DATA'); ?>> 데이터 (선택 옵션)</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="resource-type-field" id="label-field">
|
||||
<th scope="row"><label for="cl_name">한국어 라벨명</label></th>
|
||||
<td>
|
||||
<input type="text" name="cl_name" id="cl_name" class="frm_input" size="50" value="<?php echo get_text($ui_resource['cl_name']); ?>">
|
||||
<span class="frm_info">화면에 표시될 실제 텍스트 (예: 집의 유형, 창호 재질)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_code">리소스 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_code" id="resource_code" required class="required frm_input" size="30" value="<?php echo get_text($ui_resource['resource_code']); ?>">
|
||||
<span class="frm_info">개발자가 이 리소스를 호출할 때 사용할 고유 코드 (예: house_type_label, house_type_data)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_desc">설명</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_desc" id="resource_desc" class="frm_input" size="80" value="<?php echo get_text($ui_resource['resource_desc']); ?>">
|
||||
<span class="frm_info">이 리소스의 용도에 대한 설명 (관리자 참고용)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="btn_confirm01 btn_confirm">
|
||||
<a href="./ui_manager_list.php" class="btn_cancel btn">목록으로</a>
|
||||
<input type="submit" value="수정" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<script src="<?php echo G5_ADMIN_URL; ?>/code_manager/js/ui_manager.js?ver=1.2"></script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
$sub_menu = '700100';
|
||||
include_once('./_common.php');
|
||||
|
||||
// ==================================================================
|
||||
// 삭제 처리 로직
|
||||
// ==================================================================
|
||||
if (isset($_GET['mode']) && $_GET['mode'] == 'delete') {
|
||||
auth_check_menu($auth, $sub_menu, 'd');
|
||||
check_admin_token();
|
||||
$um_id = isset($_GET['um_id']) ? (int)$_GET['um_id'] : 0;
|
||||
if (!$um_id) {
|
||||
alert('um_id 값이 없습니다.');
|
||||
}
|
||||
$sql = "SELECT resource_type FROM {$g5['ui_manager_table']} WHERE um_id = '{$um_id}'";
|
||||
$row = sql_fetch($sql);
|
||||
if (isset($row['resource_type'])) {
|
||||
if ($row['resource_type'] == 'DATA') {
|
||||
$sql_delete_lang = "DELETE FROM {$g5['common_lang_table']} WHERE target_table = '{$g5['form_category_table']}' AND target_id IN (SELECT fc_id FROM {$g5['form_category_table']} WHERE um_id = '{$um_id}')";
|
||||
sql_query($sql_delete_lang);
|
||||
$sql_delete_cat = "DELETE FROM {$g5['form_category_table']} WHERE um_id = '{$um_id}'";
|
||||
sql_query($sql_delete_cat);
|
||||
}
|
||||
$sql_delete_main_lang = "DELETE FROM {$g5['common_lang_table']} WHERE target_table = '{$g5['ui_manager_table']}' AND target_id = '{$um_id}'";
|
||||
sql_query($sql_delete_main_lang);
|
||||
$sql_delete_main = "DELETE FROM {$g5['ui_manager_table']} WHERE um_id = '{$um_id}'";
|
||||
sql_query($sql_delete_main);
|
||||
}
|
||||
// 삭제 후 현재 페이지와 검색 조건을 유지하도록 $qstr 사용
|
||||
goto_url('./ui_manager_list.php?'.$qstr);
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// 💡 [핵심 수정 1] 폼 제출 처리 로직 (신규 등록)
|
||||
// ==================================================================
|
||||
// GnuBoard 표준에 따라 'w' 값이 비어있을 때를 신규 등록으로 처리합니다.
|
||||
if (empty($w) && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
auth_check_menu($auth, $sub_menu, 'w');
|
||||
check_admin_token();
|
||||
|
||||
// 입력값 정리
|
||||
$screen_code = trim($_POST['screen_code']);
|
||||
$group_code = trim($_POST['group_code']);
|
||||
$resource_code = trim($_POST['resource_code']);
|
||||
$resource_type = trim($_POST['resource_type']);
|
||||
$resource_desc = trim($_POST['resource_desc']);
|
||||
$cl_name = isset($_POST['cl_name']) ? trim($_POST['cl_name']) : '';
|
||||
|
||||
// 유효성 검사
|
||||
if (!$screen_code || !$group_code || !$resource_code || !$resource_type) {
|
||||
alert('필수 항목을 모두 입력해주세요.');
|
||||
}
|
||||
if ($resource_type == 'LABEL' && !$cl_name) {
|
||||
alert('UI 라벨 타입은 한국어 라벨명을 필수로 입력해야 합니다.');
|
||||
}
|
||||
|
||||
// 중복 체크
|
||||
$sql = "SELECT COUNT(*) as cnt FROM {$g5['ui_manager_table']} WHERE screen_code = '{$screen_code}' AND group_code = '{$group_code}' AND resource_code = '{$resource_code}'";
|
||||
$row = sql_fetch($sql);
|
||||
if ($row['cnt']) {
|
||||
alert('이미 동일한 화면/그룹/리소스 코드로 등록된 리소스가 존재합니다.');
|
||||
}
|
||||
|
||||
// 1. g5_ui_manager 테이블에 정보 INSERT
|
||||
$sql = "INSERT INTO {$g5['ui_manager_table']}
|
||||
SET screen_code = '{$screen_code}',
|
||||
group_code = '{$group_code}',
|
||||
resource_code = '{$resource_code}',
|
||||
resource_type = '{$resource_type}',
|
||||
resource_desc = '{$resource_desc}',
|
||||
is_used = '1',
|
||||
created_at = '".G5_TIME_YMDHIS."',
|
||||
created_by = '{$member['mb_id']}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
sql_query($sql);
|
||||
$um_id = sql_insert_id();
|
||||
|
||||
// 2. 리소스 타입이 'LABEL'인 경우, g5_common_lang 테이블에 정보 INSERT
|
||||
if ($resource_type == 'LABEL' && $cl_name) {
|
||||
$sql = "INSERT INTO {$g5['common_lang_table']}
|
||||
SET target_table = '{$g5['ui_manager_table']}',
|
||||
target_id = '{$um_id}',
|
||||
lang_code = 'ko',
|
||||
cl_name = '{$cl_name}',
|
||||
updated_at = '".G5_TIME_YMDHIS."',
|
||||
updated_by = '{$member['mb_id']}'";
|
||||
sql_query($sql);
|
||||
}
|
||||
|
||||
goto_url('./ui_manager_list.php');
|
||||
}
|
||||
// ==================================================================
|
||||
|
||||
auth_check_menu($auth, $sub_menu, 'r');
|
||||
|
||||
// 검색 및 페이징 변수 처리
|
||||
$sfl = isset($_GET['sfl']) ? trim($_GET['sfl']) : '';
|
||||
$stx = isset($_GET['stx']) ? trim($_GET['stx']) : '';
|
||||
$page_rows = isset($_GET['page_rows']) && (int)$_GET['page_rows'] > 0 ? (int)$_GET['page_rows'] : 15;
|
||||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
if ($page < 1) $page = 1;
|
||||
|
||||
// 페이지당 목록 수($page_rows)를 $qstr에 추가하여 다른 링크에서도 유지되도록 함
|
||||
$qstr .= ($qstr ? '&' : '') . 'page_rows=' . urlencode($page_rows);
|
||||
|
||||
$sql_search = "";
|
||||
if ($sfl && $stx) {
|
||||
$stx_escaped = sql_real_escape_string($stx);
|
||||
$sql_search = " WHERE ";
|
||||
|
||||
switch ($sfl) {
|
||||
case 'screen_code':
|
||||
case 'group_code':
|
||||
case 'resource_code':
|
||||
case 'resource_desc':
|
||||
$sql_search .= "A.{$sfl} LIKE '%{$stx_escaped}%'";
|
||||
break;
|
||||
case 'cl_name':
|
||||
$sql_search .= "B.cl_name LIKE '%{$stx_escaped}%'";
|
||||
break;
|
||||
default: // '전체' 검색
|
||||
$sql_search .= " ( A.screen_code LIKE '%{$stx_escaped}%' OR A.group_code LIKE '%{$stx_escaped}%' OR A.resource_code LIKE '%{$stx_escaped}%' OR A.resource_desc LIKE '%{$stx_escaped}%' OR B.cl_name LIKE '%{$stx_escaped}%' ) ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 검색 조건에 맞는 모든 리소스를 한 번에 가져옴
|
||||
$sql = "SELECT A.*, B.cl_name
|
||||
FROM {$g5['ui_manager_table']} AS A
|
||||
LEFT JOIN {$g5['common_lang_table']} AS B
|
||||
ON (A.um_id = B.target_id AND B.target_table = '{$g5['ui_manager_table']}' AND B.lang_code = 'ko')
|
||||
{$sql_search}
|
||||
ORDER BY A.screen_code, A.group_code, A.resource_code";
|
||||
$result = sql_query($sql);
|
||||
|
||||
// 2. PHP에서 화면별로 그룹화
|
||||
$all_grouped_resources = [];
|
||||
$total_resource_count = 0;
|
||||
while ($row = sql_fetch_array($result)) {
|
||||
$all_grouped_resources[$row['screen_code']][] = $row;
|
||||
$total_resource_count++;
|
||||
}
|
||||
|
||||
// 3. 그룹화된 결과를 기준으로 페이징 처리
|
||||
$total_count = count($all_grouped_resources); // 전체 '화면' 수
|
||||
$total_page = ceil($total_count / $page_rows);
|
||||
$from_record = ($page - 1) * $page_rows;
|
||||
|
||||
// 현재 페이지에 해당하는 그룹만 잘라냄
|
||||
$paged_groups = array_slice($all_grouped_resources, $from_record, $page_rows, true);
|
||||
|
||||
$g5['title'] = 'UI 리소스 관리';
|
||||
include_once(G5_ADMIN_PATH . '/admin.head.php');
|
||||
|
||||
add_stylesheet('<link rel="stylesheet" href="' . G5_ADMIN_URL . '/code_manager/css/code_manager.css?ver=1.3">', 0);
|
||||
?>
|
||||
|
||||
<div class="local_desc01 local_desc">
|
||||
<p>
|
||||
웹사이트의 모든 화면에 사용되는 텍스트(라벨)와 선택 옵션(데이터)을 체계적으로 관리합니다.<br>
|
||||
'화면 코드' 별로 그룹화되어 표시되며, 각 그룹을 클릭하여 내용을 확인하거나 수정할 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 검색 폼 -->
|
||||
<section id="resource_search_form">
|
||||
<h2 class="h2_frm">리소스 검색</h2>
|
||||
<form name="fsearch" id="fsearch" method="get">
|
||||
<div class="search-form-inner">
|
||||
<label for="page_rows" class="sound_only">페이지당 개수</label>
|
||||
<select name="page_rows" id="page_rows" class="frm_input">
|
||||
<option value="15" <?php echo get_selected($page_rows, 15); ?>>15개씩</option>
|
||||
<option value="30" <?php echo get_selected($page_rows, 30); ?>>30개씩</option>
|
||||
<option value="50" <?php echo get_selected($page_rows, 50); ?>>50개씩</option>
|
||||
<option value="100" <?php echo get_selected($page_rows, 100); ?>>100개씩</option>
|
||||
</select>
|
||||
|
||||
<label for="sfl" class="sound_only">검색대상</label>
|
||||
<select name="sfl" id="sfl">
|
||||
<option value="all" <?php echo get_selected($sfl, 'all'); ?>>전체</option>
|
||||
<option value="screen_code" <?php echo get_selected($sfl, 'screen_code'); ?>>화면 코드</option>
|
||||
<option value="group_code" <?php echo get_selected($sfl, 'group_code'); ?>>그룹 코드</option>
|
||||
<option value="resource_code" <?php echo get_selected($sfl, 'resource_code'); ?>>리소스 코드</option>
|
||||
<option value="resource_desc" <?php echo get_selected($sfl, 'resource_desc'); ?>>설명</option>
|
||||
<option value="cl_name" <?php echo get_selected($sfl, 'cl_name'); ?>>라벨명</option>
|
||||
</select>
|
||||
|
||||
<label for="stx" class="sound_only">검색어</label>
|
||||
<input type="text" name="stx" value="<?php echo get_text($stx) ?>" id="stx" class="frm_input" size="30">
|
||||
<input type="submit" value="검색" class="btn_submit">
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section id="code_manager">
|
||||
<div class="code-manager-header">
|
||||
<h2 class="code-manager-title">UI 리소스 목록 (총 <?php echo number_format($total_count); ?>개 화면)</h2>
|
||||
<div class="code-manager-actions">
|
||||
<button type="button" id="add-resource-btn" class="btn btn_01">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i> 새 리소스 추가
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 새 리소스 추가 폼 -->
|
||||
<div id="resource-form-container" style="display: none;">
|
||||
<form name="fresourceform" id="fresourceform" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post">
|
||||
<!-- 💡 [핵심 수정 2] 신규 등록이므로 w 값을 비워둡니다. -->
|
||||
<input type="hidden" name="w" value="">
|
||||
<input type="hidden" name="token" value="<?php echo get_admin_token(); ?>">
|
||||
<div class="tbl_frm01 tbl_wrap">
|
||||
<table>
|
||||
<caption>UI 리소스 추가 폼</caption>
|
||||
<colgroup>
|
||||
<col class="grid_4">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><label for="screen_code">화면 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="screen_code" id="screen_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">리소스가 사용될 화면의 고유 코드 (예: order_form, member_join)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="group_code">그룹 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="group_code" id="group_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">화면 내에서 리소스를 묶어줄 그룹 코드 (예: address_info, common_options)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">리소스 타입</th>
|
||||
<td>
|
||||
<label><input type="radio" name="resource_type" value="LABEL" checked> UI 라벨 (단일 텍스트)</label>
|
||||
<label><input type="radio" name="resource_type" value="DATA"> 데이터 (선택 옵션)</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="resource-type-field" id="label-field">
|
||||
<th scope="row"><label for="cl_name">한국어 라벨명</label></th>
|
||||
<td>
|
||||
<input type="text" name="cl_name" id="cl_name" class="frm_input" size="50">
|
||||
<span class="frm_info">화면에 표시될 실제 텍스트 (예: 집의 유형, 창호 재질)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_code">리소스 코드</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_code" id="resource_code" required class="required frm_input" size="30">
|
||||
<span class="frm_info">개발자가 이 리소스를 호출할 때 사용할 고유 코드 (예: house_type_label, house_type_data)</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="resource_desc">설명</label></th>
|
||||
<td>
|
||||
<input type="text" name="resource_desc" id="resource_desc" class="frm_input" size="80">
|
||||
<span class="frm_info">이 리소스의 용도에 대한 설명 (관리자 참고용)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="btn_confirm01 btn_confirm">
|
||||
<button type="button" id="cancel-resource-btn" class="btn_cancel btn">취소</button>
|
||||
<input type="submit" value="리소스 등록" class="btn_submit btn" accesskey="s">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 아코디언 형태의 리소스 목록 -->
|
||||
<div id="resource-list-accordion">
|
||||
<?php if (count($paged_groups) == 0) : ?>
|
||||
<div class="empty_list">표시할 리소스가 없습니다.</div>
|
||||
<?php else : ?>
|
||||
<?php foreach ($paged_groups as $screen_code => $resources) : ?>
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header">
|
||||
<span class="screen-title"><i class="fa fa-desktop"></i> 화면: <strong><?php echo get_text($screen_code); ?></strong></span>
|
||||
<span class="resource-count"><?php echo count($resources); ?>개 리소스</span>
|
||||
<i class="fa fa-chevron-down accordion-icon"></i>
|
||||
</div>
|
||||
<div class="accordion-content">
|
||||
<div class="tbl_head01 tbl_wrap">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 15%;">
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 10%;">
|
||||
<col>
|
||||
<col style="width: 240px;">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">그룹 코드</th>
|
||||
<th scope="col">리소스 코드</th>
|
||||
<th scope="col">타입</th>
|
||||
<th scope="col">설명</th>
|
||||
<th scope="col">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($resources as $res) : ?>
|
||||
<tr>
|
||||
<td><?php echo get_text($res['group_code']); ?></td>
|
||||
<td><?php echo get_text($res['resource_code']); ?></td>
|
||||
<td>
|
||||
<?php if ($res['resource_type'] == 'LABEL'): ?>
|
||||
<span class="res-type-label">라벨</span>
|
||||
<?php else: ?>
|
||||
<span class="res-type-data">데이터</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="td_left"><?php echo get_text($res['resource_desc']); ?></td>
|
||||
<td class="td_mng td_mng_s">
|
||||
<?php if ($res['resource_type'] == 'DATA') : ?>
|
||||
<a href="./category_list.php?um_id=<?php echo $res['um_id']; ?>" class="btn btn_03">옵션 관리</a>
|
||||
<?php endif; ?>
|
||||
<a href="./ui_manager_form.php?w=u&um_id=<?php echo $res['um_id']; ?>&<?php echo $qstr; ?>" class="btn btn_02">수정</a>
|
||||
<a href="./lang_manager.php?target_table=<?php echo $g5['ui_manager_table']; ?>&target_id=<?php echo $res['um_id']; ?>" class="btn btn_01">다국어</a>
|
||||
<button type="button" class="btn btn_delete btn_delete_resource" data-um_id="<?php echo $res['um_id']; ?>">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- 페이징 링크 출력 -->
|
||||
<div class="pagination_wrap">
|
||||
<?php
|
||||
$paging_url = $_SERVER['SCRIPT_NAME'].'?'.$qstr;
|
||||
echo get_paging(G5_IS_MOBILE ? $config['cf_mobile_pages'] : $config['cf_write_pages'], $page, $total_page, $paging_url);
|
||||
?>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<script>
|
||||
var g5_admin_token = "<?php echo get_admin_token(); ?>";
|
||||
</script>
|
||||
<script src="<?php echo G5_ADMIN_URL; ?>/code_manager/js/ui_manager.js?ver=1.3"></script>
|
||||
|
||||
<?php
|
||||
include_once(G5_ADMIN_PATH . '/admin.tail.php');
|
||||
Reference in New Issue
Block a user