Răsfoiți Sursa

新增:后台订单导出excel

Martin 5 ani în urmă
părinte
comite
3088a3b5cb

+ 18 - 9
app/common.php

@@ -102,15 +102,6 @@ function base_url()
     return $baseUrl;
 }
 
-/**
- * 获取当前uploads目录访问地址
- * @return string
- */
-function uploads_url()
-{
-    return base_url() . 'uploads';
-}
-
 /**
  * 获取当前url的子目录路径
  * @return string
@@ -126,6 +117,24 @@ function root_url()
     return $rootUrl;
 }
 
+/**
+ * 获取当前uploads目录访问地址
+ * @return string
+ */
+function uploads_url()
+{
+    return base_url() . 'uploads';
+}
+
+/**
+ * 获取当前temp目录访问地址
+ * @return string
+ */
+function temp_url()
+{
+    return base_url() . 'temp/';
+}
+
 /**
  * 获取当前的应用名称
  * @return mixed

+ 17 - 0
app/common/enum/order/ReceiptStatus.php

@@ -27,4 +27,21 @@ class ReceiptStatus extends EnumBasics
     // 已收货
     const RECEIVED = 20;
 
+    /**
+     * 获取枚举数据
+     * @return array
+     */
+    public static function data()
+    {
+        return [
+            self::NOT_RECEIVED => [
+                'name' => '未收货',
+                'value' => self::NOT_RECEIVED,
+            ],
+            self::RECEIVED => [
+                'name' => '已收货',
+                'value' => self::RECEIVED,
+            ],
+        ];
+    }
 }

+ 54 - 0
app/common/enum/order/export/ExportStatus.php

@@ -0,0 +1,54 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\common\enum\order\export;
+
+use app\common\enum\EnumBasics;
+
+/**
+ * 枚举类:导出状态
+ * Class ExportStatus
+ * @package app\common\enum\order\export
+ */
+class ExportStatus extends EnumBasics
+{
+    // 进行中
+    const NORMAL = 10;
+
+    // 已完成
+    const COMPLETED = 20;
+
+    // 失败
+    const FAIL = 30;
+
+    /**
+     * 获取枚举数据
+     * @return array
+     */
+    public static function data()
+    {
+        return [
+            self::NORMAL => [
+                'name' => '进行中',
+                'value' => self::NORMAL,
+            ],
+            self::COMPLETED => [
+                'name' => '已完成',
+                'value' => self::COMPLETED,
+            ],
+            self::FAIL => [
+                'name' => '失败',
+                'value' => self::FAIL,
+            ]
+        ];
+    }
+}

+ 9 - 0
app/common/model/OrderAddress.php

@@ -63,4 +63,13 @@ class OrderAddress extends BaseModel
         return $this['region']['province'] . $this['region']['city'] . $this['region']['region'] . $this['detail'];
     }
 
+    /**
+     * 获取完整地址
+     * @param $detail
+     * @return string
+     */
+    public static function fullAddress($detail)
+    {
+        return $detail['region']['province'] . $detail['region']['city'] . $detail['region']['region'] . $detail['detail'];
+    }
 }

+ 2 - 2
app/common/model/UploadFile.php

@@ -8,7 +8,7 @@
 // +----------------------------------------------------------------------
 // | Author: 萤火科技 <admin@yiovo.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 namespace app\common\model;
 
@@ -71,7 +71,7 @@ class UploadFile extends BaseModel
     {
         // 存储方式本地:拼接当前域名
         if ($data['storage'] === StorageEnum::LOCAL) {
-            $data['domain'] = uploads_url();
+            $data['domain'] = rtrim(uploads_url(), '/');
         }
         return "{$data['domain']}/{$data['file_path']}";
     }

+ 59 - 0
app/common/model/order/Export.php

