TransferAppHelper.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <?php
  2. namespace App\Module\Transfer\AdminControllers\Helper;
  3. use App\Module\Transfer\Models\TransferApp;
  4. use App\Module\Transfer\Enums\TransferStatus;
  5. use Dcat\Admin\Grid;
  6. use Dcat\Admin\Show;
  7. use Dcat\Admin\Form;
  8. /**
  9. * 划转应用管理辅助类
  10. */
  11. class TransferAppHelper
  12. {
  13. /**
  14. * 配置Grid表格
  15. */
  16. public static function grid(Grid $grid): void
  17. {
  18. $grid->column('id', 'ID')->sortable();
  19. $grid->column('keyname', '应用标识')->copyable();
  20. $grid->column('title', '应用名称')->limit(20);
  21. $grid->column('description', '描述')->limit(30);
  22. $grid->column('out_id2', '开放接口ID');
  23. $grid->column('out_id3', '三方平台ID');
  24. $grid->column('currency_id', '货币类型')->using([
  25. 1 => '金币',
  26. 2 => '钻石',
  27. 3 => '人民币',
  28. 4 => '美元',
  29. ])->label([
  30. 1 => 'warning',
  31. 2 => 'success',
  32. 3 => 'danger',
  33. 4 => 'primary',
  34. ]);
  35. $grid->column('fund_id', '资金账户');
  36. $grid->column('exchange_rate', '汇率')->display(function ($value) {
  37. return number_format($value, 4);
  38. });
  39. // 手续费配置
  40. $grid->column('fee_config', '手续费配置')->display(function () {
  41. $feeInfo = [];
  42. if ($this->fee_in_rate > 0 || $this->fee_in_min > 0) {
  43. $feeInfo[] = "转入: " . number_format($this->fee_in_rate * 100, 2) . "%";
  44. }
  45. if ($this->fee_out_rate > 0 || $this->fee_out_min > 0) {
  46. $feeInfo[] = "转出: " . number_format($this->fee_out_rate * 100, 2) . "%";
  47. }
  48. return empty($feeInfo) ? '无手续费' : implode('<br>', $feeInfo);
  49. });
  50. $grid->column('is_enabled', '启用状态')->switch();
  51. $grid->column('allow_transfer_in', '允许转入')->switch();
  52. $grid->column('allow_transfer_out', '允许转出')->switch();
  53. // 运行模式
  54. $grid->column('mode', '运行模式')->display(function () {
  55. $isEmpty = empty($this->order_callback_url) &&
  56. empty($this->order_in_info_url) &&
  57. empty($this->order_out_create_url) &&
  58. empty($this->order_out_info_url);
  59. return $isEmpty ? '农场内部' : '外部API';
  60. })->label([
  61. '农场内部' => 'success',
  62. '外部API' => 'primary',
  63. ]);
  64. // 支持功能
  65. $grid->column('features', '支持功能')->display(function () {
  66. $features = [];
  67. if ($this->allow_transfer_in && $this->fund_in_uid > 0) $features[] = '转入';
  68. if ($this->allow_transfer_out && $this->fund_to_uid > 0) $features[] = '转出';
  69. if (!empty($this->order_callback_url)) $features[] = '回调';
  70. return implode(', ', $features);
  71. });
  72. $grid->column('created_at', '创建时间')->sortable();
  73. $grid->column('updated_at', '更新时间')->sortable();
  74. // 筛选器
  75. $grid->filter(function (Grid\Filter $filter) {
  76. $filter->like('keyname', '应用标识');
  77. $filter->like('title', '应用名称');
  78. $filter->equal('currency_id', '货币类型')->select([
  79. 1 => '金币',
  80. 2 => '钻石',
  81. 3 => '人民币',
  82. 4 => '美元',
  83. ]);
  84. $filter->equal('is_enabled', '启用状态')->select([
  85. 1 => '启用',
  86. 0 => '禁用',
  87. ]);
  88. $filter->equal('allow_transfer_in', '允许转入')->select([
  89. 1 => '允许',
  90. 0 => '禁止',
  91. ]);
  92. $filter->equal('allow_transfer_out', '允许转出')->select([
  93. 1 => '允许',
  94. 0 => '禁止',
  95. ]);
  96. });
  97. // 操作按钮
  98. $grid->actions(function (Grid\Displayers\Actions $actions) {
  99. $actions->disableDelete(); // 禁用删除
  100. // 添加测试连接按钮
  101. $isEmpty = empty($this->order_callback_url) &&
  102. empty($this->order_in_info_url) &&
  103. empty($this->order_out_create_url) &&
  104. empty($this->order_out_info_url);
  105. if (!$isEmpty) {
  106. $actions->append('<a href="javascript:void(0)" class="btn btn-xs btn-outline-info test-connection" data-id="'.$this->id.'">测试连接</a>');
  107. }
  108. });
  109. // 批量操作
  110. $grid->batchActions(function (Grid\Tools\BatchActions $batch) {
  111. $batch->add(new \App\Module\Transfer\AdminControllers\Tools\EnableAppTool());
  112. $batch->add(new \App\Module\Transfer\AdminControllers\Tools\DisableAppTool());
  113. });
  114. // 工具栏
  115. $grid->tools(function (Grid\Tools $tools) {
  116. $tools->append('<a href="javascript:void(0)" class="btn btn-sm btn-success" onclick="refreshStats()">刷新统计</a>');
  117. });
  118. }
  119. /**
  120. * 配置Show详情
  121. */
  122. public static function show(Show $show): void
  123. {
  124. $show->field('id', 'ID');
  125. $show->field('keyname', '应用标识');
  126. $show->field('title', '应用名称');
  127. $show->field('description', '描述');
  128. $show->divider();
  129. $show->field('out_id2', '开放接口ID');
  130. $show->field('out_id3', '三方平台ID');
  131. $show->divider();
  132. $show->field('currency_id', '货币类型')->using([
  133. 1 => '金币',
  134. 2 => '钻石',
  135. 3 => '人民币',
  136. 4 => '美元',
  137. ]);
  138. $show->field('fund_id', '资金账户类型');
  139. $show->field('fund_to_uid', '转入目标账户');
  140. $show->field('fund_in_uid', '转入来源账户');
  141. $show->field('exchange_rate', '汇率')->as(function ($value) {
  142. return number_format($value, 4);
  143. });
  144. $show->divider();
  145. $show->field('fee_in_rate', '转入手续费率')->as(function ($value) {
  146. return number_format($value * 100, 2) . '%';
  147. });
  148. $show->field('fee_in_min', '转入最低手续费')->as(function ($value) {
  149. return number_format($value, 4);
  150. });
  151. $show->field('fee_in_max', '转入最高手续费')->as(function ($value) {
  152. return $value > 0 ? number_format($value, 4) : '不限制';
  153. });
  154. $show->field('fee_out_rate', '转出手续费率')->as(function ($value) {
  155. return number_format($value * 100, 2) . '%';
  156. });
  157. $show->field('fee_out_min', '转出最低手续费')->as(function ($value) {
  158. return number_format($value, 4);
  159. });
  160. $show->field('fee_out_max', '转出最高手续费')->as(function ($value) {
  161. return $value > 0 ? number_format($value, 4) : '不限制';
  162. });
  163. $show->field('fee_account_uid', '手续费收取账户')->as(function ($value) {
  164. return $value > 0 ? "UID: {$value}" : '默认账户(UID: 1)';
  165. });
  166. $show->divider();
  167. $show->field('order_callback_url', '回调通知URL');
  168. $show->field('order_in_info_url', '转入查询URL');
  169. $show->field('order_out_create_url', '转出创建URL');
  170. $show->field('order_out_info_url', '转出查询URL');
  171. $show->divider();
  172. $show->field('is_enabled', '启用状态')->using([1 => '启用', 0 => '禁用']);
  173. $show->field('allow_transfer_in', '允许转入')->using([1 => '允许', 0 => '禁止']);
  174. $show->field('allow_transfer_out', '允许转出')->using([1 => '允许', 0 => '禁止']);
  175. $show->field('mode', '运行模式')->as(function () {
  176. $isEmpty = empty($this->order_callback_url) &&
  177. empty($this->order_in_info_url) &&
  178. empty($this->order_out_create_url) &&
  179. empty($this->order_out_info_url);
  180. return $isEmpty ? '农场内部模式' : '外部API模式';
  181. });
  182. $show->divider();
  183. $show->field('created_at', '创建时间');
  184. $show->field('updated_at', '更新时间');
  185. // 关联订单统计
  186. $show->divider();
  187. $show->field('orders_count', '总订单数')->as(function () {
  188. return \App\Module\Transfer\Models\TransferOrder::where('transfer_app_id', $this->id)->count();
  189. });
  190. $show->field('completed_orders', '成功订单')->as(function () {
  191. return \App\Module\Transfer\Models\TransferOrder::where('transfer_app_id', $this->id)
  192. ->where('status', TransferStatus::COMPLETED)->count();
  193. });
  194. $show->field('total_amount', '总金额')->as(function () {
  195. $amount = \App\Module\Transfer\Models\TransferOrder::where('transfer_app_id', $this->id)->sum('amount');
  196. return number_format($amount, 2);
  197. });
  198. $show->field('total_fee', '总手续费')->as(function () {
  199. $fee = \App\Module\Transfer\Models\TransferOrder::where('transfer_app_id', $this->id)->sum('fee_amount');
  200. return number_format($fee, 4);
  201. });
  202. }
  203. /**
  204. * 配置Form表单
  205. */
  206. public static function form(Form $form): void
  207. {
  208. $form->tab('基本信息', function (Form $form) {
  209. $form->text('keyname', '应用标识')
  210. ->required()
  211. ->creationRules('required|string|max:50|unique:' . (new TransferApp)->getTable() . ',keyname')
  212. ->updateRules('required|string|max:50|unique:' . (new TransferApp)->getTable() . ',keyname,{{id}}')
  213. ->help('唯一标识符,只能包含字母、数字、下划线');
  214. $form->text('title', '应用名称')
  215. ->required()
  216. ->rules('required|string|max:100');
  217. $form->textarea('description', '应用描述')
  218. ->rows(3)
  219. ->help('应用的详细描述信息');
  220. });
  221. $form->tab('外部应用配置', function (Form $form) {
  222. $form->number('out_id2', '开放接口ID')
  223. ->min(1)
  224. ->help('开放接口应用ID,用于API对接');
  225. $form->number('out_id3', '三方平台ID')
  226. ->min(1)
  227. ->help('第三方平台应用ID,用于平台集成');
  228. });
  229. $form->tab('资金配置', function (Form $form) {
  230. $form->select('currency_id', '货币类型')
  231. ->options([
  232. 1 => '金币',
  233. 2 => '钻石',
  234. 3 => '人民币',
  235. 4 => '美元',
  236. ])
  237. ->required()
  238. ->help('选择使用的货币类型');
  239. $form->number('fund_id', '资金账户类型')
  240. ->required()
  241. ->min(1)
  242. ->help('关联的资金账户类型ID');
  243. $form->number('fund_to_uid', '转入目标账户')
  244. ->min(1)
  245. ->help('转入操作的目标账户UID');
  246. $form->number('fund_in_uid', '转入来源账户')
  247. ->min(1)
  248. ->help('转入操作的来源账户UID');
  249. $form->decimal('exchange_rate', '汇率')
  250. ->required()
  251. ->default(1.0000)
  252. ->help('汇率比例,外部应用金额:业务金额');
  253. });
  254. $form->tab('手续费配置', function (Form $form) {
  255. $form->divider('转入手续费设置');
  256. $form->decimal('fee_in_rate', '转入手续费率')
  257. ->default(0.0000)
  258. ->help('转入手续费率,范围0-1,例如0.0050表示0.5%');
  259. $form->decimal('fee_in_min', '转入最低手续费')
  260. ->default(0.0000)
  261. ->help('转入最低手续费金额,0表示无最低限制');
  262. $form->decimal('fee_in_max', '转入最高手续费')
  263. ->default(0.0000)
  264. ->help('转入最高手续费金额,0表示无最高限制');
  265. $form->divider('转出手续费设置');
  266. $form->decimal('fee_out_rate', '转出手续费率')
  267. ->default(0.0000)
  268. ->help('转出手续费率,范围0-1,例如0.0100表示1.0%');
  269. $form->decimal('fee_out_min', '转出最低手续费')
  270. ->default(0.0000)
  271. ->help('转出最低手续费金额,0表示无最低限制');
  272. $form->decimal('fee_out_max', '转出最高手续费')
  273. ->default(0.0000)
  274. ->help('转出最高手续费金额,0表示无最高限制');
  275. $form->divider('手续费账户设置');
  276. $form->number('fee_account_uid', '手续费收取账户')
  277. ->default(1)
  278. ->help('手续费收取的账户UID,默认为1');
  279. $form->display('fee_note', '说明')
  280. ->with(function () {
  281. return '手续费将从转账金额中扣除,转入时用户收到扣除手续费后的金额,转出时从用户账户额外扣除手续费';
  282. });
  283. });
  284. $form->tab('API配置', function (Form $form) {
  285. $form->url('order_callback_url', '回调通知URL')
  286. ->help('结果通知API地址,为空则不发送通知');
  287. $form->url('order_in_info_url', '转入查询URL')
  288. ->help('转入订单查询API地址,为空则不查询');
  289. $form->url('order_out_create_url', '转出创建URL')
  290. ->help('转出订单创建API地址,为空则不创建');
  291. $form->url('order_out_info_url', '转出查询URL')
  292. ->help('转出订单查询API地址,为空则不查询');
  293. $form->display('api_note', '说明')
  294. ->with(function () {
  295. return '如果所有API地址都为空,系统将运行在农场内部模式';
  296. });
  297. });
  298. $form->tab('状态设置', function (Form $form) {
  299. $form->switch('is_enabled', '启用状态')
  300. ->default(1)
  301. ->help('是否启用该应用');
  302. $form->switch('allow_transfer_in', '允许转入')
  303. ->default(1)
  304. ->help('是否允许转入操作');
  305. $form->switch('allow_transfer_out', '允许转出')
  306. ->default(1)
  307. ->help('是否允许转出操作');
  308. });
  309. // 保存前验证
  310. $form->saving(function (Form $form) {
  311. // 验证应用标识符格式
  312. if (!preg_match('/^[a-zA-Z0-9_]+$/', $form->keyname)) {
  313. return $form->response()->error('应用标识符格式无效');
  314. }
  315. // 验证汇率
  316. if ($form->exchange_rate <= 0) {
  317. return $form->response()->error('汇率必须大于0');
  318. }
  319. // 验证手续费率
  320. if ($form->fee_in_rate < 0 || $form->fee_in_rate > 1) {
  321. return $form->response()->error('转入手续费率必须在0-1之间');
  322. }
  323. if ($form->fee_out_rate < 0 || $form->fee_out_rate > 1) {
  324. return $form->response()->error('转出手续费率必须在0-1之间');
  325. }
  326. // 验证最低和最高手续费的关系
  327. if ($form->fee_in_max > 0 && $form->fee_in_min > $form->fee_in_max) {
  328. return $form->response()->error('转入最低手续费不能大于最高手续费');
  329. }
  330. if ($form->fee_out_max > 0 && $form->fee_out_min > $form->fee_out_max) {
  331. return $form->response()->error('转出最低手续费不能大于最高手续费');
  332. }
  333. // 验证手续费账户
  334. if ($form->fee_account_uid < 1) {
  335. return $form->response()->error('手续费收取账户UID必须大于0');
  336. }
  337. });
  338. }
  339. }