落地空运单聊询价字段与线路选择。

必填核对后再建单;多条线路走 H5 点选;费用只展示该线路 TMS 回包,不套用整单空运费。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-22 15:02:32 +08:00
co-authored by Cursor
parent 8afe909230
commit cfbce2fd69
53 changed files with 3470 additions and 372 deletions
+37 -35
View File
@@ -12,6 +12,7 @@
"use strict";
const crypto = require("crypto");
const { buildGroupMessageFrame, pickReplyReqId } = require("./group_message_frame.cjs");
function generateReqId(prefix) {
const timestamp = Date.now();
@@ -49,6 +50,7 @@ function startLongConnectionLoop(opts) {
lastError: "",
pending: new Map(),
lastCallback: new Map(),
lastAnyReq: "",
heartbeatTimer: null,
reconnectTimer: null,
stop: () => {},
@@ -83,38 +85,34 @@ function startLongConnectionLoop(opts) {
});
}
function sendGroupMessage({ chatId, content }) {
function sendGroupMessage({ chatId, content, callbackReqId }) {
const text = String(content || "");
const callbackReqId = state.lastCallback.get(String(chatId || "").trim()) || "";
if (callbackReqId) {
return sendWs(
{
cmd: "aibot_respond_msg",
headers: { req_id: callbackReqId },
body: {
msgtype: "stream",
stream: { id: crypto.randomUUID(), finish: true, content: text },
},
},
callbackReqId
).finally(() => {
state.lastCallback.delete(String(chatId || "").trim());
});
}
const reqId = generateReqId("aibot_send_msg");
return sendWs(
{
cmd: "aibot_send_msg",
headers: { req_id: reqId },
body: {
chatid: chatId,
chat_type: 2,
msgtype: "markdown",
markdown: { content: text },
},
},
reqId
const fromCaller = String(callbackReqId || "").trim();
const chatKey = String(chatId || "").trim();
const fromChat = state.lastCallback.get(chatKey) || "";
const replyReqId = pickReplyReqId({
fromCaller,
fromChat,
lastAny: state.lastAnyReq || "",
});
// 用这次 @ 的 req_id 回 aibot_respond_msg,群里才会引用原消息。
const reqId = replyReqId || generateReqId("aibot_send_msg");
const frame = buildGroupMessageFrame({
chatId,
content: text,
callbackReqId: replyReqId,
reqId,
});
// eslint-disable-next-line no-console
console.log(
"[aibot-long-connection] 出站 cmd=",
frame.cmd,
"chat=",
chatKey || "-",
"hasReq=",
Boolean(replyReqId)
);
return sendWs(frame, reqId);
}
/**
@@ -303,8 +301,10 @@ function startLongConnectionLoop(opts) {
return;
}
const reqId = frame.headers && frame.headers.req_id;
// 出站 ACK 带 chatid,不能当成入站,否则会盖掉这次 @ 的 req_id,群里就没有引用。
if (reqId && state.pending.has(reqId)) {
settlePending(reqId, frame.errcode, frame.errmsg, frame);
return;
}
if (frame.cmd === "aibot_event_callback") {
const ev = (frame.body && frame.body.event && frame.body.event.eventtype) || "";
@@ -318,9 +318,7 @@ function startLongConnectionLoop(opts) {
const bodyHint = frame.body || {};
const looksLikeInbound = Boolean(
frame.cmd === "aibot_msg_callback" ||
bodyHint.msgid ||
bodyHint.chatid ||
(bodyHint.text && bodyHint.text.content)
(bodyHint.msgid && (bodyHint.from || (bodyHint.text && bodyHint.text.content)))
);
if (looksLikeInbound) {
// eslint-disable-next-line no-console
@@ -333,8 +331,12 @@ function startLongConnectionLoop(opts) {
bodyHint.chatid || "-"
);
const inbound = normalizeInbound(frame);
if (reqId && inbound.chat_id) {
state.lastCallback.set(inbound.chat_id, reqId);
const chatKey = inbound.chat_id || String(bodyHint.chatid || "").trim();
if (reqId && chatKey) {
state.lastCallback.set(chatKey, reqId);
}
if (reqId) {
state.lastAnyReq = reqId;
}
const officialBody = Object.assign({}, frame.body || {}, {
aibot_direct: true,