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