Q&A 문의 공개범위 기능 추가
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

- 공개범위 설정 기능 개발(ALL/ORG/PRIVATE) - 게시물/댓글 정교화
- 요청 및 DB 처리 확장 - UI, DTO, Service 계층 업데이트
- 감사 로그 및 조회수 처리 로직 추가
This commit is contained in:
Rinjae
2026-07-13 11:32:34 +09:00
parent 9c01db9d00
commit a97378b84d
21 changed files with 721 additions and 63 deletions
+112
View File
@@ -6934,6 +6934,37 @@ button.djb-comment-submit:disabled {
font-size: 13px;
}
.djb-comment-private-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
margin-right: auto;
color: #6B7280;
font-size: 13px;
cursor: pointer;
}
.djb-comment-private-tag {
display: inline-block;
margin-left: 6px;
padding: 1px 8px;
border-radius: 10px;
background-color: #FEF3C7;
color: #92400E;
font-size: 11px;
vertical-align: middle;
}
.djb-comment-item--private {
background-color: #FFFBEB;
}
.djb-comment-item--private-hidden .djb-comment-body,
.djb-comment-item--private-hidden .djb-comment-writer {
color: #9CA3AF;
font-style: italic;
}
.hero-carousel-section {
position: relative;
width: 100%;
@@ -15565,6 +15596,87 @@ input[type=checkbox]:checked + .custom-checkbox {
}
}
.list-table-row--private {
opacity: 0.55;
cursor: default;
}
.list-table-row--private .inquiry-private-label {
color: #94A3B8;
font-style: italic;
}
.notice-title-link--disabled {
pointer-events: none;
cursor: default;
}
.inquiry-detail-views {
color: #94A3B8;
font-size: 13px;
}
.inquiry-detail-attach {
margin-top: 16px;
}
.inquiry-detail-attach .inquiry-attach-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 14px;
border: 1px solid #CBD5E1;
border-radius: 6px;
color: #1E40AF;
font-size: 13px;
text-decoration: none;
}
.inquiry-detail-attach .inquiry-attach-link:hover {
background-color: #F1F5F9;
}
.row-cell--writer {
flex-direction: column;
justify-content: center;
line-height: 1.3;
}
.row-cell--writer .inquiry-writer-org {
color: #94A3B8;
font-size: 12px;
}
.inquiry-visibility-notice {
margin-left: 12px;
font-size: 13px;
font-weight: normal;
color: #64748B;
}
.list-table-body .inquiry-status-badge {
height: 24px;
padding: 0 10px;
font-size: 12px;
}
.inquiry-lock-icon {
vertical-align: -2px;
margin-right: 3px;
color: #64748B;
}
.inquiry-detail-visibility {
display: inline-flex;
align-items: center;
gap: 2px;
color: #64748B;
font-size: 13px;
}
.inquiry-detail-visibility--private {
color: #c0392b;
font-weight: 600;
}
.inquiry-detail-visibility--private .inquiry-lock-icon {
color: #c0392b;
}
.org-register-page {
min-height: 100vh;
padding: 0;
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@
const formEl = document.getElementById('djbCommentForm');
const inputEl = document.getElementById('djbCommentInput');
const counterEl = document.getElementById('djbCommentCharCounter');
const privateEl = document.getElementById('djbCommentPrivate');
function getCsrfToken() {
// 세션 기반 CSRF: 쿠키 대신 <meta name="_csrf">에서 토큰을 읽는다.
@@ -74,14 +75,25 @@
}
comments.forEach(function (c) {
const li = document.createElement('li');
li.className = 'djb-comment-item' + (c.adminYn === 'Y' ? ' djb-comment-item--admin' : '');
var cls = 'djb-comment-item';
if (c.adminYn === 'Y') cls += ' djb-comment-item--admin';
if (c.privatePlaceholder) cls += ' djb-comment-item--private-hidden';
else if (c.privateComment) cls += ' djb-comment-item--private';
li.className = cls;
li.setAttribute('data-comment-id', c.id);
var writerHtml = (c.adminYn === 'Y')
? '<span class="djb-comment-admin-badge">관리자</span>'
: '<span class="djb-comment-writer">' + escapeHtml(c.writerName || '(알 수 없음)') + '</span>';
// 비공개 댓글(열람 권한 있는 경우)에는 "비공개" 태그 표시
var privateTag = (c.privateComment && !c.privatePlaceholder)
? '<span class="djb-comment-private-tag">비공개</span>' : '';
li.innerHTML = ''
+ '<div class="djb-comment-meta">'
+ ' <div class="djb-comment-meta-left">'
+ (c.adminYn === 'Y'
? ' <span class="djb-comment-admin-badge">관리자</span>'
: ' <span class="djb-comment-writer">' + escapeHtml(c.writerName || '(알 수 없음)') + '</span>')
+ writerHtml
+ privateTag
+ ' </div>'
+ ' <div class="djb-comment-meta-right">'
+ ' <span class="djb-comment-date">' + escapeHtml(formatDate(c.createdDate)) + '</span>'
@@ -112,9 +124,10 @@
inputEl.focus();
return;
}
var visibility = (privateEl && privateEl.checked) ? 'PRIVATE' : 'ALL';
fetchJson('/djb/inquiry/' + encodeURIComponent(inquiryId) + '/comments', {
method: 'POST',
body: JSON.stringify({ content: content })
body: JSON.stringify({ content: content, visibility: visibility })
})
.then(function (res) {
if (res.status === 409) throw new Error('종료된 문의에는 댓글을 작성할 수 없습니다.');
@@ -123,6 +136,7 @@
})
.then(function () {
inputEl.value = '';
if (privateEl) privateEl.checked = false;
updateCounter();
load();
})
@@ -254,3 +254,41 @@ button.djb-comment-submit {
color: #6B7280;
font-size: 13px;
}
// ── 260710 댓글 공개범위 ──────────────────────────────
// 작성 폼 비공개 토글
.djb-comment-private-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
margin-right: auto;
color: #6B7280;
font-size: 13px;
cursor: pointer;
}
// 비공개 댓글 태그 (열람 권한 있는 사용자에게 표시)
.djb-comment-private-tag {
display: inline-block;
margin-left: 6px;
padding: 1px 8px;
border-radius: 10px;
background-color: #FEF3C7;
color: #92400E;
font-size: 11px;
vertical-align: middle;
}
// 비공개 댓글 (열람 권한 있음) 배경 강조
.djb-comment-item--private {
background-color: #FFFBEB;
}
// 열람 권한 없는 비공개 댓글 (placeholder)
.djb-comment-item--private-hidden {
.djb-comment-body,
.djb-comment-writer {
color: #9CA3AF;
font-style: italic;
}
}
@@ -692,3 +692,101 @@
// Uses the same action button styles from .inquiry-actions above
// Supports: action-btn-primary, action-btn-secondary
}
// ── 260710 공개범위 / 조회수 / 첨부 ──────────────────────────────
// 비공개 게시물(목록) — 본인·소속 법인 관리자 외에는 흐리게 + 링크 비활성
.list-table-row--private {
opacity: 0.55;
cursor: default;
.inquiry-private-label {
color: #94A3B8;
font-style: italic;
}
}
// 접근 권한 없는 비공개 글 제목 — 클릭 불가
.notice-title-link--disabled {
pointer-events: none;
cursor: default;
}
// 상세 조회수
.inquiry-detail-views {
color: #94A3B8;
font-size: 13px;
}
// 상세 첨부 다운로드 링크 (이미지 인라인 노출 없이 강제 다운로드)
.inquiry-detail-attach {
margin-top: $spacing-md;
.inquiry-attach-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 14px;
border: 1px solid #CBD5E1;
border-radius: 6px;
color: #1E40AF;
font-size: 13px;
text-decoration: none;
&:hover {
background-color: #F1F5F9;
}
}
}
// 목록 작성자 셀: 이름 아래 (법인명) 표기
// .row-cell 은 display:flex(가로) 이므로 세로 정렬 위해 column 지정
.row-cell--writer {
flex-direction: column;
justify-content: center;
line-height: 1.3;
.inquiry-writer-org {
color: #94A3B8;
font-size: 12px;
}
}
// 목록 상단 PTL_PROPERTY 공개범위 상한 표기
.inquiry-visibility-notice {
margin-left: 12px;
font-size: 13px;
font-weight: normal;
color: #64748B;
}
// 목록 처리상태 배지 — 글자/크기 축소
.list-table-body .inquiry-status-badge {
height: 24px;
padding: 0 10px;
font-size: 12px;
}
// 비공개 글 자물쇠 아이콘 (목록 제목 앞)
.inquiry-lock-icon {
vertical-align: -2px;
margin-right: 3px;
color: #64748B;
}
// 상세 헤더 공개범위 표기
.inquiry-detail-visibility {
display: inline-flex;
align-items: center;
gap: 2px;
color: #64748B;
font-size: 13px;
&--private {
color: #c0392b;
font-weight: 600;
.inquiry-lock-icon {
color: #c0392b;
}
}
}