리펙토링 #6 참고

This commit is contained in:
Lectom C Han
2026-02-05 12:38:34 +09:00
parent 46b30af839
commit 7034a3643a
17 changed files with 76 additions and 369 deletions

View File

@@ -16,6 +16,18 @@ RewriteRule ^kngil/skin/adm\.php$ /admin [R=301,L]
RewriteCond %{THE_REQUEST} \s/+kngil/skin/index\.php [NC] RewriteCond %{THE_REQUEST} \s/+kngil/skin/index\.php [NC]
RewriteRule ^kngil/skin/index\.php$ / [R=301,L] RewriteRule ^kngil/skin/index\.php$ / [R=301,L]
# 레거시 /kngil/skin/*.skin.php -> /* (확장자 제거)
RewriteCond %{THE_REQUEST} \s/+kngil/skin/([^\s]+)\.skin\.php [NC]
RewriteRule ^kngil/skin/([^/]+)\.skin\.php$ /$1 [R=301,L]
# 레거시 /*.skin -> /* (확장자 제거)
RewriteCond %{THE_REQUEST} \s+/([^\s]+)\.skin [NC]
RewriteRule ^([^/]+)\.skin$ /$1 [R=301,L]
# 레거시 /kngil/*.skin -> /* (확장자 제거)
RewriteCond %{THE_REQUEST} \s/+kngil/([^\s]+)\.skin [NC]
RewriteRule ^kngil/([^/]+)\.skin$ /$1 [R=301,L]
# 레거시 /kngil/skin/*.php -> /* (확장자 제거) # 레거시 /kngil/skin/*.php -> /* (확장자 제거)
RewriteCond %{THE_REQUEST} \s/+kngil/skin/([^\s]+)\.php [NC] RewriteCond %{THE_REQUEST} \s/+kngil/skin/([^\s]+)\.php [NC]
RewriteRule ^kngil/skin/([^/]+)\.php$ /$1 [R=301,L] RewriteRule ^kngil/skin/([^/]+)\.php$ /$1 [R=301,L]
@@ -57,6 +69,11 @@ RewriteRule ^admin/api/faq/?$ /kngil/bbs/adm_faq_popup.php [QSA,L]
RewriteRule ^admin/api/faq/save/?$ /kngil/bbs/adm_faq_popup_save.php [QSA,L] RewriteRule ^admin/api/faq/save/?$ /kngil/bbs/adm_faq_popup_save.php [QSA,L]
RewriteRule ^admin/api/faq/delete/?$ /kngil/bbs/adm_faq_popup_delete.php [QSA,L] RewriteRule ^admin/api/faq/delete/?$ /kngil/bbs/adm_faq_popup_delete.php [QSA,L]
# Q&A 라우팅 (컨트롤러 우선)
RewriteRule ^qa_list/?$ /kngil/bbs/qa_list.php [QSA,L]
RewriteRule ^qa_detail/?$ /kngil/bbs/qa_detail.php [QSA,L]
RewriteRule ^qa_write/?$ /kngil/bbs/qa_write.php [QSA,L]
# 루트 페이지 라우팅: / -> index, /{page} -> /kngil/skin/{page}.php # 루트 페이지 라우팅: / -> index, /{page} -> /kngil/skin/{page}.php
RewriteRule ^$ /kngil/skin/index.php [L] RewriteRule ^$ /kngil/skin/index.php [L]
RewriteRule ^([^/]+)$ /kngil/skin/$1.php [L] RewriteRule ^([^/]+)$ /kngil/skin/$1.php [L]

View File

@@ -1,6 +1,7 @@
<?php <?php
// /kngil/auth/oidc-callback.php // /kngil/auth/oidc-callback.php
session_start(); require_once dirname(__DIR__) . '/bbs/env.php';
kngil_start_session();
ini_set('log_errors', '1'); ini_set('log_errors', '1');
ini_set('error_log', '/proc/self/fd/2'); ini_set('error_log', '/proc/self/fd/2');
require_once dirname(__DIR__) . '/vendor/autoload.php'; require_once dirname(__DIR__) . '/vendor/autoload.php';

View File

