🐞 fix: 进一步的检查与校准

This commit is contained in:
IGCrystal
2025-06-17 12:22:00 +08:00
parent 7e4c89b0cb
commit 38eae1d1ee
16 changed files with 75 additions and 48 deletions
@@ -3,12 +3,12 @@
<template v-slot:activator="{ props: activatorProps }">
<v-btn
v-bind="activatorProps"
:variant="props.variant === 'header' ? 'flat' : 'text'"
:color="props.variant === 'header' ? 'var(--v-theme-surface)' : undefined"
:rounded="props.variant === 'header' ? 'sm' : undefined"
:variant="(props.variant === 'header' || props.variant === 'chatbox') ? 'flat' : 'text'"
:color="(props.variant === 'header' || props.variant === 'chatbox') ? 'var(--v-theme-surface)' : undefined"
:rounded="(props.variant === 'header' || props.variant === 'chatbox') ? 'sm' : undefined"
icon
size="small"
:class="['language-switcher', `language-switcher--${props.variant}`, props.variant === 'header' ? 'action-btn' : '']"
:class="['language-switcher', `language-switcher--${props.variant}`, (props.variant === 'header' || props.variant === 'chatbox') ? 'action-btn' : '']"
>
<v-icon
size="18"
@@ -51,7 +51,7 @@ import type { Locale } from '@/i18n/types'
// 定义props来控制样式变体
const props = withDefaults(defineProps<{
variant?: 'default' | 'header'
variant?: 'default' | 'header' | 'chatbox'
}>(), {
variant: 'default'
})
@@ -101,6 +101,11 @@ const changeLanguage = async (langCode: string) => {
/* action-btn类已经处理了margin-right: 6px,不需要额外样式 */
}
/* ChatBox变体样式 - 与Header保持一致 */
.language-switcher--chatbox {
/* 继承action-btn样式,与工具栏主题按钮保持一致 */
}
/* 深色模式下的悬停效果(仅对default变体) */
:deep(.v-theme--PurpleThemeDark) .language-switcher--default:hover {
background: rgba(114, 46, 209, 0.12) !important;
+13 -10
View File
@@ -7,11 +7,11 @@
<div class="logo-text">
<h2
:style="{color: useCustomizerStore().uiTheme === 'PurpleTheme' ? '#5e35b1' : '#d7c5fa'}"
v-html="formatTitle(title)"
v-html="formatTitle(title || t('core.header.logoTitle'))"
></h2>
<!-- 父子组件传递css变量可能会出错暂时使用十六进制颜色值 -->
<h4 :style="{color: useCustomizerStore().uiTheme === 'PurpleTheme' ? '#000000aa' : '#ffffffcc'}"
class="hint-text">{{ subtitle }}</h4>
class="hint-text">{{ subtitle || t('core.header.accountDialog.title') }}</h4>
</div>
</div>
</div>
@@ -19,23 +19,26 @@
<script setup lang="ts">
import { useCustomizerStore } from "@/stores/customizer";
import { useI18n } from '@/i18n/composables';
const { t } = useI18n();
const props = withDefaults(defineProps<{
title?: string;
subtitle?: string;
}>(), {
title: 'AstrBot 仪表盘',
subtitle: '欢迎使用'
title: '', // 默认为空,组件会使用翻译值
subtitle: ''
})
// 格式化标题,在小屏幕上允许在合适位置换行
// 智能格式化标题,在小屏幕上允许在合适位置换行
const formatTitle = (title: string) => {
if (title === 'AstrBot 仪表盘') {
return 'AstrBot<wbr> 仪表盘'
} else if (title === 'AstrBot Dashboard') {
return 'AstrBot<wbr> Dashboard'
// 如果标题包含 "AstrBot" 和其他文字,在它们之间添加换行机会
if (title.includes('AstrBot ') || title.includes('AstrBot')) {
// 处理 "AstrBot 仪表盘" 或 "AstrBot Dashboard" 等格式
return title.replace(/(AstrBot)\s+(.+)/, '$1<wbr> $2');
}
return title
return title;
}
</script>
@@ -26,6 +26,7 @@
"uninstall": "Uninstall",
"update": "Update",
"language": "Language",
"locale": "en-US",
"type": "Type",
"press": "Press",
"longPress": "Long press",
@@ -1,4 +1,5 @@
{
"logoTitle": "AstrBot Dashboard",
"version": {
"hasNewVersion": "AstrBot has a new version!",
"dashboardHasNewVersion": "WebUI has a new version!"
@@ -46,7 +46,8 @@
"searchButton": "Search",
"resultsTitle": "Search Results",
"noResults": "No relevant memory content found",
"similarity": "Relevance"
"similarity": "Relevance",
"noTextContent": "No text content"
},
"addMemory": {
"title": "Add Memory Data",
@@ -79,7 +80,8 @@
"metadataValue": "Value",
"loading": "Loading...",
"close": "Close",
"noValue": "None"
"noValue": "None",
"unknown": "Unknown"
},
"messages": {
"searchQueryRequired": "Please enter search keywords",
@@ -89,6 +91,7 @@
"addSuccess": "Memory data added successfully!",
"addError": "Failed to add memory data",
"factDetailsError": "Failed to get memory details",
"metadataParseError": "Unable to parse metadata"
"metadataParseError": "Unable to parse metadata",
"relationNoMemoryData": "This relation has no associated memory data"
}
}
@@ -26,6 +26,7 @@
"uninstall": "卸载",
"update": "更新",
"language": "语言",
"locale": "zh-CN",
"type": "输入",
"press": "按",
"longPress": "长按",
@@ -1,4 +1,5 @@
{
"logoTitle": "AstrBot 仪表盘",
"version": {
"hasNewVersion": "AstrBot 有新版本!",
"dashboardHasNewVersion": "WebUI 有新版本!"
@@ -46,7 +46,8 @@
"searchButton": "搜索",
"resultsTitle": "搜索结果",
"noResults": "未找到相关记忆内容",
"similarity": "相关度"
"similarity": "相关度",
"noTextContent": "无文本内容"
},
"addMemory": {
"title": "添加记忆数据",
@@ -79,7 +80,8 @@
"metadataValue": "值",
"loading": "加载中...",
"close": "关闭",
"noValue": "无"
"noValue": "无",
"unknown": "未知"
},
"messages": {
"searchQueryRequired": "请输入搜索关键词",
@@ -89,6 +91,7 @@
"addSuccess": "记忆数据添加成功!",
"addError": "添加记忆数据失败",
"factDetailsError": "获取记忆详情失败",
"metadataParseError": "无法解析元数据"
"metadataParseError": "无法解析元数据",
"relationNoMemoryData": "该关系没有关联的记忆数据"
}
}
@@ -442,7 +442,7 @@ commonStore.getStartTime();
<v-card class="account-dialog">
<v-card-text class="py-6">
<div class="d-flex flex-column align-center mb-6">
<logo title="AstrBot 仪表盘" :subtitle="t('core.header.accountDialog.title')"></logo>
<logo :title="t('core.header.logoTitle')" :subtitle="t('core.header.accountDialog.title')"></logo>
</div>
<v-alert
v-if="accountWarning"
-1
View File
@@ -155,7 +155,6 @@ export const useCommonStore = defineStore({
return data;
})
.catch((err) => {
this.toast("获取插件市场数据失败: " + err, "error");
return Promise.reject(err);
});
},
+1 -1
View File
@@ -9,7 +9,7 @@ const customizer = useCustomizerStore();
<div
style="height: 100%; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<div id="container">
<ChatPage chatbox-mode="true"></ChatPage>
<ChatPage :chatbox-mode="true"></ChatPage>
</div>
</div>
</v-app>
+16 -6
View File
@@ -124,6 +124,12 @@
class="fullscreen-icon">mdi-fullscreen</v-icon>
</template>
</v-tooltip>
<!-- 语言切换按钮 -->
<v-tooltip :text="t('core.common.language')" v-if="chatboxMode">
<template v-slot:activator="{ props }">
<LanguageSwitcher variant="chatbox" />
</template>
</v-tooltip>
<!-- 主题切换按钮 -->
<v-tooltip :text="isDark ? tm('modes.lightMode') : tm('modes.darkMode')" v-if="chatboxMode">
<template v-slot:activator="{ props }">
@@ -286,6 +292,7 @@ import axios from 'axios';
import { marked } from 'marked';
import { useCustomizerStore } from '@/stores/customizer';
import { useI18n, useModuleI18n } from '@/i18n/composables';
import LanguageSwitcher from '@/components/shared/LanguageSwitcher.vue';
marked.setOptions({
breaks: true
@@ -294,6 +301,7 @@ marked.setOptions({
export default {
name: 'ChatPage',
components: {
LanguageSwitcher
},
props: {
chatboxMode: {
@@ -410,7 +418,7 @@ export default {
mounted() {
// Theme is now handled globally by the customizer store.
// 设置输入框标签
this.inputFieldLabel = this.tm('title');
this.inputFieldLabel = this.tm('input.chatPrompt');
this.startListeningEvent();
this.checkStatus();
this.getConversations();
@@ -637,7 +645,7 @@ export default {
type: 'bot',
message: `<audio controls class="audio-player">
<source src="${audioUrl}" type="audio/wav">
您的浏览器不支持音频播放。
${this.t('messages.errors.browser.audioNotSupported')}
</audio>`
}
this.messages.push(bot_resp);
@@ -690,12 +698,12 @@ export default {
};
this.mediaRecorder.start();
this.isRecording = true;
this.inputFieldLabel = this.tm('features.chat.input.recordingPrompt');
this.inputFieldLabel = this.tm('input.recordingPrompt');
},
async stopRecording() {
this.isRecording = false;
this.inputFieldLabel = this.tm('features.chat.input.chatPrompt');
this.inputFieldLabel = this.tm('input.chatPrompt');
this.mediaRecorder.stop();
this.mediaRecorder.onstop = async () => {
const audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
@@ -805,7 +813,7 @@ export default {
const audioUrl = await this.getMediaFile(audio);
message[i].message = `<audio controls class="audio-player">
<source src="${audioUrl}" type="audio/wav">
您的浏览器不支持音频播放。
${this.t('messages.errors.browser.audioNotSupported')}
</audio>`
}
if (message[i].image_url && message[i].image_url.length > 0) {
@@ -861,7 +869,9 @@ export default {
second: '2-digit',
hour12: false
};
return date.toLocaleString('zh-CN', options).replace(/\//g, '-').replace(/, /g, ' ');
// 使用当前语言环境的locale
const locale = this.t('core.common.locale') || 'zh-CN';
return date.toLocaleString(locale, options).replace(/\//g, '-').replace(/, /g, ' ');
},
deleteConversation(cid) {
+5 -5
View File
@@ -157,11 +157,11 @@ export default {
// 安全访问翻译的计算属性
messages() {
return {
loadError: this.tm('features.config.messages.loadError'),
saveSuccess: this.tm('features.config.messages.saveSuccess'),
saveError: this.tm('features.config.messages.saveError'),
configApplied: this.tm('features.config.messages.configApplied'),
configApplyError: this.tm('features.config.messages.configApplyError')
loadError: this.tm('messages.loadError'),
saveSuccess: this.tm('messages.saveSuccess'),
saveError: this.tm('messages.saveError'),
configApplied: this.tm('messages.configApplied'),
configApplyError: this.tm('messages.configApplyError')
};
}
},
+4 -4
View File
@@ -179,7 +179,7 @@ const checkUpdate = () => {
if (matchedPlugin) {
extension.online_version = matchedPlugin.version;
extension.has_update = extension.version !== matchedPlugin.version &&
matchedPlugin.version !== tm('features.extension.status.unknown');
matchedPlugin.version !== tm('status.unknown');
} else {
extension.has_update = false;
}
@@ -204,7 +204,7 @@ const uninstallExtension = async (extension_name) => {
};
const updateExtension = async (extension_name) => {
loadingDialog.title = tm('features.extension.status.loading');
loadingDialog.title = tm('status.loading');
loadingDialog.show = true;
try {
const res = await axios.post('/api/plugin/update', {
@@ -465,7 +465,7 @@ const newExtension = async () => {
return;
}
loading_.value = true;
loadingDialog.title = tm('features.extension.status.loading');
loadingDialog.title = tm('status.loading');
loadingDialog.show = true;
if (upload_file.value !== null) {
toast(tm('messages.installing'), "primary");
@@ -542,7 +542,7 @@ onMounted(async () => {
checkAlreadyInstalled();
checkUpdate();
} catch (err) {
console.error(tm('messages.getMarketDataFailed'), err);
toast(tm('messages.getMarketDataFailed') + " " + err, "error");
}
});
+6 -6
View File
@@ -177,11 +177,11 @@ export default {
// 安全访问翻译的计算属性
messages() {
return {
updateSuccess: this.tm('features.platform.messages.updateSuccess'),
addSuccess: this.tm('features.platform.messages.addSuccess'),
deleteSuccess: this.tm('features.platform.messages.deleteSuccess'),
statusUpdateSuccess: this.tm('features.platform.messages.statusUpdateSuccess'),
deleteConfirm: this.tm('features.platform.messages.deleteConfirm')
updateSuccess: this.tm('messages.updateSuccess'),
addSuccess: this.tm('messages.addSuccess'),
deleteSuccess: this.tm('messages.deleteSuccess'),
statusUpdateSuccess: this.tm('messages.statusUpdateSuccess'),
deleteConfirm: this.tm('messages.deleteConfirm')
};
}
},
@@ -277,7 +277,7 @@ export default {
},
deletePlatform(platform) {
if (confirm(`${this.messages.deleteConfirm} ${platform.id}?`)) {
if (confirm(`${this.messages.deleteConfirm} ${platform.id}?`)) {
axios.post('/api/config/platform/delete', { id: platform.id }).then((res) => {
this.getConfig();
this.$refs.wfr.check();
@@ -366,7 +366,7 @@ export default {
this.searchResults = Object.keys(data).map(doc_id => {
return {
doc_id: doc_id,
text: data[doc_id].text || '无文本内容',
text: data[doc_id].text || this.tm('search.noTextContent'),
score: data[doc_id].score || 0
};
});
@@ -596,7 +596,7 @@ export default {
// 格式化时间戳的辅助方法
formatTime(timestamp) {
if (!timestamp) return '未知';
if (!timestamp) return this.tm('factDialog.unknown');
try {
return new Date(timestamp).toLocaleString();
} catch (e) {
@@ -709,7 +709,7 @@ export default {
this.selectedEdgeFactId = factId;
this.getFactDetails(factId);
} else {
this.$toast.info('该关系没有关联的记忆数据');
this.$toast.info(this.tm('messages.relationNoMemoryData'));
}
});