RechargeBonusAdminService.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. <?php
  2. namespace App\Services;
  3. use App\Models\RechargeChannel;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Validator;
  6. use Illuminate\Validation\ValidationException;
  7. final class RechargeBonusAdminService
  8. {
  9. private function ready(): void
  10. {
  11. if (!RechargeBonusService::available()) throw ValidationException::withMessages(['config' => '充值赠送配置未初始化,请先完成系统更新']);
  12. }
  13. private function channel($type): string
  14. {
  15. Validator::make(['channel_type' => $type], ['channel_type' => ['required', 'string', 'max:100']])->validate();
  16. if (!RechargeChannel::where('data_type', 1)->where('type', $type)->exists()) throw ValidationException::withMessages(['channel_type' => '充值方式不存在']);
  17. return $type;
  18. }
  19. private function texts(array $texts): array
  20. {
  21. $rules = []; $messages = [];
  22. foreach (['zh' => '中文', 'en' => '英文', 'vi' => '越南文'] as $lang => $label) {
  23. $rules[$lang] = ['required', 'array:text']; $rules[$lang . '.text'] = ['required', 'string', 'max:100'];
  24. $messages[$lang . '.required'] = $label . '角标文字不能为空'; $messages[$lang . '.text.required'] = $label . '角标文字不能为空';
  25. }
  26. $result = Validator::make($texts, $rules, $messages)->validate();
  27. foreach ($result as $lang => &$text) {
  28. if (preg_replace('/[\s\p{Z}\x{200B}\x{FEFF}]+/u', '', $text['text']) === '') throw ValidationException::withMessages(['translations.' . $lang . '.text' => '角标文字不能为空']);
  29. $text['text'] = trim($text['text']);
  30. }
  31. unset($text);
  32. return $result;
  33. }
  34. public function listing(): array
  35. {
  36. $this->ready(); $rules = DB::table('recharge_bonuses')->get()->keyBy('channel_type'); $rows = [];
  37. foreach (RechargeChannel::where('data_type', 1)->orderBy('sort')->orderBy('id')->get() as $channel) {
  38. if (isset($rows[$channel->type])) continue;
  39. $rule = $rules[$channel->type] ?? null;
  40. $rows[$channel->type] = ['channel_type' => $channel->type, 'channel_name' => $channel->name,
  41. 'bonus_percent' => RechargeBonusService::percent($rule->bonus_percent ?? '0'), 'enabled' => (int)($rule->enabled ?? 0),
  42. 'translations' => $rule ? json_decode($rule->translations, true) : ['zh' => ['text' => ''], 'en' => ['text' => ''], 'vi' => ['text' => '']]];
  43. }
  44. return ['total' => count($rows), 'data' => array_values($rows)];
  45. }
  46. public function save(array $input): array
  47. {
  48. $this->ready();
  49. $data = Validator::make($input, ['channel_type' => ['required', 'string'], 'bonus_percent' => ['required', 'numeric', 'between:0,100', 'regex:/^\d+(\.\d{1,2})?$/'],
  50. 'enabled' => ['required', 'integer', 'in:0,1'], 'translations' => ['required', 'array:zh,en,vi']])->validate();
  51. $this->channel($data['channel_type']); $data['translations'] = $this->texts($data['translations']);
  52. return DB::transaction(function () use ($data) {
  53. $before = DB::table('recharge_bonuses')->where('channel_type', $data['channel_type'])->lockForUpdate()->first();
  54. $now = RechargeBonusService::now();
  55. DB::table('recharge_bonuses')->updateOrInsert(['channel_type' => $data['channel_type']], [
  56. 'bonus_percent' => bcadd((string)$data['bonus_percent'], '0', 2), 'enabled' => $data['enabled'],
  57. 'translations' => json_encode($data['translations'], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
  58. 'created_at' => $before->created_at ?? $now, 'updated_at' => $now]);
  59. OperationAuditService::record('recharge_bonus', null, 'save', (array)$before, $data);
  60. return $data;
  61. });
  62. }
  63. public function status(array $input): array
  64. {
  65. $this->ready(); $data = Validator::make($input, ['channel_type' => ['required', 'string'], 'enabled' => ['required', 'integer', 'in:0,1']])->validate();
  66. $this->channel($data['channel_type']);
  67. return DB::transaction(function () use ($data) {
  68. $row = DB::table('recharge_bonuses')->where('channel_type', $data['channel_type'])->lockForUpdate()->first();
  69. if (!$row) throw ValidationException::withMessages(['channel_type' => '请先保存该充值方式的赠送配置']);
  70. if ($data['enabled']) $this->texts(json_decode($row->translations, true));
  71. DB::table('recharge_bonuses')->where('channel_type', $data['channel_type'])->update(['enabled' => $data['enabled'], 'updated_at' => RechargeBonusService::now()]);
  72. OperationAuditService::record('recharge_bonus', null, 'status', (array)$row, $data);
  73. return $data;
  74. });
  75. }
  76. }