Quick reply
ภาพรวม
Quick reply คือชุดปุ่ม (chips) ที่ขึ้นเหนือช่องพิมพ์ข้อความบน LINE เมื่อผู้ใช้ได้รับข้อความจาก OA ผู้ดูแลสร้าง "ชุด quick reply" ไว้เป็นรายการกลางในเมนูนี้ แล้วให้เมนูอื่นมาเลือกใช้ซ้ำได้ ไม่ต้องตั้งปุ่มใหม่ทุกครั้งที่สร้างข้อความ
จุดสำคัญที่ต้องรู้ก่อนเริ่มคือ การอ้างอิงเป็นแบบอ้างอิงสด ไม่ใช่การคัดลอก — ข้อความที่ผูกชุด quick reply ไว้จะเก็บแค่ id ของชุดนั้น ไม่ได้ก็อปปี้ปุ่มไปเก็บไว้ในตัวเอง แก้ปุ่มที่นี่ครั้งเดียวจึงเปลี่ยนทุกข้อความที่อ้างอิงชุดนี้อยู่ทันที (ตรงตามคำอธิบายในฟอร์มว่า "การแก้ไขที่นี่จะอัปเดตทุกข้อความที่ใช้งานอยู่") และในทางกลับกัน การปิดใช้งานชุดหนึ่งก็ทำให้ปุ่มหายไปจากทุกข้อความที่ผูกไว้พร้อมกัน
อีกจุดที่ต้องรู้คือ ชุด quick reply ใช้ได้กับ Rich message เท่านั้น — ไม่ใช่กับ Template message แม้หน้าเว็บจะมีข้อความบางส่วนที่พูดถึง Template message อยู่ (ดูหัวข้อ รายละเอียดสำคัญ)
บทบาทที่ใช้งาน — ทีมคอนเทนต์และทีมที่ดูแลแชทของ LINE OA ที่เตรียมปุ่มตอบกลับไว้ให้ข้อความต่าง ๆ เรียกใช้ (โมดูลนี้ ไม่มี ModuleGate บังคับที่ backend ต่างจาก Rich message และ Auto-response message — ดูหัวข้อ สิทธิ์การเข้าถึง)
เส้นทางผู้ใช้งาน
1. ดูรายการชุด quick reply
เปิดเมนู ข้อความตอบกลับด่วน หน้ารายการเป็นตารางเดียว (ไม่มีแท็บ) เรียงจากใหม่ไปเก่าตามวันที่สร้าง คอลัมน์มี ลำดับ / ชื่อ / รายการ (จำนวนปุ่มในชุด) / สถานะ / การดำเนินการ ตัวกรองมี 2 ช่อง — ค้นหาจากชื่อ และเลือกสถานะ ค่าตัวกรองถูกจดจำไว้ใน sessionStorage
คอลัมน์ สถานะ เป็นสวิตช์ที่กดสลับได้จากหน้ารายการโดยตรง ไม่ต้องเข้าฟอร์ม แต่การกดปิดชุดที่ถูกใช้งานอยู่จะไม่ผ่านทันที (ดูขั้นตอนที่ 4)
2. สร้างชุด quick reply ใหม่
- กดปุ่ม สร้างข้อความตอบกลับด่วน เข้าสู่ฟอร์มสองฝั่ง (ซ้ายกรอกข้อมูล ขวาดูตัวอย่าง chips)
- กรอกชื่อ — บังคับกรอก ไม่เกิน 255 ตัวอักษร
- เพิ่มปุ่มทีละรายการ — สูงสุด 13 ปุ่ม (ตรงกับเพดานของ LINE เอง) ตัวนับ
n/13แสดงอยู่มุมขวาของหัวข้อรายการ และปุ่ม เพิ่มรายการ จะถูกปิดเมื่อครบ 13 - เลือกชนิดปุ่มจาก 6 แบบ — ข้อความ, URI / ลิงก์, ตัวเลือกวันที่/เวลา, กล้อง, คลังภาพ, ตำแหน่งที่ตั้ง
- ข้อความ — กรอกข้อความที่จะถูกส่งเข้าแชทแทนผู้ใช้เมื่อกดปุ่ม ช่องนี้เป็น autocomplete ที่ดึง keyword ของกฎที่ เปิดใช้งานอยู่ ในเมนู Auto-response message มาแนะนำ เพราะข้อความที่ปุ่มส่งกลับเข้าแชทจะไปกระตุ้นกฎตอบกลับอัตโนมัติได้จริง (เป็นคำแนะนำอย่างเดียว พิมพ์ค่าอื่นได้)
- URI / ลิงก์ — ช่องเดียว มี placeholder บอกรูปแบบที่รับ
https://... หรือ tel:... หรือ line://... - ตัวเลือกวันที่/เวลา — กรอกข้อมูล postback, เลือกโหมด (วันที่ / เวลา / วันที่และเวลา — ค่าเริ่มต้นคือวันที่และเวลา) และกำหนดค่าเริ่มต้น / ค่าต่ำสุด / ค่าสูงสุด ได้ (ไม่บังคับ)
- กล้อง / คลังภาพ / ตำแหน่งที่ตั้ง — ไม่มีฟิลด์เพิ่มเติม ระบบขึ้นข้อความกำกับว่า "LINE จะเปิดกล้อง/ตัวเลือกตำแหน่งโดยตรงเมื่อแตะ"
- ทุกปุ่มต้องมี ป้ายชื่อ (label) ที่แสดงบน chip — ไม่เกิน 20 ตัวอักษร (ช่องกรอกมีตัวนับและตัดที่ 20 ให้เลย)
- จัดลำดับปุ่ม — ปุ่มลูกศรขึ้น/ลงในแต่ละการ์ด (ลูกศรขึ้นถูกปิดที่รายการแรก ลูกศรลงถูกปิดที่รายการสุดท้าย) ลำดับในฟอร์มคือลำดับที่ผู้ใช้ LINE จะเห็นจริง
- ดูตัวอย่าง chips แบบเรียลไทม์ ที่การ์ด "ตัวอย่างชิป" คอลัมน์ขวา ซึ่งตรึงตำแหน่งไว้ (Affix) ให้เห็นตลอดขณะเลื่อนแก้ไข
- เปิด/ปิดสวิตช์ สถานะ (ค่าเริ่มต้นเมื่อสร้างใหม่คือเปิดใช้งาน) แล้วกดบันทึก ระบบพากลับหน้ารายการ
การเปลี่ยนชนิดของปุ่มที่กรอกไว้แล้ว ระบบจะ ล้างฟิลด์เฉพาะชนิดทั้งหมดให้ใหม่ เก็บไว้แค่ป้ายชื่อ เพื่อไม่ให้ฟิลด์ของชนิดเก่าค้างติดไปกับชนิดใหม่ ซึ่ง backend จะปฏิเสธ (ดูหัวข้อรายละเอียดสำคัญ)
3. นำไปใช้ในเมนูอื่น
- เปิดฟอร์มของ Rich message จะมีช่องเลือกชุด quick reply ที่โหลดเฉพาะชุดที่ เปิดใช้งานอยู่ (ดึงมาครั้งเดียว 100 รายการ ไม่แบ่งหน้า) พร้อมตัวเลือก "ไม่มี" อยู่บนสุด
- เลือกชุดแล้ว ระบบแสดง ป้ายชื่อของทุกปุ่มเป็น tag ใต้ช่องเลือกทันทีเพื่อยืนยันว่าเลือกถูกชุด และแสดง chips ในหน้าจอตัวอย่างแชทของข้อความนั้นด้วย
- หากข้อความนั้นอ้างอิงชุดที่ถูก ปิดใช้งาน ไปแล้ว ระบบจะดึงชุดนั้นมาแสดงเป็นตัวเลือกเพิ่มพร้อมป้าย "ปิดใช้งาน" และขึ้นคำเตือนว่า "จะไม่มีการส่งชิป" — ถ้าชุดนั้นถูก ลบ ไปแล้ว จะแสดงเป็น "ข้อความตอบกลับด่วนที่ไม่พร้อมใช้งาน" พร้อมคำเตือนให้เลือกรายการอื่น (ออกแบบไว้เพื่อไม่ให้หน้าเว็บโชว์ uuid เปล่า ๆ)
4. ปิดหรือลบชุดที่ถูกใช้งานอยู่
ทั้งสองการกระทำถูกป้องกันด้วยกลไกเดียวกันที่ backend แต่ผลลัพธ์ต่างกันคนละแบบ:
- ปิดใช้งาน — ระบบเปิดกล่องเตือน "ปิดใช้งานข้อความตอบกลับด่วนนี้หรือไม่?" พร้อม รายชื่อ Rich message ทุกตัวที่อ้างอิงอยู่ และคำอธิบายว่า "ข้อความเหล่านี้จะยังคงส่งต่อไป แต่จะไม่มีชิปของข้อความตอบกลับด่วนนี้" กดปุ่ม ปิดใช้งานต่อไป เพื่อยืนยัน (ระบบยิงคำขอซ้ำโดยแนบธง
forceให้อัตโนมัติ) ถ้ากดยกเลิก สวิตช์จะถูกดึงกลับไปตรงกับค่าที่เซิร์ฟเวอร์เก็บไว้จริง ไม่ค้างอยู่ที่ค่าที่กดไป - ลบ — กล่องขึ้นหัวข้อ "ข้อความตอบกลับด่วนนี้ยังถูกใช้งานอยู่" พร้อมรายชื่อผู้อ้างอิงเหมือนกัน แต่ ไม่มีปุ่มยืนยันให้ทำต่อ มีแค่ปุ่มปิด ต้องไปแก้ Rich message ที่อ้างอิงให้เลิกใช้ชุดนี้ก่อน
ในหน้าฟอร์มแก้ไข (ไม่ใช่หน้าสร้าง) ยังมีการ์ด "ใช้งานโดย" ที่คอลัมน์ขวา แสดงรายชื่อผู้อ้างอิงให้เห็นล่วงหน้า ก่อน ที่จะกดปิดหรือลบ — ดึงจาก endpoint แยกที่ให้ผลชุดเดียวกับที่กลไกป้องกันใช้
รายละเอียดสำคัญที่ตรวจสอบจากซอร์สโค้ดจริง
ยืนยันจาก internal/modules/quickreply/{controller,service,dto,items}.go ของ line-management-cms-api-go และ internal/quickreply/attach.go ของ line-management-worker-go:
- ชนิด
postbackถูกปิดไว้ที่ backend อย่างจงใจ และปิดไม่ให้เลือกที่หน้าเว็บด้วย —items.goตรวจเจอtype: "postback"แล้วปฏิเสธด้วย 400"postback is not currently supported"ทันที คอมเมนต์ในโค้ดอธิบายเหตุผลไว้ตรง ๆ ว่ายังไม่มีตัวจัดการ postback แบบทั่วไป (webhook มีแค่ prefix เฉพาะทางที่ hardcode ไว้) ปุ่ม postback จึงจะ "ยิงแล้วไม่ไปไหน" — โค้ดตรวจสอบของ postback ถูกเก็บไว้ครบเพื่อเปิดใช้ทีหลัง ฝั่งหน้าเว็บก็ตัด postback ออกจากรายการตัวเลือกด้วยเหตุผลเดียวกัน แต่ยังเก็บค่า constant และหน้าจอกรอกฟิลด์ postback ไว้เพื่อรองรับข้อมูลเก่าที่มีอยู่แล้ว - URI เป็น allowlist ที่ไม่มีการตรวจซ้ำฝั่งหน้าเว็บเลย — backend รับเฉพาะ
https://,tel:และline://เท่านั้น (เทียบแบบไม่สนตัวพิมพ์เล็กใหญ่)http://ถูก ปฏิเสธตรง ๆ ไม่ได้อัปเกรดให้เป็น https ส่วนฝั่งหน้าเว็บตรวจแค่ว่า "ช่อง URI ไม่ว่าง" ไม่ได้ตรวจ scheme เลย — พิมพ์http://...ลงไปจะผ่านการตรวจในฟอร์มทั้งหมดแล้วไปตกที่ 400 ตอนกดบันทึก - การตรวจ items เป็น "closed shape" — ฟิลด์แปลกปลอมถูกปฏิเสธ ไม่ใช่ถูกละเลย — แต่ละชนิดอนุญาตชุดคีย์ของตัวเองเท่านั้น (นอกจาก
typeและlabelที่ทุกชนิดมีได้) ถ้ามีคี่ที่ไม่เข้าพวกจะได้ 400 ระบุตำแหน่งเป็นราย index เช่นproperty items[2].uri should not existเป็นเหตุผลว่าทำไมหน้าเว็บต้องล้างฟิลด์เฉพาะชนิดทิ้งทุกครั้งที่เปลี่ยนชนิดปุ่ม - เพดานความยาวหลายค่าบังคับที่ backend เท่านั้น —
label1-20 ตัวอักษร (นับเป็น rune จึงนับอักษรไทยถูกต้อง), ข้อความของชนิด message ไม่เกิน 300, URI ไม่เกิน 1000, ข้อมูล postback ของ datetimepicker ไม่เกิน 300, ค่าเริ่มต้น/ต่ำสุด/สูงสุด ไม่เกิน 100 ต่อช่อง ในจำนวนนี้หน้าเว็บบังคับให้จริงแค่label(ผ่านmaxLengthของช่องกรอก) และชื่อชุด 255 — เพดาน 300 ของช่องข้อความไม่มีการเตือนใด ๆ ในฟอร์ม - กลไกป้องกันตอนปิดใช้งานยิงเฉพาะการเปลี่ยนสถานะ active → inactive เท่านั้น — โค้ดตรวจสามเงื่อนไขพร้อมกัน (เดิมเปิดอยู่ + จะเปลี่ยนเป็นปิด + ไม่ได้ส่ง
force) และ สแกนฐานข้อมูลเฉพาะเมื่อสามเงื่อนไขนี้ครบ เพื่อไม่ให้การแก้ชื่อหรือแก้ปุ่มธรรมดาต้องเสียเวลาสแกนโดยไม่จำเป็น การแก้ไขอื่นทั้งหมด (ปิด→ปิด, →เปิด, หรือแก้ชื่อ/ปุ่มเฉย ๆ) ไม่ถูกป้องกันเลย ส่วนธงforceเป็น ฟิลด์ที่มีอยู่แค่ในคำขอ ไม่ถูกบันทึกลงฐานข้อมูล (คอมเมนต์ระบุชัดว่าไม่เคยไปถึงคำสั่ง update) - การสแกนหาผู้อ้างอิงดูตาราง
rich_messageตารางเดียว และเป็นการตัดสินใจโดยเจตนา — คอมเมนต์ในservice.goอธิบายว่าtemplate_messageไม่มีคอลัมน์quick_reply_idเลย เพราะเทมเพลตไม่มีเส้นทางส่งออก LINE ของตัวเอง (flex ของมันถูกส่งในฐานะรายการหนึ่งของ Rich message เท่านั้น) ปุ่ม quick reply ที่ผูกกับเทมเพลตจึงจะไม่ทำงานอยู่ดี — ทั้งที่ไฟล์ข้อความหน้าเว็บยังมีป้าย "ข้อความเทมเพลต" เตรียมไว้เป็นแหล่งอ้างอิงชนิดหนึ่ง (ค่าที่ backend ไม่เคยส่งกลับมา) - worker ปฏิบัติกับชุดที่ถูกปิด/ลบ เหมือนกับ "ไม่มีชุดเลย" ไม่ถือเป็นข้อผิดพลาด — ตอนส่งจริง worker อ่าน
SELECT items FROM quick_reply WHERE id = ? AND status = 'active' AND deleted_date IS NULLถ้าไม่เจอแถวจะคืนค่าว่างเงียบ ๆ แล้ว ส่งข้อความออกไปโดยไม่มี chips ไม่ทำให้การส่งล้มเหลว (คอมเมนต์ระบุว่าเป็นพฤติกรรมที่ตั้งใจ: การปิดสวิตช์ต้องหยุด chips เงียบ ๆ ห้ามทำให้ส่งข้อความไม่ออก) และ chips ถูกแนบกับบับเบิลสุดท้ายของชุดข้อความเท่านั้น — Rich message ที่มี 5 รายการจะมี chips โผล่หลังรายการที่ 5 - ปุ่มเรียงลำดับตามคอลัมน์ "ชื่อ" ในหน้ารายการไม่ทำงานจริง — ตารางฝั่งหน้าเว็บตั้ง
sorter: trueที่คอลัมน์ชื่อและส่งorder/orderByไปกับคำขอ แต่Listของโมดูลนี้ ไม่อ่านค่าทั้งสองเลย บังคับORDER BY created_date DESCตายตัวทุกครั้ง กดหัวคอลัมน์แล้วลูกศรเปลี่ยนแต่ลำดับข้อมูลไม่เปลี่ยน - ตาราง
quick_replyไม่มี hook ลบแบบนุ่มนวลของ gorm — entity ไม่ได้ประกาศgorm.DeletedAtไว้ ทุก query ในโมดูลนี้จึงต้องเขียนdeleted_date IS NULLด้วยมือทุกครั้ง และการลบคือการประทับdeleted_date(soft delete) ข้อมูลยังอยู่ในฐานข้อมูล
เมนูที่เกี่ยวข้องกันในเส้นทางนี้
- Rich message — ผู้อ้างอิงชุด quick reply เพียงเมนูเดียวที่มีอยู่จริงในระบบ และเป็นตารางเดียวที่กลไกป้องกันการปิด/ลบสแกนหา
- Auto-response message — keyword ของกฎที่ เปิดใช้งานอยู่ ในเมนูนั้นจะโผล่เป็นคำแนะนำในช่องข้อความของปุ่มชนิด "ข้อความ" ที่นี่ เพราะข้อความที่ปุ่มส่งกลับเข้าแชทสามารถไปกระตุ้นกฎตอบกลับอัตโนมัติได้จริง
- Campaign — ไม่ได้เลือกชุด quick reply เองโดยตรง แต่ปุ่มที่ผูกกับ Rich message จะติดไปกับแคมเปญโดยอัตโนมัติเมื่อส่งออก
- Template message — ไม่ รองรับการผูกชุด quick reply (ไม่มีคอลัมน์รองรับที่ฐานข้อมูล) ถ้าต้องการปุ่มพร้อมเทมเพลต ต้องผูกที่ระดับ Rich message ที่ห่อเทมเพลตนั้นอยู่
จุดที่ควรระวัง
- แก้ปุ่มที่นี่คือแก้ข้อความที่กำลังใช้งานอยู่ทันที — ไม่มีเวอร์ชันหรือการอนุมัติคั่นกลาง ทุก Rich message ที่อ้างอิงชุดนี้จะส่งปุ่มชุดใหม่ตั้งแต่การส่งครั้งถัดไป การ์ด "ใช้งานโดย" ในฟอร์มแก้ไขคือที่เดียวที่บอกว่ากำลังจะกระทบข้อความใดบ้าง
- พิมพ์
http://ในช่อง URI จะผ่านฟอร์มแต่ไม่ผ่านการบันทึก — ฟอร์มไม่ตรวจ scheme เลย ข้อผิดพลาดจะโผล่เป็น 400 ตอนกดบันทึกเท่านั้น - ข้อความของปุ่มชนิด "ข้อความ" ยาวเกิน 300 ตัวอักษรจะบันทึกไม่ผ่าน โดยที่ช่องกรอกไม่มีตัวนับหรือคำเตือนใด ๆ ล่วงหน้า
- ปิดชุดที่ถูกใช้งานอยู่ = ปุ่มหายเงียบ ๆ ไม่มีข้อผิดพลาดที่ไหน — ข้อความยังส่งออกปกติ แต่ chips ไม่มา ไม่มี log แจ้งเตือนฝั่งผู้ใช้ ถ้าผู้ใช้แจ้งว่า "ปุ่มหายไป" ให้เช็กสถานะของชุดที่ผูกไว้ก่อนอื่น
- ปุ่มเกิน 13 รายการถูกตัดทิ้งที่ worker ด้วยอีกชั้น — ทั้งฟอร์มและ backend กันไว้ที่ 13 แล้ว แต่ถ้าข้อมูลเก่ามีเกิน worker จะตัดเอาแค่ 13 ตัวแรกไปส่ง ไม่ปฏิเสธการส่ง
- การกดเรียงลำดับตามชื่อไม่มีผล — รายการเรียงตามวันที่สร้างใหม่สุดขึ้นก่อนอยู่เสมอ ใช้ช่องค้นหาชื่อแทนถ้ามีชุดจำนวนมาก
สิทธิ์การเข้าถึง (ตรวจสอบจากซอร์สโค้ดจริง)
- ฝั่งหน้าเว็บ — ทั้งหน้ารายการและหน้าฟอร์มถูกครอบด้วย
PermissionGuardตรวจ actionVIEWของ subjectquick-reply - ฝั่งเซิร์ฟเวอร์ — โมดูลนี้ไม่มี
ModuleGateต่างจาก Rich message (ModuleGate(d, "rich-message")), Template message และ Auto-response message ที่มีบังคับใช้จริง ทั้ง 6 เส้นทางของ quick reply ผูกไว้กับauth.CheckPolicies(...)เท่านั้น ซึ่ง คอมเมนต์บนหัวไฟล์controller.goระบุตรง ๆ ว่าเป็น no-op ในวันนี้ ("auth.CheckPolicies is a no-op today — see internal/modules/auth/policy.go — but the metadata is kept for when enforcement is switched on") ผลคือผู้ใช้ที่ล็อกอินสำเร็จเรียก API ของ quick reply ได้ทุกเส้นทางแม้ผู้ดูแลระดับแพลตฟอร์มจะไม่ได้เปิดโมดูลใดให้ก็ตาม - การกันข้อมูลข้ามองค์กรเป็นการบังคับจริงเพียงชั้นเดียวที่มี — ทุก query ผูก
line_oa_idจาก context ของผู้เรียกไว้ตายตัว การเรียก id ของ OA อื่นให้ผล 404 "Quick reply not found" ไม่ใช่ 403 (จึงไม่รั่วข้อมูลว่า id นั้นมีอยู่จริงหรือไม่) - policy annotation ระดับการกระทำมีประกาศครบทั้ง
readAll/create/read/update/deleteแต่วิ่งผ่าน middleware ที่เป็น no-op เหมือนกับโมดูลอื่นส่วนใหญ่ในระบบ — เก็บไว้เป็น metadata สำหรับวันที่เปิดบังคับใช้จริง - ไม่มีเส้นทางลบแบบถาวร (hard delete) และไม่มีเส้นทางที่ต้องเป็น Super Admin ในโมดูลนี้
ไฟล์อ้างอิงจากซอร์สโค้ด
Frontend (cms-web-2026)
src/app/quick-reply/page.tsx,src/app/quick-reply/form/page.tsx— จุดเข้าหน้ารายการและฟอร์ม พร้อมPermissionGuardsrc/components/quick-reply/list/quick-reply.container.tsx— ตาราง, สวิตช์สถานะ, การจัดการ 409 ของทั้งการปิดใช้งานและการลบsrc/components/quick-reply/form/quick-reply-form.tsx,quick-reply-form.container.tsx— กฎตรวจสอบฝั่งหน้าเว็บ, การ์ด "ใช้งานโดย", การยิงซ้ำด้วยธงforcesrc/components/quick-reply/form/quick-reply-items-editor.tsx— เพดาน 13 ปุ่ม, การล้างฟิลด์เมื่อเปลี่ยนชนิด, การจัดลำดับsrc/components/quick-reply/form/enums/quick-reply-item.enum.ts— รายการชนิดปุ่มที่เลือกได้ (และเหตุผลที่ตัด postback ออก)src/components/quick-reply/QuickReplyPicker.tsx— ช่องเลือกชุดที่เมนูอื่นเรียกใช้ พร้อมการจัดการชุดที่ถูกปิด/ลบsrc/components/common/auto-response-keyword-autocomplete.tsx— คำแนะนำ keyword จากเมนู Auto-response messagesrc/services/quick-reply.service.ts— endpoint ทั้งหมดที่หน้าเว็บเรียกใช้messages/th/quick-reply.json,messages/en/quick-reply.json— ข้อความ UI ทั้งหมด
Backend (line-management-cms-api-go)
internal/modules/quickreply/controller.go— 6 เส้นทาง และคอมเมนต์ที่ระบุว่า policy เป็น no-opinternal/modules/quickreply/service.go— CRUD, การผูกline_oa_id, กลไกป้องกันการปิด/ลบ, การสแกนrich_messageinternal/modules/quickreply/dto.go— กฎตรวจสอบ name / status / ธงforceinternal/modules/quickreply/items.go— closed shape ของปุ่มแต่ละชนิด, allowlist ของ URI, การปิด postback
Worker (line-management-worker-go)
internal/quickreply/attach.go— การอ่านชุดเฉพาะที่ active, การแปลงเป็นรูปแบบของ LINE, การแนบ chips กับบับเบิลสุดท้าย
ดูรายละเอียดเชิงเทคนิคเพิ่มเติม (เวอร์ชันก่อนหน้าของทีมเอกสาร) ที่ ข้อความตอบกลับด่วน (Quick Reply)