문자온 스팸문자 필터링 기능 개발중

This commit is contained in:
hylee 2024-08-19 20:49:59 +09:00
parent b5b34604e8
commit 3d417c7b09
11 changed files with 201 additions and 63 deletions

View File

@ -160,12 +160,13 @@
<version>2.3.1</version>
</dependency>
<!-- Spring WebFlux 의존성 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,37 @@
package com.itn.admin.cmn.vo;
import lombok.*;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class CmnVO {
private int pageNum = 1; // 현재 페이지 번호 기본값 설정
private int pageSize = 10; // 페이지에 보여줄 데이터 개수 기본값 설정
private int offset; // SQL 쿼리에서 사용할 OFFSET
private int limit; // SQL 쿼리에서 사용할 LIMIT
private int totalCount; // 데이터
private int totalPageCount; // 페이지
private int startPage; // 페이지네이션의 시작 페이지 번호
private int endPage; // 페이지네이션의 페이지 번호
// 페이징을 위한 offset과 limit을 계산하는 메서드
public void calculatePaging(int totalRecordCount) {
this.totalCount = totalRecordCount;
this.offset = (pageNum - 1) * pageSize;
this.limit = pageSize;
// 페이지 계산
this.totalPageCount = (int) Math.ceil((double) totalRecordCount / pageSize);
// 페이지네이션의 시작과 페이지 계산
int pageBlockSize = 10; // 블록에 표시할 페이지
this.startPage = ((pageNum - 1) / pageBlockSize) * pageBlockSize + 1;
this.endPage = Math.min(startPage + pageBlockSize - 1, totalPageCount);
}
}

View File

@ -16,4 +16,8 @@ public interface SpamMapper {
List<SpamVO> getListWhereKeywordsIsNull(SpamVO spamVO);
void update(SpamVO spamVO);
List<SpamVO> getSpamList(SpamVO spamVO);
int getTotalRecordCount();
}

View File

@ -1,9 +1,11 @@
package com.itn.admin.itn.mjon.spam.mapper.domain;
import com.itn.admin.cmn.vo.CmnVO;
import lombok.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
* packageName : com.itn.admin.itn.mjon.spam.mapper.domain
@ -23,7 +25,7 @@ import java.time.LocalDateTime;
@Getter
@Setter
@ToString
public class SpamVO implements Serializable {
public class SpamVO extends CmnVO implements Serializable {
private static final long serialVersionUID = 1L;
@ -40,4 +42,7 @@ public class SpamVO implements Serializable {
private String lastUpdusrId; // 최종수정자ID
private LocalDateTime lastUpdtPnttm; // 최종수정일자
// spam_keywords TB 필드들
private List<String> keywordList; // 키워드 리스트
}

View File

@ -11,4 +11,6 @@ public interface SpamService {
Map<String, Object> getList(SpamVO spamVO);
void analyze();
Map<String, Object> getSpamList(SpamVO spamVO);
}

View File

@ -9,13 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Slf4j
@Service
@ -57,7 +52,7 @@ public class SpamServiceImpl implements SpamService {
// for (SpamVO spamVO : spamList) {
// API 호출 데이터 수신
// API 호출 데이터 수신
List<SpamVO> spamList = spamMapper.getListWhereKeywordsIsNull(new SpamVO());
@ -111,4 +106,27 @@ public class SpamServiceImpl implements SpamService {
}
}
}
@Override
public Map<String, Object> getSpamList(SpamVO spamVO) {
int totalRecordCount = spamMapper.getTotalRecordCount();
spamVO.calculatePaging(totalRecordCount);
List<SpamVO> spamList = spamMapper.getSpamList(spamVO);
// 키워드를 버튼용 배열로 변환
for (SpamVO spam : spamList) {
if (spam.getKeywords() != null) {
spam.setKeywordList(Arrays.asList(spam.getKeywords().split(", ")));
}
}
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("spamList", spamList);
resultMap.put("totalRecordCount", totalRecordCount);
resultMap.put("totalPageCount", spamVO.getTotalPageCount());
return resultMap;
}
}

View File

@ -1,23 +1,11 @@
package com.itn.admin.itn.mjon.spam.web;
import com.itn.admin.itn.mjon.spam.mapper.domain.SpamVO;
import com.itn.admin.itn.mjon.spam.service.SpamService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.lang.module.ModuleDescriptor;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController

View File

