diff --git a/fe-admin/src/components/pe/PeDetailTabs.tsx b/fe-admin/src/components/pe/PeDetailTabs.tsx index 8164e52..fc44fc0 100644 --- a/fe-admin/src/components/pe/PeDetailTabs.tsx +++ b/fe-admin/src/components/pe/PeDetailTabs.tsx @@ -1433,14 +1433,21 @@ function HoSoLinkRow({ ev, readOnly = false }: { ev: PeDetailBundle; readOnly?: ) : ev.hoSoLink ? ( - - {ev.hoSoLink} - + /^https?:\/\//i.test(ev.hoSoLink.trim()) ? ( + // Link web (http/https — vd SharePoint) → bấm mở thẳng tab mới. + + {ev.hoSoLink} + + ) : ( + // Đường dẫn ổ cứng/ổ mạng (O:\…, \\server) → trình duyệt CHẶN mở file:// + // từ https nên bấm sẽ hụt → hiện chữ + nút Copy để dán vào File Explorer. + + ) ) : ( )} @@ -1449,6 +1456,38 @@ function HoSoLinkRow({ ev, readOnly = false }: { ev: PeDetailBundle; readOnly?: ) } +// e.bis — Đường dẫn ổ cứng/ổ mạng (không phải http) → chữ + nút Copy. Trình duyệt +// CHẶN mở file:// từ trang https nên KHÔNG render bấm-mở (bấm sẽ hụt); thay +// bằng Copy → người dùng dán vào File Explorer (máy có map ổ mạng là mở ngay). +function PathWithCopy({ path }: { path: string }) { + const [copied, setCopied] = useState(false) + const copy = async () => { + try { + await navigator.clipboard.writeText(path) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } catch { + toast.error('Không copy được — vui lòng bôi đen đường dẫn rồi Ctrl+C.') + } + } + return ( +
+ + {path} + + +
+ ) +} + // Form row: label cố định 176px (w-44) bên trái + value bên phải (giống spec). function FormRow({ label, value }: { label: string; value: React.ReactNode }) { return ( diff --git a/fe-user/src/components/pe/PeDetailTabs.tsx b/fe-user/src/components/pe/PeDetailTabs.tsx index 8164e52..fc44fc0 100644 --- a/fe-user/src/components/pe/PeDetailTabs.tsx +++ b/fe-user/src/components/pe/PeDetailTabs.tsx @@ -1433,14 +1433,21 @@ function HoSoLinkRow({ ev, readOnly = false }: { ev: PeDetailBundle; readOnly?: ) : ev.hoSoLink ? ( -
- {ev.hoSoLink} - + /^https?:\/\//i.test(ev.hoSoLink.trim()) ? ( + // Link web (http/https — vd SharePoint) → bấm mở thẳng tab mới. + + {ev.hoSoLink} + + ) : ( + // Đường dẫn ổ cứng/ổ mạng (O:\…, \\server) → trình duyệt CHẶN mở file:// + // từ https nên bấm sẽ hụt → hiện chữ + nút Copy để dán vào File Explorer. + + ) ) : ( )} @@ -1449,6 +1456,38 @@ function HoSoLinkRow({ ev, readOnly = false }: { ev: PeDetailBundle; readOnly?: ) } +// e.bis — Đường dẫn ổ cứng/ổ mạng (không phải http) → chữ + nút Copy. Trình duyệt +// CHẶN mở file:// từ trang https nên KHÔNG render bấm-mở (bấm sẽ hụt); thay +// bằng Copy → người dùng dán vào File Explorer (máy có map ổ mạng là mở ngay). +function PathWithCopy({ path }: { path: string }) { + const [copied, setCopied] = useState(false) + const copy = async () => { + try { + await navigator.clipboard.writeText(path) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } catch { + toast.error('Không copy được — vui lòng bôi đen đường dẫn rồi Ctrl+C.') + } + } + return ( +
+ + {path} + + +
+ ) +} + // Form row: label cố định 176px (w-44) bên trái + value bên phải (giống spec). function FormRow({ label, value }: { label: string; value: React.ReactNode }) { return (