- 新增 invoice_title、showcase、wallet_log 模型及对应语言包 - 新增后台控制器、视图及搜索字段配置 - 修复服务类目删除保护逻辑 - 优化后台登录页面文案及样式 - 新增前端角色切换逻辑及页面拦截 - 新增 SVG 图标及样式变量 - 修复接口权限及下拉框默认值问题
196 行
6.7 KiB
PHP
196 行
6.7 KiB
PHP
<?php
|
||
|
||
namespace app\admin\controller;
|
||
|
||
use app\common\controller\Backend;
|
||
use think\Db;
|
||
use think\exception\PDOException;
|
||
|
||
/**
|
||
* 申诉工单管理
|
||
*
|
||
* 申诉单由师傅端发起,后台承担平台客服核实与判责答复职责
|
||
*
|
||
* @icon fa fa-gavel
|
||
*/
|
||
class Appeal extends Backend
|
||
{
|
||
/**
|
||
* Appeal模型对象
|
||
* @var \app\admin\model\Appeal
|
||
*/
|
||
protected $model = null;
|
||
|
||
protected $relationSearch = true;
|
||
protected $searchFields = 'id,content,reply,order.order_no,master.realname,master.mobile';
|
||
|
||
public function _initialize()
|
||
{
|
||
parent::_initialize();
|
||
$this->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,
|
||
]);
|
||
}
|
||
}
|