diff --git a/app/Cache/Redis/Common/CommonRedisKey.php b/app/Cache/Redis/Common/CommonRedisKey.php index d988ee3..2af1d55 100644 --- a/app/Cache/Redis/Common/CommonRedisKey.php +++ b/app/Cache/Redis/Common/CommonRedisKey.php @@ -111,4 +111,12 @@ class CommonRedisKey { return '__system:site:lngLat:list'; } + + /** + * @return string + */ + public static function yiLianYunSelfAppAccreditKey(): string + { + return '__system:yiLianYun:self:app:token'; + } } \ No newline at end of file diff --git a/app/Extend/StringUtil.php b/app/Extend/StringUtil.php index a7eefbc..b20a925 100644 --- a/app/Extend/StringUtil.php +++ b/app/Extend/StringUtil.php @@ -80,4 +80,20 @@ class StringUtil } return str_shuffle($password); } + + /** + * 生成 uuidV4 + * @return string + */ + public static function generateUUIDv4(): string + { + return sprintf( + '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + // 32位十六进制数: 8-4-4-4-12 + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), + mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) + ); + } } \ No newline at end of file diff --git a/app/Lib/Print/YlyBasicsLib.php b/app/Lib/Print/YlyBasicsLib.php new file mode 100644 index 0000000..da8e085 --- /dev/null +++ b/app/Lib/Print/YlyBasicsLib.php @@ -0,0 +1,210 @@ +redisCache->exists($key)) return $this->redisCache->get($key); + + $signData = $requestData = [ + 'client_id' => config('print.yly.client_id'), + 'timestamp' => time() + ]; + + $requestData['sign'] = $this->sign($signData); + unset($signData); + $requestData['grant_type'] = config('print.yly.grant_type'); + $requestData['scope'] = config('print.yly.scope'); + $requestData['id'] = $this->getRequestId(); + + $url = config('print.yly.no_dns_request_url').config('print.yly.self_app_accredit_url'); + + try { + $ylyResponse = $this->clientFactory->create([ + 'base_uri' => $url, + 'timeout' => 5 + ])->post($url,[ + 'headers' => [ + 'Content-Type' => 'application/json' + ], + 'body' => json_encode($requestData) + ]); + + $contents = $ylyResponse->getBody()->getContents(); + + $this->log->callbackLog(__class__.':易联云服务器返回token信息:'.json_encode($contents)); + + $res = json_decode($contents,true); + + if ($res['error'] != 0 || $res['error_description'] != 'success' || empty($res['body'])) throw new Exception($res['error_description'] ?? '打印系统Token错误'); + }catch (GuzzleException|Exception $e){ + $this->log->debug(__CLASS__.':'.__FUNCTION__.':debug:'.$e->getMessage()); + throw new ErrException($e->getMessage()); + } + + $this->redisCache->delete($key); + $this->redisCache->set($key,$res['body']['access_token']); + $this->redisCache->expire($key,config('print.yly.self_app_token_expired')); + + return $res['body']['access_token']; + } + + /** + * @param string $token + * @param string $machineCode + * @param string $content + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function printTextRequest(string $token,string $machineCode,string $content): void + { + $signData = $requestData = [ + 'client_id' => config('print.yly.client_id'), + 'timestamp' => time() + ]; + + $requestData['sign'] = $this->sign($signData); + unset($signData); + $requestData['id'] = $this->getRequestId(); + $requestData['access_token'] = $token; + $requestData['machine_code'] = $machineCode; + $requestData['origin_id'] = StringUtil::randStr(16); + if (config('print.yly.idempotence') == 1) $requestData['idempotence'] = (int)config('print.yly.idempotence'); + + $requestData['content'] = $content; + + $url = config('print.yly.no_dns_request_url').config('print.yly.print_text_url'); + + try { + $ylyResponse = $this->clientFactory->create([ + 'base_uri' => $url, + 'timeout' => 5 + ])->post($url,[ + 'headers' => [ + 'Content-Type' => 'application/json' + ], + 'body' => json_encode($requestData) + ]); + + $contents = $ylyResponse->getBody()->getContents(); + + $this->log->callbackLog(__class__.':易联云打印服务器返回token信息:'.json_encode($contents)); + + $res = json_decode($contents,true); + + if ($res['error'] != 0 || $res['error_description'] != 'success' || empty($res['body'])) throw new Exception($res['error_description'] ?? '打印错误'); + }catch (GuzzleException|Exception $e){ + $this->log->debug(__CLASS__.':'.__FUNCTION__.':debug:'.$e->getMessage()); + throw new ErrException($e->getMessage()); + } + } + + /** + * @param string $token + * @param string $machineCode + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function cancelRequest(string $token,string $machineCode): void + { + $signData = $requestData = [ + 'client_id' => config('print.yly.client_id'), + 'timestamp' => time() + ]; + + $requestData['sign'] = $this->sign($signData); + unset($signData); + $requestData['id'] = $this->getRequestId(); + $requestData['access_token'] = $token; + $requestData['machine_code'] = $machineCode; + + $url = config('print.yly.no_dns_request_url').config('print.yly.cancel_all_url'); + + try { + $ylyResponse = $this->clientFactory->create([ + 'base_uri' => $url, + 'timeout' => 5 + ])->post($url,[ + 'headers' => [ + 'Content-Type' => 'application/json' + ], + 'body' => json_encode($requestData) + ]); + + $contents = $ylyResponse->getBody()->getContents(); + + $this->log->callbackLog(__class__.':易联云取消服务器返回token信息:'.json_encode($contents)); + + $res = json_decode($contents,true); + + if ($res['error'] != 0 || $res['error_description'] != 'success' || empty($res['body'])) throw new Exception($res['error_description'] ?? '取消打印错误'); + }catch (GuzzleException|Exception $e){ + $this->log->debug(__CLASS__.':'.__FUNCTION__.':debug:'.$e->getMessage()); + throw new ErrException($e->getMessage()); + } + } + + /** + * 返回签名 拼接字符串 acb 然后再 md5 + * @param $signRequestData + * @return string + */ + private function sign($signRequestData): string + { + $signRequestData[] = config('print.yly.client_secret'); + $signText = implode('', $signRequestData); + + return md5($signText); + } + + /** + * 获取请求唯一id uuid-v4 + * @return string + */ + private function getRequestId(): string + { + return StringUtil::generateUUIDv4(); + } +} \ No newline at end of file diff --git a/app/Model/Order.php b/app/Model/Order.php index 72e8001..8beb0d4 100644 --- a/app/Model/Order.php +++ b/app/Model/Order.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Model; +use App\Constants\Common\OrderCode; use Hyperf\Database\Concerns\BuildsQueries; use Hyperf\Database\Model\Builder; use Hyperf\Database\Model\Collection; @@ -74,4 +75,15 @@ class Order extends Model { return $this->where('order_sno',$orderSno)->first(); } + + /** + * @param array $orderIds + * @return int + */ + public function isCateringByOrderIds(array $orderIds): int + { + return $this->whereIn('id', $orderIds)->update([ + 'status' => OrderCode::PLAN + ]); + } } diff --git a/app/Model/PickupCode.php b/app/Model/PickupCode.php new file mode 100644 index 0000000..57f9909 --- /dev/null +++ b/app/Model/PickupCode.php @@ -0,0 +1,33 @@ + 'integer', 'order_id' => 'integer', 'copies' => 'integer']; +} diff --git a/app/Service/Admin/Catering/Option/CateringService.php b/app/Service/Admin/Catering/Option/CateringService.php index b4467b4..3f517fc 100644 --- a/app/Service/Admin/Catering/Option/CateringService.php +++ b/app/Service/Admin/Catering/Option/CateringService.php @@ -12,6 +12,7 @@ namespace App\Service\Admin\Catering\Option; use App\Cache\Redis\Api\SiteCache; use App\Constants\Admin\CateringCode; +use App\Constants\Admin\PrintCode; use App\Constants\Common\OrderCode; use App\Constants\ConfigCode; use App\Exception\ErrException; @@ -19,9 +20,11 @@ use App\Extend\StringUtil; use App\Model\Order; use App\Model\OrderGood; use App\Model\OrderOptionCateringLog; +use App\Model\PickupCode; use App\Model\Site; use App\Model\User; use App\Service\Admin\Catering\CateringBaseService; +use App\Service\Admin\Print\PrintOrderFactory; use App\Service\ServiceTrait\Admin\Catering\PrintTrait; use Exception; use Hyperf\DbConnection\Db; @@ -92,6 +95,11 @@ class CateringService extends CateringBaseService */ protected int $partitionCount; + /** + * @var int + */ + protected int $copiesCount; + public function __construct() { parent::__construct(); @@ -99,44 +107,91 @@ class CateringService extends CateringBaseService $this->partitionCount = (int)$this->configCache->getConfigValueByKey(ConfigCode::MAXIMUM_WHOLE_CASE_SPLIT); } - public function handle() + /** + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function handle(): array { $id = (int)$this->request->input('id'); + // 获取数据源 $this->logInfo = $this->orderOptionCateringLogModel->find($id); $this->siteInfo = $this->siteModel->find($this->logInfo->site_id); + // 检测数据 $this->check(); + // 截单 打印按钮置灰 $this->closePrintAndPlaceOrder(); + // 获取订单数据 $this->getOrderData(); - $this->buildPickupCode(); + // 构建取餐码 + $this->copiesCount = $this->buildPickupCode(); + if (empty($this->orderList)) throw new ErrException('无数据打印'); + + // 打印或者喷码 $res = match ($this->request->input('type')) { CateringCode::OPTION_PRINT_YLY => $this->printOrderByYly(), - CateringCode::CATERING_STATUS_FINISH => $this->printOrderByCoding(), + CateringCode::OPTION_PRINT_CODING => $this->printOrderByCoding(), }; - return $this->return->success('success', $res); + // 关闭配餐 + $this->catering(); + + return $this->return->success('success', ['list' => $res]); } + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function catering(): void + { + if ($this->isCateringByCache()) return; + + try { + Db::beginTransaction(); + + $this->logInfo->status = CateringCode::CATERING_STATUS_FINISH; + if (!$this->logInfo->save()) throw new Exception('配餐失败1'); + + if (!$this->orderModel->isCateringByOrderIds($this->orderIds)) throw new Exception('配餐失败2'); + + Db::commit(); + + $this->joinCateringCache(); + } catch (Exception $exception) { + Db::rollback(); + throw new ErrException($exception->getMessage()); + } + } + + /** + * @return int + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ private function buildPickupCode(): int { - //todo 没写完 -// if ($this->isBuildPickupCode()) { -//// return $this->getPickupCode(); -// } + if ($this->isBuildPickupCode()) { + return $this->getPickupCode(); + } $currentCode = 0; $prefix = strtoupper(StringUtil::randStr(3)); $codeRanges = []; $takeFoodCodes = []; + $currentDate = date('Y-m-d H:i:s'); foreach ($this->orderList as &$order) { - foreach ($order['good_list'] as &$goodItem) { + foreach ($order['copies_list'] as &$copiesItem) { if ($currentCode % $this->printBoxMaxNum === 0) { $startCode = $currentCode + 1; $endCode = min($currentCode + $this->printBoxMaxNum, $this->totalCopies); @@ -146,50 +201,88 @@ class CateringService extends CateringBaseService $currentCode++; $paddedCode = str_pad((string)$currentCode, 3, '0', STR_PAD_LEFT); $fullCode = "$prefix-$paddedCode"; - $goodItem['take_food_code'] = $fullCode; - $goodItem['heapsort'] = $codeRanges[$currentCode] ?? ''; + $copiesItem['take_food_code'] = $fullCode; + $copiesItem['heapsort'] = $codeRanges[$currentCode] ?? ''; $takeFoodCodes[] = [ 'order_id' => $order['id'], - 'box_num' => $goodItem['box_num'], - 'take_food_code' => $fullCode, - 'heapsort' => $goodItem['heapsort'] + 'copies' => $copiesItem['copies'], + 'pickup_code' => $fullCode, + 'heapsort' => $copiesItem['heapsort'], + 'create_time' => $currentDate ]; } } -// $this->insertTakeFoodCode($takeFoodCodes); - + $this->insertTakeFoodCode($takeFoodCodes); + unset($currentCode,$prefix,$codeRanges,$currentDate,$startCode,$endCode,$codeGroups,$paddedCode,$fullCode); return count($takeFoodCodes); } -// private function insertTakeFoodCode(array $codeRanges) -// { -// try { -// Db::beginTransaction(); -// -// /** -// * @var TakeFoodCode $takeFoodCodeModel -// */ -// $takeFoodCodeModel = app(TakeFoodCode::class); -// $takeFoodCodeModel->whereIn('order_id',$this->orderId)->delete(); -// if (!$takeFoodCodeModel->insertAll($takeFoodCodeArr)) throw new Exception('取餐码生成失败'); -// -// if (!$this->isBuildTakeFoodToday($this->todayDate,$this->cacheLockValue)) throw new Exception('取餐码生成失败-缓存已添加'); -// -// Db::commit(); -// return count($takeFoodCodeArr); -// }catch (Exception $e) { -// Db::rollback(); -// throw new ErrException($e->getMessage()); -// } -// } + /** + * @var PickupCode + */ + #[Inject] + protected PickupCode $pickupCodeModel; + + /** + * @return int + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function getPickupCode(): int + { + $pickupCodeList = $this->pickupCodeModel + ->whereIn('order_id',$this->orderIds) + ->get(['take_food_code', 'order_id', 'box_num', 'heapsort', 'id']) + ->toArray(); + + if (empty($pickupCodeList)) { + $this->delPickUpCodeByIdCache(); + throw new ErrException('找不到数据,请重新生成'); + } + + $pickupCodeArrList = $this->buildPickupCodeListData($pickupCodeList); + + foreach ($this->orderList as &$order) { + foreach ($order['copies_list'] as &$copiesItem) { + $copiesItem['take_food_code'] = $pickupCodeArrList[$copiesItem['id']][$copiesItem]['take_food_code']; + $copiesItem['heapsort'] = $pickupCodeArrList[$copiesItem['id']][$copiesItem]['heapsort']; + } + } + unset($pickupCodeArrList); + return count($pickupCodeList); + } + + /** + * @param array $codeRanges + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function insertTakeFoodCode(array $codeRanges): void + { + try { + Db::beginTransaction(); + + $delRes = $this->pickupCodeModel->whereIn('order_id',$this->orderIds)->delete(); + $insertModel = new PickupCode(); + $insertRes = $insertModel->insert($codeRanges); + + if (!$insertRes || !$delRes) throw new Exception('取餐码生成失败'); + + $this->buildPickupCodeCache(); + + Db::commit(); + }catch (Exception $e) { + Db::rollback(); + throw new ErrException($e->getMessage()); + } + } /** * 将数组尽可能均匀地分割为指定份数 * @param array $array 输入数组 * @return array - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface */ private function splitArrayIntoPartitions(array $array): array { @@ -275,7 +368,7 @@ class CateringService extends CateringBaseService $one['driver_num'] = $driverInfo->driver_num; $one['site_order'] = $this->siteInfo->sequence; $one['real_name'] = $driverInfo->driver_name; - $one['good_list'] = array_values($orderGoodArr[$one['id']]); + $one['copies_list'] = array_values($orderGoodArr[$one['id']]); } $this->orderList = $orderList; @@ -323,6 +416,38 @@ class CateringService extends CateringBaseService return $result; } + /** + * @param array $data + * @return array + */ + private function buildPickupCodeListData(array $data): array + { + $result = []; + foreach ($data as $item) { + // 提取关键字段 + $orderId = $item["order_id"]; + $copies = $item["copies"]; + $pickupCode = $item["pickup_code"]; + $heapsort = $item["heapsort"]; + + // 按层级构建数组结构 + if (!isset($result[$orderId])) { + $result[$orderId] = []; + } + + if (!isset($result[$orderId][$copies])) { + $result[$orderId][$copies] = []; + } + + $result[$orderId][$copies][] = [ + 'pickup_code' => $pickupCode, + 'heapsort' => $heapsort, + ]; + } + + return $result; + } + /** * 打印置灰和截单 * @return void @@ -355,13 +480,123 @@ class CateringService extends CateringBaseService if ($this->logInfo->quantity <= 0) throw new ErrException('该配餐数量为0,不可配餐'); } + /** + * @var PrintOrderFactory + */ + #[Inject] + protected PrintOrderFactory $printOrderFactory; + + /** + * @return true + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ private function printOrderByYly(): true { + $service = $this->printOrderFactory->handle($this->request->input('type')); + $service->printId = (int)$this->request->input('print_id'); + $service->handle(); + + $printBoxNum = 0; + $printCurrentNum = 0; + foreach ($this->orderList as $one) { + foreach ($one['copies_list'] as $copiesItem) { + // 先加当前数量 + $printBoxNum++; + + $service->data = [ + 'pickup_code' => $copiesItem['pickup_code'], + 'driver_num' => '', + 'site_order' => '', + 'site_text' => '', + 'order_sno' => '', + 'username' => '', + 'date' => '', + 'mobile' => '', + 'heapsort' => $copiesItem['heapsort'], + 'sku' => $copiesItem['sku'], + ]; + + // 打印单份 + $service->printList(); + + // 当前数量等于最大值 归零 + if ($printBoxNum == $this->printBoxMaxNum || $this->printBoxMaxNum * $printCurrentNum+$printBoxNum == $this->copiesCount) { + $printBoxNum = 0; + $printCurrentNum++; + } + + //不归零跳出 当前循环 + if ($printBoxNum != 0) continue; + + $service->data = [ + 'driver_num' => '', + 'site_order' => '', + 'site_text' => '', + 'driver_name' => '', + 'current_num' => $printCurrentNum, + 'date_text' => date('Y-m-d'), + 'copies_num' => $this->copiesCount, + ]; + + // 打印标签 + $service->printBoxLabel(); + } + } + return true; } - private function printOrderByCoding() + /** + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function printOrderByCoding(): array { - return []; + $service = $this->printOrderFactory->handle($this->request->input('type')); + + $printBoxNum = 0; + $printCurrentNum = 0; + + + $data=[]; + foreach ($this->orderList as $one) { + foreach ($one['copies_list'] as $copiesItem) { + $service->data = [ + 'pickup_code' => $copiesItem['pickup_code'], + 'driver_num' => '', + 'site_order' => '', + 'site_text' => '', + 'order_sno' => '', + 'username' => '', + 'date' => '', + 'mobile' => '', + 'heapsort' => $copiesItem['heapsort'], + 'sku' => $copiesItem['sku'], + ]; + $data[] = $service->printList(); + + //先加当前数量 + $printBoxNum++; + + //当前数量等于最大值 归零 + if ($printBoxNum == $this->printBoxMaxNum || $this->printBoxMaxNum*$printCurrentNum+$printBoxNum == $this->copiesCount) { + $printBoxNum = 0; + $printCurrentNum++; + } + + //不归零跳出 当前循环 + if ($printBoxNum != 0) continue; + + //归零打印 +// $service->printInfo['current_num'] = $printCurrentNum; +// $service->printInfo['date_text'] = date('Y-m-d',$this->todayDate); +// $service->printInfo['box_num'] = $boxNum; +// $service->printBoxLabel(); + } + } + + return $data; } } \ No newline at end of file diff --git a/app/Service/Admin/Print/JdPrintService.php b/app/Service/Admin/Print/JdPrintService.php new file mode 100644 index 0000000..1a8805c --- /dev/null +++ b/app/Service/Admin/Print/JdPrintService.php @@ -0,0 +1,107 @@ +checkOrderData(); + + $this->buildOrderContent(); + + return $this->res; + } + + /** + * @return void + */ + private function checkOrderData(): void + { + if (empty($this->data)) throw new ErrException('打印商品数据不存在'); + + if ( + empty($this->data['pickup_code']) || + empty($this->data['driver_num']) || + empty($this->data['site_order']) || + empty($this->data['site_text']) || + empty($this->data['sku']) || + empty($this->data['order_sno']) || + empty($this->data['username']) || + empty($this->data['mobile']) || + empty($this->data['date']) || + empty($this->data['heapsort']) + ) throw new ErrException('打印数据丢失'); + } + + /** + * @return void + */ + private function buildOrderContent(): void + { + $this->res = []; + + $this->res['pickup_code'] = $this->data['pickup_code']; + $this->res['line_sort'] = sprintf('%s-%s', $this->data['driver_num'], $this->data['site_order']); + $this->res['site_name'] = $this->data['site_text']; + + $codeNum = []; + foreach ($this->data['sku'] as $one) { + for ($i = 0;$i < $one['num'];$i++) { + $codeNum[] = $one['code_num']; + } + } + sort($codeNum); + $goodsArr = array_chunk($codeNum,3,true); + $good =[]; + foreach ($goodsArr as $one) { + $good[] = array_values($one); + } + $this->res['goods_arr'] = $good; + + $this->res['order_end_number'] = substr($this->data['order_sno'], strlen($this->data['order_sno']) - 8, 8); + $this->res['username'] = $this->data['username']; + $this->res['mobile_end_number'] = substr($this->data['mobile'], strlen($this->data['mobile']) - 4, 4); + $this->res['meal_dates'] = $this->data['date']; + $this->res['build_date'] = $this->data['date'].config('print.common.production_date'); + $this->res['shelf_life'] = config('print.common.content_edible_time_tips'); + $this->res['heapsort'] = $this->data['heapsort']; + } + + /** + * @return array + */ + public function printSingleOrder(): array + { + return $this->printList(); + } + + public function printCancel() {} +} \ No newline at end of file diff --git a/app/Service/Admin/Print/PrintOrderFactory.php b/app/Service/Admin/Print/PrintOrderFactory.php new file mode 100644 index 0000000..8c0b477 --- /dev/null +++ b/app/Service/Admin/Print/PrintOrderFactory.php @@ -0,0 +1,30 @@ + new YlyPrintService(), + CateringCode::OPTION_PRINT_CODING => new JdPrintService(), + default => throw new ErrException('Order printing class does not exist'), + }; + } +} \ No newline at end of file diff --git a/app/Service/Admin/Print/PrintOrderInterface.php b/app/Service/Admin/Print/PrintOrderInterface.php new file mode 100644 index 0000000..17c6de0 --- /dev/null +++ b/app/Service/Admin/Print/PrintOrderInterface.php @@ -0,0 +1,20 @@ +orderOptionCateringLogModel->where('id',$this->printId)->first(); + + if (empty($printInfo)) throw new ErrException('打印机不存在-1'); + + if (empty($printInfo->code_value) || $printInfo->code_value == '') throw new ErrException('打印机不存在-2'); + + $this->token = $this->ylyBasicsLib->selfAppAccredit(); + $this->machineCode = $printInfo->code_value; + } + + /** + * @return true + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function printList(): true + { + $this->checkOrderData(); + + $this->buildOrderContent(); + + $this->ylyBasicsLib->printTextRequest($this->token,$this->machineCode,$this->content); + + return true; + } + + /** + * @return void + */ + private function checkOrderData(): void + { + if (empty($this->data)) throw new ErrException('打印商品数据不存在'); + + if ( + empty($this->data['pickup_code']) || + empty($this->data['driver_num']) || + empty($this->data['site_order']) || + empty($this->data['site_text']) || + empty($this->data['sku']) || + empty($this->data['order_sno']) || + empty($this->data['username']) || + empty($this->data['mobile']) || + empty($this->data['date']) || + empty($this->data['heapsort']) + ) throw new ErrException('打印数据丢失'); + } + + /** + * @return void + */ + private function buildOrderContent(): void + { + //重置数据 + $this->content = ''; + + //设置高度 + $this->content .= "100,1"; + //设置宽度 + $this->content .= "048"; + + $this->content .= "\n"; + $this->content .= "\n"; + + //取餐号 + $this->content .= "{$this->data['pickup_code']}\n"; + + //司机号码 - 线路顺序 + $this->content .= "线路:{$this->data['driver_num']}-{$this->data['site_order']}\n"; + + //配送点 + $this->content .= "配送点:{$this->data['site_text']}\n"; + + // 表头 + $this->content .= "--------------------------------\n"; + + //菜品表格 + $codeNum = []; + foreach ($this->data['sku'] as $one) { + for ($i = 0;$i < $one['num'];$i++) { + $codeNum[] = $one['code_num']; + } + } + sort($codeNum); + $goodsArr = array_chunk($codeNum,3,true); + foreach ($goodsArr as $one) { + $one = array_values($one); + switch (count($one)) { + case 1: + $this->content .= "{$one[0]}\n"; + break; + case 2: + $this->content .= "{$one[0]}.{$one[1]}\n"; + break; + case 3: + $this->content .= "{$one[0]}.{$one[1]}.{$one[2]}\n"; + break; + } + } + + //下面分割符号 + $this->content .= "--------------------------------\n"; + + //订单号 截取订单号 + $last8Chars = substr($this->data['order_sno'], strlen($this->data['order_sno']) - 8, 8); + $this->content .= "订单尾号,{$last8Chars}"; + + //用户昵称 + $this->content .= "用户昵称,{$this->data['username']}"; + + //手机尾号 + $last4Chars = substr($this->data['mobile'], strlen($this->data['mobile']) - 4, 4); + $this->content .= "手机尾号,{$last4Chars}"; + + //套餐日期 + $this->content .= "套餐日期,{$this->data['date']}"; + + //生产日期 + $productionTime = $this->data['date'].config('print.yly.production_time'); + $this->content .= "生产日期,$productionTime"; + + //保质期 + $contentEdibleTimeTips = config('print.yly.content_edible_time_tips'); + $this->content .= "保质期,$contentEdibleTimeTips"; + + $this->content .= "{$this->data['heapsort']}"; + } + + /** + * @return true + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function printSingleOrder(): true + { + return $this->printList(); + } + + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function printCancel(): void + { + $this->ylyBasicsLib->cancelRequest($this->token,$this->machineCode); + } + + /** + * @return true + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function printBoxLabel(): true + { + $this->checkBoxLabelData(); + + $this->buildBoxContent(); + + $this->ylyBasicsLib->printTextRequest($this->token,$this->machineCode,$this->content); + + return true; + } + + /** + * @return void + */ + private function checkBoxLabelData(): void + { + if (empty($this->data)) throw new ErrException('打印标签数据不存在'); + + if ( + empty($this->data['driver_num']) || + empty($this->data['site_order']) || + empty($this->data['site_text']) || + empty($this->data['copies_num']) || + empty($this->data['driver_name']) || + empty($this->data['current_num']) || + empty($this->data['date_text']) + ) throw new ErrException('打印数据丢失'); + } + + /** + * @return void + */ + private function buildBoxContent(): void + { + // 重置 + $this->content = ''; + + //设置高度 + $this->content .= "100,1"; + //设置宽度 + $this->content .= "048"; + + //上下居中 + $this->content .= "\n"; + $this->content .= "\n"; + $this->content .= "\n"; + $this->content .= "\n"; + $this->content .= "\n"; + $this->content .= "\n"; + $this->content .= "\n"; + + // 司机号码 - 线路顺序 + $this->content .= "线路:{$this->data['driver_num']}-{$this->data['site_order']}\n"; + $this->content .= "\n"; + + // 总量 + $this->content .= "总份数:{$this->data['copies_num']}\n"; + $this->content .= "\n"; + + // 箱数 + $currentNum = str_pad($this->data['current_num'], 2, '0', STR_PAD_LEFT); + $this->content .= "箱数:$currentNum\n"; + $this->content .= "\n"; + + // 配送点 + $this->content .= "配送司机: {$this->data['driver_name']}\n"; + $this->content .= "\n"; + + // 配送点 + $this->content .= "配送点: {$this->data['site_text']}\n"; + $this->content .= "\n"; + + // 套餐日期 + $this->content .= "{$this->data['date_text']}\n"; + } +} \ No newline at end of file diff --git a/app/Service/ServiceTrait/Admin/Catering/PrintTrait.php b/app/Service/ServiceTrait/Admin/Catering/PrintTrait.php index aa171b4..4546898 100644 --- a/app/Service/ServiceTrait/Admin/Catering/PrintTrait.php +++ b/app/Service/ServiceTrait/Admin/Catering/PrintTrait.php @@ -5,8 +5,8 @@ namespace App\Service\ServiceTrait\Admin\Catering; use App\Cache\Redis\Admin\AdminRedisKey; use App\Cache\Redis\RedisCache; use App\Constants\Admin\CateringCode; +use App\Exception\ErrException; use App\Extend\DateUtil; -use App\Extend\StringUtil; use Hyperf\Di\Annotation\Inject; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -27,17 +27,6 @@ trait PrintTrait protected string $pickupCodeKey; protected string $isCateringKey; - /** - * 前缀 - * @var string - */ - protected string $currentPrefix; - - /** - * 分组 - * @var array - */ - protected array $currentHeapSort; /** * @@ -155,4 +144,49 @@ trait PrintTrait return false; } + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function buildPickupCodeCache(): void + { + if (CateringCode::REDIS_FINISH_VALUE == $this->redis->hGet($this->pickupCodeKey, $this->logInfo->id)) return; + + $this->redis->hSet($this->pickupCodeKey, $this->logInfo->id, CateringCode::REDIS_FINISH_VALUE); + } + + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function delPickUpCodeByIdCache(): void + { + $this->redis->hDel($this->pickupCodeKey, $this->logInfo->id); + } + + /** + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function isCateringByCache(): bool + { + if (CateringCode::REDIS_FINISH_VALUE == $this->redis->hGet($this->isCateringKey, $this->logInfo->id)) return true; + + return false; + } + + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function joinCateringCache(): void + { + if (CateringCode::REDIS_FINISH_VALUE == $this->redis->hGet($this->isCateringKey, $this->logInfo->id)) return; + + $this->redis->hSet($this->isCateringKey, $this->logInfo->id, CateringCode::REDIS_FINISH_VALUE); + } } \ No newline at end of file diff --git a/config/autoload/print.php b/config/autoload/print.php new file mode 100644 index 0000000..45324ba --- /dev/null +++ b/config/autoload/print.php @@ -0,0 +1,64 @@ + [ + // 国内请求域名 + 'request_url' => 'https://open-api.10ss.net/v2', + // 国际请求域名 + 'internation_request_url' => 'https://open-api-os.10ss.net/v2', + // 国内请求域名(无 dns) + 'no_dns_request_url' => 'https://cloud-open-api.10ss.net/v2', + // 自有应用 access_token 一天可以获取的次数 + 'self_app_day_num' => 20, + // 自有应用 access_token 过期时间 (ps:文档中说这个值无效,可以随便设置) 设置6小时 重新获取access_token后,旧的access_token将在两小时内失效。因此,请确保及时替换为最新获取的access_token + 'self_app_token_expired' => 21600, + // grant type + 'grant_type' => 'client_credentials', + // 权限范围 + 'scope' => 'all', + // 自有 app授权 url + 'self_app_accredit_url' => '/oauth/oauth', + // 开放 oauth 2.0授权 url + 'publicly_app_oauth_accredit_url' => '/oauth/authorize', + // 开放授权 + 'publicly_app_accredit_url' => '/oauth/scancodemodel', + // 打印文本 + 'print_text_url' => '/print/index', + // 打印图片 + 'print_image_url' => '/pictureprint/index', + // string 取消所有(当前终端未打印) + 'cancel_all_url' => '/printer/cancelall', + // client_id + 'client_id' => '1093877947', + // client_secret + 'client_secret' => '65a5949913c3e7e91c943f35aeee8c2e', + // 默认1,传入本参数,会根据origin_id进行幂等处理,2小时内相同origin_id会返回上一次的结果 + 'idempotence' => 1, + // 打印抬头 + 'content_title' => env('print_content_title','合合乐团餐'), + // 打印提示 + 'content_edible_time_tips' => env('print_content_edible_time_tips','建议四小时内食用完'), + // 打印时间 + 'production_date' => env('print_production_date','11:00:00'), + ], + 'common' => [ + // 打印抬头 + 'content_title' => env('print_content_title','合合乐团餐'), + // 打印提示 + 'content_edible_time_tips' => env('print_content_edible_time_tips','建议四小时内食用完'), + // 打印时间 + 'production_date' => env('print_production_date','11:00:00'), + ] +]; +