หน้าคอนเทนต์
ภาพรวม
Content Page ใช้สร้างหน้าเนื้อหา เช่น บทความ โปรโมชัน หรือหน้า landing ที่แชร์ให้ผู้ใช้ LINE เปิดดูได้ผ่านลิงก์สาธารณะ โมดูลนี้มีวงจรชีวิตแบบระบบ CMS เต็มรูปแบบ คือ draft, publish และ archive พร้อมระบบ analytics สำหรับนับยอดเข้าชม และรองรับการล็อกหน้าด้วยรหัสผ่าน
หน้าคอนเทนต์ถูกจัดระเบียบด้วย Content Category และ Content Subcategory และเผยแพร่เป็นชุดผ่าน Content Link
Business Flow
ฝั่งผู้ดูแลระบบ
GET /api/content-pagesพร้อมพารามิเตอร์page,limit,searchและstatusลิสต์หน้าทั้งหมด โดยคืนผลลัพธ์เป็น{data, total, page, limit, totalPages}POST /api/content-pagesสร้างหน้าใหม่ด้วยสถานะเริ่มต้นเป็น draft ระบบจะ generate public token ด้วยcrypto.randomBytes(32)และหากมีการตั้งรหัสผ่าน จะเข้ารหัสด้วย bcrypt ที่ cost 10POST /api/content-pages/upload-imageอัปโหลดรูปประกอบพร้อมตรวจสอบ Content-TypeGET /api/content-pages/:idดูรายละเอียด และPATCH /api/content-pages/:idแก้ไขPOST /api/content-pages/:id/publishเผยแพร่หน้า และPOST /api/content-pages/:id/archiveย้ายเข้าคลังPOST /api/content-pages/:id/duplicateคัดลอกหน้าทั้งชุดรวมถึงรูปประกอบGET /api/content-pages/:id/analyticsดูสถิติการเข้าชม ซึ่งรวบรวมจากตารางcontent_page_view,content_page_analyticsและข้อมูล UTM ในcontent_page_utmDELETE /api/content-pages/:idเป็น soft delete ผ่านคอลัมน์deleted_dateแบบธรรมดา จึงต้องเติมเงื่อนไข filter เองในทุก query
ฝั่งผู้อ่าน
GET /api/public/content-pages/:tokenเปิดหน้าด้วย token โดยรับพารามิเตอร์passwordหน้าที่ล็อกรหัสไว้ต้องส่งรหัสให้ตรงกับค่าที่เก็บไว้ ระบบจะเทียบด้วย bcrypt หากหน้ายังไม่เผยแพร่หรือ token ไม่ถูกต้อง จะได้ errorAPP_007(Content not found)POST /api/public/content-pages/:token/trackบันทึกการเข้าชมด้วยTrackViewDtoโดยเพิ่มยอด view และเก็บ event ไว้ประมวลผลเป็น analytics แล้วตอบกลับ 200
นอกจากนี้ยังมีเส้นทางสาธารณะอีกชุดในโมดูล publicmod คือ /api/public/content/:token
ซึ่งรองรับ LIFF เพิ่มเติม
ไฟล์และฟังก์ชันหลัก
โค้ดหลักอยู่ที่ internal/modules/contentpage/ ประกอบด้วย controller.go, service.go
และ dto.go
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/content-pages | ct.findAll | readAll line-oa |
| GET | /api/content-pages/:id | ct.findOne | read line-oa |
| GET | /api/content-pages/:id/analytics | ct.getAnalytics | read line-oa |
| POST | /api/content-pages | ct.create | create line-oa |
| POST | /api/content-pages/upload-image | ct.uploadImage | create line-oa |
| POST | /api/content-pages/:id/publish | ct.publish | create line-oa |
| POST | /api/content-pages/:id/archive | ct.archive | create line-oa |
| POST | /api/content-pages/:id/duplicate | ct.duplicate | create line-oa |
| PATCH | /api/content-pages/:id | ct.update | update line-oa |
| DELETE | /api/content-pages/:id | ct.remove | delete line-oa |
| GET | /api/public/content-pages/:token | ct.getPublicContent | public |
| POST | /api/public/content-pages/:token/track | ct.trackView | public |
จุดเชื่อมต่อกับ Service อื่น
- สิทธิ์การเข้าถึง — route ฝั่งผู้ดูแลอยู่บน group
authedซึ่งใช้ global JWT policy metadata เป็นPolicyModuleLineOaซึ่งยังไม่บังคับใช้ และไม่มีModuleGateครอบ ส่วน route สาธารณะไม่มี guard - ตารางที่เกี่ยวข้อง —
content_page,content_page_translation,content_page_view,content_page_analytics,content_page_utm,content_category,content_subcategoryและline_oa - Soft delete — ใช้คอลัมน์
deleted_dateแบบธรรมดา ไม่ใช่gorm.DeletedAtจึงต้องใส่deleted_date IS NULLเองในทุก read - Storage Service — เก็บรูปประกอบของหน้าคอนเทนต์
- การเข้ารหัส — ใช้ bcrypt cost 10 สำหรับรหัสผ่านของหน้า
- โมดูลที่เกี่ยวข้อง — Content Category, Content Subcategory, Content Link และ Public API