fix download -dox never load version, improve templ page
All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 3s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 1m20s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 4s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s

This commit is contained in:
oom 2026-11-03 21:40:43 +07:00
parent 3e800533d5
commit 2486b6e434
3 changed files with 243 additions and 87 deletions

View file

@ -23,7 +23,7 @@ DOCVER_API_KEY=
DOCVER_TOKEN_SECRET= DOCVER_TOKEN_SECRET=
# ใช้ตอน migrate และ การใช้งาน # ใช้ตอน migrate และ การใช้งาน
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/ecourt-note DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/ecourt-note
### สำหรับโค้ดตัวอย่างระบบนอกเรียกเข้ามาไม่ได้ใช้ในระบบนี้ ### สำหรับโค้ดตัวอย่างระบบนอกเรียกเข้ามาไม่ได้ใช้ในระบบนี้ ห้ามเอาไช้
DOCEDIT_BASE_URL=http://127.0.0.1:3000/docedit DOCEDIT_BASE_URL=http://127.0.0.1:3000/docedit
# Optional เวลาหมดอายุที่ฝังไว้ในข้อมูล (ticket_data), worker ควรเท่ากับจำนวน CPU core -1 # Optional เวลาหมดอายุที่ฝังไว้ในข้อมูล (ticket_data), worker ควรเท่ากับจำนวน CPU core -1
TMPL_PATH='./public/tmpl' TMPL_PATH='./public/tmpl'

View file

