model = new \app\admin\model\Order; $this->view->assign("statusList", $this->model->getStatusList()); $sources = Db::name('source') ->where('status', 1) ->field(['id', 'title', 'key_word', 'pid']) ->order('pid', 'asc') ->order('sort', 'desc') ->select(); $this->sources = $sources; $filtered = array_filter($sources, function ($item) { return $item['pid'] == 0; }); $pid_map = array_column($filtered, null, 'id'); $res = []; foreach ($sources as $item) { if ($item['pid'] != 0 && isset($pid_map[$item['pid']])) { $res [] = [ ...$item, 'ptitle' => $pid_map[$item['pid']]['title'] ]; } } // dd($res); // Tree::instance()->init($sources); // $data = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title'); // dd($data); $items = Db::name('item') ->where('status', 1) ->field(['id', 'title', 'key_word', 'pid']) ->order('pid', 'asc') ->order('sort', 'desc') ->select(); $tree = $this->buildTree($items); $formattedTree = $this->formatTree($tree); $phones = Db::name('phones') ->where('assigned_user', $this->auth->id) ->field(['id', 'model', 'phone_number']) ->select(); $this->items = $items; $this->itemsformattedTree = $formattedTree; $coupons = Db::name('coupons') ->where('status', 'active') ->field(['id', 'code', 'description']) ->select(); $users = Db::name('admin') ->field(['id', 'nickname']) ->select(); $this->view->assign("sources", $res); $this->view->assign("coupons", $coupons); $this->view->assign("items", $formattedTree); $this->view->assign("phones", $phones); $this->view->assign("users", $users); //$this->view->assign("collectList", $this->model->getCollectList()); //$this->view->assign("dispatchTypeList", $this->model->getDispatchTypeList()); } /** * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 */ public function index($getArray = false, $page = 0, $input_limit = 0) { $this->request->filter(['strip_tags', 'trim']); $group = \model('auth_group_access')->where('uid', $this->auth->id)->find()->group_id ?? 0; $user = \model('admin')->find($this->auth->id); $this->assignconfig('permissions', [ 'add' => $this->auth->check('order/add'), 'edit' => $this->auth->check('order/edit'), 'copy' => $this->auth->check('order/copy'), 'reminder' => $this->auth->check('order/reminder'), 'warning' => $this->auth->check('order/warning'), 'addAbnormal' => $this->auth->check('order/addAbnormal'), 'delete' => $this->auth->check('order/delete'), 'invoice' => $this->auth->check('order/invoice'), 'aftersale' => $this->auth->check('aftersales/aftersale/add'), 'log' => $this->auth->check('order/log'), 'dispatch' => $this->auth->check('orders/dispatch/add'), 'map' => $this->auth->check('orders/dispatch/map'), ]); if (false === $this->request->isAjax() && $getArray == false) { return $this->view->fetch(); } //如果发送的来源是 Selectpage,则转发到 Selectpage if ($this->request->request('keyField')) { return $this->selectpage(); } [$where, $sort, $order, $offset, $limit] = $this->buildparams(); $build = $this->model ->field(['id', 'order_no', 'admin_id', 'customer', 'tel', 'status', 'area_id', 'address', 'source', 'source_shop', 'source_uid', 'source', 'item_title', 'item_id', 'work_tel_id', 'detail', 'remark', 'images', 'create_time', 'update_time', 'admin_id', 'dispatch_type', 'receive_type', 'plan_time', 'coupon_id', 'is_overtime', 'dispatch_admin_user', 'create_time', 'audit_time', 'total', 'online_amount', 'aftersale_id' ]) ->where($where); $filter = (array)json_decode(input()['filter'] ?? '', true); if (isset($filter['audit_time'])) { $build->where('status', \app\admin\model\Order::STATUS_FINISHED); } $admin_filter = $filter['user.nickname'] ?? false; $area_id = $filter['area_id'] ?? false; $item_id = $filter['item_id'] ?? false; $is_timeout = $filter['is_timeout'] ?? null; // dd($create_time,$filter); if ($admin_filter) { $admin_ids = Admin::where('nickname', 'like', '%' . $admin_filter . '%')->column('id'); $build->whereIn('admin_id', $admin_ids); } if ($area_id) { $build->where('area_id', 'like', $this->getSelectAreaCode($area_id) . '%'); } if ($item_id) { $item_ids = $this->getItemsById($item_id); $item_ids [] = $item_id; $build->whereIn('item_id', $item_ids); } if (!is_null($is_timeout)) { $build->where('is_overtime', $is_timeout); } if ($group == 2) { // 录单员 $build->where('admin_id', $user->id); } elseif ($group == 6) { // 派单员 // 生成 SQL 语句 $ids = $user->area_ids ?? ''; if ($ids == '') { return ['total' => 0, 'rows' => []]; } $ids = explode(',', $ids); $area_codes = $this->filterAreaCodes($ids); $build->where(function ($q) use ($area_codes) { foreach ($area_codes as $area_code) { $q->whereOr('area_id', 'like', $area_code . '%'); } }); } $build ->with(['user' => function ($q) { $q->field('id,nickname'); }, 'area' => function ($q) { $q->field('id,area_code,merge_name'); }, 'phone' => function ($q) { $q->field('id,model'); }, 'coupon' => function ($q) { $q->field('id,code,description'); }, 'source' => [ 'parent' => function ($q) { $q->field('id,title'); } ]] ) ->order($sort, $order); if ($getArray) { $list = $build->paginate([ 'list_rows' => $input_limit, 'page' => $page ]); } else { $list = $build->paginate($limit); } foreach ($list as $item) { $item->aftersale_btn = false; if ($item->aftersale_id == 0 && $this->auth->check('aftersales/aftersale/add') && $item->status == \app\admin\model\Order::STATUS_FINISHED) { //$item->status == \app\admin\model\Order::STATUS_FINISHED && $item->aftersale_btn = true; } if (isset($item->getRelation('source')->parent->title)) { $item->source_total_name = '【' . $item->getRelation('source')->parent->title . '】' . ($item->getRelation('source')->title ?? ''); } else { $item->source_total_name = ($item->getRelation('source')->title ?? ''); } if ($item->status < 60) { $item->audit_time = null; } unset($item->source); } $result = ['total' => $list->total(), 'rows' => $list->items()]; return json($result); } public function add() { // $order = \app\admin\model\Order::get(257); // $this->success(data:$order); if (false === $this->request->isPost()) { return $this->view->fetch(); } $params = $this->request->post('row/a'); // 数据验证 $validate = $this->validate($params, \app\admin\validate\Order::class . '.add'); if ($validate !== true) { $this->error($validate); } if (!$params['set_time']) { $params['plan_time'] = ''; } $params = array_filter($params, function ($val) { return $val != ''; }); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); if ($this->dataLimit && $this->dataLimitFieldAutoFill) { $params[$this->dataLimitField] = $this->auth->id; } sleep(2); Db::startTrans(); try { //是否采用模型验证 if ($this->modelValidate) { $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate; $this->model->validateFailException()->validate($validate); } $sources = $this->sources; // dd($sources); $sources = array_column($sources, null, 'id'); if (!in_array($sources[$params['source']]['pid'], [3, 8]) && empty($params['customer'])) { $this->error('请输入客户名称'); } $params['source_shop'] = $sources[$params['source']]['title'] ?? null; $itemIds = explode(',', $params['item_id'] ?? ''); $params['item_id'] = end($itemIds); $params['item_title'] = $this->findElementByValue($this->itemsformattedTree, $params['item_id'] ?? null); $params['admin_id'] = ($params['admin_id'] ?? -1) == -1 ? $this->auth->id : $params['admin_id']; if (empty($params['admin_id'])) { $params['admin_id'] = $this->auth->id; } $params['status'] = 10; $params['total'] = $params['online_amount'] ?? 0; $params['dispatch_type'] = $params['dispatch_type'] ?? 2; $params['order_no'] = $this->generateOrderNumber(); $params['create_time'] = date('Y-m-d H:i:s'); $params['update_time'] = date('Y-m-d H:i:s'); $params['receive_type'] = $params['receive_type'] ?: 1; $params['audit_time'] = date('Y-m-d H:i:s'); $result = $this->model->allowField(true)->save($params); $auth = clone $this->auth; $order = \app\admin\model\Order::where('id', $this->model->id)->with(['source' => [ 'parent' => function ($q) { $q->field('id,title'); } ]] )->find(); // dd($order); if (isset($order->getRelation('source')->parent->title)) { $order->source_total_name = '【' . $order->getRelation('source')->parent->title . '】' . ($order->getRelation('source')->title ?? ''); } else { $order->source_total_name = ($order->getRelation('source')->title ?? ''); } unset($order->source); //日志 $hookparams['order'] = $order; $hookparams['role'] = 1; $hookparams['auth'] = $auth; $hookparams['remark'] = '录入订单'; Hook::listen('order_change', $hookparams); if ($params['dispatch_type'] == 2) { AutoDispatchLogic::autoDispatch($this->model, $this->auth); } Db::commit(); } catch (ValidateException|PDOException|Exception $e) { Db::rollback(); throw $e; $this->error($e->getMessage()); } if ($result === false) { $this->error(__('No rows were inserted')); } $this->success(data: $order); } public function edit($ids = null) { if (!$ids) { if (request()->isPost()) { $ids = input('id'); if (!$ids) { $this->error('缺少订单ID'); } } else { $this->error('缺少订单ID'); } } // 获取当前ID对应的订单信息 $order = $this->model->get($ids); if (!$order) { $this->error('订单不存在'); } // 判断是否为POST请求,进行更新操作 if (request()->isPost()) { // 获取表单提交的数据 $params = input('post.row/a'); // 数据验证 $validate = $this->validate($params, \app\admin\validate\Order::class . '.edit'); if ($validate !== true) { $this->error($validate); } if (!$params['set_time']) { $params['plan_time'] = null; } //移除无用字段:是否设置上门时间 unset($params['set_time']); $params['update_time'] = date('Y-m-d H:i:s'); $sources = $this->sources; $sources = array_column($sources, 'title', 'id'); // $data['user_id'] = $this->auth->id; $params['source_shop'] = $sources[$params['source']] ?? null; $sources = $this->sources; $sources = array_column($sources, 'title', 'id'); $params['admin_id'] = ($params['admin_id'] == -1) ? $this->auth->id : $params['admin_id']; if (empty($params['admin_id'])) { $params['admin_id'] = $this->auth->id; } $params['source_shop'] = $sources[$params['source']] ?? null; $params['item_title'] = $this->findElementByValue($this->itemsformattedTree, $params['item_id'] ?? null); // $params['create_time'] = date('Y-m-d H:i:s'); $params['update_time'] = date('Y-m-d H:i:s'); $params['receive_type'] = $params['receive_type'] ?: 1; if ($order->receive_type != $params['receive_type']) { //修改派单表 OrderDispatch::where('order_id', $order->id)->whereBetween('status', [0, 30])->update(['is_receipt' => $params['receive_type'] == 1 ? 1 : 0]); } // 更新订单信息 $order->save($params); // 返回成功信息 $this->success('更新成功', 'index'); } $area = new \app\admin\model\Area(); $area_name = $area->getNameByCode($order->area_id); $order->area_name = str_replace(',', '/', $area_name ?? ''); // dd($area_name); // 将订单数据传递到视图 $this->assign('row', $order); // 渲染编辑页面 return $this->fetch(); } public function copy($ids = null) { if (!$ids) { $this->error('缺少订单ID'); } // 获取当前ID对应的订单信息 $order = $this->model->get($ids); if (!$order) { $this->error('订单不存在'); } $area = new \app\admin\model\Area(); $area_name = $area->getNameByCode($order->area_id); $order->area_name = str_replace(',', '/', $area_name); // 将订单数据传递到视图 $this->assign('row', $order); // 渲染编辑页面 return $this->fetch(); } function generateOrderNumber($prefix = '') { return \app\admin\model\Order::generateOrderNo(); } use AmapTrait; public function smart() { // $titles = Item::where('status',1)->column('title'); // $res = $this->extractCustomerInfo(request()->post('str'),$titles); // dd($res); $data = Address::smart(request()->post('str')); if ($data['item']['id'] ?? 0) { $data['item']['item'] = $this->findElementByValue($this->itemsformattedTree, $data['item']['id'] ?? null); } preg_match('/\b(1[3-9]\d{9})\b/', $data['mobile'], $match); // dd($data); $data['mobile'] = $match[0] ?? $data['mobile']; if ($data['addr'] && $data['addr'] != '') { $address = $this->getAddressByKeyword($data['addr']); if ($address) { $data['area_id'] = $address['adcode']; $location = explode(',', $address['location']); $data['lng'] = $location[0]; $data['lat'] = $location[1]; } else { $data['addr'] = ''; } } // dd($data); $this->success(data: $data); } public function reminder($ids = null) { $order = $this->model->where('id', $ids)->find(); $area_id = substr($order->area_id, 0, 4); $res = Admin::where('area_ids', 'like', '%' . $area_id . '%') ->column('id'); $insert = []; foreach ($res as $re) { $insert [] = [ 'to_id' => $re, 'type' => 1, 'title' => '催单通知', 'content' => '【催单通知】您有一条订单号为' . $order->order_no . '的订单被催单,请立即派单!' ]; } $build = new Message(); $build->saveAll($insert); $this->success($order['order_no']); } public function warning($ids = null) { if (false === $this->request->isPost()) { $order = $this->model->where('id', $ids)->find(); $abnormals = model('abnormal')->where('type', 3)->order('sort', 'desc')->select(); $options = []; foreach ($abnormals as $abnormal) { $options [] = $abnormal->toArray(); } return $this->fetch('warning', ['row' => $order, 'options' => $options]); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); $order = model('order')->get($params['order_id']); $area_id = substr($order->area_id, 0, 4); $res = Admin::where('area_ids', 'like', '%' . $area_id . '%') ->column('id'); $dispatch_admin = AuthGroupAccess::where('group_id', 6) ->column('uid'); $res = array_values(array_intersect($res, $dispatch_admin)); $message = $params['detail'] ?? ''; $abnormals = model('abnormal')->where('type', 3) ->where('id', $params['abnormal_id'])->find(); $insert = []; foreach ($res as $re) { $insert [] = [ 'to_id' => $re, 'type' => 1, 'title' => '订单内容变更', 'content' => '【订单内容变更】您有一条订单' . $order->order_no . '信息被修改,异常类型【' . $abnormals->title . '】,备注:【' . $message . '】,请注意查收。' ]; } $build = new Message(); $build->saveAll($insert); $this->success('操作成功'); } public function addAbnormal($ids = null) { if (false === $this->request->isPost()) { $abnormals = model('abnormal')->where('type', 1)->order('sort', 'desc')->select(); $abnormals_data = []; foreach ($abnormals as $abnormal) { $abnormals_data [] = $abnormal->toArray(); } $order = model('order')->get($ids); return $this->fetch('abnormal', ['row' => $order, 'options' => $abnormals_data]); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); $order = model('order')->get($params['order_id']); $result = false; Db::startTrans(); try { $abnormal_title = model('abnormal')->get($params['abnormal_id'])->title ?? ''; $insert = [ 'order_id' => $params['order_id'], 'status' => 0, 'level' => $params['level'], 'abnormal_id' => $params['abnormal_id'], 'abnormal_title' => $abnormal_title, 'detail' => $params['detail'], 'admin_id' => $this->auth->id, 'admin_user' => $this->auth->getUserInfo()['nickname'] ?? '', 'create_time' => now()->format('Y-m-d H:m:s'), 'update_time' => now()->format('Y-m-d H:m:s'), ]; $orderDispatch = OrderDispatch::where('order_id', $order->id)->whereBetween('status', '>=', 0)->find(); if ($params['abnormal_id'] == 2 || $params['abnormal_id'] == 3) { $order->status = \app\admin\model\Order::STATUS_CANCEL; $order->save(); if (!empty($orderDispatch)) { $orderLogic = new OrderLogic(); $orderLogic->cancelOrderDispatch($orderDispatch, $this->auth, '订单被取消', false); //日志 $hookparams['order'] = $order; $hookparams['role'] = 1; $hookparams['auth'] = $this->auth; $hookparams['remark'] = $params['remark'] ?? ''; Hook::listen('order_change', $hookparams); } $insert['deal_type'] = 2; $insert['handle_detail'] = '系统取消订单'; $insert['handle_admin_user'] = config('system_name'); $insert['handle_admin_id'] = config('system_id'); $insert['handle_time'] = now()->format('Y-m-d H:i:s'); $insert['status'] = 1; } else if ($params['abnormal_id'] == 5 || $params['abnormal_id'] == 15) { $order->status = \app\admin\model\Order::STATUS_DISPATCHING; $order->save(); if (!empty($orderDispatch)) { $OrderLogic = new OrderLogic(); $OrderLogic->noWorkerCanGetIt($orderDispatch, '系统取消' . $abnormal_title); AutoDispatchLogic::autoDispatch($order); } $insert['deal_type'] = 3; $insert['handle_detail'] = '系统重新派单'; $insert['handle_admin_user'] = config('system_name'); $insert['handle_admin_id'] = config('system_id'); $insert['handle_time'] = now()->format('Y-m-d H:i:s'); $insert['status'] = 1; } else { Message::create([ 'to_id' => $order->admin_id, 'type' => 1, 'title' => '订单报错通知', 'content' => '【订单报错通知】您有一条订单号为' . $order->order_no . '的订单订单信息录入错误,请前往报错订单界面进行查看,并立即处理!' ]); } $result = \model('order_abnormal')->insert($insert); Db::commit(); } catch (ValidateException|PDOException|Exception $e) { Db::rollback(); $this->error($e->getMessage()); } if ($result === false) { $this->error(__('No rows were inserted')); } $this->success(); } public function delete($ids = null) { if (false === $this->request->isPost()) { $options = \model('abnormal')->where('type', 2)->select(); $op = []; foreach ($options as $option) { $op[] = ['id' => $option->id, 'title' => $option->title]; } $order = model('order')->get($ids); if (!$order) { $this->error('Not Find'); } return $this->fetch('delete', ['row' => $order, 'options' => $op]); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); $send_mail = $params['notify'] ?? false; $result = false; Db::startTrans(); $order = model('order')->get($params['order_id']); if (!$order) { $this->error('Not Find'); } try { $params['status'] = \app\admin\model\Order::STATUS_CANCEL; unset($params['notify']); $result = $order->allowField(true)->save($params); $dispatch = OrderDispatch::where('order_id', $order->id)->where('status', '>=', 0)->find(); if (!empty($dispatch)) { $orderLogic = new OrderLogic(); $orderLogic->cancelOrderDispatch($dispatch, $this->auth, '订单被取消', false); } //日志 $hookparams['order'] = $order; $hookparams['role'] = 1; $hookparams['auth'] = $this->auth; $hookparams['remark'] = $params['remark'] ?? '取消订单'; Hook::listen('order_change', $hookparams); Db::commit(); } catch (ValidateException|PDOException|Exception $e) { Db::rollback(); $this->error($e->getMessage()); } if ($result === false) { $this->error(__('No rows were inserted')); } if ($send_mail) { SendMailLogic::sendToCustomStop($order->tel); } $this->success(); } public function send($ids = null) { if (false === $this->request->isPost()) { $options = \model('admin')->select(); $op = []; foreach ($options as $option) { $op[] = ['id' => $option->id, 'title' => $option->nickname]; } $order = model('order')->get($ids); return $this->fetch('delete', ['row' => $order, 'options' => $op]); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); $result = false; Db::startTrans(); try { $order = model('order')->get($params['order_id']); if (!$order) { $this->error('Not Find'); } $params['status'] = \app\admin\model\Order::STATUS_CANCEL; $result = $order->allowField(true)->save($params); Db::commit(); } catch (ValidateException|PDOException|Exception $e) { Db::rollback(); $this->error($e->getMessage()); } if ($result === false) { $this->error(__('No rows were inserted')); } $this->success(); } /** * 编辑 * * @param $ids * @return string * @throws DbException * @throws \think\Exception */ public function invoice($ids = null) { if (false === $this->request->isPost()) { $order = model('order')->get($ids); return $this->fetch('order/invoice/add', ['row' => $order]); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } $params = $this->preExcludeFields($params); if ($this->dataLimit && $this->dataLimitFieldAutoFill) { $params[$this->dataLimitField] = $this->auth->id; } $result = false; Db::startTrans(); try { $params['invoice_method'] = 1; $result = (new Invoice())->allowField(true)->save($params); Db::commit(); } catch (ValidateException|PDOException|Exception $e) { Db::rollback(); $this->error($e->getMessage()); } if ($result === false) { $this->error(__('No rows were inserted')); } $this->success(); } function findElementByValue($data, $targetValue, $path = []) { foreach ($data as $item) { // 将当前节点的 label 添加到路径中 $newPath = array_merge($path, [$item['label']]); // 如果找到目标值,返回路径 if ($item['value'] == $targetValue) { return implode(' / ', $newPath); } // 如果当前节点有 children,递归搜索 if (isset($item['children']) && is_array($item['children'])) { $result = $this->findElementByValue($item['children'], $targetValue, $newPath); if ($result) { return $result; } } } return null; // 如果找不到返回 null } protected function buildparams($searchfields = null, $relationSearch = null) { $searchfields = is_null($searchfields) ? $this->searchFields : $searchfields; $relationSearch = is_null($relationSearch) ? $this->relationSearch : $relationSearch; $search = $this->request->get("search", ''); $filter = $this->request->get("filter", ''); $op = $this->request->get("op", '', 'trim'); $sort = $this->request->get("sort", !empty($this->model) && $this->model->getPk() ? $this->model->getPk() : 'id'); $order = $this->request->get("order", "DESC"); $offset = max(0, $this->request->get("offset/d", 0)); $limit = max(0, $this->request->get("limit/d", 0)); $limit = $limit ?: 999999; //新增自动计算页码 $page = $limit ? intval($offset / $limit) + 1 : 1; if ($this->request->has("page")) { $page = max(0, $this->request->get("page/d", 1)); } $this->request->get([config('paginate.var_page') => $page]); $filter = (array)json_decode($filter, true); unset($filter['item_id']); unset($filter['area_id']); $filter = $filter ? $filter : []; $where = []; $alias = []; $bind = []; $name = ''; $aliasName = ''; if (!empty($this->model) && $relationSearch) { $name = $this->model->getTable(); $alias[$name] = Loader::parseName(basename(str_replace('\\', '/', get_class($this->model)))); $aliasName = $alias[$name] . '.'; } $sortArr = explode(',', $sort); foreach ($sortArr as $index => & $item) { $item = stripos($item, ".") === false ? $aliasName . trim($item) : $item; } unset($item); $sort = implode(',', $sortArr); $adminIds = $this->getDataLimitAdminIds(); if (is_array($adminIds)) { $where[] = [$aliasName . $this->dataLimitField, 'in', $adminIds]; } if ($search) { $searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields); foreach ($searcharr as $k => &$v) { $v = stripos($v, ".") === false ? $aliasName . $v : $v; } unset($v); $where[] = [implode("|", $searcharr), "LIKE", "%{$search}%"]; } $index = 0; $op = (array)json_decode($op, true); foreach ($filter as $k => $v) { if ($k == 'user.nickname' || $k == 'is_timeout') continue; if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $k)) { continue; } $sym = $op[$k] ?? '='; if (stripos($k, ".") === false) { $k = $aliasName . $k; } $v = !is_array($v) ? trim($v) : $v; $sym = strtoupper($op[$k] ?? $sym); //null和空字符串特殊处理 if (!is_array($v)) { if (in_array(strtoupper($v), ['NULL', 'NOT NULL'])) { $sym = strtoupper($v); } if (in_array($v, ['""', "''"])) { $v = ''; $sym = '='; } } switch ($sym) { case '=': case '<>': $where[] = [$k, $sym, (string)$v]; break; case 'LIKE': case 'NOT LIKE': case 'LIKE %...%': case 'NOT LIKE %...%': $where[] = [$k, trim(str_replace('%...%', '', $sym)), "%{$v}%"]; break; // ✅ 新增:右匹配(like%) case 'LIKE%': $where[] = [$k, 'LIKE', "{$v}%"]; break; // ✅ 新增:左匹配(%like) case '%LIKE': $where[] = [$k, 'LIKE', "%{$v}"]; break; case '>': case '>=': case '<': case '<=': $where[] = [$k, $sym, intval($v)]; break; case 'FINDIN': case 'FINDINSET': case 'FIND_IN_SET': $v = is_array($v) ? $v : explode(',', str_replace(' ', ',', $v)); $findArr = array_values($v); foreach ($findArr as $idx => $item) { $bindName = "item_" . $index . "_" . $idx; $bind[$bindName] = $item; $where[] = "FIND_IN_SET(:{$bindName}, `" . str_replace('.', '`.`', $k) . "`)"; } break; case 'IN': case 'IN(...)': case 'NOT IN': case 'NOT IN(...)': $where[] = [$k, str_replace('(...)', '', $sym), is_array($v) ? $v : explode(',', $v)]; break; case 'BETWEEN': case 'NOT BETWEEN': $arr = array_slice(explode(',', $v), 0, 2); if (stripos($v, ',') === false || !array_filter($arr, function ($v) { return $v != '' && $v !== false && $v !== null; })) { continue 2; } //当出现一边为空时改变操作符 if ($arr[0] === '') { $sym = $sym == 'BETWEEN' ? '<=' : '>'; $arr = $arr[1]; } elseif ($arr[1] === '') { $sym = $sym == 'BETWEEN' ? '>=' : '<'; $arr = $arr[0]; } $where[] = [$k, $sym, $arr]; break; case 'RANGE': case 'NOT RANGE': $v = str_replace(' - ', ',', $v); $arr = array_slice(explode(',', $v), 0, 2); if (stripos($v, ',') === false || !array_filter($arr)) { continue 2; } //当出现一边为空时改变操作符 if ($arr[0] === '') { $sym = $sym == 'RANGE' ? '<=' : '>'; $arr = $arr[1]; } elseif ($arr[1] === '') { $sym = $sym == 'RANGE' ? '>=' : '<'; $arr = $arr[0]; } $tableArr = explode('.', $k); if (count($tableArr) > 1 && $tableArr[0] != $name && !in_array($tableArr[0], $alias) && !empty($this->model) && $this->relationSearch) { //修复关联模型下时间无法搜索的BUG $relation = Loader::parseName($tableArr[0], 1, false); $alias[$this->model->$relation()->getTable()] = $tableArr[0]; } $where[] = [$k, str_replace('RANGE', 'BETWEEN', $sym) . ' TIME', $arr]; break; case 'NULL': case 'IS NULL': case 'NOT NULL': case 'IS NOT NULL': $where[] = [$k, strtolower(str_replace('IS ', '', $sym))]; break; default: break; } $index++; } if (!empty($this->model)) { $this->model->alias($alias); } $model = $this->model; $where = function ($query) use ($where, $alias, $bind, &$model) { if (!empty($model)) { $model->alias($alias); $model->bind($bind); } foreach ($where as $k => $v) { if (is_array($v)) { call_user_func_array([$query, 'where'], $v); } else { $query->where($v); } } }; return [$where, $sort, $order, $offset, $limit, $page, $alias, $bind]; } public function log($ids) { //设置过滤方法 $this->request->filter(['strip_tags', 'trim']); $dispatch_id = $this->request->get('dispatch_id'); if (false === $this->request->isAjax()) { //page2变更日志 $orderLogs = OrderLog::where('order_id', $ids)->order('id', 'desc')->select(); $this->view->assign('logs', json_encode($orderLogs)); $this->view->assign('cdnurl', config('upload.cdnurl')); return $this->fetch('orders/dispatchlog/index'); } //如果发送的来源是 Selectpage,则转发到 Selectpage if ($this->request->request('keyField')) { return $this->selectpage(); } [$where, $sort, $order, $offset, $limit] = $this->buildparams(); $list = $this->model ->where($where) ->where('dispatch_id', $dispatch_id) ->order($sort, $order) ->paginate($limit); $result = ['total' => $list->total(), 'rows' => $list->items()]; return json($result); } public function export() { // 表头结构(可从参数获取或手动定义) $columns = json_decode($this->request->get('columns', ''), true); // dd($columns); if (!$columns) { // 用第一页数据自动生成字段 $sample = $this->index(true, 1, 1)->getData(); if (!isset($sample['rows'][0])) { return json(['code' => 0, 'msg' => '无数据可导出']); } $columns = []; foreach ($sample['rows'][0] as $key => $value) { $columns[] = ['field' => $key, 'title' => $key]; } } // 数据获取函数:分页获取数据(支持返回 array) $fetchData = function ($page, $limit) { $result = $this->index(true, $page, $limit); $order = new \app\admin\model\Order(); foreach ($result->getData()['rows'] as $item){ $item->status = $order->getStatusList()[$item->status] ?? ''; $item->dispatch_type = $item->dispatch_type == 1 ? '手动派单' : '自动派单'; $item->is_overtime = $item->is_overtime ? '超时' : '未超时'; $item->receive_type = $item->receive_type == 1 ? '已收定金' : '已收全款'; $images = explode(',',$item->images ?? ''); $url = ''; if ($images){ foreach ($images as $img){ if($img == '')continue; $url .= cdnurl($img) . ','; } } $item->images = $url; } return $result->getData()['rows'] ?? []; }; $this->exportCsvByStream($columns, $fetchData, '订单导出_' . date('Ymd_His') . '.xlsx'); } }