model = new \app\admin\model\Appeal; $this->view->assign("typeList", $this->model->getTypeList()); $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(['order', 'master']) ->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->assignAppealContext($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->assignAppealContext($row); return $this->view->fetch(); } $params = $this->request->post('row/a', []); $status = (string)($params['status'] ?? $row['status']); $reply = trim((string)($params['reply'] ?? '')); $statusList = $this->model->getStatusList(); if (!isset($statusList[$status])) { $this->error('工单流转状态不合法'); } if (in_array($status, ['done', 'reject'], true) && $reply === '') { $this->error('标记完结或驳回申诉时,必须填写平台核查答复说明'); } $oldStatus = (string)$row['status']; $oldReply = (string)$row['reply']; Db::startTrans(); try { $row->allowField(['status', 'reply'])->save([ 'status' => $status, 'reply' => mb_substr($reply, 0, 500), ]); // 状态流转或答复更新时,自动推送站内通知给申诉师傅 if (($status !== $oldStatus || $reply !== $oldReply) && (int)$row['master_id'] > 0) { $statusText = $statusList[$status] ?? $status; $orderNo = ''; if ((int)$row['order_id'] > 0) { $orderNo = (string)Db::name('order')->where('id', (int)$row['order_id'])->value('order_no'); } $msgTitle = '申诉工单处理通知(' . $statusText . ')'; $msgContent = ($orderNo !== '' ? '关联订单 ' . $orderNo . ' 的' : '您的') . '申诉状态已更新为「' . $statusText . '」'; if ($reply !== '') { $msgContent .= '。平台答复:' . $reply; } Db::name('message')->insert([ 'receive_type' => 'master', 'receive_id' => (int)$row['master_id'], 'type' => 'audit', 'title' => mb_substr($msgTitle, 0, 100), 'content' => mb_substr($msgContent, 0, 500), 'order_id' => (int)$row['order_id'], 'is_read' => 0, 'createtime' => time(), ]); } Db::commit(); } catch (PDOException|\Exception $e) { Db::rollback(); $this->error($e->getMessage()); } $this->success(); } /** * 申诉单由师傅端提交,禁止后台伪造录入 */ public function add() { $this->error('申诉工单仅支持师傅端发起,后台不可手动新增'); } /** * 申诉仲裁记录需留痕备查,禁止物理删除 */ public function del($ids = null) { $this->error('申诉工单与判责记录禁止删除'); } /** * 组装申诉关联上下文数据 */ protected function assignAppealContext($row) { $master = (int)$row['master_id'] > 0 ? Db::name('master')->where('id', (int)$row['master_id'])->find() : null; $order = (int)$row['order_id'] > 0 ? Db::name('order')->where('id', (int)$row['order_id'])->find() : null; $customer = ($order && (int)$order['user_id'] > 0) ? Db::name('user')->where('id', (int)$order['user_id'])->field('id,nickname,username,mobile')->find() : null; $review = ($order && (int)$order['id'] > 0) ? Db::name('review')->where('order_id', (int)$order['id'])->find() : null; $orderMedias = ($order && (int)$order['id'] > 0) ? Db::name('order_media')->where('order_id', (int)$order['id'])->order('id asc')->select() : []; $appealImages = array_values(array_filter(array_map('trim', explode(',', (string)$row['images'])))); $reviewImages = $review ? array_values(array_filter(array_map('trim', explode(',', (string)$review['images'])))) : []; $orderStatusMap = [ 0 => '待支付', 1 => '待接单', 2 => '待上门', 3 => '已到达', 4 => '服务中', 5 => '待验收', 6 => '已完成', 9 => '已取消', 10 => '售后/异常' ]; $this->view->assign([ 'row' => $row, 'master' => $master ?: [], 'order' => $order ?: [], 'customer' => $customer ?: [], 'review' => $review ?: [], 'orderMedias' => $orderMedias, 'appealImages' => $appealImages, 'reviewImages' => $reviewImages, 'orderStatusMap' => $orderStatusMap, ]); } }