@ -34,8 +34,7 @@ async function processRequest(fid: string, tid: string, uid: string, uname: stri
try { //ตรวจสอบ docx เวอร์ชั่นล่าสุดก่อนถ้าไม่พบค่อยเอาจากฐานข้อมูลมาสร้าง raw Json try { //ตรวจสอบ docx เวอร์ชั่นล่าสุดก่อนถ้าไม่พบค่อยเอาจากฐานข้อมูลมาสร้าง raw Json
const params = new URLSearchParams({ type: 'docx', ticket_data }); const params = new URLSearchParams({ type: 'docx', ticket_data });
console.log(`search ${DOCEDIT_BASE_URL}/api/document/latest?${params.toString()}`); const lastestDocxResponse = await fetch(`${DOCEDIT_BASE_URL}/api/documents/latest?${params.toString()}`, {
const lastestDocxResponse = await fetch(`${DOCEDIT_BASE_URL}/api/document/latest?${params.toString()}`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -44,7 +43,7 @@ async function processRequest(fid: string, tid: string, uid: string, uname: stri
}); });
// เช็ค Content-Type และ Status ก่อน // เช็ค Content-Type และ Status ก่อน
const contentType = lastestDocxResponse.headers.get('content-type') || ''; const contentType = lastestDocxResponse.headers.get('content-type') || '';
if (lastestDocxResponse.ok && !!contentType.includes('text/html')) { if (lastestDocxResponse.ok && !contentType.includes('text/html')) {
console.log('Fund latest docx from docedit, returning stream to browser'); console.log('Fund latest docx from docedit, returning stream to browser');
const stream = lastestDocxResponse.body; const stream = lastestDocxResponse.body;
//ส่ง Binary Stream กลับไปยัง Browser พร้อม Header กำหนดประเภทไฟล์ //ส่ง Binary Stream กลับไปยัง Browser พร้อม Header กำหนดประเภทไฟล์

View file

@ -2,8 +2,15 @@
'use client'; 'use client';
import Link from "next/link"; import Link from "next/link";
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
// import { createDownloadFormAction } from './actions';
import DependentDropdown, { DropdownData } from '@/components/utils/DependentDropdown'; import DependentDropdown, { DropdownData } from '@/components/utils/DependentDropdown';
import {
Bookmark,ToyBrick,FilePenLine,BicepsFlexed,Rocket,Workflow, Files,Blocks,FileQuestionMark,
ExternalLink,
FileText,
Highlighter,
MessagesSquare,
} from "lucide-react";
@ -21,24 +28,148 @@ export default function HomePage() {
} }
return ( return (
<div style={{ padding: '2rem' }}> <div style={{ padding: '2rem' }}>
<div className="p-8 max-w-md mx-auto space-y-8 bg-gray-50 min-h-screen"> <div className="mx-auto max-w-4xl px-4 pb-16 pt-12 sm:px-6">
<h1 className="text-xl font-bold text-center">ตัวอย่างการใช้ สร้างเอกสารจาก Template</h1> <h1 className="font-display text-3xl tracking-tight text-ink sm:text-headline">
<div> eCourt Template
ตัวอย่าง Frontend ส่งข้อมูลผ่าน &lt;form&gt;(POST) หรือ &lt;a&gt;(GET) </h1>
เพื่อรองรับ Vanilla JavaScript และ Classic Framework ใช้การเปลี่ยนหน้าเพื่อดาว์นโหลดไฟล์ <p className="mt-2 text-body text-ink-soft">
ตัวอย่างหน้าแบบ <Link href='/tmpl/dl.html'>Plain HTML</Link> ระบบสร้างเทมเพลตเอกสารแบบใหม่ MS Word จากไฟล์ JSON และ Template docx
</p>
<section className="mt-10">
<div className="border-b border-line pb-3">
<h2 className="font-display text-section-title text-ink">
ระบบนี้ทำอะไรได้
</h2>
</div> </div>
<div className="p-4 border rounded-xl bg-white shadow-sm"> <div className="mt-5 grid gap-5 sm:grid-cols-2">
{[
{
icon: FileText,
title: "DOCX Template",
detail:
"ออกแบบหน้าของเอกสารจาก Microsoft Word โดยไม่ต้องใช้เครื่องมือพิเศษ " +
"สามารถนำเอกสารตัวเดิมมาใช้ออกแบบได้เลย " +
"ไม่จำเป็นต้องมีความรู้ด้านการเขียนโปรแกรมหรือ XML ก็สามารถสร้างเทมเพลตได้",
},
{
icon: FilePenLine,
title: "Fill Form",
detail:
"รอรับ Rich และ Plain Text Content Control " +
"สามารถสร้างฟอร์มสำหรับกรอกข้อมูลพร้อมข้อมูลตั้งต้น " +
"ผู้ใช้สามารถนำไปกรอกข้อมูลใน Word ได้เลย และสามารถเใช้โปรแกรมดึงข้อมูลกับมาเก็บในฐานข้อมูลได้",
},
{
icon: ToyBrick,
title: "Integrate with Other System",
detail:
"มี Web API สำหรับสร้างเอกสารจากเทมเพลต(DOCX) กับข้อมูล(JSON) " +
"มี API Key เพื่อจำกัดการใช้งาน สามารถออกบัตรผ่านที่ลงลายเซ็นต์ด้วย HmacSha256" +
"เพื่อให้ผสานกับระบบงานอื่นๆ ได้อย่างปลอดภัย",
},
{
icon: FileText,
title: "Dynamic Document",
detail:
"รองรับเทมเพลตที่ซับซ้อน ข้อมูลที่มีไม่แน่นอนอย่างอาเรย์ การแสดงผลตามเงื่อนไขแบบต่างๆ " +
"สามารถเขียนโปรแกรมเพิ่มลงในเทมเพลตได้ รองรับ FOR , IF แทรกโค้ด " +
"ฟังก์ชั่นในตัวเพื่อรองรับการสร้าง Content Control Bookmark ฯลฯ",
},
{
icon: Rocket,
title: " High Performance",
detail:
"containerization ขยายระบบได้ง่าย, ระบบเทมเพลตใช้การ XML โดยตรง " +
"การสร้าง template เป็นแบบ Multi-Thread รองรับ CPU หลายแกน " +
"",
},
].map(({ icon: Icon, title, detail }) => (
<div
key={title}
className="flex gap-4 rounded-xl border border-line bg-white p-6"
>
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<Icon className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">{title}</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
{detail}
</p>
</div>
</div>
))}
</div>
</section>
<section className="mt-10">
<div className="border-b border-line pb-3">
<h2 className="font-display text-section-title text-ink">
ตัวอย่างการใช้งาน
</h2>
</div>
<div className="mt-5 grid gap-5 sm:grid-cols-2">
<div className="flex gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<ExternalLink className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">Link (GET)</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
<Link href="/api/template/download-docx?tid=T_X&fid=T_no_warning&uid=john&uname=John%20Doe">T_no_warning_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T_X&fid=TF_no_warning_P2&uid=john&uname=John%20Doe">TF_no_warning_P2_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T_X&fid=TS_P2_IN&uid=john&uname=John%20Doe">TS_P2_IN_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T12_X&fid=T12_b2_IN&uid=john&uname=John%20Doe">T12_b2_IN_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T12_X&fid=T12_FD155_3s-long&uid=john&uname=John%20Doe">T12_FD155_3s-long_john_xxx.docx</Link><br />
</p>
</div>
</div>
<div className="flex gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<Files className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">Template & Data</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
<h2 className="font-semibold text-blue-600 mb-2"></h2>
Template: <Link href="/tmpl/T_X.docx">T_X.docx</Link>, &nbsp;
<Link href="/tmpl/T12_X.docx">T12_X.docx</Link><br />
Data: <Link href="tmpl/TF_no_warning_P2.json">TF_no_warning_P2.json</Link>, &nbsp;
<Link href="/tmpl/T_no_warning.json">T_no_warning.json</Link>, &nbsp;
<Link href="/tmpl/TS_P2_IN.json">TS_P2_IN.json</Link><br />
<Link href="/tmpl/T12_b2_IN.json">T12_b2_IN.json</Link>, &nbsp;
<Link href="/tmpl/T12_FD155_3s-long.json">T12_FD155_3s-long.json</Link>
</p>
</div>
</div>
<div className="flex gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<FilePenLine className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">Form (POST)</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
<form action="/docedit/api/template/download-docx" method="POST"> <form action="/docedit/api/template/download-docx" method="POST">
<h2 className="font-semibold text-blue-600 mb-2">Form POST</h2>
<DependentDropdown data={templateData} name1='tid' name2='fid' <DependentDropdown data={templateData} name1='tid' name2='fid'
label1="Template(tid):" label2="ข้อมูล(fid):" onSelectChange={handleTmplSelect} /> label1="Template(tid):" label2="ข้อมูล(fid):" onSelectChange={handleTmplSelect} />
<div className="mb-2"></div> <div className="mb-2"></div>
<div> <div>
uid:<input type="text" name="uid" className="p-2 mb-2 border border-gray-300 rounded-md" defaultValue="john" /> <label htmlFor="uid">uid: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="text" name="uid" className="p-2 mb-2 border border-gray-300 rounded-md" defaultValue="john" />
</label>
</div> </div>
<div> <div>
uname:<input type="text" name="uname" className="p-2 mb-2 border border-gray-300 rounded-md" defaultValue="John Doe" /> <label htmlFor="uname">uname:
<input type="text" name="uname" className="p-2 mb-2 border border-gray-300 rounded-md" defaultValue="John Doe" />
</label>
</div> </div>
<button <button
type="submit" type="submit"
@ -54,59 +185,85 @@ export default function HomePage() {
ดาวน์โหลดเอกสาร MS Word ดาวน์โหลดเอกสาร MS Word
</button> </button>
</form> </form>
</div>
<div className="p-4 border rounded-xl bg-white shadow-sm">
<h2 className="font-semibold text-blue-600 mb-2">A Link Get(new)</h2>
<Link href="/api/template/download-docx?tid=T_X&fid=T_no_warning&uid=john&uname=John%20Doe">T_no_warning_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T_X&fid=TF_no_warning_P2&uid=john&uname=John%20Doe">TF_no_warning_P2_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T_X&fid=TS_P2_IN&uid=john&uname=John%20Doe">TS_P2_IN_john_xxx.docx</Link><br />
<Link href="/api/template/download-docx?tid=T12_X&fid=T12_b2_IN&uid=john&uname=John%20Doe">T12_b2_IN_john_xxx.docx</Link><br /> </p>
<Link href="/api/template/download-docx?tid=T12_X&fid=T12_FD155_3s-long&uid=john&uname=John%20Doe">T12_FD155_3s-long_john_xxx.docx</Link><br />
</div> </div>
<div className="p-4 border rounded-xl bg-white shadow-sm">
<h2 className="font-semibold text-blue-600 mb-2">Template & Data</h2>
Template: <Link href="/tmpl/T_X.docx">T_X.docx</Link>, &nbsp;
<Link href="/tmpl/T12_X.docx">T12_X.docx</Link><br />
Data: <Link href="tmpl/TF_no_warning_P2.json">TF_no_warning_P2.json</Link>, &nbsp;
<Link href="/tmpl/T_no_warning.json">T_no_warning.json</Link>, &nbsp;
<Link href="/tmpl/TS_P2_IN.json">TS_P2_IN.json</Link><br />
<Link href="/tmpl/T12_b2_IN.json">T12_b2_IN.json</Link>, &nbsp;
<Link href="/tmpl/T12_FD155_3s-long.json">T12_FD155_3s-long.json</Link>
</div> </div>
<div className="p-4 border rounded-xl bg-white shadow-sm">
<h2 className="font-semibold text-blue-600 mb-2">Flow</h2> <div className="flex gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<Workflow className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">Flow</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
<div className="text-xl font-bold text-center"> <div className="text-xl font-bold text-center">
หน้านี้(เลือกไฟล์)<br /> ลิงค์เลือกไฟล์<br />
&darr; <br /> &darr; <br />
download-docx(ตรวจสิทธิ์,ส่งเทมเพลต ID,ส่งข้อมูล)<br /> ตรวจสิทธิ์ สร้าง docx <br />
&darr; <br /> &darr; <br />
generate(เปิดเทมเพลต,สร้าง docx)<br /> ดาว์นโหลด เปิด Word<br />
&darr; <br /> &darr; <br />
ดาว์นโหลด docx เปิด MS Word อัตโนมัติ<br /> Add-ins ตรวจสอบไฟล์<br />
&darr; <br /> &darr; <br />
Add-ins ตรวจสอบไฟล์, ผู้ใช้แก้ไข docx<br /> Versioning<br />
&darr; <br /> &darr; <br />
Versioning(คุมเวอร์ชั่น)<br /> อัปเดตฐานข้อมูลและไฟล์<br />
&darr; <br /> </div>
ecourt(อัปเดตฐานข้อมูลและไฟล์)<br /> </p>
</div> </div>
</div> </div>
<div className="flex gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<FileQuestionMark className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">วิธีการใช้งาน</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
<Link href="https://www.youtube.com/watch?v=QxMitSk3S4E" className="focus-ring -m-1 inline-block rounded-md px-1 py-0.5 font-medium text-primary transition hover:underline">
แนะนำเทมเพลตของ Docedit เบื้องต้น</Link><br />
<Link href="https://www.youtube.com/watch?v=3emGNqRZgMs" className="focus-ring -m-1 inline-block rounded-md px-1 py-0.5 font-medium text-primary transition hover:underline">
Sideload Office add-ins</Link>
</p>
</div> </div>
<div className="p-8 max-w-md mx-auto space-y-8 bg-gray-50 min-h-screen"> </div>
<div className="p-10 max-w-md border rounded-xl bg-white shadow-sm">
<h2 className="font-semibold text-blue-600 mb-2">Addin</h2> </div>
ติดตั้ง Word Add-ins ด้วยสคริปต์นี้ <br/> </section>
<Link href="/wordaddin/install-word-addins.ps1"> install-word-addins.ps1 </Link> <section className="mt-10">
<div className="border-b border-line pb-3">
<h2 className="font-display text-section-title text-ink">
Add-ins
</h2>
</div>
<div className="mt-5 flex max-w-xxl gap-4 rounded-xl border border-line bg-white p-6">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/[0.08] text-primary">
<Blocks className="h-5 w-5" aria-hidden />
</span>
<div>
<h3 className="font-display text-subhead text-ink">
Word Add-ins<br />
</h3>
<p className="mt-1.5 text-sm leading-relaxed text-ink-soft">
ดาวน์โหลด&nbsp;
<Link href="/wordaddin/manifest.xml" className="focus-ring -m-1 inline-block rounded-md px-1 py-0.5 font-medium text-primary transition hover:underline">
manifest.xml </Link>&nbsp;
ไว้ที่ SharePoint แชร์เน็ตเวิร์ก หรือดาวน์โหลดสคริปต์ PowerShell(Dev Install) &nbsp;
<Link href="/wordaddin/install-word-addins.ps1" className="focus-ring -m-1 inline-block rounded-md px-1 py-0.5 font-medium text-primary transition hover:underline">
install-word-addins.ps1 </Link> &nbsp;
แล้วใช้คำสั่ง PowerShell ด้านล่างเพื่อติดตั้ง Add-ins ใน Word<br />
<br /> <br />
ติดติดปัญหาบน Power Shell ให้เรียกสองบรรทัดล่างก่อน <br />
<p className="whitespace-nowrap">Unblock-File .\install-word-addins.ps1</p> <p className="whitespace-nowrap">Unblock-File .\install-word-addins.ps1</p>
<p className="whitespace-nowrap">Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force</p> <p className="whitespace-nowrap">Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force</p>
<p className="whitespace-nowrap">.\install-word-addins.ps1 -Install</p> <p className="whitespace-nowrap">.\install-word-addins.ps1 -Install</p>
</p>
</div> </div>
</div>
</section>
</div> </div>
</div> </div>
); );
} }