mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-03 10:30:51 +08:00
fix: optimize batch email performance and fix gift card issues
- Add chunking and batching for admin email sending - Fix gift card pagination and add per_page limits - Update frontend prompts and complete language packs
This commit is contained in:
@@ -65,15 +65,7 @@ class GiftCardController extends Controller
|
|||||||
];
|
];
|
||||||
})->values();
|
})->values();
|
||||||
|
|
||||||
return response()->json([
|
return $this->paginate( $templates);
|
||||||
'data' => $data,
|
|
||||||
'pagination' => [
|
|
||||||
'current_page' => $templates->currentPage(),
|
|
||||||
'last_page' => $templates->lastPage(),
|
|
||||||
'per_page' => $templates->perPage(),
|
|
||||||
'total' => $templates->total(),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -352,7 +344,7 @@ class GiftCardController extends Controller
|
|||||||
'batch_id' => 'string',
|
'batch_id' => 'string',
|
||||||
'status' => 'integer|in:0,1,2,3',
|
'status' => 'integer|in:0,1,2,3',
|
||||||
'page' => 'integer|min:1',
|
'page' => 'integer|min:1',
|
||||||
'per_page' => 'integer|min:1|max:100',
|
'per_page' => 'integer|min:1|max:500',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$query = GiftCardCode::with(['template', 'user']);
|
$query = GiftCardCode::with(['template', 'user']);
|
||||||
@@ -391,15 +383,7 @@ class GiftCardController extends Controller
|
|||||||
];
|
];
|
||||||
})->values();
|
})->values();
|
||||||
|
|
||||||
return response()->json([
|
return $this->paginate($codes);
|
||||||
'data' => $data,
|
|
||||||
'pagination' => [
|
|
||||||
'current_page' => $codes->currentPage(),
|
|
||||||
'last_page' => $codes->lastPage(),
|
|
||||||
'per_page' => $codes->perPage(),
|
|
||||||
'total' => $codes->total(),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -464,7 +448,7 @@ class GiftCardController extends Controller
|
|||||||
'template_id' => 'integer|exists:v2_gift_card_template,id',
|
'template_id' => 'integer|exists:v2_gift_card_template,id',
|
||||||
'user_id' => 'integer|exists:v2_user,id',
|
'user_id' => 'integer|exists:v2_user,id',
|
||||||
'page' => 'integer|min:1',
|
'page' => 'integer|min:1',
|
||||||
'per_page' => 'integer|min:1|max:100',
|
'per_page' => 'integer|min:1|max:500',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$query = GiftCardUsage::with(['template', 'code', 'user', 'inviteUser']);
|
$query = GiftCardUsage::with(['template', 'code', 'user', 'inviteUser']);
|
||||||
@@ -480,7 +464,7 @@ class GiftCardController extends Controller
|
|||||||
$perPage = $request->input('per_page', 15);
|
$perPage = $request->input('per_page', 15);
|
||||||
$usages = $query->orderBy('created_at', 'desc')->paginate($perPage);
|
$usages = $query->orderBy('created_at', 'desc')->paginate($perPage);
|
||||||
|
|
||||||
$data = $usages->getCollection()->map(function ($usage) {
|
$usages->transform(function ($usage) {
|
||||||
return [
|
return [
|
||||||
'id' => $usage->id,
|
'id' => $usage->id,
|
||||||
'code' => $usage->code->code ?? '',
|
'code' => $usage->code->code ?? '',
|
||||||
@@ -493,15 +477,7 @@ class GiftCardController extends Controller
|
|||||||
'created_at' => $usage->created_at,
|
'created_at' => $usage->created_at,
|
||||||
];
|
];
|
||||||
})->values();
|
})->values();
|
||||||
return response()->json([
|
return $this->paginate($usages);
|
||||||
'data' => $data,
|
|
||||||
'pagination' => [
|
|
||||||
'current_page' => $usages->currentPage(),
|
|
||||||
'last_page' => $usages->lastPage(),
|
|
||||||
'per_page' => $usages->perPage(),
|
|
||||||
'total' => $usages->total(),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use App\Utils\Helper;
|
|||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@@ -442,22 +443,38 @@ class UserController extends Controller
|
|||||||
$sort = $request->input('sort') ? $request->input('sort') : 'created_at';
|
$sort = $request->input('sort') ? $request->input('sort') : 'created_at';
|
||||||
$builder = User::orderBy($sort, $sortType);
|
$builder = User::orderBy($sort, $sortType);
|
||||||
$this->applyFiltersAndSorts($request, $builder);
|
$this->applyFiltersAndSorts($request, $builder);
|
||||||
$users = $builder->get();
|
|
||||||
foreach ($users as $user) {
|
$subject = $request->input('subject');
|
||||||
SendEmailJob::dispatch(
|
$content = $request->input('content');
|
||||||
[
|
$templateValue = [
|
||||||
|
'name' => admin_setting('app_name', 'XBoard'),
|
||||||
|
'url' => admin_setting('app_url'),
|
||||||
|
'content' => $content
|
||||||
|
];
|
||||||
|
|
||||||
|
$chunkSize = 1000;
|
||||||
|
$totalProcessed = 0;
|
||||||
|
|
||||||
|
$builder->chunk($chunkSize, function ($users) use ($subject, $templateValue, &$totalProcessed) {
|
||||||
|
$jobs = [];
|
||||||
|
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$jobs[] = new SendEmailJob([
|
||||||
'email' => $user->email,
|
'email' => $user->email,
|
||||||
'subject' => $request->input('subject'),
|
'subject' => $subject,
|
||||||
'template_name' => 'notify',
|
'template_name' => 'notify',
|
||||||
'template_value' => [
|
'template_value' => $templateValue
|
||||||
'name' => admin_setting('app_name', 'XBoard'),
|
], 'send_email_mass');
|
||||||
'url' => admin_setting('app_url'),
|
}
|
||||||
'content' => $request->input('content')
|
|
||||||
]
|
if (!empty($jobs)) {
|
||||||
],
|
Bus::batch($jobs)
|
||||||
'send_email_mass'
|
->allowFailures()
|
||||||
);
|
->dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$totalProcessed += $users->count();
|
||||||
|
});
|
||||||
|
|
||||||
return $this->success(true);
|
return $this->success(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
use App\Services\MailService;
|
use App\Services\MailService;
|
||||||
|
use Illuminate\Bus\Batchable;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
@@ -11,7 +12,7 @@ use Illuminate\Queue\SerializesModels;
|
|||||||
|
|
||||||
class SendEmailJob implements ShouldQueue
|
class SendEmailJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Batchable;
|
||||||
protected $params;
|
protected $params;
|
||||||
|
|
||||||
public $tries = 3;
|
public $tries = 3;
|
||||||
|
|||||||
20
public/assets/admin/assets/index.js
vendored
20
public/assets/admin/assets/index.js
vendored
File diff suppressed because one or more lines are too long
315
public/assets/admin/locales/en-US.js
vendored
315
public/assets/admin/locales/en-US.js
vendored
@@ -967,6 +967,10 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
"previousPage": "Previous page",
|
"previousPage": "Previous page",
|
||||||
"nextPage": "Next page",
|
"nextPage": "Next page",
|
||||||
"lastPage": "Go to last page"
|
"lastPage": "Go to last page"
|
||||||
|
},
|
||||||
|
"viewOptions": {
|
||||||
|
"button": "Columns",
|
||||||
|
"label": "Toggle columns"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
@@ -1198,62 +1202,74 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"giftCard": {
|
"giftCard": {
|
||||||
"types": {
|
"title": "Gift Card Management",
|
||||||
"1": "General Gift Card",
|
"description": "Manage gift card templates, redemption codes, and usage records.",
|
||||||
"2": "Plan-Specific Gift Card",
|
"tabs": {
|
||||||
"3": "Mystery Box Reward",
|
"templates": "Template Management",
|
||||||
"4": "Task Gift Card"
|
"codes": "Redemption Code Management",
|
||||||
},
|
"usages": "Usage Records",
|
||||||
"status": {
|
"statistics": "Statistics"
|
||||||
"0": "Unused",
|
|
||||||
"1": "Used",
|
|
||||||
"2": "Disabled",
|
|
||||||
"3": "Expired"
|
|
||||||
},
|
},
|
||||||
"template": {
|
"template": {
|
||||||
"title": "Gift Card Templates",
|
"title": "Template Management",
|
||||||
"add": "Add Template",
|
"description": "Manage gift card templates, including creating, editing, and deleting templates.",
|
||||||
"search": "Search template name...",
|
"table": {
|
||||||
|
"title": "Template List",
|
||||||
|
"columns": {
|
||||||
|
"id": "ID",
|
||||||
|
"name": "Name",
|
||||||
|
"type": "Type",
|
||||||
|
"status": "Status",
|
||||||
|
"sort": "Sort",
|
||||||
|
"rewards": "Rewards",
|
||||||
|
"created_at": "Created At",
|
||||||
|
"actions": "Actions",
|
||||||
|
"no_rewards": "No Rewards"
|
||||||
|
}
|
||||||
|
},
|
||||||
"form": {
|
"form": {
|
||||||
|
"add": "Add Template",
|
||||||
|
"edit": "Edit Template",
|
||||||
"name": {
|
"name": {
|
||||||
"label": "Name",
|
"label": "Template Name",
|
||||||
"placeholder": "Enter template name"
|
"placeholder": "Please enter template name",
|
||||||
|
"required": "Please enter template name"
|
||||||
},
|
},
|
||||||
"sort": {
|
"sort": {
|
||||||
"label": "Sort",
|
"label": "Sort",
|
||||||
"placeholder": "Smaller numbers come first"
|
"placeholder": "Smaller numbers appear first"
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"label": "Type",
|
"label": "Type",
|
||||||
"placeholder": "Select gift card type"
|
"placeholder": "Please select gift card type"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
"placeholder": "Enter gift card description"
|
"placeholder": "Please enter gift card description"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"description": "If disabled, this template cannot be used to generate or redeem new gift cards."
|
"description": "When disabled, this template cannot generate or redeem new gift cards."
|
||||||
},
|
},
|
||||||
"display": {
|
"display": {
|
||||||
"title": "Display Settings"
|
"title": "Display Effect"
|
||||||
},
|
},
|
||||||
"theme_color": {
|
"theme_color": {
|
||||||
"label": "Theme Color"
|
"label": "Theme Color"
|
||||||
},
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
"label": "Icon",
|
"label": "Icon",
|
||||||
"placeholder": "Enter the URL of the icon"
|
"placeholder": "Please enter icon URL"
|
||||||
},
|
},
|
||||||
"background_image": {
|
"background_image": {
|
||||||
"label": "Background Image",
|
"label": "Background Image",
|
||||||
"placeholder": "Enter the URL of the background image"
|
"placeholder": "Please enter background image URL"
|
||||||
},
|
},
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"title": "Usage Conditions",
|
"title": "Usage Conditions",
|
||||||
"new_user_max_days": {
|
"new_user_max_days": {
|
||||||
"label": "New User Registration Day Limit",
|
"label": "New User Registration Days Limit",
|
||||||
"placeholder": "e.g., 7 (only for users registered within 7 days)"
|
"placeholder": "Example: 7 (Only for users registered within 7 days)"
|
||||||
},
|
},
|
||||||
"new_user_only": {
|
"new_user_only": {
|
||||||
"label": "New Users Only"
|
"label": "New Users Only"
|
||||||
@@ -1262,15 +1278,15 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
"label": "Paid Users Only"
|
"label": "Paid Users Only"
|
||||||
},
|
},
|
||||||
"require_invite": {
|
"require_invite": {
|
||||||
"label": "Requires Invitation"
|
"label": "Require Invitation Relationship"
|
||||||
},
|
},
|
||||||
"allowed_plans": {
|
"allowed_plans": {
|
||||||
"label": "Allowed Plans",
|
"label": "Allowed Plans",
|
||||||
"placeholder": "Select allowed plans (leave empty for no restriction)"
|
"placeholder": "Select plans allowed for redemption (leave empty for no restriction)"
|
||||||
},
|
},
|
||||||
"disallowed_plans": {
|
"disallowed_plans": {
|
||||||
"label": "Disallowed Plans",
|
"label": "Disallowed Plans",
|
||||||
"placeholder": "Select disallowed plans (leave empty for no restriction)"
|
"placeholder": "Select plans forbidden for redemption (leave empty for no restriction)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"limits": {
|
"limits": {
|
||||||
@@ -1280,64 +1296,64 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
"placeholder": "Leave empty for no limit"
|
"placeholder": "Leave empty for no limit"
|
||||||
},
|
},
|
||||||
"cooldown_hours": {
|
"cooldown_hours": {
|
||||||
"label": "Cooldown for Same Type (Hours)",
|
"label": "Cooldown Hours for Same Type",
|
||||||
"placeholder": "Leave empty for no limit"
|
"placeholder": "Leave empty for no limit"
|
||||||
},
|
},
|
||||||
"invite_reward_rate": {
|
"invite_reward_rate": {
|
||||||
"label": "Inviter Reward Rate",
|
"label": "Inviter Reward Rate",
|
||||||
"placeholder": "e.g., 0.2 (for 20%)",
|
"placeholder": "Example: 0.2 (represents 20%)",
|
||||||
"description": "If the user has an inviter, the inviter's reward = balance reward * this rate"
|
"description": "When user has an inviter, inviter reward = balance reward × this rate"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rewards": {
|
"rewards": {
|
||||||
"title": "Reward Content",
|
"title": "Rewards",
|
||||||
"balance": {
|
"balance": {
|
||||||
"label": "Reward Amount (in Yuan)",
|
"label": "Reward Balance (Yuan)",
|
||||||
"short_label": "Balance",
|
"short_label": "Balance",
|
||||||
"placeholder": "Enter the reward amount in Yuan"
|
"placeholder": "Please enter reward amount (Yuan)"
|
||||||
},
|
},
|
||||||
"transfer_enable": {
|
"transfer_enable": {
|
||||||
"label": "Reward Traffic (in GB)",
|
"label": "Reward Traffic (GB)",
|
||||||
"short_label": "Traffic",
|
"short_label": "Traffic",
|
||||||
"placeholder": "Enter the reward traffic in GB"
|
"placeholder": "Please enter reward traffic (GB)"
|
||||||
},
|
},
|
||||||
"expire_days": {
|
"expire_days": {
|
||||||
"label": "Extend Validity (in days)",
|
"label": "Extend Validity (Days)",
|
||||||
"short_label": "Validity",
|
"short_label": "Validity",
|
||||||
"placeholder": "Enter the number of days to extend"
|
"placeholder": "Please enter extension days"
|
||||||
},
|
},
|
||||||
"transfer": {
|
"transfer": {
|
||||||
"label": "Reward Traffic (in bytes)",
|
"label": "Reward Traffic (Bytes)",
|
||||||
"placeholder": "Enter the reward traffic in bytes"
|
"placeholder": "Please enter reward traffic (bytes)"
|
||||||
},
|
},
|
||||||
"days": {
|
"days": {
|
||||||
"label": "Extend Validity (in days)",
|
"label": "Extend Validity (Days)",
|
||||||
"placeholder": "Enter the number of days to extend"
|
"placeholder": "Please enter extension days"
|
||||||
},
|
},
|
||||||
"device_limit": {
|
"device_limit": {
|
||||||
"label": "Increase Device Limit",
|
"label": "Increase Device Count",
|
||||||
"short_label": "Devices",
|
"short_label": "Devices",
|
||||||
"placeholder": "Enter the number of devices to increase"
|
"placeholder": "Please enter increased device count"
|
||||||
},
|
},
|
||||||
"reset_package": {
|
"reset_package": {
|
||||||
"label": "Reset Monthly Traffic",
|
"label": "Reset Monthly Traffic",
|
||||||
"description": "If enabled, the user's current plan traffic usage will be reset to zero upon redemption."
|
"description": "When enabled, redemption will clear the user's current plan's used traffic."
|
||||||
},
|
},
|
||||||
"reset_count": {
|
"reset_count": {
|
||||||
"description": "This type of card will reset the user's traffic usage for the current month."
|
"description": "This type of card will reset the user's monthly traffic usage."
|
||||||
},
|
},
|
||||||
"task_card": {
|
"task_card": {
|
||||||
"description": "The specific rewards for task gift cards will be configured in the task system."
|
"description": "Specific rewards for task gift cards will be configured in the task system."
|
||||||
},
|
},
|
||||||
"plan_id": {
|
"plan_id": {
|
||||||
"label": "Specify Plan",
|
"label": "Specified Plan",
|
||||||
"short_label": "Plan",
|
"short_label": "Plan",
|
||||||
"placeholder": "Select a plan"
|
"placeholder": "Please select a plan"
|
||||||
},
|
},
|
||||||
"plan_validity_days": {
|
"plan_validity_days": {
|
||||||
"label": "Plan Validity (in days)",
|
"label": "Plan Validity (Days)",
|
||||||
"short_label": "Plan Validity",
|
"short_label": "Plan Validity",
|
||||||
"placeholder": "Leave empty to use the plan's default validity"
|
"placeholder": "Leave empty to use plan default validity"
|
||||||
},
|
},
|
||||||
"random_rewards": {
|
"random_rewards": {
|
||||||
"label": "Random Reward Pool",
|
"label": "Random Reward Pool",
|
||||||
@@ -1349,87 +1365,182 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
|||||||
"title": "Special Configuration",
|
"title": "Special Configuration",
|
||||||
"start_time": {
|
"start_time": {
|
||||||
"label": "Event Start Time",
|
"label": "Event Start Time",
|
||||||
"placeholder": "Pick a start date"
|
"placeholder": "Please select start date"
|
||||||
},
|
},
|
||||||
"end_time": {
|
"end_time": {
|
||||||
"label": "Event End Time",
|
"label": "Event End Time",
|
||||||
"placeholder": "Pick an end date"
|
"placeholder": "Please select end date"
|
||||||
},
|
},
|
||||||
"festival_bonus": {
|
"festival_bonus": {
|
||||||
"label": "Festival Reward Multiplier",
|
"label": "Festival Reward Multiplier",
|
||||||
"placeholder": "e.g., 1.5 (for 1.5x)"
|
"placeholder": "Example: 1.5 (represents 1.5x)"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"submit": {
|
||||||
|
"saving": "Saving...",
|
||||||
|
"save": "Save"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"edit": "Edit",
|
||||||
|
"delete": "Delete",
|
||||||
|
"deleteConfirm": {
|
||||||
|
"title": "Confirm Delete",
|
||||||
|
"description": "This action will permanently delete this template. Are you sure you want to continue?",
|
||||||
|
"confirmText": "Delete"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"code": {
|
"code": {
|
||||||
"title": "Code Management",
|
"title": "Redemption Code Management",
|
||||||
"add": "Generate Codes",
|
|
||||||
"search": "Search codes...",
|
|
||||||
"form": {
|
"form": {
|
||||||
|
"generate": "Generate Redemption Codes",
|
||||||
"template_id": {
|
"template_id": {
|
||||||
"label": "Gift Card Template",
|
"label": "Select Template",
|
||||||
"placeholder": "Select a template"
|
"placeholder": "Please select a template to generate redemption codes"
|
||||||
},
|
},
|
||||||
"count": {
|
"count": {
|
||||||
"label": "Quantity to Generate",
|
"label": "Generation Count"
|
||||||
"placeholder": "Enter the quantity to generate"
|
|
||||||
},
|
},
|
||||||
"prefix": {
|
"prefix": {
|
||||||
"label": "Code Prefix",
|
"label": "Custom Prefix (Optional)"
|
||||||
"placeholder": "Leave empty for default prefix GC"
|
|
||||||
},
|
},
|
||||||
"expires_hours": {
|
"expires_hours": {
|
||||||
"label": "Validity (Hours)",
|
"label": "Validity (Hours)"
|
||||||
"placeholder": "From generation time, leave empty for no expiration"
|
|
||||||
},
|
},
|
||||||
"max_usage": {
|
"max_usage": {
|
||||||
"label": "Max Usage Count",
|
"label": "Max Usage Count"
|
||||||
"placeholder": "Total times each code can be used"
|
|
||||||
},
|
},
|
||||||
"download_csv": "Export as CSV"
|
"download_csv": "Export CSV",
|
||||||
|
"submit": {
|
||||||
|
"generating": "Generating...",
|
||||||
|
"generate": "Generate Now"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Manage gift card redemption codes, including generation, viewing, and exporting codes.",
|
||||||
|
"generate": {
|
||||||
|
"title": "Generate Redemption Codes",
|
||||||
|
"template": "Select Template",
|
||||||
|
"count": "Generation Count",
|
||||||
|
"prefix": "Custom Prefix",
|
||||||
|
"expires_hours": "Validity (Hours)",
|
||||||
|
"max_usage": "Max Usage Count",
|
||||||
|
"submit": "Generate"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"code": "Code",
|
"title": "Redemption Code List",
|
||||||
"template": "Template",
|
"columns": {
|
||||||
"status": "Status",
|
"id": "ID",
|
||||||
"expires_at": "Expires At",
|
"code": "Redemption Code",
|
||||||
"used_at": "Used At",
|
"template_name": "Template Name",
|
||||||
"used_by": "Used By",
|
"status": "Status",
|
||||||
"max_usage": "Max Uses",
|
"expires_at": "Expires At",
|
||||||
"usage_count": "Usage Count"
|
"usage_count": "Used Count",
|
||||||
|
"max_usage": "Available Count",
|
||||||
|
"created_at": "Created At"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"messages": {
|
"actions": {
|
||||||
"generateSuccess": "Codes generated successfully",
|
"enable": "Enable",
|
||||||
"generateFailed": "Failed to generate codes",
|
"disable": "Disable",
|
||||||
"deleteConfirm": "Are you sure you want to delete this code? This action cannot be undone.",
|
"export": "Export",
|
||||||
"deleteSuccess": "Code deleted successfully",
|
"exportConfirm": {
|
||||||
"deleteFailed": "Failed to delete code"
|
"title": "Confirm Export",
|
||||||
|
"description": "This will export all redemption codes from the selected batch as a text file. Are you sure you want to continue?",
|
||||||
|
"confirmText": "Export"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"0": "Unused",
|
||||||
|
"1": "Used",
|
||||||
|
"2": "Disabled",
|
||||||
|
"3": "Expired"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"messages": {
|
"usage": {
|
||||||
"formInvalid": "Form validation failed, please check your input.",
|
"title": "Usage Records",
|
||||||
"templateCreated": "Template created successfully",
|
"description": "View gift card usage records and detailed information.",
|
||||||
"templateUpdated": "Template updated successfully",
|
"table": {
|
||||||
"createTemplateFailed": "Failed to create template",
|
"columns": {
|
||||||
"updateTemplateFailed": "Failed to update template",
|
"id": "ID",
|
||||||
"deleteConfirm": "Are you sure you want to delete this template? All codes under it will also be deleted.",
|
"code": "Redemption Code",
|
||||||
"deleteSuccess": "Template deleted successfully",
|
"template_name": "Template Name",
|
||||||
"deleteFailed": "Failed to delete template",
|
"user_email": "User Email",
|
||||||
"codesGenerated": "Codes generated successfully"
|
"rewards_given": "Rewards Given",
|
||||||
},
|
"invite_rewards": "Invitation Rewards",
|
||||||
"table": {
|
"multiplier_applied": "Multiplier Applied",
|
||||||
"columns": {
|
"ip_address": "IP Address",
|
||||||
"no_rewards": "No Rewards"
|
"created_at": "Usage Time",
|
||||||
|
"actions": "Actions"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"view": "View Details"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"statistics": {
|
||||||
|
"title": "Statistics",
|
||||||
|
"description": "View gift card statistics and usage analysis.",
|
||||||
|
"total": {
|
||||||
|
"title": "Overall Statistics",
|
||||||
|
"templates_count": "Total Templates",
|
||||||
|
"active_templates_count": "Active Templates",
|
||||||
|
"codes_count": "Total Redemption Codes",
|
||||||
|
"used_codes_count": "Used Redemption Codes",
|
||||||
|
"usages_count": "Usage Records"
|
||||||
|
},
|
||||||
|
"daily": {
|
||||||
|
"title": "Daily Usage",
|
||||||
|
"chart": "Usage Trend Chart"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"title": "Type Statistics",
|
||||||
|
"chart": "Type Distribution Chart"
|
||||||
|
},
|
||||||
|
"dateRange": {
|
||||||
|
"label": "Date Range",
|
||||||
|
"start": "Start Date",
|
||||||
|
"end": "End Date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types": {
|
||||||
|
"1": "General Gift Card",
|
||||||
|
"2": "Plan Gift Card",
|
||||||
|
"3": "Mystery Gift Card",
|
||||||
|
"4": "Task Gift Card"
|
||||||
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"currency": {
|
"search": "Search gift cards...",
|
||||||
"yuan": "Yuan"
|
"reset": "Reset",
|
||||||
},
|
"filter": "Filter",
|
||||||
"time": {
|
"export": "Export",
|
||||||
"day": "day"
|
"refresh": "Refresh",
|
||||||
}
|
"back": "Back",
|
||||||
|
"close": "Close",
|
||||||
|
"confirm": "Confirm",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"enabled": "Enabled",
|
||||||
|
"disabled": "Disabled",
|
||||||
|
"loading": "Loading...",
|
||||||
|
"noData": "No Data",
|
||||||
|
"success": "Operation Successful",
|
||||||
|
"error": "Operation Failed"
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"formInvalid": "Please check if the form input is correct",
|
||||||
|
"templateCreated": "Template created successfully",
|
||||||
|
"templateUpdated": "Template updated successfully",
|
||||||
|
"templateDeleted": "Template deleted successfully",
|
||||||
|
"codeGenerated": "Redemption codes generated successfully",
|
||||||
|
"generateCodeFailed": "Failed to generate redemption codes",
|
||||||
|
"codeStatusUpdated": "Redemption code status updated successfully",
|
||||||
|
"updateCodeStatusFailed": "Failed to update redemption code status",
|
||||||
|
"codesExported": "Redemption codes exported successfully",
|
||||||
|
"createTemplateFailed": "Failed to create template",
|
||||||
|
"updateTemplateFailed": "Failed to update template",
|
||||||
|
"deleteTemplateFailed": "Failed to delete template",
|
||||||
|
"loadDataFailed": "Failed to load data",
|
||||||
|
"codesGenerated": "Redemption codes generated successfully"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"route": {
|
"route": {
|
||||||
|
|||||||
4
public/assets/admin/locales/zh-CN.js
vendored
4
public/assets/admin/locales/zh-CN.js
vendored
@@ -972,6 +972,10 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
|
|||||||
"previousPage": "上一页",
|
"previousPage": "上一页",
|
||||||
"nextPage": "下一页",
|
"nextPage": "下一页",
|
||||||
"lastPage": "跳转到最后一页"
|
"lastPage": "跳转到最后一页"
|
||||||
|
},
|
||||||
|
"viewOptions": {
|
||||||
|
"button": "显示列",
|
||||||
|
"label": "切换显示列"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
|
|||||||
Reference in New Issue
Block a user