Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c29c8a466 | |||
| d2052d0e16 | |||
| 9c4f3cfb04 | |||
| 71f4cb6f79 | |||
| 171feee9ea |
+5
-6
@@ -135,7 +135,6 @@ sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src/main/java'
|
||||
srcDir 'src/main/java/djb'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,11 +150,11 @@ compileJava {
|
||||
}
|
||||
|
||||
processResources {
|
||||
exclude { details ->
|
||||
details.file.name.startsWith('application-') &&
|
||||
details.file.name.endsWith('.yml') &&
|
||||
!(details.file.name in ['application-stage.yml', 'application-prod.yml'])
|
||||
}
|
||||
// exclude { details ->
|
||||
// details.file.name.startsWith('application-') &&
|
||||
// details.file.name.endsWith('.yml') &&
|
||||
// !(details.file.name in ['application-stage.yml', 'application-prod.yml'])
|
||||
// }
|
||||
}
|
||||
|
||||
test {
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.eactive.apim.portal.apps.community.notice.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IncidentAffectedApiDTO {
|
||||
private String apiId;
|
||||
private String apiName;
|
||||
}
|
||||
@@ -8,11 +8,18 @@ import org.hibernate.validator.constraints.Length;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PortalNoticeDTO {
|
||||
|
||||
public static final String NOTICE_TYPE_NORMAL = "1";
|
||||
public static final String NOTICE_TYPE_MAINTENANCE = "2";
|
||||
public static final String NOTICE_TYPE_INCIDENT = "3";
|
||||
|
||||
private String id;
|
||||
|
||||
@NotEmpty(message = "제목을 입력해주세요.")
|
||||
@@ -29,9 +36,33 @@ public class PortalNoticeDTO {
|
||||
|
||||
private boolean useYn;
|
||||
|
||||
private String fixYn;
|
||||
|
||||
private String noticeType;
|
||||
|
||||
private String inquirerName;
|
||||
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
private LocalDateTime lastModifiedDate;
|
||||
|
||||
// ───── 장애/점검 연동 필드 ─────
|
||||
private String summary;
|
||||
private LocalDateTime startedAt;
|
||||
private LocalDateTime endAt;
|
||||
private String state;
|
||||
private String previousState;
|
||||
private List<IncidentAffectedApiDTO> affectedApis = Collections.emptyList();
|
||||
|
||||
public boolean isIncidentType() {
|
||||
return NOTICE_TYPE_INCIDENT.equals(noticeType);
|
||||
}
|
||||
|
||||
public boolean isMaintenanceType() {
|
||||
return NOTICE_TYPE_MAINTENANCE.equals(noticeType);
|
||||
}
|
||||
|
||||
public boolean isIncidentOrMaintenance() {
|
||||
return isIncidentType() || isMaintenanceType();
|
||||
}
|
||||
}
|
||||
+45
-3
@@ -1,8 +1,12 @@
|
||||
package com.eactive.apim.portal.apps.community.notice.service;
|
||||
|
||||
import com.eactive.apim.portal.apps.community.notice.dto.IncidentAffectedApiDTO;
|
||||
import com.eactive.apim.portal.apps.community.notice.dto.PortalNoticeDTO;
|
||||
import com.eactive.apim.portal.apps.community.notice.dto.PortalNoticeSearch;
|
||||
import com.eactive.apim.portal.apps.community.notice.mapper.PortalNoticeMapper;
|
||||
import com.eactive.apim.portal.djb.apistatus.incident.entity.DjbApistatusIncident;
|
||||
import com.eactive.apim.portal.djb.apistatus.incident.repository.DjbApistatusIncidentApiRepository;
|
||||
import com.eactive.apim.portal.djb.apistatus.incident.repository.DjbApistatusIncidentRepository;
|
||||
import com.eactive.apim.portal.portalNotice.entity.PortalNotice;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -12,7 +16,10 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service("portalNoticeFacade")
|
||||
@RequiredArgsConstructor
|
||||
@@ -20,12 +27,13 @@ public class PortalNoticeFacadeImpl implements PortalNoticeFacade {
|
||||
|
||||
private final PortalNoticeService portalNoticeService;
|
||||
private final PortalNoticeMapper portalNoticeMapper;
|
||||
private final DjbApistatusIncidentRepository incidentRepository;
|
||||
private final DjbApistatusIncidentApiRepository incidentApiRepository;
|
||||
|
||||
@Override
|
||||
public List<PortalNoticeDTO> getLatestNotices() {
|
||||
PortalNoticeSearch search = new PortalNoticeSearch();
|
||||
Pageable pageable = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "createdDate"));
|
||||
// Pageable pageable = Pageable.ofSize(3);
|
||||
Page<PortalNoticeDTO> notices = getNotices(search, pageable);
|
||||
return notices.getContent();
|
||||
}
|
||||
@@ -36,13 +44,47 @@ public class PortalNoticeFacadeImpl implements PortalNoticeFacade {
|
||||
Specification<PortalNotice> spec = Specification.where(search.buildSpecification())
|
||||
.and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("useYn"),"Y"));
|
||||
|
||||
Page<PortalNotice> noticesPage = portalNoticeService.getNotices(spec, pageable);
|
||||
// 상단고정(fixYn='Y') 우선 정렬 — 호출자의 sort 앞에 결합 (admin Service 와 일관)
|
||||
Sort fixYnFirst = Sort.by(Sort.Direction.DESC, "fixYn");
|
||||
Pageable fixedPageable = PageRequest.of(
|
||||
pageable.getPageNumber(),
|
||||
pageable.getPageSize(),
|
||||
fixYnFirst.and(pageable.getSort())
|
||||
);
|
||||
|
||||
Page<PortalNotice> noticesPage = portalNoticeService.getNotices(spec, fixedPageable);
|
||||
return noticesPage.map(portalNoticeMapper::map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortalNoticeDTO getNotice(String id) {
|
||||
PortalNotice portalNotice = portalNoticeService.getNotice(id);
|
||||
return portalNoticeMapper.map(portalNotice);
|
||||
PortalNoticeDTO dto = portalNoticeMapper.map(portalNotice);
|
||||
populateIncident(dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private void populateIncident(PortalNoticeDTO dto) {
|
||||
if (!dto.isIncidentOrMaintenance()) {
|
||||
dto.setAffectedApis(Collections.emptyList());
|
||||
return;
|
||||
}
|
||||
Optional<DjbApistatusIncident> incidentOpt = incidentRepository.findByNoticeId(dto.getId());
|
||||
if (!incidentOpt.isPresent()) {
|
||||
dto.setAffectedApis(Collections.emptyList());
|
||||
return;
|
||||
}
|
||||
DjbApistatusIncident incident = incidentOpt.get();
|
||||
dto.setSummary(incident.getSummary());
|
||||
dto.setStartedAt(incident.getStartedAt());
|
||||
dto.setEndAt(incident.getEndAt());
|
||||
dto.setState(incident.getState() == null ? null : incident.getState().name());
|
||||
dto.setPreviousState(incident.getPreviousState() == null ? null : incident.getPreviousState().name());
|
||||
|
||||
List<IncidentAffectedApiDTO> apis = incidentApiRepository
|
||||
.findByIncidentIdOrderByApiId(incident.getIncidentId()).stream()
|
||||
.map(api -> new IncidentAffectedApiDTO(api.getApiId(), api.getApiName()))
|
||||
.collect(Collectors.toList());
|
||||
dto.setAffectedApis(apis);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -6,8 +6,10 @@ import com.eactive.apim.portal.apps.community.qna.mapper.InquiryMapper;
|
||||
import com.eactive.apim.portal.common.user.PortalAuthenticatedUser;
|
||||
import com.eactive.apim.portal.common.util.SecurityUtil;
|
||||
import com.eactive.apim.portal.common.util.StringMaskingUtil;
|
||||
import com.eactive.apim.portal.djb.community.qna.comment.service.InquiryAdminNotifier;
|
||||
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums;
|
||||
import com.eactive.apim.portal.qna.entity.Inquiry;
|
||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -15,6 +17,8 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@@ -22,6 +26,7 @@ public class InquiryFacadeImpl implements InquiryFacade {
|
||||
|
||||
private final InquiryService inquiryService;
|
||||
private final InquiryMapper inquiryMapper;
|
||||
private final InquiryAdminNotifier inquiryAdminNotifier;
|
||||
|
||||
@Override
|
||||
public Page<InquiryDTO> getInquiries(InquirySearch search, Pageable pageable, PortalAuthenticatedUser user) {
|
||||
@@ -81,9 +86,16 @@ public class InquiryFacadeImpl implements InquiryFacade {
|
||||
|
||||
@Override
|
||||
public void createInquiry(InquiryDTO inquiryDTO) throws IOException {
|
||||
PortalAuthenticatedUser current = SecurityUtil.getPortalAuthenticatedUser();
|
||||
Inquiry inquiry = inquiryMapper.toEntity(inquiryDTO);
|
||||
inquiry.setInquirer(SecurityUtil.getPortalAuthenticatedUser());
|
||||
inquiry.setInquirer(current);
|
||||
inquiryService.createInquiry(inquiry);
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("inquiryId", inquiry.getId());
|
||||
params.put("inquirySubject", inquiry.getInquirySubject());
|
||||
params.put("writerName", current.getUserName());
|
||||
inquiryAdminNotifier.notifyPortalAdmins(MessageCode.INQUIRY_CREATED, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.eactive.apim.portal.djb.community.qna.comment.repository;
|
||||
|
||||
import com.eactive.apim.portal.user.entity.UserInfo;
|
||||
import com.eactive.eai.data.jpa.BaseRepository;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@EMSDataSource
|
||||
public interface UserInfoRepository extends BaseRepository<UserInfo, String> {
|
||||
|
||||
/**
|
||||
* TSEAIRM02.roleidnfiname 컬럼은 콤마로 구분된 복수 역할을 저장한다.
|
||||
* (예: {@code "admin,portal-admin"}). Oracle native query로 콤마 토큰 매치.
|
||||
*/
|
||||
@Query(value = "SELECT * FROM TSEAIRM02 t"
|
||||
+ " WHERE ',' || t.ROLEIDNFINAME || ',' LIKE '%,' || :role || ',%'",
|
||||
nativeQuery = true)
|
||||
List<UserInfo> findByRoleContaining(@Param("role") String role);
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.eactive.apim.portal.djb.community.qna.comment.service;
|
||||
|
||||
import com.eactive.apim.portal.djb.community.qna.comment.repository.UserInfoRepository;
|
||||
import com.eactive.apim.portal.djb.community.qna.constant.DjbAdminRole;
|
||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import com.eactive.apim.portal.template.service.MessageHandlerService;
|
||||
import com.eactive.apim.portal.template.service.MessageRecipient;
|
||||
import com.eactive.apim.portal.user.entity.UserInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Q&A 등록/댓글 등록 시 portal-admin 역할(TSEAIRM02)을 가진 관리자 전원에게
|
||||
* 알림 메시지를 발행한다. 발송 실패는 트랜잭션 롤백을 유발하지 않는다.
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InquiryAdminNotifier {
|
||||
|
||||
private final UserInfoRepository userInfoRepository;
|
||||
private final MessageHandlerService messageHandlerService;
|
||||
|
||||
public void notifyPortalAdmins(MessageCode code, Map<String, Object> params) {
|
||||
try {
|
||||
List<UserInfo> admins = userInfoRepository.findByRoleContaining(DjbAdminRole.PORTAL_ADMIN);
|
||||
if (admins == null || admins.isEmpty()) {
|
||||
log.warn("portal-admin 역할 관리자가 없습니다 — 알림 미발송 code={}", code.name());
|
||||
return;
|
||||
}
|
||||
for (UserInfo admin : admins) {
|
||||
try {
|
||||
MessageRecipient recipient = toRecipient(admin);
|
||||
messageHandlerService.publishEvent(code, recipient, params);
|
||||
} catch (Exception e) {
|
||||
log.warn("portal-admin 개별 알림 발행 실패 — userid={}, code={}",
|
||||
admin.getUserid(), code.name(), e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("portal-admin 알림 발행 실패 — code={}", code.name(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageRecipient toRecipient(UserInfo admin) {
|
||||
MessageRecipient r = new MessageRecipient();
|
||||
r.setUsername(admin.getUsername());
|
||||
r.setUserId(admin.getEmad());
|
||||
r.setPhone(admin.getCphnno());
|
||||
r.setMessengerId(admin.getUserid());
|
||||
return r;
|
||||
}
|
||||
}
|
||||
+2
-13
@@ -13,8 +13,6 @@ import com.eactive.apim.portal.portaluser.repository.PortalUserRepository;
|
||||
import com.eactive.apim.portal.qna.entity.Inquiry;
|
||||
import com.eactive.apim.portal.qna.entity.InquiryComment;
|
||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import com.eactive.apim.portal.template.service.MessageHandlerService;
|
||||
import com.eactive.apim.portal.template.service.MessageRecipient;
|
||||
import com.eactive.apim.portal.user.entity.UserInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -44,7 +42,7 @@ public class InquiryCommentFacadeImpl implements InquiryCommentFacade {
|
||||
private final InquiryCommentService commentService;
|
||||
private final InquiryCommentRepository commentRepository;
|
||||
private final InquiryCommentPermissionChecker permissionChecker;
|
||||
private final MessageHandlerService messageHandlerService;
|
||||
private final InquiryAdminNotifier adminNotifier;
|
||||
private final PortalUserRepository portalUserRepository;
|
||||
private final UserInfoRepository userInfoRepository;
|
||||
|
||||
@@ -96,21 +94,12 @@ public class InquiryCommentFacadeImpl implements InquiryCommentFacade {
|
||||
}
|
||||
|
||||
private void publishAdminNotification(Inquiry inquiry, InquiryComment comment, PortalAuthenticatedUser current) {
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("inquiryId", inquiry.getId());
|
||||
params.put("inquirySubject", inquiry.getInquirySubject());
|
||||
params.put("commentContent", comment.getCommentDetail());
|
||||
params.put("writerName", current.getUserName());
|
||||
messageHandlerService.publishEvent(
|
||||
MessageCode.INQUIRY_COMMENT_CREATED_ADMIN,
|
||||
MessageRecipient.of(current),
|
||||
params
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.warn("Q&A 댓글 등록 관리자 알림 발행 실패 — inquiryId={}, commentId={}",
|
||||
inquiry.getId(), comment.getId(), e);
|
||||
}
|
||||
adminNotifier.notifyPortalAdmins(MessageCode.INQUIRY_COMMENT_CREATED, params);
|
||||
}
|
||||
|
||||
private Map<String, String> resolveWriterNames(List<InquiryComment> comments) {
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.eactive.apim.portal.djb.community.qna.constant;
|
||||
|
||||
public final class DjbAdminRole {
|
||||
|
||||
/** TSEAIRM02.roleidnfiname 컬럼에서 포털 관리자를 식별하는 값. */
|
||||
public static final String PORTAL_ADMIN = "portal-admin";
|
||||
|
||||
private DjbAdminRole() {
|
||||
}
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.eactive.apim.portal.djb.community.qna.comment.event;
|
||||
|
||||
import com.eactive.apim.portal.template.entity.MessageCode;
|
||||
import com.eactive.apim.portal.template.service.MessageEventHandler;
|
||||
import com.eactive.apim.portal.template.service.MessageRecipient;
|
||||
import com.eactive.apim.portal.template.service.MessageSendEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class InquiryCommentCreatedAdminEvent implements MessageEventHandler {
|
||||
|
||||
public static final MessageCode KEY = MessageCode.INQUIRY_COMMENT_CREATED_ADMIN;
|
||||
|
||||
@Override
|
||||
public MessageCode getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowAdditionalRecipients() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Q&A 댓글 등록 알림";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "<div>사용 가능 변수: </div><br/>"
|
||||
+ "<div> - inquiryId: 문의 ID </div><br/>"
|
||||
+ "<div> - inquirySubject: 문의 제목 </div><br/>"
|
||||
+ "<div> - commentContent: 댓글 본문 </div><br/>"
|
||||
+ "<div> - writerName: 작성자 이름 </div><br/>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageSendEvent createEvent(Object source, MessageRecipient recipient, Map<String, Object> params) {
|
||||
Map<String, String> requestParams = new HashMap<>();
|
||||
requestParams.put("inquiryId", toStr(params.get("inquiryId")));
|
||||
requestParams.put("inquirySubject", toStr(params.get("inquirySubject")));
|
||||
requestParams.put("commentContent", toStr(params.get("commentContent")));
|
||||
requestParams.put("writerName", toStr(params.get("writerName")));
|
||||
return new MessageSendEvent(source, KEY, recipient, requestParams);
|
||||
}
|
||||
|
||||
private String toStr(Object value) {
|
||||
return value == null ? "" : value.toString();
|
||||
}
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package com.eactive.apim.portal.djb.community.qna.comment.repository;
|
||||
|
||||
import com.eactive.apim.portal.user.entity.UserInfo;
|
||||
import com.eactive.eai.data.jpa.BaseRepository;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
|
||||
@EMSDataSource
|
||||
public interface UserInfoRepository extends BaseRepository<UserInfo, String> {
|
||||
}
|
||||
@@ -15,10 +15,50 @@
|
||||
|
||||
<!-- Notice Header: Title and Date -->
|
||||
<div class="notice-detail-header">
|
||||
<h2 class="notice-detail-title" th:text="${portalNotice.noticeSubject}">개인정보처리 방침 정정 공지</h2>
|
||||
<h2 class="notice-detail-title">
|
||||
<span th:if="${portalNotice.noticeType == '3'}"
|
||||
style="display:inline-block;padding:2px 10px;margin-right:8px;border-radius:12px;font-size:14px;vertical-align:middle;background:#fde7e9;color:#c0152a;">장애</span>
|
||||
<span th:if="${portalNotice.noticeType == '2'}"
|
||||
style="display:inline-block;padding:2px 10px;margin-right:8px;border-radius:12px;font-size:14px;vertical-align:middle;background:#fff4d6;color:#9a6700;">점검</span>
|
||||
<span th:text="${portalNotice.noticeSubject}">개인정보처리 방침 정정 공지</span>
|
||||
</h2>
|
||||
<span class="notice-detail-date" th:text="${#temporals.format(portalNotice.createdDate, 'yyyy.MM.dd')}">2025.11.01</span>
|
||||
</div>
|
||||
|
||||
<!-- 장애/점검 정보 영역 -->
|
||||
<div class="notice-detail-incident-info" th:if="${portalNotice.incidentOrMaintenance}"
|
||||
style="margin:16px 0;padding:16px;background:#f7f8fa;border:1px solid #e3e6eb;border-radius:8px;">
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<colgroup>
|
||||
<col style="width:120px;"><col><col style="width:120px;"><col>
|
||||
</colgroup>
|
||||
<tr>
|
||||
<th style="text-align:left;padding:6px 8px;">시작</th>
|
||||
<td style="padding:6px 8px;"
|
||||
th:text="${portalNotice.startedAt != null ? #temporals.format(portalNotice.startedAt, 'yyyy.MM.dd HH:mm') : '-'}">-</td>
|
||||
<th style="text-align:left;padding:6px 8px;">종료</th>
|
||||
<td style="padding:6px 8px;"
|
||||
th:text="${portalNotice.endAt != null ? #temporals.format(portalNotice.endAt, 'yyyy.MM.dd HH:mm') : '진행중'}">-</td>
|
||||
</tr>
|
||||
<tr th:if="${portalNotice.incidentType}">
|
||||
<th style="text-align:left;padding:6px 8px;">상태</th>
|
||||
<td colspan="3" style="padding:6px 8px;" th:text="${portalNotice.state != null ? portalNotice.state : '-'}">-</td>
|
||||
</tr>
|
||||
<tr th:if="${portalNotice.affectedApis != null and !portalNotice.affectedApis.isEmpty()}">
|
||||
<th style="text-align:left;padding:6px 8px;vertical-align:top;">영향 API</th>
|
||||
<td colspan="3" style="padding:6px 8px;">
|
||||
<ul style="margin:0;padding-left:18px;">
|
||||
<li th:each="api : ${portalNotice.affectedApis}">
|
||||
<strong th:text="${api.apiId}">API_ID</strong>
|
||||
<span th:if="${api.apiName != null and !api.apiName.isEmpty()}"
|
||||
th:text="| - ${api.apiName}|"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Attachment Section -->
|
||||
<div class="notice-detail-attachment" th:if="${!#strings.isEmpty(portalNotice.fileId)}">
|
||||
<div class="attachment-list" th:with="fileInfo=${@fileService.findById(portalNotice.fileId)}">
|
||||
|
||||
@@ -58,6 +58,15 @@
|
||||
<div class="row-cell row-cell--title" style="flex: 1; min-width: 200px;" data-label="제목">
|
||||
<a th:href="@{/portalnotice/detail(id=${notice.id})}" class="notice-title-link">
|
||||
<span class="notice-number" th:text="|[${page.totalElements - (page.number * page.size) - status.index}]|">[1]</span>
|
||||
<span class="notice-fix-badge"
|
||||
th:if="${notice.fixYn == 'Y'}"
|
||||
style="display:inline-block;padding:2px 8px;margin-right:6px;border-radius:10px;font-size:12px;background:#e5f0ff;color:#0a4ea3;font-weight:600;">고정</span>
|
||||
<span class="notice-type-badge notice-type-badge--incident"
|
||||
th:if="${notice.noticeType == '3'}"
|
||||
style="display:inline-block;padding:2px 8px;margin-right:6px;border-radius:10px;font-size:12px;background:#fde7e9;color:#c0152a;">장애</span>
|
||||
<span class="notice-type-badge notice-type-badge--maintenance"
|
||||
th:if="${notice.noticeType == '2'}"
|
||||
style="display:inline-block;padding:2px 8px;margin-right:6px;border-radius:10px;font-size:12px;background:#fff4d6;color:#9a6700;">점검</span>
|
||||
<span th:text="${notice.noticeSubject}">공지사항 제목</span>
|
||||
<span class="file-icon" th:if="${notice.fileId != null and !notice.fileId.isEmpty()}">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
Reference in New Issue
Block a user