@@ -0,0 +1,59 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\common\model\order;
+
+use cores\BaseModel;
+
+/**
+ * 订单导出Excel记录模型
+ * Class Export
+ * @package app\common\model\order
+ */
+class Export extends BaseModel
+{
+    // 定义表名
+    protected $name = 'order_export';
+
+    // 定义主键
+    protected $pk = 'id';
+
+    /**
+     * 获取器:下单时间(开始)
+     * @param $value
+     * @return string
+     */
+    public function getStartTimeAttr($value)
+    {
+        return format_time($value, false);
+    }
+
+    /**
+     * 获取器:下单时间(结束)
+     * @param $value
+     * @return string
+     */
+    public function getEndTimeAttr($value)
+    {
+        return format_time($value, false);
+    }
+
+    /**
+     * 导出记录详情
+     * @param int $id
+     * @return array|null|static
+     */
+    public static function detail(int $id)
+    {
+        return self::get($id);
+    }
+}

+ 52 - 0
app/store/controller/order/Export.php

@@ -0,0 +1,52 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\store\controller\order;
+
+use app\store\controller\Controller;
+use app\store\model\order\Export as ExportModel;
+use app\store\service\order\Export as ExportService;
+use app\common\exception\BaseException;
+
+/**
+ * 订单导出记录控制器
+ * Class Export
+ * @package app\store\controller\order
+ */
+class Export extends Controller
+{
+    /**
+     * 执行订单导出excel
+     * @return array|\think\response\Json
+     * @throws BaseException
+     */
+    public function exportOrder()
+    {
+        $model = new ExportService;
+        if (!$model->exportOrder($this->request->param())) {
+            $this->renderError($model->getError() ?: '导出失败');
+        }
+        return $this->renderSuccess('导出Excel文件成功,请在导出记录中下载');
+    }
+
+    /**
+     * 订单导出记录
+     * @return array|\think\response\Json
+     * @throws \think\db\exception\DbException
+     */
+    public function list()
+    {
+        $model = new ExportModel;
+        $list = $model->getList();
+        return $this->renderSuccess(compact('list'));
+    }
+}

+ 2 - 2
app/store/model/Order.php

@@ -8,7 +8,7 @@
 // +----------------------------------------------------------------------
 // | Author: 萤火科技 <admin@yiovo.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 namespace app\store\model;
 
@@ -101,7 +101,7 @@ class Order extends OrderModel
         // 设置订单类型条件
         $dataTypeFilter = $this->getFilterDataType($dataType);
         // 获取数据列表
-        return $this->with(['goods.image', 'address', 'user.avatar'])
+        return $this->with(['goods.image', 'address', 'user.avatar', 'express'])
             ->alias('order')
             ->field('order.*')
             ->join('user', 'user.user_id = order.user_id')

+ 49 - 0
app/store/model/order/Export.php

@@ -0,0 +1,49 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\store\model\order;
+
+use app\common\model\order\Export as ExportModel;
+
+/**
+ * 订单导出Excel记录模型
+ * Class Export
+ * @package app\store\model\order
+ */
+class Export extends ExportModel
+{
+    /**
+     * 获取导出记录
+     * @return mixed
+     * @throws \think\db\exception\DbException
+     */
+    public function getList()
+    {
+        // 获取列表记录
+        $list = $this->order(['create_time' => 'desc'])->paginate(10);
+        // 生成下载url
+        foreach ($list as &$item) {
+            $item['download_url'] = base_url() . $item['file_path'];
+        }
+        return $list;
+    }
+
+    /**
+     * 新增数据
+     * @param $data
+     * @return bool
+     */
+    public function add($data)
+    {
+        return $this->save($data);
+    }
+}

+ 286 - 0
app/store/service/order/Export.php

