byt-lingxiao-ai 0.3.28 → 0.3.30
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/AudioSubtitle.vue +60 -0
- package/components/ChatWindow.vue +362 -70
- package/components/assets/left.png +0 -0
- package/components/assets/right.png +0 -0
- package/components/config/blacklist.js +3 -0
- package/components/config/index.js +12 -3
- package/components/mixins/audioMixin.js +137 -80
- package/components/mixins/webSocketMixin.js +7 -10
- package/dist/index.common.js +546 -133
- package/dist/index.common.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.umd.js +546 -133
- 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 +2 -2
package/dist/index.common.js
CHANGED
|
@@ -66359,7 +66359,7 @@ if (typeof window !== 'undefined') {
|
|
|
66359
66359
|
var es_iterator_constructor = __webpack_require__(8111);
|
|
66360
66360
|
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.iterator.for-each.js
|
|
66361
66361
|
var es_iterator_for_each = __webpack_require__(7588);
|
|
66362
|
-
;// ./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=
|
|
66362
|
+
;// ./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=959a9f66&scoped=true
|
|
66363
66363
|
var render = function render() {
|
|
66364
66364
|
var _vm = this,
|
|
66365
66365
|
_c = _vm._self._c;
|
|
@@ -66369,16 +66369,16 @@ var render = function render() {
|
|
|
66369
66369
|
}, [_c('audio', {
|
|
66370
66370
|
ref: "audioPlayer",
|
|
66371
66371
|
staticClass: "hidden-audio",
|
|
66372
|
+
attrs: {
|
|
66373
|
+
"src": _vm.audioSrc,
|
|
66374
|
+
"controls": "",
|
|
66375
|
+
"preload": "auto"
|
|
66376
|
+
},
|
|
66372
66377
|
on: {
|
|
66373
66378
|
"timeupdate": _vm.onTimeUpdate,
|
|
66374
66379
|
"ended": _vm.onAudioEnded
|
|
66375
66380
|
}
|
|
66376
|
-
},
|
|
66377
|
-
attrs: {
|
|
66378
|
-
"src": _vm.audioSrc,
|
|
66379
|
-
"type": "audio/mpeg"
|
|
66380
|
-
}
|
|
66381
|
-
}), _vm._v(" 您的浏览器不支持音频元素。 ")]), _vm.robotStatus !== 'leaving' ? _c('ChatRobot', {
|
|
66381
|
+
}), _vm.robotStatus !== 'leaving' ? _c('ChatRobot', {
|
|
66382
66382
|
attrs: {
|
|
66383
66383
|
"status": _vm.robotStatus
|
|
66384
66384
|
}
|
|
@@ -66387,7 +66387,9 @@ var render = function render() {
|
|
|
66387
66387
|
"status": _vm.avaterStatus
|
|
66388
66388
|
},
|
|
66389
66389
|
on: {
|
|
66390
|
-
"mousedown":
|
|
66390
|
+
"mousedown": function ($event) {
|
|
66391
|
+
return _vm.startDrag($event);
|
|
66392
|
+
}
|
|
66391
66393
|
}
|
|
66392
66394
|
}), _c('ChatWindowDialog', {
|
|
66393
66395
|
attrs: {
|
|
@@ -66412,6 +66414,11 @@ var render = function render() {
|
|
|
66412
66414
|
},
|
|
66413
66415
|
expression: "visible"
|
|
66414
66416
|
}
|
|
66417
|
+
}), _c('AudioSubtitle', {
|
|
66418
|
+
ref: "audioSubtitle",
|
|
66419
|
+
attrs: {
|
|
66420
|
+
"current-subtitle": _vm.currentSubtitle
|
|
66421
|
+
}
|
|
66415
66422
|
})], 1);
|
|
66416
66423
|
};
|
|
66417
66424
|
var staticRenderFns = [];
|
|
@@ -69543,6 +69550,59 @@ var ChatWindowDialog_component = normalizeComponent(
|
|
|
69543
69550
|
)
|
|
69544
69551
|
|
|
69545
69552
|
/* harmony default export */ var ChatWindowDialog = (ChatWindowDialog_component.exports);
|
|
69553
|
+
;// ./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/AudioSubtitle.vue?vue&type=template&id=4f65515b&scoped=true
|
|
69554
|
+
var AudioSubtitlevue_type_template_id_4f65515b_scoped_true_render = function render() {
|
|
69555
|
+
var _vm = this,
|
|
69556
|
+
_c = _vm._self._c;
|
|
69557
|
+
return _vm.currentSubtitle ? _c('div', {
|
|
69558
|
+
staticClass: "subtitle-container"
|
|
69559
|
+
}, [_c('div', {
|
|
69560
|
+
staticClass: "subtitle-text"
|
|
69561
|
+
}, [_c('div', {
|
|
69562
|
+
staticClass: "subtitle-left"
|
|
69563
|
+
}), _vm._v(" " + _vm._s(_vm.currentSubtitle) + " "), _c('div', {
|
|
69564
|
+
staticClass: "subtitle-right"
|
|
69565
|
+
})])]) : _vm._e();
|
|
69566
|
+
};
|
|
69567
|
+
var AudioSubtitlevue_type_template_id_4f65515b_scoped_true_staticRenderFns = [];
|
|
69568
|
+
|
|
69569
|
+
;// ./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/AudioSubtitle.vue?vue&type=script&lang=js
|
|
69570
|
+
/* harmony default export */ var AudioSubtitlevue_type_script_lang_js = ({
|
|
69571
|
+
props: {
|
|
69572
|
+
currentSubtitle: {
|
|
69573
|
+
type: String,
|
|
69574
|
+
default: ''
|
|
69575
|
+
}
|
|
69576
|
+
}
|
|
69577
|
+
});
|
|
69578
|
+
;// ./components/AudioSubtitle.vue?vue&type=script&lang=js
|
|
69579
|
+
/* harmony default export */ var components_AudioSubtitlevue_type_script_lang_js = (AudioSubtitlevue_type_script_lang_js);
|
|
69580
|
+
;// ./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/AudioSubtitle.vue?vue&type=style&index=0&id=4f65515b&prod&scoped=true&lang=css
|
|
69581
|
+
// extracted by mini-css-extract-plugin
|
|
69582
|
+
|
|
69583
|
+
;// ./components/AudioSubtitle.vue?vue&type=style&index=0&id=4f65515b&prod&scoped=true&lang=css
|
|
69584
|
+
|
|
69585
|
+
;// ./components/AudioSubtitle.vue
|
|
69586
|
+
|
|
69587
|
+
|
|
69588
|
+
|
|
69589
|
+
;
|
|
69590
|
+
|
|
69591
|
+
|
|
69592
|
+
/* normalize component */
|
|
69593
|
+
|
|
69594
|
+
var AudioSubtitle_component = normalizeComponent(
|
|
69595
|
+
components_AudioSubtitlevue_type_script_lang_js,
|
|
69596
|
+
AudioSubtitlevue_type_template_id_4f65515b_scoped_true_render,
|
|
69597
|
+
AudioSubtitlevue_type_template_id_4f65515b_scoped_true_staticRenderFns,
|
|
69598
|
+
false,
|
|
69599
|
+
null,
|
|
69600
|
+
"4f65515b",
|
|
69601
|
+
null
|
|
69602
|
+
|
|
69603
|
+
)
|
|
69604
|
+
|
|
69605
|
+
/* harmony default export */ var AudioSubtitle = (AudioSubtitle_component.exports);
|
|
69546
69606
|
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
|
|
69547
69607
|
var es_array_buffer_detached = __webpack_require__(6573);
|
|
69548
69608
|
// EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
|
|
@@ -69556,23 +69616,92 @@ var es_typed_array_with = __webpack_require__(9577);
|
|
|
69556
69616
|
|
|
69557
69617
|
|
|
69558
69618
|
|
|
69619
|
+
|
|
69620
|
+
|
|
69621
|
+
|
|
69622
|
+
|
|
69623
|
+
|
|
69559
69624
|
/* harmony default export */ var audioMixin = ({
|
|
69560
69625
|
data() {
|
|
69561
69626
|
return {
|
|
69627
|
+
audioContext: null,
|
|
69628
|
+
workletNode: null,
|
|
69629
|
+
mediaStreamSource: null,
|
|
69562
69630
|
isRecording: false,
|
|
69563
69631
|
isMicAvailable: false,
|
|
69564
|
-
|
|
69565
|
-
microphone: null,
|
|
69566
|
-
processor: null,
|
|
69567
|
-
audioBuffer: new Float32Array(0)
|
|
69632
|
+
audioData: new Float32Array(128)
|
|
69568
69633
|
};
|
|
69569
69634
|
},
|
|
69570
69635
|
methods: {
|
|
69636
|
+
async initAudioWorklet() {
|
|
69637
|
+
if (this.audioContext) return;
|
|
69638
|
+
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
69639
|
+
this.audioContext = new AudioContext({
|
|
69640
|
+
sampleRate: this.SAMPLE_RATE
|
|
69641
|
+
});
|
|
69642
|
+
const processorCode = `
|
|
69643
|
+
class RecorderProcessor extends AudioWorkletProcessor {
|
|
69644
|
+
constructor() {
|
|
69645
|
+
super();
|
|
69646
|
+
this.buffer = [];
|
|
69647
|
+
this.frameSize = ${this.FRAME_SIZE};
|
|
69648
|
+
}
|
|
69649
|
+
|
|
69650
|
+
process(inputs) {
|
|
69651
|
+
const input = inputs[0];
|
|
69652
|
+
if (!input || !input[0]) return true;
|
|
69653
|
+
|
|
69654
|
+
const channel = input[0];
|
|
69655
|
+
|
|
69656
|
+
for (let i = 0; i < channel.length; i++) {
|
|
69657
|
+
this.buffer.push(channel[i]);
|
|
69658
|
+
}
|
|
69659
|
+
|
|
69660
|
+
while (this.buffer.length >= this.frameSize) {
|
|
69661
|
+
const frame = this.buffer.splice(0, this.frameSize);
|
|
69662
|
+
|
|
69663
|
+
// PCM
|
|
69664
|
+
const pcm = this.floatTo16BitPCM(frame);
|
|
69665
|
+
this.port.postMessage({
|
|
69666
|
+
type: 'audio',
|
|
69667
|
+
payload: pcm
|
|
69668
|
+
});
|
|
69669
|
+
|
|
69670
|
+
// Visual(下采样)
|
|
69671
|
+
this.port.postMessage({
|
|
69672
|
+
type: 'visual',
|
|
69673
|
+
payload: new Float32Array(frame.slice(0, 128))
|
|
69674
|
+
});
|
|
69675
|
+
}
|
|
69676
|
+
return true;
|
|
69677
|
+
}
|
|
69678
|
+
|
|
69679
|
+
floatTo16BitPCM(float32Array) {
|
|
69680
|
+
const pcm = new Int16Array(float32Array.length);
|
|
69681
|
+
for (let i = 0; i < float32Array.length; i++) {
|
|
69682
|
+
let s = Math.max(-1, Math.min(1, float32Array[i]));
|
|
69683
|
+
pcm[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
|
|
69684
|
+
}
|
|
69685
|
+
return pcm.buffer;
|
|
69686
|
+
}
|
|
69687
|
+
}
|
|
69688
|
+
|
|
69689
|
+
registerProcessor('recorder-processor', RecorderProcessor);
|
|
69690
|
+
`;
|
|
69691
|
+
const blob = new Blob([processorCode], {
|
|
69692
|
+
type: 'application/javascript'
|
|
69693
|
+
});
|
|
69694
|
+
const moduleUrl = URL.createObjectURL(blob);
|
|
69695
|
+
await this.audioContext.audioWorklet.addModule(moduleUrl);
|
|
69696
|
+
this.workletNode = new AudioWorkletNode(this.audioContext, 'recorder-processor');
|
|
69697
|
+
this.workletNode.port.onmessage = this.handleWorkletMessage;
|
|
69698
|
+
},
|
|
69571
69699
|
async initAudio() {
|
|
69572
69700
|
if (this.isRecording) return;
|
|
69573
69701
|
try {
|
|
69574
69702
|
this.isMicAvailable = true;
|
|
69575
|
-
|
|
69703
|
+
await this.initAudioWorklet();
|
|
69704
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
69576
69705
|
audio: {
|
|
69577
69706
|
sampleRate: this.SAMPLE_RATE,
|
|
69578
69707
|
channelCount: 1,
|
|
@@ -69581,103 +69710,95 @@ var es_typed_array_with = __webpack_require__(9577);
|
|
|
69581
69710
|
autoGainControl: false
|
|
69582
69711
|
}
|
|
69583
69712
|
});
|
|
69584
|
-
this.
|
|
69585
|
-
|
|
69586
|
-
|
|
69587
|
-
|
|
69588
|
-
|
|
69589
|
-
this.processor.onaudioprocess = this.processAudio;
|
|
69590
|
-
this.microphone.connect(this.processor);
|
|
69591
|
-
this.processor.connect(this.audioContext.destination);
|
|
69713
|
+
this.mediaStreamSource = this.audioContext.createMediaStreamSource(this.stream);
|
|
69714
|
+
this.mediaStreamSource.connect(this.workletNode);
|
|
69715
|
+
if (this.audioContext.state === 'suspended') {
|
|
69716
|
+
await this.audioContext.resume();
|
|
69717
|
+
}
|
|
69592
69718
|
this.isRecording = true;
|
|
69593
|
-
console.log(
|
|
69594
|
-
} catch (
|
|
69595
|
-
console.error(
|
|
69719
|
+
console.log(`AudioWorklet 录音中 (${this.SAMPLE_RATE}Hz)`);
|
|
69720
|
+
} catch (e) {
|
|
69721
|
+
console.error('音频初始化失败:', e);
|
|
69596
69722
|
this.isRecording = false;
|
|
69597
69723
|
this.isMicAvailable = false;
|
|
69598
69724
|
}
|
|
69599
69725
|
},
|
|
69600
|
-
|
|
69601
|
-
|
|
69602
|
-
|
|
69603
|
-
|
|
69604
|
-
|
|
69605
|
-
|
|
69606
|
-
|
|
69607
|
-
|
|
69608
|
-
const frame = this.audioBuffer.slice(0, this.FRAME_SIZE);
|
|
69609
|
-
this.audioBuffer = this.audioBuffer.slice(this.FRAME_SIZE);
|
|
69610
|
-
const pcmData = this.floatTo16BitPCM(frame);
|
|
69611
|
-
if (this.ws && this.ws.readyState === this.ws.OPEN) {
|
|
69612
|
-
this.ws.send(pcmData);
|
|
69726
|
+
handleWorkletMessage(e) {
|
|
69727
|
+
const {
|
|
69728
|
+
type,
|
|
69729
|
+
payload
|
|
69730
|
+
} = e.data;
|
|
69731
|
+
if (type === 'audio') {
|
|
69732
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
69733
|
+
this.ws.send(payload);
|
|
69613
69734
|
}
|
|
69614
69735
|
}
|
|
69615
69736
|
},
|
|
69616
|
-
floatTo16BitPCM(input) {
|
|
69617
|
-
const output = new Int16Array(input.length);
|
|
69618
|
-
for (let i = 0; i < input.length; i++) {
|
|
69619
|
-
const s = Math.max(-1, Math.min(1, input[i]));
|
|
69620
|
-
output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
|
69621
|
-
}
|
|
69622
|
-
return output.buffer;
|
|
69623
|
-
},
|
|
69624
69737
|
stopRecording() {
|
|
69625
69738
|
if (!this.isRecording) return;
|
|
69626
|
-
if (this.
|
|
69627
|
-
if (this.
|
|
69628
|
-
if (this.
|
|
69739
|
+
if (this.mediaStreamSource) this.mediaStreamSource.disconnect();
|
|
69740
|
+
if (this.workletNode) this.workletNode.disconnect();
|
|
69741
|
+
if (this.stream) {
|
|
69742
|
+
this.stream.getTracks().forEach(t => t.stop());
|
|
69743
|
+
}
|
|
69629
69744
|
if (this.audioContext) {
|
|
69630
|
-
this.audioContext.close()
|
|
69631
|
-
|
|
69632
|
-
});
|
|
69745
|
+
this.audioContext.close();
|
|
69746
|
+
this.audioContext = null;
|
|
69633
69747
|
}
|
|
69634
69748
|
this.isRecording = false;
|
|
69749
|
+
console.log('录音已停止');
|
|
69750
|
+
},
|
|
69751
|
+
handleWebSocketMessage(data) {
|
|
69752
|
+
if (data.type === 'detection') {
|
|
69753
|
+
if (this.robotStatus === 'speaking') {
|
|
69754
|
+
this.robotStatus = 'waiting';
|
|
69755
|
+
}
|
|
69756
|
+
this.avaterStatus = 'normal';
|
|
69757
|
+
this.startTime = Date.now();
|
|
69758
|
+
}
|
|
69759
|
+
if (data.type === 'Collecting') {
|
|
69760
|
+
this.avaterStatus = 'thinking';
|
|
69761
|
+
}
|
|
69762
|
+
if (data.type === 'command') {
|
|
69763
|
+
if (this.startTime) {
|
|
69764
|
+
console.log(`[Latency] ${Date.now() - this.startTime}ms`);
|
|
69765
|
+
this.startTime = null;
|
|
69766
|
+
}
|
|
69767
|
+
this.analyzeAudioCommand(data.category);
|
|
69768
|
+
}
|
|
69635
69769
|
},
|
|
69636
69770
|
play() {
|
|
69637
|
-
this.
|
|
69638
|
-
this.$refs.audioPlayer.play();
|
|
69771
|
+
this.$refs.audioPlayer?.play();
|
|
69639
69772
|
},
|
|
69640
69773
|
pause() {
|
|
69641
|
-
|
|
69642
|
-
this.robotStatus = 'waiting';
|
|
69643
|
-
this.$refs.audioPlayer.pause();
|
|
69774
|
+
this.$refs.audioPlayer?.pause();
|
|
69644
69775
|
},
|
|
69645
69776
|
stop() {
|
|
69646
|
-
|
|
69647
|
-
|
|
69648
|
-
|
|
69649
|
-
|
|
69650
|
-
},
|
|
69651
|
-
analyzeAudioCommand(command) {
|
|
69652
|
-
console.log('分析音频命令:', command);
|
|
69653
|
-
if (command === 'C5') {
|
|
69654
|
-
this.robotStatus = 'entering';
|
|
69655
|
-
setTimeout(() => {
|
|
69656
|
-
this.robotStatus = 'speaking';
|
|
69657
|
-
this.play();
|
|
69658
|
-
}, 3000);
|
|
69659
|
-
} else if (command === 'C8') {
|
|
69660
|
-
this.robotStatus = 'speaking';
|
|
69661
|
-
this.play();
|
|
69662
|
-
} else if (command === 'C7') {
|
|
69663
|
-
this.robotStatus = 'waiting';
|
|
69664
|
-
this.pause();
|
|
69665
|
-
} else if (command === 'C6') {
|
|
69666
|
-
this.robotStatus = 'leaving';
|
|
69667
|
-
this.avaterStatus = 'normal';
|
|
69668
|
-
this.stop();
|
|
69669
|
-
}
|
|
69777
|
+
const p = this.$refs.audioPlayer;
|
|
69778
|
+
if (!p) return;
|
|
69779
|
+
p.pause();
|
|
69780
|
+
p.currentTime = 0;
|
|
69670
69781
|
}
|
|
69671
69782
|
}
|
|
69672
69783
|
});
|
|
69673
69784
|
// EXTERNAL MODULE: ./node_modules/core-js/modules/esnext.json.parse.js
|
|
69674
69785
|
var esnext_json_parse = __webpack_require__(8335);
|
|
69675
69786
|
;// ./components/config/index.js
|
|
69676
|
-
const baseUrl = window.location.host;
|
|
69787
|
+
// const baseUrl = window.location.host;
|
|
69788
|
+
|
|
69677
69789
|
const API_URL = `/lingxiao-byt/api/v1/mcp/ask`; // 对话
|
|
69678
|
-
const WS_URL = `ws://${baseUrl}/audio/ws/`;
|
|
69679
|
-
const
|
|
69790
|
+
// export const WS_URL = `ws://${baseUrl}/audio/ws/`; // 语音
|
|
69791
|
+
const WS_URL = `ws://220.189.237.146:8312/audio/ws/`; // 测试语音
|
|
69792
|
+
|
|
69793
|
+
const AUDIO_URL = '/minio/lingxiaoai/byt.mp3'; // 导览 铜梁
|
|
69794
|
+
|
|
69795
|
+
const COLLECTION = '/minio/lingxiaoai/collection.mp3';
|
|
69796
|
+
const AREA_BOARD = '/minio/lingxiaoai/area_board.mp3'; // 区域看板
|
|
69797
|
+
const ENTERPRISE_APPLICATION = '/minio/lingxiaoai/enterprise_application.mp3'; // 企业应用
|
|
69798
|
+
const REGIONAL_APPLICATION = '/minio/lingxiaoai/regional_application.mp3'; // 区域应用
|
|
69799
|
+
|
|
69680
69800
|
const TIME_JUMP_POINTS_URL = '/minio/lingxiaoai/timeJumpPoints.json'; // 语音url跳转节点
|
|
69801
|
+
const SUBTITLE_POINTS_URL = '/minio/lingxiaoai/subTitlePoints.json'; // 字幕跳转节点
|
|
69681
69802
|
;// ./components/mixins/webSocketMixin.js
|
|
69682
69803
|
|
|
69683
69804
|
|
|
@@ -69697,11 +69818,7 @@ const TIME_JUMP_POINTS_URL = '/minio/lingxiaoai/timeJumpPoints.json'; // 语音u
|
|
|
69697
69818
|
methods: {
|
|
69698
69819
|
initWebSocket() {
|
|
69699
69820
|
try {
|
|
69700
|
-
// this.ws = new WebSocket('ws://10.2.233.41:9999');
|
|
69701
|
-
// 测试
|
|
69702
|
-
// console.log('WS_URL:', WS_URL)
|
|
69703
69821
|
this.ws = new WebSocket(WS_URL);
|
|
69704
|
-
// this.ws = new WebSocket('ws://192.168.8.87/audio/ws/');
|
|
69705
69822
|
this.ws.binaryType = 'arraybuffer';
|
|
69706
69823
|
this.ws.onopen = async () => {
|
|
69707
69824
|
console.log('WebSocket 连接成功');
|
|
@@ -69771,12 +69888,15 @@ const TIME_JUMP_POINTS_URL = '/minio/lingxiaoai/timeJumpPoints.json'; // 语音u
|
|
|
69771
69888
|
console.log('状态: 处理中');
|
|
69772
69889
|
|
|
69773
69890
|
// 性能检测终点
|
|
69774
|
-
if (this.startTime) {
|
|
69775
|
-
|
|
69776
|
-
|
|
69777
|
-
|
|
69778
|
-
}
|
|
69891
|
+
// if (this.startTime) {
|
|
69892
|
+
// const latency = Date.now() - this.startTime;
|
|
69893
|
+
// console.log(`[Latency] 完整命令处理耗时: ${latency}ms`); // 记录端到端延迟
|
|
69894
|
+
// this.startTime = null;
|
|
69895
|
+
// }
|
|
69896
|
+
|
|
69779
69897
|
this.analyzeAudioCommand(data.category);
|
|
69898
|
+
} else if (data.type === 'voice') {
|
|
69899
|
+
this.analyzeVoiceCommand(data.category);
|
|
69780
69900
|
} else {
|
|
69781
69901
|
console.log('状态: 其他');
|
|
69782
69902
|
this.avaterStatus = 'normal';
|
|
@@ -70170,6 +70290,9 @@ function generateUuid() {
|
|
|
70170
70290
|
},
|
|
70171
70291
|
beforeDestroy() {}
|
|
70172
70292
|
});
|
|
70293
|
+
;// ./components/config/blacklist.js
|
|
70294
|
+
const BLACKLIST = ['81010400' // 南方水泥
|
|
70295
|
+
];
|
|
70173
70296
|
;// ./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
|
|
70174
70297
|
|
|
70175
70298
|
|
|
@@ -70189,15 +70312,30 @@ function generateUuid() {
|
|
|
70189
70312
|
|
|
70190
70313
|
|
|
70191
70314
|
|
|
70315
|
+
|
|
70192
70316
|
const SAMPLE_RATE = 16000;
|
|
70193
70317
|
const FRAME_SIZE = 512;
|
|
70194
|
-
const
|
|
70318
|
+
const ROBOT_STATUS = {
|
|
70319
|
+
ENTERING: 'entering',
|
|
70320
|
+
// 进入中
|
|
70321
|
+
SPEAKING: 'speaking',
|
|
70322
|
+
// 说话中
|
|
70323
|
+
WAITING: 'waiting',
|
|
70324
|
+
// 等待中
|
|
70325
|
+
LEAVING: 'leaving' // 离开中
|
|
70326
|
+
};
|
|
70327
|
+
const AVATAR_STATUS = {
|
|
70328
|
+
NORMAL: 'normal',
|
|
70329
|
+
// 正常
|
|
70330
|
+
THINKING: 'thinking' // 思考中
|
|
70331
|
+
};
|
|
70195
70332
|
/* harmony default export */ var ChatWindowvue_type_script_lang_js = ({
|
|
70196
70333
|
name: 'ChatWindow',
|
|
70197
70334
|
components: {
|
|
70198
70335
|
ChatRobot: ChatRobot,
|
|
70199
70336
|
ChatAvatar: ChatAvatar,
|
|
70200
|
-
ChatWindowDialog: ChatWindowDialog
|
|
70337
|
+
ChatWindowDialog: ChatWindowDialog,
|
|
70338
|
+
AudioSubtitle: AudioSubtitle
|
|
70201
70339
|
},
|
|
70202
70340
|
mixins: [audioMixin, webSocketMixin, messageMixin],
|
|
70203
70341
|
props: {
|
|
@@ -70208,32 +70346,67 @@ const startTime = null;
|
|
|
70208
70346
|
},
|
|
70209
70347
|
data() {
|
|
70210
70348
|
return {
|
|
70349
|
+
lastTimeUpdate: null,
|
|
70350
|
+
// 上次更新时间
|
|
70211
70351
|
chatId: generateUuid(),
|
|
70352
|
+
// 唯一标识当前聊天会话
|
|
70212
70353
|
audioSrc: AUDIO_URL,
|
|
70354
|
+
// 音频文件URL
|
|
70213
70355
|
inputMessage: '',
|
|
70356
|
+
// 当前输入的消息
|
|
70214
70357
|
visible: false,
|
|
70358
|
+
// 是否显示聊天窗口
|
|
70215
70359
|
messages: [],
|
|
70360
|
+
// 聊天消息数组
|
|
70216
70361
|
messageLoading: true,
|
|
70362
|
+
// 是否正在加载消息
|
|
70217
70363
|
robotStatus: 'leaving',
|
|
70364
|
+
// 机器人状态 entering: 进入中, waiting: 等待中, speaking: 说话中, leaving: 离开中
|
|
70218
70365
|
avaterStatus: 'normal',
|
|
70366
|
+
// 头像状态 normal: 正常, thinking: 思考中
|
|
70219
70367
|
currentMessage: null,
|
|
70368
|
+
// 当前正在处理的消息
|
|
70220
70369
|
thinkStatus: true,
|
|
70370
|
+
// 是否思考中
|
|
70221
70371
|
jumpedTimePoints: new Set(),
|
|
70372
|
+
// 已跳转的时间点集合
|
|
70222
70373
|
SAMPLE_RATE,
|
|
70374
|
+
// 采样率 16000Hz
|
|
70223
70375
|
FRAME_SIZE,
|
|
70224
|
-
|
|
70225
|
-
// 检查性能使用
|
|
70376
|
+
// 帧大小 512
|
|
70226
70377
|
dragThreshold: 5,
|
|
70227
70378
|
// 拖拽阈值
|
|
70228
70379
|
isDragging: false,
|
|
70380
|
+
// 是否正在拖拽
|
|
70229
70381
|
dragStartX: 0,
|
|
70382
|
+
// 拖拽开始时的X坐标
|
|
70230
70383
|
dragStartY: 0,
|
|
70384
|
+
// 拖拽开始时的Y坐标
|
|
70231
70385
|
currentX: 10,
|
|
70386
|
+
// 当前X坐标
|
|
70232
70387
|
currentY: 20,
|
|
70388
|
+
// 当前Y坐标
|
|
70233
70389
|
initialX: 10,
|
|
70390
|
+
// 初始X坐标
|
|
70234
70391
|
initialY: 20,
|
|
70392
|
+
// 初始Y坐标
|
|
70235
70393
|
hasMoved: false,
|
|
70236
|
-
|
|
70394
|
+
// 是否已移动
|
|
70395
|
+
timeJumpPoints: null,
|
|
70396
|
+
// 跳转
|
|
70397
|
+
subTitlePoints: null,
|
|
70398
|
+
// 字幕
|
|
70399
|
+
currentJumpPoints: [],
|
|
70400
|
+
// 当前跳转点数组
|
|
70401
|
+
currentSubtitles: [],
|
|
70402
|
+
// 当前字幕数组
|
|
70403
|
+
currentSubtitle: '',
|
|
70404
|
+
// 当前字幕,
|
|
70405
|
+
jumpIndex: 0,
|
|
70406
|
+
// 当前跳转索引
|
|
70407
|
+
subtitleIndex: 0,
|
|
70408
|
+
// 当前字幕索引
|
|
70409
|
+
isTourRunning: false // 是否正在导览
|
|
70237
70410
|
};
|
|
70238
70411
|
},
|
|
70239
70412
|
computed: {
|
|
@@ -70251,12 +70424,12 @@ const startTime = null;
|
|
|
70251
70424
|
};
|
|
70252
70425
|
}
|
|
70253
70426
|
},
|
|
70254
|
-
mounted() {
|
|
70427
|
+
async mounted() {
|
|
70255
70428
|
this.initWebSocket();
|
|
70256
70429
|
if (this.appendToBody) {
|
|
70257
70430
|
this.appendToBodyHandler();
|
|
70258
70431
|
}
|
|
70259
|
-
this.fetchTimeJumpPoints();
|
|
70432
|
+
await Promise.all([this.fetchTimeJumpPoints(), this.fetchSubTitlePoints()]);
|
|
70260
70433
|
this.$nextTick(() => {
|
|
70261
70434
|
const chatEl = this.$el;
|
|
70262
70435
|
const style = window.getComputedStyle(chatEl);
|
|
@@ -70276,16 +70449,27 @@ const startTime = null;
|
|
|
70276
70449
|
document.removeEventListener('mouseup', this.stopDrag);
|
|
70277
70450
|
},
|
|
70278
70451
|
methods: {
|
|
70452
|
+
initGuide() {
|
|
70453
|
+
this.jumpIndex = 0;
|
|
70454
|
+
this.subtitleIndex = 0;
|
|
70455
|
+
this.jumpedTimePoints.clear();
|
|
70456
|
+
this.setRobotStatus(ROBOT_STATUS.LEAVING);
|
|
70457
|
+
this.setAvatarStatus(AVATAR_STATUS.NORMAL);
|
|
70458
|
+
},
|
|
70459
|
+
setRobotStatus(status) {
|
|
70460
|
+
this.robotStatus = status || ROBOT_STATUS.LEAVING;
|
|
70461
|
+
},
|
|
70462
|
+
setAvatarStatus(status) {
|
|
70463
|
+
this.avaterStatus = status || AVATAR_STATUS.NORMAL;
|
|
70464
|
+
},
|
|
70279
70465
|
toggleWindow() {
|
|
70280
|
-
if (this.avaterStatus === 'thinking') return;
|
|
70281
70466
|
this.visible = !this.visible;
|
|
70282
70467
|
if (this.visible) {
|
|
70283
70468
|
this.currentX = this.initialX;
|
|
70284
70469
|
this.currentY = this.initialY;
|
|
70285
70470
|
}
|
|
70286
70471
|
},
|
|
70287
|
-
startDrag() {
|
|
70288
|
-
console.log('startDrag');
|
|
70472
|
+
startDrag(event) {
|
|
70289
70473
|
if (this.robotStatus !== 'leaving' && this.visible) return;
|
|
70290
70474
|
this.isDragging = true;
|
|
70291
70475
|
this.hasMoved = false;
|
|
@@ -70337,9 +70521,18 @@ const startTime = null;
|
|
|
70337
70521
|
document.removeEventListener('mousemove', this.onDrag);
|
|
70338
70522
|
document.removeEventListener('mouseup', this.stopDrag);
|
|
70339
70523
|
if (!this.hasMoved) {
|
|
70340
|
-
this.
|
|
70524
|
+
this.handleClick();
|
|
70341
70525
|
}
|
|
70342
70526
|
},
|
|
70527
|
+
handleClick() {
|
|
70528
|
+
if (this.avaterStatus === 'thinking') return;
|
|
70529
|
+
if (this.isInBlacklist()) return;
|
|
70530
|
+
this.toggleWindow();
|
|
70531
|
+
},
|
|
70532
|
+
isInBlacklist() {
|
|
70533
|
+
const tenantId = getCookie('bonyear-tenantId');
|
|
70534
|
+
return tenantId && BLACKLIST.includes(tenantId);
|
|
70535
|
+
},
|
|
70343
70536
|
handleThinkingClick() {
|
|
70344
70537
|
this.thinkStatus = !this.thinkStatus;
|
|
70345
70538
|
},
|
|
@@ -70355,54 +70548,274 @@ const startTime = null;
|
|
|
70355
70548
|
},
|
|
70356
70549
|
async fetchTimeJumpPoints() {
|
|
70357
70550
|
try {
|
|
70358
|
-
const res = await fetch(TIME_JUMP_POINTS_URL);
|
|
70551
|
+
const res = await fetch(TIME_JUMP_POINTS_URL + '?timestamp=' + Date.now());
|
|
70359
70552
|
const data = await res.json();
|
|
70360
|
-
this.timeJumpPoints =
|
|
70361
|
-
console.log('时间跳转点加载完成:', this.timeJumpPoints);
|
|
70553
|
+
this.timeJumpPoints = data;
|
|
70362
70554
|
} catch (err) {
|
|
70363
70555
|
console.error('获取时间跳转点失败:', err);
|
|
70364
|
-
this.timeJumpPoints =
|
|
70556
|
+
this.timeJumpPoints = null;
|
|
70557
|
+
}
|
|
70558
|
+
},
|
|
70559
|
+
async fetchSubTitlePoints() {
|
|
70560
|
+
try {
|
|
70561
|
+
const res = await fetch(SUBTITLE_POINTS_URL + '?timestamp=' + Date.now());
|
|
70562
|
+
const data = await res.json();
|
|
70563
|
+
this.subTitlePoints = data;
|
|
70564
|
+
} catch (err) {
|
|
70565
|
+
console.error('获取字幕跳转点失败');
|
|
70566
|
+
this.subTitlePoints = null;
|
|
70567
|
+
}
|
|
70568
|
+
},
|
|
70569
|
+
normalizeCommand(cmd = '') {
|
|
70570
|
+
return cmd.trim() // 去掉 \n \r 空格
|
|
70571
|
+
.replace(/[\u200B-\u200D]/g, '') // 去零宽字符
|
|
70572
|
+
.replace(/[。!?,、,.!?]/g, ''); // 去标点
|
|
70573
|
+
},
|
|
70574
|
+
// 分析音频语音指令
|
|
70575
|
+
analyzeVoiceCommand(name) {
|
|
70576
|
+
console.log('===== analyzeVoiceCommand =====');
|
|
70577
|
+
console.log('typeof name:', typeof name);
|
|
70578
|
+
console.log('name === "结束导览":', name === '结束导览');
|
|
70579
|
+
console.log('Object.prototype.toString:', Object.prototype.toString.call(name));
|
|
70580
|
+
const normalized = this.normalizeCommand(name);
|
|
70581
|
+
const commandMap = {
|
|
70582
|
+
'开始导览': this.startTheTour,
|
|
70583
|
+
'开始区域看板导览': this.startAreaBoardTour,
|
|
70584
|
+
'开始企业应用导览': this.startEnterpriseApplicationTour,
|
|
70585
|
+
'开始区域应用导览': this.startRegionalApplicationTour,
|
|
70586
|
+
'暂停导览': this.pauseTheTour,
|
|
70587
|
+
'继续导览': this.resumeTheTour,
|
|
70588
|
+
'结束导览': this.offTheTour,
|
|
70589
|
+
'返回首页': this.returnToHome,
|
|
70590
|
+
'未知指令': this.offTheTour
|
|
70591
|
+
};
|
|
70592
|
+
const handler = commandMap[normalized];
|
|
70593
|
+
if (!handler) {
|
|
70594
|
+
console.warn('未定义的指令:', name);
|
|
70595
|
+
return;
|
|
70596
|
+
}
|
|
70597
|
+
handler();
|
|
70598
|
+
},
|
|
70599
|
+
// 启动导览
|
|
70600
|
+
async onTheTour() {
|
|
70601
|
+
if (this.isTourRunning) return;
|
|
70602
|
+
this.isTourRunning = true;
|
|
70603
|
+
const audio = this.$refs.audioPlayer;
|
|
70604
|
+
if (!audio) return;
|
|
70605
|
+
this.setRobotStatus(ROBOT_STATUS.ENTERING);
|
|
70606
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
70607
|
+
this.setRobotStatus(ROBOT_STATUS.SPEAKING);
|
|
70608
|
+
try {
|
|
70609
|
+
await audio.play();
|
|
70610
|
+
} catch (e) {
|
|
70611
|
+
console.error('播放音频失败:', e);
|
|
70612
|
+
} finally {
|
|
70613
|
+
this.isTourRunning = false;
|
|
70614
|
+
}
|
|
70615
|
+
},
|
|
70616
|
+
// 暂停导览
|
|
70617
|
+
pauseTheTour() {
|
|
70618
|
+
this.pause();
|
|
70619
|
+
this.setRobotStatus(ROBOT_STATUS.WAITING);
|
|
70620
|
+
},
|
|
70621
|
+
// 继续导览
|
|
70622
|
+
resumeTheTour() {
|
|
70623
|
+
this.play();
|
|
70624
|
+
this.setRobotStatus(ROBOT_STATUS.SPEAKING);
|
|
70625
|
+
},
|
|
70626
|
+
// 结束导览
|
|
70627
|
+
offTheTour() {
|
|
70628
|
+
this.stop();
|
|
70629
|
+
this.currentSubtitle = '';
|
|
70630
|
+
this.setRobotStatus(ROBOT_STATUS.LEAVING);
|
|
70631
|
+
this.setAvatarStatus(AVATAR_STATUS.NORMAL);
|
|
70632
|
+
},
|
|
70633
|
+
// 返回首页
|
|
70634
|
+
returnToHome() {
|
|
70635
|
+
this.setRobotStatus(ROBOT_STATUS.LEAVING);
|
|
70636
|
+
this.setAvatarStatus(AVATAR_STATUS.NORMAL);
|
|
70637
|
+
this.$appOptions.router.push({
|
|
70638
|
+
path: '/'
|
|
70639
|
+
});
|
|
70640
|
+
},
|
|
70641
|
+
initJumpPoints(name) {
|
|
70642
|
+
// 初始化跳转点
|
|
70643
|
+
if (name) {
|
|
70644
|
+
this.currentJumpPoints = this.timeJumpPoints[name] || [];
|
|
70645
|
+
console.log('currentJumpPoints:', this.currentJumpPoints);
|
|
70646
|
+
} else {
|
|
70647
|
+
this.currentJumpPoints = this.timeJumpPoints;
|
|
70648
|
+
}
|
|
70649
|
+
},
|
|
70650
|
+
initSubtitles(name) {
|
|
70651
|
+
console.log('name:', name);
|
|
70652
|
+
if (name) {
|
|
70653
|
+
this.currentSubtitles = this.subTitlePoints[name] || [];
|
|
70654
|
+
} else {
|
|
70655
|
+
this.currentSubtitles = this.subTitlePoints;
|
|
70656
|
+
}
|
|
70657
|
+
},
|
|
70658
|
+
// 开始导览
|
|
70659
|
+
async startTheTour() {
|
|
70660
|
+
await this.setAudio(COLLECTION); // 重置音频源
|
|
70661
|
+
|
|
70662
|
+
// 重置指针
|
|
70663
|
+
this.initGuide();
|
|
70664
|
+
// 重置跳转点指针
|
|
70665
|
+
this.initJumpPoints('开始导览');
|
|
70666
|
+
// 重置字幕指针
|
|
70667
|
+
this.initSubtitles('开始导览');
|
|
70668
|
+
await this.onTheTour();
|
|
70669
|
+
},
|
|
70670
|
+
// 开始区域看板导览
|
|
70671
|
+
async startAreaBoardTour() {
|
|
70672
|
+
// 重置audio
|
|
70673
|
+
await this.setAudio(AREA_BOARD);
|
|
70674
|
+
|
|
70675
|
+
// 重置指针
|
|
70676
|
+
this.initGuide();
|
|
70677
|
+
// 重置跳转点指针
|
|
70678
|
+
this.initJumpPoints('开始区域看板导览');
|
|
70679
|
+
// 重置字幕指针
|
|
70680
|
+
this.initSubtitles('开始区域看板导览');
|
|
70681
|
+
await this.onTheTour();
|
|
70682
|
+
},
|
|
70683
|
+
// 开始企业应用导览
|
|
70684
|
+
async startEnterpriseApplicationTour() {
|
|
70685
|
+
await this.setAudio(ENTERPRISE_APPLICATION);
|
|
70686
|
+
|
|
70687
|
+
// 重置指针
|
|
70688
|
+
this.initGuide();
|
|
70689
|
+
// 重置跳转点指针
|
|
70690
|
+
this.initJumpPoints('开始企业应用导览');
|
|
70691
|
+
// 重置字幕指针
|
|
70692
|
+
this.initSubtitles('开始企业应用导览');
|
|
70693
|
+
await this.onTheTour();
|
|
70694
|
+
},
|
|
70695
|
+
// 开始区域应用导览
|
|
70696
|
+
async startRegionalApplicationTour() {
|
|
70697
|
+
await this.setAudio(REGIONAL_APPLICATION);
|
|
70698
|
+
|
|
70699
|
+
// 重置指针
|
|
70700
|
+
this.initGuide();
|
|
70701
|
+
// 重置跳转点指针
|
|
70702
|
+
this.initJumpPoints('开始区域应用导览');
|
|
70703
|
+
// 重置字幕指针
|
|
70704
|
+
this.initSubtitles('开始区域应用导览');
|
|
70705
|
+
await this.onTheTour();
|
|
70706
|
+
},
|
|
70707
|
+
// 分析音频命令
|
|
70708
|
+
analyzeAudioCommand(command) {
|
|
70709
|
+
console.log('分析音频命令:', command);
|
|
70710
|
+
if (command === 'C5') {
|
|
70711
|
+
this.setRobotStatus(ROBOT_STATUS.ENTERING);
|
|
70712
|
+
setTimeout(() => {
|
|
70713
|
+
this.setRobotStatus(ROBOT_STATUS.SPEAKING);
|
|
70714
|
+
this.play();
|
|
70715
|
+
}, 3000);
|
|
70716
|
+
}
|
|
70717
|
+
if (command === 'C8') {
|
|
70718
|
+
this.setRobotStatus(ROBOT_STATUS.SPEAKING);
|
|
70719
|
+
this.play();
|
|
70720
|
+
}
|
|
70721
|
+
if (command === 'C7') {
|
|
70722
|
+
this.setRobotStatus(ROBOT_STATUS.WAITING);
|
|
70723
|
+
this.pause();
|
|
70724
|
+
}
|
|
70725
|
+
if (command === 'C6') {
|
|
70726
|
+
this.setRobotStatus(ROBOT_STATUS.LEAVING);
|
|
70727
|
+
this.stop();
|
|
70365
70728
|
}
|
|
70366
70729
|
},
|
|
70730
|
+
// 处理点击跳转时间
|
|
70731
|
+
handleJumpPoint(currentTime) {
|
|
70732
|
+
console.log('jumpIndex:', this.jumpIndex);
|
|
70733
|
+
const point = this.currentJumpPoints[this.jumpIndex];
|
|
70734
|
+
if (!point) return;
|
|
70735
|
+
console.log('currentTime:', currentTime);
|
|
70736
|
+
console.log('point.time:', point.time);
|
|
70737
|
+
if (currentTime >= point.time && !this.jumpedTimePoints.has(point.time)) {
|
|
70738
|
+
this.jumpedTimePoints.add(point.time);
|
|
70739
|
+
this.jumpIndex++;
|
|
70740
|
+
this.$appOptions.store.dispatch('tags/addTagview', {
|
|
70741
|
+
path: point.url,
|
|
70742
|
+
fullPath: point.url,
|
|
70743
|
+
label: point.title,
|
|
70744
|
+
name: point.title,
|
|
70745
|
+
meta: {
|
|
70746
|
+
title: point.title
|
|
70747
|
+
},
|
|
70748
|
+
query: {},
|
|
70749
|
+
params: {}
|
|
70750
|
+
});
|
|
70751
|
+
this.$appOptions.router.push({
|
|
70752
|
+
path: point.url
|
|
70753
|
+
});
|
|
70754
|
+
}
|
|
70755
|
+
},
|
|
70756
|
+
// 处理播放字幕
|
|
70757
|
+
handlePlaySubtitles(currentTime) {
|
|
70758
|
+
const subtitle = this.currentSubtitles[this.subtitleIndex];
|
|
70759
|
+
if (!subtitle) return;
|
|
70760
|
+
if (currentTime < subtitle.start) return;
|
|
70761
|
+
|
|
70762
|
+
// 正在播放当前字幕
|
|
70763
|
+
if (currentTime >= subtitle.start && currentTime <= subtitle.end) {
|
|
70764
|
+
if (this.currentSubtitle !== subtitle.text) {
|
|
70765
|
+
this.currentSubtitle = subtitle.text;
|
|
70766
|
+
}
|
|
70767
|
+
return;
|
|
70768
|
+
}
|
|
70769
|
+
|
|
70770
|
+
// 超过当前字幕,推进游标
|
|
70771
|
+
if (currentTime > subtitle.end) {
|
|
70772
|
+
this.subtitleIndex++;
|
|
70773
|
+
this.currentSubtitle = '';
|
|
70774
|
+
}
|
|
70775
|
+
},
|
|
70776
|
+
async setAudio(src) {
|
|
70777
|
+
return new Promise((resolve, reject) => {
|
|
70778
|
+
const audio = this.$refs.audioPlayer;
|
|
70779
|
+
if (!audio) return reject('未找到音频元素');
|
|
70780
|
+
audio.pause();
|
|
70781
|
+
audio.currentTime = 0;
|
|
70782
|
+
|
|
70783
|
+
// ✅ 用响应式数据
|
|
70784
|
+
this.audioSrc = src;
|
|
70785
|
+
this.$nextTick(() => {
|
|
70786
|
+
audio.load();
|
|
70787
|
+
const onCanPlay = () => {
|
|
70788
|
+
audio.removeEventListener('canplay', onCanPlay);
|
|
70789
|
+
resolve();
|
|
70790
|
+
};
|
|
70791
|
+
audio.addEventListener('canplay', onCanPlay);
|
|
70792
|
+
});
|
|
70793
|
+
});
|
|
70794
|
+
},
|
|
70367
70795
|
// 音频时间更新处理
|
|
70368
70796
|
onTimeUpdate() {
|
|
70797
|
+
const now = performance.now();
|
|
70798
|
+
if (this.lastTimeUpdate && now - this.lastTimeUpdate < 200) return;
|
|
70799
|
+
this.lastTimeUpdate = now;
|
|
70369
70800
|
const audio = this.$refs.audioPlayer;
|
|
70370
70801
|
const currentTime = audio.currentTime;
|
|
70371
|
-
|
|
70372
|
-
this.
|
|
70373
|
-
if (currentTime >= point.time && currentTime < point.time + 1 && !this.jumpedTimePoints.has(point.time)) {
|
|
70374
|
-
console.log('触发跳转:', point.url);
|
|
70375
|
-
this.jumpedTimePoints.add(point.time);
|
|
70376
|
-
this.$appOptions.store.dispatch('tags/addTagview', {
|
|
70377
|
-
path: point.url,
|
|
70378
|
-
fullPath: point.url,
|
|
70379
|
-
label: point.title,
|
|
70380
|
-
name: point.title,
|
|
70381
|
-
meta: {
|
|
70382
|
-
title: point.title
|
|
70383
|
-
},
|
|
70384
|
-
query: {},
|
|
70385
|
-
params: {}
|
|
70386
|
-
});
|
|
70387
|
-
this.$appOptions.router.push({
|
|
70388
|
-
path: point.url
|
|
70389
|
-
});
|
|
70390
|
-
}
|
|
70391
|
-
});
|
|
70802
|
+
this.handleJumpPoint(currentTime);
|
|
70803
|
+
this.handlePlaySubtitles(currentTime);
|
|
70392
70804
|
},
|
|
70393
70805
|
onAudioEnded() {
|
|
70394
|
-
this.
|
|
70395
|
-
this.
|
|
70806
|
+
this.currentSubtitle = '';
|
|
70807
|
+
this.setRobotStatus(ROBOT_STATUS.LEAVING);
|
|
70808
|
+
this.setAvatarStatus(AVATAR_STATUS.NORMAL);
|
|
70396
70809
|
this.jumpedTimePoints.clear();
|
|
70397
70810
|
}
|
|
70398
70811
|
}
|
|
70399
70812
|
});
|
|
70400
70813
|
;// ./components/ChatWindow.vue?vue&type=script&lang=js
|
|
70401
70814
|
/* harmony default export */ var components_ChatWindowvue_type_script_lang_js = (ChatWindowvue_type_script_lang_js);
|
|
70402
|
-
;// ./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=
|
|
70815
|
+
;// ./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=959a9f66&prod&scoped=true&lang=css
|
|
70403
70816
|
// extracted by mini-css-extract-plugin
|
|
70404
70817
|
|
|
70405
|
-
;// ./components/ChatWindow.vue?vue&type=style&index=0&id=
|
|
70818
|
+
;// ./components/ChatWindow.vue?vue&type=style&index=0&id=959a9f66&prod&scoped=true&lang=css
|
|
70406
70819
|
|
|
70407
70820
|
;// ./components/ChatWindow.vue
|
|
70408
70821
|
|
|
@@ -70419,7 +70832,7 @@ var ChatWindow_component = normalizeComponent(
|
|
|
70419
70832
|
staticRenderFns,
|
|
70420
70833
|
false,
|
|
70421
70834
|
null,
|
|
70422
|
-
"
|
|
70835
|
+
"959a9f66",
|
|
70423
70836
|
null
|
|
70424
70837
|
|
|
70425
70838
|
)
|