댓글에서 평점을 입력받아 글보기 화면과 글 리스트 화면에 해당 점수 평점을 출력하는 게시판을 만들어보겠습니다.
본 팁은 댓글의 추천수를 활용하여 게시글의 평점을 매기는 시스템입니다.
고로, 댓글 자체의 추천 시스템은 활용할 수가 없습니다.
댓글 자체에 좋아요, 싫어요를 할 수 있는 voted_count와 blamed_count 컬럼 중 voted_count를 사용하기 때문에 그렇습니다.
그 밖에 활용할만한 카운트 컬럼이 없더군요 ㅠ
해당 팁은 기존 board 모듈의 콘트롤러를 수정하고 쿼리문을 추가하고 하는 식으로 개발된 팁입니다.
가능하신 분은 별도 모듈을 개발하셔서 댓글을 작성할 때 해당 모듈로 해당 함수를 호출하는 식으로 개발하시면 될듯합니다.
※ document.getDocumentList가 호출되는 시점에서 해당 모듈에 있는 함수로 트리거로 통해 바꿔치기 하는 식으로 개발하시면, 코어는 건드릴 필요없이 작업이 가능합니다.
아직 제 수준은 거기까지가 안되므로 ;ㅁ;
1. 수정할 파일목록
1) 댓글 쓰기
/modules/board/skins/sketchbook5_review/_comment_write.html
2) 글보기 파일
/modules/board/skins/sketchbook5_review/_read_review.html
3) 게시판 모듈 코멘트 쓰기 쿼리문
/modules/board/tpl/filter/insert_comment.xml
4) 게시판 모듈 콘트롤러 파일
/modules/board/board.controller.php
5)
/modules/board/queries/insert_comment.xml
6)
/modules/board/queries/plusPackageStar.xml
7)
/modules/board/queries/voteAdd.xml
8)
/modules/board/queries/voteRemove.xml
9)
/modules/board/queries/voteSum.xml
_comment_write.html
<input type="hidden" name="star_point" value="" />
<ul class="starPoint">
<li><input type="radio" name="grd" id="grd1"><label for="grd1"><span class="grd grd1">1</span></label></li>
<li><input type="radio" name="grd" id="grd2"><label for="grd2"><span class="grd grd2">2</span></label></li>
<li><input type="radio" name="grd" id="grd3"><label for="grd3"><span class="grd grd3">3</span></label></li>
<li><input type="radio" name="grd" id="grd4"><label for="grd4"><span class="grd grd4">4</span></label></li>
<li><input type="radio" name="grd" id="grd5"><label for="grd5"><span class="grd grd5">5</span></label></li>
</ul>
코멘트 작성 form 안에 위 코드를 추가합니다.
_read_review.html
_read.html 파일에 인클루드되는 파일입니다.
{@
$mi->tmb_effect='N';
if(!$mi->rd_tl_font) $mi->rd_tl_font='ngeb';
if(!$mi->rd_top_font) $mi->rd_top_font='ngeb';
if(!$mi->rd_btm_font) $mi->rd_btm_font='ngeb';
if(!$mi->prev_next_cut_size) $mi->prev_next_cut_size=60;
$sns_link=$oDocument->getPermanentUrl().'?l='.$lang_type;
$sns_title=urlencode($oDocument->getTitle());
}
<include target="_read_cat.html" cond="$mi->default_style=='review'"/>
<div class="lst_sort">
<a class="sort1" href="{getUrl('mid',$mid,'order_type','','sort_index','','document_srl','')}">인기</a>
<a class="sort2" href="{getUrl('mid',$mid,'order_type','desc','sort_index','regdate','document_srl','')}">신규등록</a>
<a class="sort3" href="?mid={$mid}&order_type=desc&sort_index=regdate&act=dispBoardTagList">브랜드별</a>
<div class="cat_m">카테고리별</div>
</div>
<div class="rd<!--@if(!$mi->rd_nav_style)--> rd_nav_style2<!--@end--><!--@if($mi->default_style=='blog')--> rd_blog {$mi->blog_style}<!--@end--> clear" style="padding:{$mi->rd_padding};" data-docSrl="{$oDocument->document_srl}">
<!--// Header -->
<div class="rd_hd clear">
<!--브랜드명 이미지-->
<div class="brand">
<include target="./assets/brand.html" />
</div>
<!--이미지 썸네일-->
<div class="thumb">
<block loop="$oDocument->getUploadedFiles()=>$key,$file">
<!--@if($key==0)-->
<block cond="!$mi->img_insert2">
{@
$ext=substr($file->source_filename, -4);
$ext=strtolower($ext);
$extImg=in_array($ext,array('.jpg','jpeg','.gif','.png'));
}
</block>
<block cond="$mi->img_insert2">
{@
$ext=substr($file->source_filename, -15);
$ext=strtolower($ext);
$extImg=in_array($ext,array('_rd_gallery.jpg','rd_gallery.jpeg','_rd_gallery.gif','_rd_gallery.png'));
}
</block>
<img cond="$extImg" src="{$file->uploaded_filename}" alt="" />
<!--@end-->
</block>
</div>
<!--브랜드명 태그 -->
{@ $tag_list=$oDocument->get('tag_list') }
<div class="info_brandname">{$tag_list[0]}</div>
<!--제목-->
<div class="title">{$oDocument->getTitle()}</div>
<!--별점-->
{@
//별점포인트
$star_point = $oDocument->get('voted_count')/$oDocument->getCommentcount();
$star_point_format = number_format((float)$star_point, 2, '.', '');
//별점퍼센트
$starRating = $oDocument->get('voted_count')*10*2/$oDocument->getCommentcount();
}
<div class="starbox">
<div class="star_rating"><span style="width:{$starRating}%"></span></div>
<div class="star_point">{$star_point_format}점</div>
<div class="star_comment">({$oDocument->getCommentcount()}명)</div>
</div>
<!--카테고리-->
<div class="cat">{$category_list[$oDocument->get('category_srl')]->title}부문</div>
<!--제품정보(사용자정의)-->
<block loop="$oDocument->getExtraVars() => $key,$val">
<span class="info_size" cond="$val->eid=='info_size'">{$val->getValueHTML()}</span>
</block>
/ <block loop="$oDocument->getExtraVars() => $key,$val">
<span class="info_size" cond="$val->eid=='info_price'">{$val->getValueHTML()}</span>
</block>
</div>
<!--// Body -->
<div class="rd_body clear">
<article>{$oDocument->getContent(false)}</article>
<!--최저가 바로가기(사용자정의)-->
<block loop="$oDocument->getExtraVars() => $key,$val">
<div class="info_link" cond="$val->eid=='info_link' && $val->getValueHTML()">
<a href="{$val->getValueHTML()}" target="_blank">최저가 바로가기</a>
</div>
</block>
</div>
<!--// Footer -->
<div class="rd_ft">
<div class="starbox">
<div class="star_point">{$star_point_format}점</div>
<div class="star_comment">({$oDocument->getCommentcount()}명 평가)</div>
<div class="star_rating">
<span style="width:{$starRating}%"></span>
</div>
</div>
<div class="graph_wrap">
{@
$oDB = &DB::getInstance();
$query = $oDB->_query('select * from xe_member_message where receiver_srl = '.$logged_info->member_srl.' AND message_type = "R" ORDER BY regdate DESC limit 0, 5');
$result = $oDB->_fetch($query);
$oMemberModel =& getModel('member');
$member_info = $oMemberModel->getMemberInfoByMemberSrl($val->sender_srl);
}
{@
$oDB = &DB::getInstance();
$query5 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 5');
$result5 = $oDB->_fetch($query5);
$query4 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 4');
$result4 = $oDB->_fetch($query4);
$query3 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 3');
$result3 = $oDB->_fetch($query3);
$query2 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 2');
$result2 = $oDB->_fetch($query2);
$query1 = $oDB->_query('select count(*) as cnt from xe_comments where document_srl = '.$oDocument->document_srl.' and voted_count = 1');
$result1 = $oDB->_fetch($query1);
}
<div class="review_box">
<canvas id="chart-1"></canvas>
</div>
<script src="./assets/Chart.bundle.js"></script>
<script src="./assets/utils.js"></script>
<load target="js/chart.js" type="body" />
<script>
var presets = window.chartColors;
var utils = Samples.utils;
var options = {
maintainAspectRatio: false,
spanGaps: false,
elements: {
line: {
tension: 0.100001
}
},
plugins: {
filler: {
propagate: false
}
},
scales: {
xAxes: [{
// x 텍스트
display: true,
ticks: {
autoSkip: false,
maxRotation: 0
},
//x 가이드라인
gridLines: {
display:false
}
}],
yAxes: [{
// y 텍스트
display: true,
// y가이드라인
gridLines: {
display:true
}
}]
}
};
[false, 'origin', 'start', 'end'].forEach(function(boundary, index) {
new Chart('chart-' + index, {
type: 'line',
data: {
//labels : ["최악","별로","쏘쏘","굿굿","짱짱"],
labels : ["","","","",""],
datasets: [{
backgroundColor: utils.transparentize(presets.red),
borderColor: presets.red,
//data : [2,6,9,26,45],
data : [{$result1->cnt},{$result2->cnt},{$result3->cnt},{$result4->cnt},{$result5->cnt}],
label: '',
fill: boundary
}]
},
options: utils.merge(options, {
title: {
text: '',
display: true
},
//responsive: true,
// 타이틀
legend: {
display: false
}
})
});
});
</script>
</div>
</div>
<!--// Read Footer Navi -->
<div class="rd_ft_nav clear">
<a cond="$mi->default_style!='viewer' && $mi->rd_ft_nav" class="btn_img fl" href="{getUrl('document_srl','')}"><i class="fa fa-bars"></i> {$lang->cmd_list}</a>
<!--// SNS small -->
<include cond="!$mi->to_sns" target="_read_sns.html" />
<!--// Read Nav -->
{@ $ft_read_nav=1}
<include target="_read_nav.html" />
{@ $ft_read_nav=''}
</div>
<!--// Comment -->
<block cond="$mi->cmt_wrt=='sns'">
{@
$mi->cmt_wrt_position='';
$mi->profile_img='';
}
</block>
<div cond="!$mi->viewer_cmt" class="fdb_lst_wrp {$mi->fdb_style} {$mi->profile_img}">
<div id="{$oDocument->document_srl}_comment" class="fdb_lst clear {$mi->fdb_nav} {$mi->cmt_wrt_position}">
<!--// Editor -->
<!--@if($mi->cmt_wrt=='sns')-->
<!--// SocialXE -->
<div cond="$oDocument->allowComment() && $mi->select_editor!='N'" class="editor_select bubble fr m_no" title="{$lang->noti_rfsh}">
<a class="tg_btn2" href="#" data-href="#editor_select"><em class="fa fa-info-circle bd_info_icon"></em> {$lang->select_editor}</a>
<div cond="$rd_idx==0" id="editor_select" class="editor_select_cnt tg_cnt2 wrp"><button type="button" class="tg_blur2"></button>
<a class="on"|cond="$mi->cmt_wrt=='simple'" href="#" onclick="jQuery.cookie('bd_editor','simple');location.reload();return false"><em>✔ </em>{$lang->textarea}</a>
<a class="on"|cond="$mi->cmt_wrt=='editor'" href="#" onclick="jQuery.cookie('bd_editor','editor');location.reload();return false"><em>✔ </em>{$lang->wysiwyg}</a>
<a class="on"|cond="$mi->cmt_wrt=='sns'" href="#" onclick="jQuery.cookie('bd_editor','sns');location.reload();return false"><em>✔ </em>{$lang->sxc_editor}</a>
<i class="edge"></i><button type="button" class="tg_blur2"></button>
<!--// ie8; --><i class="ie8_only bl"></i><i class="ie8_only br"></i>
</div>
</div>
<img class="zbxe_widget_output" widget="socialxe_comment" skin="sketchbook5" colorset="{$mi->colorset}" document_srl="{$oDocument->document_srl}" content_link="{getFullUrl('','document_srl',$oDocument->document_srl,'dummy','1')}" content_title="{htmlspecialchars($oDocument->getTitleText())}" enter_send="N" auto_view_sub="Y"|cond="!$mi->auto_view_sub" style="overflow:visible" />
<!--@else-->
<!--// Comment Write : Top -->
<include cond="$oDocument->allowComment() && !$mi->cmt_wrt_position" target="_comment_write.html" />
<!--// Comment List -->
<div id="cmtPosition" aria-live="polite"><include target="_comment.html" /></div>
<!--// Comment Write : Bottom -->
<include cond="$oDocument->allowComment() && $mi->cmt_wrt_position=='cmt_wrt_btm'" target="_comment_write.html" />
<!--@end-->
</div>
</div>
</div>
<!--// 목록 보이지 않을 때 보이는 하단 메뉴 -->
<div cond="$mi->rd_lst && $mi->default_style!='blog'" class="btm_mn clear" style="border-top:1px solid #CCC">
<div class="fl">
<a class="btn_img" href="{getUrl('document_srl','')}"><i class="fa fa-bars"></i> {$lang->cmd_list}</a>
</div>
</div>
<hr id="rd_end_{$oDocument->document_srl}" class="rd_end clear" />
insert_comment.xml
<filter name="insert_comment" module="board" act="procBoardInsertComment">
<form>
<node target="star_point" required="true" />
<node target="document_srl" required="true" />
<node target="nick_name" required="true" maxlength="20"/>
<node target="password" required="true" />
<node target="email_address" maxlength="250" filter="email" />
<node target="homepage" maxlength="250" filter="url" />
<node target="content" required="true" minlength="1" />
</form>
<parameter>
<param name="mid" target="mid" />
<param name="document_srl" target="document_srl" />
<param name="comment_srl" target="comment_srl" />
<param name="parent_srl" target="parent_srl" />
<param name="nick_name" target="nick_name" />
<param name="password" target="password" />
<param name="email_address" target="email_address" />
<param name="homepage" target="homepage" />
<param name="content" target="content" />
<param name="is_secret" target="is_secret" />
<param name="notify_message" target="notify_message" />
<param name="star_point" target="star_point" />
</parameter>
<response callback_func="completeInsertComment">
<tag name="error" />
<tag name="message" />
<tag name="mid" />
<tag name="document_srl" />
<tag name="comment_srl" />
</response>
</filter>
코멘트를 작성할 때 star_point를 추가해주는 파일입니다.
<node target="star_point" required="true" />
<param name="star_point" target="star_point" />
기본 inset_comment.xml 에서 이 부분만 추가되었습니다.
board.controller.php
게시판 모듈 콘트롤러 파일입니다.
코멘트를 작성할 때도 동작하는 파일입니다.
334번째 줄에 다음과 같은 구문을 찾아주세요.
if($comment->comment_srl != $obj->comment_srl) {
...
}
오른쪽 처럼 수정하시면 됩니다.
336줄
$obj->voted_count = $obj->star_point;
349줄
$obj->voted_count = $obj->star_point;
369줄
$star_obj->module_srl = $this->module_srl;
$star_obj->document_srl = $obj->document_srl;
$star_obj->voted_count = $oDocument->get('voted_count')+$obj->star_point;
$output = executeQuery('board.voteAdd', $star_obj);
//$star_args->package_srl = $args->package_srl;
//$star_args->voted = $package->voted+$args->star_point;
//$output = executeQuery('resource.plusPackageStar', $star_args);
//$output = executeQuery('document.procDocumentVoteUp', $star_obj);
// $document_srl = Context::get('target_srl');
// $oDocumentModel = getModel('document');
// $oDocumentController = getController('document');
// $document_srl = Context::get('document_srl');
// return $oDocumentController->updateVotedCount($document_srl);
board.controller.php에서 코멘트 삭제시 차감하는 코드도 추가해야합니다.
function procBoardDeleteComment() 부분을 찾아서 반드시 그 바로 아래 첫번째줄에 작성해야합니다.
// 댓글 삭제 시 게시물 추천수 차감하기
$obj = Context::getRequestVars();
$obj->module_srl = $this->module_srl;
$document_srl = Context::get('document_srl');
$oDocumentModel = &getModel('document');
$oDocument = $oDocumentModel->getDocument($document_srl);
$comment_srl = Context::get('comment_srl');
$oCommentModel = getModel('comment');
$oComment = $oCommentModel->getComment($comment_srl, FALSE, FALSE);
$star_obj->module_srl = $this->module_srl;
$star_obj->document_srl = $obj->document_srl;
$star_obj->voted_count = $oDocument->get('voted_count')-$oComment->get('voted_count');
$output = executeQuery('board.voteAdd', $star_obj);
<스크린샷>
1) 평점+댓글쓰기 화면
2) 리스트 화면
- 글정렬 순서를 추천수+내림정렬로 하면 됩니다.