评价管理

This commit is contained in:
devil_gong 2019-05-14 18:39:05 +08:00
parent 3e7c4a1f12
commit 1937401189
8 changed files with 595 additions and 79 deletions

View File

@ -0,0 +1,231 @@
<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2019 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\admin\controller;
use app\service\GoodsCommentsService;
/**
* 商品评价管理
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-01T21:51:08+0800
*/
class Goodscomments extends Common
{
/**
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-03T12:39:08+0800
*/
public function __construct()
{
// 调用父类前置方法
parent::__construct();
// 登录校验
$this->IsLogin();
// 权限校验
$this->IsPower();
}
/**
* 问答列表
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-06T21:31:53+0800
*/
public function Index()
{
// 参数
$params = input();
// 分页
$number = MyC('admin_page_number', 10, true);
// 条件
$where = GoodsCommentsService::GoodsCommentsListWhere($params);
// 获取总数
$total = GoodsCommentsService::GoodsCommentsTotal($where);
// 分页
$page_params = array(
'number' => $number,
'total' => $total,
'where' => $params,
'page' => isset($params['page']) ? intval($params['page']) : 1,
'url' => MyUrl('admin/answer/index'),
);
$page = new \base\Page($page_params);
$this->assign('page_html', $page->GetPageHtml());
// 获取列表
$data_params = array(
'm' => $page->GetPageStarNumber(),
'n' => $number,
'where' => $where,
'is_public' => 0,
);
$data = GoodsCommentsService::GoodsCommentsList($data_params);
$this->assign('data_list', $data['data']);
// 状态
$this->assign('common_is_show_list', lang('common_is_show_list'));
// 是否
$this->assign('common_is_text_list', lang('common_is_text_list'));
// 参数
$this->assign('params', $params);
return $this->fetch();
}
/**
* [SaveInfo 添加/编辑页面]
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-14T21:37:02+0800
*/
public function SaveInfo()
{
// 参数
$params = input();
// 数据
$data = [];
if(!empty($params['id']))
{
// 获取列表
$data_params = array(
'm' => 0,
'n' => 1,
'where' => ['id'=>intval($params['id'])],
'field' => '*',
);
$ret = GoodsCommentsService::AnswerList($data_params);
// 内容
if(!empty($ret['data'][0]['content']))
{
$ret['data'][0]['content'] = str_replace('<br />', "\n", $ret['data'][0]['content']);
}
// 回复内容
if(!empty($ret['data'][0]['reply']))
{
$ret['data'][0]['reply'] = str_replace('<br />', "\n", $ret['data'][0]['reply']);
}
$data = empty($ret['data'][0]) ? [] : $ret['data'][0];
}
$this->assign('data', $data);
// 状态
$this->assign('common_is_show_list', lang('common_is_show_list'));
// 是否
$this->assign('common_is_text_list', lang('common_is_text_list'));
// 参数
unset($params['id']);
$this->assign('params', $params);
return $this->fetch();
}
/**
* [Save 保存]
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-25T22:36:12+0800
*/
public function Save()
{
// 是否ajax请求
if(!IS_AJAX)
{
return $this->error('非法访问');
}
// 开始处理
$params = input();
return GoodsCommentsService::AnswerSave($params);
}
/**
* 问答删除
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-15T11:03:30+0800
*/
public function Delete()
{
// 是否ajax请求
if(!IS_AJAX)
{
return $this->error('非法访问');
}
// 开始处理
$params = input();
$params['user_type'] = 'admin';
return GoodsCommentsService::AnswerDelete($params);
}
/**
* 问答回复处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2018-03-28T15:07:17+0800
*/
public function Reply()
{
// 是否ajax请求
if(!IS_AJAX)
{
return $this->error('非法访问');
}
// 开始处理
$params = input();
return GoodsCommentsService::AnswerReply($params);
}
/**
* 状态更新
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-01-12T22:23:06+0800
*/
public function StatusUpdate()
{
// 是否ajax请求
if(!IS_AJAX)
{
return $this->error('非法访问');
}
// 开始处理
$params = input();
return GoodsCommentsService::AnswerStatusUpdate($params);
}
}
?>

View File

