ข้อความตอบกลับด่วน (Quick Reply)
ภาพรวม
Quick Reply คือชุดปุ่ม (chips) ที่ LINE แสดงเหนือช่องพิมพ์ข้อความเมื่อผู้ใช้ได้รับข้อความจาก OA เมื่อผู้ใช้กดปุ่ม ระบบจะทำงานตามชนิดของปุ่มที่ตั้งไว้ เช่น ส่งข้อความกลับเข้าห้องแชท เปิดลิงก์ เปิดกล้อง หรือส่งตำแหน่งที่ตั้ง
ฟีเจอร์นี้ให้แอดมินสร้าง "ชุด quick reply" เก็บไว้เป็นรายการกลาง แล้วให้ Rich Message และ Template Message มาอ้างอิงชุดเดิมซ้ำได้ โดยไม่ต้องตั้งค่าปุ่มใหม่ทุกครั้งที่สร้างข้อความ เหมาะกับทีมที่ต้องส่งข้อความหลายแบบแต่ต้องการชุดปุ่มลัดชุดเดียวกัน
ข้อมูล 1 ชุดประกอบด้วย
| ข้อมูล | คำอธิบาย |
|---|---|
| ชื่อชุด | ชื่อที่ใช้อ้างอิงในตารางและในตัวเลือกของฟีเจอร์อื่น ความยาวไม่เกิน 255 ตัวอักษร |
| รายการปุ่ม (items) | ปุ่มในชุด สูงสุด 13 ปุ่ม แต่ละปุ่มมี label ไม่เกิน 20 ตัวอักษร |
| สถานะ | เปิด (active) / ปิด (inactive) ชุดที่ปิดอยู่จะไม่ถูกส่ง chips ออกไป |
ชนิดของปุ่มที่เลือกได้จากหน้าจอ
| ชนิด | ข้อมูลที่ต้องกรอกเพิ่ม | ผลเมื่อผู้ใช้กด |
|---|---|---|
ข้อความ (message) | ข้อความที่จะส่ง | ส่งข้อความนั้นเข้าห้องแชทแทนผู้ใช้ |
ลิงก์ (uri) | URL | เปิดลิงก์ที่กำหนด |
เลือกวันที่/เวลา (datetimepicker) | ข้อมูลอ้างอิง, โหมด (วันที่ / เวลา / วันที่และเวลา), ค่าเริ่มต้น, ค่าต่ำสุด, ค่าสูงสุด | เปิดตัวเลือกวันที่หรือเวลา |
กล้อง (camera) | - | เปิดกล้องถ่ายภาพ |
คลังภาพ (cameraRoll) | - | เปิดคลังภาพในเครื่อง |
ตำแหน่งที่ตั้ง (location) | - | เปิดหน้าจอส่งตำแหน่ง |
หมายเหตุ: ชนิด postback ไม่เปิดให้เลือกจากหน้าจอ เพราะฝั่ง API ไม่รองรับ แต่ระบบยังอ่านและแสดงข้อมูลเดิมที่เป็นชนิดนี้ได้
จุดสำคัญที่ต้องทราบ
- ชุดที่ยังถูกใช้งานอยู่จะถูกป้องกันไว้ หากพยายามปิดหรือลบชุดที่มี Rich Message หรือ Template Message อ้างอิงอยู่ ระบบจะแจ้งเตือนพร้อมแสดงรายการผู้อ้างอิงทั้งหมด
- กรณี ปิดใช้งาน ผู้ใช้ยืนยันเพื่อดำเนินการต่อได้ (บันทึกซ้ำแบบบังคับ) แต่กรณี ลบ จะทำต่อไม่ได้ ต้องไปแก้ข้อความที่อ้างอิงอยู่ให้เลิกใช้ชุดนี้ก่อน
- ข้อจำกัดจำนวนปุ่มและความยาว label เป็นข้อกำหนดของ LINE Messaging API ไม่สามารถขยายเกินได้
Business Flow
การจัดการรายการชุด quick reply
- เข้าหน้ารายการ ระบบตรวจสิทธิ์การเข้าถึง (สิทธิ์
VIEWของโมดูลquick-reply) ก่อนแสดงผล - ระบบอ่านเงื่อนไขการกรองล่าสุดที่จดจำไว้ในเซสชัน ถ้าไม่มีจะเริ่มที่หน้าแรก 10 รายการต่อหน้า
- ตารางแสดงลำดับ ชื่อชุด (เรียงลำดับได้) จำนวนปุ่มในชุด สถานะ และปุ่มดำเนินการ
- ค้นหาด้วยชื่อและกรองตามสถานะได้ เมื่อกดค้นหาระบบจะกลับไปหน้าแรกและบันทึกเงื่อนไขไว้ ส่วนปุ่มล้างค่าจะรีเซ็ตฟอร์มและล้างเงื่อนไขที่จดจำไว้ทั้งหมด
- สลับสถานะเปิด/ปิดได้จากสวิตช์ในตาราง ระบบบันทึกทันที
- หากปิดชุดที่ยังถูกอ้างอิงอยู่ ระบบจะแสดงกล่องยืนยันพร้อมรายการผู้อ้างอิง ผู้ใช้เลือกยืนยันเพื่อปิดต่อได้ หากกดยกเลิกระบบจะดึงสถานะจริงจากเซิร์ฟเวอร์กลับมาแสดง เพื่อไม่ให้สวิตช์ค้างอยู่ในค่าที่ยังไม่ได้บันทึก
- การลบต้องยืนยันก่อนเสมอ เมื่อสำเร็จระบบจะแจ้งผลและรีเฟรชตาราง หากชุดนั้นยังถูกอ้างอิงอยู่ ระบบจะแสดงรายการผู้อ้างอิงพร้อมปุ่มปิดอย่างเดียว โดยไม่มีทางเลือกให้ลบต่อ
การสร้างและแก้ไขชุด quick reply
- ฟอร์มทำงาน 3 กรณี คือ สร้างใหม่ แก้ไข และดูอย่างเดียว โดยหัวข้อและ breadcrumb เปลี่ยนตามกรณี (ไม่มีโหมดทำสำเนา)
- โหมดแก้ไขจะโหลดข้อมูลชุดเดิมและรายการ "ถูกใช้ที่ไหน" พร้อมกัน เพื่อให้เห็นผลกระทบก่อนแก้ไข ส่วนโหมดสร้างใหม่จะตั้งสถานะเริ่มต้นเป็นเปิดใช้งาน
- กรอกชื่อชุด แล้วเพิ่มปุ่มทีละรายการ ปุ่มใหม่จะเริ่มต้นเป็นชนิดข้อความเสมอ และปุ่มเพิ่มจะถูกปิดเมื่อครบ 13 รายการ
- แต่ละรายการปรับลำดับขึ้น/ลง หรือลบออกได้ ลำดับในหน้าจอคือลำดับที่ chips จะแสดงจริงบน LINE
- เมื่อเปลี่ยนชนิดของปุ่ม ระบบจะล้างค่าเฉพาะชนิดเดิมทิ้งและเก็บไว้เฉพาะ label เพื่อไม่ให้ข้อมูลของชนิดเก่าติดค้างไปกับข้อมูลที่บันทึก
- คอลัมน์ขวาแสดงตัวอย่าง chips แบบเรียลไทม์ตามที่แก้ไข และในโหมดแก้ไขจะมีการ์ดสรุปว่าชุดนี้ถูกใช้ที่ข้อความใดบ้าง
- ก่อนบันทึกระบบตรวจสอบตามลำดับ ได้แก่ ต้องมีอย่างน้อย 1 ปุ่ม ไม่เกิน 13 ปุ่ม ทุกปุ่มต้องมี label ที่ไม่ใช่ช่องว่าง label ไม่เกิน 20 ตัวอักษร และต้องกรอกข้อมูลที่จำเป็นตามชนิดของปุ่มครบ (ข้อความต้องมีข้อความ ลิงก์ต้องมี URL ตัวเลือกวันที่/เวลาต้องมีข้อมูลอ้างอิง)
- เมื่อบันทึกสำเร็จ กรณีสร้างใหม่ระบบจะแสดงกล่องแจ้งผลแล้วพากลับหน้ารายการ ส่วนกรณีแก้ไขจะแจ้งผลสั้น ๆ แล้วกลับหน้ารายการทันที
- หากการแก้ไขเป็นการปิดใช้งานชุดที่ยังถูกอ้างอิงอยู่ ระบบจะแสดงกล่องยืนยันพร้อมรายการผู้อ้างอิง ยืนยันแล้วจะบันทึกซ้ำแบบบังคับ หากยกเลิกระบบจะคืนค่าสวิตช์สถานะกลับเป็นค่าจริงจากเซิร์ฟเวอร์
- หากเซิร์ฟเวอร์ตอบกลับเป็นข้อผิดพลาดรายฟิลด์ ระบบจะแสดงข้อความใต้ฟิลด์นั้นโดยตรง กรณีอื่นจะแสดงเป็นกล่องแจ้งข้อผิดพลาด
การนำชุด quick reply ไปใช้ในข้อความอื่น
- ฟอร์มของ Rich Message มีช่องเลือกชุด quick reply ซึ่งโหลดเฉพาะชุดที่เปิดใช้งานอยู่ (สูงสุด 100 รายการ ไม่มีการแบ่งหน้า) และมีตัวเลือก "ไม่ใช้" อยู่หัวรายการ
- หากข้อความนั้นผูกกับชุดที่ถูกปิดหรือถูกลบไปแล้ว ระบบจะพยายามดึงข้อมูลชุดนั้นมาแสดงชื่อให้อ่านออก แทนการแสดงรหัสอ้างอิงดิบ
- ถ้าชุดยังอยู่แต่ปิดใช้งาน จะติดป้ายเตือนว่าชุดที่ปิดอยู่จะไม่ถูกส่ง chips ออกไป
- ถ้าดึงข้อมูลไม่ได้เลย จะแสดงว่าไม่พบชุดนี้พร้อมข้อความเตือน
- เมื่อเลือกชุดแล้ว ระบบจะแสดง label ของปุ่มทั้งหมดใต้ช่องเลือก เพื่อยืนยันว่าเลือกชุดถูกต้อง
- หน้าจอพรีวิวแชทของฟีเจอร์ข้อความต่าง ๆ จะแสดง chips ในรูปแบบเดียวกับที่ผู้ใช้เห็นบน LINE
หน้าจอและองค์ประกอบหลัก
หน้ารายการ (/quick-reply)
- ส่วนกรองข้อมูล — ช่องค้นหาชื่อชุด และตัวเลือกสถานะ พร้อมปุ่มค้นหา/ล้างค่า
- ตารางรายการ — ลำดับ ชื่อชุด จำนวนปุ่ม สถานะ (สวิตช์) และปุ่มแก้ไข/ลบ รองรับการเรียงตามชื่อและการแบ่งหน้า
- กล่องเตือนกรณียังถูกใช้งาน — แสดงรายการข้อความที่อ้างอิงชุดนี้ โดยกรณีปิดใช้งานจะมีปุ่มยืนยัน ส่วนกรณีลบจะมีเพียงปุ่มปิด
ไฟล์อ้างอิงหลัก: src/app/quick-reply/page.tsx, src/components/quick-reply/list/quick-reply.container.tsx
หน้าฟอร์ม (/quick-reply/form)
- ช่องชื่อชุด — บังคับกรอก จำกัด 255 ตัวอักษร
- ตัวแก้ไขรายการปุ่ม — การ์ดต่อ 1 ปุ่ม ประกอบด้วย label ตัวเลือกชนิด ฟิลด์เฉพาะชนิด และปุ่มเลื่อนขึ้น/ลง/ลบ พร้อมตัวนับจำนวนปุ่มที่ใช้ไปเทียบกับเพดาน 13
- ช่องข้อความของปุ่มชนิดข้อความ — ใช้ช่องกรอกแบบ AutoComplete ที่แนะนำ keyword ของ Auto Response ที่เปิดใช้งานอยู่ เพราะข้อความนี้จะถูกส่งเข้าห้องแชทและอาจไปกระตุ้นกฎ Auto Response
- สวิตช์สถานะ — กำหนดว่าชุดนี้พร้อมใช้งานหรือไม่
- แผงพรีวิว chips — ตรึงอยู่กับหน้าจอขณะเลื่อน แสดงผลตามค่าที่กำลังแก้ไขแบบทันที
- การ์ด "ถูกใช้ที่ไหน" — แสดงเฉพาะโหมดแก้ไข รวมรายการ Rich Message และ Template Message ที่อ้างอิงชุดนี้
- ในโหมดดูอย่างเดียว ทุกฟิลด์จะถูกปิดการแก้ไขและซ่อนปุ่มบันทึก/ยกเลิก
ไฟล์อ้างอิงหลัก: src/app/quick-reply/form/page.tsx, src/components/quick-reply/form/quick-reply-form.container.tsx, src/components/quick-reply/form/quick-reply-form.tsx, src/components/quick-reply/form/quick-reply-items-editor.tsx
คอมโพเนนต์ร่วม
src/components/quick-reply/QuickReplyPicker.tsx— ช่องเลือกชุด quick reply ที่ใช้ในฟอร์ม Rich Message พร้อมกลไกจัดการกรณีชุดที่ผูกไว้ถูกปิดหรือถูกลบsrc/components/quick-reply/QuickReplyChipsPreview.tsx— ตัวแสดง chips สไตล์ LINE ใช้ทั้งในฟอร์ม quick reply และในพรีวิวแชทของฟีเจอร์ข้อความอื่นsrc/components/quick-reply/QuickReplyReferenceList.tsx— ตัวแสดงรายการ "ถูกใช้ที่ไหน" ใช้ร่วมกันทั้งกับข้อมูลที่ดึงมาโดยตรงและกับข้อมูลผู้อ้างอิงที่แนบมากับข้อผิดพลาด
บริการฝั่ง API
รวมอยู่ที่ src/services/quick-reply.service.ts ภายใต้ path หลัก quick-reply
| ความสามารถ | Endpoint |
|---|---|
| ดึงรายการชุด | GET /quick-reply |
| ดึงข้อมูลชุดรายตัว | GET /quick-reply/{id} |
| ดูรายการผู้อ้างอิง | GET /quick-reply/{id}/references |
| สร้างชุดใหม่ | POST /quick-reply |
| แก้ไขชุด (รวมถึงการสลับสถานะ) | PUT /quick-reply/{id} |
| ลบชุด | DELETE /quick-reply/{id} |
หมายเหตุ: ฟีเจอร์นี้ไม่มี endpoint แยกสำหรับเปลี่ยนสถานะ การสลับสวิตช์ในตารางจึงส่งข้อมูลทั้งชุดกลับไปพร้อมสถานะใหม่ และสามารถแนบค่า force เพื่อข้ามการป้องกันกรณีปิดใช้งานชุดที่ยังถูกอ้างอิงได้ ส่วนการลบไม่มีทางเลือกบังคับ
จุดเชื่อมต่อกับฟีเจอร์อื่น
- สิทธิ์การใช้งาน — ทั้งหน้ารายการและหน้าฟอร์มถูกควบคุมด้วยสิทธิ์ของโมดูล
quick-replyซึ่งผูกอยู่กับสิทธิ์โมดูลเดียวกับ Auto Response การเปิดสิทธิ์ Auto Response จึงปลดล็อกเมนู Quick Reply ไปพร้อมกัน - Rich Message Management — เป็นผู้ใช้หลักของชุด quick reply ผ่านช่องเลือกในฟอร์ม และเป็นสาเหตุหลักที่ทำให้ชุดถูกป้องกันไม่ให้ปิดหรือลบ
- Template Message — เป็นอีกหนึ่งแหล่งอ้างอิงที่ปรากฏในรายการ "ถูกใช้ที่ไหน"
- Auto Response — ให้ keyword ที่เปิดใช้งานอยู่มาเป็นคำแนะนำในช่องข้อความของปุ่มชนิดข้อความ เพื่อให้ข้อความที่ปุ่มส่งกลับเข้าแชทตรงกับกฎที่มีอยู่จริง
- พรีวิวแชทกลาง — คอมโพเนนต์พรีวิวแชทของระบบเรียกใช้ตัวแสดง chips ชุดเดียวกัน ทำให้ภาพตัวอย่างในทุกฟีเจอร์สอดคล้องกัน
- โครงสร้างพื้นฐานร่วม — ใช้ระบบยืนยันตัวตนและ HTTP client กลางของ CMS (ออกจากระบบอัตโนมัติเมื่อ token หมดอายุ) ระบบ breadcrumb และเมนูด้านข้าง ชุด modal มาตรฐาน และการจดจำเงื่อนไขการกรองใน sessionStorage เช่นเดียวกับหน้ารายการอื่นในระบบ
รายละเอียดฝั่ง Backend (CMS API)
โค้ดฝั่ง backend อยู่ที่โมดูล internal/modules/quickreply/ เป็น โมดูลที่เขียนขึ้นใหม่ ไม่ได้ย้ายมาจากระบบเดิม โครงสร้างจึงอ้างอิงรูปแบบของโมดูลเรียบง่ายที่มีอยู่แล้วในระบบ (เช่น หมวดคอนเทนต์ และ Template Message) จุดที่ต่างจากโมดูลอื่นชัดเจนคือมี endpoint references แยกไว้สำหรับตรวจการอ้างอิงก่อนลบ
สิทธิ์ที่ต้องมี
- ทุก route ต้องผ่านการยืนยันตัวตนกลาง (JWT) และ token นั้นต้องมีข้อมูล LINE OA ที่เลือกไว้ ถ้าไม่มี request จะไม่ผ่าน
- ระบบกำหนดชื่อ policy ของโมดูลนี้ให้ตรงกับชื่อโมดูลที่ฝั่ง CMS ใช้ (
quick-reply) ไว้ล่วงหน้า เพื่อให้เปิดการบังคับสิทธิ์รายโมดูลได้ในอนาคตโดยไม่ต้องแก้ชื่อ - ข้อสังเกตด้านความปลอดภัย — ต่างจาก Auto Response โมดูลนี้ ยังไม่ได้ครอบด้วย module gate และค่า policy ที่ประกาศไว้ยังเป็นเพียงข้อมูลกำกับ (metadata) ที่ยังไม่ถูกบังคับใช้จริง หมายความว่าการซ่อนเมนูตามสิทธิ์เกิดขึ้นที่ฝั่งหน้าจอเป็นหลัก ผู้ใช้ที่ล็อกอินแล้วและเลือก OA แล้วยังเรียก endpoint เหล่านี้ได้โดยตรง จึงไม่ควรถือว่าการซ่อนเมนูเป็นการควบคุมสิทธิ์ที่แท้จริง
Validation และ Business Rule ที่ backend ตรวจ
- ทุก query ถูก จำกัดขอบเขตตาม LINE OA ที่เลือกอยู่ ข้อมูลของ OA อื่นจะไม่ถูกดึงมาไม่ว่าจะเรียกด้วย id ตรง ๆ ก็ตาม
- เมื่อขอข้อมูลรายตัวด้วย id ที่ไม่มีอยู่จริง หรือ id ที่เป็นของ OA อื่น backend จะตอบเป็น "ไม่พบข้อมูล" อย่างชัดเจน ไม่ใช่คืนค่าว่างเปล่า ทำให้หน้าจอแยกกรณี "ไม่มีสิทธิ์เห็น" กับ "ข้อมูลผิดพลาด" ได้ถูก
GET /api/quick-reply/:id/referencesเป็น endpoint สำหรับตอบว่าชุดนี้ถูกอ้างอิงอยู่ที่ไหน ซึ่งเป็นข้อมูลที่หน้าจอนำไปแสดงในกล่องเตือนก่อนปิดหรือลบ- ไม่มี endpoint แยกสำหรับเปลี่ยนสถานะ การเปิด/ปิดจึงเป็นการเรียก endpoint แก้ไขปกติ (
PUT /api/quick-reply/:id) ด้วยข้อมูลทั้งชุด
สิ่งที่บันทึกและผลข้างเคียง (Side Effect)
- ข้อมูลถูกบันทึกในตาราง
quick_replyเพียงตารางเดียว โมดูลนี้ไม่มีการเขียน cache หรือส่งงานเข้าคิวใด ๆ - การลบเป็น soft delete โดยประทับเวลาที่ลบไว้ในคอลัมน์
deleted_dateแถวข้อมูลยังอยู่ในฐานข้อมูล - ชุดปุ่มที่บันทึกไว้จะถูกนำไปแนบกับ payload ที่ส่งเข้า LINE ตอนส่งข้อความจริง ซึ่งเกิดขึ้นในเส้นทางของฟีเจอร์ที่ส่งข้อความ ไม่ใช่ในโมดูลนี้
Edge Case และข้อสังเกตที่ควรรู้
- โครงสร้างข้อมูลของตารางนี้ไม่ได้ใช้กลไก soft delete อัตโนมัติของ ORM ดังนั้นทุก query ต้องเขียนเงื่อนไข "ยังไม่ถูกลบ" ด้วยตัวเองทุกครั้ง หากมี query ใดลืมใส่เงื่อนไขนี้ ชุดที่ถูกลบไปแล้วจะโผล่กลับมาในผลลัพธ์ เป็นจุดที่ต้องระวังเวลาเพิ่ม query ใหม่ในโมดูลนี้
- เพราะการลบเป็นแบบ soft delete ชุดที่ผู้ใช้ลบไปแล้วยังถูกอ้างถึงได้จากข้อความที่ผูกไว้เดิม ซึ่งเป็นเหตุผลที่หน้าฟอร์มต้องมีกลไกดึงข้อมูลชุดที่ถูกลบมาแสดงชื่อให้อ่านออก แทนการแสดงรหัสอ้างอิงดิบ
- การป้องกันไม่ให้ลบชุดที่ยังถูกใช้งาน อาศัยข้อมูลจาก endpoint
referencesประกอบกับการตรวจฝั่ง backend ตอนลบ การเพิ่มฟีเจอร์ใหม่ที่อ้างอิงชุด quick reply จึงต้องทำให้ endpoint นี้รู้จักแหล่งอ้างอิงใหม่ด้วย ไม่เช่นนั้นการเตือนจะไม่ครบ