feat: 게시판 연관상품 목록 표준화

This commit is contained in:
이주일
2026-07-18 11:57:45 +09:00
parent 713bd6a64d
commit 6d77feabbe
4 changed files with 64 additions and 70 deletions

View File

@@ -570,19 +570,11 @@ public class BOGnrlbbscttService {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
// 게시글 연관상품 조회 // 게시글 연관상품 조회
List<DataMap> goodsList = new ArrayList<>(); List<DataMap> goodsList = new ArrayList<>();
DataMap result = new DataMap();
goodsList = mapper.selectBOBbscttDtlGoods(bbsctt); goodsList = mapper.selectBOBbscttDtlGoods(bbsctt);
/*게시판 설정 > 추천 상품 노출 선택 시 사용자 게시글 상세 상품 노출 */
if (!goodsList.isEmpty()) {
if ("sopmal".equals(bbsctt.getServerDv())) {
result = goodsService.selectBoGoodsRelateList(goodsList);
}
}
/*사용자 , 관리자 페이지 구분*/ /*사용자 , 관리자 페이지 구분*/
if ("sopmal".equals(bbsctt.getServerDv())) { if ("sopmal".equals(bbsctt.getServerDv())) {
map.put("goodsList", result); map.put("goodsList", goodsList);
} else { } else {
map.put("goodsList", goodsList); map.put("goodsList", goodsList);
} }

View File

@@ -2656,19 +2656,33 @@
WHERE 1=1 WHERE 1=1
AND FGI.GOODS_INNB = FBG.GOODS_INNB AND FGI.GOODS_INNB = FBG.GOODS_INNB
AND FGI.SOPMAL_CD = FBG.SOPMAL_CD AND FGI.SOPMAL_CD = FBG.SOPMAL_CD
AND FGI.IMG_KND = '03' AND FGI.IMG_KND = '02'
AND FGI.CUT_NB = 1 AND FGI.CUT_NB = 1
LIMIT 1 LIMIT 1
)IMG ) AS IMG
,FG.GOODS_NM ,FG.GOODS_NM
,FGO.CNSMRPRIC ,FG.GOODS_ICON_CD
,FGO.SLEPRIC ,FG.SRT_DC
,FGO.STDR_DV_AT ,FG.GOODS_STTUS_CD
,FN_GET_COMMCODE_NAME('GOODS_STTUS', FG.GOODS_STTUS_CD) AS GOODS_STTUS_NM ,IFNULL(ROUND(FGO.CNSMRPRIC, 0), 0) AS CNSMRPRIC
,FN_GET_COMMCODE_NAME('EXPSR', FG.EXPSR_DV_CD) AS EXPSR_NM ,IFNULL(ROUND(FGO.SLEPRIC, 0), 0) AS SLEPRIC
,FBG.ORDR_GOODS_OPTN_INNB ,IFNULL(ROUND(((FGO.CNSMRPRIC - FGO.SLEPRIC) / NULLIF(FGO.CNSMRPRIC, 0)) * 100, 0), 0) AS SLE_PERCENT
,FBG.SOPMAL_CD ,IFNULL((SELECT ROUND(AVG(FBA.EVL_SCORE), 1)
,FBG.RE_ORDER_AT FROM GC_BOARDDATA_GOODS RBG
INNER JOIN GC_BOARDDATA RB ON RB.BBSCTT_INNB = RBG.BBSCTT_INNB AND RB.SOPMAL_CD = RBG.SOPMAL_CD
INNER JOIN GC_BOARDMANAGER RBM ON RBM.BBS_ID = RB.BBS_ID AND RBM.SOPMAL_CD = RB.SOPMAL_CD
LEFT JOIN GC_BOARDFORM RBF ON RBF.BBS_ID = RBM.BBS_ID AND RBF.SOPMAL_CD = RBM.SOPMAL_CD AND RBF.USE_AT = 'Y' AND RBF.ADIT_ITM_DV_CD = '04'
LEFT JOIN GC_BOARD_ADDITM FBA ON FBA.BBSCTT_INNB = RB.BBSCTT_INNB AND FBA.SOPMAL_CD = RB.SOPMAL_CD AND FBA.QESITM_INNB = RBF.QESITM_INNB
WHERE RBG.SOPMAL_CD = FG.SOPMAL_CD
AND RBG.GOODS_INNB IN (SELECT CAST(RVW_GROUP_NB AS DECIMAL(10)) FROM GC_GOODS_RVW_V WHERE SOPMAL_CD = FG.SOPMAL_CD AND GOODS_INNB = FG.GOODS_INNB)
AND RB.USE_AT = 'Y' AND RB.DEPTH = 0 AND RBM.BBS_TY_CD IN ('06', '07')), 0) AS AVG_EVL_SCORE
,IFNULL((SELECT COUNT(RB.BBSCTT_INNB)
FROM GC_BOARDDATA_GOODS RBG
INNER JOIN GC_BOARDDATA RB ON RB.BBSCTT_INNB = RBG.BBSCTT_INNB AND RB.SOPMAL_CD = RBG.SOPMAL_CD
INNER JOIN GC_BOARDMANAGER RBM ON RBM.BBS_ID = RB.BBS_ID AND RBM.SOPMAL_CD = RB.SOPMAL_CD
WHERE RBG.SOPMAL_CD = FG.SOPMAL_CD
AND RBG.GOODS_INNB IN (SELECT CAST(RVW_GROUP_NB AS DECIMAL(10)) FROM GC_GOODS_RVW_V WHERE SOPMAL_CD = FG.SOPMAL_CD AND GOODS_INNB = FG.GOODS_INNB)
AND RB.USE_AT = 'Y' AND RB.DEPTH = 0 AND RBM.BBS_TY_CD IN ('06', '07')), 0) AS CNT_BBSCTT
FROM GC_BOARDDATA_GOODS FBG FROM GC_BOARDDATA_GOODS FBG
INNER JOIN GC_GOODS FG ON INNER JOIN GC_GOODS FG ON
FG.GOODS_INNB = FBG.GOODS_INNB FG.GOODS_INNB = FBG.GOODS_INNB
@@ -2688,6 +2702,16 @@
</otherwise> </otherwise>
</choose> </choose>
AND FGO.STDR_DV_AT = 'Y' AND FGO.STDR_DV_AT = 'Y'
<if test="serverDv == 'sopmal'">
AND FGO.OPTN_EXPSR_AT = 'Y'
AND FGO.USE_AT = 'Y'
AND FG.USE_AT = 'Y'
AND FG.GOODS_KND_CD = '01'
AND FG.GOODS_STTUS_CD IN ('01', '02')
AND (FG.EXPSR_DV_CD = '01' OR (FG.EXPSR_DV_CD = '03' AND SYSDATE() BETWEEN FG.EXPSR_BGN_DT AND FG.EXPSR_END_DT))
ORDER BY CASE FG.GOODS_STTUS_CD WHEN '02' THEN 1 ELSE 0 END ASC, FBG.REGIST_DT ASC, FBG.GOODS_INNB ASC
LIMIT 12
</if>
</select> </select>
<!-- 게시글 연관상품 삭제 (게시글 수정시)--> <!-- 게시글 연관상품 삭제 (게시글 수정시)-->

