You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yanzong/app/store/service/order/Export.php

311 lines
11 KiB

<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\store\service\order;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use app\store\model\{Order as OrderModel, order\Export as ExportModel, OrderAddress as OrderAddressModel};
use app\common\library\helper;
use app\common\service\BaseService;
use app\common\service\Goods as GoodsService;
use app\common\enum\order\{
PayStatus as PayStatusEnum,
OrderSource as OrderSourceEnum,
OrderStatus as OrderStatusEnum,
DeliveryType as DeliveryTypeEnum,
ReceiptStatus as ReceiptStatusEnum,
DeliveryStatus as DeliveryStatusEnum,
export\ExportStatus as ExportStatusEnum
};
use app\common\enum\payment\Method as PaymentMethodEnum;
use cores\exception\BaseException;
/**
* 服务层:订单导出Excel
* Class Export
* @package app\store\service\order
*/
class Export extends BaseService
{
// 表格文件标题名称
private string $title = '订单导出结果';
/**
* 执行订单导出excel
* @param array $param
* @return bool
* @throws BaseException
*/
public function exportOrder(array $param): bool
{
// 根据条件查询订单列表
$orderList = $this->getOrderList($param);
// 格式化生成表格数据
$excelList = $this->getExcelList($orderList->toArray(), $param['columns']);
// 获取导出的记录列名集
$columns = $this->getColumns($param['columns']);
// 输出并写入到excel文件
$filePath = $this->outputExcel($columns, $excelList);
// 新增订单导出记录
$this->record($param, $filePath);
return true;
}
/**
* 根据条件查询订单列表
* @param array $param
* @return mixed
* @throws BaseException
*/
private function getOrderList(array $param)
{
// 根据条件查询订单列表
$orderList = (new OrderModel)->getListAll($param);
if (empty($orderList) || $orderList->isEmpty()) {
throwError('很抱歉,没有查询到订单数据');
}
return $orderList;
}
/**
* 输出并写入到excel文件
* @param array $columns 列名
* @param array $excelList 表格内容
* @return string
* @throws BaseException
*/
private function outputExcel(array $columns, array $excelList): string
{
// 生成工作表
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet()->setTitle($this->title);
// 列宽
$sheet->getDefaultColumnDimension()->setWidth(24);
// 默认行高
$sheet->getDefaultRowDimension()->setRowHeight(20);
// 字体加粗(第一行)
$sheet->getStyle('1')->getFont()->setBold(true);
// 写入标题数据
foreach ($columns as $key => $val) {
$sheet->setCellValueByColumnAndRow($key + 1, 1, $val);
}
// 写入内容数据
foreach ($excelList as $key => $item) {
$row = $key + 2;
foreach (array_values($item) as $k => $val) {
$sheet->setCellValueByColumnAndRow($k + 1, $row, $val);
}
}
// 生成文件路径
$fileName = 'order-' . time() . '.xlsx';
// 获取导出的文件夹路径
$filePath = $this->getExportPath();
// 保存到文件
try {
$writer = new Xlsx($spreadsheet);
$writer->save(public_path() . $filePath . $fileName);
} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
throwError($e->getMessage());
}
return $filePath . $fileName;
}
/**
* 获取导出的文件夹路径
* @return string
*/
private function getExportPath(): string
{
$filePath = 'downloads/' . $this->getStoreId() . '/';
!is_dir($filePath) && mkdir($filePath, 0755, true);
return $filePath;
}
/**
* 写入订单导出记录
* @param array $param
* @param string $filePath
* @return void
*/
private function record(array $param, string $filePath): void
{
// 生成记录数据
$data = [
'file_path' => $filePath,
'status' => ExportStatusEnum::COMPLETED,
'store_id' => $this->getStoreId(),
];
// 起止时间
if (!empty($param['betweenTime'])) {
$times = between_time($param['betweenTime']);
$data['start_time'] = $times['start_time'];
$data['end_time'] = $times['end_time'];
}
// 新增记录
$model = new ExportModel;
$model->add($data);
}
/**
* 获取导出的记录列名集
* @param array $onlyFields
* @return array
*/
private function getColumns(array $onlyFields): array
{
return array_values(helper::pick($this->dictionary(), $onlyFields));
}
/**
* 订单记录字典
* @return string[]
*/
private function dictionary(): array
{
return [
'order_id' => '订单ID',
'order_no' => '订单号',
'goods_detail' => '商品信息',
'total_price' => '商品总额',
'coupon_money' => '优惠券抵扣金额',
'points_money' => '积分抵扣金额',
'update_price' => '后台改价',
'express_price' => '运费金额',
'pay_price' => '订单实付款',
'pay_method' => '支付方式',
'create_time' => '下单时间',
'user_info' => '买家信息',
'buyer_remark' => '买家留言',
'delivery_type' => '配送方式',
'receipt_name' => '收货人',
'receipt_phone' => '联系电话',
'receipt_address' => '收货地址',
'extract_shop_name' => '自提门店名称',
'extract_linkman' => '自提联系人',
'extract_phone' => '自提联系电话',
'pay_status' => '付款状态',
'pay_time' => '付款时间',
'delivery_status' => '发货状态',
'delivery_time' => '发货时间',
'receipt_status' => '收货状态',
'receipt_time' => '收货时间',
'order_status' => '订单状态',
'is_comment' => '是否已评价',
'order_source' => '订单来源',
];
}
/**
* 格式化生成表格数据
* @param array $orderList
* @param array $onlyFields
* @return array
*/
private function getExcelList(array $orderList, array $onlyFields): array
{
// 获取订单表格数据
$excelList = $this->getOrderDataForExcel($orderList);
// 仅输出用户设置的字段
$data = [];
foreach ($excelList as $item) {
$data[] = helper::pick($item, $onlyFields);
}
return $data;
}
/**
* 获取订单列表数据(用于生成Excel)
* @param $orderList
* @return array
*/
private function getOrderDataForExcel($orderList): array
{
// 表格内容
$dataArray = [];
foreach ($orderList as $order) {
$dataArray[] = [
'order_id' => $this->filterValue($order['order_id']),
'order_no' => $this->filterValue($order['order_no']),
'goods_detail' => $this->filterGoodsInfo($order),
'total_price' => $this->filterValue($order['total_price']) . '元',
'coupon_money' => $this->filterValue($order['coupon_money']) . '元',
'points_money' => $this->filterValue($order['points_money']) . '元',
'update_price' => "{$order['update_price']['symbol']}{$order['update_price']['value']}",
'express_price' => $this->filterValue($order['express_price']) . '元',
'pay_price' => $this->filterValue($order['pay_price']) . '元',
'pay_method' => $this->filterPayMethod($order['pay_method']),
'create_time' => $this->filterValue($order['create_time']),
'user_info' => $this->filterValue($order['user']['nick_name']),
'buyer_remark' => $this->filterValue($order['buyer_remark']),
'delivery_type' => DeliveryTypeEnum::data()[$order['delivery_type']]['name'],
'receipt_name' => !empty($order['address']) ? $this->filterValue($order['address']['name']) : '',
'receipt_phone' => !empty($order['address']) ? $this->filterValue($order['address']['phone']) : '',
'receipt_address' => !empty($order['address']) ? OrderAddressModel::fullAddress($order['address']) : '',
'extract_shop_name' => !empty($order['extract_shop']) ? $order['extract_shop']['shop_name'] : '',
'extract_linkman' => !empty($order['extract']) ? $order['extract']['linkman'] : '',
'extract_phone' => !empty($order['extract']) ? $order['extract']['phone'] : '',
'pay_status' => PayStatusEnum::data()[$order['pay_status']]['name'],
'pay_time' => $order['pay_time'],
'delivery_status' => DeliveryStatusEnum::data()[$order['delivery_status']]['name'],
'delivery_time' => $order['delivery_time'] ?: '',
'receipt_status' => ReceiptStatusEnum::data()[$order['receipt_status']]['name'],
'receipt_time' => $order['receipt_time'] ?: '',
'order_status' => OrderStatusEnum::data()[$order['order_status']]['name'],
'is_comment' => $order['is_comment'] ? '是' : '否',
'order_source' => OrderSourceEnum::data()[$order['order_source']]['name'],
];
}
return $dataArray;
}
/**
* 格式化支付方式
* @param string $payMethod
* @return string
*/
private function filterPayMethod(string $payMethod): string
{
$enum = PaymentMethodEnum::data();
return isset($enum[$payMethod]) ? $enum[$payMethod]['name'] : '';
}
/**
* 格式化商品信息
* @param $order
* @return string
*/
private function filterGoodsInfo($order): string
{
$content = '';
foreach ($order['goods'] as $key => $goods) {
$content .= ($key + 1) . ".商品名称:{$goods['goods_name']}\n";
if (!empty($goods['goods_props'])) {
$goodsAttr = GoodsService::goodsPropsToAttr($goods['goods_props']);
$content .= " 商品规格:{$goodsAttr}\n";
}
$content .= " 购买数量:{$goods['total_num']}\n";
$content .= " 商品总价:{$goods['total_price']}\n\n";
}
return $content;
}
/**
* 表格值过滤
* @param $value
* @return string
*/
private function filterValue($value): string
{
return "\t{$value}\t";
}
}