댓글에서 평점을 입력받아 글보기 화면과 글 리스트 화면에 해당 점수 평점을 출력하는 게시판을 만들어보겠습니다.
본 팁은 댓글의 추천수를 활용하여 게시글의 평점을 매기는 시스템입니다.
고로, 댓글 자체의 추천 시스템은 활용할 수가 없습니다.
댓글 자체에 좋아요, 싫어요를 할 수 있는 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) 리스트 화면
- 글정렬 순서를 추천수+내림정렬로 하면 됩니다.