View File

@@ -132,13 +132,13 @@
}); });
} else { //메인화면 호출 안할 시 } else { //메인화면 호출 안할 시
// 상품 - 4열 슬라이드 타입 (이벤트 추천 상품 슬릭 이벤트) // 상품 - 4열 슬라이드 타입 (이벤트 추천 상품 슬릭 이벤트)
$('.four-row-slick').slick({ $('.relate-goods-slick').slick({
slidesToShow: 4, slidesToShow: 4,
slidesToScroll: 4, slidesToScroll: 4,
speed: 900, speed: 900,
infinite: true, infinite: true,
prevArrow: $('.four-row-slick__prev'), prevArrow: $('.relate-goods-slick__prev'),
nextArrow: $('.four-row-slick__next'), nextArrow: $('.relate-goods-slick__next'),
}); });
} }
} }
@@ -938,7 +938,7 @@
</div> </div>
</c:if> </c:if>
<%-------------------------------%> <%-------------------------------%>
<c:if test="${bbsInfo.recomendGoodsExpsrAt eq 'Y' && not empty goodsList.relateInfoList}"> <c:if test="${bbsInfo.recomendGoodsExpsrAt eq 'Y' && not empty goodsList}">
<div class="cartOrder"> <div class="cartOrder">
<div class="main-section__container"> <div class="main-section__container">
<section class="main-section main-section__four-row"> <section class="main-section main-section__four-row">
@@ -950,22 +950,18 @@
</div> </div>
</div> </div>
<div class="product-list-type1"> <div class="product-list-type1">
<div class="four-row-slick evtSlick"> <div class="${fn:length(goodsList) gt 4 ? 'four-row-slick relate-goods-slick evtSlick' : 'four-row-slick'}">
<c:forEach var = "item" items="${goodsList.relateInfoList}"> <c:forEach var = "item" items="${goodsList}">
<c:if test = "${not empty item.goodsInnb}"> <c:if test = "${not empty item.goodsInnb}">
<div class="product-unit"> <div class="product-unit">
<div class="product-unit-image"> <div class="product-unit-image">
<c:forEach var = "img" items = "${goodsList.relateImgList}"> <button type="button" onclick = "fn_move_goods_dtl(<c:out value="${item.goodsInnb}"/>)" value="${item.goodsInnb}">
<c:if test = "${item.goodsInnb eq img.goodsInnb}"> <spring:eval expression="@environment.getProperty('sopmalfo.common.fileupload.cdnurl')" var="cdnurl"/>
<button type="button" onclick = "fn_move_goods_dtl(<c:out value="${item.goodsInnb}"/>)" value="${item.goodsInnb}"> <img src="<c:out value = "${cdnurl}${item.img}"/>" style="width: 100%;
<spring:eval expression="@environment.getProperty('sopmalfo.common.fileupload.cdnurl')" var="cdnurl"/>
<img src="<c:out value = "${cdnurl}${img.img}"/>" style="width: 100%;
height: 304px; /* 원하는 고정 높이 설정 */ height: 304px; /* 원하는 고정 높이 설정 */
object-fit: cover; /* 이미지 비율을 유지하면서 영역에 맞게 자름 */" object-fit: cover; /* 이미지 비율을 유지하면서 영역에 맞게 자름 */"
onerror="this.src='/pc/images/image_placeholder.png'" alt="해당 이미지에 대한 설명"> onerror="this.src='/pc/images/image_placeholder.png'" alt="해당 이미지에 대한 설명">
</button> </button>
</c:if>
</c:forEach>
</div> </div>
<div class="product-unit-info"> <div class="product-unit-info">
<div class="product-badge-container"> <div class="product-badge-container">
@@ -996,48 +992,42 @@
</button> </button>
</div> </div>
<div class="product-unit-price"> <div class="product-unit-price">
<c:forEach var="goodsOpt" items="${goodsList.relateGoodsOptList}">
<c:if test="${item.goodsInnb eq goodsOpt.goodsInnb && goodsOpt.stdrDvAt eq 'Y'}">
<div class="product-unit-price__price"> <div class="product-unit-price__price">
<span class="product-unit-price__original"> <span class="product-unit-price__original">
<fmt:formatNumber value="${goodsOpt.cnsmrpric}" pattern="#,###"/> <fmt:formatNumber value="${item.cnsmrpric}" pattern="#,###"/>
</span> </span>
<span class="product-unit-price__current"> <span class="product-unit-price__current">
<fmt:formatNumber value="${goodsOpt.slepric}" pattern="#,###"/> <fmt:formatNumber value="${item.slepric}" pattern="#,###"/>
</span> </span>
</div> </div>
<div class="product-unit-price__sale"> <div class="product-unit-price__sale">
<span class="percent"><c:out value = "${goodsOpt.slePercent}"/>%</span> <span class="percent"><c:out value = "${item.slePercent}"/>%</span>
</div> </div>
</c:if>
</c:forEach>
</div> </div>
<span class="product-unit-price__monthly-payment"><c:out value = "${item.srtDc}"/></span> <span class="product-unit-price__monthly-payment"><c:out value = "${item.srtDc}"/></span>
</div> </div>
<div class="product-unit-rating"> <div class="product-unit-rating">
<i class="icon icon_rating-star"></i> <i class="icon icon_rating-star"></i>
<c:forEach var = "evlInfo" items="${goodsList.goodsRvwEvlList}"> <span class="product-unit-rating__score"><c:out value = "${item.avgEvlScore}"/></span>
<c:if test = "${evlInfo.goodsInnb eq item.goodsInnb}"> <span class="product-unit-rating__count">(<fmt:formatNumber value="${item.cntBbsctt}" pattern="#,###"/>)</span>
<span class="product-unit-rating__score"><c:out value = "${evlInfo.avgEvlScore}"/>${goodsOpt.goodInnb}</span>
<span class="product-unit-rating__count">(<fmt:formatNumber value="${evlInfo.cntBbsctt}" pattern="#,###"/>)</span>
</c:if>
</c:forEach>
</div> </div>
</div> </div>
</div> </div>
</c:if> </c:if>
</c:forEach> </c:forEach>
</div> </div>
<c:if test="${fn:length(goodsList) gt 4}">
<div class="four-row-slick__btn-container"> <div class="four-row-slick__btn-container">
<button class="four-row-slick__prev"> <button class="relate-goods-slick__prev">
<i class="icon icon_prev02"></i> <i class="icon icon_prev02"></i>
<span class="visually-hidden">이전</span> <span class="visually-hidden">이전</span>
</button> </button>
<button class="four-row-slick__next"> <button class="relate-goods-slick__next">
<i class="icon icon_next02"></i> <i class="icon icon_next02"></i>
<span class="visually-hidden">다음</span> <span class="visually-hidden">다음</span>
</button> </button>
</div> </div>
</c:if>
</div> </div>
</section> </section>
</div> </div>