@@ -0,0 +1,286 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 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;
+use app\store\model\order\Export as ExportModel;
+use app\store\model\OrderAddress as OrderAddressModel;
+use app\common\library\helper;
+use app\common\service\BaseService;
+use app\common\enum\order\PayType as PayTypeEnum;
+use app\common\enum\order\PayStatus as PayStatusEnum;
+use app\common\enum\order\OrderSource as OrderSourceEnum;
+use app\common\enum\order\OrderStatus as OrderStatusEnum;
+use app\common\enum\order\DeliveryType as DeliveryTypeEnum;
+use app\common\enum\order\ReceiptStatus as ReceiptStatusEnum;
+use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
+use app\common\enum\order\export\ExportStatus as ExportStatusEnum;
+use app\common\exception\BaseException;
+
+/**
+ * 服务层:订单导出Excel
+ * Class Export
+ * @package app\store\service\order
+ */
+class Export extends BaseService
+{
+    // 表格文件标题名称
+    private $title = '订单导出结果';
+
+    /**
+     * 执行订单导出excel
+     * @param array $param
+     * @return bool
+     * @throws BaseException
+     */
+    public function exportOrder(array $param)
+    {
+        // 根据条件查询订单列表
+        $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)
+    {
+        // 根据条件查询订单列表
+        $model = new OrderModel;
+        $orderList = $model->getListAll(OrderModel::LIST_TYPE_ALL, $param);
+        if ($orderList->isEmpty()) {
+            throwError('很抱歉,没有查询到订单数据');
+        }
+        return $orderList;
+    }
+
+    /**
+     * 输出并写入到excel文件
+     * @param array $columns 列名
+     * @param array $excelList 表格内容
+     * @return bool
+     * @throws BaseException
+     */
+    private function outputExcel(array $columns, array $excelList)
+    {
+        // 生成工作表
+        $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 = 'temp/' . $this->getStoreId() . '/';
+        // 保存到文件
+        try {
+            $writer = new Xlsx($spreadsheet);
+            $writer->save(public_path() . $filePath . $fileName);
+        } catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
+            throwError($e->getMessage());
+        }
+        return $filePath . $fileName;
+    }
+
+    // 记录导出记录
+    private function record(array $param, string $filePath)
+    {
+        // 生成记录数据
+        $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;
+        return $model->add($data);
+    }
+
+    /**
+     * 获取导出的记录列名集
+     * @param array $onlyFields
+     * @return array
+     */
+    private function getColumns(array $onlyFields)
+    {
+        return array_values(helper::pick($this->dictionary(), $onlyFields));
+    }
+
+    /**
+     * 订单记录字典
+     * @return string[]
+     */
+    private function dictionary()
+    {
+        return [
+            'order_id' => '订单ID',
+            'order_no' => '订单号',
+            'goods_detail' => '商品信息',
+            'total_price' => '商品总额',
+            'coupon_money' => '优惠券抵扣金额',
+            'points_money' => '积分抵扣金额',
+            'update_price' => '后台改价',
+            'express_price' => '运费金额',
+            'pay_price' => '订单实付款',
+            'pay_type' => '支付方式',
+            'create_time' => '下单时间',
+            'user_info' => '买家信息',
+            'buyer_remark' => '买家留言',
+            'delivery_type' => '配送方式',
+            'receipt_name' => '收货人',
+            'receipt_phone' => '联系电话',
+            'receipt_address' => '收货地址',
+            'express_company' => '物流公司',
+            'express_no' => '物流单号',
+            '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)
+    {
+        // 获取订单表格数据
+        $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)
+    {
+        // 表格内容
+        $dataArray = [];
+        foreach ($orderList as $order) {
+            $dataArray[] = [
+                'order_id' => $order['order_id'],
+                'order_no' => $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_type' => PayTypeEnum::data()[$order['pay_type']]['name'],
+                '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' => $this->filterValue($order['address']['name']),
+                'receipt_phone' => $this->filterValue($order['address']['phone']),
+                'receipt_address' => !empty($order['address']) ? OrderAddressModel::fullAddress($order['address']) : '',
+                'express_company' => !empty($order['express']) ? $order['express']['express_name'] : '',
+                'express_no' => $this->filterValue($order['express_no']),
+                '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 $order
+     * @return string
+     */
+    private function filterGoodsInfo($order)
+    {
+        $content = '';
+        foreach ($order['goods'] as $key => $goods) {
+            $content .= ($key + 1) . ".商品名称:{$goods['goods_name']}\n";
+            !empty($goods['goods_attr']) && $content .= " 商品规格:{$goods['goods_attr']}\n";
+            $content .= " 购买数量:{$goods['total_num']}\n";
+            $content .= " 商品总价:{$goods['total_price']}元\n\n";
+        }
+        return $content;
+    }
+
+    /**
+     * 表格值过滤
+     * @param $value
+     * @return string
+     */
+    private function filterValue($value)
+    {
+        return $value;
+        //return "\t" . $value . "\t";
+    }
+
+}