@myun/gimi-chat 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apis/fetch.d.ts +64 -0
- package/dist/apis/fetch.js +512 -0
- package/dist/apis/useApi.d.ts +57 -0
- package/dist/apis/useApi.js +378 -0
- package/dist/assets/image/Subtract.png +0 -0
- package/dist/assets/image/ai-logo.png +0 -0
- package/dist/assets/image/copyIcon.png +0 -0
- package/dist/assets/image/deepthinkActive.png +0 -0
- package/dist/assets/image/empty-img-dark.png +0 -0
- package/dist/assets/image/empty-img.png +0 -0
- package/dist/assets/image/like_active.png +0 -0
- package/dist/assets/image/love.png +0 -0
- package/dist/assets/image/retry.png +0 -0
- package/dist/assets/image/soundOut.png +0 -0
- package/dist/assets/image/unlike_active.png +0 -0
- package/dist/assets/image/unlove.png +0 -0
- package/dist/assets/lottie/ai-bg.json +1704 -0
- package/dist/assets/lottie/ai-loading.json +192 -0
- package/dist/assets/lottie/ai-output-loading.json +272 -0
- package/dist/assets/lottie/ai-output-normal.json +17694 -0
- package/dist/assets/lottie/ai-output-strengthen.json +17321 -0
- package/dist/assets/lottie/ai-voice-play.json +1 -0
- package/dist/assets/lottie/living.json +705 -0
- package/dist/assets/lottie/myun-living.json +726 -0
- package/dist/assets/lottie/myun-loading.json +530 -0
- package/dist/components/ai-chat-dialogue/index.d.ts +16 -0
- package/dist/components/ai-chat-dialogue/index.js +1056 -0
- package/dist/components/ai-chat-dialogue/index.module.scss +272 -0
- package/dist/components/ai-chat-dialogue/message-parser.d.ts +36 -0
- package/dist/components/ai-chat-dialogue/message-parser.js +52 -0
- package/dist/components/ai-chat-dialogue/tlv.d.ts +7 -0
- package/dist/components/ai-chat-dialogue/tlv.js +32 -0
- package/dist/components/ai-chat-dialogue/volc-voice-call-client.d.ts +47 -0
- package/dist/components/ai-chat-dialogue/volc-voice-call-client.js +246 -0
- package/dist/components/ai-correction/index.d.ts +5 -0
- package/dist/components/ai-correction/index.js +45 -0
- package/dist/components/ai-loading/index.d.ts +3 -0
- package/dist/components/ai-loading/index.js +14 -0
- package/dist/components/ai-loading/index.module.scss +11 -0
- package/dist/components/answer-item/index.d.ts +27 -0
- package/dist/components/answer-item/index.js +194 -0
- package/dist/components/answer-item/index.module.scss +295 -0
- package/dist/components/ask-card/index.d.ts +10 -0
- package/dist/components/ask-card/index.js +76 -0
- package/dist/components/ask-card/index.module.scss +125 -0
- package/dist/components/chat-input/index.d.ts +31 -0
- package/dist/components/chat-input/index.js +433 -0
- package/dist/components/chat-input/index.module.scss +44 -0
- package/dist/components/chat-voice/VoiceCommunication.d.ts +7 -0
- package/dist/components/chat-voice/VoiceCommunication.js +69 -0
- package/dist/components/chat-voice/VoiceRecord.d.ts +7 -0
- package/dist/components/chat-voice/VoiceRecord.js +34 -0
- package/dist/components/conversation-delete/index.d.ts +5 -0
- package/dist/components/conversation-delete/index.js +24 -0
- package/dist/components/dots-loading/index.d.ts +2 -0
- package/dist/components/dots-loading/index.js +11 -0
- package/dist/components/dots-loading/index.module.scss +45 -0
- package/dist/components/empty/index.d.ts +9 -0
- package/dist/components/empty/index.js +32 -0
- package/dist/components/empty/index.module.scss +27 -0
- package/dist/components/excel-components/ExcelCard.d.ts +11 -0
- package/dist/components/excel-components/ExcelCard.js +35 -0
- package/dist/components/excel-components/ExcelExcuting.d.ts +10 -0
- package/dist/components/excel-components/ExcelExcuting.js +263 -0
- package/dist/components/excel-components/ExcelFailCard.d.ts +9 -0
- package/dist/components/excel-components/ExcelFailCard.js +20 -0
- package/dist/components/excel-components/ExcelSuccessCard.d.ts +5 -0
- package/dist/components/excel-components/ExcelSuccessCard.js +50 -0
- package/dist/components/excel-components/index.module.scss +210 -0
- package/dist/components/excel-components/styles.module.scss +186 -0
- package/dist/components/file-card/fileCardSidebar.d.ts +8 -0
- package/dist/components/file-card/fileCardSidebar.js +56 -0
- package/dist/components/file-card/index.d.ts +15 -0
- package/dist/components/file-card/index.js +97 -0
- package/dist/components/file-card/index.module.scss +139 -0
- package/dist/components/file-preview/index.d.ts +3 -0
- package/dist/components/file-preview/index.js +229 -0
- package/dist/components/file-preview/index.module.scss +120 -0
- package/dist/components/file-upload/index.d.ts +16 -0
- package/dist/components/file-upload/index.js +238 -0
- package/dist/components/file-upload/uploadV1.d.ts +16 -0
- package/dist/components/file-upload/uploadV1.js +267 -0
- package/dist/components/gimi-sidebar/index.d.ts +17 -0
- package/dist/components/gimi-sidebar/index.js +41 -0
- package/dist/components/gimi-sidebar/index.module.scss +136 -0
- package/dist/components/header/index.d.ts +5 -0
- package/dist/components/header/index.js +20 -0
- package/dist/components/header/index.module.scss +26 -0
- package/dist/components/iconfont-com/index.d.ts +11 -0
- package/dist/components/iconfont-com/index.js +29 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/knowledge-trace/KnowledgeIconComponent.d.ts +7 -0
- package/dist/components/knowledge-trace/KnowledgeIconComponent.js +101 -0
- package/dist/components/knowledge-trace/classList.d.ts +6 -0
- package/dist/components/knowledge-trace/classList.js +72 -0
- package/dist/components/knowledge-trace/documentList.d.ts +6 -0
- package/dist/components/knowledge-trace/documentList.js +75 -0
- package/dist/components/knowledge-trace/index.d.ts +18 -0
- package/dist/components/knowledge-trace/index.js +155 -0
- package/dist/components/knowledge-trace/index.module.scss +262 -0
- package/dist/components/knowledge-trace/interfaces.d.ts +166 -0
- package/dist/components/knowledge-trace/interfaces.js +1 -0
- package/dist/components/knowledge-trace/videoList.d.ts +6 -0
- package/dist/components/knowledge-trace/videoList.js +91 -0
- package/dist/components/lottie-img/index.d.ts +8 -0
- package/dist/components/lottie-img/index.js +99 -0
- package/dist/components/message-actions/CopyButton.d.ts +7 -0
- package/dist/components/message-actions/CopyButton.js +33 -0
- package/dist/components/message-actions/LikeButton.d.ts +7 -0
- package/dist/components/message-actions/LikeButton.js +34 -0
- package/dist/components/message-actions/RegenerateButton.d.ts +5 -0
- package/dist/components/message-actions/RegenerateButton.js +27 -0
- package/dist/components/message-actions/UnLikeButton.d.ts +7 -0
- package/dist/components/message-actions/UnLikeButton.js +34 -0
- package/dist/components/message-actions/VoicePlay.d.ts +10 -0
- package/dist/components/message-actions/VoicePlay.js +74 -0
- package/dist/components/message-list/index.d.ts +19 -0
- package/dist/components/message-list/index.js +167 -0
- package/dist/components/message-list/index.module.scss +304 -0
- package/dist/components/no-microphone-root/index.d.ts +6 -0
- package/dist/components/no-microphone-root/index.js +36 -0
- package/dist/components/no-microphone-root/index.module.scss +42 -0
- package/dist/components/preset-agent-content/index.d.ts +8 -0
- package/dist/components/preset-agent-content/index.js +24 -0
- package/dist/components/preset-agent-content/index.module.scss +48 -0
- package/dist/components/quoted-content/index.d.ts +0 -0
- package/dist/components/quoted-content/index.js +171 -0
- package/dist/components/quoted-content/index.module.scss +76 -0
- package/dist/components/reasoning-content/index.d.ts +6 -0
- package/dist/components/reasoning-content/index.js +116 -0
- package/dist/components/reasoning-content/index.module.scss +164 -0
- package/dist/components/reference-content/index.d.ts +28 -0
- package/dist/components/reference-content/index.js +125 -0
- package/dist/components/reference-content/index.module.scss +73 -0
- package/dist/components/templates/CommonChat.d.ts +5 -0
- package/dist/components/templates/CommonChat.js +218 -0
- package/dist/components/templates/GimiChatComponent.d.ts +4 -0
- package/dist/components/templates/GimiChatComponent.js +23 -0
- package/dist/components/templates/demo/demo.d.ts +2 -0
- package/dist/components/templates/demo/demo.js +110 -0
- package/dist/components/templates/index.module.scss +119 -0
- package/dist/components/upload-list/index.d.ts +15 -0
- package/dist/components/upload-list/index.js +90 -0
- package/dist/components/upload-list/index.module.scss +119 -0
- package/dist/components/voice-bars/index.d.ts +4 -0
- package/dist/components/voice-bars/index.js +174 -0
- package/dist/components/voice-check-dialog/index.d.ts +8 -0
- package/dist/components/voice-check-dialog/index.js +163 -0
- package/dist/components/voice-check-dialog/index.module.scss +9 -0
- package/dist/components/voice-recording/index.d.ts +9 -0
- package/dist/components/voice-recording/index.js +54 -0
- package/dist/components/voice-recording/index.module.scss +41 -0
- package/dist/components/work-flow-content/demo.d.ts +3 -0
- package/dist/components/work-flow-content/demo.js +11 -0
- package/dist/components/work-flow-content/index.d.ts +6 -0
- package/dist/components/work-flow-content/index.js +55 -0
- package/dist/components/work-flow-content/index.module.scss +23 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.js +24 -0
- package/dist/hooks/useChatActions.d.ts +12 -0
- package/dist/hooks/useChatActions.js +207 -0
- package/dist/hooks/useChatHistory.d.ts +8 -0
- package/dist/hooks/useChatHistory.js +225 -0
- package/dist/hooks/useChatMessage.d.ts +49 -0
- package/dist/hooks/useChatMessage.js +87 -0
- package/dist/hooks/useChatRecommend.d.ts +8 -0
- package/dist/hooks/useChatRecommend.js +126 -0
- package/dist/hooks/useChatStream.d.ts +20 -0
- package/dist/hooks/useChatStream.js +244 -0
- package/dist/hooks/useChatUI.d.ts +32 -0
- package/dist/hooks/useChatUI.js +134 -0
- package/dist/hooks/useChatVoice.d.ts +11 -0
- package/dist/hooks/useChatVoice.js +379 -0
- package/dist/hooks/useCommonChatAPI.d.ts +27 -0
- package/dist/hooks/useCommonChatAPI.js +1276 -0
- package/dist/hooks/useFile.d.ts +13 -0
- package/dist/hooks/useFile.js +288 -0
- package/dist/hooks/useKnowledgeService.d.ts +17 -0
- package/dist/hooks/useKnowledgeService.js +210 -0
- package/dist/hooks/useLastEventId.d.ts +8 -0
- package/dist/hooks/useLastEventId.js +66 -0
- package/dist/hooks/useLongPoll.d.ts +3 -0
- package/dist/hooks/useLongPoll.js +111 -0
- package/dist/hooks/useScroll.d.ts +4 -0
- package/dist/hooks/useScroll.js +172 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interfaces/chatMessage.d.ts +139 -0
- package/dist/interfaces/fileInterface.d.ts +10 -0
- package/dist/interfaces/fileInterface.js +11 -0
- package/dist/interfaces/knowledgeTrace.d.ts +177 -0
- package/dist/store/hooks.d.ts +4 -0
- package/dist/store/hooks.js +3 -0
- package/dist/store/index.d.ts +7 -0
- package/dist/store/index.js +7 -0
- package/dist/store/slices/gimiMenuSlice.d.ts +95 -0
- package/dist/store/slices/gimiMenuSlice.js +251 -0
- package/dist/utils/chatInputUtil.d.ts +19 -0
- package/dist/utils/chatInputUtil.js +45 -0
- package/dist/utils/tools.d.ts +50 -0
- package/dist/utils/tools.js +474 -0
- package/dist/utils/voice-stream.d.ts +119 -0
- package/dist/utils/voice-stream.js +1162 -0
- package/package.json +2 -3
- package/LICENSE +0 -21
|
@@ -0,0 +1,1056 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
6
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
8
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
9
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
10
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
11
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
12
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
13
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
14
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
15
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
16
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
17
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
18
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
19
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
20
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
21
|
+
import React, { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
|
|
22
|
+
import LottieImg from "../lottie-img";
|
|
23
|
+
import styles from "./index.module.scss";
|
|
24
|
+
import classNames from 'classnames';
|
|
25
|
+
import { Toast, Tooltip } from '@douyinfe/semi-ui';
|
|
26
|
+
import Header from "../header";
|
|
27
|
+
import IconFontCom from "../iconfont-com";
|
|
28
|
+
import { debounce } from 'lodash';
|
|
29
|
+
import useScroll from "../../hooks/useScroll";
|
|
30
|
+
// import { useUnload } from '@/utils/custom-hooks';
|
|
31
|
+
import { VolcVoiceCallClient } from "./volc-voice-call-client";
|
|
32
|
+
import { AGENT_BRIEF, parseVolcBinaryMessage } from "./message-parser";
|
|
33
|
+
import useApi from "../../apis/useApi";
|
|
34
|
+
import { Spin } from '@douyinfe/semi-ui';
|
|
35
|
+
import { createPortal } from 'react-dom';
|
|
36
|
+
import { useDispatch } from 'react-redux';
|
|
37
|
+
|
|
38
|
+
// 2. 定义组件完整的 Props 接口
|
|
39
|
+
|
|
40
|
+
var AiExplain = /*#__PURE__*/forwardRef(function (_ref) {
|
|
41
|
+
var paper = _ref.paper,
|
|
42
|
+
setSpeech = _ref.setSpeech,
|
|
43
|
+
_ref$handleHangUp = _ref.handleHangUp,
|
|
44
|
+
handleHangUp = _ref$handleHangUp === void 0 ? function () {} : _ref$handleHangUp;
|
|
45
|
+
var _useState = useState(true),
|
|
46
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
47
|
+
showCaptions = _useState2[0],
|
|
48
|
+
setShowCaptions = _useState2[1]; // 是否打开字幕
|
|
49
|
+
var _useState3 = useState(false),
|
|
50
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
51
|
+
isDisable = _useState4[0],
|
|
52
|
+
setIsDisable = _useState4[1];
|
|
53
|
+
var _useState5 = useState('新对话'),
|
|
54
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
55
|
+
headerTitle = _useState6[0],
|
|
56
|
+
setHeaderTitle = _useState6[1];
|
|
57
|
+
var clientRef = useRef(null);
|
|
58
|
+
var containerRef = useRef(null);
|
|
59
|
+
var _useState7 = useState(true),
|
|
60
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
61
|
+
audioEnabled = _useState8[0],
|
|
62
|
+
setAudioEnabled = _useState8[1]; // 是否打开声音
|
|
63
|
+
var _useState9 = useState(0),
|
|
64
|
+
_useState10 = _slicedToArray(_useState9, 2),
|
|
65
|
+
status = _useState10[0],
|
|
66
|
+
setStatus = _useState10[1]; // 状态 0 连接中 1 正在说话 2 ai回复中 3 静音 4 连接失败 5 连接成功后显示请说话。。。
|
|
67
|
+
var _useState11 = useState(null),
|
|
68
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
69
|
+
oldStatus = _useState12[0],
|
|
70
|
+
setOldStatus = _useState12[1];
|
|
71
|
+
// 是否是正在思考状态(强关联火山接口)
|
|
72
|
+
var _useState13 = useState(false),
|
|
73
|
+
_useState14 = _slicedToArray(_useState13, 2),
|
|
74
|
+
isThinking = _useState14[0],
|
|
75
|
+
setIsThinking = _useState14[1];
|
|
76
|
+
// 实时语音回复消息列表
|
|
77
|
+
var _useState15 = useState([]),
|
|
78
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
79
|
+
messageList = _useState16[0],
|
|
80
|
+
setMessageList = _useState16[1];
|
|
81
|
+
var ref1 = useRef(null); // 用来记录是否第一次说话 6 第一次说话后显示正在听
|
|
82
|
+
var audioEnabledRef = useRef(audioEnabled); // 解决事件监听中闭包问题
|
|
83
|
+
var timer = useRef(null);
|
|
84
|
+
// 是否是首次进入
|
|
85
|
+
var _useState17 = useState(false),
|
|
86
|
+
_useState18 = _slicedToArray(_useState17, 2),
|
|
87
|
+
isFirstUse = _useState18[0],
|
|
88
|
+
setIsFirstUse = _useState18[1];
|
|
89
|
+
// 文本的looding状态
|
|
90
|
+
var _useState19 = useState(false),
|
|
91
|
+
_useState20 = _slicedToArray(_useState19, 2),
|
|
92
|
+
isTextLoading = _useState20[0],
|
|
93
|
+
setIsTextLoading = _useState20[1];
|
|
94
|
+
var _useScroll = useScroll(containerRef),
|
|
95
|
+
_useScroll2 = _slicedToArray(_useScroll, 2),
|
|
96
|
+
throttledScrollToBottom = _useScroll2[0],
|
|
97
|
+
scrollBottomForce = _useScroll2[1];
|
|
98
|
+
var _useApi = useApi(),
|
|
99
|
+
_startVoiceChat = _useApi.startVoiceChat,
|
|
100
|
+
_stopVoiceChat = _useApi.stopVoiceChat,
|
|
101
|
+
getUserFirstUse = _useApi.getUserFirstUse,
|
|
102
|
+
getRtcConfig = _useApi.getRtcConfig;
|
|
103
|
+
var dispatch = useDispatch();
|
|
104
|
+
var UNSUPPORTED_CALL_MSG_KEY = 'ai-chat-unsupported-call';
|
|
105
|
+
var unsupportedShownRef = useRef(false);
|
|
106
|
+
var renderStatus = useMemo(function () {
|
|
107
|
+
if (!audioEnabled) {
|
|
108
|
+
if (isThinking) return /*#__PURE__*/React.createElement("div", {
|
|
109
|
+
className: styles.statusText
|
|
110
|
+
}, '你已静音(正在思考中)', " ");
|
|
111
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
112
|
+
className: styles.statusText
|
|
113
|
+
}, '你已静音');
|
|
114
|
+
}
|
|
115
|
+
switch (status) {
|
|
116
|
+
case 0:
|
|
117
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LottieImg, {
|
|
118
|
+
name: "aiLoading",
|
|
119
|
+
size: [30, 50]
|
|
120
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
121
|
+
className: styles.statusText
|
|
122
|
+
}, "\u6B63\u5728\u8FDE\u63A5"));
|
|
123
|
+
case 1:
|
|
124
|
+
case 6:
|
|
125
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LottieImg, {
|
|
126
|
+
name: "aiOutputLoading",
|
|
127
|
+
size: [34, 60]
|
|
128
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
129
|
+
className: styles.statusText
|
|
130
|
+
}, "\u6B63\u5728\u8046\u542C"));
|
|
131
|
+
case 2:
|
|
132
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
133
|
+
className: styles.statusImg
|
|
134
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
135
|
+
className: styles.iconOutside
|
|
136
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
137
|
+
className: styles.iconInside
|
|
138
|
+
}))), /*#__PURE__*/React.createElement("div", {
|
|
139
|
+
className: styles.statusText
|
|
140
|
+
}, "\u8BF4\u8BDD\u6216\u70B9\u51FB\u53EF\u4EE5\u6253\u65AD\u6211"));
|
|
141
|
+
case 4:
|
|
142
|
+
// 网络错误状态打断TextLoading
|
|
143
|
+
setIsTextLoading(false);
|
|
144
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
145
|
+
className: classNames(styles.statusText, styles.danger, styles.pointer)
|
|
146
|
+
}, "\u70B9\u51FB\u91CD\u65B0\u8FDE\u63A5"));
|
|
147
|
+
case 5:
|
|
148
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LottieImg, {
|
|
149
|
+
name: "aiOutputLoading",
|
|
150
|
+
size: [34, 60]
|
|
151
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
152
|
+
className: styles.statusText
|
|
153
|
+
}, "\u4F60\u53EF\u4EE5\u5F00\u59CB\u8BF4\u8BDD"));
|
|
154
|
+
case 7:
|
|
155
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LottieImg, {
|
|
156
|
+
name: "aiOutputLoading",
|
|
157
|
+
size: [34, 60]
|
|
158
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
159
|
+
className: styles.statusText
|
|
160
|
+
}, "\u6B63\u5728\u601D\u8003"));
|
|
161
|
+
default:
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}, [status, audioEnabled, isThinking]);
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 拆分混杂字符串中的「纯文字内容」和「moduleType开头的JSON对象」
|
|
168
|
+
* @param str 原始混杂字符串(中文+JSON,JSON含嵌套花括号)
|
|
169
|
+
* @returns { text: 纯文字内容, json: 解析后的JSON对象 | null }
|
|
170
|
+
*/
|
|
171
|
+
function splitTextAndModuleTypeJson(str) {
|
|
172
|
+
// 定位 "moduleType" 锚点(JSON的核心标识)
|
|
173
|
+
var moduleTypeAnchor = '"moduleType"';
|
|
174
|
+
var anchorIndex = str.indexOf(moduleTypeAnchor);
|
|
175
|
+
|
|
176
|
+
// 情况1:无moduleType,全部视为纯文字
|
|
177
|
+
if (anchorIndex === -1) {
|
|
178
|
+
return {
|
|
179
|
+
text: str.trim(),
|
|
180
|
+
json: null
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 向前找JSON起始的 {(处理中文和花括号穿插的情况)
|
|
185
|
+
var jsonStartIdx = -1;
|
|
186
|
+
for (var i = anchorIndex - 1; i >= 0; i--) {
|
|
187
|
+
if (str[i] === '{') {
|
|
188
|
+
jsonStartIdx = i;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// 未找到JSON起始{,全部视为纯文字
|
|
193
|
+
if (jsonStartIdx === -1) {
|
|
194
|
+
return {
|
|
195
|
+
text: str.trim(),
|
|
196
|
+
json: null
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 3. 向后匹配嵌套花括号,找到JSON结束的 }
|
|
201
|
+
var braceCount = 0;
|
|
202
|
+
var jsonEndIdx = -1;
|
|
203
|
+
for (var _i = jsonStartIdx; _i < str.length; _i++) {
|
|
204
|
+
if (str[_i] === '{') braceCount++;
|
|
205
|
+
if (str[_i] === '}') braceCount--;
|
|
206
|
+
|
|
207
|
+
// 计数器归0 = 最外层花括号闭合(匹配完成)
|
|
208
|
+
if (braceCount === 0) {
|
|
209
|
+
jsonEndIdx = _i;
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// 未找到匹配的结束},全部视为纯文字
|
|
214
|
+
if (jsonEndIdx === -1) {
|
|
215
|
+
return {
|
|
216
|
+
text: str.trim(),
|
|
217
|
+
json: null
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 4. 拆分文字和JSON(处理JSON前后的文字)
|
|
222
|
+
// 纯文字 = JSON前的文字 + JSON后的文字
|
|
223
|
+
var textBeforeJson = str.slice(0, jsonStartIdx).trim();
|
|
224
|
+
var textAfterJson = str.slice(jsonEndIdx + 1).trim();
|
|
225
|
+
var pureText = "".concat(textBeforeJson, " ").concat(textAfterJson).trim();
|
|
226
|
+
|
|
227
|
+
// 5. 解析JSON(容错处理)
|
|
228
|
+
var parsedJson = null;
|
|
229
|
+
try {
|
|
230
|
+
var jsonStr = str.slice(jsonStartIdx, jsonEndIdx + 1);
|
|
231
|
+
parsedJson = JSON.parse(jsonStr);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error('JSON解析失败:', error);
|
|
234
|
+
// 解析失败时,文字包含全部内容,JSON为null
|
|
235
|
+
return {
|
|
236
|
+
text: str.trim(),
|
|
237
|
+
json: null
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
text: pureText,
|
|
242
|
+
json: parsedJson
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 静音
|
|
247
|
+
var handleVoice = /*#__PURE__*/function () {
|
|
248
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(flag) {
|
|
249
|
+
var enable, _clientRef$current;
|
|
250
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
251
|
+
while (1) switch (_context.prev = _context.next) {
|
|
252
|
+
case 0:
|
|
253
|
+
if (navigator.onLine) {
|
|
254
|
+
_context.next = 3;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
Toast.error('无法连接到网络');
|
|
258
|
+
return _context.abrupt("return");
|
|
259
|
+
case 3:
|
|
260
|
+
enable = flag === undefined ? audioEnabled : flag;
|
|
261
|
+
_context.prev = 4;
|
|
262
|
+
_context.next = 7;
|
|
263
|
+
return (_clientRef$current = clientRef.current) === null || _clientRef$current === void 0 ? void 0 : _clientRef$current.setAudioEnable(!enable);
|
|
264
|
+
case 7:
|
|
265
|
+
if (status !== 4) {
|
|
266
|
+
if (enable) {
|
|
267
|
+
if (status === 7 || status === 2) {
|
|
268
|
+
setOldStatus(status);
|
|
269
|
+
} else {
|
|
270
|
+
setOldStatus(null);
|
|
271
|
+
}
|
|
272
|
+
setStatus(3);
|
|
273
|
+
} else {
|
|
274
|
+
// 当前为静音状态时解除静音,状态同步 (目前逻辑有历史记录就为正在聆听否则为你可以开始说话)
|
|
275
|
+
// messageList.length > 0 ? setStatus(1) : setStatus(5);
|
|
276
|
+
// if (!messageList.length) {
|
|
277
|
+
// setStatus(5);
|
|
278
|
+
// } else if (status !== 7 && status !== 2) {
|
|
279
|
+
// // 如果当前静音后不是思考状态也不是ai回复中的状态就让状态为正在聆听
|
|
280
|
+
// setStatus(1);
|
|
281
|
+
// }
|
|
282
|
+
if (status !== 2 && status !== 7) {
|
|
283
|
+
if (!messageList.length) {
|
|
284
|
+
setStatus(5); // 你可以开始说话
|
|
285
|
+
} else {
|
|
286
|
+
if (status === 3 && oldStatus) {
|
|
287
|
+
setStatus(oldStatus);
|
|
288
|
+
} else {
|
|
289
|
+
setStatus(1); // 正在聆听
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
setAudioEnabled(!enable);
|
|
296
|
+
_context.next = 13;
|
|
297
|
+
break;
|
|
298
|
+
case 11:
|
|
299
|
+
_context.prev = 11;
|
|
300
|
+
_context.t0 = _context["catch"](4);
|
|
301
|
+
case 13:
|
|
302
|
+
case "end":
|
|
303
|
+
return _context.stop();
|
|
304
|
+
}
|
|
305
|
+
}, _callee, null, [[4, 11]]);
|
|
306
|
+
}));
|
|
307
|
+
return function handleVoice(_x) {
|
|
308
|
+
return _ref2.apply(this, arguments);
|
|
309
|
+
};
|
|
310
|
+
}();
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 合并相邻的answer条目(以question为分隔符)
|
|
314
|
+
* @param messageList 原始消息列表
|
|
315
|
+
* @returns 合并后的新列表
|
|
316
|
+
*/
|
|
317
|
+
function mergeAnswerByQuestion(messageList) {
|
|
318
|
+
var mergedList = [];
|
|
319
|
+
var tempAnswers = []; // 暂存待合并的answer
|
|
320
|
+
var _iterator = _createForOfIteratorHelper(messageList),
|
|
321
|
+
_step;
|
|
322
|
+
try {
|
|
323
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
324
|
+
var item = _step.value;
|
|
325
|
+
if (item.type === 'question') {
|
|
326
|
+
// 遇到question:先合并之前暂存的answer,再添加当前question
|
|
327
|
+
if (tempAnswers.length > 0) {
|
|
328
|
+
// 合并answer:拼接content,其他字段取最后一个
|
|
329
|
+
var _mergedAnswer = _objectSpread(_objectSpread({}, tempAnswers[tempAnswers.length - 1]), {}, {
|
|
330
|
+
// 取最后一个的id/type/definite
|
|
331
|
+
content: tempAnswers.map(function (ans) {
|
|
332
|
+
return ans.content;
|
|
333
|
+
}).join('') // 拼接所有content
|
|
334
|
+
});
|
|
335
|
+
mergedList.push(_mergedAnswer);
|
|
336
|
+
tempAnswers = []; // 清空暂存
|
|
337
|
+
}
|
|
338
|
+
mergedList.push(item); // 添加当前question
|
|
339
|
+
} else if (item.type === 'answer') {
|
|
340
|
+
// 遇到answer:暂存起来
|
|
341
|
+
tempAnswers.push(item);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 处理列表末尾剩余的answer(如果有)
|
|
346
|
+
} catch (err) {
|
|
347
|
+
_iterator.e(err);
|
|
348
|
+
} finally {
|
|
349
|
+
_iterator.f();
|
|
350
|
+
}
|
|
351
|
+
if (tempAnswers.length > 0) {
|
|
352
|
+
var mergedAnswer = _objectSpread(_objectSpread({}, tempAnswers[tempAnswers.length - 1]), {}, {
|
|
353
|
+
content: tempAnswers.map(function (ans) {
|
|
354
|
+
return ans.content;
|
|
355
|
+
}).join('')
|
|
356
|
+
});
|
|
357
|
+
mergedList.push(mergedAnswer);
|
|
358
|
+
}
|
|
359
|
+
return mergedList;
|
|
360
|
+
}
|
|
361
|
+
var initClient = /*#__PURE__*/function () {
|
|
362
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
|
|
363
|
+
var _data$VoiceChat;
|
|
364
|
+
var res, data, rtc, startVoiceChatParams, stopVoiceChatParams, client;
|
|
365
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
366
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
367
|
+
case 0:
|
|
368
|
+
_context2.prev = 0;
|
|
369
|
+
_context2.next = 3;
|
|
370
|
+
return navigator.mediaDevices.getUserMedia({
|
|
371
|
+
audio: true
|
|
372
|
+
});
|
|
373
|
+
case 3:
|
|
374
|
+
_context2.next = 9;
|
|
375
|
+
break;
|
|
376
|
+
case 5:
|
|
377
|
+
_context2.prev = 5;
|
|
378
|
+
_context2.t0 = _context2["catch"](0);
|
|
379
|
+
dispatch({
|
|
380
|
+
type: 'gimiMenu/setShowMicWarning',
|
|
381
|
+
payload: {
|
|
382
|
+
showMicWarning: true
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
throw new Error('需要麦克风访问权限');
|
|
386
|
+
case 9:
|
|
387
|
+
_context2.next = 11;
|
|
388
|
+
return getRtcConfig();
|
|
389
|
+
case 11:
|
|
390
|
+
res = _context2.sent;
|
|
391
|
+
data = res.result;
|
|
392
|
+
rtc = {
|
|
393
|
+
appId: data.RTCConfig.AppId,
|
|
394
|
+
roomId: data.RTCConfig.RoomId,
|
|
395
|
+
custom: {
|
|
396
|
+
botId: paper.botId,
|
|
397
|
+
conversationId: paper.conversationId
|
|
398
|
+
},
|
|
399
|
+
userId: data.RTCConfig.UserId,
|
|
400
|
+
taskId: data === null || data === void 0 || (_data$VoiceChat = data.VoiceChat) === null || _data$VoiceChat === void 0 ? void 0 : _data$VoiceChat.TaskId,
|
|
401
|
+
token: data === null || data === void 0 ? void 0 : data.RTCConfig.Token
|
|
402
|
+
};
|
|
403
|
+
if (!(!(rtc !== null && rtc !== void 0 && rtc.appId) || !(rtc !== null && rtc !== void 0 && rtc.roomId) || !(rtc !== null && rtc !== void 0 && rtc.userId) || !(rtc !== null && rtc !== void 0 && rtc.token))) {
|
|
404
|
+
_context2.next = 16;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
throw new Error('RTC 配置不完整');
|
|
408
|
+
case 16:
|
|
409
|
+
startVoiceChatParams = {
|
|
410
|
+
roomId: rtc.roomId,
|
|
411
|
+
taskId: rtc.taskId,
|
|
412
|
+
custom: rtc.custom
|
|
413
|
+
};
|
|
414
|
+
stopVoiceChatParams = {
|
|
415
|
+
appId: rtc.appId,
|
|
416
|
+
roomId: rtc.roomId,
|
|
417
|
+
taskId: rtc.taskId
|
|
418
|
+
}; // 创建 VolcVoiceCallClient 实例
|
|
419
|
+
client = new VolcVoiceCallClient({
|
|
420
|
+
rtcConfig: {
|
|
421
|
+
appId: rtc.appId,
|
|
422
|
+
roomId: rtc.roomId,
|
|
423
|
+
userId: rtc.userId,
|
|
424
|
+
token: rtc.token,
|
|
425
|
+
// agentName: rtc.agentName,
|
|
426
|
+
agentName: paper.botId + paper.conversationId
|
|
427
|
+
},
|
|
428
|
+
startVoiceChat: function startVoiceChat(p) {
|
|
429
|
+
return _startVoiceChat(p);
|
|
430
|
+
},
|
|
431
|
+
stopVoiceChat: function stopVoiceChat(p) {
|
|
432
|
+
return _stopVoiceChat(p);
|
|
433
|
+
},
|
|
434
|
+
startVoiceChatParams: startVoiceChatParams,
|
|
435
|
+
stopVoiceChatParams: stopVoiceChatParams
|
|
436
|
+
});
|
|
437
|
+
client.onError(function (err) {
|
|
438
|
+
console.log(err);
|
|
439
|
+
});
|
|
440
|
+
// 消息回复回调
|
|
441
|
+
client.onBinaryMessage(function (buffer) {
|
|
442
|
+
var info = new TextDecoder().decode(buffer);
|
|
443
|
+
|
|
444
|
+
// 解析二进制消息(转成前端可识别的格式)
|
|
445
|
+
var evt = parseVolcBinaryMessage(buffer);
|
|
446
|
+
console.log(evt);
|
|
447
|
+
console.log(info);
|
|
448
|
+
if (!evt) return;
|
|
449
|
+
if (evt.kind === 'subtitle') {
|
|
450
|
+
var text = evt.text,
|
|
451
|
+
userId = evt.userId,
|
|
452
|
+
definite = evt.definite;
|
|
453
|
+
if (!text) return;
|
|
454
|
+
|
|
455
|
+
// 归属:userId === 自己 => question,否则 answer
|
|
456
|
+
var msgType = userId && rtc.userId && userId === rtc.userId ? 'question' : 'answer';
|
|
457
|
+
// 当用户说话时TextLoading一定不存在
|
|
458
|
+
if (msgType === 'question') {
|
|
459
|
+
setIsTextLoading(false);
|
|
460
|
+
} else {
|
|
461
|
+
// 有文字返回状态则切换为正在说话
|
|
462
|
+
setStatus(2);
|
|
463
|
+
}
|
|
464
|
+
if (text.includes('moduleType')) {
|
|
465
|
+
var textData = splitTextAndModuleTypeJson(text).json || {};
|
|
466
|
+
// 标准通话模式文字回显结束停止文字加载
|
|
467
|
+
if (textData.moduleType === 'end' && textData.conversationStatus && textData.conversationStatus === 'stop') {
|
|
468
|
+
setIsTextLoading(false);
|
|
469
|
+
}
|
|
470
|
+
// 卡片和问答直接关闭
|
|
471
|
+
if (textData.moduleType === 'skill' || textData.moduleType === 'ask') {
|
|
472
|
+
// 关闭loading
|
|
473
|
+
setIsTextLoading(false);
|
|
474
|
+
}
|
|
475
|
+
if (textData.answerType === 1 || textData.moduleType === 'skill') {
|
|
476
|
+
var _clientRef$current2, _clientRef$current2$m;
|
|
477
|
+
// 静音点击置灰
|
|
478
|
+
setIsDisable(true);
|
|
479
|
+
// 静音
|
|
480
|
+
handleVoice(true);
|
|
481
|
+
// 静音播放
|
|
482
|
+
(_clientRef$current2 = clientRef.current) === null || _clientRef$current2 === void 0 || (_clientRef$current2$m = _clientRef$current2.mutePlayback) === null || _clientRef$current2$m === void 0 || _clientRef$current2$m.call(_clientRef$current2);
|
|
483
|
+
|
|
484
|
+
// 关键1:创建提示框前,先销毁旧的(避免多个提示框)
|
|
485
|
+
// if (warningMessageRef.current) {
|
|
486
|
+
// message.destroy(); // 销毁所有 message,包括当前警告框
|
|
487
|
+
// warningMessageRef.current = null;
|
|
488
|
+
// }
|
|
489
|
+
// warningMessageRef.current = message.open({
|
|
490
|
+
// type: 'warning',
|
|
491
|
+
// content: '后续流程暂不支持通话展示,可挂断后继续',
|
|
492
|
+
// duration: 0,
|
|
493
|
+
// style: {
|
|
494
|
+
// marginTop: '30vh',
|
|
495
|
+
// },
|
|
496
|
+
// });
|
|
497
|
+
if (!unsupportedShownRef.current) {
|
|
498
|
+
unsupportedShownRef.current = true;
|
|
499
|
+
}
|
|
500
|
+
Toast.warning({
|
|
501
|
+
id: UNSUPPORTED_CALL_MSG_KEY,
|
|
502
|
+
content: '后续流程暂不支持通话展示,可挂断后继续',
|
|
503
|
+
duration: 0,
|
|
504
|
+
style: {
|
|
505
|
+
marginTop: '30vh'
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// 增量更新字幕列表(核心优化:避免重复创建条目)
|
|
513
|
+
setMessageList(function (prev) {
|
|
514
|
+
var lastIdx = _toConsumableArray(prev).reverse().findIndex(function (m) {
|
|
515
|
+
return m.type === msgType;
|
|
516
|
+
});
|
|
517
|
+
var idx = lastIdx === -1 ? -1 : prev.length - 1 - lastIdx;
|
|
518
|
+
var last = idx >= 0 ? prev[idx] : null;
|
|
519
|
+
// 如果上一条同侧字幕还在增量中(definite=false),继续更新它
|
|
520
|
+
|
|
521
|
+
if (last && !last.definite) {
|
|
522
|
+
var copy = prev.slice();
|
|
523
|
+
copy[idx] = _objectSpread(_objectSpread({}, last), {}, {
|
|
524
|
+
content: text,
|
|
525
|
+
definite: !!definite
|
|
526
|
+
});
|
|
527
|
+
return copy;
|
|
528
|
+
}
|
|
529
|
+
if (!text.includes('moduleType')) {
|
|
530
|
+
// 否则新增一条(上一条已经 definite 或者不存在)
|
|
531
|
+
var answerData = [].concat(_toConsumableArray(prev), [{
|
|
532
|
+
id: "".concat(Date.now(), "-").concat(msgType),
|
|
533
|
+
type: msgType,
|
|
534
|
+
content: text,
|
|
535
|
+
definite: !!definite
|
|
536
|
+
}]);
|
|
537
|
+
return mergeAnswerByQuestion(answerData);
|
|
538
|
+
} else {
|
|
539
|
+
// 存在moduleType
|
|
540
|
+
var parsed = splitTextAndModuleTypeJson(text);
|
|
541
|
+
// 获取字符串的纯文本
|
|
542
|
+
var pureText = parsed.text;
|
|
543
|
+
// 存在纯文本就推进信息流中,不存在的话不推入信息流
|
|
544
|
+
if (pureText) {
|
|
545
|
+
var _answerData = [].concat(_toConsumableArray(prev), [{
|
|
546
|
+
id: "".concat(Date.now(), "-").concat(msgType),
|
|
547
|
+
type: msgType,
|
|
548
|
+
content: pureText,
|
|
549
|
+
definite: !!definite
|
|
550
|
+
}]);
|
|
551
|
+
return mergeAnswerByQuestion(_answerData);
|
|
552
|
+
} else {
|
|
553
|
+
return _toConsumableArray(prev);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
if (evt.kind === 'brief') {
|
|
559
|
+
// 映射 status:AI 说话中 -> 2,结束 -> 1
|
|
560
|
+
if (evt.stageCode === AGENT_BRIEF.SPEAKING) setStatus(2);
|
|
561
|
+
if (evt.stageCode === AGENT_BRIEF.THINKING) {
|
|
562
|
+
// state改变状态 isThinking强关联是否在思考
|
|
563
|
+
setIsThinking(true);
|
|
564
|
+
setStatus(7);
|
|
565
|
+
} else {
|
|
566
|
+
setIsThinking(false);
|
|
567
|
+
}
|
|
568
|
+
if (evt.stageCode === AGENT_BRIEF.FINISHED) setStatus(1);
|
|
569
|
+
if (evt.stageCode === AGENT_BRIEF.INTERRUPTED) setStatus(1);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
clientRef.current = client;
|
|
574
|
+
case 22:
|
|
575
|
+
case "end":
|
|
576
|
+
return _context2.stop();
|
|
577
|
+
}
|
|
578
|
+
}, _callee2, null, [[0, 5]]);
|
|
579
|
+
}));
|
|
580
|
+
return function initClient() {
|
|
581
|
+
return _ref3.apply(this, arguments);
|
|
582
|
+
};
|
|
583
|
+
}();
|
|
584
|
+
|
|
585
|
+
// 断开连接
|
|
586
|
+
var handleDisconnect = /*#__PURE__*/function () {
|
|
587
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
|
|
588
|
+
var _clientRef$current3, _clientRef$current4;
|
|
589
|
+
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
590
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
591
|
+
case 0:
|
|
592
|
+
_context3.prev = 0;
|
|
593
|
+
// 销毁warning提示框
|
|
594
|
+
// if (warningMessageRef.current) {
|
|
595
|
+
// message.destroy(); // 销毁所有 message,包括当前警告框
|
|
596
|
+
// warningMessageRef.current = null;
|
|
597
|
+
// }
|
|
598
|
+
if (unsupportedShownRef.current) {
|
|
599
|
+
unsupportedShownRef.current = false;
|
|
600
|
+
Toast.close(UNSUPPORTED_CALL_MSG_KEY);
|
|
601
|
+
}
|
|
602
|
+
_context3.next = 4;
|
|
603
|
+
return (_clientRef$current3 = clientRef.current) === null || _clientRef$current3 === void 0 ? void 0 : _clientRef$current3.setAudioEnable(false);
|
|
604
|
+
case 4:
|
|
605
|
+
_context3.next = 6;
|
|
606
|
+
return (_clientRef$current4 = clientRef.current) === null || _clientRef$current4 === void 0 ? void 0 : _clientRef$current4.disconnect();
|
|
607
|
+
case 6:
|
|
608
|
+
clientRef.current = null;
|
|
609
|
+
_context3.next = 11;
|
|
610
|
+
break;
|
|
611
|
+
case 9:
|
|
612
|
+
_context3.prev = 9;
|
|
613
|
+
_context3.t0 = _context3["catch"](0);
|
|
614
|
+
case 11:
|
|
615
|
+
case "end":
|
|
616
|
+
return _context3.stop();
|
|
617
|
+
}
|
|
618
|
+
}, _callee3, null, [[0, 9]]);
|
|
619
|
+
}));
|
|
620
|
+
return function handleDisconnect() {
|
|
621
|
+
return _ref4.apply(this, arguments);
|
|
622
|
+
};
|
|
623
|
+
}();
|
|
624
|
+
// 启动 RTC 连接、初始化客户端、加入房间
|
|
625
|
+
var handleConnect = /*#__PURE__*/function () {
|
|
626
|
+
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
|
|
627
|
+
var _clientRef$current5, _ref1$current;
|
|
628
|
+
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
629
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
630
|
+
case 0:
|
|
631
|
+
_context4.prev = 0;
|
|
632
|
+
if (clientRef.current) {
|
|
633
|
+
_context4.next = 4;
|
|
634
|
+
break;
|
|
635
|
+
}
|
|
636
|
+
_context4.next = 4;
|
|
637
|
+
return initClient();
|
|
638
|
+
case 4:
|
|
639
|
+
_context4.next = 6;
|
|
640
|
+
return (_clientRef$current5 = clientRef.current) === null || _clientRef$current5 === void 0 ? void 0 : _clientRef$current5.connect();
|
|
641
|
+
case 6:
|
|
642
|
+
// 判断麦克风是否开启(再判断「是否首次说话 + 消息列表是否为空」)是的话 状态5:连接成功,提示「你可以开始说话」
|
|
643
|
+
// 否则 状态1:非首次/有消息,提示「正在聆听」,没开启则状态3:麦克风静音,提示「你已静音」
|
|
644
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
645
|
+
audioEnabledRef.current ? !((_ref1$current = ref1.current) !== null && _ref1$current !== void 0 && _ref1$current.status) && !messageList.length ? setStatus(5) : setStatus(1) : setStatus(3);
|
|
646
|
+
_context4.next = 16;
|
|
647
|
+
break;
|
|
648
|
+
case 9:
|
|
649
|
+
_context4.prev = 9;
|
|
650
|
+
_context4.t0 = _context4["catch"](0);
|
|
651
|
+
setStatus(4); // 状态4:连接失败,提示「点击重新连接」
|
|
652
|
+
if (!((_context4.t0 === null || _context4.t0 === void 0 ? void 0 : _context4.t0.message) === '需要麦克风访问权限')) {
|
|
653
|
+
_context4.next = 15;
|
|
654
|
+
break;
|
|
655
|
+
}
|
|
656
|
+
Toast.error('未开启麦克风权限');
|
|
657
|
+
return _context4.abrupt("return");
|
|
658
|
+
case 15:
|
|
659
|
+
Toast.error(_context4.t0 === null || _context4.t0 === void 0 ? void 0 : _context4.t0.message);
|
|
660
|
+
case 16:
|
|
661
|
+
case "end":
|
|
662
|
+
return _context4.stop();
|
|
663
|
+
}
|
|
664
|
+
}, _callee4, null, [[0, 9]]);
|
|
665
|
+
}));
|
|
666
|
+
return function handleConnect() {
|
|
667
|
+
return _ref5.apply(this, arguments);
|
|
668
|
+
};
|
|
669
|
+
}();
|
|
670
|
+
// 重新连接逻辑
|
|
671
|
+
var reconnect = /*#__PURE__*/function () {
|
|
672
|
+
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
|
|
673
|
+
return _regeneratorRuntime().wrap(function _callee5$(_context5) {
|
|
674
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
675
|
+
case 0:
|
|
676
|
+
setStatus(0);
|
|
677
|
+
_context5.next = 3;
|
|
678
|
+
return handleDisconnect();
|
|
679
|
+
case 3:
|
|
680
|
+
handleConnect();
|
|
681
|
+
case 4:
|
|
682
|
+
case "end":
|
|
683
|
+
return _context5.stop();
|
|
684
|
+
}
|
|
685
|
+
}, _callee5);
|
|
686
|
+
}));
|
|
687
|
+
return function reconnect() {
|
|
688
|
+
return _ref6.apply(this, arguments);
|
|
689
|
+
};
|
|
690
|
+
}();
|
|
691
|
+
|
|
692
|
+
// 打断
|
|
693
|
+
var handleInterrupt = function handleInterrupt() {
|
|
694
|
+
try {
|
|
695
|
+
var _clientRef$current6;
|
|
696
|
+
(_clientRef$current6 = clientRef.current) === null || _clientRef$current6 === void 0 || _clientRef$current6.interrupt();
|
|
697
|
+
} catch (_unused4) {}
|
|
698
|
+
};
|
|
699
|
+
// 防抖 限制打断 AI 按钮的频率
|
|
700
|
+
var clickInterrupt = debounce(function () {
|
|
701
|
+
// 校验1:检查网络是否在线
|
|
702
|
+
if (!navigator.onLine) {
|
|
703
|
+
Toast.error('无法连接到网络');
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
// 校验2:检查当前状态是否为“连接失败(status=4)”
|
|
707
|
+
if (status === 4) {
|
|
708
|
+
reconnect(); // 触发重新连接
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
// 校验3:仅当 AI 正在回复(status=2)时,执行打断
|
|
712
|
+
if (status === 2) {
|
|
713
|
+
handleInterrupt(); // 调用真正的打断逻辑
|
|
714
|
+
}
|
|
715
|
+
}, 400);
|
|
716
|
+
// 返回文字对话并断连接
|
|
717
|
+
var handleBack = /*#__PURE__*/function () {
|
|
718
|
+
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
|
|
719
|
+
return _regeneratorRuntime().wrap(function _callee6$(_context6) {
|
|
720
|
+
while (1) switch (_context6.prev = _context6.next) {
|
|
721
|
+
case 0:
|
|
722
|
+
// 销毁warning提示框
|
|
723
|
+
// if (warningMessageRef?.current) {
|
|
724
|
+
// message.destroy(); // 销毁所有 message,包括当前警告框
|
|
725
|
+
// warningMessageRef.current = null;
|
|
726
|
+
// }
|
|
727
|
+
|
|
728
|
+
setMessageList([]);
|
|
729
|
+
_context6.next = 3;
|
|
730
|
+
return handleDisconnect();
|
|
731
|
+
case 3:
|
|
732
|
+
setSpeech(false);
|
|
733
|
+
// 外部捕获挂断回调
|
|
734
|
+
if (handleHangUp) {
|
|
735
|
+
handleHangUp();
|
|
736
|
+
}
|
|
737
|
+
case 5:
|
|
738
|
+
case "end":
|
|
739
|
+
return _context6.stop();
|
|
740
|
+
}
|
|
741
|
+
}, _callee6);
|
|
742
|
+
}));
|
|
743
|
+
return function handleBack() {
|
|
744
|
+
return _ref7.apply(this, arguments);
|
|
745
|
+
};
|
|
746
|
+
}();
|
|
747
|
+
/** 获取用户是否是首次进入 */
|
|
748
|
+
var getUserFirstUseInfo = /*#__PURE__*/function () {
|
|
749
|
+
var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
|
|
750
|
+
var res;
|
|
751
|
+
return _regeneratorRuntime().wrap(function _callee7$(_context7) {
|
|
752
|
+
while (1) switch (_context7.prev = _context7.next) {
|
|
753
|
+
case 0:
|
|
754
|
+
_context7.prev = 0;
|
|
755
|
+
_context7.next = 3;
|
|
756
|
+
return getUserFirstUse({
|
|
757
|
+
type: 'voice'
|
|
758
|
+
});
|
|
759
|
+
case 3:
|
|
760
|
+
res = _context7.sent;
|
|
761
|
+
if (!(res.status !== 0)) {
|
|
762
|
+
_context7.next = 6;
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
return _context7.abrupt("return");
|
|
766
|
+
case 6:
|
|
767
|
+
setIsFirstUse((res === null || res === void 0 ? void 0 : res.result.isFirstUse) || false);
|
|
768
|
+
_context7.next = 13;
|
|
769
|
+
break;
|
|
770
|
+
case 9:
|
|
771
|
+
_context7.prev = 9;
|
|
772
|
+
_context7.t0 = _context7["catch"](0);
|
|
773
|
+
Toast.error(_context7.t0.message);
|
|
774
|
+
console.log(_context7.t0);
|
|
775
|
+
case 13:
|
|
776
|
+
case "end":
|
|
777
|
+
return _context7.stop();
|
|
778
|
+
}
|
|
779
|
+
}, _callee7, null, [[0, 9]]);
|
|
780
|
+
}));
|
|
781
|
+
return function getUserFirstUseInfo() {
|
|
782
|
+
return _ref8.apply(this, arguments);
|
|
783
|
+
};
|
|
784
|
+
}();
|
|
785
|
+
|
|
786
|
+
// 切换回字幕后滚到最底下
|
|
787
|
+
useEffect(function () {
|
|
788
|
+
if (showCaptions) scrollBottomForce();
|
|
789
|
+
}, [showCaptions]);
|
|
790
|
+
|
|
791
|
+
// 监听麦克风是否静音
|
|
792
|
+
useEffect(function () {
|
|
793
|
+
audioEnabledRef.current = audioEnabled;
|
|
794
|
+
}, [audioEnabled]);
|
|
795
|
+
|
|
796
|
+
// // 监听是否是思考状态从而改变lodding状态
|
|
797
|
+
useEffect(function () {
|
|
798
|
+
if (isThinking) {
|
|
799
|
+
setIsTextLoading(true);
|
|
800
|
+
}
|
|
801
|
+
}, [isThinking]);
|
|
802
|
+
useEffect(function () {
|
|
803
|
+
var _messageList$;
|
|
804
|
+
// 滚动到底部
|
|
805
|
+
throttledScrollToBottom();
|
|
806
|
+
if (messageList.length !== 1 || !((_messageList$ = messageList[0]) !== null && _messageList$ !== void 0 && _messageList$.content)) return;
|
|
807
|
+
// \p{P} 是 Unicode 属性转义,匹配所有标点符号(包含中文、英文、特殊符号等)
|
|
808
|
+
var punctuationRegex = /(?:[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDEAD\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F])/g;
|
|
809
|
+
// 提取第一条消息内容并过滤所有标点符号
|
|
810
|
+
var pureText = messageList[0].content.replace(punctuationRegex, '');
|
|
811
|
+
// 原始内容(保留标点)
|
|
812
|
+
var originalContent = messageList[0].content;
|
|
813
|
+
if (pureText.length <= 20) {
|
|
814
|
+
// 纯文字≤20:直接用原始内容
|
|
815
|
+
setHeaderTitle(originalContent);
|
|
816
|
+
} else {
|
|
817
|
+
var charCount = 0; // 统计纯文字数量
|
|
818
|
+
var result = ''; // 最终截取的内容
|
|
819
|
+
var _iterator2 = _createForOfIteratorHelper(originalContent),
|
|
820
|
+
_step2;
|
|
821
|
+
try {
|
|
822
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
823
|
+
var char = _step2.value;
|
|
824
|
+
// 遇到标点:直接加入结果,不计数
|
|
825
|
+
if (punctuationRegex.test(char)) {
|
|
826
|
+
result += char;
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
// 纯文字:计数+1,加入结果
|
|
830
|
+
charCount += 1;
|
|
831
|
+
result += char;
|
|
832
|
+
// 达到20个纯文字:停止遍历
|
|
833
|
+
if (charCount === 20) break;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// 检查截取结果最后一个字符是否是标点:是则替换为省略号,否则直接加
|
|
837
|
+
} catch (err) {
|
|
838
|
+
_iterator2.e(err);
|
|
839
|
+
} finally {
|
|
840
|
+
_iterator2.f();
|
|
841
|
+
}
|
|
842
|
+
var lastChar = result.slice(-1);
|
|
843
|
+
var finalTitle = punctuationRegex.test(lastChar) ? result.slice(0, -1) + '...' : result + '...';
|
|
844
|
+
setHeaderTitle(finalTitle);
|
|
845
|
+
}
|
|
846
|
+
}, [messageList]);
|
|
847
|
+
|
|
848
|
+
// 初始化语音对话(核心业务入口)
|
|
849
|
+
useEffect(function () {
|
|
850
|
+
handleConnect(); // 启动 RTC 连接、初始化客户端、加入房间
|
|
851
|
+
setShowCaptions(paper.enableCaptions); // 初始化字幕开关状态(从 paper 配置读取)
|
|
852
|
+
// 字幕标题三秒钟后隐藏
|
|
853
|
+
timer.current = setTimeout(function () {
|
|
854
|
+
setIsFirstUse(false);
|
|
855
|
+
}, 3000);
|
|
856
|
+
}, [paper]);
|
|
857
|
+
|
|
858
|
+
// 断开 RTC 连接、停止 AI 任务、释放麦克风
|
|
859
|
+
// useUnload(() => {
|
|
860
|
+
// console.log('页面卸载, 断开连接');
|
|
861
|
+
// if (warningMessageRef.current) {
|
|
862
|
+
// message.destroy();
|
|
863
|
+
// warningMessageRef.current = null;
|
|
864
|
+
// }
|
|
865
|
+
// handleDisconnect();
|
|
866
|
+
// });
|
|
867
|
+
useEffect(function () {
|
|
868
|
+
var onPageHide = function onPageHide(e) {
|
|
869
|
+
// 如果进入 bfcache(往返缓存),不一定要断开;你们按业务决定
|
|
870
|
+
// 一般实时通话建议断开,所以也可以不判断 persisted
|
|
871
|
+
if (e.persisted) return;
|
|
872
|
+
handleDisconnect();
|
|
873
|
+
};
|
|
874
|
+
// 有的浏览器 pagehide 覆盖更好,有的用 unload 兜底
|
|
875
|
+
window.addEventListener('pagehide', onPageHide);
|
|
876
|
+
window.addEventListener('unload', handleDisconnect);
|
|
877
|
+
return function () {
|
|
878
|
+
window.removeEventListener('pagehide', onPageHide);
|
|
879
|
+
window.removeEventListener('unload', handleDisconnect);
|
|
880
|
+
};
|
|
881
|
+
}, []);
|
|
882
|
+
|
|
883
|
+
// 页面刷新时,提示用户
|
|
884
|
+
useEffect(function () {
|
|
885
|
+
var handleBeforeUnload = function handleBeforeUnload(e) {
|
|
886
|
+
var isInCall = !!clientRef.current && status !== 4;
|
|
887
|
+
if (!isInCall) return;
|
|
888
|
+
e.preventDefault();
|
|
889
|
+
e.returnValue = '重新加载页面将结束当前语音通话,是否继续?';
|
|
890
|
+
return e.returnValue;
|
|
891
|
+
};
|
|
892
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
893
|
+
return function () {
|
|
894
|
+
return window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
895
|
+
};
|
|
896
|
+
}, [status]);
|
|
897
|
+
useEffect(function () {
|
|
898
|
+
// 监听页面可见性变化(比如用户切到其他标签页)
|
|
899
|
+
var handleVisibilityChange = /*#__PURE__*/function () {
|
|
900
|
+
var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8() {
|
|
901
|
+
return _regeneratorRuntime().wrap(function _callee8$(_context8) {
|
|
902
|
+
while (1) switch (_context8.prev = _context8.next) {
|
|
903
|
+
case 0:
|
|
904
|
+
if (!(document.visibilityState === 'visible')) {
|
|
905
|
+
_context8.next = 4;
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
console.log('页面显示');
|
|
909
|
+
_context8.next = 8;
|
|
910
|
+
break;
|
|
911
|
+
case 4:
|
|
912
|
+
console.log('页面隐藏--');
|
|
913
|
+
// 打断输出并且静音
|
|
914
|
+
_context8.next = 7;
|
|
915
|
+
return handleInterrupt();
|
|
916
|
+
case 7:
|
|
917
|
+
// 打断 AI 发言(避免用户切走后 AI 还在说话)
|
|
918
|
+
handleVoice(true); // 静音
|
|
919
|
+
case 8:
|
|
920
|
+
case "end":
|
|
921
|
+
return _context8.stop();
|
|
922
|
+
}
|
|
923
|
+
}, _callee8);
|
|
924
|
+
}));
|
|
925
|
+
return function handleVisibilityChange() {
|
|
926
|
+
return _ref9.apply(this, arguments);
|
|
927
|
+
};
|
|
928
|
+
}();
|
|
929
|
+
// 获取用户首次使用信息
|
|
930
|
+
getUserFirstUseInfo();
|
|
931
|
+
var handleLineChange = /*#__PURE__*/function () {
|
|
932
|
+
var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
|
|
933
|
+
return _regeneratorRuntime().wrap(function _callee9$(_context9) {
|
|
934
|
+
while (1) switch (_context9.prev = _context9.next) {
|
|
935
|
+
case 0:
|
|
936
|
+
Toast.error('无法连接到网络');
|
|
937
|
+
_context9.next = 3;
|
|
938
|
+
return handleDisconnect();
|
|
939
|
+
case 3:
|
|
940
|
+
// 断开RTC连接(避免无效重连)
|
|
941
|
+
setStatus(4); // 把状态改为「连接失败」,UI显示“点击重新连接”
|
|
942
|
+
case 4:
|
|
943
|
+
case "end":
|
|
944
|
+
return _context9.stop();
|
|
945
|
+
}
|
|
946
|
+
}, _callee9);
|
|
947
|
+
}));
|
|
948
|
+
return function handleLineChange() {
|
|
949
|
+
return _ref10.apply(this, arguments);
|
|
950
|
+
};
|
|
951
|
+
}();
|
|
952
|
+
// 挂载时绑定监听
|
|
953
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
954
|
+
// 监听设备网络断开
|
|
955
|
+
window.addEventListener('offline', handleLineChange);
|
|
956
|
+
// 卸载时移除监听(防止内存泄漏)
|
|
957
|
+
return function () {
|
|
958
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
959
|
+
window.removeEventListener('offline', handleLineChange);
|
|
960
|
+
clearTimeout(timer.current);
|
|
961
|
+
};
|
|
962
|
+
}, []);
|
|
963
|
+
return /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement("div", {
|
|
964
|
+
className: styles.aiChat
|
|
965
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
966
|
+
className: styles.bgImg
|
|
967
|
+
}, /*#__PURE__*/React.createElement(LottieImg, {
|
|
968
|
+
name: "aiBg",
|
|
969
|
+
size: ['100%', '100%']
|
|
970
|
+
})), /*#__PURE__*/React.createElement(Tooltip, {
|
|
971
|
+
placement: "bottomRight",
|
|
972
|
+
overlayClassName: "out-tooltip ai-chat-tooltip",
|
|
973
|
+
visible: isFirstUse,
|
|
974
|
+
title: showCaptions ? '点击可关闭字幕' : '点击可开启字幕'
|
|
975
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
976
|
+
className: styles.rightWrap
|
|
977
|
+
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
978
|
+
placement: "bottom",
|
|
979
|
+
title: showCaptions ? '关闭字幕' : '打开字幕',
|
|
980
|
+
overlayClassName: "ai-chat-tooltip"
|
|
981
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
982
|
+
className: styles.iconWrap
|
|
983
|
+
}, /*#__PURE__*/React.createElement(IconFontCom, {
|
|
984
|
+
type: !showCaptions ? 'icon-a-tongyong-zhankaibeifen1' : 'icon-tongyong-zhankaibeifen1',
|
|
985
|
+
size: 20,
|
|
986
|
+
extraStyle: {
|
|
987
|
+
cursor: 'pointer'
|
|
988
|
+
},
|
|
989
|
+
onClick: function onClick() {
|
|
990
|
+
return setShowCaptions(!showCaptions);
|
|
991
|
+
}
|
|
992
|
+
}))))), /*#__PURE__*/React.createElement("div", {
|
|
993
|
+
className: classNames(styles.main)
|
|
994
|
+
}, /*#__PURE__*/React.createElement(Header, {
|
|
995
|
+
title: headerTitle
|
|
996
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
997
|
+
className: classNames(styles.content, 'scrollBar'),
|
|
998
|
+
ref: containerRef
|
|
999
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1000
|
+
className: styles.container
|
|
1001
|
+
}, showCaptions ? status === 5 || status === 6 ? /*#__PURE__*/React.createElement("div", {
|
|
1002
|
+
className: styles.tips
|
|
1003
|
+
}, status === 5 ? '请说话' : '正在听...') : /*#__PURE__*/React.createElement("div", null, messageList.map(function (item) {
|
|
1004
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1005
|
+
className: classNames(styles.item, _defineProperty({}, styles.answer, item.type === 'answer')),
|
|
1006
|
+
key: item.id
|
|
1007
|
+
}, item.content);
|
|
1008
|
+
}), isTextLoading ? /*#__PURE__*/React.createElement(Spin, null) : null) : /*#__PURE__*/React.createElement("div", {
|
|
1009
|
+
className: styles.voiceWrap
|
|
1010
|
+
}, /*#__PURE__*/React.createElement(LottieImg, {
|
|
1011
|
+
name: status === 2 ? 'aiOutputStrengthen' : 'aiOutputNormal',
|
|
1012
|
+
size: [242, 235]
|
|
1013
|
+
}))), /*#__PURE__*/React.createElement("div", {
|
|
1014
|
+
className: styles.bottom
|
|
1015
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1016
|
+
className: classNames(styles.status, _defineProperty({}, styles.pointer, status === 2)),
|
|
1017
|
+
onClick: clickInterrupt
|
|
1018
|
+
}, renderStatus), /*#__PURE__*/React.createElement("div", {
|
|
1019
|
+
className: styles.btnWrap
|
|
1020
|
+
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
1021
|
+
placement: "top",
|
|
1022
|
+
visible: isFirstUse,
|
|
1023
|
+
title: audioEnabled ? '关闭麦克风' : '打开麦克风',
|
|
1024
|
+
overlayClassName: "ai-chat-tooltip"
|
|
1025
|
+
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
1026
|
+
placement: "top",
|
|
1027
|
+
title: audioEnabled ? '关闭麦克风' : '打开麦克风',
|
|
1028
|
+
overlayClassName: "ai-chat-tooltip"
|
|
1029
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1030
|
+
className: classNames(styles.btnItem, isDisable ? styles.disable : ''),
|
|
1031
|
+
onClick: function onClick() {
|
|
1032
|
+
return handleVoice();
|
|
1033
|
+
}
|
|
1034
|
+
}, /*#__PURE__*/React.createElement(IconFontCom, {
|
|
1035
|
+
type: audioEnabled ? 'icon-voice' : 'icon-a-voice1',
|
|
1036
|
+
size: 34
|
|
1037
|
+
})))), /*#__PURE__*/React.createElement(Tooltip, {
|
|
1038
|
+
placement: "top",
|
|
1039
|
+
visible: isFirstUse,
|
|
1040
|
+
title: '挂断电话',
|
|
1041
|
+
overlayClassName: "ai-chat-tooltip"
|
|
1042
|
+
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
1043
|
+
placement: "top",
|
|
1044
|
+
title: '挂断电话',
|
|
1045
|
+
overlayClassName: "ai-chat-tooltip"
|
|
1046
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1047
|
+
className: styles.btnItem,
|
|
1048
|
+
onClick: function onClick() {
|
|
1049
|
+
return handleBack();
|
|
1050
|
+
}
|
|
1051
|
+
}, /*#__PURE__*/React.createElement(IconFontCom, {
|
|
1052
|
+
type: "icon-a-mti-guaduanshi",
|
|
1053
|
+
size: 34
|
|
1054
|
+
}))))))))), document.body);
|
|
1055
|
+
});
|
|
1056
|
+
export default AiExplain;
|