yumoqing 2b921a209d sync: local modifications to integrated_crm_app
- Updated app/integrated_crm_app.py, build.sh, conf/config.json
- Added config.ini, schema.sql, send_email.py, test_db_conn.py
- Added full wwwroot/ with bricks framework, all module frontends, login/main UI
2026-04-28 18:54:07 +08:00

134 lines
3.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var bricks = window.bricks || {};
bricks.ContinueAudioPlayer = class extends bricks.VBox {
constructor(options) {
super(options);
this.ws_url = options.ws_url;
this.options = options || {};
this.audioContext = null;
this.gainNode = null;
this.nextStartTime = 0;
this.started = false;
this.muted = false;
this.volume = 1.0;
this.initAudioContext();
}
initAudioContext() {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
this.gainNode = this.audioContext.createGain();
this.gainNode.gain.value = this.volume;
this.gainNode.connect(this.audioContext.destination);
this.nextStartTime = this.audioContext.currentTime;
this.started = true;
}
base64ToArrayBuffer(base64) {
const binaryStr = atob(base64);
const len = binaryStr.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryStr.charCodeAt(i);
}
return bytes.buffer;
}
handleAudioTrack(arrayBuffer) {
this.audioContext.decodeAudioData(arrayBuffer).then(decodedBuffer => {
const source = this.audioContext.createBufferSource();
source.buffer = decodedBuffer;
source.connect(this.gainNode);
const startTime = Math.max(this.audioContext.currentTime, this.nextStartTime);
source.start(startTime);
this.nextStartTime = startTime + decodedBuffer.duration;
if (typeof this.options.onStart === 'function') {
this.options.onStart();
}
source.onended = () => {
if (typeof this.options.onEnd === 'function') {
this.options.onEnd();
}
};
}).catch(err => {
console.error("Error decoding audio data:", err);
});
}
/**
* ⏸ 暂停播放
*/
pauseAudio() {
if (this.audioContext && this.audioContext.state === 'running') {
this.audioContext.suspend().then(() => {
if (typeof this.options.onPause === 'function') {
this.options.onPause();
}
});
}
}
/**
* ▶️ 恢复播放
*/
resumeAudio() {
if (this.audioContext && this.audioContext.state === 'suspended') {
this.audioContext.resume().then(() => {
if (typeof this.options.onResume === 'function') {
this.options.onResume();
}
});
}
}
/**
* 🔁 重新开始播放
*/
restart() {
console.log("Restarting audio playback...");
if (this.audioContext && this.audioContext.state !== 'closed') {
this.audioContext.close().then(() => {
this.initAudioContext();
});
} else {
this.initAudioContext();
}
}
/**
* 🔊 设置音量0.0 - 1.0
*/
setVolume(value) {
this.volume = Math.max(0, Math.min(1, value));
if (this.gainNode) {
this.gainNode.gain.value = this.muted ? 0 : this.volume;
}
this.emit('onVolumeChange', this.volume);
}
/**
* 🔇 切换静音
*/
toggleMute() {
this.muted = !this.muted;
this.gainNode.gain.value = this.muted ? 0 : this.volume;
this.emit('onVolumeChange', this.muted ? 0 : this.volume);
}
/**
* 🧩 触发事件回调
*/
emit(eventName, ...args) {
if (typeof this.options[eventName] === 'function') {
this.options[eventName](...args);
}
}
}
bricks.Factory.register('ContinueAudioPlayer', bricks.ContinueAudioPlayer);