From 86899df0550abe65408b7bf861df706f99614e65 Mon Sep 17 00:00:00 2001 From: panliang <1163816051@qq.com> Date: Thu, 4 Dec 2025 19:34:32 +0800 Subject: [PATCH] =?UTF-8?q?admin=20PointLogController=20Excel=E5=AF=BC?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Admin/Controllers/OrderController.php | 53 +++++++++++++- app/Admin/Controllers/PointLogController.php | 73 +++++++++++++++++++- app/Enums/PointLogAction.php | 4 ++ composer.json | 1 + composer.lock | 73 ++++++++++++++++++-- 5 files changed, 196 insertions(+), 8 deletions(-) diff --git a/app/Admin/Controllers/OrderController.php b/app/Admin/Controllers/OrderController.php index 457dff06..3df94854 100644 --- a/app/Admin/Controllers/OrderController.php +++ b/app/Admin/Controllers/OrderController.php @@ -77,7 +77,9 @@ class OrderController extends AdminController '商品ID', '商品名称', '数量', - '价格', + '销售价格', + '会员价格', + '成本价', '积分', '金额', '待发货数量', @@ -88,9 +90,26 @@ class OrderController extends AdminController '订单状态', '下单时间', '是否换货', + '本次积分余额', + '首次办卡时间' ])); $query->lazyById()->each(function ($order) use ($writer) { + $pointBalance = '-'; + if ($order->point_discount_amount > 0) { + $pointLog = PointLog::query() + ->where('loggable_type', (new Order())->getMorphClass()) + ->where('loggable_id', $order->id) + ->where('action', PointLogAction::Consumption) + ->first(); + $pointBalance = bcdiv($pointLog->after_points, 100, 0); + } + $userVipTime = '-'; + $userVip = UserVip::where('user_id', $order->user_id)->where('status', UserVip::STATUS_SUCCESS)->orderBy('success_time', 'asc')->first(); + if ($userVip) { + $userVipTime = $userVip->success_time->format("Y-m-d H:i:s"); + } + foreach ($order->products as $product) { $writer->addRow( WriterEntityFactory::createRowFromArray([ @@ -98,6 +117,8 @@ class OrderController extends AdminController $product->name, $product->quantity, bcdiv($product->sell_price, '100', 2), + bcdiv($product->vip_price, '100', 2), + bcdiv($product->cost_price, '100', 2), bcdiv($product->point_discount_amount, '100', 2), bcdiv($product->total_amount, '100', 2), $product->remain_quantity, @@ -108,6 +129,8 @@ class OrderController extends AdminController $order->order_status_text, $order->created_at?->toDateTimeString(), $order->is_change ? '是' : '否', + $pointBalance, + $userVipTime, ]) ); } @@ -474,6 +497,10 @@ class OrderController extends AdminController $grid->column('vip_price', '会员价格')->display(function ($value) { return bcdiv($value, 100, 2); })->prepend('¥'); + $grid->column('cost_price', '成本价')->display(function ($value) { + return bcdiv($value, 100, 2); + })->prepend('¥'); + $grid->column('quantity'); $grid->column('vip_discount_amount', '会员折扣')->display(function ($value) { return bcdiv($value, 100, 2); @@ -706,21 +733,41 @@ class OrderController extends AdminController $writer->openToBrowser('发货单'.date('Ymd').'.xlsx'); $writer->addRow(WriterEntityFactory::createRowFromArray([ - '订单编号', '下单手机号', '商品编号', '商品名称', '数量', '姓名', '电话', '地址', '下单时间', '快递公司', '发货单号', '发货数量', + '订单编号', '下单手机号', '商品编号', '商品名称', '销售价格', '会员价格', '成本价', '下单数量', '剩余发货数量', '姓名', '电话', '地址', '下单时间', '快递公司', '发货单号', '发货数量', '本次积分余额', '首次办卡时间' ])); foreach (Order::with('products', 'user')->needShipping()->cursor() as $order) { + $pointBalance = '-'; + if ($order->point_discount_amount > 0) { + $pointLog = PointLog::query() + ->where('loggable_type', (new Order())->getMorphClass()) + ->where('loggable_id', $order->id) + ->where('action', PointLogAction::Consumption) + ->first(); + $pointBalance = bcdiv($pointLog->after_points, 100, 0); + } + $userVipTime = '-'; + $userVip = UserVip::where('user_id', $order->user_id)->where('status', UserVip::STATUS_SUCCESS)->orderBy('success_time', 'asc')->first(); + if ($userVip) { + $userVipTime = $userVip->success_time->format("Y-m-d H:i:s"); + } foreach ($order->products as $product) { if ($product->remain_quantity > 0) { $writer->addRow(WriterEntityFactory::createRowFromArray([ $order->sn, $order->user->phone, $product->sku_id, - $product->name.'数量:'.$product->remain_quantity, + $product->name, + bcdiv($product->sell_price, 100, 2), + bcdiv($product->vip_price, 100, 2), + bcdiv($product->cost_price, 100, 2), + $product->quantity, $product->remain_quantity, $order->consignee_name, $order->consignee_telephone, $order->consignee_zone.$order->consignee_address, $order->created_at->toDateTimeString(), + $pointBalance, + $userVipTime, ])); } } diff --git a/app/Admin/Controllers/PointLogController.php b/app/Admin/Controllers/PointLogController.php index 74bb058c..581e7bd3 100644 --- a/app/Admin/Controllers/PointLogController.php +++ b/app/Admin/Controllers/PointLogController.php @@ -5,7 +5,11 @@ namespace App\Admin\Controllers; use App\Admin\Repositories\PointLog as PointLogRepository; use App\Admin\Widgets\InfoBox; use App\Enums\PointLogAction; +use App\Models\Order; +use App\Models\OrderProduct; use App\Models\PointLog; +use App\Models\UserInfo; +use App\Models\UserVip; use Dcat\Admin\Admin; use Dcat\Admin\Grid; use Dcat\Admin\Http\Controllers\AdminController; @@ -32,11 +36,78 @@ class PointLogController extends AdminController $builder = PointLogRepository::with(['user', 'administrator']); return Grid::make($builder, function (Grid $grid) { + + $grid->export()->disableExportAll()->titles([ + 'id' => 'ID', + 'username' => '用户昵称', + 'user_id' => __('point-log.fields.user.phone'), + 'first_rechare_time' => '首次充值时间', + 'first_rechare_type' => '首次充值类型', + 'first_rechare_money' => '首次充值金额', + 'renew_rechare_count' => '续费次数', + 'renew_rechare_type' => '续费类型', + 'renew_rechare_latest_time' => '最近一次续费时间', + 'renew_rechare_money_total' => '续费金额合计', + 'action' => __('point-log.fields.action'), + 'change_points' => __('point-log.fields.change_points'), + 'before_points' => __('point-log.fields.before_points'), + 'after_points' => __('point-log.fields.after_points'), + 'goods_cost_price' => '商品成本价', + 'remark' => __('point-log.fields.remark'), + 'administrator' => '操作人', + 'created_at' => __('admin.created_at'), + ])->rows(function ($rows) { + foreach ($rows as &$row) { + $userInfo = UserInfo::where('user_id', $row['user_id'])->first(); + $firstVip = UserVip::where('user_id', $row['user_id'])->where('status', UserVip::STATUS_SUCCESS)->orderBy('success_time', 'asc')->first(); + $vipCount = UserVip::where('user_id', $row['user_id'])->where('status', UserVip::STATUS_SUCCESS)->count(); + + $row['user_id'] = data_get($row, 'user.phone'); + $row['username'] = data_get($userInfo, 'nickname'); + + $row['first_rechare_time'] = $firstVip ? $firstVip->success_time->format('Y-m-d H:i:s') : ''; + $row['first_rechare_type'] = data_get($firstVip, 'name'); + $row['first_rechare_money'] = data_get($firstVip, 'price'); + + $row['renew_rechare_count'] = ''; + $row['renew_rechare_type'] = ''; + $row['renew_rechare_latest_time'] = ''; + $row['renew_rechare_money_total'] = ''; + if ($vipCount > 1) { + $row['renew_rechare_count'] = $vipCount - 1; + $latestVip = UserVip::where('user_id', $row['user_id'])->where('status', UserVip::STATUS_SUCCESS)->orderBy('success_time', 'desc')->first(); + $row['renew_rechare_type'] = data_get($latestVip, 'name'); + $row['renew_rechare_latest_time'] = data_get($latestVip, 'success_time'); + + $sum = UserVip::where('user_id', $row['user_id'])->where('status', UserVip::STATUS_SUCCESS)->where('id', '!=', $firstVip->id)->sum('price'); + $row['renew_rechare_money_total'] = $sum; + } + + $row['action'] = PointLogAction::getLabel(data_get($row, 'action')); + $row['change_points'] = bcdiv(data_get($row, 'change_points'), 100, 2); + $row['before_points'] = bcdiv(data_get($row, 'before_points'), 100, 2); + $row['after_points'] = bcdiv(data_get($row, 'after_points'), 100, 2); + $row['remark'] = data_get($row, 'remark'); + + // 商品成本价 + $row['goods_cost_price'] = ''; + if ($row['loggable_type'] == (new Order)->getMorphClass()) { + $costPrice = OrderProduct::where('order_id', $row['loggable_id'])->sum('cost_price'); + $row['goods_cost_price'] = bcdiv($costPrice, 100, 2); + } + + $row['administrator'] = data_get($row, 'administrator.name'); + $row['created_at'] = data_get($row, 'created_at'); + } + + return $rows; + }); + $grid->model()->orderBy('id', 'desc'); $grid->column('id')->sortable(); $grid->column('user.phone')->copyable(); - $grid->column('action')->display(fn ($action) => $action->label())->label();; + $grid->column('action')->display(fn ($action) => $action->label())->label(); $grid->column('change_points')->display(function ($value) { return bcdiv($value, 100, 2); }); diff --git a/app/Enums/PointLogAction.php b/app/Enums/PointLogAction.php index 1885b054..9f1cd99d 100644 --- a/app/Enums/PointLogAction.php +++ b/app/Enums/PointLogAction.php @@ -24,4 +24,8 @@ enum PointLogAction: int { self::Refund->value => '退还', ]; } + + public static function getLabel($value) { + return data_get(static::options(), $value, ""); + } } diff --git a/composer.json b/composer.json index 71ab3513..4d2d6bc7 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "alipaysdk/easysdk": "^2.2", "alphasnow/aliyun-oss-laravel": "^3.0", "box/spout": "^3.3", + "dcat/easy-excel": "^1.1", "dcat/laravel-admin": "2.1.5-beta", "fruitcake/laravel-cors": "^2.0", "gregwar/captcha": "^1.1", diff --git a/composer.lock b/composer.lock index 72554070..6ba6d260 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5ea856539b7c9cb2093859052437846e", + "content-hash": "c446666cf2eb04902a98f7b967974898", "packages": [ { "name": "adbario/php-dot-notation", @@ -1107,6 +1107,71 @@ }, "time": "2020-10-02T16:03:48+00:00" }, + { + "name": "dcat/easy-excel", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/jqhph/easy-excel.git", + "reference": "20ee838b07f1f5d9c075b84e6f4807cbb21c44b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jqhph/easy-excel/zipball/20ee838b07f1f5d9c075b84e6f4807cbb21c44b0", + "reference": "20ee838b07f1f5d9c075b84e6f4807cbb21c44b0", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "box/spout": "~3", + "league/flysystem": "~1|~2|~3", + "php": ">=7.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2", + "phpunit/phpunit": "~7|~8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dcat\\EasyExcel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "jqh", + "email": "841324345@qq.com" + } + ], + "description": "使用简单实用的语义化接口快速读写Excel文件", + "homepage": "https://github.com/jqhph/easy-excel", + "keywords": [ + "box spout", + "csv", + "easy excel", + "excel", + "ods", + "office", + "read", + "spreadsheet", + "stream", + "xlsx" + ], + "support": { + "issues": "https://github.com/jqhph/easy-excel/issues", + "source": "https://github.com/jqhph/easy-excel/tree/1.1.0" + }, + "time": "2022-03-03T03:04:13+00:00" + }, { "name": "dcat/laravel-admin", "version": "2.1.5-beta", @@ -12085,12 +12150,12 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.0" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" }