byt-lingxiao-ai 0.2.4 → 0.2.6
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/components/AiMessage.vue +109 -0
- package/components/ChatAvatar.vue +86 -0
- package/components/ChatInputBox.vue +127 -0
- package/components/ChatMessageList.vue +81 -0
- package/components/ChatRobot.vue +38 -0
- package/components/ChatWindow.vue +78 -819
- package/components/ChatWindowDialog.vue +82 -0
- package/components/ChatWindowHeader.vue +98 -0
- package/components/UserMessage.vue +35 -0
- package/components/mixins/audioMixin.js +122 -0
- package/components/mixins/messageMixin.js +158 -0
- package/components/mixins/webSocketMixin.js +88 -0
- package/components/utils/StreamParser.js +277 -0
- package/dist/img/output.85c6bd8b.png +0 -0
- package/dist/img/thinking.05f29a84.png +0 -0
- package/dist/index.common.js +1363 -450
- package/dist/index.common.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.umd.js +1363 -450
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.common.js
CHANGED
|
@@ -3746,7 +3746,7 @@ if (typeof window !== 'undefined') {
|
|
|
3746
3746
|
var es_iterator_constructor = __webpack_require__(8111);
|
|
3747
3747
|
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.iterator.for-each.js
|
|
3748
3748
|
var es_iterator_for_each = __webpack_require__(7588);
|
|
3749
|
-
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=template&id=
|
|
3749
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=template&id=d604373c&scoped=true
|
|
3750
3750
|
var render = function render() {
|
|
3751
3751
|
var _vm = this,
|
|
3752
3752
|
_c = _vm._self._c;
|
|
@@ -3764,27 +3764,289 @@ var render = function render() {
|
|
|
3764
3764
|
"src": _vm.audioSrc,
|
|
3765
3765
|
"type": "audio/mpeg"
|
|
3766
3766
|
}
|
|
3767
|
-
}), _vm._v(" 您的浏览器不支持音频元素。 ")]), _vm.robotStatus !== 'leaving' ? _c('
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3767
|
+
}), _vm._v(" 您的浏览器不支持音频元素。 ")]), _vm.robotStatus !== 'leaving' ? _c('ChatRobot', {
|
|
3768
|
+
attrs: {
|
|
3769
|
+
"status": _vm.robotStatus
|
|
3770
|
+
}
|
|
3771
|
+
}) : _c('ChatAvatar', {
|
|
3772
|
+
attrs: {
|
|
3773
|
+
"status": _vm.avaterStatus
|
|
3774
|
+
},
|
|
3771
3775
|
on: {
|
|
3772
3776
|
"click": _vm.toggleWindow
|
|
3773
3777
|
}
|
|
3778
|
+
}), _c('ChatWindowDialog', {
|
|
3779
|
+
attrs: {
|
|
3780
|
+
"messages": _vm.messages,
|
|
3781
|
+
"input-message": _vm.inputMessage,
|
|
3782
|
+
"think-status": _vm.thinkStatus
|
|
3783
|
+
},
|
|
3784
|
+
on: {
|
|
3785
|
+
"update:inputMessage": function ($event) {
|
|
3786
|
+
_vm.inputMessage = $event;
|
|
3787
|
+
},
|
|
3788
|
+
"send": _vm.handleSend,
|
|
3789
|
+
"thinking-click": _vm.handleThinkingClick,
|
|
3790
|
+
"overlay-click": _vm.handleOverlayClick
|
|
3791
|
+
},
|
|
3792
|
+
model: {
|
|
3793
|
+
value: _vm.visible,
|
|
3794
|
+
callback: function ($$v) {
|
|
3795
|
+
_vm.visible = $$v;
|
|
3796
|
+
},
|
|
3797
|
+
expression: "visible"
|
|
3798
|
+
}
|
|
3799
|
+
})], 1);
|
|
3800
|
+
};
|
|
3801
|
+
var staticRenderFns = [];
|
|
3802
|
+
|
|
3803
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
|
|
3804
|
+
var es_array_push = __webpack_require__(4114);
|
|
3805
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.difference.v2.js
|
|
3806
|
+
var es_set_difference_v2 = __webpack_require__(7642);
|
|
3807
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.intersection.v2.js
|
|
3808
|
+
var es_set_intersection_v2 = __webpack_require__(8004);
|
|
3809
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js
|
|
3810
|
+
var es_set_is_disjoint_from_v2 = __webpack_require__(3853);
|
|
3811
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.is-subset-of.v2.js
|
|
3812
|
+
var es_set_is_subset_of_v2 = __webpack_require__(5876);
|
|
3813
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.is-superset-of.v2.js
|
|
3814
|
+
var es_set_is_superset_of_v2 = __webpack_require__(2475);
|
|
3815
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.symmetric-difference.v2.js
|
|
3816
|
+
var es_set_symmetric_difference_v2 = __webpack_require__(5024);
|
|
3817
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.set.union.v2.js
|
|
3818
|
+
var es_set_union_v2 = __webpack_require__(1698);
|
|
3819
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatRobot.vue?vue&type=template&id=3d936cb2&scoped=true
|
|
3820
|
+
var ChatRobotvue_type_template_id_3d936cb2_scoped_true_render = function render() {
|
|
3821
|
+
var _vm = this,
|
|
3822
|
+
_c = _vm._self._c;
|
|
3823
|
+
return _c('div', {
|
|
3824
|
+
class: ['chat-robot', _vm.status]
|
|
3825
|
+
});
|
|
3826
|
+
};
|
|
3827
|
+
var ChatRobotvue_type_template_id_3d936cb2_scoped_true_staticRenderFns = [];
|
|
3828
|
+
|
|
3829
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatRobot.vue?vue&type=script&lang=js
|
|
3830
|
+
/* harmony default export */ var ChatRobotvue_type_script_lang_js = ({
|
|
3831
|
+
name: 'ChatRobot',
|
|
3832
|
+
props: {
|
|
3833
|
+
status: {
|
|
3834
|
+
type: String,
|
|
3835
|
+
required: true,
|
|
3836
|
+
validator: value => ['entering', 'waiting', 'speaking'].includes(value)
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
});
|
|
3840
|
+
;// ./components/ChatRobot.vue?vue&type=script&lang=js
|
|
3841
|
+
/* harmony default export */ var components_ChatRobotvue_type_script_lang_js = (ChatRobotvue_type_script_lang_js);
|
|
3842
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatRobot.vue?vue&type=style&index=0&id=3d936cb2&prod&scoped=true&lang=css
|
|
3843
|
+
// extracted by mini-css-extract-plugin
|
|
3844
|
+
|
|
3845
|
+
;// ./components/ChatRobot.vue?vue&type=style&index=0&id=3d936cb2&prod&scoped=true&lang=css
|
|
3846
|
+
|
|
3847
|
+
;// ./node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js
|
|
3848
|
+
/* globals __VUE_SSR_CONTEXT__ */
|
|
3849
|
+
|
|
3850
|
+
// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
|
|
3851
|
+
// This module is a runtime utility for cleaner component module output and will
|
|
3852
|
+
// be included in the final webpack user bundle.
|
|
3853
|
+
|
|
3854
|
+
function normalizeComponent(
|
|
3855
|
+
scriptExports,
|
|
3856
|
+
render,
|
|
3857
|
+
staticRenderFns,
|
|
3858
|
+
functionalTemplate,
|
|
3859
|
+
injectStyles,
|
|
3860
|
+
scopeId,
|
|
3861
|
+
moduleIdentifier /* server only */,
|
|
3862
|
+
shadowMode /* vue-cli only */
|
|
3863
|
+
) {
|
|
3864
|
+
// Vue.extend constructor export interop
|
|
3865
|
+
var options =
|
|
3866
|
+
typeof scriptExports === 'function' ? scriptExports.options : scriptExports
|
|
3867
|
+
|
|
3868
|
+
// render functions
|
|
3869
|
+
if (render) {
|
|
3870
|
+
options.render = render
|
|
3871
|
+
options.staticRenderFns = staticRenderFns
|
|
3872
|
+
options._compiled = true
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
// functional template
|
|
3876
|
+
if (functionalTemplate) {
|
|
3877
|
+
options.functional = true
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
// scopedId
|
|
3881
|
+
if (scopeId) {
|
|
3882
|
+
options._scopeId = 'data-v-' + scopeId
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3885
|
+
var hook
|
|
3886
|
+
if (moduleIdentifier) {
|
|
3887
|
+
// server build
|
|
3888
|
+
hook = function (context) {
|
|
3889
|
+
// 2.3 injection
|
|
3890
|
+
context =
|
|
3891
|
+
context || // cached call
|
|
3892
|
+
(this.$vnode && this.$vnode.ssrContext) || // stateful
|
|
3893
|
+
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
|
|
3894
|
+
// 2.2 with runInNewContext: true
|
|
3895
|
+
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
|
3896
|
+
context = __VUE_SSR_CONTEXT__
|
|
3897
|
+
}
|
|
3898
|
+
// inject component styles
|
|
3899
|
+
if (injectStyles) {
|
|
3900
|
+
injectStyles.call(this, context)
|
|
3901
|
+
}
|
|
3902
|
+
// register component module identifier for async chunk inferrence
|
|
3903
|
+
if (context && context._registeredComponents) {
|
|
3904
|
+
context._registeredComponents.add(moduleIdentifier)
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
// used by ssr in case component is cached and beforeCreate
|
|
3908
|
+
// never gets called
|
|
3909
|
+
options._ssrRegister = hook
|
|
3910
|
+
} else if (injectStyles) {
|
|
3911
|
+
hook = shadowMode
|
|
3912
|
+
? function () {
|
|
3913
|
+
injectStyles.call(
|
|
3914
|
+
this,
|
|
3915
|
+
(options.functional ? this.parent : this).$root.$options.shadowRoot
|
|
3916
|
+
)
|
|
3917
|
+
}
|
|
3918
|
+
: injectStyles
|
|
3919
|
+
}
|
|
3920
|
+
|
|
3921
|
+
if (hook) {
|
|
3922
|
+
if (options.functional) {
|
|
3923
|
+
// for template-only hot-reload because in that case the render fn doesn't
|
|
3924
|
+
// go through the normalizer
|
|
3925
|
+
options._injectStyles = hook
|
|
3926
|
+
// register for functional component in vue file
|
|
3927
|
+
var originalRender = options.render
|
|
3928
|
+
options.render = function renderWithStyleInjection(h, context) {
|
|
3929
|
+
hook.call(context)
|
|
3930
|
+
return originalRender(h, context)
|
|
3931
|
+
}
|
|
3932
|
+
} else {
|
|
3933
|
+
// inject component registration as beforeCreate hook
|
|
3934
|
+
var existing = options.beforeCreate
|
|
3935
|
+
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
return {
|
|
3940
|
+
exports: scriptExports,
|
|
3941
|
+
options: options
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
;// ./components/ChatRobot.vue
|
|
3946
|
+
|
|
3947
|
+
|
|
3948
|
+
|
|
3949
|
+
;
|
|
3950
|
+
|
|
3951
|
+
|
|
3952
|
+
/* normalize component */
|
|
3953
|
+
|
|
3954
|
+
var component = normalizeComponent(
|
|
3955
|
+
components_ChatRobotvue_type_script_lang_js,
|
|
3956
|
+
ChatRobotvue_type_template_id_3d936cb2_scoped_true_render,
|
|
3957
|
+
ChatRobotvue_type_template_id_3d936cb2_scoped_true_staticRenderFns,
|
|
3958
|
+
false,
|
|
3959
|
+
null,
|
|
3960
|
+
"3d936cb2",
|
|
3961
|
+
null
|
|
3962
|
+
|
|
3963
|
+
)
|
|
3964
|
+
|
|
3965
|
+
/* harmony default export */ var ChatRobot = (component.exports);
|
|
3966
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatAvatar.vue?vue&type=template&id=7b09a9c8&scoped=true
|
|
3967
|
+
var ChatAvatarvue_type_template_id_7b09a9c8_scoped_true_render = function render() {
|
|
3968
|
+
var _vm = this,
|
|
3969
|
+
_c = _vm._self._c;
|
|
3970
|
+
return _c('div', {
|
|
3971
|
+
staticClass: "chat-ai",
|
|
3972
|
+
on: {
|
|
3973
|
+
"click": function ($event) {
|
|
3974
|
+
return _vm.$emit('click');
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3774
3977
|
}, [_c('div', {
|
|
3775
|
-
|
|
3978
|
+
class: ['chat-ai-avater', _vm.status]
|
|
3776
3979
|
}), _c('div', {
|
|
3777
3980
|
staticClass: "chat-ai-text"
|
|
3778
|
-
}, [_vm._v(
|
|
3981
|
+
}, [_vm._v(_vm._s(_vm.statusText))])]);
|
|
3982
|
+
};
|
|
3983
|
+
var ChatAvatarvue_type_template_id_7b09a9c8_scoped_true_staticRenderFns = [];
|
|
3984
|
+
|
|
3985
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatAvatar.vue?vue&type=script&lang=js
|
|
3986
|
+
/* harmony default export */ var ChatAvatarvue_type_script_lang_js = ({
|
|
3987
|
+
name: 'ChatAvatar',
|
|
3988
|
+
props: {
|
|
3989
|
+
status: {
|
|
3990
|
+
type: String,
|
|
3991
|
+
required: true,
|
|
3992
|
+
validator: value => ['normal', 'thinking', 'output'].includes(value)
|
|
3993
|
+
}
|
|
3994
|
+
},
|
|
3995
|
+
computed: {
|
|
3996
|
+
statusText() {
|
|
3997
|
+
const textMap = {
|
|
3998
|
+
'normal': '凌霄AI',
|
|
3999
|
+
'thinking': '思考中',
|
|
4000
|
+
'output': '语音中'
|
|
4001
|
+
};
|
|
4002
|
+
return textMap[this.status];
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
});
|
|
4006
|
+
;// ./components/ChatAvatar.vue?vue&type=script&lang=js
|
|
4007
|
+
/* harmony default export */ var components_ChatAvatarvue_type_script_lang_js = (ChatAvatarvue_type_script_lang_js);
|
|
4008
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatAvatar.vue?vue&type=style&index=0&id=7b09a9c8&prod&scoped=true&lang=css
|
|
4009
|
+
// extracted by mini-css-extract-plugin
|
|
4010
|
+
|
|
4011
|
+
;// ./components/ChatAvatar.vue?vue&type=style&index=0&id=7b09a9c8&prod&scoped=true&lang=css
|
|
4012
|
+
|
|
4013
|
+
;// ./components/ChatAvatar.vue
|
|
4014
|
+
|
|
4015
|
+
|
|
4016
|
+
|
|
4017
|
+
;
|
|
4018
|
+
|
|
4019
|
+
|
|
4020
|
+
/* normalize component */
|
|
4021
|
+
|
|
4022
|
+
var ChatAvatar_component = normalizeComponent(
|
|
4023
|
+
components_ChatAvatarvue_type_script_lang_js,
|
|
4024
|
+
ChatAvatarvue_type_template_id_7b09a9c8_scoped_true_render,
|
|
4025
|
+
ChatAvatarvue_type_template_id_7b09a9c8_scoped_true_staticRenderFns,
|
|
4026
|
+
false,
|
|
4027
|
+
null,
|
|
4028
|
+
"7b09a9c8",
|
|
4029
|
+
null
|
|
4030
|
+
|
|
4031
|
+
)
|
|
4032
|
+
|
|
4033
|
+
/* harmony default export */ var ChatAvatar = (ChatAvatar_component.exports);
|
|
4034
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowDialog.vue?vue&type=template&id=5eca994a&scoped=true
|
|
4035
|
+
var ChatWindowDialogvue_type_template_id_5eca994a_scoped_true_render = function render() {
|
|
4036
|
+
var _vm = this,
|
|
4037
|
+
_c = _vm._self._c;
|
|
4038
|
+
return _c('div', {
|
|
3779
4039
|
directives: [{
|
|
3780
4040
|
name: "show",
|
|
3781
4041
|
rawName: "v-show",
|
|
3782
|
-
value: _vm.
|
|
3783
|
-
expression: "
|
|
4042
|
+
value: _vm.value,
|
|
4043
|
+
expression: "value"
|
|
3784
4044
|
}],
|
|
3785
4045
|
staticClass: "chat-overlay",
|
|
3786
4046
|
on: {
|
|
3787
|
-
"click":
|
|
4047
|
+
"click": function ($event) {
|
|
4048
|
+
return _vm.$emit('overlay-click');
|
|
4049
|
+
}
|
|
3788
4050
|
}
|
|
3789
4051
|
}, [_c('div', {
|
|
3790
4052
|
staticClass: "chat-window",
|
|
@@ -3793,15 +4055,97 @@ var render = function render() {
|
|
|
3793
4055
|
$event.stopPropagation();
|
|
3794
4056
|
}
|
|
3795
4057
|
}
|
|
3796
|
-
}, [_c('
|
|
4058
|
+
}, [_c('ChatWindowHeader', {
|
|
4059
|
+
on: {
|
|
4060
|
+
"close": function ($event) {
|
|
4061
|
+
return _vm.$emit('input', false);
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
}), _c('ChatMessageList', {
|
|
4065
|
+
ref: "messageList",
|
|
4066
|
+
attrs: {
|
|
4067
|
+
"messages": _vm.messages,
|
|
4068
|
+
"think-status": _vm.thinkStatus
|
|
4069
|
+
},
|
|
4070
|
+
on: {
|
|
4071
|
+
"thinking-click": function ($event) {
|
|
4072
|
+
return _vm.$emit('thinking-click');
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
}), _c('ChatInputBox', {
|
|
4076
|
+
attrs: {
|
|
4077
|
+
"value": _vm.inputMessage
|
|
4078
|
+
},
|
|
4079
|
+
on: {
|
|
4080
|
+
"input": function ($event) {
|
|
4081
|
+
return _vm.$emit('update:inputMessage', $event);
|
|
4082
|
+
},
|
|
4083
|
+
"send": function ($event) {
|
|
4084
|
+
return _vm.$emit('send');
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
})], 1)]);
|
|
4088
|
+
};
|
|
4089
|
+
var ChatWindowDialogvue_type_template_id_5eca994a_scoped_true_staticRenderFns = [];
|
|
4090
|
+
|
|
4091
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowHeader.vue?vue&type=template&id=6518e4ca&scoped=true
|
|
4092
|
+
var ChatWindowHeadervue_type_template_id_6518e4ca_scoped_true_render = function render() {
|
|
4093
|
+
var _vm = this,
|
|
4094
|
+
_c = _vm._self._c;
|
|
4095
|
+
return _c('div', {
|
|
3797
4096
|
staticClass: "chat-window-header"
|
|
3798
4097
|
}, [_c('div', {
|
|
3799
4098
|
staticClass: "chat-window-header-title"
|
|
3800
|
-
}, [_vm._v("凌霄大模型
|
|
4099
|
+
}, [_vm._v("凌霄大模型AI123对话")]), _c('div', {
|
|
4100
|
+
staticClass: "chat-window-header-open",
|
|
4101
|
+
on: {
|
|
4102
|
+
"click": _vm.handleOpen
|
|
4103
|
+
}
|
|
4104
|
+
}, [_c('svg', {
|
|
4105
|
+
attrs: {
|
|
4106
|
+
"xmlns": "http://www.w3.org/2000/svg",
|
|
4107
|
+
"width": "24",
|
|
4108
|
+
"height": "24",
|
|
4109
|
+
"viewBox": "0 0 24 24",
|
|
4110
|
+
"fill": "none"
|
|
4111
|
+
}
|
|
4112
|
+
}, [_c('path', {
|
|
4113
|
+
attrs: {
|
|
4114
|
+
"d": "M14.5 4.5H19.5V9.5",
|
|
4115
|
+
"stroke": "#4E5969",
|
|
4116
|
+
"stroke-width": "1.66667",
|
|
4117
|
+
"stroke-linecap": "round",
|
|
4118
|
+
"stroke-linejoin": "round"
|
|
4119
|
+
}
|
|
4120
|
+
}), _c('path', {
|
|
4121
|
+
attrs: {
|
|
4122
|
+
"d": "M9.5 19.5H4.5V14.5",
|
|
4123
|
+
"stroke": "#4E5969",
|
|
4124
|
+
"stroke-width": "1.66667",
|
|
4125
|
+
"stroke-linecap": "round",
|
|
4126
|
+
"stroke-linejoin": "round"
|
|
4127
|
+
}
|
|
4128
|
+
}), _c('path', {
|
|
4129
|
+
attrs: {
|
|
4130
|
+
"d": "M19.5 4.5L14.0833 9.91667",
|
|
4131
|
+
"stroke": "#4E5969",
|
|
4132
|
+
"stroke-width": "1.66667",
|
|
4133
|
+
"stroke-linecap": "round",
|
|
4134
|
+
"stroke-linejoin": "round"
|
|
4135
|
+
}
|
|
4136
|
+
}), _c('path', {
|
|
4137
|
+
attrs: {
|
|
4138
|
+
"d": "M9.91667 14.083L4.5 19.4997",
|
|
4139
|
+
"stroke": "#4E5969",
|
|
4140
|
+
"stroke-width": "1.66667",
|
|
4141
|
+
"stroke-linecap": "round",
|
|
4142
|
+
"stroke-linejoin": "round"
|
|
4143
|
+
}
|
|
4144
|
+
})])]), _c('div', {
|
|
3801
4145
|
staticClass: "chat-window-header-close",
|
|
3802
4146
|
on: {
|
|
3803
4147
|
"click": function ($event) {
|
|
3804
|
-
_vm
|
|
4148
|
+
return _vm.$emit('close');
|
|
3805
4149
|
}
|
|
3806
4150
|
}
|
|
3807
4151
|
}, [_c('svg', {
|
|
@@ -3828,23 +4172,268 @@ var render = function render() {
|
|
|
3828
4172
|
"stroke-linecap": "round",
|
|
3829
4173
|
"stroke-linejoin": "round"
|
|
3830
4174
|
}
|
|
3831
|
-
})])])])
|
|
4175
|
+
})])])]);
|
|
4176
|
+
};
|
|
4177
|
+
var ChatWindowHeadervue_type_template_id_6518e4ca_scoped_true_staticRenderFns = [];
|
|
4178
|
+
|
|
4179
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowHeader.vue?vue&type=script&lang=js
|
|
4180
|
+
/* harmony default export */ var ChatWindowHeadervue_type_script_lang_js = ({
|
|
4181
|
+
name: 'ChatWindowHeader',
|
|
4182
|
+
methods: {
|
|
4183
|
+
handleOpen() {
|
|
4184
|
+
const path = this.$router.resolve({
|
|
4185
|
+
name: '/chat'
|
|
4186
|
+
});
|
|
4187
|
+
window.open(path.href, '_blank');
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
});
|
|
4191
|
+
;// ./components/ChatWindowHeader.vue?vue&type=script&lang=js
|
|
4192
|
+
/* harmony default export */ var components_ChatWindowHeadervue_type_script_lang_js = (ChatWindowHeadervue_type_script_lang_js);
|
|
4193
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowHeader.vue?vue&type=style&index=0&id=6518e4ca&prod&scoped=true&lang=css
|
|
4194
|
+
// extracted by mini-css-extract-plugin
|
|
4195
|
+
|
|
4196
|
+
;// ./components/ChatWindowHeader.vue?vue&type=style&index=0&id=6518e4ca&prod&scoped=true&lang=css
|
|
4197
|
+
|
|
4198
|
+
;// ./components/ChatWindowHeader.vue
|
|
4199
|
+
|
|
4200
|
+
|
|
4201
|
+
|
|
4202
|
+
;
|
|
4203
|
+
|
|
4204
|
+
|
|
4205
|
+
/* normalize component */
|
|
4206
|
+
|
|
4207
|
+
var ChatWindowHeader_component = normalizeComponent(
|
|
4208
|
+
components_ChatWindowHeadervue_type_script_lang_js,
|
|
4209
|
+
ChatWindowHeadervue_type_template_id_6518e4ca_scoped_true_render,
|
|
4210
|
+
ChatWindowHeadervue_type_template_id_6518e4ca_scoped_true_staticRenderFns,
|
|
4211
|
+
false,
|
|
4212
|
+
null,
|
|
4213
|
+
"6518e4ca",
|
|
4214
|
+
null
|
|
4215
|
+
|
|
4216
|
+
)
|
|
4217
|
+
|
|
4218
|
+
/* harmony default export */ var ChatWindowHeader = (ChatWindowHeader_component.exports);
|
|
4219
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatMessageList.vue?vue&type=template&id=ba7356ea&scoped=true
|
|
4220
|
+
var ChatMessageListvue_type_template_id_ba7356ea_scoped_true_render = function render() {
|
|
4221
|
+
var _vm = this,
|
|
4222
|
+
_c = _vm._self._c;
|
|
4223
|
+
return _c('div', {
|
|
3832
4224
|
ref: "chatArea",
|
|
3833
4225
|
staticClass: "chat-window-content scrollbar-hide"
|
|
3834
4226
|
}, _vm._l(_vm.messages, function (message) {
|
|
3835
4227
|
return _c('div', {
|
|
3836
4228
|
key: message.id,
|
|
3837
4229
|
staticClass: "chat-window-message"
|
|
3838
|
-
}, [message.type === 'user' ? _c('
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
}
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
4230
|
+
}, [message.type === 'user' ? _c('UserMessage', {
|
|
4231
|
+
attrs: {
|
|
4232
|
+
"content": message.content
|
|
4233
|
+
}
|
|
4234
|
+
}) : _c('AiMessage', {
|
|
4235
|
+
attrs: {
|
|
4236
|
+
"message": message,
|
|
4237
|
+
"think-status": _vm.thinkStatus
|
|
4238
|
+
},
|
|
4239
|
+
on: {
|
|
4240
|
+
"thinking-click": function ($event) {
|
|
4241
|
+
return _vm.$emit('thinking-click');
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
})], 1);
|
|
4245
|
+
}), 0);
|
|
4246
|
+
};
|
|
4247
|
+
var ChatMessageListvue_type_template_id_ba7356ea_scoped_true_staticRenderFns = [];
|
|
4248
|
+
|
|
4249
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/UserMessage.vue?vue&type=template&id=6a2b6167&scoped=true
|
|
4250
|
+
var UserMessagevue_type_template_id_6a2b6167_scoped_true_render = function render() {
|
|
4251
|
+
var _vm = this,
|
|
4252
|
+
_c = _vm._self._c;
|
|
4253
|
+
return _c('div', {
|
|
4254
|
+
staticClass: "chat-window-message-user"
|
|
4255
|
+
}, [_c('div', {
|
|
4256
|
+
staticClass: "user-message"
|
|
4257
|
+
}, [_vm._v(_vm._s(_vm.content))])]);
|
|
4258
|
+
};
|
|
4259
|
+
var UserMessagevue_type_template_id_6a2b6167_scoped_true_staticRenderFns = [];
|
|
4260
|
+
|
|
4261
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/UserMessage.vue?vue&type=script&lang=js
|
|
4262
|
+
/* harmony default export */ var UserMessagevue_type_script_lang_js = ({
|
|
4263
|
+
name: 'UserMessage',
|
|
4264
|
+
props: {
|
|
4265
|
+
content: {
|
|
4266
|
+
type: String,
|
|
4267
|
+
required: true
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
});
|
|
4271
|
+
;// ./components/UserMessage.vue?vue&type=script&lang=js
|
|
4272
|
+
/* harmony default export */ var components_UserMessagevue_type_script_lang_js = (UserMessagevue_type_script_lang_js);
|
|
4273
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/UserMessage.vue?vue&type=style&index=0&id=6a2b6167&prod&scoped=true&lang=css
|
|
4274
|
+
// extracted by mini-css-extract-plugin
|
|
4275
|
+
|
|
4276
|
+
;// ./components/UserMessage.vue?vue&type=style&index=0&id=6a2b6167&prod&scoped=true&lang=css
|
|
4277
|
+
|
|
4278
|
+
;// ./components/UserMessage.vue
|
|
4279
|
+
|
|
4280
|
+
|
|
4281
|
+
|
|
4282
|
+
;
|
|
4283
|
+
|
|
4284
|
+
|
|
4285
|
+
/* normalize component */
|
|
4286
|
+
|
|
4287
|
+
var UserMessage_component = normalizeComponent(
|
|
4288
|
+
components_UserMessagevue_type_script_lang_js,
|
|
4289
|
+
UserMessagevue_type_template_id_6a2b6167_scoped_true_render,
|
|
4290
|
+
UserMessagevue_type_template_id_6a2b6167_scoped_true_staticRenderFns,
|
|
4291
|
+
false,
|
|
4292
|
+
null,
|
|
4293
|
+
"6a2b6167",
|
|
4294
|
+
null
|
|
4295
|
+
|
|
4296
|
+
)
|
|
4297
|
+
|
|
4298
|
+
/* harmony default export */ var UserMessage = (UserMessage_component.exports);
|
|
4299
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/AiMessage.vue?vue&type=template&id=3347daf6&scoped=true
|
|
4300
|
+
var AiMessagevue_type_template_id_3347daf6_scoped_true_render = function render() {
|
|
4301
|
+
var _vm = this,
|
|
4302
|
+
_c = _vm._self._c;
|
|
4303
|
+
return _c('div', {
|
|
4304
|
+
staticClass: "chat-window-message-ai"
|
|
4305
|
+
}, [_c('div', {
|
|
4306
|
+
staticClass: "ai-render"
|
|
4307
|
+
}, [_c('div', {
|
|
4308
|
+
staticClass: "ai-thinking",
|
|
4309
|
+
on: {
|
|
4310
|
+
"click": function ($event) {
|
|
4311
|
+
return _vm.$emit('thinking-click');
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
}, [_c('div', {
|
|
4315
|
+
staticClass: "ai-thinking-time"
|
|
4316
|
+
}, [_vm._v("思考用时" + _vm._s(_vm.message.time) + "秒")]), _vm.thinkStatus ? _c('div', {
|
|
4317
|
+
staticClass: "ai-thinking-content"
|
|
4318
|
+
}, [_vm._v(_vm._s(_vm.message.thinking))]) : _vm._e()]), _c('div', {
|
|
4319
|
+
staticClass: "ai-content"
|
|
4320
|
+
}, [_vm._v(_vm._s(_vm.message.content))])])]);
|
|
4321
|
+
};
|
|
4322
|
+
var AiMessagevue_type_template_id_3347daf6_scoped_true_staticRenderFns = [];
|
|
4323
|
+
|
|
4324
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/AiMessage.vue?vue&type=script&lang=js
|
|
4325
|
+
/* harmony default export */ var AiMessagevue_type_script_lang_js = ({
|
|
4326
|
+
name: 'AiMessage',
|
|
4327
|
+
props: {
|
|
4328
|
+
message: {
|
|
4329
|
+
type: Object,
|
|
4330
|
+
required: true
|
|
4331
|
+
},
|
|
4332
|
+
thinkStatus: {
|
|
4333
|
+
type: Boolean,
|
|
4334
|
+
default: true
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
});
|
|
4338
|
+
;// ./components/AiMessage.vue?vue&type=script&lang=js
|
|
4339
|
+
/* harmony default export */ var components_AiMessagevue_type_script_lang_js = (AiMessagevue_type_script_lang_js);
|
|
4340
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/AiMessage.vue?vue&type=style&index=0&id=3347daf6&prod&scoped=true&lang=css
|
|
4341
|
+
// extracted by mini-css-extract-plugin
|
|
4342
|
+
|
|
4343
|
+
;// ./components/AiMessage.vue?vue&type=style&index=0&id=3347daf6&prod&scoped=true&lang=css
|
|
4344
|
+
|
|
4345
|
+
;// ./components/AiMessage.vue
|
|
4346
|
+
|
|
4347
|
+
|
|
4348
|
+
|
|
4349
|
+
;
|
|
4350
|
+
|
|
4351
|
+
|
|
4352
|
+
/* normalize component */
|
|
4353
|
+
|
|
4354
|
+
var AiMessage_component = normalizeComponent(
|
|
4355
|
+
components_AiMessagevue_type_script_lang_js,
|
|
4356
|
+
AiMessagevue_type_template_id_3347daf6_scoped_true_render,
|
|
4357
|
+
AiMessagevue_type_template_id_3347daf6_scoped_true_staticRenderFns,
|
|
4358
|
+
false,
|
|
4359
|
+
null,
|
|
4360
|
+
"3347daf6",
|
|
4361
|
+
null
|
|
4362
|
+
|
|
4363
|
+
)
|
|
4364
|
+
|
|
4365
|
+
/* harmony default export */ var AiMessage = (AiMessage_component.exports);
|
|
4366
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatMessageList.vue?vue&type=script&lang=js
|
|
4367
|
+
|
|
4368
|
+
|
|
4369
|
+
/* harmony default export */ var ChatMessageListvue_type_script_lang_js = ({
|
|
4370
|
+
name: 'ChatMessageList',
|
|
4371
|
+
components: {
|
|
4372
|
+
UserMessage: UserMessage,
|
|
4373
|
+
AiMessage: AiMessage
|
|
4374
|
+
},
|
|
4375
|
+
props: {
|
|
4376
|
+
messages: {
|
|
4377
|
+
type: Array,
|
|
4378
|
+
required: true
|
|
4379
|
+
},
|
|
4380
|
+
thinkStatus: {
|
|
4381
|
+
type: Boolean,
|
|
4382
|
+
default: true
|
|
4383
|
+
}
|
|
4384
|
+
},
|
|
4385
|
+
methods: {
|
|
4386
|
+
scrollToBottom() {
|
|
4387
|
+
this.$nextTick(() => {
|
|
4388
|
+
const chatArea = this.$refs.chatArea;
|
|
4389
|
+
if (chatArea) {
|
|
4390
|
+
chatArea.scrollTop = chatArea.scrollHeight;
|
|
4391
|
+
}
|
|
4392
|
+
});
|
|
4393
|
+
}
|
|
4394
|
+
},
|
|
4395
|
+
watch: {
|
|
4396
|
+
messages: {
|
|
4397
|
+
handler() {
|
|
4398
|
+
this.scrollToBottom();
|
|
4399
|
+
},
|
|
4400
|
+
deep: true
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
});
|
|
4404
|
+
;// ./components/ChatMessageList.vue?vue&type=script&lang=js
|
|
4405
|
+
/* harmony default export */ var components_ChatMessageListvue_type_script_lang_js = (ChatMessageListvue_type_script_lang_js);
|
|
4406
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatMessageList.vue?vue&type=style&index=0&id=ba7356ea&prod&scoped=true&lang=css
|
|
4407
|
+
// extracted by mini-css-extract-plugin
|
|
4408
|
+
|
|
4409
|
+
;// ./components/ChatMessageList.vue?vue&type=style&index=0&id=ba7356ea&prod&scoped=true&lang=css
|
|
4410
|
+
|
|
4411
|
+
;// ./components/ChatMessageList.vue
|
|
4412
|
+
|
|
4413
|
+
|
|
4414
|
+
|
|
4415
|
+
;
|
|
4416
|
+
|
|
4417
|
+
|
|
4418
|
+
/* normalize component */
|
|
4419
|
+
|
|
4420
|
+
var ChatMessageList_component = normalizeComponent(
|
|
4421
|
+
components_ChatMessageListvue_type_script_lang_js,
|
|
4422
|
+
ChatMessageListvue_type_template_id_ba7356ea_scoped_true_render,
|
|
4423
|
+
ChatMessageListvue_type_template_id_ba7356ea_scoped_true_staticRenderFns,
|
|
4424
|
+
false,
|
|
4425
|
+
null,
|
|
4426
|
+
"ba7356ea",
|
|
4427
|
+
null
|
|
4428
|
+
|
|
4429
|
+
)
|
|
4430
|
+
|
|
4431
|
+
/* harmony default export */ var ChatMessageList = (ChatMessageList_component.exports);
|
|
4432
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatInputBox.vue?vue&type=template&id=6f416073&scoped=true
|
|
4433
|
+
var ChatInputBoxvue_type_template_id_6f416073_scoped_true_render = function render() {
|
|
4434
|
+
var _vm = this,
|
|
4435
|
+
_c = _vm._self._c;
|
|
4436
|
+
return _c('div', {
|
|
3848
4437
|
staticClass: "chat-window-footer"
|
|
3849
4438
|
}, [_c('div', {
|
|
3850
4439
|
staticClass: "chat-window-textarea"
|
|
@@ -3854,24 +4443,27 @@ var render = function render() {
|
|
|
3854
4443
|
"type": "textarea",
|
|
3855
4444
|
"placeholder": "有什么我能帮您的吗?",
|
|
3856
4445
|
"rows": "2",
|
|
3857
|
-
"resize": "none"
|
|
4446
|
+
"resize": "none",
|
|
4447
|
+
"value": _vm.value
|
|
3858
4448
|
},
|
|
3859
4449
|
on: {
|
|
3860
|
-
"
|
|
4450
|
+
"input": function ($event) {
|
|
4451
|
+
return _vm.$emit('input', $event);
|
|
4452
|
+
}
|
|
3861
4453
|
},
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
},
|
|
3867
|
-
expression: "inputMessage"
|
|
4454
|
+
nativeOn: {
|
|
4455
|
+
"keydown": function ($event) {
|
|
4456
|
+
return _vm.handleKeyDown.apply(null, arguments);
|
|
4457
|
+
}
|
|
3868
4458
|
}
|
|
3869
4459
|
}), _c('div', {
|
|
3870
4460
|
staticClass: "chat-window-bar"
|
|
3871
4461
|
}, [_c('div', {
|
|
3872
4462
|
staticClass: "chat-window-send",
|
|
3873
4463
|
on: {
|
|
3874
|
-
"click":
|
|
4464
|
+
"click": function ($event) {
|
|
4465
|
+
return _vm.$emit('send');
|
|
4466
|
+
}
|
|
3875
4467
|
}
|
|
3876
4468
|
}, [_c('svg', {
|
|
3877
4469
|
attrs: {
|
|
@@ -3910,187 +4502,202 @@ var render = function render() {
|
|
|
3910
4502
|
"height": "20",
|
|
3911
4503
|
"fill": "white"
|
|
3912
4504
|
}
|
|
3913
|
-
})])])])])])], 1)])
|
|
4505
|
+
})])])])])])], 1)]);
|
|
3914
4506
|
};
|
|
3915
|
-
var
|
|
4507
|
+
var ChatInputBoxvue_type_template_id_6f416073_scoped_true_staticRenderFns = [];
|
|
3916
4508
|
|
|
3917
|
-
|
|
3918
|
-
var
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
var
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
|
|
3940
|
-
var es_typed_array_with = __webpack_require__(9577);
|
|
3941
|
-
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=script&lang=js
|
|
4509
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatInputBox.vue?vue&type=script&lang=js
|
|
4510
|
+
/* harmony default export */ var ChatInputBoxvue_type_script_lang_js = ({
|
|
4511
|
+
name: 'ChatInputBox',
|
|
4512
|
+
props: {
|
|
4513
|
+
value: {
|
|
4514
|
+
type: String,
|
|
4515
|
+
default: ''
|
|
4516
|
+
}
|
|
4517
|
+
},
|
|
4518
|
+
methods: {
|
|
4519
|
+
handleKeyDown(e) {
|
|
4520
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
4521
|
+
e.preventDefault();
|
|
4522
|
+
this.$emit('send');
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4526
|
+
});
|
|
4527
|
+
;// ./components/ChatInputBox.vue?vue&type=script&lang=js
|
|
4528
|
+
/* harmony default export */ var components_ChatInputBoxvue_type_script_lang_js = (ChatInputBoxvue_type_script_lang_js);
|
|
4529
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatInputBox.vue?vue&type=style&index=0&id=6f416073&prod&scoped=true&lang=css
|
|
4530
|
+
// extracted by mini-css-extract-plugin
|
|
3942
4531
|
|
|
4532
|
+
;// ./components/ChatInputBox.vue?vue&type=style&index=0&id=6f416073&prod&scoped=true&lang=css
|
|
3943
4533
|
|
|
4534
|
+
;// ./components/ChatInputBox.vue
|
|
3944
4535
|
|
|
3945
4536
|
|
|
3946
4537
|
|
|
4538
|
+
;
|
|
3947
4539
|
|
|
3948
4540
|
|
|
4541
|
+
/* normalize component */
|
|
3949
4542
|
|
|
4543
|
+
var ChatInputBox_component = normalizeComponent(
|
|
4544
|
+
components_ChatInputBoxvue_type_script_lang_js,
|
|
4545
|
+
ChatInputBoxvue_type_template_id_6f416073_scoped_true_render,
|
|
4546
|
+
ChatInputBoxvue_type_template_id_6f416073_scoped_true_staticRenderFns,
|
|
4547
|
+
false,
|
|
4548
|
+
null,
|
|
4549
|
+
"6f416073",
|
|
4550
|
+
null
|
|
4551
|
+
|
|
4552
|
+
)
|
|
3950
4553
|
|
|
4554
|
+
/* harmony default export */ var ChatInputBox = (ChatInputBox_component.exports);
|
|
4555
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowDialog.vue?vue&type=script&lang=js
|
|
3951
4556
|
|
|
3952
4557
|
|
|
3953
4558
|
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
4559
|
+
/* harmony default export */ var ChatWindowDialogvue_type_script_lang_js = ({
|
|
4560
|
+
name: 'ChatWindowDialog',
|
|
4561
|
+
components: {
|
|
4562
|
+
ChatWindowHeader: ChatWindowHeader,
|
|
4563
|
+
ChatMessageList: ChatMessageList,
|
|
4564
|
+
ChatInputBox: ChatInputBox
|
|
4565
|
+
},
|
|
3958
4566
|
props: {
|
|
3959
|
-
|
|
4567
|
+
value: {
|
|
4568
|
+
type: Boolean,
|
|
4569
|
+
required: true
|
|
4570
|
+
},
|
|
4571
|
+
messages: {
|
|
4572
|
+
type: Array,
|
|
4573
|
+
required: true
|
|
4574
|
+
},
|
|
4575
|
+
inputMessage: {
|
|
4576
|
+
type: String,
|
|
4577
|
+
default: ''
|
|
4578
|
+
},
|
|
4579
|
+
thinkStatus: {
|
|
3960
4580
|
type: Boolean,
|
|
3961
4581
|
default: true
|
|
3962
4582
|
}
|
|
3963
|
-
}
|
|
4583
|
+
}
|
|
4584
|
+
});
|
|
4585
|
+
;// ./components/ChatWindowDialog.vue?vue&type=script&lang=js
|
|
4586
|
+
/* harmony default export */ var components_ChatWindowDialogvue_type_script_lang_js = (ChatWindowDialogvue_type_script_lang_js);
|
|
4587
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindowDialog.vue?vue&type=style&index=0&id=5eca994a&prod&scoped=true&lang=css
|
|
4588
|
+
// extracted by mini-css-extract-plugin
|
|
4589
|
+
|
|
4590
|
+
;// ./components/ChatWindowDialog.vue?vue&type=style&index=0&id=5eca994a&prod&scoped=true&lang=css
|
|
4591
|
+
|
|
4592
|
+
;// ./components/ChatWindowDialog.vue
|
|
4593
|
+
|
|
4594
|
+
|
|
4595
|
+
|
|
4596
|
+
;
|
|
4597
|
+
|
|
4598
|
+
|
|
4599
|
+
/* normalize component */
|
|
4600
|
+
|
|
4601
|
+
var ChatWindowDialog_component = normalizeComponent(
|
|
4602
|
+
components_ChatWindowDialogvue_type_script_lang_js,
|
|
4603
|
+
ChatWindowDialogvue_type_template_id_5eca994a_scoped_true_render,
|
|
4604
|
+
ChatWindowDialogvue_type_template_id_5eca994a_scoped_true_staticRenderFns,
|
|
4605
|
+
false,
|
|
4606
|
+
null,
|
|
4607
|
+
"5eca994a",
|
|
4608
|
+
null
|
|
4609
|
+
|
|
4610
|
+
)
|
|
4611
|
+
|
|
4612
|
+
/* harmony default export */ var ChatWindowDialog = (ChatWindowDialog_component.exports);
|
|
4613
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
|
|
4614
|
+
var es_array_buffer_detached = __webpack_require__(6573);
|
|
4615
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
|
|
4616
|
+
var es_array_buffer_transfer = __webpack_require__(8100);
|
|
4617
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer-to-fixed-length.js
|
|
4618
|
+
var es_array_buffer_transfer_to_fixed_length = __webpack_require__(7936);
|
|
4619
|
+
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
|
|
4620
|
+
var es_typed_array_with = __webpack_require__(9577);
|
|
4621
|
+
;// ./components/mixins/audioMixin.js
|
|
4622
|
+
|
|
4623
|
+
|
|
4624
|
+
|
|
4625
|
+
|
|
4626
|
+
/* harmony default export */ var audioMixin = ({
|
|
3964
4627
|
data() {
|
|
3965
4628
|
return {
|
|
3966
|
-
audioSrc: '/minio/lingxiaoai/byt.mp3',
|
|
3967
|
-
// 音频URL
|
|
3968
|
-
inputMessage: '',
|
|
3969
|
-
// 输入消息
|
|
3970
|
-
visible: false,
|
|
3971
|
-
// 窗口是否可见
|
|
3972
|
-
messages: [{
|
|
3973
|
-
id: 1,
|
|
3974
|
-
type: 'user',
|
|
3975
|
-
sender: '',
|
|
3976
|
-
time: '',
|
|
3977
|
-
content: '你好,欢迎来到凌霄大模型AI对话。'
|
|
3978
|
-
}, {
|
|
3979
|
-
id: 2,
|
|
3980
|
-
type: 'ai',
|
|
3981
|
-
sender: 'AI',
|
|
3982
|
-
time: '',
|
|
3983
|
-
content: '欢迎来到凌霄大模型AI对话。'
|
|
3984
|
-
}, {
|
|
3985
|
-
id: 3,
|
|
3986
|
-
type: 'ai',
|
|
3987
|
-
sender: 'AI',
|
|
3988
|
-
time: '',
|
|
3989
|
-
content: '请输入您的问题。'
|
|
3990
|
-
}, {
|
|
3991
|
-
id: 4,
|
|
3992
|
-
type: 'user',
|
|
3993
|
-
sender: '用户',
|
|
3994
|
-
time: '',
|
|
3995
|
-
content: '你好,欢迎来到凌霄大模型AI对话。'
|
|
3996
|
-
}],
|
|
3997
|
-
// 消息列表
|
|
3998
4629
|
isRecording: false,
|
|
3999
|
-
// 正在录制
|
|
4000
4630
|
isMicAvailable: false,
|
|
4001
|
-
// 麦克风是否可用
|
|
4002
|
-
mediaRecorder: null,
|
|
4003
|
-
// 媒体录制器
|
|
4004
|
-
ws: null,
|
|
4005
|
-
// WebSocket连接
|
|
4006
|
-
// wsUrl: 'wss://mes.shnfonline.top:8316/ai_model/ws/voice-stream', // WebSocket URL
|
|
4007
|
-
wsUrl: 'ws://192.168.8.9:9999/ai_model/ws/voice-stream',
|
|
4008
|
-
// WebSocket URL
|
|
4009
|
-
isConnected: false,
|
|
4010
|
-
// WebSocket是否已连接
|
|
4011
4631
|
audioContext: null,
|
|
4012
|
-
// 音频上下文
|
|
4013
4632
|
microphone: null,
|
|
4014
|
-
// 麦克风输入节点
|
|
4015
4633
|
processor: null,
|
|
4016
|
-
|
|
4017
|
-
robotStatus: 'leaving',
|
|
4018
|
-
// 机器人状态 waiting, speaking, leaving, entering
|
|
4019
|
-
audioBuffer: new Float32Array(0) // 音频缓冲区
|
|
4634
|
+
audioBuffer: new Float32Array(0)
|
|
4020
4635
|
};
|
|
4021
4636
|
},
|
|
4022
|
-
mounted() {
|
|
4023
|
-
this.initWebSocket();
|
|
4024
|
-
|
|
4025
|
-
// 处理append-to-body逻辑
|
|
4026
|
-
if (this.appendToBody) {
|
|
4027
|
-
this.appendToBodyHandler();
|
|
4028
|
-
}
|
|
4029
|
-
},
|
|
4030
|
-
unmounted() {
|
|
4031
|
-
this.closeWebSocket();
|
|
4032
|
-
this.stopRecording();
|
|
4033
|
-
},
|
|
4034
|
-
beforeDestroy() {
|
|
4035
|
-
// 组件销毁前,如果元素被移动到body中,需要移除
|
|
4036
|
-
if (this.appendToBody && this.$el.parentElement === document.body) {
|
|
4037
|
-
document.body.removeChild(this.$el);
|
|
4038
|
-
}
|
|
4039
|
-
this.closeWebSocket();
|
|
4040
|
-
this.stopRecording();
|
|
4041
|
-
},
|
|
4042
4637
|
methods: {
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4638
|
+
async initAudio() {
|
|
4639
|
+
if (this.isRecording) return;
|
|
4640
|
+
try {
|
|
4641
|
+
this.isMicAvailable = true;
|
|
4642
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
4643
|
+
audio: {
|
|
4644
|
+
sampleRate: this.SAMPLE_RATE,
|
|
4645
|
+
channelCount: 1,
|
|
4646
|
+
noiseSuppression: true,
|
|
4647
|
+
echoCancellation: true
|
|
4648
|
+
}
|
|
4649
|
+
});
|
|
4650
|
+
this.audioContext = new AudioContext({
|
|
4651
|
+
sampleRate: this.SAMPLE_RATE
|
|
4652
|
+
});
|
|
4653
|
+
this.microphone = this.audioContext.createMediaStreamSource(stream);
|
|
4654
|
+
this.processor = this.audioContext.createScriptProcessor(this.FRAME_SIZE, 1, 1);
|
|
4655
|
+
this.processor.onaudioprocess = this.processAudio;
|
|
4656
|
+
this.microphone.connect(this.processor);
|
|
4657
|
+
this.processor.connect(this.audioContext.destination);
|
|
4658
|
+
this.isRecording = true;
|
|
4659
|
+
console.log(`录音中 (采样率: ${this.audioContext.sampleRate}Hz)`);
|
|
4660
|
+
} catch (error) {
|
|
4661
|
+
console.error("音频初始化失败:", error);
|
|
4662
|
+
this.isRecording = false;
|
|
4663
|
+
this.isMicAvailable = false;
|
|
4054
4664
|
}
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
title: '角色管理'
|
|
4070
|
-
}];
|
|
4071
|
-
// 检查当前时间是否达到跳转点
|
|
4072
|
-
timeJumpPoints.forEach(point => {
|
|
4073
|
-
// 使用一定的误差范围,确保不会因为播放进度的微小差异而错过跳转点
|
|
4074
|
-
if (currentTime >= point.time && currentTime < point.time + 0.5 && !this.jumpedTimePoints.has(point.time)) {
|
|
4075
|
-
this.jumpedTimePoints.add(point.time);
|
|
4076
|
-
console.log(`到达时间点 ${point.time} 秒,跳转到 ${point.title}`);
|
|
4077
|
-
this.$appOptions.store.dispatch('tags/addTagview', {
|
|
4078
|
-
path: point.url,
|
|
4079
|
-
fullPath: point.url,
|
|
4080
|
-
label: point.title,
|
|
4081
|
-
name: point.title,
|
|
4082
|
-
meta: {
|
|
4083
|
-
title: point.title
|
|
4084
|
-
},
|
|
4085
|
-
query: {},
|
|
4086
|
-
params: {}
|
|
4087
|
-
});
|
|
4088
|
-
this.$appOptions.router.push({
|
|
4089
|
-
path: point.url
|
|
4090
|
-
});
|
|
4665
|
+
},
|
|
4666
|
+
processAudio(event) {
|
|
4667
|
+
if (!this.isRecording) return;
|
|
4668
|
+
const inputData = event.inputBuffer.getChannelData(0);
|
|
4669
|
+
const tempBuffer = new Float32Array(this.audioBuffer.length + inputData.length);
|
|
4670
|
+
tempBuffer.set(this.audioBuffer, 0);
|
|
4671
|
+
tempBuffer.set(inputData, this.audioBuffer.length);
|
|
4672
|
+
this.audioBuffer = tempBuffer;
|
|
4673
|
+
while (this.audioBuffer.length >= this.FRAME_SIZE) {
|
|
4674
|
+
const frame = this.audioBuffer.slice(0, this.FRAME_SIZE);
|
|
4675
|
+
this.audioBuffer = this.audioBuffer.slice(this.FRAME_SIZE);
|
|
4676
|
+
const pcmData = this.floatTo16BitPCM(frame);
|
|
4677
|
+
if (this.ws && this.ws.readyState === this.ws.OPEN) {
|
|
4678
|
+
this.ws.send(pcmData);
|
|
4091
4679
|
}
|
|
4092
|
-
}
|
|
4093
|
-
|
|
4680
|
+
}
|
|
4681
|
+
},
|
|
4682
|
+
floatTo16BitPCM(input) {
|
|
4683
|
+
const output = new Int16Array(input.length);
|
|
4684
|
+
for (let i = 0; i < input.length; i++) {
|
|
4685
|
+
const s = Math.max(-1, Math.min(1, input[i]));
|
|
4686
|
+
output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
|
4687
|
+
}
|
|
4688
|
+
return output.buffer;
|
|
4689
|
+
},
|
|
4690
|
+
stopRecording() {
|
|
4691
|
+
if (!this.isRecording) return;
|
|
4692
|
+
if (this.microphone) this.microphone.disconnect();
|
|
4693
|
+
if (this.processor) this.processor.disconnect();
|
|
4694
|
+
if (this.analyser) this.analyser.disconnect();
|
|
4695
|
+
if (this.audioContext) {
|
|
4696
|
+
this.audioContext.close().catch(e => {
|
|
4697
|
+
console.error("关闭音频上下文失败:", e);
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
this.isRecording = false;
|
|
4094
4701
|
},
|
|
4095
4702
|
play() {
|
|
4096
4703
|
this.robotStatus = 'speaking';
|
|
@@ -4106,40 +4713,62 @@ const FRAME_SIZE = 512;
|
|
|
4106
4713
|
this.$refs.audioPlayer.currentTime = 0;
|
|
4107
4714
|
this.jumpedTimePoints.clear();
|
|
4108
4715
|
},
|
|
4716
|
+
analyzeAudioCommand(command) {
|
|
4717
|
+
console.log('分析音频命令:', command);
|
|
4718
|
+
if (command === 'C5') {
|
|
4719
|
+
this.robotStatus = 'entering';
|
|
4720
|
+
setTimeout(() => {
|
|
4721
|
+
this.robotStatus = 'speaking';
|
|
4722
|
+
this.play();
|
|
4723
|
+
}, 3000);
|
|
4724
|
+
} else if (command === 'C8') {
|
|
4725
|
+
this.robotStatus = 'speaking';
|
|
4726
|
+
this.play();
|
|
4727
|
+
} else if (command === 'C7') {
|
|
4728
|
+
this.robotStatus = 'waiting';
|
|
4729
|
+
this.pause();
|
|
4730
|
+
} else if (command === 'C6') {
|
|
4731
|
+
this.robotStatus = 'leaving';
|
|
4732
|
+
this.stop();
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
});
|
|
4737
|
+
;// ./components/mixins/webSocketMixin.js
|
|
4738
|
+
|
|
4739
|
+
|
|
4740
|
+
|
|
4741
|
+
/* harmony default export */ var webSocketMixin = ({
|
|
4742
|
+
data() {
|
|
4743
|
+
return {
|
|
4744
|
+
ws: null,
|
|
4745
|
+
wsUrl: 'ws://192.168.8.9:9999/ai_model/ws/voice-stream',
|
|
4746
|
+
isConnected: false
|
|
4747
|
+
};
|
|
4748
|
+
},
|
|
4749
|
+
methods: {
|
|
4109
4750
|
initWebSocket() {
|
|
4110
4751
|
try {
|
|
4111
4752
|
this.ws = new WebSocket(this.wsUrl);
|
|
4112
4753
|
this.ws.binaryType = 'arraybuffer';
|
|
4113
4754
|
this.ws.onopen = async () => {
|
|
4114
|
-
console.log('连接成功');
|
|
4755
|
+
console.log('WebSocket 连接成功');
|
|
4115
4756
|
this.isConnected = true;
|
|
4116
4757
|
this.initAudio();
|
|
4117
4758
|
};
|
|
4118
4759
|
this.ws.onmessage = event => {
|
|
4119
4760
|
try {
|
|
4120
4761
|
console.log("收到原始消息:", event.data);
|
|
4121
|
-
// 二进制数据直接返回
|
|
4122
4762
|
if (event.data instanceof ArrayBuffer) {
|
|
4123
4763
|
console.log("收到二进制音频数据");
|
|
4124
4764
|
return;
|
|
4125
4765
|
}
|
|
4126
|
-
// 解析JSON数据
|
|
4127
4766
|
const data = JSON.parse(event.data);
|
|
4128
4767
|
console.log("解析后的数据:", data);
|
|
4129
4768
|
if (data.type === 'config') {
|
|
4130
4769
|
console.log('配置信息:', data);
|
|
4131
4770
|
} else if (data.code === 0) {
|
|
4132
|
-
|
|
4133
|
-
console.log('检测到唤醒词...');
|
|
4134
|
-
} else if (data.data.type === 'Collecting') {
|
|
4135
|
-
console.log('状态: 采集中...');
|
|
4136
|
-
} else if (data.data.type === 'command') {
|
|
4137
|
-
// 根据指令改变机器人的状态
|
|
4138
|
-
console.log('状态: 处理中...');
|
|
4139
|
-
this.analyzeAudioCommand(data.data.category);
|
|
4140
|
-
} else {
|
|
4141
|
-
console.log('状态: 其他...');
|
|
4142
|
-
}
|
|
4771
|
+
this.handleWebSocketMessage(data.data);
|
|
4143
4772
|
} else {
|
|
4144
4773
|
console.error("服务器返回错误:", data.msg);
|
|
4145
4774
|
}
|
|
@@ -4148,7 +4777,7 @@ const FRAME_SIZE = 512;
|
|
|
4148
4777
|
}
|
|
4149
4778
|
};
|
|
4150
4779
|
this.ws.onclose = () => {
|
|
4151
|
-
console.log('连接关闭');
|
|
4780
|
+
console.log('WebSocket 连接关闭');
|
|
4152
4781
|
this.isConnected = false;
|
|
4153
4782
|
if (this.isRecording) {
|
|
4154
4783
|
this.stopRecording();
|
|
@@ -4156,76 +4785,367 @@ const FRAME_SIZE = 512;
|
|
|
4156
4785
|
setTimeout(() => {
|
|
4157
4786
|
console.log('尝试重新建立连接');
|
|
4158
4787
|
if (!this.isConnected) {
|
|
4159
|
-
// 尝试重连
|
|
4160
4788
|
this.initWebSocket();
|
|
4161
4789
|
}
|
|
4162
4790
|
}, 3000);
|
|
4163
4791
|
};
|
|
4792
|
+
this.ws.onerror = error => {
|
|
4793
|
+
console.error('WebSocket 错误:', error);
|
|
4794
|
+
};
|
|
4164
4795
|
} catch (error) {
|
|
4165
4796
|
console.error('WebSocket连接失败:', error);
|
|
4166
4797
|
}
|
|
4167
4798
|
},
|
|
4799
|
+
handleWebSocketMessage(data) {
|
|
4800
|
+
if (data.type === 'detection') {
|
|
4801
|
+
console.log('检测到唤醒词');
|
|
4802
|
+
this.avaterStatus = 'normal';
|
|
4803
|
+
} else if (data.type === 'Collecting') {
|
|
4804
|
+
console.log('状态: 采集中');
|
|
4805
|
+
this.avaterStatus = 'thinking';
|
|
4806
|
+
} else if (data.type === 'command') {
|
|
4807
|
+
console.log('状态: 处理中');
|
|
4808
|
+
this.analyzeAudioCommand(data.category);
|
|
4809
|
+
} else {
|
|
4810
|
+
console.log('状态: 其他');
|
|
4811
|
+
}
|
|
4812
|
+
},
|
|
4168
4813
|
closeWebSocket() {
|
|
4169
4814
|
if (this.ws) {
|
|
4170
4815
|
this.ws.close();
|
|
4171
4816
|
}
|
|
4172
|
-
}
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
});
|
|
4820
|
+
;// ./components/utils/StreamParser.js
|
|
4821
|
+
|
|
4822
|
+
|
|
4823
|
+
/**
|
|
4824
|
+
* SSE (Server-Sent Events) 流解析器
|
|
4825
|
+
* 优化点:
|
|
4826
|
+
* 1. 使用状态机模式处理标签解析
|
|
4827
|
+
* 2. 批量更新减少DOM操作
|
|
4828
|
+
* 3. 内存优化:避免频繁字符串拼接
|
|
4829
|
+
* 4. 可配置的更新频率
|
|
4830
|
+
*/
|
|
4831
|
+
class StreamParser {
|
|
4832
|
+
constructor(options = {}) {
|
|
4833
|
+
this.options = {
|
|
4834
|
+
updateInterval: 16,
|
|
4835
|
+
// 更新间隔(ms),默认约60fps
|
|
4836
|
+
batchSize: 100,
|
|
4837
|
+
// 批处理大小
|
|
4838
|
+
debug: false,
|
|
4839
|
+
// 是否开启调试
|
|
4840
|
+
...options
|
|
4841
|
+
};
|
|
4842
|
+
this.reset();
|
|
4843
|
+
}
|
|
4844
|
+
|
|
4845
|
+
/**
|
|
4846
|
+
* 重置解析器状态
|
|
4847
|
+
*/
|
|
4848
|
+
reset() {
|
|
4849
|
+
this.buffer = '';
|
|
4850
|
+
this.contentBuffer = []; // 使用数组缓冲,避免频繁字符串拼接
|
|
4851
|
+
this.thinkingBuffer = [];
|
|
4852
|
+
this.inTag = false;
|
|
4853
|
+
this.tagBuffer = '';
|
|
4854
|
+
this.updateTimer = null;
|
|
4855
|
+
this.status = 'output'; // thinking | output
|
|
4856
|
+
this.metrics = {
|
|
4857
|
+
startTime: Date.now(),
|
|
4858
|
+
chunks: 0,
|
|
4859
|
+
events: 0,
|
|
4860
|
+
chars: 0
|
|
4861
|
+
};
|
|
4862
|
+
}
|
|
4863
|
+
|
|
4864
|
+
/**
|
|
4865
|
+
* 处理流数据块
|
|
4866
|
+
* @param {string} chunk - 接收到的数据块
|
|
4867
|
+
* @param {Function} callback - 更新回调函数
|
|
4868
|
+
*/
|
|
4869
|
+
processChunk(chunk, callback) {
|
|
4870
|
+
this.metrics.chunks++;
|
|
4871
|
+
this.buffer += chunk;
|
|
4872
|
+
|
|
4873
|
+
// SSE 格式:事件由双换行符分隔
|
|
4874
|
+
const events = this.buffer.split('\n\n');
|
|
4875
|
+
|
|
4876
|
+
// 保留最后一个可能不完整的事件
|
|
4877
|
+
this.buffer = events.pop() || '';
|
|
4878
|
+
|
|
4879
|
+
// 处理完整的事件
|
|
4880
|
+
for (const event of events) {
|
|
4881
|
+
if (event.trim()) {
|
|
4882
|
+
this.metrics.events++;
|
|
4883
|
+
this.processEvent(event, callback);
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4886
|
+
}
|
|
4887
|
+
|
|
4888
|
+
/**
|
|
4889
|
+
* 处理单个SSE事件
|
|
4890
|
+
*/
|
|
4891
|
+
processEvent(eventStr, callback) {
|
|
4892
|
+
const lines = eventStr.split('\n');
|
|
4893
|
+
for (const line of lines) {
|
|
4894
|
+
// 解析 data: 行
|
|
4895
|
+
if (line.startsWith('data:')) {
|
|
4896
|
+
const data = line.substring(5).trim();
|
|
4897
|
+
if (data === '[DONE]') {
|
|
4898
|
+
this.flush(callback);
|
|
4899
|
+
return;
|
|
4900
|
+
}
|
|
4901
|
+
try {
|
|
4902
|
+
const parsed = JSON.parse(data);
|
|
4903
|
+
const content = parsed?.choices?.[0]?.delta?.content;
|
|
4904
|
+
if (content) {
|
|
4905
|
+
this.metrics.chars += content.length;
|
|
4906
|
+
this.parseContent(content, callback);
|
|
4186
4907
|
}
|
|
4187
|
-
})
|
|
4908
|
+
} catch (error) {
|
|
4909
|
+
if (this.options.debug) {
|
|
4910
|
+
console.warn('[StreamParser] JSON解析失败:', data);
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4188
4916
|
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4917
|
+
/**
|
|
4918
|
+
* 使用状态机解析内容和标签
|
|
4919
|
+
*/
|
|
4920
|
+
parseContent(content, callback) {
|
|
4921
|
+
let i = 0;
|
|
4922
|
+
while (i < content.length) {
|
|
4923
|
+
if (this.inTag) {
|
|
4924
|
+
// 在标签内部,查找标签结束
|
|
4925
|
+
const endIndex = content.indexOf('>', i);
|
|
4926
|
+
if (endIndex !== -1) {
|
|
4927
|
+
// 找到标签结束
|
|
4928
|
+
this.tagBuffer += content.substring(i, endIndex + 1);
|
|
4929
|
+
this.handleTag(this.tagBuffer);
|
|
4930
|
+
this.tagBuffer = '';
|
|
4931
|
+
this.inTag = false;
|
|
4932
|
+
i = endIndex + 1;
|
|
4933
|
+
} else {
|
|
4934
|
+
// 标签未结束,缓存剩余部分
|
|
4935
|
+
this.tagBuffer += content.substring(i);
|
|
4936
|
+
break;
|
|
4937
|
+
}
|
|
4938
|
+
} else {
|
|
4939
|
+
// 不在标签内,查找标签开始
|
|
4940
|
+
const startIndex = content.indexOf('<', i);
|
|
4941
|
+
if (startIndex !== -1) {
|
|
4942
|
+
// 找到标签开始,先处理前面的文本
|
|
4943
|
+
if (startIndex > i) {
|
|
4944
|
+
this.appendText(content.substring(i, startIndex));
|
|
4945
|
+
}
|
|
4195
4946
|
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4947
|
+
// 检查是否是完整标签
|
|
4948
|
+
const endIndex = content.indexOf('>', startIndex);
|
|
4949
|
+
if (endIndex !== -1) {
|
|
4950
|
+
// 完整标签
|
|
4951
|
+
const tag = content.substring(startIndex, endIndex + 1);
|
|
4952
|
+
this.handleTag(tag);
|
|
4953
|
+
i = endIndex + 1;
|
|
4954
|
+
} else {
|
|
4955
|
+
// 不完整标签,标记进入标签状态
|
|
4956
|
+
this.inTag = true;
|
|
4957
|
+
this.tagBuffer = content.substring(startIndex);
|
|
4958
|
+
break;
|
|
4959
|
+
}
|
|
4960
|
+
} else {
|
|
4961
|
+
// 没有标签,全部是文本
|
|
4962
|
+
this.appendText(content.substring(i));
|
|
4963
|
+
break;
|
|
4964
|
+
}
|
|
4208
4965
|
}
|
|
4966
|
+
}
|
|
4967
|
+
|
|
4968
|
+
// 定时批量更新
|
|
4969
|
+
this.scheduleUpdate(callback);
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4972
|
+
/**
|
|
4973
|
+
* 处理标签
|
|
4974
|
+
*/
|
|
4975
|
+
handleTag(tag) {
|
|
4976
|
+
const tagName = tag.toLowerCase();
|
|
4977
|
+
if (tagName === '<think>') {
|
|
4978
|
+
this.status = 'thinking';
|
|
4979
|
+
} else if (tagName === '</think>') {
|
|
4980
|
+
this.status = 'output';
|
|
4981
|
+
}
|
|
4982
|
+
// 可扩展:支持更多标签类型
|
|
4983
|
+
// else if (tagName.startsWith('<code')) {
|
|
4984
|
+
// this.status = 'code';
|
|
4985
|
+
// }
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4988
|
+
/**
|
|
4989
|
+
* 添加文本到缓冲区
|
|
4990
|
+
*/
|
|
4991
|
+
appendText(text) {
|
|
4992
|
+
if (!text) return;
|
|
4993
|
+
if (this.status === 'thinking') {
|
|
4994
|
+
this.thinkingBuffer.push(text);
|
|
4995
|
+
} else {
|
|
4996
|
+
this.contentBuffer.push(text);
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
|
|
5000
|
+
/**
|
|
5001
|
+
* 计划更新(防抖)
|
|
5002
|
+
*/
|
|
5003
|
+
scheduleUpdate(callback) {
|
|
5004
|
+
if (this.updateTimer) return;
|
|
5005
|
+
this.updateTimer = setTimeout(() => {
|
|
5006
|
+
this.flush(callback);
|
|
5007
|
+
this.updateTimer = null;
|
|
5008
|
+
}, this.options.updateInterval);
|
|
5009
|
+
}
|
|
5010
|
+
|
|
5011
|
+
/**
|
|
5012
|
+
* 立即刷新缓冲区
|
|
5013
|
+
*/
|
|
5014
|
+
flush(callback) {
|
|
5015
|
+
if (!callback) return;
|
|
5016
|
+
const hasThinking = this.thinkingBuffer.length > 0;
|
|
5017
|
+
const hasContent = this.contentBuffer.length > 0;
|
|
5018
|
+
if (!hasThinking && !hasContent) return;
|
|
5019
|
+
|
|
5020
|
+
// 使用 join 比字符串拼接性能更好
|
|
5021
|
+
const result = {
|
|
5022
|
+
thinking: hasThinking ? this.thinkingBuffer.join('') : null,
|
|
5023
|
+
content: hasContent ? this.contentBuffer.join('') : null,
|
|
5024
|
+
status: this.status
|
|
5025
|
+
};
|
|
5026
|
+
|
|
5027
|
+
// 清空缓冲区
|
|
5028
|
+
this.thinkingBuffer = [];
|
|
5029
|
+
this.contentBuffer = [];
|
|
5030
|
+
|
|
5031
|
+
// 回调更新
|
|
5032
|
+
callback(result);
|
|
5033
|
+
}
|
|
5034
|
+
|
|
5035
|
+
/**
|
|
5036
|
+
* 完成解析
|
|
5037
|
+
*/
|
|
5038
|
+
finish(callback) {
|
|
5039
|
+
this.flush(callback);
|
|
5040
|
+
if (this.updateTimer) {
|
|
5041
|
+
clearTimeout(this.updateTimer);
|
|
5042
|
+
this.updateTimer = null;
|
|
5043
|
+
}
|
|
5044
|
+
if (this.options.debug) {
|
|
5045
|
+
const duration = Date.now() - this.metrics.startTime;
|
|
5046
|
+
console.log('[StreamParser] 解析完成:', {
|
|
5047
|
+
耗时: `${duration}ms`,
|
|
5048
|
+
数据块: this.metrics.chunks,
|
|
5049
|
+
事件数: this.metrics.events,
|
|
5050
|
+
字符数: this.metrics.chars,
|
|
5051
|
+
平均速度: `${(this.metrics.chars / duration * 1000).toFixed(0)} chars/s`
|
|
5052
|
+
});
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
|
|
5056
|
+
/**
|
|
5057
|
+
* 销毁解析器
|
|
5058
|
+
*/
|
|
5059
|
+
destroy() {
|
|
5060
|
+
if (this.updateTimer) {
|
|
5061
|
+
clearTimeout(this.updateTimer);
|
|
5062
|
+
}
|
|
5063
|
+
this.reset();
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
/**
|
|
5068
|
+
* 使用示例:
|
|
5069
|
+
*
|
|
5070
|
+
* const parser = new StreamParser({ debug: true });
|
|
5071
|
+
*
|
|
5072
|
+
* // 处理流
|
|
5073
|
+
* for await (const chunk of stream) {
|
|
5074
|
+
* parser.processChunk(chunk, (result) => {
|
|
5075
|
+
* if (result.thinking) {
|
|
5076
|
+
* message.thinking += result.thinking;
|
|
5077
|
+
* }
|
|
5078
|
+
* if (result.content) {
|
|
5079
|
+
* message.content += result.content;
|
|
5080
|
+
* }
|
|
5081
|
+
* this.$forceUpdate();
|
|
5082
|
+
* });
|
|
5083
|
+
* }
|
|
5084
|
+
*
|
|
5085
|
+
* // 完成
|
|
5086
|
+
* parser.finish();
|
|
5087
|
+
*/
|
|
5088
|
+
;// ./components/mixins/messageMixin.js
|
|
5089
|
+
|
|
5090
|
+
|
|
5091
|
+
/* harmony default export */ var messageMixin = ({
|
|
5092
|
+
data() {
|
|
5093
|
+
return {
|
|
5094
|
+
streamParser: null
|
|
5095
|
+
};
|
|
5096
|
+
},
|
|
5097
|
+
created() {
|
|
5098
|
+
// 初始化流解析器
|
|
5099
|
+
this.streamParser = new StreamParser({
|
|
5100
|
+
updateInterval: 16,
|
|
5101
|
+
// 约60fps
|
|
5102
|
+
debug: "production" === 'development'
|
|
5103
|
+
});
|
|
5104
|
+
},
|
|
5105
|
+
methods: {
|
|
5106
|
+
createAiMessage() {
|
|
5107
|
+
const message = {
|
|
5108
|
+
id: this.messages.length + 1,
|
|
5109
|
+
type: 'ai',
|
|
5110
|
+
sender: 'AI',
|
|
5111
|
+
time: '',
|
|
5112
|
+
thinking: '',
|
|
5113
|
+
charts: [],
|
|
5114
|
+
content: ''
|
|
5115
|
+
};
|
|
5116
|
+
this.messages.push(message);
|
|
5117
|
+
this.currentMessage = message;
|
|
5118
|
+
return message;
|
|
5119
|
+
},
|
|
5120
|
+
createUserMessage(content) {
|
|
5121
|
+
const message = {
|
|
5122
|
+
id: this.messages.length + 1,
|
|
5123
|
+
type: 'user',
|
|
5124
|
+
sender: '用户',
|
|
5125
|
+
time: '',
|
|
5126
|
+
content
|
|
5127
|
+
};
|
|
5128
|
+
this.messages.push(message);
|
|
5129
|
+
this.inputMessage = '';
|
|
5130
|
+
return message;
|
|
4209
5131
|
},
|
|
4210
5132
|
async handleSend() {
|
|
4211
5133
|
if (!this.inputMessage.trim()) {
|
|
4212
5134
|
return;
|
|
4213
5135
|
}
|
|
4214
5136
|
const message = this.inputMessage.trim();
|
|
4215
|
-
|
|
4216
|
-
this.
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
time: new Date().toLocaleTimeString(),
|
|
4221
|
-
content: this.inputMessage
|
|
4222
|
-
});
|
|
4223
|
-
this.inputMessage = '';
|
|
5137
|
+
this.createUserMessage(message);
|
|
5138
|
+
this.createAiMessage();
|
|
5139
|
+
|
|
5140
|
+
// 重置解析器
|
|
5141
|
+
this.streamParser.reset();
|
|
4224
5142
|
try {
|
|
4225
|
-
const
|
|
5143
|
+
const startTime = Date.now();
|
|
5144
|
+
const controller = new AbortController();
|
|
5145
|
+
const token = `Bearer ac627d0a-8346-4ae9-b93a-f37ff6210adc`;
|
|
4226
5146
|
const response = await fetch('/bytserver/api-model/chat/stream', {
|
|
4227
|
-
timeout: 30000,
|
|
4228
5147
|
method: 'POST',
|
|
5148
|
+
signal: controller.signal,
|
|
4229
5149
|
headers: {
|
|
4230
5150
|
'Content-Type': 'application/json',
|
|
4231
5151
|
'Authorization': token
|
|
@@ -4235,243 +5155,236 @@ const FRAME_SIZE = 512;
|
|
|
4235
5155
|
})
|
|
4236
5156
|
});
|
|
4237
5157
|
if (!response.ok) {
|
|
4238
|
-
throw new Error(
|
|
5158
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5159
|
+
}
|
|
5160
|
+
|
|
5161
|
+
// 使用优化的流处理
|
|
5162
|
+
await this.consumeStream(response.body);
|
|
5163
|
+
|
|
5164
|
+
// 完成解析
|
|
5165
|
+
this.streamParser.finish(this.handleStreamUpdate);
|
|
5166
|
+
|
|
5167
|
+
// 记录耗时
|
|
5168
|
+
const duration = Date.now() - startTime;
|
|
5169
|
+
if (this.currentMessage) {
|
|
5170
|
+
this.currentMessage.time = (duration / 1000).toFixed(2);
|
|
4239
5171
|
}
|
|
4240
|
-
console.log(
|
|
4241
|
-
// 解析响应流
|
|
4242
|
-
this.parseResponseStream(response.body);
|
|
5172
|
+
console.log(`流处理完成,总耗时: ${duration}ms`);
|
|
4243
5173
|
} catch (error) {
|
|
4244
5174
|
console.error('发送消息失败:', error);
|
|
5175
|
+
if (this.currentMessage) {
|
|
5176
|
+
this.currentMessage.content = '抱歉,发生了错误,请重试。';
|
|
5177
|
+
this.$forceUpdate();
|
|
5178
|
+
}
|
|
4245
5179
|
}
|
|
4246
5180
|
},
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
5181
|
+
/**
|
|
5182
|
+
* 消费流数据
|
|
5183
|
+
*/
|
|
5184
|
+
async consumeStream(readableStream) {
|
|
5185
|
+
const reader = readableStream.getReader();
|
|
5186
|
+
const decoder = new TextDecoder('utf-8');
|
|
5187
|
+
try {
|
|
5188
|
+
// eslint-disable-next-line no-constant-condition
|
|
5189
|
+
while (true) {
|
|
5190
|
+
const {
|
|
5191
|
+
done,
|
|
5192
|
+
value
|
|
5193
|
+
} = await reader.read();
|
|
5194
|
+
if (done) break;
|
|
5195
|
+
const chunk = decoder.decode(value, {
|
|
5196
|
+
stream: true
|
|
5197
|
+
});
|
|
5198
|
+
|
|
5199
|
+
// 使用解析器处理数据块
|
|
5200
|
+
this.streamParser.processChunk(chunk, this.handleStreamUpdate);
|
|
5201
|
+
}
|
|
5202
|
+
} finally {
|
|
5203
|
+
reader.releaseLock();
|
|
4257
5204
|
}
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
5205
|
+
},
|
|
5206
|
+
/**
|
|
5207
|
+
* 处理流更新回调
|
|
5208
|
+
*/
|
|
5209
|
+
handleStreamUpdate(result) {
|
|
5210
|
+
if (!this.currentMessage) return;
|
|
5211
|
+
|
|
5212
|
+
// 更新思考内容
|
|
5213
|
+
if (result.thinking) {
|
|
5214
|
+
this.currentMessage.thinking += result.thinking;
|
|
4262
5215
|
}
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
this.
|
|
5216
|
+
|
|
5217
|
+
// 更新回复内容
|
|
5218
|
+
if (result.content) {
|
|
5219
|
+
this.currentMessage.content += result.content;
|
|
4267
5220
|
}
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
this.
|
|
5221
|
+
|
|
5222
|
+
// 更新状态
|
|
5223
|
+
if (result.status === 'thinking') {
|
|
5224
|
+
this.avaterStatus = 'thinking';
|
|
5225
|
+
} else {
|
|
5226
|
+
this.avaterStatus = 'output';
|
|
4272
5227
|
}
|
|
4273
|
-
},
|
|
4274
|
-
// 解析响应流
|
|
4275
|
-
parseResponseStream(body) {
|
|
4276
|
-
console.log(body);
|
|
4277
|
-
},
|
|
4278
|
-
processAudio(event) {
|
|
4279
|
-
if (!this.isRecording) return;
|
|
4280
|
-
// 5. 获取音频数据并处理
|
|
4281
|
-
const inputData = event.inputBuffer.getChannelData(0);
|
|
4282
5228
|
|
|
4283
|
-
//
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
5229
|
+
// 触发视图更新
|
|
5230
|
+
this.$forceUpdate();
|
|
5231
|
+
}
|
|
5232
|
+
},
|
|
5233
|
+
beforeDestroy() {
|
|
5234
|
+
// 清理解析器
|
|
5235
|
+
if (this.streamParser) {
|
|
5236
|
+
this.streamParser.destroy();
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
5239
|
+
});
|
|
5240
|
+
;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=script&lang=js
|
|
4288
5241
|
|
|
4289
|
-
// 当累积足够一帧时发送
|
|
4290
|
-
while (this.audioBuffer.length >= FRAME_SIZE) {
|
|
4291
|
-
const frame = this.audioBuffer.slice(0, FRAME_SIZE);
|
|
4292
|
-
this.audioBuffer = this.audioBuffer.slice(FRAME_SIZE);
|
|
4293
5242
|
|
|
4294
|
-
// 转换为16位PCM
|
|
4295
|
-
const pcmData = this.floatTo16BitPCM(frame);
|
|
4296
5243
|
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
5244
|
+
|
|
5245
|
+
|
|
5246
|
+
|
|
5247
|
+
|
|
5248
|
+
|
|
5249
|
+
|
|
5250
|
+
|
|
5251
|
+
|
|
5252
|
+
|
|
5253
|
+
|
|
5254
|
+
|
|
5255
|
+
const SAMPLE_RATE = 16000;
|
|
5256
|
+
const FRAME_SIZE = 512;
|
|
5257
|
+
/* harmony default export */ var ChatWindowvue_type_script_lang_js = ({
|
|
5258
|
+
name: 'ChatWindow',
|
|
5259
|
+
components: {
|
|
5260
|
+
ChatRobot: ChatRobot,
|
|
5261
|
+
ChatAvatar: ChatAvatar,
|
|
5262
|
+
ChatWindowDialog: ChatWindowDialog
|
|
5263
|
+
},
|
|
5264
|
+
mixins: [audioMixin, webSocketMixin, messageMixin],
|
|
5265
|
+
props: {
|
|
5266
|
+
appendToBody: {
|
|
5267
|
+
type: Boolean,
|
|
5268
|
+
default: true
|
|
5269
|
+
}
|
|
5270
|
+
},
|
|
5271
|
+
data() {
|
|
5272
|
+
return {
|
|
5273
|
+
audioSrc: '/minio/lingxiaoai/byt.mp3',
|
|
5274
|
+
inputMessage: '',
|
|
5275
|
+
visible: false,
|
|
5276
|
+
messages: [{
|
|
5277
|
+
id: 1,
|
|
5278
|
+
type: 'user',
|
|
5279
|
+
sender: '',
|
|
5280
|
+
time: '',
|
|
5281
|
+
content: '你好,欢迎来到凌霄大模型AI对话。'
|
|
5282
|
+
}, {
|
|
5283
|
+
id: 2,
|
|
5284
|
+
type: 'ai',
|
|
5285
|
+
sender: 'AI',
|
|
5286
|
+
time: '',
|
|
5287
|
+
thinking: '嗯,用户问的是回转窑的工业应用。首先,我需要回忆一下之前对话的内容。用户之前让我解释了水泥的制作流程,特别是提到了回转窑在高温煅烧熟料中的作用。',
|
|
5288
|
+
charts: [{
|
|
5289
|
+
title: '',
|
|
5290
|
+
options: {}
|
|
5291
|
+
}],
|
|
5292
|
+
content: '回转窑(Rotary Kiln)是一种长筒形旋转煅烧设备(类似倾斜安装的大管子),因其独特的旋转运动和高温耐火衬里设计,在多个工业领域都有广泛应用'
|
|
5293
|
+
}],
|
|
5294
|
+
robotStatus: 'leaving',
|
|
5295
|
+
avaterStatus: 'normal',
|
|
5296
|
+
currentMessage: null,
|
|
5297
|
+
thinkStatus: true,
|
|
5298
|
+
jumpedTimePoints: new Set(),
|
|
5299
|
+
SAMPLE_RATE,
|
|
5300
|
+
FRAME_SIZE
|
|
5301
|
+
};
|
|
5302
|
+
},
|
|
5303
|
+
mounted() {
|
|
5304
|
+
this.initWebSocket();
|
|
5305
|
+
if (this.appendToBody) {
|
|
5306
|
+
this.appendToBodyHandler();
|
|
5307
|
+
}
|
|
5308
|
+
},
|
|
5309
|
+
beforeDestroy() {
|
|
5310
|
+
if (this.appendToBody && this.$el.parentElement === document.body) {
|
|
5311
|
+
document.body.removeChild(this.$el);
|
|
5312
|
+
}
|
|
5313
|
+
this.closeWebSocket();
|
|
5314
|
+
this.stopRecording();
|
|
5315
|
+
},
|
|
5316
|
+
methods: {
|
|
4311
5317
|
toggleWindow() {
|
|
4312
5318
|
this.visible = !this.visible;
|
|
4313
5319
|
},
|
|
4314
|
-
|
|
4315
|
-
this.
|
|
5320
|
+
handleThinkingClick() {
|
|
5321
|
+
this.thinkStatus = !this.thinkStatus;
|
|
4316
5322
|
},
|
|
4317
|
-
|
|
5323
|
+
handleOverlayClick() {
|
|
4318
5324
|
this.visible = false;
|
|
4319
5325
|
},
|
|
4320
|
-
|
|
5326
|
+
appendToBodyHandler() {
|
|
4321
5327
|
this.$nextTick(() => {
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
chatArea.scrollTop = chatArea.scrollHeight;
|
|
5328
|
+
if (this.$el.parentElement !== document.body) {
|
|
5329
|
+
document.body.appendChild(this.$el);
|
|
4325
5330
|
}
|
|
4326
5331
|
});
|
|
4327
5332
|
},
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
stopRecording() {
|
|
4335
|
-
if (!this.isRecording) return;
|
|
4336
|
-
if (this.microphone) this.microphone.disconnect();
|
|
4337
|
-
if (this.processor) this.processor.disconnect();
|
|
4338
|
-
if (this.analyser) this.analyser.disconnect();
|
|
4339
|
-
if (this.audioContext) {
|
|
4340
|
-
this.audioContext.close().catch(e => {
|
|
4341
|
-
console.error("关闭音频上下文失败:", e);
|
|
4342
|
-
});
|
|
5333
|
+
// 音频时间更新处理
|
|
5334
|
+
onTimeUpdate() {
|
|
5335
|
+
const audio = this.$refs.audioPlayer;
|
|
5336
|
+
const currentTime = audio.currentTime;
|
|
5337
|
+
if (!this.jumpedTimePoints) {
|
|
5338
|
+
this.jumpedTimePoints = new Set();
|
|
4343
5339
|
}
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
5340
|
+
const timeJumpPoints = [{
|
|
5341
|
+
time: 40,
|
|
5342
|
+
url: '/permission/user',
|
|
5343
|
+
name: 'permission_user',
|
|
5344
|
+
title: '用户管理'
|
|
5345
|
+
}, {
|
|
5346
|
+
time: 65,
|
|
5347
|
+
url: '/permission/menu',
|
|
5348
|
+
name: 'permission_menu',
|
|
5349
|
+
title: '菜单管理'
|
|
5350
|
+
}, {
|
|
5351
|
+
time: 75,
|
|
5352
|
+
url: '/permission/role',
|
|
5353
|
+
name: 'permission_role',
|
|
5354
|
+
title: '角色管理'
|
|
5355
|
+
}];
|
|
5356
|
+
timeJumpPoints.forEach(point => {
|
|
5357
|
+
if (currentTime >= point.time && currentTime < point.time + 0.5 && !this.jumpedTimePoints.has(point.time)) {
|
|
5358
|
+
this.jumpedTimePoints.add(point.time);
|
|
5359
|
+
this.$appOptions.store.dispatch('tags/addTagview', {
|
|
5360
|
+
path: point.url,
|
|
5361
|
+
fullPath: point.url,
|
|
5362
|
+
label: point.title,
|
|
5363
|
+
name: point.title,
|
|
5364
|
+
meta: {
|
|
5365
|
+
title: point.title
|
|
5366
|
+
},
|
|
5367
|
+
query: {},
|
|
5368
|
+
params: {}
|
|
5369
|
+
});
|
|
5370
|
+
this.$appOptions.router.push({
|
|
5371
|
+
path: point.url
|
|
5372
|
+
});
|
|
4354
5373
|
}
|
|
4355
5374
|
});
|
|
4356
5375
|
},
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
this.
|
|
4360
|
-
}
|
|
4361
|
-
},
|
|
4362
|
-
watch: {
|
|
4363
|
-
messages: {
|
|
4364
|
-
handler() {
|
|
4365
|
-
this.scrollToBottom();
|
|
4366
|
-
},
|
|
4367
|
-
deep: true
|
|
5376
|
+
onAudioEnded() {
|
|
5377
|
+
this.robotStatus = 'leaving';
|
|
5378
|
+
this.jumpedTimePoints.clear();
|
|
4368
5379
|
}
|
|
4369
5380
|
}
|
|
4370
5381
|
});
|
|
4371
5382
|
;// ./components/ChatWindow.vue?vue&type=script&lang=js
|
|
4372
5383
|
/* harmony default export */ var components_ChatWindowvue_type_script_lang_js = (ChatWindowvue_type_script_lang_js);
|
|
4373
|
-
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=style&index=0&id=
|
|
5384
|
+
;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./components/ChatWindow.vue?vue&type=style&index=0&id=d604373c&prod&scoped=true&lang=css
|
|
4374
5385
|
// extracted by mini-css-extract-plugin
|
|
4375
5386
|
|
|
4376
|
-
;// ./components/ChatWindow.vue?vue&type=style&index=0&id=
|
|
4377
|
-
|
|
4378
|
-
;// ./node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js
|
|
4379
|
-
/* globals __VUE_SSR_CONTEXT__ */
|
|
4380
|
-
|
|
4381
|
-
// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
|
|
4382
|
-
// This module is a runtime utility for cleaner component module output and will
|
|
4383
|
-
// be included in the final webpack user bundle.
|
|
4384
|
-
|
|
4385
|
-
function normalizeComponent(
|
|
4386
|
-
scriptExports,
|
|
4387
|
-
render,
|
|
4388
|
-
staticRenderFns,
|
|
4389
|
-
functionalTemplate,
|
|
4390
|
-
injectStyles,
|
|
4391
|
-
scopeId,
|
|
4392
|
-
moduleIdentifier /* server only */,
|
|
4393
|
-
shadowMode /* vue-cli only */
|
|
4394
|
-
) {
|
|
4395
|
-
// Vue.extend constructor export interop
|
|
4396
|
-
var options =
|
|
4397
|
-
typeof scriptExports === 'function' ? scriptExports.options : scriptExports
|
|
4398
|
-
|
|
4399
|
-
// render functions
|
|
4400
|
-
if (render) {
|
|
4401
|
-
options.render = render
|
|
4402
|
-
options.staticRenderFns = staticRenderFns
|
|
4403
|
-
options._compiled = true
|
|
4404
|
-
}
|
|
4405
|
-
|
|
4406
|
-
// functional template
|
|
4407
|
-
if (functionalTemplate) {
|
|
4408
|
-
options.functional = true
|
|
4409
|
-
}
|
|
4410
|
-
|
|
4411
|
-
// scopedId
|
|
4412
|
-
if (scopeId) {
|
|
4413
|
-
options._scopeId = 'data-v-' + scopeId
|
|
4414
|
-
}
|
|
4415
|
-
|
|
4416
|
-
var hook
|
|
4417
|
-
if (moduleIdentifier) {
|
|
4418
|
-
// server build
|
|
4419
|
-
hook = function (context) {
|
|
4420
|
-
// 2.3 injection
|
|
4421
|
-
context =
|
|
4422
|
-
context || // cached call
|
|
4423
|
-
(this.$vnode && this.$vnode.ssrContext) || // stateful
|
|
4424
|
-
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
|
|
4425
|
-
// 2.2 with runInNewContext: true
|
|
4426
|
-
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
|
4427
|
-
context = __VUE_SSR_CONTEXT__
|
|
4428
|
-
}
|
|
4429
|
-
// inject component styles
|
|
4430
|
-
if (injectStyles) {
|
|
4431
|
-
injectStyles.call(this, context)
|
|
4432
|
-
}
|
|
4433
|
-
// register component module identifier for async chunk inferrence
|
|
4434
|
-
if (context && context._registeredComponents) {
|
|
4435
|
-
context._registeredComponents.add(moduleIdentifier)
|
|
4436
|
-
}
|
|
4437
|
-
}
|
|
4438
|
-
// used by ssr in case component is cached and beforeCreate
|
|
4439
|
-
// never gets called
|
|
4440
|
-
options._ssrRegister = hook
|
|
4441
|
-
} else if (injectStyles) {
|
|
4442
|
-
hook = shadowMode
|
|
4443
|
-
? function () {
|
|
4444
|
-
injectStyles.call(
|
|
4445
|
-
this,
|
|
4446
|
-
(options.functional ? this.parent : this).$root.$options.shadowRoot
|
|
4447
|
-
)
|
|
4448
|
-
}
|
|
4449
|
-
: injectStyles
|
|
4450
|
-
}
|
|
4451
|
-
|
|
4452
|
-
if (hook) {
|
|
4453
|
-
if (options.functional) {
|
|
4454
|
-
// for template-only hot-reload because in that case the render fn doesn't
|
|
4455
|
-
// go through the normalizer
|
|
4456
|
-
options._injectStyles = hook
|
|
4457
|
-
// register for functional component in vue file
|
|
4458
|
-
var originalRender = options.render
|
|
4459
|
-
options.render = function renderWithStyleInjection(h, context) {
|
|
4460
|
-
hook.call(context)
|
|
4461
|
-
return originalRender(h, context)
|
|
4462
|
-
}
|
|
4463
|
-
} else {
|
|
4464
|
-
// inject component registration as beforeCreate hook
|
|
4465
|
-
var existing = options.beforeCreate
|
|
4466
|
-
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
|
|
4467
|
-
}
|
|
4468
|
-
}
|
|
4469
|
-
|
|
4470
|
-
return {
|
|
4471
|
-
exports: scriptExports,
|
|
4472
|
-
options: options
|
|
4473
|
-
}
|
|
4474
|
-
}
|
|
5387
|
+
;// ./components/ChatWindow.vue?vue&type=style&index=0&id=d604373c&prod&scoped=true&lang=css
|
|
4475
5388
|
|
|
4476
5389
|
;// ./components/ChatWindow.vue
|
|
4477
5390
|
|
|
@@ -4482,18 +5395,18 @@ function normalizeComponent(
|
|
|
4482
5395
|
|
|
4483
5396
|
/* normalize component */
|
|
4484
5397
|
|
|
4485
|
-
var
|
|
5398
|
+
var ChatWindow_component = normalizeComponent(
|
|
4486
5399
|
components_ChatWindowvue_type_script_lang_js,
|
|
4487
5400
|
render,
|
|
4488
5401
|
staticRenderFns,
|
|
4489
5402
|
false,
|
|
4490
5403
|
null,
|
|
4491
|
-
"
|
|
5404
|
+
"d604373c",
|
|
4492
5405
|
null
|
|
4493
5406
|
|
|
4494
5407
|
)
|
|
4495
5408
|
|
|
4496
|
-
/* harmony default export */ var ChatWindow = (
|
|
5409
|
+
/* harmony default export */ var ChatWindow = (ChatWindow_component.exports);
|
|
4497
5410
|
;// ./components/index.js
|
|
4498
5411
|
|
|
4499
5412
|
|