Xin Zhang
[fix]: update config modal layout.
20896dc
raw
history blame
10.1 kB
<script setup lang="ts">
import router from "@/router.ts";
import { useSettingsStore } from "@/stores/config.ts";
import { onMounted, ref, reactive, computed, h } from "vue";
import { Modal } from 'ant-design-vue';
import { SettingTwoTone } from "@ant-design/icons-vue";
import axios from "axios";
const base_url = axios.defaults.baseURL
const settingsStore = useSettingsStore()
import setting from "@/assets/setting.png"
onMounted(async () => {
await fetchASRLanguages();
await fetchTTSRoles();
});
const chatAction = async () => {
const state = await startAudioChat();
if (!state) {
console.error('Failed to start audio chat system service');
Modal.error({
title: 'Error',
content: 'Failed to start audio chat system service',
});
return;
}
router.replace('/home')
}
const chatLoading = ref<boolean>(false);
const startAudioChat = async () => {
try {
chatLoading.value = true;
const response = await fetch(`${base_url}/system/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
enable_echo_cancellation: echoCancel.value
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('ASR Instance started successfully:', data);
return true;
} catch (error) {
console.error('Error starting ASR instance:', error);
return false;
} finally {
chatLoading.value = false;
}
}
const modelOpen = ref<boolean>(false);
const modalLoading = ref<boolean>(false);
const handleCancel = () => {
modelOpen.value = false;
};
const handleSubmit = async () => {
console.log('Selected Language:', language.value);
console.log('Selected Role:', role.value);
console.log('Echo Cancel:', echoCancel.value);
settingsStore.$state.language = language.value;
settingsStore.$state.role = role.value || '';
settingsStore.$state.echoCancel = echoCancel.value;
await pushConfig(settingsStore.$state.role);
};
const pushConfig = async (model_id: string) => {
try {
modalLoading.value = true;
const response = await fetch(`${base_url}/tts/models/load`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"model_id": model_id,
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Config pushed successfully:', data);
const response2 = await fetch(`${base_url}/asr/instance/create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"language": language.value,
})
});
if (!response2.ok) {
throw new Error(`HTTP error! status: ${response2.status}`);
}
const data2 = await response2.json();
console.log('ASR Language set successfully:', data2);
} catch (err) {
console.error('Error pushing config:', err);
Modal.error({
title: 'Error',
content: "Error config: " + JSON.stringify(err),
});
} finally {
modalLoading.value = false;
modelOpen.value = false;
}
console.log('Selected Language:', language.value);
console.log('Selected Role:', role.value);
}
const language = ref<string>(settingsStore.$state.language || 'zh');
const languages = reactive([]);
const languageOptions = {
'zh': 'Chinese',
'en': 'English',
'auto': 'Auto',
};
const role = ref<string>(settingsStore.$state.role || '');
const roles = reactive([])
const echoCancel = ref<boolean>(settingsStore.$state.echoCancel ?? true);
const radioStyle = reactive({
display: 'flex',
height: '36px',
lineHeight: '36px',
fontSize: '15px',
});
const filteredRoles = computed(() => {
const is_chinese = language.value == 'zh';
return roles.filter(ro => ro['is_chinese_voice'] == is_chinese);
});
const fetchTTSRoles = async () => {
try {
const response = await fetch(`${base_url}/tts/models`);
const data = await response.json()
if (data && data.models) {
// @ts-ignore
roles.splice(0, data.length, ...data.models)
console.log('Fetched TTS Roles:', roles);
if (data.current_model_id) {
role.value = data.current_model_id;
}
}
} catch (error) {
console.error('Error fetching TTS roles:', error);
}
};
const fetchASRLanguages = async () => {
try {
const response = await fetch(`${base_url}/asr/languages`);
const data = await response.json();
if (data && data.languages) {
// @ts-ignore
languages.splice(0, languages.length, ...data.languages);
console.log('Fetched ASR Languages:', data.languages);
if (data.current_asr_language) {
language.value = data.current_asr_language;
}
}
} catch (error) {
console.error('Error fetching ASR languages:', error);
}
};
const toggleSider = () => {
settingsStore.$patch({ sider_open: !settingsStore.$state.sider_open });
console.log('sider open: ', modelOpen.value);
};
</script>
<template>
<div class="welcome-wrapper">
<div class="content">
<div class="inner-content">
<div class="text-box">
<div class="title">
欢迎使用
</div>
<div class="sub-title">
点击下方按钮开始对话
</div>
</div>
<div class="btn-box">
<a-button @click="chatAction" block :loading="chatLoading" type="primary" size="large">
<span>开始对话</span>
</a-button>
</div>
</div>
</div>
<div class="actions">
<!-- <a-button type="text" @click="toggleSider">sider</a-button> -->
<a-button type="text" @click="modelOpen = true"
style="width:44px; height: 44px; margin-right:24px;margin-bottom: 24px;">
<template #icon>
<img :src="setting" width="28" height="28" alt="settings" />
</template>
</a-button>
</div>
<a-modal v-model:open="modelOpen" :title="null" :mask-closable="false" centered>
<template #footer>
<a-button key="back" @click="handleCancel">Cancel</a-button>
<a-button key="submit" type="primary" :loading="modalLoading" @click="handleSubmit">Submit</a-button>
</template>
<div class="languages">
<div class="echo-cancel-item">
<div style="display: flex; justify-content: space-between; align-items: center;">
<p style="margin: 0;">Enable Echo Cancellation:</p>
<a-switch v-model:checked="echoCancel" />
</div>
</div>
</div>
<div class="languages">
<div class="language-item">
<p>Select Language:</p>
<a-select v-model:value="language" style="width: 100%;">
<a-select-option v-for="lan in languages" :value="lan" :key="lan">
{{ languageOptions[lan] }}
</a-select-option>
</a-select>
</div>
</div>
<div class="languages">
<div class="role-item">
<p>Select voice Role:</p>
<a-radio-group size="large" v-model:value="role">
<a-radio v-for="r in filteredRoles" :style="radioStyle" :value="r['id']" :key="r['id']">
{{ r['character_name'] }}
</a-radio>
</a-radio-group>
</div>
</div>
</a-modal>
</div>
</template>
<style lang="scss" scoped>
.languages {
margin-top: 40px;
margin-bottom: 8px;
p {
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
}
}
.welcome-wrapper {
width: 100%;
height: 100%;
background-image: url('@/assets/bg.png');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
background-position: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
color: #fff;
.content {
width: 100%;
height: 80vh;
display: flex;
flex-direction: column;
justify-content: space-around;
margin-top: 64px;
.inner-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 20px;
.text-box {
color: #000;
margin-bottom: 36px;
.title {
font-size: 24px;
font-weight: 600;
margin-bottom: 24px;
}
.sub-title {
font-size: 15px;
margin-top: 10px;
}
}
.btn-box {
width: 224px;
height: 80px;
}
}
}
.actions {
width: 100%;;
height: 64px;
display: flex;
justify-content: flex-end;
}
}
</style>