model = new \app\admin\model\Review; $this->view->assign("statusList", $this->model->getStatusList()); } /** * 评价列表 */ public function index() { $this->request->filter(['strip_tags', 'trim']); if (false === $this->request->isAjax()) { return $this->view->fetch(); } if ($this->request->request('keyField')) { return $this->selectpage(); } [$where, $sort, $order, $offset, $limit] = $this->buildparams(); $list = $this->model ->with(['user', 'master', 'order']) ->where($where) ->order($sort, $order) ->paginate($limit); $result = ['total' => $list->total(), 'rows' => $list->items()]; return json($result); } /** * 评价全景详情(关联订单、雇主、师傅及晒单状态) */ public function detail($ids = null) { $row = $this->model->get($ids); if (!$row) { $this->error(__('No Results were found')); } $this->assignReviewContext($row); return $this->view->fetch(); } /** * 评价合规治理(保护业主原始评分与图文只读,仅变更展示状态与回复,并联动晒单表) */ public function edit($ids = null) { $row = $this->model->get($ids); if (!$row) { $this->error(__('No Results were found')); } if (false === $this->request->isPost()) { $this->assignReviewContext($row); return $this->view->fetch(); } $params = $this->request->post('row/a', []); $status = (string)($params['status'] ?? $row['status']); $reply = trim((string)($params['reply'] ?? $row['reply'])); if (!in_array($status, ['normal', 'hidden'], true)) { $this->error('评价状态参数不合法'); } Db::startTrans(); try { $row->allowField(['status', 'reply'])->save([ 'status' => $status, 'reply' => mb_substr($reply, 0, 500), ]); // 若屏蔽违规评价,同步下架该工单关联的业主晒单,防止首页继续曝光 if ($status === 'hidden' && (int)$row['order_id'] > 0) { Db::name('showcase')->where('order_id', (int)$row['order_id'])->update([ 'status' => 'hidden', 'updatetime' => time(), ]); } // 重算对应师傅综合评分 if ((int)$row['master_id'] > 0) { $this->recalcMasterScore((int)$row['master_id']); } Db::commit(); } catch (PDOException|\Exception $e) { Db::rollback(); $this->error($e->getMessage()); } $this->success(); } /** * 批量显隐同步联动晒单表并重算师傅评分 */ public function multi($ids = null) { if (false === $this->request->isPost()) { $this->error(__('Invalid parameters')); } $ids = $ids ?: $this->request->post('ids'); $params = (string)$this->request->post('params'); if (empty($ids) || $params === '') { $this->error(__('Parameter %s can not be empty', 'ids')); } parse_str($params, $values); $status = $values['status'] ?? null; if (!in_array($status, ['normal', 'hidden'], true)) { $this->error('仅支持批量切换显示或隐藏状态'); } $idArr = array_values(array_filter(array_map('intval', explode(',', (string)$ids)))); if (!$idArr) { $this->error(__('No rows were updated')); } $affectedReviews = Db::name('review')->where('id', 'in', $idArr)->field('id,order_id,master_id')->select(); Db::startTrans(); try { Db::name('review')->where('id', 'in', $idArr)->update(['status' => $status]); if ($status === 'hidden') { $orderIds = array_values(array_filter(array_map('intval', array_column($affectedReviews, 'order_id')))); if ($orderIds) { Db::name('showcase')->where('order_id', 'in', $orderIds)->update([ 'status' => 'hidden', 'updatetime' => time(), ]); } } $masterIds = array_values(array_unique(array_filter(array_map('intval', array_column($affectedReviews, 'master_id'))))); foreach ($masterIds as $mid) { $this->recalcMasterScore($mid); } Db::commit(); } catch (PDOException|\Exception $e) { Db::rollback(); $this->error($e->getMessage()); } $this->success(); } /** * 真实履约评价禁止后台手工伪造(刷单防御) */ public function add() { $this->error('服务评价仅支持完工业主真实提交,后台不可手动新增'); } /** * 删除违规评价(同步隐藏关联晒单并重算对应师傅综合评分) */ public function del($ids = null) { if (false === $this->request->isPost()) { $this->error(__('Invalid parameters')); } $ids = $ids ?: $this->request->post('ids'); $idArr = array_values(array_filter(array_map('intval', explode(',', (string)$ids)))); if (!$idArr) { $this->error(__('Parameter %s can not be empty', 'ids')); } $rows = Db::name('review')->where('id', 'in', $idArr)->field('id,order_id,master_id')->select(); if (!$rows) { $this->error(__('No Results were found')); } Db::startTrans(); try { $orderIds = array_values(array_unique(array_filter(array_map('intval', array_column($rows, 'order_id'))))); $masterIds = array_values(array_unique(array_filter(array_map('intval', array_column($rows, 'master_id'))))); Db::name('review')->where('id', 'in', $idArr)->delete(); if ($orderIds) { Db::name('showcase')->where('order_id', 'in', $orderIds)->update([ 'status' => 'hidden', 'updatetime' => time(), ]); } foreach ($masterIds as $mid) { $this->recalcMasterScore($mid); } Db::commit(); } catch (PDOException|\Exception $e) { Db::rollback(); $this->error($e->getMessage()); } $this->success(); } /** * 重算师傅有效公开评价的平均分并同步至师傅档案 */ protected function recalcMasterScore($masterId) { $masterId = (int)$masterId; if ($masterId <= 0) { return; } $avg = Db::name('review') ->where('master_id', $masterId) ->where('status', 'normal') ->avg('score'); $newScore = $avg !== null ? round((float)$avg, 2) : 5.00; Db::name('master')->where('id', $masterId)->update([ 'score' => $newScore, 'updatetime' => time(), ]); } /** * 解析标签字符串或 JSON 数组 */ protected function parseTags($raw) { $raw = trim((string)$raw); if ($raw === '') { return []; } if ($raw[0] === '[') { $arr = json_decode($raw, true); if (is_array($arr)) { return array_values(array_filter(array_map('trim', $arr))); } } return array_values(array_filter(array_map('trim', explode(',', $raw)))); } /** * 组装评价关联数据 */ protected function assignReviewContext($row) { $order = (int)$row['order_id'] > 0 ? Db::name('order')->where('id', (int)$row['order_id'])->find() : null; $user = (int)$row['user_id'] > 0 ? Db::name('user')->where('id', (int)$row['user_id'])->field('id,nickname,username,mobile,avatar')->find() : null; $master = (int)$row['master_id'] > 0 ? Db::name('master')->where('id', (int)$row['master_id'])->field('id,realname,mobile,score,order_count')->find() : null; $showcase = (int)$row['order_id'] > 0 ? Db::name('showcase')->where('order_id', (int)$row['order_id'])->find() : null; $reviewTags = $this->parseTags($row['tags']); $reviewImages = array_values(array_filter(array_map('trim', explode(',', (string)$row['images'])))); $this->view->assign([ 'row' => $row, 'order' => $order ?: [], 'user' => $user ?: [], 'master' => $master ?: [], 'showcase' => $showcase ?: [], 'reviewTags' => $reviewTags, 'reviewImages' => $reviewImages, ]); } }