nuxt-layer-core 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/layers/solution/app/components/CoursesSection.vue +244 -244
- package/app/layers/solution/app/components/CtaSection.vue +3 -3
- package/app/layers/solution/app/components/FeaturesSection.vue +66 -66
- package/app/layers/solution/app/components/HeroSection.vue +3 -3
- package/app/layers/solution/app/components/LinuxVersionsSection.vue +1 -1
- package/app/layers/solution/app/components/PricingPlansSection.vue +396 -396
- package/app/layers/solution/app/components/RegistrationForm.vue +1 -1
- package/app/layers/solution/app/components/TestimonialsSection.vue +57 -57
- package/app/layers/solution/app/components/TheFooter.vue +60 -60
- package/app/layers/solution/app/components/TheHeader.vue +6 -6
- package/app/layers/solution/app/components/proxmox/HeroSection.vue +3 -3
- package/package.json +1 -1
|
@@ -1,245 +1,245 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<section id="dao-tao" class="py-24 bg-[#F7F9FB] border-t border-slate-200">
|
|
3
|
-
<div class="max-w-7xl mx-auto px-6 lg:px-8" id="chi-phi">
|
|
4
|
-
<div class="text-center mb-20">
|
|
5
|
-
<span
|
|
6
|
-
class="inline-block text-[#004AC6] font-bold uppercase tracking-widest text-xs mb-3 px-3 py-1 bg-blue-50 rounded-full">
|
|
7
|
-
Chương trình đào tạo
|
|
8
|
-
</span>
|
|
9
|
-
<h3 class="font-['Montserrat'] font-extrabold text-3xl sm:text-4xl text-slate-900 mb-4">
|
|
10
|
-
Các khóa đào tạo Proxmox VE
|
|
11
|
-
</h3>
|
|
12
|
-
<p class="text-slate-500 max-w-2xl mx-auto leading-relaxed">
|
|
13
|
-
Nội dung bám sát chương trình chính thức của Proxmox, kết hợp lý thuyết chuyên sâu và thực hành trên hệ thống
|
|
14
|
-
thực tế.
|
|
15
|
-
</p>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<div class="grid grid-cols-1
|
|
19
|
-
<div v-for="(plan, i) in formattedPlans" :key="plan.id" :data-delay="i * 150" class="course-card group relative"
|
|
20
|
-
:class="plan.highlight ? '
|
|
21
|
-
<!-- Glow nền cho card nổi bật -->
|
|
22
|
-
<div v-if="plan.highlight"
|
|
23
|
-
class="absolute -inset-3 bg-gradient-to-br from-[#004AC6]/25 via-blue-400/15 to-transparent rounded-[28px] blur-2xl opacity-70 -z-10">
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
<div
|
|
27
|
-
class="relative bg-white rounded-2xl flex flex-col overflow-hidden transition-all duration-300 ease-out h-full"
|
|
28
|
-
:class="plan.highlight
|
|
29
|
-
? 'ring-1 ring-[#004AC6]/15 shadow-[0_8px_30px_-6px_rgba(0,74,198,0.25)] hover:shadow-[0_20px_45px_-10px_rgba(0,74,198,0.35)] hover:-translate-y-1'
|
|
30
|
-
: 'ring-1 ring-slate-200 shadow-[0_2px_10px_-2px_rgba(15,23,42,0.06)] hover:ring-blue-200 hover:shadow-[0_12px_30px_-8px_rgba(15,23,42,0.12)] hover:-translate-y-1'
|
|
31
|
-
">
|
|
32
|
-
<div v-if="plan.highlight"
|
|
33
|
-
class="bg-gradient-to-r from-[#004AC6] to-[#1D63E0] text-white text-[11px] font-bold py-2.5 text-center uppercase tracking-widest flex items-center justify-center gap-1.5">
|
|
34
|
-
<Icon name="lucide:sparkles" class="w-3.5 h-3.5" />
|
|
35
|
-
Được tư vấn chọn nhiều nhất
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<div class="p-7 flex flex-col gap-5">
|
|
39
|
-
<div class="flex justify-between items-start">
|
|
40
|
-
<div
|
|
41
|
-
class="w-12 h-12 rounded-xl flex items-center justify-center transition-transform duration-300 group-hover:scale-105"
|
|
42
|
-
:class="plan.highlight
|
|
43
|
-
? 'bg-blue-50 text-[#004AC6] ring-4 ring-blue-50/70'
|
|
44
|
-
: 'bg-slate-50 text-slate-400'
|
|
45
|
-
">
|
|
46
|
-
<!-- <Icon :name="plan.icon" class="w-5 h-5" /> -->
|
|
47
|
-
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 34 512 444">
|
|
48
|
-
<path
|
|
49
|
-
d="M137.9 34.1c-10.5 0-19.7 1.9-28.5 5.7-8.6 3.8-16.2 8.9-22.9 15.6l170 186.4L426.1 55.3c-6.7-6.7-14.3-11.8-23.4-15.6-8.3-3.8-18-5.7-28-5.7-10.5 0-20.5 2.2-29.4 6.2-9.2 4-16.7 10-23.7 17l-65.2 72.2-66-72.2c-6.7-7-14.3-12.9-23.7-17-8.3-4-18.3-6.1-28.8-6.1M256.4 270l-170 186.7c6.7 6.5 14.3 11.8 22.9 15.6 8.9 3.8 18.1 5.7 28 5.7 11 0 20.5-2.4 29.4-6.2 9.4-4.3 17.5-10 24.2-17l65.5-72.2 65.4 72.2c6.7 7 14.3 12.7 23.4 17 8.9 3.8 18.6 6.2 29.4 6.2 10 0 19.7-1.9 28-5.7 9.2-3.8 16.7-9.2 23.4-15.6z"
|
|
50
|
-
style="fill-rule:evenodd;clip-rule:evenodd" />
|
|
51
|
-
<path
|
|
52
|
-
d="M56 90.1c-10.8.3-21.3 2.4-30.7 6.5-9.7 4-18 9.7-25.3 16.7L129.8 256 0 398.5c7.3 7.3 15.6 12.9 25.3 17.2 9.4 4.3 19.9 6.2 30.7 6.7 11.6-.5 22.4-2.4 32.3-7.3q15-6.9 25.8-18.6l128-140.5-127.9-140.3c-7.8-7.5-16.2-13.7-26.1-18.6-10-4.6-20.5-6.7-32.1-7m399.7 0c-11.6.3-21.8 2.4-31.8 7-10 4.8-18.6 11-26.1 18.6L270.4 256l127.4 140.6q11.25 11.7 26.1 18.6c10 4.8 20.2 6.7 31.8 7.3 11.6-.5 21.5-2.4 31-6.7 10.2-4.3 18-10 25.3-17.2L382.5 256 512 113.3c-7.3-7-15.1-12.7-25.3-16.7-9.4-4.1-19.4-6.2-31-6.5"
|
|
53
|
-
style="fill-rule:evenodd;clip-rule:evenodd;fill:#e57000" />
|
|
54
|
-
</svg>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<span class="text-[10px] font-bold uppercase tracking-wider px-2.5 py-1 rounded-full" :class="plan.highlight
|
|
58
|
-
? 'bg-blue-50 text-[#004AC6]'
|
|
59
|
-
: 'bg-slate-100 text-slate-500'
|
|
60
|
-
">
|
|
61
|
-
{{ formatLevel(plan.level) }}
|
|
62
|
-
</span>
|
|
63
|
-
</div>
|
|
64
|
-
|
|
65
|
-
<div>
|
|
66
|
-
<h4 class="font-bold text-xl text-slate-900 mb-2">
|
|
67
|
-
{{ plan.name }}
|
|
68
|
-
</h4>
|
|
69
|
-
<p class="text-slate-500 text-sm leading-relaxed">
|
|
70
|
-
{{ plan.description }}
|
|
71
|
-
</p>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<div class="pb-5 border-b border-slate-100">
|
|
75
|
-
<span class="font-['Montserrat'] font-extrabold text-2xl text-slate-900">
|
|
76
|
-
{{ plan.duration }}
|
|
77
|
-
</span>
|
|
78
|
-
<span class="text-slate-400 text-sm flex items-center gap-1.5 mt-2">
|
|
79
|
-
<Icon name="lucide:monitor-play" class="w-4 h-4" />
|
|
80
|
-
Online / thực hành
|
|
81
|
-
</span>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
<span class="text-[13px] text-slate-600 leading-loose [&_svg]:inline [&_svg]:text-[#004AC6]"
|
|
85
|
-
v-html="plan.included"></span>
|
|
86
|
-
|
|
87
|
-
<div v-if="plan.outcome" class="p-4 rounded-xl" :class="plan.highlight
|
|
88
|
-
? 'bg-gradient-to-br from-blue-50 to-indigo-50/60 border border-blue-100'
|
|
89
|
-
: 'bg-slate-50 border border-slate-100'
|
|
90
|
-
">
|
|
91
|
-
<span class="flex items-center gap-1.5 text-[10px] font-bold uppercase tracking-widest mb-2"
|
|
92
|
-
:class="plan.highlight ? 'text-[#004AC6]' : 'text-slate-500'">
|
|
93
|
-
<Icon name="lucide:target" class="w-3.5 h-3.5" />
|
|
94
|
-
Kết quả đạt được
|
|
95
|
-
</span>
|
|
96
|
-
<p class="text-xs leading-relaxed font-semibold"
|
|
97
|
-
:class="plan.highlight ? 'text-blue-900' : 'text-slate-700'">
|
|
98
|
-
{{ plan.outcome }}
|
|
99
|
-
</p>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
|
|
103
|
-
<div v-if="isConsultant" class="p-7 pt-2 mt-auto">
|
|
104
|
-
<button @click="handleSelectPlan(plan)"
|
|
105
|
-
class="w-full py-3.5 rounded-xl font-bold text-sm transition-all duration-300 cursor-pointer" :class="plan.highlight
|
|
106
|
-
? 'bg-[#004AC6] text-white shadow-lg shadow-blue-500/25 hover:bg-[#1D4ED8] hover:shadow-blue-500/40'
|
|
107
|
-
: 'border border-slate-200 text-slate-600 hover:border-[#004AC6] hover:text-[#004AC6] hover:bg-blue-50/50'
|
|
108
|
-
">
|
|
109
|
-
Liên hệ tư vấn
|
|
110
|
-
</button>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
</section>
|
|
117
|
-
</template>
|
|
118
|
-
|
|
119
|
-
<script setup>
|
|
120
|
-
useScrollAnimate('.course-card', 'fade-up')
|
|
121
|
-
|
|
122
|
-
const props = defineProps({
|
|
123
|
-
targetCTA: { type: String, default: '' },
|
|
124
|
-
slug: { type: String, default: '' },
|
|
125
|
-
itemId01Groups01: { type: Object, default: null },
|
|
126
|
-
itemId02Groups01: { type: Object, default: null },
|
|
127
|
-
itemId03Groups01: { type: Object, default: null },
|
|
128
|
-
itemId01Groups02: { type: Object, default: null },
|
|
129
|
-
itemId02Groups02: { type: Object, default: null },
|
|
130
|
-
itemId03Groups02: { type: Object, default: null },
|
|
131
|
-
itemId01Groups03: { type: Object, default: null },
|
|
132
|
-
itemId02Groups03: { type: Object, default: null },
|
|
133
|
-
itemId03Groups03: { type: Object, default: null },
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
const isConsultant = computed(() => props.targetCTA === 'CONSULTANT')
|
|
137
|
-
const router = useRouter()
|
|
138
|
-
|
|
139
|
-
function handleSelectPlan(plan) {
|
|
140
|
-
router.push({
|
|
141
|
-
path: `/tu-van/khoa-hoc-proxmox`,
|
|
142
|
-
query: {
|
|
143
|
-
plan: plan.id,
|
|
144
|
-
name: plan.name,
|
|
145
|
-
level: plan.level,
|
|
146
|
-
duration: plan.duration,
|
|
147
|
-
description: plan.description || '',
|
|
148
|
-
},
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function formatLevel(level) {
|
|
153
|
-
const labels = {
|
|
154
|
-
basic: 'Cơ bản',
|
|
155
|
-
advanced: 'Nâng cao',
|
|
156
|
-
expert: 'Chuyên gia',
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return labels[level || ''] || level || ''
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const samplePlans = [
|
|
163
|
-
{
|
|
164
|
-
id: 'sample-1',
|
|
165
|
-
name: 'Deployment & Management',
|
|
166
|
-
icon: 'lucide:graduation-cap',
|
|
167
|
-
level: 'Nền tảng',
|
|
168
|
-
duration: '14 giờ · Từ 2 buổi',
|
|
169
|
-
description: 'Dành cho IT admin, kỹ sư hệ thống cần triển khai và quản trị ảo hóa trên máy chủ đơn.',
|
|
170
|
-
included: [
|
|
171
|
-
'Kiến trúc, cài đặt & thiết lập hệ thống',
|
|
172
|
-
'Cấu hình mạng (Bridge, VLAN, SDN)',
|
|
173
|
-
'Lưu trữ nội bộ & quản lý VM/LXC',
|
|
174
|
-
'Backup & Restore qua giao diện/CLI',
|
|
175
|
-
'Phân quyền, xác thực & Tường lửa',
|
|
176
|
-
'Chuyển đổi V2V và P2V'
|
|
177
|
-
],
|
|
178
|
-
highlight: false,
|
|
179
|
-
outcome: 'Thành thạo triển khai, vận hành, sao lưu và xử lý sự cố trên máy chủ đơn lẻ.'
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
id: 'sample-2',
|
|
183
|
-
name: 'Clustering & Shared Storage',
|
|
184
|
-
icon: 'lucide:network',
|
|
185
|
-
level: 'Chuyên sâu',
|
|
186
|
-
duration: '14 giờ · Từ 2 buổi',
|
|
187
|
-
description: 'Kỹ sư cần xây dựng cụm, triển khai HA, Ceph và tối ưu hóa tài nguyên diện rộng.',
|
|
188
|
-
included: [
|
|
189
|
-
'Kiến trúc cụm (Corosync, pmxcfs)',
|
|
190
|
-
'Triển khai lưu trữ siêu hội tụ Ceph',
|
|
191
|
-
'Tính sẵn sàng cao (HA) cho VM/LXC',
|
|
192
|
-
'Nhân bản đĩa ZFS (Replication)',
|
|
193
|
-
'Kịch bản sự cố & QDevice tiebreaker',
|
|
194
|
-
'Tự động hóa với REST API & CLI'
|
|
195
|
-
],
|
|
196
|
-
highlight: true,
|
|
197
|
-
outcome: 'Đủ năng lực quản trị cụm nhiều node, lưu trữ phân tán Ceph và duy trì HA an toàn.'
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
id: 'sample-3',
|
|
201
|
-
name: 'Proxmox VE Bundle',
|
|
202
|
-
icon: 'lucide:package',
|
|
203
|
-
level: 'Trọn gói',
|
|
204
|
-
duration: '28 giờ · Từ 4-5 buổi',
|
|
205
|
-
description: 'Deep dive nền tảng toàn diện: bao trọn kiến thức từ máy chủ đơn đến cụm phức tạp.',
|
|
206
|
-
included: [
|
|
207
|
-
'Trọn bộ nội dung khóa Nền tảng',
|
|
208
|
-
'Trọn bộ nội dung khóa Chuyên sâu',
|
|
209
|
-
'Lab thực hành với môi trường thực tế',
|
|
210
|
-
'Hướng dẫn xử lý các ca lỗi production'
|
|
211
|
-
],
|
|
212
|
-
highlight: false,
|
|
213
|
-
outcome: 'Trở thành chuyên gia Proxmox thực thụ, sẵn sàng thi chứng chỉ và quản trị hạ tầng quy mô lớn.'
|
|
214
|
-
}
|
|
215
|
-
]
|
|
216
|
-
|
|
217
|
-
const rawItems = computed(() => [
|
|
218
|
-
props.itemId01Groups01,
|
|
219
|
-
props.itemId02Groups01,
|
|
220
|
-
props.itemId03Groups01,
|
|
221
|
-
props.itemId01Groups02,
|
|
222
|
-
props.itemId02Groups02,
|
|
223
|
-
props.itemId03Groups02,
|
|
224
|
-
props.itemId01Groups03,
|
|
225
|
-
props.itemId02Groups03,
|
|
226
|
-
props.itemId03Groups03,
|
|
227
|
-
])
|
|
228
|
-
|
|
229
|
-
const formattedPlans = computed(() => {
|
|
230
|
-
const items = rawItems.value.map(normalizePlanItem).filter(Boolean)
|
|
231
|
-
if (!items.length) return samplePlans
|
|
232
|
-
|
|
233
|
-
return items.map((item, index) => ({
|
|
234
|
-
id: item.id || `plan-${index}`,
|
|
235
|
-
name: item.name,
|
|
236
|
-
level: item.level,
|
|
237
|
-
duration: item.duration,
|
|
238
|
-
description: item.description,
|
|
239
|
-
included: item.features,
|
|
240
|
-
icon: item.icon,
|
|
241
|
-
highlight: index === 1,
|
|
242
|
-
outcome: '',
|
|
243
|
-
}))
|
|
244
|
-
})
|
|
1
|
+
<template>
|
|
2
|
+
<section id="dao-tao" class="py-24 bg-[#F7F9FB] border-t border-slate-200">
|
|
3
|
+
<div class="max-w-7xl mx-auto px-6 lg:px-8" id="chi-phi">
|
|
4
|
+
<div class="text-center mb-20">
|
|
5
|
+
<span
|
|
6
|
+
class="inline-block text-[#004AC6] font-bold uppercase tracking-widest text-xs mb-3 px-3 py-1 bg-blue-50 rounded-full">
|
|
7
|
+
Chương trình đào tạo
|
|
8
|
+
</span>
|
|
9
|
+
<h3 class="font-['Montserrat'] font-extrabold text-3xl sm:text-4xl text-slate-900 mb-4">
|
|
10
|
+
Các khóa đào tạo Proxmox VE
|
|
11
|
+
</h3>
|
|
12
|
+
<p class="text-slate-500 max-w-2xl mx-auto leading-relaxed">
|
|
13
|
+
Nội dung bám sát chương trình chính thức của Proxmox, kết hợp lý thuyết chuyên sâu và thực hành trên hệ thống
|
|
14
|
+
thực tế.
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 lg:gap-8">
|
|
19
|
+
<div v-for="(plan, i) in formattedPlans" :key="plan.id" :data-delay="i * 150" class="course-card group relative"
|
|
20
|
+
:class="plan.highlight ? 'lg:-mt-6' : 'lg:mt-0'">
|
|
21
|
+
<!-- Glow nền cho card nổi bật -->
|
|
22
|
+
<div v-if="plan.highlight"
|
|
23
|
+
class="absolute -inset-3 bg-gradient-to-br from-[#004AC6]/25 via-blue-400/15 to-transparent rounded-[28px] blur-2xl opacity-70 -z-10">
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div
|
|
27
|
+
class="relative bg-white rounded-2xl flex flex-col overflow-hidden transition-all duration-300 ease-out h-full"
|
|
28
|
+
:class="plan.highlight
|
|
29
|
+
? 'ring-1 ring-[#004AC6]/15 shadow-[0_8px_30px_-6px_rgba(0,74,198,0.25)] hover:shadow-[0_20px_45px_-10px_rgba(0,74,198,0.35)] hover:-translate-y-1'
|
|
30
|
+
: 'ring-1 ring-slate-200 shadow-[0_2px_10px_-2px_rgba(15,23,42,0.06)] hover:ring-blue-200 hover:shadow-[0_12px_30px_-8px_rgba(15,23,42,0.12)] hover:-translate-y-1'
|
|
31
|
+
">
|
|
32
|
+
<div v-if="plan.highlight"
|
|
33
|
+
class="bg-gradient-to-r from-[#004AC6] to-[#1D63E0] text-white text-[11px] font-bold py-2.5 text-center uppercase tracking-widest flex items-center justify-center gap-1.5">
|
|
34
|
+
<Icon name="lucide:sparkles" class="w-3.5 h-3.5" />
|
|
35
|
+
Được tư vấn chọn nhiều nhất
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="p-7 flex flex-col gap-5">
|
|
39
|
+
<div class="flex justify-between items-start">
|
|
40
|
+
<div
|
|
41
|
+
class="w-12 h-12 rounded-xl flex items-center justify-center transition-transform duration-300 group-hover:scale-105"
|
|
42
|
+
:class="plan.highlight
|
|
43
|
+
? 'bg-blue-50 text-[#004AC6] ring-4 ring-blue-50/70'
|
|
44
|
+
: 'bg-slate-50 text-slate-400'
|
|
45
|
+
">
|
|
46
|
+
<!-- <Icon :name="plan.icon" class="w-5 h-5" /> -->
|
|
47
|
+
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 34 512 444">
|
|
48
|
+
<path
|
|
49
|
+
d="M137.9 34.1c-10.5 0-19.7 1.9-28.5 5.7-8.6 3.8-16.2 8.9-22.9 15.6l170 186.4L426.1 55.3c-6.7-6.7-14.3-11.8-23.4-15.6-8.3-3.8-18-5.7-28-5.7-10.5 0-20.5 2.2-29.4 6.2-9.2 4-16.7 10-23.7 17l-65.2 72.2-66-72.2c-6.7-7-14.3-12.9-23.7-17-8.3-4-18.3-6.1-28.8-6.1M256.4 270l-170 186.7c6.7 6.5 14.3 11.8 22.9 15.6 8.9 3.8 18.1 5.7 28 5.7 11 0 20.5-2.4 29.4-6.2 9.4-4.3 17.5-10 24.2-17l65.5-72.2 65.4 72.2c6.7 7 14.3 12.7 23.4 17 8.9 3.8 18.6 6.2 29.4 6.2 10 0 19.7-1.9 28-5.7 9.2-3.8 16.7-9.2 23.4-15.6z"
|
|
50
|
+
style="fill-rule:evenodd;clip-rule:evenodd" />
|
|
51
|
+
<path
|
|
52
|
+
d="M56 90.1c-10.8.3-21.3 2.4-30.7 6.5-9.7 4-18 9.7-25.3 16.7L129.8 256 0 398.5c7.3 7.3 15.6 12.9 25.3 17.2 9.4 4.3 19.9 6.2 30.7 6.7 11.6-.5 22.4-2.4 32.3-7.3q15-6.9 25.8-18.6l128-140.5-127.9-140.3c-7.8-7.5-16.2-13.7-26.1-18.6-10-4.6-20.5-6.7-32.1-7m399.7 0c-11.6.3-21.8 2.4-31.8 7-10 4.8-18.6 11-26.1 18.6L270.4 256l127.4 140.6q11.25 11.7 26.1 18.6c10 4.8 20.2 6.7 31.8 7.3 11.6-.5 21.5-2.4 31-6.7 10.2-4.3 18-10 25.3-17.2L382.5 256 512 113.3c-7.3-7-15.1-12.7-25.3-16.7-9.4-4.1-19.4-6.2-31-6.5"
|
|
53
|
+
style="fill-rule:evenodd;clip-rule:evenodd;fill:#e57000" />
|
|
54
|
+
</svg>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<span class="text-[10px] font-bold uppercase tracking-wider px-2.5 py-1 rounded-full" :class="plan.highlight
|
|
58
|
+
? 'bg-blue-50 text-[#004AC6]'
|
|
59
|
+
: 'bg-slate-100 text-slate-500'
|
|
60
|
+
">
|
|
61
|
+
{{ formatLevel(plan.level) }}
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div>
|
|
66
|
+
<h4 class="font-bold text-xl text-slate-900 mb-2">
|
|
67
|
+
{{ plan.name }}
|
|
68
|
+
</h4>
|
|
69
|
+
<p class="text-slate-500 text-sm leading-relaxed">
|
|
70
|
+
{{ plan.description }}
|
|
71
|
+
</p>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="pb-5 border-b border-slate-100">
|
|
75
|
+
<span class="font-['Montserrat'] font-extrabold text-2xl text-slate-900">
|
|
76
|
+
{{ plan.duration }}
|
|
77
|
+
</span>
|
|
78
|
+
<span class="text-slate-400 text-sm flex items-center gap-1.5 mt-2">
|
|
79
|
+
<Icon name="lucide:monitor-play" class="w-4 h-4" />
|
|
80
|
+
Online / thực hành
|
|
81
|
+
</span>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<span class="text-[13px] text-slate-600 leading-loose [&_svg]:inline [&_svg]:text-[#004AC6]"
|
|
85
|
+
v-html="plan.included"></span>
|
|
86
|
+
|
|
87
|
+
<div v-if="plan.outcome" class="p-4 rounded-xl" :class="plan.highlight
|
|
88
|
+
? 'bg-gradient-to-br from-blue-50 to-indigo-50/60 border border-blue-100'
|
|
89
|
+
: 'bg-slate-50 border border-slate-100'
|
|
90
|
+
">
|
|
91
|
+
<span class="flex items-center gap-1.5 text-[10px] font-bold uppercase tracking-widest mb-2"
|
|
92
|
+
:class="plan.highlight ? 'text-[#004AC6]' : 'text-slate-500'">
|
|
93
|
+
<Icon name="lucide:target" class="w-3.5 h-3.5" />
|
|
94
|
+
Kết quả đạt được
|
|
95
|
+
</span>
|
|
96
|
+
<p class="text-xs leading-relaxed font-semibold"
|
|
97
|
+
:class="plan.highlight ? 'text-blue-900' : 'text-slate-700'">
|
|
98
|
+
{{ plan.outcome }}
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div v-if="isConsultant" class="p-7 pt-2 mt-auto">
|
|
104
|
+
<button @click="handleSelectPlan(plan)"
|
|
105
|
+
class="w-full py-3.5 rounded-xl font-bold text-sm transition-all duration-300 cursor-pointer" :class="plan.highlight
|
|
106
|
+
? 'bg-[#004AC6] text-white shadow-lg shadow-blue-500/25 hover:bg-[#1D4ED8] hover:shadow-blue-500/40'
|
|
107
|
+
: 'border border-slate-200 text-slate-600 hover:border-[#004AC6] hover:text-[#004AC6] hover:bg-blue-50/50'
|
|
108
|
+
">
|
|
109
|
+
Liên hệ tư vấn
|
|
110
|
+
</button>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</section>
|
|
117
|
+
</template>
|
|
118
|
+
|
|
119
|
+
<script setup>
|
|
120
|
+
useScrollAnimate('.course-card', 'fade-up')
|
|
121
|
+
|
|
122
|
+
const props = defineProps({
|
|
123
|
+
targetCTA: { type: String, default: '' },
|
|
124
|
+
slug: { type: String, default: '' },
|
|
125
|
+
itemId01Groups01: { type: Object, default: null },
|
|
126
|
+
itemId02Groups01: { type: Object, default: null },
|
|
127
|
+
itemId03Groups01: { type: Object, default: null },
|
|
128
|
+
itemId01Groups02: { type: Object, default: null },
|
|
129
|
+
itemId02Groups02: { type: Object, default: null },
|
|
130
|
+
itemId03Groups02: { type: Object, default: null },
|
|
131
|
+
itemId01Groups03: { type: Object, default: null },
|
|
132
|
+
itemId02Groups03: { type: Object, default: null },
|
|
133
|
+
itemId03Groups03: { type: Object, default: null },
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const isConsultant = computed(() => props.targetCTA === 'CONSULTANT')
|
|
137
|
+
const router = useRouter()
|
|
138
|
+
|
|
139
|
+
function handleSelectPlan(plan) {
|
|
140
|
+
router.push({
|
|
141
|
+
path: `/tu-van/khoa-hoc-proxmox`,
|
|
142
|
+
query: {
|
|
143
|
+
plan: plan.id,
|
|
144
|
+
name: plan.name,
|
|
145
|
+
level: plan.level,
|
|
146
|
+
duration: plan.duration,
|
|
147
|
+
description: plan.description || '',
|
|
148
|
+
},
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function formatLevel(level) {
|
|
153
|
+
const labels = {
|
|
154
|
+
basic: 'Cơ bản',
|
|
155
|
+
advanced: 'Nâng cao',
|
|
156
|
+
expert: 'Chuyên gia',
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return labels[level || ''] || level || ''
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const samplePlans = [
|
|
163
|
+
{
|
|
164
|
+
id: 'sample-1',
|
|
165
|
+
name: 'Deployment & Management',
|
|
166
|
+
icon: 'lucide:graduation-cap',
|
|
167
|
+
level: 'Nền tảng',
|
|
168
|
+
duration: '14 giờ · Từ 2 buổi',
|
|
169
|
+
description: 'Dành cho IT admin, kỹ sư hệ thống cần triển khai và quản trị ảo hóa trên máy chủ đơn.',
|
|
170
|
+
included: [
|
|
171
|
+
'Kiến trúc, cài đặt & thiết lập hệ thống',
|
|
172
|
+
'Cấu hình mạng (Bridge, VLAN, SDN)',
|
|
173
|
+
'Lưu trữ nội bộ & quản lý VM/LXC',
|
|
174
|
+
'Backup & Restore qua giao diện/CLI',
|
|
175
|
+
'Phân quyền, xác thực & Tường lửa',
|
|
176
|
+
'Chuyển đổi V2V và P2V'
|
|
177
|
+
],
|
|
178
|
+
highlight: false,
|
|
179
|
+
outcome: 'Thành thạo triển khai, vận hành, sao lưu và xử lý sự cố trên máy chủ đơn lẻ.'
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
id: 'sample-2',
|
|
183
|
+
name: 'Clustering & Shared Storage',
|
|
184
|
+
icon: 'lucide:network',
|
|
185
|
+
level: 'Chuyên sâu',
|
|
186
|
+
duration: '14 giờ · Từ 2 buổi',
|
|
187
|
+
description: 'Kỹ sư cần xây dựng cụm, triển khai HA, Ceph và tối ưu hóa tài nguyên diện rộng.',
|
|
188
|
+
included: [
|
|
189
|
+
'Kiến trúc cụm (Corosync, pmxcfs)',
|
|
190
|
+
'Triển khai lưu trữ siêu hội tụ Ceph',
|
|
191
|
+
'Tính sẵn sàng cao (HA) cho VM/LXC',
|
|
192
|
+
'Nhân bản đĩa ZFS (Replication)',
|
|
193
|
+
'Kịch bản sự cố & QDevice tiebreaker',
|
|
194
|
+
'Tự động hóa với REST API & CLI'
|
|
195
|
+
],
|
|
196
|
+
highlight: true,
|
|
197
|
+
outcome: 'Đủ năng lực quản trị cụm nhiều node, lưu trữ phân tán Ceph và duy trì HA an toàn.'
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
id: 'sample-3',
|
|
201
|
+
name: 'Proxmox VE Bundle',
|
|
202
|
+
icon: 'lucide:package',
|
|
203
|
+
level: 'Trọn gói',
|
|
204
|
+
duration: '28 giờ · Từ 4-5 buổi',
|
|
205
|
+
description: 'Deep dive nền tảng toàn diện: bao trọn kiến thức từ máy chủ đơn đến cụm phức tạp.',
|
|
206
|
+
included: [
|
|
207
|
+
'Trọn bộ nội dung khóa Nền tảng',
|
|
208
|
+
'Trọn bộ nội dung khóa Chuyên sâu',
|
|
209
|
+
'Lab thực hành với môi trường thực tế',
|
|
210
|
+
'Hướng dẫn xử lý các ca lỗi production'
|
|
211
|
+
],
|
|
212
|
+
highlight: false,
|
|
213
|
+
outcome: 'Trở thành chuyên gia Proxmox thực thụ, sẵn sàng thi chứng chỉ và quản trị hạ tầng quy mô lớn.'
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
const rawItems = computed(() => [
|
|
218
|
+
props.itemId01Groups01,
|
|
219
|
+
props.itemId02Groups01,
|
|
220
|
+
props.itemId03Groups01,
|
|
221
|
+
props.itemId01Groups02,
|
|
222
|
+
props.itemId02Groups02,
|
|
223
|
+
props.itemId03Groups02,
|
|
224
|
+
props.itemId01Groups03,
|
|
225
|
+
props.itemId02Groups03,
|
|
226
|
+
props.itemId03Groups03,
|
|
227
|
+
])
|
|
228
|
+
|
|
229
|
+
const formattedPlans = computed(() => {
|
|
230
|
+
const items = rawItems.value.map(normalizePlanItem).filter(Boolean)
|
|
231
|
+
if (!items.length) return samplePlans
|
|
232
|
+
|
|
233
|
+
return items.map((item, index) => ({
|
|
234
|
+
id: item.id || `plan-${index}`,
|
|
235
|
+
name: item.name,
|
|
236
|
+
level: item.level,
|
|
237
|
+
duration: item.duration,
|
|
238
|
+
description: item.description,
|
|
239
|
+
included: item.features,
|
|
240
|
+
icon: item.icon,
|
|
241
|
+
highlight: index === 1,
|
|
242
|
+
outcome: '',
|
|
243
|
+
}))
|
|
244
|
+
})
|
|
245
245
|
</script>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<section id="lien-he" class="py-24 bg-white border-t border-slate-200">
|
|
3
3
|
<div class="max-w-7xl mx-auto px-6 lg:px-8">
|
|
4
|
-
<div class="cta-card bg-[#F7F9FB] rounded-3xl flex flex-col
|
|
4
|
+
<div class="cta-card bg-[#F7F9FB] rounded-3xl flex flex-col lg:flex-row shadow-2xl">
|
|
5
5
|
<div
|
|
6
|
-
class="
|
|
6
|
+
class="lg:w-5/12 rounded-t-3xl bg-gradient-to-br from-[#004AC6] to-[#1D4ED8] p-6 text-white space-y-6 sm:p-10 sm:space-y-8 lg:rounded-tr-none lg:rounded-bl-3xl lg:p-12">
|
|
7
7
|
<p class="text-xs font-bold uppercase tracking-widest text-blue-100">Bắt đầu</p>
|
|
8
8
|
<h3 class="font-['Montserrat'] font-extrabold text-2xl sm:text-3xl leading-tight">
|
|
9
9
|
Đặt lịch tư vấn khóa học miễn phí, 30 phút
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
</div>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
|
-
<div class="
|
|
29
|
+
<div class="lg:w-7/12 rounded-b-3xl bg-white p-6 sm:p-10 lg:rounded-bl-none lg:rounded-tr-3xl lg:p-12">
|
|
30
30
|
<form class="space-y-5" @submit.prevent="handleSubmit" novalidate>
|
|
31
31
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
|
32
32
|
<div class="space-y-1.5">
|