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