@ -9,6 +9,8 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@ -23,13 +25,11 @@ public class SpamController {
@GetMapping(value = "/mjon/spam/select")
public String select(@ModelAttribute("spamVO") SpamVO spamVO, Model model) {
//
//
// Map<String, Object> resultMap = spamService.getList(spamVO);
// model.addAttribute("spamList", resultMap.get("spamList"));
//
// model.addAttribute("list", resultMap.get("resultList"));
Map<String, Object> map = spamService.getSpamList(spamVO);
model.addAttribute("spamList", map.get("spamList"));
model.addAttribute("pagingVO", spamVO);
return "mjon/spam/select";
}

View File

@ -4,6 +4,33 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itn.admin.itn.mjon.spam.mapper.SpamMapper">
<!-- 페이징 처리를 위해 전체 레코드 수를 구하는 쿼리 -->
<select id="getTotalRecordCount" resultType="int">
SELECT COUNT(*) FROM spam_keywords
</select>
<select id="getSpamList" parameterType="spamVO" resultType="SpamVO">
SELECT
SPAM_ID,
MSG_GROUP_ID,
SMS_TXT,
SPAM_RSN,
KEYWORDS,
CHC_KEYWORDS,
TIMESTAMP,
CATEG,
FRST_REGISTER_ID,
FRST_REGIST_PNTTM,
LAST_UPDUSR_ID,
LAST_UPDT_PNTTM
FROM
spam_keywords
ORDER BY
SPAM_ID
LIMIT #{limit} OFFSET #{offset}
</select>
<select id="getList" parameterType="spamVO" resultType="spamVO">
SELECT

View File

@ -99,7 +99,7 @@
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a th:href="@{/mjon/spam}" class="nav-link">
<a th:href="@{/mjon/spam/select}" class="nav-link">
<i class="fas fa-exclamation-triangle nav-icon"></i>
<p>스팸문자</p>
</a>

View File

@ -38,6 +38,25 @@
text-align: center;
vertical-align: middle;
}
/*단어 버튼 css*/
/* .word-button {
background-color: #007bff; !* 기본 배경색 *!
color: white; !* 글자색 *!
border: none; !* 테두리 없애기 *!
border-radius: 15px; !* 둥근 모서리 *!
padding: 5px 10px; !* 패딩 조절 *!
margin: 3px; !* 버튼 사이 간격 *!
cursor: pointer; !* 커서 모양 변경 *!
font-size: 14px; !* 글자 크기 *!
transition: background-color 0.3s ease; !* 배경색 전환 효과 *!
}
.word-button:hover {
background-color: #0056b3; !* 마우스 오버 시 배경색 *!
}*/
</style>
<script>
@ -83,55 +102,82 @@
<div class="card">
<div class="card-header">
<h3 class="card-title">스팸 단어 선택</h3>
<h3 class="card-title" th:text="'Total '+${pagingVO.totalCount}+'건'">스팸 단어 선택</h3>
</div>
<!-- /.card-header -->
<div class="card-body p-0">
<table class="table table-hover table-fixed">
<table class="table table-hover">
<thead>
<tr>
<th style="width: 5%;">번호</th>
<th style="width: 25%;">스팸문자</th>
<th style="width: 25%;">복합명사</th>
<th style="width: 35%;">복합명사</th>
<th style="width: 25%;">핵심 단어</th>
<th style="width: 20%;">스팸분류</th>
<th style="width: 10%;">스팸분류</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>(광고)♥봄맞이 특별이벤트 진행중♥ ...</td>
<td>'바다', '서비스', '갯수', '이건조제한', ...</td>
<td>'바다', '서비스', '갯수', '이건조제한', 'EVENT 1' ...</td>
<td>
<select class="form-control">
<option>선택</option>
<option>성인</option>
<option>불법</option>
<option>해당없음</option>
</select>
</td>
</tr>
<tr>
<td>2</td>
<td>[국민건강보험]...</td>
<td>'바다', '서비스', '갯수'...</td>
<td>'바다', '서비스'...</td>
<td>
<select class="form-control">
<option>선택</option>
<option>성인</option>
<option>불법</option>
<option>해당없음</option>
</select>
</td>
</tr>
<!-- 추가 행을 여기에 추가 -->
<tr th:each="spam, iterStat : ${spamList}">
<td th:text="${iterStat.index + 1}"></td>
<td th:text="${spam.smsTxt}">스팸문자 내용</td>
<td>
<span th:each="word : ${spam.keywordList}">
<!--
- adminLTE3 css 참고
btn: 버튼 스타일을 적용합니다.
btn-primary: 파란색 배경의 버튼을 만듭니다. 다른 색상은 btn-secondary, btn-success, btn-danger 등으로 변경할 수 있습니다.
btn-sm: 작은 크기의 버튼을 만듭니다.
rounded-pill: 모서리를 둥글게 처리하여 pill 형태의 버튼을 만듭니다.
mx-1: 좌우에 0.25rem(약 4px)의 여백 추가
my-1: 상하에 0.25rem(약 4px)의 여백 추가
-->
<button class="btn btn-primary rounded-pill mx-1 my-1"
th:text="${word}"
th:data-spamid="${spam.spamId}"
th:data-word="${word}"
onclick="handleClick(this)"></button>
</span>
</td>
<!-- <td th:text="${spam.keywords}">복합명사 목록</td>-->
<td th:text="${spam.chcKeywords}">핵심 단어 목록</td>
<td>
<select class="form-control" th:value="${spam.categ}">
<option>선택</option>
<option value="성인">성인</option>
<option value="불법">불법</option>
<option value="해당없음">해당없음</option>
</select>
</td>
</tr>
</tbody>
</table>
<!-- Pagination -->
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="${pagingVO.pageNum == 1} ? 'disabled'">
<a class="page-link" th:href="@{/mjon/spam/select(pageNum=${pagingVO.pageNum - 1}, pageSize=${pagingVO.pageSize})}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<li class="page-item" th:each="i : ${#numbers.sequence(pagingVO.startPage, pagingVO.endPage)}"
th:classappend="${i == pagingVO.pageNum} ? 'active'">
<a class="page-link" th:text="${i}"
th:href="@{/mjon/spam/select(pageNum=${i}, pageSize=${pagingVO.pageSize})}"></a>
</li>
<li class="page-item" th:classappend="${pagingVO.pageNum == pagingVO.totalPageCount} ? 'disabled'">
<a class="page-link" th:href="@{/mjon/spam/select(pageNum=${pagingVO.pageNum + 1}, pageSize=${pagingVO.pageSize})}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
<!-- /.card-body -->
@ -180,6 +226,16 @@
$(function () {
});
function handleClick(button) {
var spamId = button.getAttribute('data-spamid');
var word = button.getAttribute('data-word');
console.log("Spam ID:", spamId, "Word:", word);
// 여기에 추가적인 로직을 구현하세요.
// 부모 요소인 span을 찾아서 제거
var span = button.parentElement;
span.remove();
}
</script>