Backoffice stage 2: chats (support + concierge, files)

- ChatThread per client/provider and channel; messages get files, internal notes,
  source (bot/mini app) and delivery errors; reply templates. Migration moves old
  concierge messages into threads.
- Routing: subscribers write to the concierge, others to support; /support and
  /concierge in the client bot; staff can take, transfer, close and move threads.
- Telegram: photos/documents from clients and providers, replies with the channel
  header, files sent from storage, notifications only to the assignee or the
  channel's staff, "Reply" into a specific thread.
- New admin: /chats with list, conversation, notes, files, templates, client panel;
  "Message" button on the client card; dashboard counts threads awaiting reply.
- Client mini app: in-app chat screen sharing the same conversation.
- Old admin keeps working on the same data (notes hidden there).
- Tests for routing, notes, assign/close/move, lists, recipients; separate test DB
  via TEST_DB_NAME; dev:chats-demo script.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zabudko-ruandClaude Opus 5.5 committed 2026-10-21 01:50:37 +04:00
1 parent d452824c62
commit 23ffb2bf1d
46 files changed
+4176 -144

No files matched your search

+30 -4
View File
@@ -442,7 +442,9 @@
"PROVIDER_NOT_LINKED": "服务人员尚未通过邀请打开工作机器人,暂时无法发送消息。",
"CARD_EXPIRED": "二维码已过期或无效——请客户重新打开会员卡。",
"OFFER_NOT_AVAILABLE": "该优惠不适用于客户当前等级。",
"OFFER_LIMIT_REACHED": "该优惠次数已用完。"
"OFFER_LIMIT_REACHED": "该优惠次数已用完。",
"CONCIERGE_SUBSCRIBERS_ONLY": "专属礼宾仅面向 Barev+ 和 Barev Elite 会员。目前请联系客服,我们同样会帮你。",
"ASSIGNEE_NO_ACCESS": "该成员无权访问此频道。"
},
"client": {
"nav": {
@@ -654,6 +656,20 @@
"used_ONCE": "已使用",
"used_WEEK": "下周可再次使用",
"used_MONTH": "下月可再次使用"
},
"chat": {
"title": "与 Barev Club 聊天",
"support": "客服",
"concierge": "专属礼宾",
"hint": "这与机器人聊天是同一个对话:回复会同时出现在这里和 Telegram。",
"empty": "告诉我们需要什么帮助,我们会在这里回复。",
"placeholder": "输入消息…",
"send": "发送",
"attach": "附加照片或文件",
"conciergeOnly": "专属礼宾包含在 Barev+ 和 Barev Elite 中",
"team": "Barev Club",
"fileTooBig": "文件超过 10 MB",
"file": "文件"
}
},
"pro": {
@@ -815,7 +831,12 @@
"cmdHelp": "帮助",
"webRequestOrdered": "申请 {{request}} 号已收到,并已生成订单 {{order}} 号,时间:{{date}}。状态请在应用中查看。",
"webRequestLinked": "申请 {{request}} 号已收到。客服会联系你确认时间。",
"conciergeReceived": "已转给礼宾,我们会在这个聊天中回复你。"
"conciergeReceived": "已转给礼宾,我们会在这个聊天中回复你。",
"supportReceived": "已转给客服,我们会在这个聊天中回复你。",
"channelSupport": "现在你在给客服写信。直接发送消息、照片或文件即可。",
"channelConcierge": "现在你在给专属礼宾写信。直接发送消息、照片或文件即可。",
"cmdSupport": "联系客服",
"cmdConcierge": "联系礼宾(Barev+)"
},
"pro": {
"notLinked": "此机器人供 Barev Club 服务人员使用。请向客服索取邀请链接。",
@@ -844,7 +865,11 @@
"newRequest": "应用申请 #{{number}}",
"newWebRequest": "网站申请 #{{number}}",
"loginOk": "登录已确认,请返回浏览器。",
"loginExpired": "登录链接已过期,请刷新管理页面。"
"loginExpired": "登录链接已过期,请刷新管理页面。",
"channelSupport": "客服",
"channelConcierge": "礼宾",
"file": "文件",
"chatAssigned": "{{by}} 将对话转交给你:{{name}}"
},
"partner": {
"valid": "{{name}} — {{level}},会员卡有效",
@@ -948,7 +973,8 @@
"openPlan": "打开应用",
"concierge": "Barev Club 礼宾",
"subscriptionActivated": "{{plan}} 已开通,有效期至 {{date}}。服务价格已含折扣。",
"operator": "Barev Club 客服"
"operator": "Barev Club 客服",
"support": "Barev Club 客服支持"
},
"admin": {
"nav": {