@ -0,0 +1,251 @@
{{include file="public/header" /}}
<!-- right content start -->
<div class="content-right">
<div class="content">
<!-- form start -->
<form class="am-form form-validation form-search" method="post" action="{{:MyUrl('admin/goodscomments/index')}}" request-type="form">
<div class="thin">
<div class="am-input-group am-input-group-sm am-fl so">
<input type="text" autocomplete="off" name="keywords" class="am-radius" placeholder="用户名/昵称/手机/邮箱/商品标题" value="{{if !empty($params.keywords)}}{{$params.keywords}}{{/if}}" />
<span class="am-input-group-btn">
<button class="am-btn am-btn-default am-radius" type="submit" data-am-loading="{spinner:'circle-o-notch', loadingText:'搜索中...'}">搜索</button>
</span>
</div>
<label class="am-fl thin_sub more-submit">
更多筛选条件
{{if isset($params['is_more']) and $params['is_more'] eq 1}}
<input type="checkbox" name="is_more" value="1" id="is_more" checked />
<i class="am-icon-angle-up"></i>
{{else /}}
<input type="checkbox" name="is_more" value="1" id="is_more" />
<i class="am-icon-angle-down"></i>
{{/if}}
</label>
</div>
<table class="so-list more-where {{if !isset($params['is_more'])}}none{{/if}}">
<tbody>
<tr>
<td>
<span>显隐:</span>
<select name="is_show" class="chosen-select" data-placeholder="是否显示...">
<option value="-1">是否显示...</option>
{{foreach $common_is_show_list as $v}}
<option value="{{$v.id}}" {{if isset($params['is_show']) and $params['is_show'] eq $v['id']}}selected{{/if}}>{{$v.name}}</option>
{{/foreach}}
</select>
</td>
<td>
<span>回复:</span>
<select name="is_reply" class="chosen-select" data-placeholder="是否回复...">
<option value="-1">是否回复...</option>
{{if !empty($common_is_text_list)}}
{{foreach $common_is_text_list as $v}}
<option value="{{$v.id}}" {{if isset($params['is_reply']) and $params['is_reply'] eq $v['id']}}selected{{/if}}>{{$v.name}}</option>
{{/foreach}}
{{/if}}
</select>
</td>
</tr>
<tr>
<td class="time">
<span>时间:</span>
<span>
<input type="text" autocomplete="off" name="time_start" class="am-form-field am-input-sm am-radius Wdate" placeholder="起始时间" value="{{if !empty($params.time_start)}}{{$params.time_start}}{{/if}}" data-validation-message="日期格式有误" onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" autocomplete="off" /><i class="am-icon-calendar"></i>
</span>
<em class="text-grey">~</em>
<span>
<input type="text" autocomplete="off" name="time_end" class="am-form-field am-input-sm am-radius Wdate" placeholder="结束时间" value="{{if !empty($params.time_end)}}{{$params.time_end}}{{/if}}" pattern="^[0-9]{4}-[0-9]{2}-[0-9]{2}$" data-validation-message="日期格式有误" onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" autocomplete="off" /><i class="am-icon-calendar"></i>
</span>
</td>
<td>
<button type="submit" class="am-btn am-btn-primary am-radius am-btn-xs btn-loading-example" data-am-loading="{spinner:'circle-o-notch', loadingText:'搜索中...'}">搜索</button>
<a href="{{:MyUrl('admin/goodscomments/index')}}" class="am-btn am-btn-warning am-radius am-btn-sm reset-submit">清除条件</a>
</td>
</tr>
</tbody>
</table>
</form>
<!-- form end -->
<!-- operation start -->
<div class="am-g m-t-15">
<a href="{{:MyUrl('admin/goodscomments/saveinfo')}}" class="am-btn am-btn-secondary am-radius am-btn-xs am-icon-plus"> 新增</a>
</div>
<!-- operation end -->
<!-- list start -->
<table class="am-table am-table-striped am-table-hover am-text-middle m-t-10">
<thead>
<tr>
<th class="am-hide-md-down">用户信息</th>
<th class="am-hide-sm-only">业务类型</th>
<th class="am-hide-sm-only">内容</th>
<th class="am-hide-sm-only">回复内容</th>
<th class="am-hide-sm-only">匿名</th>
<th class="am-hide-sm-only">回复时间</th>
<th class="am-hide-sm-only">创建时间</th>
<th>是否显示</th>
<th>更多</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{{if !empty($data_list)}}
{{foreach $data_list as $v}}
<tr id="data-list-{{$v.id}}" {{if $v['is_show'] eq 0}}class="am-active"{{/if}}>
<td class="user-info am-hide-md-down">
{{if !empty($v['user'])}}
<img src="{{$v.user.avatar}}" alt="{{$v.user.user_name_view}}" class="am-img-thumbnail am-radius am-align-left" />
<ul class="user-base">
<li>名称:{{if empty($v['user']['username'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.username}}{{/if}}</li>
<li>昵称:{{if empty($v['user']['nickname'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.nickname}}{{/if}}</li>
<li>手机:{{if empty($v['user']['mobile'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.mobile}}{{/if}}</li>
<li>邮箱:{{if empty($v['user']['email'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.email}}{{/if}}</li>
</ul>
{{else /}}
用户信息异常
{{/if}}
</td>
<td>{{$v.business_type}}</td>
<td class="am-hide-sm-only">
<div class="reply-content">
{{$v.content|raw}}
</div>
</td>
<td class="am-hide-sm-only">
{{if $v['is_reply'] eq 1 and !empty($v['reply'])}}
<div class="reply-content">
{{$v.reply|raw}}
</div>
<p>{{$v.reply_time_time}}</p>
{{else /}}
<span class="cr-ddd">未回复</span>
{{/if}}
</td>
<td class="am-hide-sm-only">{{$v.is_anonymous_text}}</td>
<td class="am-hide-sm-only">{{$v.add_time_time}}</td>
<td>
<a href="javascript:;" class="am-icon-btn am-icon-check submit-state {{if $v['is_show'] eq 1}}am-success{{else /}}am-default{{/if}}" data-url="{{:MyUrl('admin/goodscomments/statusupdate')}}" data-id="{{$v.id}}" data-state="{{$v['is_show']}}" data-is-update-status="1"></a>
</td>
<td>
<span class="am-icon-caret-down c-p" data-am-modal="{target: '#my-popup{{$v.id}}'}"> 查看更多</span>
<div class="am-popup am-radius" id="my-popup{{$v.id}}">
<div class="am-popup-inner">
<div class="am-popup-hd">
<h4 class="am-popup-title">详情内容</h4>
<span data-am-modal-close
class="am-close">&times;</span>
</div>
<div class="am-popup-bd">
<dl class="dl-content">
<dt>用户信息</dt>
<dd>
{{if !empty($v['user'])}}
<img src="{{$v.user.avatar}}" alt="{{$v.user.user_name_view}}" class="am-img-thumbnail am-radius am-align-left" />
<ul class="user-base">
<li>名称:{{if empty($v['user']['username'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.username}}{{/if}}</li>
<li>昵称:{{if empty($v['user']['nickname'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.nickname}}{{/if}}</li>
<li>手机:{{if empty($v['user']['mobile'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.mobile}}{{/if}}</li>
<li>邮箱:{{if empty($v['user']['email'])}}<span class="cr-ccc">未填写</span>{{else /}}{{$v.user.email}}{{/if}}</li>
</ul>
{{else /}}
用户信息异常
{{/if}}
</dd>
<dt>业务类型</dt>
<dd>{{$v.business_type}}</dd>
<dt>内容</dt>
<dd>{{$v.content|raw}}</dd>
<dt>匿名</dt>
<dd>{{$v.is_anonymous_text}}</dd>
<dt>是否显示</dt>
<dd>{{if empty($v['is_show_text'])}}<span class="cr-ddd">未填写</span>{{else /}}{{$v.is_show_text}}{{/if}}</dd>
<dt>回复内容</dt>
<dd>
{{if $v['is_reply'] eq 1 and !empty($v['reply'])}}
<div class="reply-content">
{{$v.reply|raw}}
</div>
<p>{{$v.reply_time_time}}</p>
{{else /}}
<span class="cr-ddd">未回复</span>
{{/if}}
</dd>
<dt>匿名</dt>
<dd>{{$v.reply_time}}</dd>
<dt>创建时间</dt>
<dd>{{$v.add_time_time}}</dd>
</dl>
</div>
</div>
</div>
</td>
<td class="view-operation">
<a href="{{:MyUrl('admin/goodscomments/saveinfo', array_merge($params, ['id'=>$v['id']]))}}">
<button class="am-btn am-btn-secondary am-btn-xs am-radius am-icon-edit"> 编辑</button>
</a>
{{if $v['is_reply'] eq 0}}
<button class="am-btn am-btn-success am-btn-xs am-radius submit-reply am-icon-gavel" data-am-modal="{target: '#my-popup-reply'}" data-json='{{:json_encode($v)}}'> 回复</button>
{{/if}}
<button class="am-btn am-btn-danger am-btn-xs am-radius am-icon-trash-o submit-delete" data-url="{{:MyUrl('admin/goodscomments/delete')}}" data-id="{{$v.id}}"> 删除</button>
</td>
</tr>
{{/foreach}}
{{/if}}
</tbody>
</table>
{{if empty($data_list)}}
<div class="table-no"><i class="am-icon-warning"></i> 没有相关数据</div>
{{/if}}
<!-- list end -->
<!-- 处理窗口 -->
<div class="am-popup am-radius" id="my-popup-reply">
<div class="am-popup-inner">
<div class="am-popup-hd">
<h4 class="am-popup-title">回复</h4>
<span data-am-modal-close class="am-close">&times;</span>
</div>
<div class="am-popup-bd">
<dl class="dl-content">
<dt>联系人</dt>
<dd>
<span class="reply-name"></span> - <span class="reply-tel"></span>
</dd>
</dl>
<form class="am-form form-validation" action="{{:MyUrl('admin/goodscomments/reply')}}" method="POST" request-type="ajax-reload" enctype="multipart/form-data">
<div class="am-form-group">
<label>回复内容</label>
<textarea name="reply" rows="5" class="am-radius" placeholder="回复内容格式 2~230 个字符" data-validation-message="回复内容格式 2~230 个字符" maxlength="230"></textarea>
</div>
<div class="am-form-group reply-submit am-form-group-refreshing t-c">
<input type="hidden" name="id" value="" />
<button type="submit" class="am-btn am-btn-success am-radius am-btn-sm" data-am-loading="{loadingText:'处理中...'}" data-status="0">回复</button>
</div>
</form>
</div>
</div>
</div>
<!-- page start -->
{{if !empty($data_list)}}
{{$page_html|raw}}
{{/if}}
<!-- page end -->
</div>
</div>
<!-- right content end -->
<!-- footer start -->
{{include file="public/footer" /}}
<!-- footer end -->

View File

@ -66,7 +66,7 @@ class Goods extends Common
$ret['data'][0]['is_favor'] = ($ret_favor['code'] == 0) ? $ret_favor['data'] : 0;
// 商品评价总数
$ret['data'][0]['comments_count'] = GoodsService::GoodsCommentsTotal($goods_id);
$ret['data'][0]['comments_count'] = GoodsCommentsService::GoodsCommentsTotal(['goods_id'=>$goods_id]);
// 商品收藏总数
$ret['data'][0]['favor_count'] = GoodsService::GoodsFavorTotal(['goods_id'=>$goods_id]);

View File

@ -191,6 +191,7 @@ class Order extends Common
{
$params = input('post.');
$params['user'] = $this->user;
$params['business_type'] = '订单';
return GoodsCommentsService::Comments($params);
} else {
$this->assign('msg', '非法访问');

View File

@ -40,6 +40,11 @@ class GoodsCommentsService
'key_name' => 'id',
'error_msg' => '订单id有误',
],
[
'checked_type' => 'empty',
'key_name' => 'business_type',
'error_msg' => '业务类型标记不能为空',
],
[
'checked_type' => 'isset',
'key_name' => 'goods_id',
@ -109,12 +114,13 @@ class GoodsCommentsService
'shop_id' => $order['shop_id'],
'order_id' => $order_id,
'goods_id' => $goods_id,
'business_type' => $params['business_type'],
'content' => isset($params['content'][$k]) ? htmlspecialchars(trim($params['content'][$k])) : '',
'rating' => isset($params['rating'][$k]) ? intval($params['rating'][$k]) : 0,
'is_anonymous' => isset($params['is_anonymous']) ? min(1, intval($params['is_anonymous'])) : 0,
'add_time' => time(),
];
if(Db::name('OrderComments')->insertGetId($data) <= 0)
if(Db::name('GoodsComments')->insertGetId($data) <= 0)
{
Db::rollback();
return DataReturn('评价内容添加失败', -100);
@ -149,7 +155,7 @@ class GoodsCommentsService
$order_by = empty($params['order_by']) ? 'id desc' : $params['order_by'];
// 获取数据列表
$data = Db::name('OrderComments')->where($where)->limit($m, $n)->order($order_by)->select();
$data = Db::name('GoodsComments')->where($where)->limit($m, $n)->order($order_by)->select();
if(!empty($data))
{
$common_is_text_list = lang('common_is_text_list');
@ -167,9 +173,15 @@ class GoodsCommentsService
$v['user'] = $user;
}
// 订单规格
$spec = Db::name('OrderDetail')->where(['order_id'=>$v['order_id'], 'goods_id'=>$v['goods_id']])->value('spec');
$v['spec'] = empty($spec) ? null : json_decode($spec);
// 业务类型
$msg = null;
switch($v['business_type'])
{
// 订单
case 'order' :
$msg = self::BusinessTypeOrderSpec($v['order_id'], $v['goods_id'], $v['user_id']);
}
$v['msg'] = empty($msg) ? null : $msg;
// 是否
$v['is_reply_text'] = isset($common_is_text_list[$v['is_reply']]) ? $common_is_text_list[$v['is_reply']]['name'] : '';
@ -187,6 +199,40 @@ class GoodsCommentsService
return DataReturn('处理成功', 0, $data);
}
/**
* 订单规格字符串处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-05-14
* @desc description
* @param [int] $order_id [订单id]
* @param [int] $goods_id [商品id]
* @param [int] $user_id [用户id]
* @return [string] [规格字符串]
*/
private static function BusinessTypeOrderSpec($order_id, $goods_id, $user_id = 0)
{
$string = null;
$spec = Db::name('OrderDetail')->where(['order_id'=>$order_id, 'goods_id'=>$goods_id])->value('spec');
if(!empty($spec))
{
$spec = json_decode($spec, true);
if(is_array($spec) && !empty($spec))
{
foreach($spec as $k=>$v)
{
if($k > 0)
{
$string .= ' | ';
}
$string .= $v['type'].''.$v['value'];
}
}
}
return $string;
}
/**
* 商品评论总数
* @author Devil
@ -198,7 +244,7 @@ class GoodsCommentsService
*/
public static function GoodsCommentsTotal($where = [])
{
return (int) Db::name('OrderComments')->where($where)->count();
return (int) Db::name('GoodsComments')->where($where)->count();
}
/**
@ -220,7 +266,7 @@ class GoodsCommentsService
$where[] = ['user_id', '=', $params['user']['id']];
}
// 关键字根据用户筛选
// 关键字根据用户筛选,商品标题
if(!empty($params['keywords']))
{
if(empty($params['user']))
@ -230,8 +276,14 @@ class GoodsCommentsService
{
$where[] = ['user_id', 'in', $user_ids];
} else {
// 无数据条件,走单号条件
$where[] = ['recharge_no', '=', $params['keywords']];
// 无数据条件,走商品
$goods_ids = Db::name('Goods')->where('title', 'like', '%'.$params['keywords'].'%')->column('id');
if(!empty($goods_ids))
{
$where[] = ['goods_id', 'in', $goods_ids];
} else {
$where[] = ['id', '=', 0];
}
}
}
}
@ -248,6 +300,10 @@ class GoodsCommentsService
{
$where[] = ['is_reply', '=', intval($params['is_reply'])];
}
if(!empty($params['business_type']))
{
$where[] = ['business_type', '='. $params['business_type']];
}
if(!empty($params['time_start']))

View File

@ -613,20 +613,6 @@ class GoodsService
return DataReturn('操作成功', 0, empty($temp) ? 0 : 1);
}
/**
* 商品评论总数
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-09-29
* @desc description
* @param [array] $where [条件]
*/
public static function GoodsCommentsTotal($goods_id)
{
return (int) Db::name('OrderComments')->where(['goods_id'=>intval($goods_id)])->count();
}
/**
* 前端商品收藏列表条件
* @author Devil

File diff suppressed because one or more lines are too long

View File

@ -55,18 +55,9 @@ function GoodsCommentsHtml(page)
html += '<p>'+result.data.data[i]['content']+'</p>';
// 规格
if((result.data.data[i]['spec'] || null) != null)
if((result.data.data[i]['msg'] || null) != null)
{
var spec_string = '';
for(var s in result.data.data[i]['spec'])
{
if(s > 0)
{
spec_string += ' | ';
}
spec_string += result.data.data[i]['spec'][s]['type']+''+result.data.data[i]['spec'][s]['value'];
}
html += '<p class="comment-spec">'+spec_string+'</p>';
html += '<p class="comment-spec">'+result.data.data[i]['msg']+'</p>';
}
// 回复