@@ -57,3 +57,25 @@ function kngil_load_env_once(string $path): void
$_SERVER[$name] = $value; $_SERVER[$name] = $value;
} }
} }
// 세션 쿠키 경로를 루트로 고정해 경로 변경 시 로그인 상태가 유지되도록 합니다.
function kngil_start_session(): void
{
if (session_status() !== PHP_SESSION_NONE) {
return;
}
$params = session_get_cookie_params();
$samesite = $params['samesite'] ?? 'Lax';
session_set_cookie_params([
'lifetime' => $params['lifetime'],
'path' => '/',
'domain' => $params['domain'],
'secure' => $params['secure'],
'httponly' => $params['httponly'],
'samesite' => $samesite,
]);
session_start();
}

View File

@@ -1,5 +1,6 @@
<?php <?php
session_start(); require_once __DIR__ . '/env.php';
kngil_start_session();
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php'; require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);

View File

@@ -5,7 +5,8 @@
* - secret_key: MY_SECRET_KEY * - secret_key: MY_SECRET_KEY
*/ */
session_start(); require_once __DIR__ . '/env.php';
kngil_start_session();
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php'; require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
@@ -209,4 +210,4 @@ try {
'error' => true, 'error' => true,
'message' => $e->getMessage() 'message' => $e->getMessage()
], JSON_UNESCAPED_UNICODE); ], JSON_UNESCAPED_UNICODE);
} }

View File

