request->isPost()) { $page = $this->request->param('page/d', 1); $size = $this->request->param('size/d', 20); $searchParams = $this->request->param('searchParams/a', []); if(!empty(input("get.status/s"))){ $searchParams["status"]= input("get.status/s"); } $res = $this->getOrderList($searchParams, $page, $size); return $this->json(0, 'success', $res); } if(!empty(input("get.status/s"))){ $this->data['dataUrl'] = "/manager/mall/order/index?status=" . input("get.status/s"); } $this->data['statusList'] = OrderModel::statusTextList(); return $this->view(); } /** * 积分订单 * * @throws Exception */ public function score() { if ($this->request->isPost()) { $page = $this->request->param('page/d', 1); $size = $this->request->param('size/d', 20); $searchParams = $this->request->param('searchParams/a', []); $searchParams['is_score'] = OrderModel::COMMON_ON; $res = $this->getOrderList($searchParams, $page, $size); return $this->json(0, 'success', $res); } $this->data['statusList'] = OrderModel::statusTextList(); $this->data['dataUrl'] = '/manager/mall/order/score'; $this->data['isScore'] = OrderModel::COMMON_ON; return $this->view('manager/mall/order/index'); } /** * @param array $searchParams * @param int $page * @param int $size * @return array * @throws Exception */ protected function getOrderList(array $searchParams, int $page, int $size): array { // 主动触发:自动检测处理过期订单 // OrderRepository::getInstance()->autoCheckInvalidOrders(); $status = $searchParams['status'] ?? ''; $startAt = $searchParams['start_at'] ?? ''; $endAt = $searchParams['end_at'] ?? ''; $hasVirtual = $searchParams['has_virtual'] ?? ''; $isScore = $searchParams['is_score'] ?? 0; $whereMap = []; $userWhereMap = []; $order = ['id' => 'desc']; $whereMap[] = ['is_score', '=', $isScore]; if (!empty($status) && in_array($status, array_keys(OrderRepository::getInstance()->orderStatusTextList()))) { $whereMap[] = ['status', '=', $status]; } if ($hasVirtual != '') { $whereMap[] = ['has_virtual', '=', $hasVirtual]; } if (!empty($startAt) && strtotime($startAt)) { $whereMap[] = ['created_at', '>= TIME', $startAt]; } if (!empty($endAt) && strtotime($endAt)) { $whereMap[] = ['created_at', '<= TIME', $endAt]; } if (isset($searchParams['coding']) && !empty($searchParams['coding'])) { $whereMap[] = ['coding', '=', $searchParams['coding']]; } if (isset($searchParams['contacts']) && !empty($searchParams['contacts'])) { $whereMap[] = ['contacts', 'like', "%".$searchParams['contacts']."%"]; } if (isset($searchParams['phone']) && !empty($searchParams['phone'])) { $whereMap[] = ['phone', 'like', "%".$searchParams['phone']."%"]; } if (isset($searchParams['nickname']) && !empty($searchParams['nickname'])) { $userWhereMap[] = ['nickname', 'like', "%".$searchParams['nickname']."%"]; } $res = OrderModel::findList($whereMap, [], $page, $size, function ($q)use($userWhereMap) { if (!empty($userWhereMap)) { return $q->hasWhere('account', function ($query) use ($userWhereMap) { $query->where($userWhereMap); }); } else { return $q->with(['account']); } }, $order); $res['list'] = $res['list']->each(function ($item) { $item->status_text = OrderModel::statusTextList()[$item->status] ?? ''; //$item->price = Math::fen2Yuan($item->price); $item->nickname = $item->account->nickname ?? ''; $item->real_name = $item->account->real_name ?? ''; $item->pick_self_text = $item->pick_self == 1 ? '自提' : '邮寄'; $item->is_score_text = $item->is_score == 1 ? '是' : '否'; }); return $res; } /** * 获取订单商品列表 * * @return Json * @throws Exception */ public function getOrderSpu(): Json { $coding = input('coding/s', ''); $where = []; $where[] = ['order_coding', '=', $coding]; $res = OrderSku::findList($where); $res['list'] = $res['list']->each(function ($item) { $item->activity_text = \app\model\Spu::activityTextList()[$item->activity_type] ?? ''; }); return $this->json(0, '操作成功', $res); } /** * 核销订单 * * @return Json * @throws RepositoryException * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function checkSku(): Json { $coding = input('coding/s', ''); $id = input('id/d', 0); $num = input('num/d', 1); try { $checkUserInfo = sprintf("ID:%d 昵称:%s", $this->auth['user_id'], $this->auth['nickname']); OrderRepository::getInstance()->checkBase($coding, $id, $num, $checkUserInfo, OrderModel::CHECK_TYPE_BACKEND); event('OrderSpuCheck', $coding); return $this->json(0, '核销成功'); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } /** * 订单发货、重发(填写快递信息) * 已有快递记录则覆盖 * */ public function send() { $repo = OrderRepository::getInstance(); $orderId = $this->request->param('id/d', 0); try { $order = $repo->findByid($orderId, [], function ($q) { return $q->with([ 'account', 'skus' => function ($qr) { $qr->with(['sku']); } ]); }); if (empty($order)) { return $this->json(4004, '没有相关的订单信息!'); } } catch (RepositoryException $e) { return $this->json(4004, '没有相关的订单信息!'); } if ($this->request->isPost()) { $data = [ 'express_number' => trim($this->request->param('express_number/s', '')), 'express_id' => $this->request->param('express_id/d', 0), 'business_remarks' => trim($this->request->param('business_remarks/s', '')) ]; Db::startTrans(); try { $nowDate = date('Y-m-d H:i:s'); if ($order->pick_self == 1) { $sendData = [ 'shipped_at' => $nowDate, 'business_remarks' => $data['business_remarks'], ]; if (empty($order['shipped_at'])) { $sendData['shipped_at'] = $nowDate; } $sendData['status'] = OrderModel::STATUS_SHIPPED; } else { $this->validate($data, [ 'express_number|快递单号' => 'require|max:100', 'express_id|快递公司' => 'require|gt:0', 'business_remarks|卖家备注' => 'max:2000', ]); if (!$express = Express::findById($data['express_id'])) { throw new ValidateException('没有相关的快递配置信息'); } if (!in_array($order['status'], [OrderModel::STATUS_PAID, OrderModel::STATUS_SHIPPED])) { throw new ValidateException('该订单当前状态不支持配送信息的录入'); } $sendData = [ 'express_number' => $data['express_number'], 'express_code' => $express['code'], 'express_name' => $express['name'], 'business_remarks' => $data['business_remarks'], ]; if (empty($order['shipped_at']) || $order['express_number'] != $data['express_number']) { $sendData['shipped_at'] = $nowDate; } if ($order['status'] == OrderModel::STATUS_PAID) { $sendData['status'] = OrderModel::STATUS_SHIPPED; } } $order->save($sendData); Db::commit(); } catch (ValidateException $e) { Db::rollback(); return $this->json(4001, $e->getMessage()); } catch (TraitException | RepositoryException $e) { Db::rollback(); return $this->json(4002, '配送信息保存失败!'); } return $this->json(); } $this->data['id'] = $orderId; $this->data['item'] = $order; $this->data['expressJson'] = $this->handleXmExpress([$order->express_code]); $this->data['statusList'] = OrderModel::statusTextList(); return $this->view(); } /** * 订单详情 * * @return Json|View * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function info() { $id = input('id/d', 0); $item = OrderModel::findById($id, [], function ($q) { return $q->with(['account', 'skus']); }); if ($this->request->isPost()) { $data = input("item/a",[]); $data["shipped_at"] = empty($data["shipped_at"])?null:$data["shipped_at"]; $data["accepted_at"] = empty($data["accepted_at"])?null:$data["accepted_at"]; $data["wedding_date"] = empty($data["wedding_date"])?null:$data["wedding_date"]; $data["expected_delivery_date"] = empty($data["expected_delivery_date"])?null:$data["expected_delivery_date"]; $item->save($data); return $this->json(); } $this->data['id'] = $id; $this->data['item'] = $item; $this->data['statusList'] = OrderModel::statusTextList(); return $this->view(); } private function handleXmOrderStatus(array $selected = [], array $disabled = []) { $list = []; $statusList = OrderRepository::getInstance()->orderStatusTextList(); foreach ($statusList as $key => $val) { $list[] = [ 'name' => $val, 'value' => $key, 'selected' => in_array($key, $selected), 'disabled' => in_array($key, $disabled), ]; } return json_encode($list, JSON_UNESCAPED_UNICODE); } private function handleXmExpress(array $selected = [], array $disabled = []) { $selected = array_filter($selected); $disabled = array_filter($disabled); $list = []; $items = OrderRepository::getInstance()->allExpress(); foreach ($items as $item) { $list[] = [ 'name' => $item->name, 'value' => $item->id, 'selected' => in_array($item->code, $selected), 'disabled' => in_array($item->code, $disabled), ]; } return json_encode($list, JSON_UNESCAPED_UNICODE); } /** * 导出订单列表 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function exportOrderList(): Json { if ($this->request->isPost()) { $ids = input('ids/a', []); $type = input('type/s', 'all'); $isScore = input('is_score/d', 0); $where = []; $where[] = ['status', '=', OrderModel::STATUS_PAID]; $where[] = ['pick_self', '=', OrderModel::COMMON_OFF]; if ($type !== 'all') { //获取指定订单列表 $where[] = ['id', 'in', $ids]; } $where[] = ['is_score', '=', $isScore]; $list = OrderModel::where($where)->order('id', 'desc')->select(); $result['header'] = [ '订单编号', '订单状态', '下单时间', '付款时间', '配送方式', '收货信息', '买家选择快递', '快递编码', '快递单号', '注:1.若快递公司变更,请一定更改快递编码 2.上传物流时请直接在快递单号一栏填写,切勿变更列的顺序' ]; if ($list->isEmpty()) { return $this->json(200, '没有相应订单'); } $result['data'] = []; $statusList = OrderModel::statusTextList(); $list->each(function ($item) use (&$result, $statusList) { $arr = [ "'".$item['coding'],//订单编号 $statusList[$item['status']] ?? '其他',//订单状态 "'".$item['created_at'],//下单时间 "'".$item['paid_at'],//付款时间 $item['pick_self'] == 1 ? '自提' : '邮寄',//配送方式 $item['pick_self'] == 1 ? '自提' : $item['address'],//收货信息 $item['pick_self'] == 1 ? '自提' : $item['express_name'],//买家选择的快递公司 "'".$item['pick_self'] == 1 ? '' : $item['express_code'],//买家选择等快递编码 '',//快递单号 ]; $result['data'][] = $arr; }); return $this->json(0, 'success', $result); } return $this->json(4000, '请求错误'); } /** * 导入物流 * * @return Json * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function importOrder(): Json { if ($this->request->isPost()) { $fileSrc = input('file/s', ''); $path = public_path().$fileSrc; if (!file_exists($path)) { return $this->json(4000, '文件地址错误'.$path); } $inputFileType = IOFactory::identify($path); $reader = IOFactory::createReader($inputFileType); $spreadsheet = $reader->load($path); $expressList = Express::column('name', 'code');//快递公司列表 $expressCodeList = array_keys($expressList);//快递编号列表 $sheetData = $spreadsheet->getActiveSheet()->removeRow(1)->toArray(null, true, true, true); $orderCodingList = []; $update = []; $now = date('Y-m-d H:i:s'); foreach ($sheetData as $key => $data) { $currentKey = $key + 1; if (!isset($data['A']) || empty($data['A'])) { return $this->json(4000, '第'.$currentKey.'行记录订单号不存在'); } if (!isset($data['H']) || !in_array($data['H'], $expressCodeList)) { return $this->json(4000, '第'.$currentKey.'行快递公司编号不存在'); } if (!isset($data['I']) || empty($data['I'])) { continue; // 快递单号不存在则不更新 // return $this->json(4000, '第'.$currentKey.'行快递单号不存在'); } $orderCoding = $data['A']; $expressCode = $data['H']; $expressNumber = $data['I']; $orderCodingList[] = $orderCoding; $update[$orderCoding] = [ 'coding' => $orderCoding, 'status' => OrderModel::STATUS_SHIPPED, 'express_code' => $expressCode, 'express_number' => $expressNumber, 'shipped_at' => $now, 'express_name' => $expressList[$expressCode] ?? '', ]; } $orderList = OrderModel::whereIn('coding', $orderCodingList)->column('id,coding,status', 'coding'); $notUpdateStatus = [];//不更新状态都记录 $existCodings = array_keys($orderList);//数据库存在的订单编号 $coding2Id = []; // 仅修改快递信息,不修改订单状态的列表 即仅状态=付款的订单修改状态 foreach ($orderList as $order) { if ($order['status'] != OrderModel::STATUS_PAID) { $notUpdateStatus[] = $order['coding']; } $coding2Id[$order['coding']] = $order['id']; } // 存在差异的订单号(数据库不存在的) $diff = array_diff($orderCodingList, $existCodings); foreach ($update as $coding => $item) { if (in_array($coding, $diff) || !isset($coding2Id[$coding])) { unset($update[$coding]); continue; } $update[$coding]['id'] = $coding2Id[$coding]; if (in_array($coding, $notUpdateStatus)) { unset($update[$coding]['status']); } } (new OrderModel())->saveAll($update); return $this->json(0, '操作成功', ['count' => count($update)]); } return $this->json(4000, '请求错误'); } /** * 修改订单里面的sku信息 * * @return Json * @throws Exception */ public function editOrderSku(): Json { if ($this->request->isPost()) { $item = input('post.'); $validate = $this->validateByApi($item, [ 'id' => 'require', 'field' => 'require', 'value' => 'require', ]); if ($validate !== true) { return $validate; } $orderRep = OrderRepository::getInstance(); if (!$orderSkuInfo = $orderRep->getOrderSku($item['id'])) { return $this->json(4001, '订单商品记录不存在'); } if (!$order = OrderModel::findOne([["coding","=",$orderSkuInfo["order_coding"]]])) { return $this->json(4001, '订单记录不存在'); } Db::startTrans(); try { $orderSkuInfo[$item['field']] = $item['value']; //如果是 修改的字段时 数量或者单价 就要调整 $orderSkuInfo["subtotal"] = $orderSkuInfo["num"] * $orderSkuInfo["price"]; $orderSkuInfo->save(); $orderOriginalPrice = $orderRep->getOrderOriginalPrice($orderSkuInfo["order_coding"],$orderSkuInfo["coding"]); $orderOriginalPrice += $orderSkuInfo["subtotal"]; $order->save(["original_price"=>$orderOriginalPrice]); Db::commit(); return $this->json(0,"修改成功",["original_price"=>$orderOriginalPrice]); } catch (ValidateException $e) { return $this->json(4001, $e->getError()); } } return $this->json(4000, '非法请求'); } /** * 修改订单里面的sku信息 * * @return Json * @throws Exception */ public function editStatus() { $id = input('id/d'); if(!$order = OrderModel::findById($id)){ return $this->json(4001,"订单不存在"); } if ($this->request->isPost()) { $status = input("status/s"); Db::startTrans(); try { $order->save(["status"=>$status]); Db::commit(); return $this->json(); } catch (Exception $e) { return $this->json(4001, $e->getError()); } } $this->data['statusList'] = OrderModel::statusTextList(); $this->data['status'] = $order["status"]; $this->data['id'] = $id; return $this->view(); } /** * 导出订单信息 * */ public function exportOrderInfo() { $id = input("id/d"); $type = input("type/s","save"); $order = OrderModel::findById($id, [], function ($q) { return $q->with([ 'skus']); }); // 水平居中对齐 $styleArray = [ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER, ], ]; // Create new Spreadsheet object $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $spreadsheet->getActiveSheet()->setTitle('订单信息'); //设置默认行高。 $sheet->getDefaultRowDimension()->setRowHeight(30); //需要设置单元格 上下 水平居中的单元格 $needSetapplyFromArray = [ "A1","C1","D1","A2","B2","C2","D2","E2", ]; // 需要设置的单元格宽度 $setColWidth = [ "A"=>"45", "B"=>"30", "C"=>"30", "D"=>"30", "E"=>"30", ]; foreach ($setColWidth as $key=>$citem){ $spreadsheet->getActiveSheet()->getColumnDimension($key)->setWidth($citem); } //合并单元格 $spreadsheet->getActiveSheet()->mergeCells('A1:B1'); $sheet->setCellValue('A1', "日 期 : ".$order->created_at); $sheet->setCellValue('C1', "订单号 : "); $sheet->setCellValue('D1', " " . $order->coding); $sheet->setCellValue('A2', "商 品 名称"); $sheet->setCellValue('B2', "单 位"); $sheet->setCellValue('C2', "数 量"); $sheet->setCellValue('D2', "单 价"); $sheet->setCellValue('E2', "小 计"); //开始写入订单商品数据 $startRow = 3;//从第四行开始写入 $skusCount = count($order->skus->toArray()); foreach ($order->skus as $key => $item){ $sheet->setCellValue('A'.($startRow+$key), $item["spu_name"]); $sheet->setCellValue('B'.($startRow+$key), $item["sku_unit"]); $sheet->setCellValue('C'.($startRow+$key), $item["num"]); $sheet->setCellValue('D'.($startRow+$key), $item["price"]); $sheet->setCellValue('E'.($startRow+$key), $item["subtotal"]); $needSetapplyFromArray[]='A'.($startRow+$key); $needSetapplyFromArray[]='B'.($startRow+$key); $needSetapplyFromArray[]='C'.($startRow+$key); $needSetapplyFromArray[]='D'.($startRow+$key); $needSetapplyFromArray[]='E'.($startRow+$key); } $needSetapplyFromArray[] = 'D' . ($startRow + $skusCount); $needSetapplyFromArray[] = 'E' . ($startRow + $skusCount); $sheet->setCellValue('D' . ($startRow + $skusCount), "合 计"); $sheet->setCellValue('E' . ($startRow + $skusCount), $order->original_price); //单元格文字样式设置 // getStyle 获取单元格样式 // getFont 获取单元格文字样式 // setBold 设置文字粗细 // setName 设置文字字体 // setSize 设置文字大小 $sheet->getStyle('D' . ($startRow + $skusCount))->getFont()->setBold(true)->setSize(18); $sheet->getStyle('E' . ($startRow + $skusCount))->getFont()->setBold(true)->setSize(18); $sheet->getStyle('D1')->getFont()->setBold(true); $sheet->getStyle('A2:E2')->getFont()->setBold(true); $sheet->getStyle('C3:E' . ($startRow + $skusCount - 1))->getFont()->setBold(true); $sheet->getStyle('A1:E' . ($startRow + $skusCount - 1))->getFont()->setSize(12); $sheet->getStyle('A' . (($startRow + $skusCount + 1)))->getFont()->setSize(12); //设置字体颜色 $sheet->getStyle('D' . ($startRow + $skusCount))->getFont()->getColor()->setARGB(Color::COLOR_RED); $sheet->getStyle('E' . ($startRow + $skusCount))->getFont()->getColor()->setARGB(Color::COLOR_RED); $spreadsheet->getActiveSheet()->mergeCells('A' . ($startRow + $skusCount + 1) . ":" . 'E'.($startRow + $skusCount + 2)); $sheet->setCellValue('A' . (($startRow + $skusCount + 1)), "婚 期:" . $order->wedding_date . " ,希望到货时间:" . $order->expected_delivery_date . " ,收 货 地 址:" . $order->address . " ,联 系 人 :" . $order->contacts . " ,联 系 人 电 话:" . $order->phone ); $needSetapplyFromArray[] = 'A' . (($startRow + $skusCount + 1)); //设置单元格 上下 水平居中 foreach ($needSetapplyFromArray as $key => $item) { $sheet->getStyle($item)->applyFromArray($styleArray); } //第一种保存方式 $writer = new Xlsx($spreadsheet); //保存的路径可自行设置 $path = "storage/order_excel/" ; if(!is_writable($path)){ return $this->json(4001,"上传文件夹需要写入权限"); } $path.=date("Ymd")."/"; if(!is_dir(public_path().$path)){ mkdir(public_path().$path); } $downloadFileName = $order->contacts . "_" . $order->phone . "_" . $order->coding ; $fileName = $downloadFileName . ".xlsx"; $filepath = public_path().$path. $fileName; $writer->save($filepath); if($type =="save"){ return download($filepath,$downloadFileName ); }else{ return $this->json(0,"success",["url"=>$path.$fileName]); } } /** * 导出订单信息 * */ public function exportOrderInfoZip() { $urls = input("urls/s",''); $urls = array_filter(explode(",", $urls)); if(empty($urls)){ return $this->json("4001","空的文件"); } if(count($urls)>10){ return $this->json("4001","最多支持10个文件"); } $zipdir = date("Ymd_His_") .randomStr(); $downloadZipFilename = $zipdir. '.zip'; $zipFilename = public_path() . 'storage/order_excel_zip/' . $downloadZipFilename; $zip = new \ZipArchive(); // 打开一个zip文档,ZipArchive::OVERWRITE:如果存在这样的文档,则覆盖;ZipArchive::CREATE:如果不存在,则创建 $res = $zip->open($zipFilename, $zip::OVERWRITE | $zip::CREATE); $zip->addEmptyDir($zipdir); if($res){ foreach ($urls as $url) { $filrnamearr = explode("/",$url); $filrname = end($filrnamearr); $zip->addFile(public_path() . $url, $zipdir . "/" . $filrname); } $zip->close(); return download($zipFilename, $downloadZipFilename); } return $this->json(5001,"创建压缩文件失败"); } public function del() { $id = input("id/d",0); $order = OrderModel::findById($id); if(empty($order)){ return $this->json(4001,"订单不存在"); } Db::startTrans(); try { OrderSku::where("order_coding",$order["coding"])->delete(); $order->delete(); Db::commit(); return $this->json(); }catch (Exception $e){ Db::rollback(); return $this->json(5001,"删除订单失败"); } } }