Add SnapshotActionMail class and email template for snapshot actions; implement email notifications for create, remove, and revert actions
This commit is contained in:
@@ -9,7 +9,6 @@ use App\Jobs\VirtualMachine\Snapshot\CreateSnapshot;
|
||||
use App\Jobs\VirtualMachine\Snapshot\RevertSnapshot;
|
||||
use App\Jobs\VirtualMachine\Snapshot\RemoveSnapshot;
|
||||
use App\Models\ModuleSnapshot;
|
||||
use App\Models\ModuleVmware;
|
||||
use App\Services\ActivityLogger;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -40,12 +39,12 @@ class SnapshotController extends Controller
|
||||
$snapshotName = sprintf('%s-%s-%d', $vm->name, $today, $existingCount + 1);
|
||||
|
||||
$snapshot = ModuleSnapshot::create([
|
||||
'name' => $snapshotName,
|
||||
'description' => $payload['description'] ?? null,
|
||||
'customer_id' => $customer->id,
|
||||
'name' => $snapshotName,
|
||||
'description' => $payload['description'] ?? null,
|
||||
'customer_id' => $customer->id,
|
||||
'module_vmware_id' => $vm->id,
|
||||
'status' => 'pending',
|
||||
'snapshot_ref' => null,
|
||||
'status' => 'pending',
|
||||
'snapshot_ref' => null,
|
||||
]);
|
||||
|
||||
CreateSnapshot::dispatch($snapshot->id);
|
||||
@@ -62,10 +61,10 @@ class SnapshotController extends Controller
|
||||
'error' => false,
|
||||
'message' => 'Đã gửi yêu cầu tạo snapshot vào hàng đợi',
|
||||
'data' => [
|
||||
'id' => $snapshot->id,
|
||||
'name' => $snapshot->name,
|
||||
'id' => $snapshot->id,
|
||||
'name' => $snapshot->name,
|
||||
'description' => $snapshot->description,
|
||||
'status' => 'pending',
|
||||
'status' => 'pending',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -5,23 +5,28 @@ namespace App\Jobs\VirtualMachine\Snapshot;
|
||||
use App\Events\NotificationStatus;
|
||||
use App\Http\Services\Telegram;
|
||||
use App\Http\Services\vCenter as ServiceVCenter;
|
||||
use App\Mail\Customer\SnapshotActionMail;
|
||||
use App\Models\ModuleSnapshot;
|
||||
use App\Models\ModuleSnapshotLimit;
|
||||
use App\Models\ModuleVmware;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class CreateSnapshot implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected Telegram $telegram;
|
||||
|
||||
public function __construct(
|
||||
public int $snapshotId
|
||||
) {}
|
||||
) {
|
||||
$this->telegram = new Telegram();
|
||||
}
|
||||
|
||||
public function handle(ServiceVCenter $serviceVCenter)
|
||||
{
|
||||
@@ -37,23 +42,20 @@ class CreateSnapshot implements ShouldQueue
|
||||
|
||||
$product = $snapshot->vm;
|
||||
|
||||
// Resolve vCenter using helper method
|
||||
$vcenter = $serviceVCenter->resolveVCenterFromProduct($product);
|
||||
|
||||
if (!$vcenter) {
|
||||
$snapshot->update([
|
||||
'status' => 'failed',
|
||||
'status' => 'failed',
|
||||
'error_message' => 'Không tìm thấy thông tin vCenter',
|
||||
]);
|
||||
throw new \Exception('Không tìm thấy thông tin vCenter cho VM');
|
||||
}
|
||||
|
||||
try {
|
||||
// Config vCenter
|
||||
$serviceVCenter->token = $vcenter->token;
|
||||
$serviceVCenter->token = $vcenter->token;
|
||||
$serviceVCenter->apiUri = $vcenter->host;
|
||||
|
||||
// Call vCenter with snapshot name from DB
|
||||
$result = $serviceVCenter->CreateSnapShot($product, $snapshot->name);
|
||||
|
||||
if ($result === 'Login_Again') {
|
||||
@@ -71,13 +73,11 @@ class CreateSnapshot implements ShouldQueue
|
||||
throw new \Exception($result['message'] ?? 'Lỗi tạo snapshot');
|
||||
}
|
||||
|
||||
// Update DB SUCCESS
|
||||
$snapshot->update([
|
||||
'status' => 'success',
|
||||
'status' => 'success',
|
||||
'snapshot_ref' => $result['data'] ?? $snapshot->name,
|
||||
]);
|
||||
|
||||
// Increment quota CHỈ khi success
|
||||
ModuleSnapshotLimit::where('customer_id', $snapshot->customer_id)
|
||||
->increment('used');
|
||||
|
||||
@@ -85,9 +85,34 @@ class CreateSnapshot implements ShouldQueue
|
||||
"Snapshot {$snapshot->name} tạo thành công",
|
||||
true
|
||||
));
|
||||
|
||||
$product->loadMissing('customer');
|
||||
if ($product->customer?->email) {
|
||||
Mail::to($product->customer->email)->queue(new SnapshotActionMail([
|
||||
'action' => 'create',
|
||||
'fullname' => $product->customer->fullname,
|
||||
'vm_name' => $product->name,
|
||||
'snapshot_name' => $snapshot->name,
|
||||
'action_at' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
}
|
||||
|
||||
$this->telegram->SendMessage(
|
||||
"📸 <b>SNAPSHOT CREATED SUCCESSFULLY</b>\n\n" .
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" .
|
||||
"🖥️ <b>Server:</b> `{$product->name}`\n" .
|
||||
"📸 <b>Snapshot:</b> `{$snapshot->name}`\n" .
|
||||
"👤 <b>Customer:</b> `#{$snapshot->customer_id}`\n" .
|
||||
"🆔 <b>VM ID:</b> `{$product->vmware_id}`\n" .
|
||||
"⏰ <b>Created:</b> `" . now()->format('d/m/Y H:i:s') . "`\n" .
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" .
|
||||
"💡 <b>Status:</b> ✅ Completed\n" .
|
||||
"🔧 <b>Action:</b> Snapshot Creation\n" .
|
||||
"📊 <b>Queue:</b> snapshots"
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
$snapshot->update([
|
||||
'status' => 'failed',
|
||||
'status' => 'failed',
|
||||
'error_message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
@@ -101,7 +126,7 @@ class CreateSnapshot implements ShouldQueue
|
||||
|
||||
if ($snapshot) {
|
||||
$snapshot->update([
|
||||
'status' => 'failed',
|
||||
'status' => 'failed',
|
||||
'error_message' => $exception->getMessage(),
|
||||
]);
|
||||
}
|
||||
@@ -110,5 +135,12 @@ class CreateSnapshot implements ShouldQueue
|
||||
"Snapshot thất bại: {$exception->getMessage()}",
|
||||
false
|
||||
));
|
||||
|
||||
$this->telegram->SendErrorMessage([
|
||||
'job_name' => 'CreateSnapshot',
|
||||
'snapshot_id' => $this->snapshotId,
|
||||
'error' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Jobs\VirtualMachine\Snapshot;
|
||||
use App\Events\NotificationStatus;
|
||||
use App\Http\Services\Telegram;
|
||||
use App\Http\Services\vCenter as ServiceVCenter;
|
||||
use App\Mail\Customer\SnapshotActionMail;
|
||||
use App\Models\ModuleSnapshot;
|
||||
use App\Models\ModuleSnapshotLimit;
|
||||
use App\Models\ModuleVmware;
|
||||
@@ -14,6 +15,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class RemoveSnapshot implements ShouldQueue
|
||||
{
|
||||
@@ -117,6 +119,17 @@ class RemoveSnapshot implements ShouldQueue
|
||||
// Send success notification
|
||||
Event(new NotificationStatus("Xóa snapshot thành công cho VPS {$product->name}", true));
|
||||
|
||||
$product->loadMissing('customer');
|
||||
if ($product->customer?->email) {
|
||||
Mail::to($product->customer->email)->queue(new SnapshotActionMail([
|
||||
'action' => 'remove',
|
||||
'fullname' => $product->customer->fullname,
|
||||
'vm_name' => $product->name,
|
||||
'snapshot_name' => $snapshotName,
|
||||
'action_at' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
}
|
||||
|
||||
// Send Telegram notification
|
||||
$this->telegram->SendMessage(
|
||||
"🗑️ <b>SNAPSHOT REMOVED SUCCESSFULLY</b>\n\n" .
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Jobs\VirtualMachine\Snapshot;
|
||||
use App\Events\NotificationStatus;
|
||||
use App\Http\Services\Telegram;
|
||||
use App\Http\Services\vCenter as ServiceVCenter;
|
||||
use App\Mail\Customer\SnapshotActionMail;
|
||||
use App\Models\ModuleSnapshot;
|
||||
use App\Models\ModuleVmware;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -13,6 +14,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class RevertSnapshot implements ShouldQueue
|
||||
{
|
||||
@@ -107,6 +109,17 @@ class RevertSnapshot implements ShouldQueue
|
||||
// Send success notification
|
||||
Event(new NotificationStatus("Khôi phục snapshot thành công cho VPS {$product->name}", true));
|
||||
|
||||
$product->loadMissing('customer');
|
||||
if ($product->customer?->email) {
|
||||
Mail::to($product->customer->email)->queue(new SnapshotActionMail([
|
||||
'action' => 'revert',
|
||||
'fullname' => $product->customer->fullname,
|
||||
'vm_name' => $product->name,
|
||||
'snapshot_name' => $snapshot->name,
|
||||
'action_at' => now()->format('d/m/Y H:i:s'),
|
||||
]));
|
||||
}
|
||||
|
||||
// Send Telegram notification
|
||||
$this->telegram->SendMessage(
|
||||
"🔄 <b>SNAPSHOT REVERTED SUCCESSFULLY</b>\n\n" .
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail\Customer;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SnapshotActionMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public array $data) {}
|
||||
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$subjects = [
|
||||
'create' => 'Tạo Snapshot thành công',
|
||||
'remove' => 'Xóa Snapshot thành công',
|
||||
'revert' => 'Khôi phục Snapshot thành công',
|
||||
];
|
||||
|
||||
$appName = $this->payload()['company_name'] ?? config('app.name', 'The Gioi So');
|
||||
$subject = $subjects[$this->data['action'] ?? 'create'] ?? 'Thông báo Snapshot';
|
||||
|
||||
return new Envelope(subject: "{$subject} — {$appName}");
|
||||
}
|
||||
|
||||
public function content(): Content
|
||||
{
|
||||
$data = $this->payload();
|
||||
|
||||
return new Content(
|
||||
view: 'emails.customer.snapshot-action',
|
||||
with: [
|
||||
'appName' => $data['company_name'] ?? config('app.name', 'The Gioi So'),
|
||||
'fullName' => $data['fullname'] ?? 'Quý khách',
|
||||
'vmName' => $data['vm_name'] ?? '',
|
||||
'snapshotName' => $data['snapshot_name'] ?? '',
|
||||
'action' => $data['action'] ?? 'create',
|
||||
'actionAt' => $data['action_at'] ?? now()->format('d/m/Y H:i:s'),
|
||||
'loginUrl' => $data['login_url'] ?? rtrim(config('app.frontend_url', ''), '/') . '/dang-nhap',
|
||||
'supportEmail' => $data['support_email'] ?? config('mail.support_email', 'support@thegioiso.com'),
|
||||
'supportPhone' => $data['support_phone'] ?? config('mail.support_phone', '1900.xxxx'),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
private function payload(): array
|
||||
{
|
||||
try {
|
||||
$setting = Setting::where('key', 'setting')->first();
|
||||
$settingValue = $setting ? json_decode((string) $setting->value, true) : [];
|
||||
} catch (\Throwable) {
|
||||
$settingValue = [];
|
||||
}
|
||||
|
||||
return array_merge([
|
||||
'company_name' => $settingValue['company'] ?? config('app.name', 'The Gioi So'),
|
||||
'support_email' => $settingValue['email'] ?? config('mail.support_email', 'support@thegioiso.com'),
|
||||
'support_phone' => $settingValue['hotline'] ?? ($settingValue['phone'] ?? config('mail.support_phone', '1900.xxxx')),
|
||||
'login_url' => rtrim(config('app.frontend_url', ''), '/') . '/dang-nhap',
|
||||
], $this->data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
@php
|
||||
$appName = $appName ?? config('app.name', 'Thế Giới Số');
|
||||
$fullName = $fullName ?? 'Quý khách';
|
||||
$vmName = $vmName ?? '';
|
||||
$snapshotName = $snapshotName ?? '';
|
||||
$action = $action ?? 'create';
|
||||
$actionAt = $actionAt ?? now()->format('d/m/Y H:i:s');
|
||||
$loginUrl = $loginUrl ?? rtrim(config('app.frontend_url', ''), '/') . '/dang-nhap';
|
||||
$supportEmail = $supportEmail ?? 'support@tgs.com.vn';
|
||||
$supportPhone = $supportPhone ?? '1900. 6119';
|
||||
|
||||
$actionLabels = [
|
||||
'create' => ['icon' => '📸', 'title' => 'Tạo Snapshot thành công', 'desc' => 'Snapshot máy chủ ảo của bạn đã được tạo thành công', 'status' => 'Tạo thành công ✓'],
|
||||
'remove' => ['icon' => '🗑️', 'title' => 'Xóa Snapshot thành công', 'desc' => 'Snapshot máy chủ ảo của bạn đã được xóa thành công', 'status' => 'Xóa thành công ✓'],
|
||||
'revert' => ['icon' => '🔄', 'title' => 'Khôi phục Snapshot thành công', 'desc' => 'Máy chủ ảo của bạn đã được khôi phục về snapshot thành công', 'status' => 'Khôi phục thành công ✓'],
|
||||
];
|
||||
$label = $actionLabels[$action] ?? $actionLabels['create'];
|
||||
@endphp
|
||||
|
||||
<table style="border-collapse: collapse; width: 100%; background-color: #efefef;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding: 20px;" align="center" valign="top">
|
||||
<table style="padding-top: 20px; padding-bottom: 20px; border-collapse: collapse; background-color: #ffffff; width: 700px;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 700px;" valign="top">
|
||||
<table style="border-collapse: collapse; width: 100%;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="background-color: #f06824; padding: 34px 30px 30px; text-align: center; font-family: Arial, Helvetica, sans-serif; color: #ffffff;" align="center" valign="top" bgcolor="#f06824">
|
||||
<div style="font-size: 42px; line-height: 1; margin-bottom: 12px;">{{ $label['icon'] }}</div>
|
||||
<h1 style="margin: 0 0 8px; padding: 0; color: #ffffff; font-family: Arial, Helvetica, sans-serif; font-size: 24px; line-height: 1.35; font-weight: 700;">
|
||||
{{ $label['title'] }}
|
||||
</h1>
|
||||
<div style="font-size: 14px; line-height: 1.6; color: #ffffff;">
|
||||
{{ $label['desc'] }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; padding: 0 30px;" align="center" valign="top">
|
||||
<table style="border-collapse: collapse; background-color: #ffffff; width: 100%;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 15px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.7; color: #000000;" valign="top" height="15">
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: left;">Xin chào <strong>{{ $fullName }}</strong>,</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: left;">
|
||||
Thao tác snapshot máy chủ ảo của bạn tại <strong>{{ $appName }}</strong> đã hoàn tất.
|
||||
</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
<table style="border-collapse: collapse; width: 100%; background-color: #f9fafb; border: 1px dashed #d1d5db; border-radius: 6px;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding: 14px 18px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.8; color: #000000;">
|
||||
<div>Máy chủ: <strong style="font-family: 'Menlo','Consolas',monospace; color: #111827;">{{ $vmName }}</strong></div>
|
||||
<div>Snapshot: <strong style="font-family: 'Menlo','Consolas',monospace; color: #111827;">{{ $snapshotName }}</strong></div>
|
||||
<div>Thời gian: <strong style="font-family: 'Menlo','Consolas',monospace; color: #111827;">{{ $actionAt }}</strong></div>
|
||||
<div>Trạng thái: <strong style="color: #16a34a;">{{ $label['status'] }}</strong></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: left;">
|
||||
Bạn có thể đăng nhập vào cổng quản lý để kiểm tra trạng thái dịch vụ.
|
||||
</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: center;">
|
||||
<a style="display: inline-block; background-color: #f06824; color: #ffffff !important; text-decoration: none; padding: 12px 28px; border-radius: 3px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 700;" href="{{ $loginUrl }}" target="_blank" rel="noopener">
|
||||
Đăng nhập ngay
|
||||
</a>
|
||||
</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: left; color: #6b7280; font-size: 13px;">
|
||||
Nếu bạn có thắc mắc, vui lòng liên hệ với chúng tôi qua <strong>{{ $supportEmail }}</strong> hoặc <strong>{{ $supportPhone }}</strong>.
|
||||
</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
<div style="text-align: left; color: #666666; font-size: 13px;">
|
||||
Email này được gửi tự động. Vui lòng không trả lời email này.
|
||||
</div>
|
||||
<div style="text-align: left;"> </div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f06824; width: 700px; color: #ffffff;" valign="top" bgcolor="#f06824">
|
||||
<table style="border-collapse: collapse; background-color: #f06824; width: 100%; color: #ffffff;" border="0" cellspacing="0" cellpadding="0" align="left" bgcolor="#f06824">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding: 0;" width="100%">
|
||||
<table style="border-collapse: collapse; width: 100%;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 100%; height: 1px; background: #ffffff;" bgcolor="#ffffff" width="100%" height="1"><span style="font-size: 14px; color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height: 10px; color: #ffffff;" valign="top" height="10"><span style="font-size: 14px; color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 0; text-align: left; font-family: Helvetica, Arial, sans-serif; color: #ffffff; font-size: 16px; line-height: 150%;" align="center" valign="top">
|
||||
<table style="border-collapse: collapse; color: #ffffff;" border="0" cellspacing="0" cellpadding="0" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 3%; color: #ffffff;"><span style="color: #ffffff;"> </span></td>
|
||||
<td style="vertical-align: middle; text-align: center; padding: 5px 10px; border: 1px solid #ffffff; color: #ffffff;" valign="top">
|
||||
<a style="color: #ffffff; font-family: Helvetica, Arial, sans-serif; font-size: 10px; line-height: 1; font-weight: normal; text-transform: uppercase; word-wrap: break-word; text-decoration: none;" href="https://tgs.com.vn/premium-hosting/" target="_blank" rel="noopener"><span style="color: #ffffff;">Premium HOSTING</span></a>
|
||||
</td>
|
||||
<td style="width: 3%; color: #ffffff;"><span style="color: #ffffff;"> </span></td>
|
||||
<td style="vertical-align: middle; text-align: center; padding: 5px 10px; border: 1px solid #ffffff; color: #ffffff;" valign="top">
|
||||
<a style="color: #ffffff; font-family: Helvetica, Arial, sans-serif; font-size: 10px; line-height: 1; font-weight: normal; text-transform: uppercase; word-wrap: break-word; text-decoration: none;" href="https://tgs.com.vn/cloud-server/" target="_blank" rel="noopener"><span style="color: #ffffff;">Cloud SERVER</span></a>
|
||||
</td>
|
||||
<td style="width: 3%; color: #ffffff;"><span style="color: #ffffff;"> </span></td>
|
||||
<td style="vertical-align: middle; text-align: center; padding: 5px 10px; border: 1px solid #ffffff; color: #ffffff;" valign="top">
|
||||
<a style="color: #ffffff; font-family: Helvetica, Arial, sans-serif; font-size: 10px; line-height: 1; font-weight: normal; text-transform: uppercase; word-wrap: break-word; text-decoration: none;" href="https://cloudemail.vn/" target="_blank" rel="noopener"><span style="color: #ffffff;">EMAIL DOANH NGHIỆP</span></a>
|
||||
</td>
|
||||
<td style="width: 3%; color: #ffffff;"><span style="color: #ffffff;"> </span></td>
|
||||
<td style="vertical-align: middle; text-align: center; padding: 5px 10px; border: 1px solid #ffffff; color: #ffffff;" valign="top">
|
||||
<a style="color: #ffffff; font-family: Helvetica, Arial, sans-serif; font-size: 10px; line-height: 1; font-weight: normal; text-transform: uppercase; word-wrap: break-word; text-decoration: none;" href="https://tgs.com.vn/thiet-ke-website/" target="_blank" rel="noopener"><span style="color: #ffffff;">Thiết Kế WEBSITE</span></a>
|
||||
</td>
|
||||
<td style="width: 3%; color: #ffffff;"><span style="color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height: 10px; color: #ffffff;" valign="top" height="10"><span style="font-size: 14px; color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 0;" width="100%">
|
||||
<table style="border-collapse: collapse; width: 100%;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 100%; height: 1px; background: #ffffff;" bgcolor="#ffffff" width="100%" height="1"><span style="font-size: 14px; color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" bgcolor="#065d88">
|
||||
<table style="border-collapse: collapse; background-color: #f06824; border-top: 0; border-bottom: 0; width: 100%;" border="0" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 30px;">
|
||||
<td style="height: 30px;" valign="top" height="10"> </td>
|
||||
</tr>
|
||||
<tr style="height: 148px;">
|
||||
<td style="padding: 0; font-family: Helvetica, Arial, sans-serif; text-decoration: none; color: #e7e7e7; font-size: 16px; font-weight: normal; line-height: 150%; vertical-align: top; text-align: center; height: 148px;" align="center">
|
||||
<p style="margin: 0; padding: 0; font-family: Helvetica, Arial, sans-serif; color: white; font-size: 11pt; line-height: 200%;">
|
||||
<span style="color: #ffffff; font-family: 'times new roman', times, serif;"><strong style="font-size: 20px;">CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ THẾ GIỚI SỐ</strong></span><br>
|
||||
<span style="color: #ffffff; font-family: arial, helvetica, sans-serif; font-size: 12pt;">Địa chỉ: 128/38 Tân Hương, Phường Phú Thọ Hòa, Thành Phố Hồ Chí Minh</span><br>
|
||||
<span style="color: #ffffff; font-family: arial, helvetica, sans-serif; font-size: 12pt;">Tel: (028) 7309. 7379 - Tổng đài: {{ $supportPhone }}</span><br>
|
||||
<span style="font-family: arial, helvetica, sans-serif; font-size: 12pt;">Email: <span style="color: #ffffff;"><a style="color: #ffffff; text-decoration: none;" href="mailto:{{ $supportEmail }}">{{ $supportEmail }}</a></span></span><br>
|
||||
<span style="text-decoration: none; font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #ffffff !important;">
|
||||
<a style="color: #ffffff !important; text-decoration: none;" href="https://www.tgs.com.vn">www.TGS.com.vn</a> &
|
||||
<a style="color: #ffffff !important; text-decoration: none;" href="https://www.thegioiso.cloud">www.thegioiso.CLOUD</a> &
|
||||
<a style="color: #ffffff !important; text-decoration: none;" href="https://www.thegioiserver.com">www.thegioiSERVER.com</a> &
|
||||
<a style="color: #ffffff !important; text-decoration: none;" href="https://www.cloudemail.vn">www.CloudEmail.vn</a>
|
||||
</span>
|
||||
</p>
|
||||
<p style="margin: 0; padding: 0; font-family: Helvetica, Arial, sans-serif; color: white; font-size: 11pt; line-height: 200%;">
|
||||
<span style="text-decoration: none; font-family: 'times new roman', times, serif; color: #ffffff !important; font-size: 12pt;">
|
||||
<span style="color: #ffffff; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;">
|
||||
<span style="text-decoration: none; font-family: 'times new roman', times, serif; color: #ffffff !important;">
|
||||
<span style="font-family: arial, sans-serif;"><strong>🥇Thế Giới Số🥇</strong>- Premium HOSTING • CLOUD • SERVER & WEBSITE | 15+ năm Phụng Sự 🚀</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height: 30px; color: #ffffff;" valign="top" height="30"><span style="font-size: 14px; color: #ffffff;"> </span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
Reference in New Issue
Block a user