@@ -14,7 +14,7 @@ if (session_status() === PHP_SESSION_NONE) {
if (empty($_SESSION['login'])) { if (empty($_SESSION['login'])) {
echo "<script> echo "<script>
alert('로그인 후 이용 가능합니다.'); alert('로그인 후 이용 가능합니다.');
location.href = '/qa_list.skin'; location.href = '/qa_list';
</script>"; </script>";
exit; exit;
} }
@@ -92,7 +92,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
$pdo->commit(); $pdo->commit();
header("Location: /qa_list.skin"); header("Location: /qa_list");
exit; exit;
} catch (Exception $e) { } catch (Exception $e) {
@@ -230,4 +230,4 @@ $isOwner = ($post['user_id'] === $me);
/* =============================== /* ===============================
12. 스킨 렌더링 12. 스킨 렌더링
=============================== */ =============================== */
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_detail.skin.php'; include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_detail.php';

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /**
* Q&A 리스트 컨트롤러 * Q&A 리스트 컨트롤러
* - 스킨: /kngil/skin/qa_list.skin.php (URL: /qa_list.skin) * - 스킨: /kngil/skin/qa_list.php (URL: /qa_list)
*/ */
ini_set('display_errors', 1); ini_set('display_errors', 1);
@@ -149,4 +149,4 @@ $totalPages = (int)ceil($totalCount / $pageSize);
/* ========================= /* =========================
7. 스킨 렌더링 7. 스킨 렌더링
========================= */ ========================= */
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_list.skin.php'; include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_list.php';

View File

@@ -42,7 +42,7 @@ try {
]); ]);
// 상세 페이지로 복귀 // 상세 페이지로 복귀
header("Location: /kngil/bbs/qa_detail.php?id={$postId}"); header("Location: /qa_detail?id={$postId}");
exit; exit;
} catch (Exception $e) { } catch (Exception $e) {

View File

@@ -17,7 +17,7 @@ if (session_status() === PHP_SESSION_NONE) {
if (empty($_SESSION['login'])) { if (empty($_SESSION['login'])) {
echo "<script> echo "<script>
alert('로그인이 필요합니다.'); alert('로그인이 필요합니다.');
location.href = '/qa_list.skin'; location.href = '/qa_list';
</script>"; </script>";
exit; exit;
} }
@@ -216,7 +216,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
handle_file_uploads($pdo, $postId); handle_file_uploads($pdo, $postId);
} }
header("Location: /kngil/bbs/qa_detail.php?id={$postId}"); header("Location: /qa_detail?id={$postId}");
exit; exit;
} catch (Exception $e) { } catch (Exception $e) {
@@ -228,4 +228,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
/* =============================== /* ===============================
7. 화면 출력 7. 화면 출력
=============================== */ =============================== */
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_write.skin.php'; include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_write.php';

View File

@@ -1,9 +1,6 @@
<?php <?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/../bbs/env.php'; require_once __DIR__ . '/../bbs/env.php';
kngil_start_session();
kngil_load_env_once(dirname(__DIR__, 2) . '/.env'); kngil_load_env_once(dirname(__DIR__, 2) . '/.env');
$isLogin = isset($_SESSION['login']); $isLogin = isset($_SESSION['login']);
@@ -229,7 +226,7 @@ $isCompanyAdmin = in_array($auth, ['BS100100', 'BS100200', 'BS100300', 'BS100400
<div class="floating-menu"> <div class="floating-menu">
<ul> <ul>
<li class="floating-faq"> <li class="floating-faq">
<a href="/qa_list.skin"> <a href="/qa_list">
<i class="ico-faq"></i> <i class="ico-faq"></i>
<span>Q&A</span> <span>Q&A</span>
</a> </a>

View File

@@ -82,7 +82,7 @@
</ul> </ul>
</div> </div>
<div class="btn-wrap"> <div class="btn-wrap">
<a href="/faq_list.skin" class="btn-contact"> <a href="/faq_list" class="btn-contact">
<i class="ico-contact"></i> <i class="ico-contact"></i>
KNGIL 구매문의 KNGIL 구매문의
</a> </a>

View File

@@ -63,10 +63,10 @@
<ul class="sub-tab"> <ul class="sub-tab">
<li class="on"> <li class="on">
<a href="/faq_list.skin">자주하는 질문(FAQ)</a> <a href="/faq_list">자주하는 질문(FAQ)</a>
</li> </li>
<li> <li>
<a href="/kngil/bbs/qa_list.php">문의하기(Q&A)</a> <a href="/qa_list">문의하기(Q&A)</a>
</li> </li>
<li> <li>
<a href="https://939.co.kr/saman/" target="_blank">원격지원</a> <a href="https://939.co.kr/saman/" target="_blank">원격지원</a>

View File

@@ -29,7 +29,7 @@
if (!$isLogin) { if (!$isLogin) {
echo "<script> echo "<script>
alert('로그인 후 문의 등록이 가능합니다.'); alert('로그인 후 문의 등록이 가능합니다.');
location.href = '/qa_list.skin'; location.href = '/qa_list';
</script>"; </script>";
exit; exit;
} }
@@ -56,8 +56,8 @@
<p class="sub-txt">KNGIL 관련 문의하기</p> <p class="sub-txt">KNGIL 관련 문의하기</p>
</div> </div>
<ul class="sub-tab"> <ul class="sub-tab">
<li><a href="/faq_list.skin">자주하는 질문(FAQ)</a></li> <li><a href="/faq_list">자주하는 질문(FAQ)</a></li>
<li class="on"><a href="/kngil/bbs/qa_list.php">문의하기(Q&A)</a></li> <li class="on"><a href="/qa_list">문의하기(Q&A)</a></li>
<li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li> <li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li>
</ul> </ul>
</section> </section>
@@ -196,11 +196,11 @@
<!-- 수정 버튼 (로그인 사용자 == 작성자 경우에만) --> <!-- 수정 버튼 (로그인 사용자 == 작성자 경우에만) -->
<?php if ($me === $_SESSION['login']['user_id'] ?? ''): ?> <?php if ($me === $_SESSION['login']['user_id'] ?? ''): ?>
<button class="btn-secondary" onclick="location.href='/kngil/bbs/qa_write.php?id=<?= $post['post_id'] ?>'">수정</button> <button class="btn-secondary" onclick="location.href='/qa_write?id=<?= $post['post_id'] ?>'">수정</button>
<button class="btn-secondary" id="btn-delete" data-status="<?= $post['stat_bc'] ?>" data-id="<?= $post['post_id'] ?>">삭제</button> <button class="btn-secondary" id="btn-delete" data-status="<?= $post['stat_bc'] ?>" data-id="<?= $post['post_id'] ?>">삭제</button>
<?php endif; ?> <?php endif; ?>
<!-- <button onclick="history.back()">닫기</button> --> <!-- <button onclick="history.back()">닫기</button> -->
<button class="btn-primary" onclick="location.href='/kngil/bbs/qa_list.php'"> <button class="btn-primary" onclick="location.href='/qa_list'">
<i class="fa fa-list" aria-hidden="true"></i> 목록</button> <i class="fa fa-list" aria-hidden="true"></i> 목록</button>
</div> </div>
@@ -324,7 +324,7 @@
const form = document.createElement('form'); const form = document.createElement('form');
form.method = 'post'; form.method = 'post';
form.action = "/kngil/bbs/qa_detail.php"; // ✅ 중요 form.action = "/qa_detail"; // ✅ 중요
const actionInput = document.createElement('input'); const actionInput = document.createElement('input');
actionInput.type = 'hidden'; actionInput.type = 'hidden';

View File

@@ -56,8 +56,8 @@
<p class="sub-txt">KNGIL 관련 문의하기</p> <p class="sub-txt">KNGIL 관련 문의하기</p>
</div> </div>
<ul class="sub-tab"> <ul class="sub-tab">
<li><a href="/faq_list.skin">자주하는 질문(FAQ)</a></li> <li><a href="/faq_list">자주하는 질문(FAQ)</a></li>
<li class="on"><a href="/kngil/bbs/qa_list.php">문의하기(Q&A)</a></li> <li class="on"><a href="/qa_list">문의하기(Q&A)</a></li>
<li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li> <li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li>
</ul> </ul>
</section> </section>
@@ -142,7 +142,7 @@
$rowNumber = $totalIndex - $idx; // 연속 번호 재계산 $rowNumber = $totalIndex - $idx; // 연속 번호 재계산
?> ?>
<?php $isNotice = ($row['category'] === 'notice'); ?> <?php $isNotice = ($row['category'] === 'notice'); ?>
<tr class="<?= $isNotice ? 'row-notice' : '' ?>" onclick="location.href='/kngil/bbs/qa_detail.php?id=<?= urlencode($row['post_id']) ?>'" style="cursor:pointer;"> <tr class="<?= $isNotice ? 'row-notice' : '' ?>" onclick="location.href='/qa_detail?id=<?= urlencode($row['post_id']) ?>'" style="cursor:pointer;">
<!-- 번호: 공지 or 연속번호 --> <!-- 번호: 공지 or 연속번호 -->
<td><?= $isNotice ? '공지' : $rowNumber ?></td> <td><?= $isNotice ? '공지' : $rowNumber ?></td>
<!-- 구분 --> <!-- 구분 -->
@@ -233,7 +233,7 @@
</div> </div>
<?php endif ?> <?php endif ?>
<div class="btn-wrap right"> <div class="btn-wrap right">
<button type="button" class="btn-primary" onclick="location.href='/qa_write.skin'"> <button type="button" class="btn-primary" onclick="location.href='/qa_write'">
<i class="fa fa-pencil" aria-hidden="true"></i> 문의등록 <i class="fa fa-pencil" aria-hidden="true"></i> 문의등록
</button> </button>
</div> </div>
@@ -247,7 +247,7 @@
</div><!-- contents END /egbim1/skin/qa/basic/descope_qa_write.skin.php--> </div><!-- contents END /egbim1/skin/qa/basic/descope_qa_write.php-->
</div><!-- container END --> </div><!-- container END -->
<button class="btn_top js__top topbtn_on" onclick="window.scrollTo(0,0);" style="bottom:60px;"><div class="arrow"></div></button> <button class="btn_top js__top topbtn_on" onclick="window.scrollTo(0,0);" style="bottom:60px;"><div class="arrow"></div></button>
@@ -328,7 +328,7 @@ $(document).on("click", ".btn-move", function() {
alert("Q&A ID를 입력하세요."); alert("Q&A ID를 입력하세요.");
return; return;
} }
location.href = "/kngil/bbs/qa_detail.php?id=" + qnaId; location.href = "/qa_detail?id=" + qnaId;
}); });
$("#qna-id-search").on("keypress", function(e){ $("#qna-id-search").on("keypress", function(e){

View File

@@ -1,332 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<?php include __DIR__ . "/_head.php"; ?>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Q&A 게시판 리스트</title>
<link rel="stylesheet" href="/kngil/css/qa/font-awesome.min.css?ver=2303229">
<!-- 디자인팀 작성 -->
<script src="/kngil/js/lib/jquery-3.6.1.min.js" type="text/javascript"></script>
<script src="/kngil/js/qa/jquery.mousewheel.min.js" type="text/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollToPlugin.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.1/dist/aos.css" type="text/css"/>
<link rel="stylesheet" href="https://unpkg.com/lenis@1.1.9/dist/lenis.css">
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
<script src="https://unpkg.com/lenis@1.1.9/dist/lenis.min.js"></script>
<!-- <script src="/kngil/js/qa/qa_popup.js" type="text/javascript"></script>
<script src="/kngil/js/qa/qa_common.js" type="text/javascript"></script>
<script src="/kngil/js/qa/qa_index.js" type="text/javascript"></script> -->
<link rel="stylesheet" href="/kngil/css/qa/qa_reset.css"/>
<link rel="stylesheet" href="/kngil/css/qa/qa_font.css"/>
<link rel="stylesheet" href="/kngil/css/qa/qa_style.css"/>
<!-- <link rel="stylesheet" href="/kngil/css/style.css"/> -->
<!-- //디자인팀 작성 -->
</head>
<body>
<div class="wrapper">
<!-- HEADER -->
<?php include __DIR__ . "/_header.php"; ?>
<!-- //HEADER -->
<?php
include __DIR__ . "/pop_join.php";
include __DIR__ . "/pop_agreement.php";
include __DIR__ . "/pop_mypage01.php";
include __DIR__ . "/pop_mypage02.php";
include __DIR__ . "/pop_mypage03.php";
include __DIR__ . "/pop_password.php";
include __DIR__ . "/pop_privacy.php";
include __DIR__ . "/pop_search.php";
// include __DIR__ . "/_nav.php";
?>
<?php
$search = $search ?? '';
$cats = $cats ?? [];
$writer = $writer ?? '';
$status = $status ?? 'all';
?>
<div class="qa-container container faq">
<section class="intro">
<div class="top js__dark">
<h2 data-aos="fade-down" data-aos-duration="1000">Q&amp;A</h2>
<span>EG-BIM 관련 문의하기</span>
</div>
<ul class="sub_tab">
<li><a href="/faq_list.skin">자주하는 질문(FAQ)</a></li>
<li class="on"><a href="/kngil/bbs/qa_list.php">문의하기(Q&A)</a></li>
<li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li>
</ul>
</section>
<span class="sub_tit">문의하기(Q&A)</span>
<div class="contents">
<form class="qa-controls" method="get" action="">
<div class="search-wrap">
<div class="qa-filters">
<div class="check-group">
<!-- <strong>구분</strong> -->
<?php
// 선택 여부 유틸
$isChecked = function($v) use ($cats) {
return in_array($v, $cats ?? [], true) ? 'checked' : '';
};
// 아무 것도 선택 안되어 있으면 전체 on
$allOn = empty($cats);
?>
<label><input type="checkbox" name="cat[]" value="전체"> 전체</label>
<label><input type="checkbox" name="cat[]" value="일반문의"> 일반</label>
<label><input type="checkbox" name="cat[]" value="개선문의"> 개선</label>
<label><input type="checkbox" name="cat[]" value="오류문의"> 오류</label>
<?php if (!empty($_SESSION['login'])): ?>
<label><input type="checkbox" name="cat[]" value="관리글"> 관리</label>
<?php endif; ?>
</div>
<div class="check-box">
<strong>작성자</strong>
<label><input type="checkbox" name="writer" value="me" <?= $writer==='me' ?'checked':'' ?>> 내가 작성한 글</label>
</div>
<?php if (!empty($_SESSION['login'])): ?>
<?php $status = $_GET['status'] ?? 'all'; ?>
<div class="check-box1" style="margin-left:20px;">
<strong>상태</strong>
<select name="status" class="status-select">
<option value="all" <?= $status==='all'?'selected':'' ?>>전체</option>
<option value="wait" <?= $status==='wait'?'selected':'' ?>>문의접수</option>
<option value="review"<?= $status==='review'?'selected':'' ?>>문의검토</option>
<option value="deep" <?= $status==='deep'?'selected':'' ?>>정밀검토</option>
<option value="patch" <?= $status==='patch'?'selected':'' ?>>패치예정</option>
<option value="done" <?= $status==='done'?'selected':'' ?>>답변완료</option>
</select>
</div>
<?php endif; ?>
</div>
<div class="qa-search search-box">
<?php if (!empty($_SESSION['login'])): ?>
<input type="number" class="qna-id-input" placeholder="Q&A ID">
<button type="button" class="btn-move">이동</button>
<?php endif; ?>
<input type="text" name="q" value="<?= htmlspecialchars($search) ?>" placeholder="제목+내용 검색어를 입력하세요">
<button type="submit" class="btn-search">
<i class="fa fa-search"></i> 검색
</button>
</div>
</div>
</form>
<div class="tbl-wrap">
<table>
<colgroup>
<col style="width:5%"><col style="width:7%"><col style="width:12%"><col style="width:12%">
<col style="width:7%"><col style="width:auto"><col style="width:9%"><col style="width:9%">
</colgroup>
<thead>
<tr>
<th>번호</th><th>구분</th><th>회사</th><th>부서</th>
<th>작성자</th><th>제목</th><th>등록일</th><th>상태</th>
</tr>
</thead>
<tbody>
<?php
$totalIndex = $totalCount - ($page - 1) * $pageSize;
$idx = 0;
?>
<?php foreach($posts as $row): ?>
<?php
$isNotice = ($row['category'] === 'notice');
$rowNumber = $totalIndex - $idx; // 연속 번호 재계산
?>
<?php $isNotice = ($row['category'] === 'notice'); ?>
<tr class="<?= $isNotice ? 'row-notice' : '' ?>" onclick="location.href='/kngil/bbs/qa_detail.php?id=<?= urlencode($row['post_id']) ?>'" style="cursor:pointer;">
<!-- 번호: 공지 or 연속번호 -->
<td><?= $isNotice ? '공지' : $rowNumber ?></td>
<!-- 구분 -->
<td><?= htmlspecialchars($row['category']) ?></td>
<!-- 회사 -->
<td><?= htmlspecialchars($row['display_company']) ?></td>
<!-- 부서 -->
<td><?= htmlspecialchars($row['dept_nm'] ?? '') ?></td>
<!-- 작성자 -->
<td><?= htmlspecialchars($row['display_name']) ?></td>
<!-- 제목 -->
<td class="left">
<?php if (!empty($row['is_secret'])): ?>
<span style="color:#999">[비밀글]</span>
<?php endif; ?>
<span class="title-text">
<?= htmlspecialchars($row['title']) ?>
</span>
<!-- 댓글 개수 -->
<?php if (!empty($row['comment_count'])): ?>
<span class="badge badge-comment" style="color:#007bff; margin-left:5px;">
<i class="fa fa-commenting-o"></i> <?= $row['comment_count'] ?>
</span>
<?php endif; ?>
<!-- 첨부파일 개수 -->
<?php if (!empty($row['file_count'])): ?>
<span class="badge badge-file" style="color:#28a745; margin-left:5px;">
<i class="fa fa-paperclip"></i> <?= $row['file_count'] ?>
</span>
<?php endif; ?>
</td>
<!-- 등록일 -->
<td><?= htmlspecialchars(substr($row['created_at'],0,10)) ?></td>
<!-- 상태 -->
<td>
<?php if ($row['category'] === 'notice'): ?>
<!-- 공지사항이면 상태값 안 보여줌 -->
<span></span>
<?php else: ?>
<span class="status-<?= htmlspecialchars($row['status']) ?>">
<?= $row['status']==='wait' ? '문의접수'
: ($row['status']==='review' ? '문의검토'
: ($row['status']==='deep' ? '정밀검토'
: ($row['status']==='patch' ? '패치예정'
: ($row['status']==='done' ? '답변완료'
: '')))) ?>
</span>
<?php endif; ?>
</td>
</tr>
<?php $idx++; ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($totalPages > 1): ?>
<div class="pagination">
<?php if ($page > 1): ?>
<a href="?<?= http_build_query(array_merge($_GET, ['page'=>$page-1])) ?>" class="prev">이전</a>
<?php else: ?><span class="prev">이전</span><?php endif ?>
<?php
$blockSize = 10;
$currentBlock= ceil($page / $blockSize);
$start = ($currentBlock - 1) * $blockSize + 1;
$end = min($totalPages, $currentBlock * $blockSize);
for ($i = $start; $i <= $end; $i++):
?>
<?php if ($i == $page): ?>
<!-- ✅ 여기! 현재 페이지는 span.current -->
<span class="current"><?= $i ?></span>
<?php else: ?>
<a href="?<?= http_build_query(array_merge($_GET, ['page'=>$i])) ?>"><?= $i ?></a>
<?php endif ?>
<?php endfor ?>
<?php if ($page < $totalPages): ?>
<a href="?<?= http_build_query(array_merge($_GET, ['page'=>$page+1])) ?>" class="next">다음</a>
<?php else: ?><span class="next">다음</span><?php endif ?>
</div>
<?php endif ?>
<div class="btn-group">
<button type="button" class="btn btn-write" onclick="location.href='/qa_write.skin'">
<i class="fa fa-pencil" aria-hidden="true"></i> 문의등록
</button>
</div>
</div><!-- contents END /egbim1/skin/qa/basic/descope_qa_write.skin.php-->
</div><!-- container END -->
<button class="btn_top js__top topbtn_on" onclick="window.scrollTo(0,0);" style="bottom:60px;"><div class="arrow"></div></button>
<!-- FOOTER -->
<?php include __DIR__ . "/_footer.php"; ?>
<!-- //FOOTER -->
</div><!-- wrapper END -->
<script src="/kngil/js/index.js"></script>
<script src="/kngil/js/mypage.js"></script>
<script src="/kngil/js/join.js"></script>
<script src="/kngil/js/login_sms.js"></script>
<script>
// AOS / Lenis 초기화 (안전 가드)
try {
AOS.init();
if (typeof Lenis !== 'undefined') {
const lenis = new Lenis();
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time)=>{ lenis.raf(time * 1000) });
gsap.ticker.lagSmoothing(0);
window.lenis = lenis; // 다른 코드에서 접근할 수 있게
}
} catch(e) { console.error(e); }
</script>
<script>
// ===== 공용 유틸 =====
function getQueryString(name){
// 페이지 구성 요소가 없을 수 있으므로 가드
const intro = document.querySelector('.intro_wrap');
if (intro) intro.style.display = "none";
const mainMask = document.querySelector('.main_mask');
if (mainMask) mainMask.classList.add('skip');
return new URLSearchParams(window.location.search).get(name);
}
// 필터 변경 시 자동 제출
(function(){
const form = document.querySelector('.qa-controls');
const boxes = Array.from(document.querySelectorAll('.qa-controls input[name="cat[]"]'));
const writer = document.querySelector('.qa-controls input[name="writer"]');
function submitForm(){ form && form.submit(); }
function syncAllToggle(changed){
const allBox = boxes.find(b => b.value === 'all');
const itemBoxes = boxes.filter(b => b.value !== 'all');
if (!allBox) return;
if (changed && changed.value === 'all') {
// 전체 체크 시 개별은 해제
if (allBox.checked) itemBoxes.forEach(b => b.checked = false);
} else {
// 개별 체크 시 전체 해제
if (itemBoxes.some(b => b.checked)) allBox.checked = false;
// 개별이 전부 해제되면 전체 자동 체크
if (!itemBoxes.some(b => b.checked)) allBox.checked = true;
}
}
boxes.forEach(b => {
b.addEventListener('change', function(){ syncAllToggle(this); submitForm(); });
});
if (writer) writer.addEventListener('change', submitForm);
})();
// Q&A ID 검색
$(document).on("click", ".btn-move", function() {
const qnaId = $(".qna-id-input").val().trim();
if (!qnaId) {
alert("Q&A ID를 입력하세요.");
return;
}
location.href = "/kngil/bbs/qa_detail.php?id=" + qnaId;
});
$("#qna-id-search").on("keypress", function(e){
if(e.key === "Enter"){
$("#qna-id-btn").click();
}
});
</script>

View File

@@ -46,7 +46,7 @@
if (!$isLogin) { if (!$isLogin) {
echo "<script> echo "<script>
alert('로그인 후 문의 등록이 가능합니다.'); alert('로그인 후 문의 등록이 가능합니다.');
location.href = '/qa_list.skin'; location.href = '/qa_list';
</script>"; </script>";
exit; exit;
} }
@@ -70,15 +70,15 @@
<p class="sub-txt">KNGIL 관련 문의하기</p> <p class="sub-txt">KNGIL 관련 문의하기</p>
</div> </div>
<ul class="sub-tab"> <ul class="sub-tab">
<li><a href="/faq_list.skin">자주하는 질문(FAQ)</a></li> <li><a href="/faq_list">자주하는 질문(FAQ)</a></li>
<li class="on"><a href="/kngil/bbs/qa_list.php">문의하기(Q&A)</a></li> <li class="on"><a href="/qa_list">문의하기(Q&A)</a></li>
<li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li> <li><a href="https://939.co.kr/saman/" target="_blank">원격지원</a></li>
</ul> </ul>
</section> </section>
<section class="sub-content"> <section class="sub-content">
<h3 class="sub-tit">문의하기(Q&A)</h3> <h3 class="sub-tit">문의하기(Q&A)</h3>
<form id="qaForm" <form id="qaForm"
action="/kngil/bbs/qa_write.php<?= $isEdit ? '?id=' . $post['post_id'] : '' ?>" action="/qa_write<?= $isEdit ? '?id=' . $post['post_id'] : '' ?>"
method="POST" method="POST"
enctype="multipart/form-data"> enctype="multipart/form-data">
<div class="form-area"> <div class="form-area">