View File

@@ -1413,7 +1413,7 @@
</c:if> </c:if>
<%-------------------------------%> <%-------------------------------%>
<%--연관상품영역--%> <%--연관상품영역--%>
<c:if test="${bbsInfo.recomendGoodsExpsrAt eq 'Y' && not empty goodsList.relateInfoList}"> <c:if test="${bbsInfo.recomendGoodsExpsrAt eq 'Y' && not empty goodsList}">
<section class="main-section main-section__category-type"> <section class="main-section main-section__category-type">
<div class="main-section-header"> <div class="main-section-header">
<div class="main-section-title"> <div class="main-section-title">
@@ -1423,9 +1423,9 @@
</div> </div>
</div> </div>
<div class="product-list-vertical-twoAndaHalf"> <div class="product-list-vertical-twoAndaHalf">
<div class="swiper product-list-vertical-twoAndaHalf__swiper"> <div class="swiper ${fn:length(goodsList) gt 4 ? 'product-list-vertical-twoAndaHalf__swiper' : ''}">
<div class="swiper-wrapper"> <div class="swiper-wrapper">
<c:forEach var = "item" items="${goodsList.relateInfoList}"> <c:forEach var = "item" items="${goodsList}">
<c:if test = "${not empty item.goodsInnb}"> <c:if test = "${not empty item.goodsInnb}">
<div class="swiper-slide"> <div class="swiper-slide">
<div class="product-unit"> <div class="product-unit">
@@ -1442,17 +1442,13 @@
</c:choose> </c:choose>
</div> </div>
</c:if> </c:if>
<c:forEach var="img" items="${goodsList.relateImgList}">
<c:if test="${item.goodsInnb eq img.goodsInnb}">
<a style="cursor:pointer" loading="lazy" <a style="cursor:pointer" loading="lazy"
onclick = "fn_move_goods_dtl(<c:out value="${item.goodsInnb}"/>)"> onclick = "fn_move_goods_dtl(<c:out value="${item.goodsInnb}"/>)">
<spring:eval expression="@environment.getProperty('sopmalfo.common.fileupload.cdnurl')" var="cdnurl"/> <spring:eval expression="@environment.getProperty('sopmalfo.common.fileupload.cdnurl')" var="cdnurl"/>
<img src="<c:out value = "${cdnurl}${img.img}"/>" <img src="<c:out value = "${cdnurl}${item.img}"/>"
onerror="this.src='/pc/images/image_placeholder.png'" onerror="this.src='/pc/images/image_placeholder.png'"
alt="해당 이미지에 대한 설명"> alt="해당 이미지에 대한 설명">
</a> </a>
</c:if>
</c:forEach>
</div> </div>
<div class="product-unit-info"> <div class="product-unit-info">
<c:set var="iconString" value="${item.goodsIconCd}" /> <c:set var="iconString" value="${item.goodsIconCd}" />
@@ -1481,32 +1477,24 @@
</a> </a>
</div> </div>
<div class="product-unit-price"> <div class="product-unit-price">
<c:forEach var="goodsOpt" items="${goodsList.relateGoodsOptList}">
<c:if test="${item.goodsInnb eq goodsOpt.goodsInnb && goodsOpt.stdrDvAt eq 'Y'}">
<div class="product-unit-price__price"> <div class="product-unit-price__price">
<span class="product-unit-price__original"> <span class="product-unit-price__original">
<fmt:formatNumber value="${goodsOpt.cnsmrpric}" pattern="#,###"/> <fmt:formatNumber value="${item.cnsmrpric}" pattern="#,###"/>
</span> </span>
<span class="product-unit-price__current"> <span class="product-unit-price__current">
<fmt:formatNumber value="${goodsOpt.slepric}" pattern="#,###"/> <fmt:formatNumber value="${item.slepric}" pattern="#,###"/>
</span> </span>
</div> </div>
<div class="product-unit-price__sale"> <div class="product-unit-price__sale">
<span class="percent"><c:out value = "${goodsOpt.slePercent}"/>%</span> <span class="percent"><c:out value = "${item.slePercent}"/>%</span>
</div> </div>
</c:if>
</c:forEach>
</div> </div>
<span class="product-unit-price__monthly-payment"><c:out value = "${item.srtDc}"/></span> <span class="product-unit-price__monthly-payment"><c:out value = "${item.srtDc}"/></span>
</div> </div>
<div class="product-unit-rating"> <div class="product-unit-rating">
<i class="icon icon_rating-star"></i> <i class="icon icon_rating-star"></i>
<c:forEach var = "evlInfo" items="${goodsList.goodsRvwEvlList}"> <span class="product-unit-rating__score"><c:out value = "${item.avgEvlScore}"/></span>
<c:if test = "${evlInfo.goodsInnb eq item.goodsInnb}"> <span class="product-unit-rating__count">(<fmt:formatNumber value="${item.cntBbsctt}" pattern="#,###"/>)</span>
<span class="product-unit-rating__score"><c:out value = "${evlInfo.avgEvlScore}"/>${goodsOpt.goodInnb}</span>
<span class="product-unit-rating__count">(<fmt:formatNumber value="${evlInfo.cntBbsctt}" pattern="#,###"/>)</span>
</c:if>
</c:forEach>
</div> </div>
</div> </div>
</div> </div>