diff --git a/README.md b/README.md index 78ce750..e0e5970 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,30 @@ Website tĩnh (Ladipage). Cần chạy qua **web server cục bộ** — không 2. Trình duyệt sẽ mở: `http://localhost:8080/www.mewedding.vn/index.html` 3. Dừng server: nhấn `Ctrl+C` trong cửa sổ đen (hoặc đóng cửa sổ). +## Mở qua WiFi (điện thoại / máy khác cùng mạng) + +1. Máy tính và điện thoại **cùng WiFi** (không dùng guest network chặn LAN). +2. Chạy **`start.bat`** — cửa sổ PowerShell in thêm dòng dạng: + `http://192.168.x.x:8080/www.mewedding.vn/index.html` +3. Trên điện thoại, mở đúng URL đó (thay `192.168.x.x` bằng IP hiện in ra). +4. **Điện thoại không vào được** (hay gặp nhất): + - Chạy lại **`setup-wifi.ps1`** (Admin) — script mở **firewall cổng 8080** và đặt Wi-Fi sang **Private**. + - Trên điện thoại dùng đúng URL dòng **`>>> DIEN THOAI`** (thường `http://192.168.1.x:8080/...`), không dùng `localhost`. + - Điện thoại **tắt 4G/5G**, chỉ dùng WiFi cùng nhà; tắt VPN trên PC/điện thoại. + - Router: tắt **AP isolation / client isolation** nếu bật. + - Cửa sổ `start.bat` có dòng `192.168.x.x -> ...` khi điện thoại truy cập → server nhận được; không có dòng → firewall/router chặn. +6. **Ảnh không hiện trên điện thoại:** trang cần **internet** cho font/icon LadiPage (`https://w.ladicdn.com`). Ảnh trong thư mục `w.ladicdn.com` tải từ máy tính — nếu vẫn trống, xem cửa sổ server có dòng `[404]` (sai đường dẫn). Tải lại trang sau khi chạy lại `start.bat`. +5. Lần đầu bind cổng lỗi: chạy **một lần** (PowerShell **Admin**), trong thư mục dự án: + ```powershell + cd "E:\WD\WD-HN" + powershell -ExecutionPolicy Bypass -File .\setup-wifi.ps1 + ``` + Hoặc lệnh tay (**không** dùng `%USERNAME%` trong PowerShell — sẽ lỗi 1332): + ```powershell + netsh http add urlacl url=http://+:8080/ user="$env:USERDOMAIN\$env:USERNAME" + ``` + Trong **CMD (Admin)** thì dùng được: `netsh http add urlacl url=http://+:8080/ user=%USERNAME%` + ## Chạy bằng PowerShell ```powershell diff --git a/kill-server.ps1 b/kill-server.ps1 new file mode 100644 index 0000000..d630bc2 --- /dev/null +++ b/kill-server.ps1 @@ -0,0 +1,7 @@ +Get-CimInstance Win32_Process | + Where-Object { $_.CommandLine -like '*serve.ps1*' } | + ForEach-Object { + Write-Host "Dung PID $($_.ProcessId)" + Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue + } +Start-Sleep -Seconds 2 diff --git a/mo-firewall.bat b/mo-firewall.bat new file mode 100644 index 0000000..00bd489 --- /dev/null +++ b/mo-firewall.bat @@ -0,0 +1,8 @@ +@echo off +chcp 65001 >nul +cd /d "%~dp0" +echo. +echo Dang mo firewall cong 8080 (can cua so Admin)... +echo. +powershell -NoProfile -Command "Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File \"\"%~dp0setup-wifi.ps1\"\"'" +timeout /t 3 >nul diff --git a/restart.bat b/restart.bat new file mode 100644 index 0000000..0053650 --- /dev/null +++ b/restart.bat @@ -0,0 +1,9 @@ +@echo off +chcp 65001 >nul +cd /d "%~dp0" +echo. +echo Dang dung server cu (neu co)... +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0kill-server.ps1" +echo. +echo Dang khoi dong lai... +start "Thiep cuoi" powershell -NoProfile -ExecutionPolicy Bypass -NoExit -File "%~dp0serve.ps1" diff --git a/serve.ps1 b/serve.ps1 index 21da04a..e6660d5 100644 --- a/serve.ps1 +++ b/serve.ps1 @@ -1,7 +1,9 @@ # Simple static file server for the wedding site (Windows, no Node/Python required) +# Listens on localhost + LAN IPs so phones on the same WiFi can open the site. $ErrorActionPreference = "Stop" $root = $PSScriptRoot $port = 8080 +$sitePath = "/www.mewedding.vn/index.html" $mime = @{ ".html" = "text/html; charset=utf-8" @@ -30,71 +32,208 @@ function Get-ContentType([string]$path) { return "application/octet-stream" } -function Send-File([System.Net.HttpListenerContext]$ctx, [string]$filePath) { - $bytes = [System.IO.File]::ReadAllBytes($filePath) - $ctx.Response.ContentType = Get-ContentType $filePath +function Send-File([System.Net.HttpListenerContext]$ctx, [string]$filePath, [string]$extraContentType = $null) { + $bytes = if ($extraContentType -eq 'text/html') { + $text = [System.IO.File]::ReadAllText($filePath, [Text.UTF8Encoding]::new($false)) + if ($text -notmatch '', ('' + "`n ") + } + [Text.Encoding]::UTF8.GetBytes($text) + } else { + [System.IO.File]::ReadAllBytes($filePath) + } + $ctx.Response.ContentType = if ($extraContentType) { $extraContentType } else { Get-ContentType $filePath } + $ctx.Response.Headers.Add('Cache-Control', 'public, max-age=3600') $ctx.Response.ContentLength64 = $bytes.Length $ctx.Response.OutputStream.Write($bytes, 0, $bytes.Length) } -$listener = New-Object System.Net.HttpListener -$listener.Prefixes.Add("http://localhost:$port/") -$listener.Start() +function Resolve-StaticFile([string]$root, [string]$rawPath) { + $rel = [System.Uri]::UnescapeDataString($rawPath).TrimStart('/').Replace('/', [IO.Path]::DirectorySeparatorChar) + $candidates = @( + $rel, + ($rel -replace '%20', ' '), + ($rel -replace '\\ ', ' ') + ) | Select-Object -Unique -$url = "http://localhost:$port/www.mewedding.vn/index.html" -Write-Host "" -Write-Host " Thiep cuoi dang chay tai:" -ForegroundColor Green -Write-Host " $url" -ForegroundColor Cyan -Write-Host "" -Write-Host " Nhan Ctrl+C de dung server." -ForegroundColor DarkGray -Write-Host "" + $rootFull = [IO.Path]::GetFullPath($root) + foreach ($c in $candidates) { + if ([string]::IsNullOrWhiteSpace($c)) { continue } + $fp = [IO.Path]::GetFullPath((Join-Path $root $c)) + if ($fp.StartsWith($rootFull, [StringComparison]::OrdinalIgnoreCase) -and (Test-Path $fp -PathType Leaf)) { + return $fp + } + } + + # Tim file theo ten (ho tro ten co dau / khoang trang khac encoding) + $leaf = Split-Path $rel -Leaf + $parent = Split-Path (Join-Path $root $rel) -Parent + if ($leaf -and (Test-Path $parent -PathType Container)) { + $decodedLeaf = [System.Uri]::UnescapeDataString($leaf.Replace('+', ' ')) + $hit = Get-ChildItem -LiteralPath $parent -File -ErrorAction SilentlyContinue | + Where-Object { $_.Name -eq $decodedLeaf -or $_.Name -eq $leaf } | + Select-Object -First 1 + if ($hit) { return $hit.FullName } + } + return $null +} + +function Test-ValidLanIPv4([string]$ip) { + return $ip -match '^\d{1,3}(\.\d{1,3}){3}$' -and + $ip -notmatch '^127\.' -and + $ip -notmatch '^169\.254\.' +} + +function Get-LanIPv4Addresses { + $rows = @() + try { + $rows = @(Get-NetIPAddress -AddressFamily IPv4 -ErrorAction Stop | + Where-Object { Test-ValidLanIPv4 $_.IPAddress }) + } + catch { + $hostEntry = [System.Net.Dns]::GetHostEntry([System.Net.Dns]::GetHostName()) + foreach ($a in $hostEntry.AddressList) { + if ($a.AddressFamily -eq 'InterNetwork') { + $ip = $a.ToString() + if (Test-ValidLanIPv4 $ip) { + $rows += [PSCustomObject]@{ IPAddress = $ip; InterfaceAlias = 'Unknown' } + } + } + } + } + + # Bo VPN / adapter ao + $rows = @($rows | Where-Object { + $_.InterfaceAlias -notmatch 'VPN|OpenVPN|TAP|TUN|Hyper-V|Virtual|Loopback|vEthernet' -and + $_.InterfaceAlias -notmatch 'Connection\s*\*' + }) + + $wifi = @($rows | Where-Object { $_.InterfaceAlias -match 'Wi-?Fi' } | ForEach-Object { $_.IPAddress } | Select-Object -Unique) + $eth = @($rows | Where-Object { $_.InterfaceAlias -match 'Ethernet' -and $_.InterfaceAlias -notmatch 'Virtual' } | + ForEach-Object { $_.IPAddress } | Select-Object -Unique) + $other = @($rows | ForEach-Object { $_.IPAddress } | Where-Object { $_ -notin $wifi -and $_ -notin $eth } | Select-Object -Unique) + + return @($wifi + $eth + $other | Select-Object -Unique) +} + +function Get-WifiIPv4 { + $all = @(Get-LanIPv4Addresses) + return ($all | Select-Object -First 1) +} + +function Start-HttpServer([int]$port) { + $wildcard = "http://+:${port}/" + $listener = New-Object System.Net.HttpListener + $null = $listener.Prefixes.Add($wildcard) + try { + $listener.Start() + return @{ Listener = $listener; Mode = 'wildcard' } + } + catch { + if ($_.Exception.Message -match 'conflict|already') { + throw [System.InvalidOperationException]::new( + 'PORT_BUSY: Dong cua so PowerShell dang chay start.bat (Ctrl+C) roi chay lai.') + } + throw + } +} + +$lanIps = @(Get-LanIPv4Addresses) +$fwOk = @(Get-NetFirewallRule -DisplayName "Wedding Site LAN $port" -ErrorAction SilentlyContinue | + Where-Object { $_.Enabled -eq 'True' }).Count -gt 0 + +$bindMode = $null +$listener = $null try { - Start-Process $url | Out-Null -} catch { - Write-Host " Mo trinh duyet thu cong: $url" -ForegroundColor Yellow + $started = Start-HttpServer $port + $listener = $started.Listener + $bindMode = $started.Mode +} +catch { + Write-Host " Loi khoi dong server: $($_.Exception.Message)" -ForegroundColor Red + Write-Host " Dong server cu (Ctrl+C) hoac: Stop-Process -Name powershell -Force (neu bi ket)" -ForegroundColor Yellow + Write-Host " Neu can: PowerShell (Admin) -> .\setup-wifi.ps1" -ForegroundColor Yellow + exit 1 +} + +$localUrl = "http://localhost:${port}${sitePath}" +$wifiIp = Get-WifiIPv4 +Write-Host '' +Write-Host ' Thiep cuoi dang chay:' -ForegroundColor Green +Write-Host " May tinh: $localUrl" -ForegroundColor Cyan +if ($wifiIp) { + $phoneUrl = "http://${wifiIp}:${port}${sitePath}" + Write-Host '' + Write-Host ' >>> DIEN THOAI (cung WiFi) - copy URL nay:' -ForegroundColor Yellow + Write-Host " $phoneUrl" -ForegroundColor Green +} +if ($lanIps.Count -gt 1) { + Write-Host '' + Write-Host ' IP khac (chi dung neu URL tren khong vao):' -ForegroundColor DarkGray + foreach ($ip in $lanIps) { + if ($ip -ne $wifiIp) { + Write-Host " http://${ip}:${port}${sitePath}" -ForegroundColor DarkGray + } + } +} +elseif (-not $wifiIp) { + Write-Host '' + Write-Host ' Khong tim thay IP WiFi. Ket noi WiFi roi chay lai start.bat.' -ForegroundColor Yellow +} +if (-not $fwOk) { + Write-Host '' + Write-Host ' !!! CHUA MO FIREWALL - dien thoai thuong KHONG vao duoc !!!' -ForegroundColor Red + Write-Host ' Chuot phai setup-wifi.ps1 -> Run as administrator (hoac mo-firewall.bat)' -ForegroundColor Yellow +} +Write-Host '' +Write-Host ' Dien thoai khong vao? Chay lai setup-wifi.ps1 (Admin) de mo firewall.' -ForegroundColor DarkGray +Write-Host ' Tat VPN tren may tinh/dien thoai. Router tat AP isolation neu co.' -ForegroundColor DarkGray +Write-Host ' Nhan Ctrl+C de dung server.' -ForegroundColor DarkGray +Write-Host '' + +try { + Start-Process $localUrl | Out-Null +} +catch { + Write-Host " Mo trinh duyet thu cong: $localUrl" -ForegroundColor Yellow } while ($listener.IsListening) { $context = $listener.GetContext() $request = $context.Request $response = $context.Response + $client = $request.RemoteEndPoint.Address.ToString() + Write-Host " [$((Get-Date).ToString('HH:mm:ss'))] $client -> $($request.Url.LocalPath)" -ForegroundColor DarkGray try { $rawPath = $request.Url.LocalPath if ([string]::IsNullOrWhiteSpace($rawPath) -or $rawPath -eq "/") { - $rawPath = "/www.mewedding.vn/index.html" + $rawPath = $sitePath } - $relative = [System.Uri]::UnescapeDataString($rawPath).TrimStart("/").Replace("/", [IO.Path]::DirectorySeparatorChar) - $filePath = Join-Path $root $relative - $filePath = [IO.Path]::GetFullPath($filePath) + $rootFull = [IO.Path]::GetFullPath($root) + $filePath = Resolve-StaticFile $root $rawPath - if (-not $filePath.StartsWith([IO.Path]::GetFullPath($root), [StringComparison]::OrdinalIgnoreCase)) { - $response.StatusCode = 403 - $buf = [Text.Encoding]::UTF8.GetBytes("403 Forbidden") - $response.OutputStream.Write($buf, 0, $buf.Length) - continue - } - - if (Test-Path $filePath -PathType Container) { - $index = Join-Path $filePath "index.html" - if (Test-Path $index) { $filePath = $index } else { - $response.StatusCode = 404 - $buf = [Text.Encoding]::UTF8.GetBytes("404 Not Found") - $response.OutputStream.Write($buf, 0, $buf.Length) - continue + if (-not $filePath) { + $dirRel = [System.Uri]::UnescapeDataString($rawPath).TrimStart('/').Replace('/', [IO.Path]::DirectorySeparatorChar) + $dirPath = [IO.Path]::GetFullPath((Join-Path $root $dirRel)) + if ($dirPath.StartsWith($rootFull, [StringComparison]::OrdinalIgnoreCase) -and (Test-Path $dirPath -PathType Container)) { + $index = Join-Path $dirPath "index.html" + if (Test-Path $index) { $filePath = $index } } } - if (-not (Test-Path $filePath -PathType Leaf)) { + if (-not $filePath) { $response.StatusCode = 404 + Write-Host " [404] $rawPath" -ForegroundColor Red $buf = [Text.Encoding]::UTF8.GetBytes("404 Not Found: $rawPath") $response.OutputStream.Write($buf, 0, $buf.Length) continue } - Send-File $context $filePath + $asHtml = $filePath.EndsWith('index.html', [StringComparison]::OrdinalIgnoreCase) + Send-File $context $filePath $(if ($asHtml) { 'text/html' } else { $null }) } catch { $response.StatusCode = 500 diff --git a/setup-wifi.ps1 b/setup-wifi.ps1 new file mode 100644 index 0000000..d3d17e1 --- /dev/null +++ b/setup-wifi.ps1 @@ -0,0 +1,63 @@ +# Chay MOT LAN bang PowerShell (Admin): urlacl + mo firewall cong 8080 + Wi-Fi -> Private +# Chuot phai -> Run as administrator + +$ErrorActionPreference = "Stop" +$port = 8080 +$url = "http://+:${port}/" +$fwRuleName = "Wedding Site LAN $port" + +function Test-IsAdmin { + $id = [Security.Principal.WindowsIdentity]::GetCurrent() + $p = New-Object Security.Principal.WindowsPrincipal($id) + return $p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} + +if (-not (Test-IsAdmin)) { + Write-Host "Can quyen Administrator." -ForegroundColor Red + Write-Host "Chuot phai file setup-wifi.ps1 -> Run with PowerShell (Admin)" -ForegroundColor Yellow + exit 1 +} + +# --- URL ACL --- +netsh http delete urlacl url=$url 2>$null | Out-Null + +$user = if ($env:USERDOMAIN -and $env:USERNAME) { + "$($env:USERDOMAIN)\$($env:USERNAME)" +} else { + $env:USERNAME +} + +Write-Host "Dang them URL ACL cho user: $user" -ForegroundColor Cyan +netsh http add urlacl url=$url user="$user" 2>&1 | Out-Null +if ($LASTEXITCODE -ne 0) { + netsh http delete urlacl url=$url 2>$null | Out-Null + netsh http add urlacl url=$url user=Everyone 2>&1 | Out-Null +} +if ($LASTEXITCODE -ne 0) { + Write-Host " URL ACL that bai. Xem huong dan trong README.md" -ForegroundColor Red + exit 1 +} +Write-Host " URL ACL: OK" -ForegroundColor Green + +# --- Firewall: cho phep dien thoai vao cong 8080 --- +Get-NetFirewallRule -DisplayName $fwRuleName -ErrorAction SilentlyContinue | + Remove-NetFirewallRule -ErrorAction SilentlyContinue + +New-NetFirewallRule -DisplayName $fwRuleName ` + -Direction Inbound -Action Allow -Protocol TCP -LocalPort $port ` + -Profile Domain, Private, Public | Out-Null +Write-Host " Firewall: da mo cong TCP $port (Public + Private)" -ForegroundColor Green + +# --- Dat Wi-Fi la Private --- +$wifi = Get-NetConnectionProfile -ErrorAction SilentlyContinue | + Where-Object { $_.InterfaceAlias -match 'Wi-?Fi' } | Select-Object -First 1 +if ($wifi -and $wifi.NetworkCategory -eq 'Public') { + Set-NetConnectionProfile -InterfaceAlias $wifi.InterfaceAlias -NetworkCategory Private + Write-Host " Wi-Fi: da doi sang mang Rieng tu (Private)" -ForegroundColor Green +} + +Write-Host "" +Write-Host " Xong. Chay start.bat - tren dien thoai dung IP Wi-Fi in ra." -ForegroundColor Green +Write-Host "" +$portPattern = ':' + $port +netsh http show urlacl | Select-String -Pattern $portPattern diff --git a/www.mewedding.vn/index.html b/www.mewedding.vn/index.html index be82166..52dc334 100644 --- a/www.mewedding.vn/index.html +++ b/www.mewedding.vn/index.html @@ -3910,7 +3910,7 @@ height: 302px; top: -2px; left: -58px; - background-image: url("../w.ladicdn.com/s800x650/5c728619c417ab07e5194baa/z5583219164432_981e1b1759655c926afea9680f0cbef7-20240628123950-rmi1q.jpg"); + background-image: url("/w.ladicdn.com/s800x650/5c728619c417ab07e5194baa/z5583219164432_981e1b1759655c926afea9680f0cbef7-20240628123950-rmi1q.jpg"); } #PARAGRAPH130 { @@ -5526,7 +5526,7 @@ } #SECTION22 { - height: 899.1px; + height: 919.1px; } #SECTION22>.ladi-section-background { @@ -5593,7 +5593,7 @@ #GROUP171, #BOX44 { width: 383px; - height: 363px; + height: 383px; } #GROUP170 { @@ -5657,7 +5657,7 @@ } #GROUP169 { - top: 313.5px; + top: 336px; left: 24.25px; } @@ -5720,7 +5720,7 @@ #GROUP173, #GROUP174 { width: 353px; - height: 51px; + height: 77px; top: 250.719px; left: 24.25px; } @@ -5748,20 +5748,21 @@ } #GROUP171 { - top: 514.054px; + top: 534.054px; left: 18.5px; } #IMAGE46>.ladi-image>.ladi-image-background { - width: 158.994px; - height: 238.491px; - top: -18px; - left: -2px; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-position: center center; background-image: url("../w.ladicdn.com/PREWEDDING THANH NHAN - MINH HIEP/NLV_6222.jpg"); } #GROUP172 { - top: 314.5px; + top: 336px; left: 24.25px; } @@ -8274,7 +8275,7 @@
@@ -8384,7 +8385,7 @@

