| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- <?php
- namespace App\Module\Transfer\AdminControllers\Helper;
- use App\Module\Transfer\Models\TransferOrder;
- use App\Module\Transfer\Enums\TransferStatus;
- use App\Module\Transfer\Enums\TransferType;
- use Dcat\Admin\Grid;
- use Dcat\Admin\Show;
- use Dcat\Admin\Form;
- /**
- * 划转订单管理辅助类
- */
- class TransferOrderHelper
- {
- /**
- * 配置Grid表格
- */
- public static function grid(Grid $grid): void
- {
- $grid->column('id', 'ID')->sortable();
-
- $grid->column('transfer_app.title', '应用名称')->limit(15);
-
- $grid->column('out_order_id', '外部订单ID')->copyable();
-
- $grid->column('user_id', '用户ID')->link(function ($value) {
- return admin_url("users/{$value}");
- });
-
- $grid->column('out_user_id', '外部用户ID')->limit(15);
-
- $grid->column('type', '类型')->display(function ($value) {
- $typeMap = [
- 1 => '转入',
- 2 => '转出',
- ];
- $labelMap = [
- 1 => 'success',
- 2 => 'warning',
- ];
- // 处理枚举对象
- $typeValue = is_object($value) ? $value->value : $value;
- $text = $typeMap[$typeValue] ?? '未知';
- $label = $labelMap[$typeValue] ?? 'default';
- return "<span class=\"label label-{$label}\">{$text}</span>";
- });
- $grid->column('status', '状态')->display(function ($value) {
- $statusMap = [
- 1 => '已创建',
- 20 => '处理中',
- 30 => '已回调',
- 100 => '已完成',
- -1 => '失败',
- ];
- $labelMap = [
- 1 => 'info',
- 20 => 'warning',
- 30 => 'primary',
- 100 => 'success',
- -1 => 'danger',
- ];
- // 处理枚举对象
- $statusValue = is_object($value) ? $value->value : $value;
- $text = $statusMap[$statusValue] ?? '未知';
- $label = $labelMap[$statusValue] ?? 'default';
- return "<span class=\"label label-{$label}\">{$text}</span>";
- });
-
- $grid->column('out_amount', '外部金额')->display(function ($value) {
- return number_format($value, 4);
- });
-
- $grid->column('amount', '内部金额')->display(function ($value) {
- return number_format($value, 4);
- });
- // 手续费信息
- $grid->column('fee_info', '手续费信息')->display(function () {
- if ($this->fee_amount > 0) {
- $feeRate = number_format($this->fee_rate * 100, 2) . '%';
- $feeAmount = number_format($this->fee_amount, 4);
- $actualAmount = number_format($this->actual_amount, 4);
- return "费率: {$feeRate}<br>手续费: {$feeAmount}<br>实际: {$actualAmount}";
- }
- return '无手续费';
- });
- $grid->column('exchange_rate', '汇率')->display(function ($value) {
- return number_format($value, 4);
- });
-
- $grid->column('created_at', '创建时间')->sortable();
- $grid->column('completed_at', '完成时间');
-
- // 处理时长
- $grid->column('duration', '处理时长')->display(function () {
- if ($this->completed_at && $this->created_at) {
- // 确保计算正确的时间差(完成时间 - 创建时间)
- $seconds = $this->completed_at->getTimestamp() - $this->created_at->getTimestamp();
- // 如果时间差为负数或0,显示为0秒
- if ($seconds <= 0) {
- return '0秒';
- }
- if ($seconds < 60) {
- return $seconds . '秒';
- } elseif ($seconds < 3600) {
- return round($seconds / 60, 1) . '分钟';
- } else {
- return round($seconds / 3600, 1) . '小时';
- }
- }
- return '-';
- });
- // 筛选器
- $grid->filter(function (Grid\Filter $filter) {
- $filter->equal('transfer_app_id', '应用')->select(
- \App\Module\Transfer\Models\TransferApp::pluck('title', 'id')
- );
-
- $filter->equal('type', '类型')->select([
- 1 => '转入',
- 2 => '转出',
- ]);
-
- $filter->equal('status', '状态')->select([
- 1 => '已创建',
- 20 => '处理中',
- 30 => '已回调',
- 100 => '已完成',
- -1 => '失败',
- ]);
-
- $filter->equal('user_id', '用户ID');
- $filter->like('out_order_id', '外部订单ID');
- $filter->like('out_user_id', '外部用户ID');
-
- $filter->between('amount', '内部金额');
- $filter->between('created_at', '创建时间')->datetime();
- });
- // 操作按钮
- $grid->actions(function (Grid\Displayers\Actions $actions) {
- $actions->disableDelete(); // 禁用删除
- $actions->disableEdit(); // 禁用编辑
-
- // 重试按钮
- if ($this->canRetry()) {
- $actions->append('<a href="javascript:void(0)" class="btn btn-xs btn-outline-warning retry-order" data-id="'.$this->id.'">重试</a>');
- }
-
- // 手动完成按钮(仅转出订单)
- if ($this->isTransferOut() && !$this->isFinalStatus()) {
- $actions->append('<a href="javascript:void(0)" class="btn btn-xs btn-outline-success manual-complete" data-id="'.$this->id.'">手动完成</a>');
- }
- });
- // 批量操作
- $grid->batchActions(function (Grid\Tools\BatchActions $batch) {
- $batch->add(new \App\Module\Transfer\AdminControllers\Tools\RetryOrderTool());
- });
- // 工具栏
- $grid->tools(function (Grid\Tools $tools) {
- $tools->append('<a href="javascript:void(0)" class="btn btn-sm btn-primary" onclick="showStats()">统计信息</a>');
- $tools->append(new \App\Module\Transfer\AdminControllers\Tools\ExportOrderTool());
- });
- // 默认排序
- $grid->model()->orderBy('created_at', 'desc');
- }
- /**
- * 配置Show详情
- */
- public static function show(Show $show): void
- {
- $show->field('id', 'ID');
-
- $show->divider();
- $show->field('transfer_app.title', '应用名称');
- $show->field('out_order_id', '外部订单ID');
- $show->field('out_user_id', '外部用户ID');
- $show->field('user_id', '内部用户ID');
-
- $show->field('type', '订单类型')->using([
- 1 => '转入',
- 2 => '转出',
- ]);
-
- $show->field('status', '订单状态')->using([
- 1 => '已创建',
- 20 => '处理中',
- 30 => '已回调',
- 100 => '已完成',
- -1 => '失败',
- ]);
-
- $show->divider();
- $show->field('out_amount', '外部金额')->as(function ($value) {
- return number_format($value, 10);
- });
- $show->field('amount', '内部金额')->as(function ($value) {
- return number_format($value, 10);
- });
- $show->field('exchange_rate', '使用汇率')->as(function ($value) {
- return number_format($value, 4);
- });
- // 手续费信息
- $show->field('fee_rate', '手续费率')->as(function ($value) {
- return number_format($value * 100, 2) . '%';
- });
- $show->field('fee_amount', '手续费金额')->as(function ($value) {
- return number_format($value, 4);
- });
- $show->field('actual_amount', '实际到账金额')->as(function ($value) {
- return number_format($value, 4);
- });
- $show->field('has_fee', '是否收取手续费')->as(function () {
- return $this->fee_amount > 0 ? '是' : '否';
- });
-
- $show->divider();
- $show->field('currency_id', '货币类型')->using([
- 1 => '金币',
- 2 => '钻石',
- 3 => '人民币',
- 4 => '美元',
- ]);
- $show->field('fund_id', '资金账户类型');
- $show->divider();
- $show->field('callback_data', '回调数据')->json();
- $show->divider();
- $show->field('error_message', '错误信息');
- $show->field('remark', '备注信息');
- $show->divider();
- $show->field('created_at', '创建时间');
- $show->field('processed_at', '处理时间');
- $show->field('callback_at', '回调时间');
- $show->field('completed_at', '完成时间');
- $show->field('updated_at', '更新时间');
-
- // 处理时长
- $show->field('processing_duration', '处理时长')->as(function () {
- if ($this->completed_at && $this->created_at) {
- return $this->completed_at->diffForHumans($this->created_at, true);
- }
- return '未完成';
- });
- }
- /**
- * 获取状态统计
- */
- public static function getStatusStats(): array
- {
- $stats = TransferOrder::selectRaw('status, COUNT(*) as count, SUM(amount) as amount')
- ->groupBy('status')
- ->get()
- ->keyBy('status');
- $result = [];
- foreach (TransferStatus::cases() as $status) {
- $stat = $stats->get($status->value);
- $result[] = [
- 'status' => $status->getDescription(),
- 'count' => $stat ? number_format($stat->count) : 0,
- 'amount' => $stat ? number_format($stat->amount, 2) : '0.00',
- 'color' => $status->getColor(),
- ];
- }
- return $result;
- }
- /**
- * 获取类型统计
- */
- public static function getTypeStats(): array
- {
- $stats = TransferOrder::selectRaw('type, COUNT(*) as count, SUM(amount) as amount')
- ->groupBy('type')
- ->get()
- ->keyBy('type');
- $result = [];
- foreach (TransferType::cases() as $type) {
- $stat = $stats->get($type->value);
- $result[] = [
- 'type' => $type->getDescription(),
- 'count' => $stat ? number_format($stat->count) : 0,
- 'amount' => $stat ? number_format($stat->amount, 2) : '0.00',
- 'color' => $type->getColor(),
- ];
- }
- return $result;
- }
- /**
- * 获取今日统计
- */
- public static function getTodayStats(): array
- {
- $today = now()->startOfDay();
- $total = TransferOrder::where('created_at', '>=', $today)->count();
- $completed = TransferOrder::where('created_at', '>=', $today)
- ->where('status', TransferStatus::COMPLETED)->count();
- $failed = TransferOrder::where('created_at', '>=', $today)
- ->where('status', TransferStatus::FAILED)->count();
- $amount = TransferOrder::where('created_at', '>=', $today)->sum('amount');
- $feeAmount = TransferOrder::where('created_at', '>=', $today)->sum('fee_amount');
- return [
- 'total' => number_format($total),
- 'completed' => number_format($completed),
- 'failed' => number_format($failed),
- 'success_rate' => $total > 0 ? number_format($completed / $total * 100, 1) . '%' : '0%',
- 'amount' => number_format($amount, 2),
- 'fee_amount' => number_format($feeAmount, 2),
- ];
- }
- /**
- * 获取手续费统计
- */
- public static function getFeeStats(): array
- {
- $stats = TransferOrder::selectRaw('
- COUNT(*) as total_orders,
- SUM(fee_amount) as total_fee,
- AVG(fee_rate) as avg_fee_rate,
- SUM(CASE WHEN type = 1 THEN fee_amount ELSE 0 END) as in_fee,
- SUM(CASE WHEN type = 2 THEN fee_amount ELSE 0 END) as out_fee,
- COUNT(CASE WHEN type = 1 THEN 1 END) as in_orders,
- COUNT(CASE WHEN type = 2 THEN 1 END) as out_orders
- ')
- ->where('status', TransferStatus::COMPLETED)
- ->where('fee_amount', '>', 0)
- ->first();
- return [
- 'total_orders' => number_format($stats->total_orders ?? 0),
- 'total_fee' => number_format($stats->total_fee ?? 0, 4),
- 'avg_fee_rate' => number_format(($stats->avg_fee_rate ?? 0) * 100, 2) . '%',
- 'in_fee' => number_format($stats->in_fee ?? 0, 4),
- 'out_fee' => number_format($stats->out_fee ?? 0, 4),
- 'in_orders' => number_format($stats->in_orders ?? 0),
- 'out_orders' => number_format($stats->out_orders ?? 0),
- ];
- }
- }
|