문자온 스팸문자 필터링 기능 개발중
This commit is contained in:
parent
b5b34604e8
commit
3d417c7b09
7
pom.xml
7
pom.xml
@ -160,12 +160,13 @@
|
|||||||
<version>2.3.1</version>
|
<version>2.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring WebFlux 의존성 -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>com.github.pagehelper</groupId>
|
||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||||
|
<version>1.4.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
37
src/main/java/com/itn/admin/cmn/vo/CmnVO.java
Normal file
37
src/main/java/com/itn/admin/cmn/vo/CmnVO.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,4 +16,8 @@ public interface SpamMapper {
|
|||||||
List<SpamVO> getListWhereKeywordsIsNull(SpamVO spamVO);
|
List<SpamVO> getListWhereKeywordsIsNull(SpamVO spamVO);
|
||||||
|
|
||||||
void update(SpamVO spamVO);
|
void update(SpamVO spamVO);
|
||||||
|
|
||||||
|
List<SpamVO> getSpamList(SpamVO spamVO);
|
||||||
|
|
||||||
|
int getTotalRecordCount();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
package com.itn.admin.itn.mjon.spam.mapper.domain;
|
package com.itn.admin.itn.mjon.spam.mapper.domain;
|
||||||
|
|
||||||
|
import com.itn.admin.cmn.vo.CmnVO;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* packageName : com.itn.admin.itn.mjon.spam.mapper.domain
|
* packageName : com.itn.admin.itn.mjon.spam.mapper.domain
|
||||||
@ -23,7 +25,7 @@ import java.time.LocalDateTime;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@ToString
|
@ToString
|
||||||
public class SpamVO implements Serializable {
|
public class SpamVO extends CmnVO implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -40,4 +42,7 @@ public class SpamVO implements Serializable {
|
|||||||
private String lastUpdusrId; // 최종수정자ID
|
private String lastUpdusrId; // 최종수정자ID
|
||||||
private LocalDateTime lastUpdtPnttm; // 최종수정일자
|
private LocalDateTime lastUpdtPnttm; // 최종수정일자
|
||||||
|
|
||||||
|
|
||||||
|
// spam_keywords TB 외 필드들
|
||||||
|
private List<String> keywordList; // 키워드 리스트
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,4 +11,6 @@ public interface SpamService {
|
|||||||
Map<String, Object> getList(SpamVO spamVO);
|
Map<String, Object> getList(SpamVO spamVO);
|
||||||
|
|
||||||
void analyze();
|
void analyze();
|
||||||
|
|
||||||
|
Map<String, Object> getSpamList(SpamVO spamVO);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,13 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -57,7 +52,7 @@ public class SpamServiceImpl implements SpamService {
|
|||||||
|
|
||||||
// for (SpamVO spamVO : spamList) {
|
// for (SpamVO spamVO : spamList) {
|
||||||
|
|
||||||
// API 호출 및 데이터 수신
|
// API 호출 및 데이터 수신
|
||||||
|
|
||||||
List<SpamVO> spamList = spamMapper.getListWhereKeywordsIsNull(new SpamVO());
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,11 @@
|
|||||||
package com.itn.admin.itn.mjon.spam.web;
|
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 com.itn.admin.itn.mjon.spam.service.SpamService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.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
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import org.springframework.ui.Model;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@ -23,13 +25,11 @@ public class SpamController {
|
|||||||
|
|
||||||
@GetMapping(value = "/mjon/spam/select")
|
@GetMapping(value = "/mjon/spam/select")
|
||||||
public String select(@ModelAttribute("spamVO") SpamVO spamVO, Model model) {
|
public String select(@ModelAttribute("spamVO") SpamVO spamVO, Model model) {
|
||||||
//
|
|
||||||
//
|
|
||||||
// Map<String, Object> resultMap = spamService.getList(spamVO);
|
|
||||||
|
|
||||||
// model.addAttribute("spamList", resultMap.get("spamList"));
|
Map<String, Object> map = spamService.getSpamList(spamVO);
|
||||||
//
|
|
||||||
// model.addAttribute("list", resultMap.get("resultList"));
|
model.addAttribute("spamList", map.get("spamList"));
|
||||||
|
model.addAttribute("pagingVO", spamVO);
|
||||||
|
|
||||||
return "mjon/spam/select";
|
return "mjon/spam/select";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,33 @@
|
|||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="com.itn.admin.itn.mjon.spam.mapper.SpamMapper">
|
<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 id="getList" parameterType="spamVO" resultType="spamVO">
|
||||||
SELECT
|
SELECT
|
||||||
|
|||||||
@ -99,7 +99,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-treeview">
|
<ul class="nav nav-treeview">
|
||||||
<li class="nav-item">
|
<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>
|
<i class="fas fa-exclamation-triangle nav-icon"></i>
|
||||||
<p>스팸문자</p>
|
<p>스팸문자</p>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -38,6 +38,25 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
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>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -83,55 +102,82 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title">스팸 단어 선택</h3>
|
<h3 class="card-title" th:text="'Total '+${pagingVO.totalCount}+'건'">스팸 단어 선택</h3>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.card-header -->
|
<!-- /.card-header -->
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
|
|
||||||
<table class="table table-hover table-fixed">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 5%;">번호</th>
|
<th style="width: 5%;">번호</th>
|
||||||
<th style="width: 25%;">스팸문자</th>
|
<th style="width: 25%;">스팸문자</th>
|
||||||
<th style="width: 25%;">복합명사</th>
|
<th style="width: 35%;">복합명사</th>
|
||||||
<th style="width: 25%;">핵심 단어</th>
|
<th style="width: 25%;">핵심 단어</th>
|
||||||
<th style="width: 20%;">스팸분류</th>
|
<th style="width: 10%;">스팸분류</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr th:each="spam, iterStat : ${spamList}">
|
||||||
<td>1</td>
|
<td th:text="${iterStat.index + 1}"></td>
|
||||||
<td>(광고)♥봄맞이 특별이벤트 진행중♥ ...</td>
|
<td th:text="${spam.smsTxt}">스팸문자 내용</td>
|
||||||
<td>'바다', '서비스', '갯수', '이건조제한', ...</td>
|
<td>
|
||||||
<td>'바다', '서비스', '갯수', '이건조제한', 'EVENT 1' ...</td>
|
<span th:each="word : ${spam.keywordList}">
|
||||||
<td>
|
<!--
|
||||||
<select class="form-control">
|
- adminLTE3 css 참고
|
||||||
<option>선택</option>
|
btn: 버튼 스타일을 적용합니다.
|
||||||
<option>성인</option>
|
btn-primary: 파란색 배경의 버튼을 만듭니다. 다른 색상은 btn-secondary, btn-success, btn-danger 등으로 변경할 수 있습니다.
|
||||||
<option>불법</option>
|
btn-sm: 작은 크기의 버튼을 만듭니다.
|
||||||
<option>해당없음</option>
|
rounded-pill: 모서리를 둥글게 처리하여 pill 형태의 버튼을 만듭니다.
|
||||||
</select>
|
|
||||||
</td>
|
mx-1: 좌우에 0.25rem(약 4px)의 여백 추가
|
||||||
</tr>
|
my-1: 상하에 0.25rem(약 4px)의 여백 추가
|
||||||
<tr>
|
-->
|
||||||
<td>2</td>
|
<button class="btn btn-primary rounded-pill mx-1 my-1"
|
||||||
<td>[국민건강보험]...</td>
|
th:text="${word}"
|
||||||
<td>'바다', '서비스', '갯수'...</td>
|
th:data-spamid="${spam.spamId}"
|
||||||
<td>'바다', '서비스'...</td>
|
th:data-word="${word}"
|
||||||
<td>
|
onclick="handleClick(this)"></button>
|
||||||
<select class="form-control">
|
</span>
|
||||||
<option>선택</option>
|
</td>
|
||||||
<option>성인</option>
|
<!-- <td th:text="${spam.keywords}">복합명사 목록</td>-->
|
||||||
<option>불법</option>
|
<td th:text="${spam.chcKeywords}">핵심 단어 목록</td>
|
||||||
<option>해당없음</option>
|
<td>
|
||||||
</select>
|
<select class="form-control" th:value="${spam.categ}">
|
||||||
</td>
|
<option>선택</option>
|
||||||
</tr>
|
<option value="성인">성인</option>
|
||||||
<!-- 추가 행을 여기에 추가 -->
|
<option value="불법">불법</option>
|
||||||
|
<option value="해당없음">해당없음</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</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">«</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">»</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.card-body -->
|
<!-- /.card-body -->
|
||||||
@ -180,6 +226,16 @@
|
|||||||
$(function () {
|
$(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>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user