Xác nhận tham dự

-
@@ -8398,7 +8399,7 @@
@@ -10216,7 +10217,7 @@ "cs": [ { "dr": "action", - "dC": "../w.ladicdn.com/s400/Black and White Minimalist Flower Initials Logo.png", + "dC": "/w.ladicdn.com/s400/Black%20and%20White%20Minimalist%20Flower%20Initials%20Logo.png", "dF": "image", "a": "lightbox" } @@ -10266,19 +10267,19 @@ "FORM_ITEM8": { "a": "form_item", "bS": "textarea", "bQ": 2 }, "FORM_ITEM9": { "a": "form_item", "bS": "select", "bQ": 3 }, "FORM_ITEM10": { "a": "form_item", "bS": "select", "bQ": 4 }, - "GROUP76": { "a": "group", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://docs.google.com/spreadsheets/d/1yHaSeIG84bWKwrHu2PWKUGUbM3J49gYUT6CwJ323PMM/edit?gid=1246856894#gid=1246856894", "a": "link" }] }, + "GROUP76": { "a": "group", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://docs.google.com/spreadsheets/d/1sSg0n0FPt8c6K-Wf62D-IuIcpCkskE6YZ9wpN6AVOQE/edit?gid=1731966803#gid=1731966803", "a": "link" }] }, "PARAGRAPH90": { "a": "paragraph", "F": "tada", "C": "1s" }, "SHAPE35": { "a": "shape", "F": "wobble", "C": "1s" }, "PARAGRAPH91": { "a": "paragraph", "F": "fadeInDown", "C": "0s" }, "BUTTON20": { "a": "button", "cs": [{ "dr": "action", "dw": "QRchure", "a": "popup" }] }, "BUTTON21": { "a": "button", "cs": [{ "dr": "action", "dw": "QRcodau", "a": "popup" }] }, - "BUTTON26": { "a": "button", "cs": [{ "dr": "action", "dv": "_self", "dw": "../w.ladicdn.com/5c728619c417ab07e5194baa/QR cô dâu.jpg", "a": "link" }] }, + "BUTTON26": { "a": "button", "cs": [{ "dr": "action", "dv": "_self", "dw": "/w.ladicdn.com/5c728619c417ab07e5194baa/QR%20c%C3%B4%20d%C3%A2u.jpg", "a": "link" }] }, "BUTTON27": { "a": "button", "cs": [{ "dr": "action", "dL": "19038818159010", "a": "copy_clipboard" }] }, - "IMAGE24": { "a": "image", "cs": [{ "dr": "action", "dC": "../w.ladicdn.com/5c728619c417ab07e5194baa/QR cô dâu.jpg", "dF": "image", "a": "lightbox" }] }, + "IMAGE24": { "a": "image", "cs": [{ "dr": "action", "dC": "/w.ladicdn.com/5c728619c417ab07e5194baa/QR%20c%C3%B4%20d%C3%A2u.jpg", "dF": "image", "a": "lightbox" }] }, "QRcodau": { "a": "popup", "X": "default", "U": "background-color: rgba(0, 0, 0, 0.5);" }, - "BUTTON28": { "a": "button", "cs": [{ "dr": "action", "dv": "_self", "dw": "../w.ladicdn.com/5c728619c417ab07e5194baa/QrChuRe.jpg", "a": "link" }] }, + "BUTTON28": { "a": "button", "cs": [{ "dr": "action", "dv": "_self", "dw": "/w.ladicdn.com/5c728619c417ab07e5194baa/QrChuRe.jpg", "a": "link" }] }, "BUTTON29": { "a": "button", "cs": [{ "dr": "action", "dL": "4504995135", "a": "copy_clipboard" }] }, - "IMAGE25": { "a": "image", "cs": [{ "dr": "action", "dC": "../w.ladicdn.com/5c728619c417ab07e5194baa/QrChuRe.jpg", "dF": "image", "a": "lightbox" }] }, + "IMAGE25": { "a": "image", "cs": [{ "dr": "action", "dC": "/w.ladicdn.com/5c728619c417ab07e5194baa/QrChuRe.jpg", "dF": "image", "a": "lightbox" }] }, "QRchure": { "a": "popup", "X": "default", "U": "background-color: rgba(0, 0, 0, 0.5);" }, "PARAGRAPH100": { "a": "paragraph", "D": "fadeInUp", "A": "0s" }, "PARAGRAPH101": { "a": "paragraph", "F": "fadeInUp", "C": "0s" }, @@ -10410,8 +10411,8 @@ "BUTTON46": { "a": "button", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://maps.app.goo.gl/Gxu38EXCi59UQARw6?g_st=iz", "a": "link" }] }, "GROUP171": { "a": "group", "D": "fadeInUp", "A": "0s" }, "GROUP177": { "a": "group", "D": "fadeInUp", "A": "1s" }, - "PARAGRAPH164": { "a": "paragraph", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://www.messenger.com/t/meweddingg", "a": "link" }] }, - "PARAGRAPH163": { "a": "paragraph", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://www.messenger.com/t/meweddingg", "a": "link" }] }, + "PARAGRAPH164": { "a": "paragraph", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://www.facebook.com/hiep.leminh.5686?locale=vi_VN", "a": "link" }] }, + "PARAGRAPH163": { "a": "paragraph", "cs": [{ "dr": "action", "dv": "_blank", "dw": "https://www.facebook.com/pttnhan102?locale=vi_VN", "a": "link" }] }, "VIDEO3": { "a": "video", "ci": "https://s.ladicdn.com/5c728619c417ab07e5194baa/trang-toan-20240602160049-h2egz.mp4", "ch": "direct", "cg": true, "D": "fadeInUp", "A": "1s" }, "HEADLINE6": { "a": "headline", "D": "bounceIn", "A": "0s" }, "GROUP178": { "a": "group", "F": "bounceIn", "C": "0s" }, @@ -10587,7 +10588,7 @@