Parcourir la source

添加了对话页面的国际化

kagg886 il y a 1 mois
Parent
commit
6e3cab5c57
2 fichiers modifiés avec 77 ajouts et 66 suppressions
  1. 10 3
      src/i18n/index.ts
  2. 67 63
      src/views/assistant/index.vue

+ 10 - 3
src/i18n/index.ts

@@ -46,6 +46,10 @@ import pagesDateCenterZhcn from './pages/dateCenter/zh-cn';
 import pagesDateCenterEn from './pages/dateCenter/en';
 import pagesDateCenterZhtw from './pages/dateCenter/zh-tw';
 
+import pagesAssistantZhcn from './pages/assistant/zh-cn';
+import pagesAssistantEn from './pages/assistant/en';
+import pagesAssistantZhtw from './pages/assistant/zh-tw';
+
 
 // 定义语言国际化内容
 /**
@@ -65,7 +69,8 @@ const messages = {
 			iotCard: pagesIotcardZhcn,
 			projects: pagesProjectsZhcn,
 			property: pagesPropertyZhcn,
-			dateCenter: pagesDateCenterZhcn
+			dateCenter: pagesDateCenterZhcn,
+			assistant: pagesAssistantZhcn
 		}
 	},
 	[enLocale.name]: {
@@ -79,7 +84,8 @@ const messages = {
 			iotCard: pagesIotcardEn,
 			projects: pagesProjectsEn,
 			property: pagesPropertyEn,
-			dateCenter: pagesDateCenterEn
+			dateCenter: pagesDateCenterEn,
+			assistant: pagesAssistantEn
 		},	
 	},
 	[zhtwLocale.name]: {
@@ -93,7 +99,8 @@ const messages = {
 			iotCard: pagesIotcardZhtw,
 			projects: pagesProjectsZhtw,
 			property: pagesPropertyZhtw,
-			dateCenter: pagesDateCenterZhtw
+			dateCenter: pagesDateCenterZhtw,
+			assistant: pagesAssistantZhtw
 		},
 	},
 };

+ 67 - 63
src/views/assistant/index.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 import { computed, isReactive, nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
+import { useI18n } from 'vue-i18n'
 import { Local } from '/@/utils/storage'
 import {
 	ArrowDown,
@@ -46,6 +47,9 @@ import system from '/@/api/system'
 
 const plugins: Array<MarkdownPlugin<any>> = [EChartsPlugin(), ToolsLoadingPlugin(), TablePlugin(), StructDataPlugin()]
 
+// 国际化
+const { t } = useI18n()
+
 //聊天管理接口
 // 消息列表
 const messages = ref<Message[]>([])
@@ -66,7 +70,7 @@ const dropToUploadZone = ref<HTMLElement>()
 
 const { isOverDropZone } = useDropZone(dropToUploadZone, async (files: File[] | null) => {
 	if (loadingUpload.value) {
-		ElMessage.warning('请等待上传完成')
+		ElMessage.warning(t('message.assistant.status.uploading'))
 		return
 	}
 	if (files === null || files.length === 0) return
@@ -166,12 +170,12 @@ const removeAttachment = (index: number) => {
 const modelOptions = ref<LmConfigInfo[]>([])
 const modelLabel = computed(() => {
 	if (!loadingModels.value && selectedModel.value === undefined) {
-		return '未配置模型'
+		return t('message.assistant.status.noModelConfigured')
 	}
 	const select = modelOptions.value.filter((i) => i.id === selectedModel.value)
 
 	if (select.length === 0) {
-		return '加载中'
+		return t('message.assistant.status.loading')
 	}
 
 	return select[0].modelName
@@ -208,7 +212,7 @@ const displayPromptList = computed(() => {
 	if (customPrompt.value.trim() !== '') {
 		r.splice(1, 0, {
 			id: -2,
-			title: `自定义提示词 (${customPrompt.value.length}) 字`,
+			title: t('message.assistant.prompt.customPromptWithCount', { count: customPrompt.value.length }),
 			prompt: customPrompt.value,
 		})
 	}
@@ -231,12 +235,12 @@ watch(selectPromptId, (newVal) => {
 })
 const promptLabel = computed(() => {
 	if (!loadingPromptList.value && selectPromptId.value === undefined) {
-		return '未配置提示词'
+		return t('message.assistant.status.noPromptConfigured')
 	}
 	const select = displayPromptList.value.filter((i) => i.id === selectPromptId.value)
 
 	if (select.length === 0) {
-		return '加载中'
+		return t('message.assistant.status.loading')
 	}
 
 	return select[0].title
@@ -253,7 +257,7 @@ const { loading: loadingPromptList, doLoading: loadPromptList } = useLoading(asy
 	if (promptList.value.length !== 0) {
 		promptList.value.unshift({
 			id: -1,
-			title: '不启用提示词',
+			title: t('message.assistant.prompt.noPrompt'),
 			prompt: '',
 		})
 	}
@@ -346,11 +350,11 @@ const replaceMessage = async (index: number) => {
 
 		if (aiMessage?.like === true) {
 			const confirm = await ElMessageBox({
-				title: '提示',
-				message: '替换消息会导致收藏内容被修改,是否继续?',
+				title: t('message.assistant.messages.prompt'),
+				message: t('message.assistant.messages.replaceMessageWarning'),
 				type: 'warning',
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
+				confirmButtonText: t('message.assistant.buttons.confirmDialog'),
+				cancelButtonText: t('message.assistant.buttons.cancelDialog'),
 			})
 
 			if (!confirm) {
@@ -509,7 +513,7 @@ ${resp.request.data.replace('\n', '')}
 				.catch(() => false)
 
 			if (!save_status) {
-				ElMessage.warning('消息保存失败,切换对话会导致消息记录丢失')
+				ElMessage.warning(t('message.assistant.messages.messageSaveFailed'))
 			}
 
 			chatInstance.value = undefined
@@ -536,7 +540,7 @@ const scrollToBottom = () => {
 // 所有会话
 const conversations = ref<LmSession[]>([])
 const displayConversations = computed(() => {
-	return [{ session_id: -1, title: '收藏夹' }, ...conversations.value]
+	return [{ session_id: -1, title: t('message.assistant.sidebar.bookmark') }, ...conversations.value]
 })
 const { loading: loadConversations, doLoading: doLoadConversations } = useLoading(async () => {
 	const data: { list: LmSession[]; total: number } = await assist.session
@@ -625,7 +629,7 @@ const { loading: loadingDeleteConversation, doLoading: deleteConversation } = us
 	if (!res) {
 		return
 	}
-	ElMessage.success('删除成功')
+	ElMessage.success(t('message.assistant.messages.deleteSuccess'))
 	activeConversationId.value = undefined
 	messages.value = []
 	conversations.value = conversations.value.filter((item) => item.session_id !== id)
@@ -646,15 +650,15 @@ const multiDeleteConversationClear = () => {
 // 多选删除会话
 const startMultidelete = async () => {
 	if (multiDeleteConversationModel.value.selectedConversations.length === 0) {
-		ElMessage.warning('请选择要删除的会话')
+		ElMessage.warning(t('message.assistant.messages.selectConversationsToDelete'))
 		return
 	}
 	const confirm = await ElMessageBox.confirm(
-		`确定要删除选中的 ${multiDeleteConversationModel.value.selectedConversations.length} 个会话吗?此操作不可恢复!`,
-		'警告',
+		t('message.assistant.messages.deleteConfirm', { count: multiDeleteConversationModel.value.selectedConversations.length }),
+		t('message.assistant.messages.warning'),
 		{
-			confirmButtonText: '确定',
-			cancelButtonText: '取消',
+			confirmButtonText: t('message.assistant.buttons.confirmDialog'),
+			cancelButtonText: t('message.assistant.buttons.cancelDialog'),
 			type: 'error',
 		}
 	)
@@ -672,7 +676,7 @@ const startMultidelete = async () => {
 		return
 	}
 
-	ElMessage.success('删除成功')
+	ElMessage.success(t('message.assistant.messages.deleteSuccess'))
 
 	await nextTick()
 	conversations.value = conversations.value.filter((item) => !multiDeleteConversationModel.value.selectedConversations.includes(item.session_id))
@@ -681,7 +685,7 @@ const startMultidelete = async () => {
 // 创建新对话
 const { loading: creatingConversation, doLoading: createConversationAndSetItActive } = useLoading(async () => {
 	// 调用API创建新对话,默认标题为"新对话"
-	const { id } = await assist.session.add('新对话')
+	const { id } = await assist.session.add(t('message.assistant.sidebar.createConversation'))
 	// 刷新对话列表
 	await doLoadConversations()
 
@@ -900,7 +904,7 @@ const isSystemLoading = computed(()=> {
 		<!-- 左侧会话列表 -->
 		<el-aside width="300px" class="chat-sidebar">
 			<div class="sidebar-header">
-				<h3>对话历史</h3>
+				<h3>{{ t('message.assistant.sidebar.conversationHistory') }}</h3>
 				<el-dropdown v-model="showSettingsPanel" trigger="click" placement="bottom-end">
 					<el-button round :icon="EleSetting" size="small">
 						<el-icon class="el-icon--right">
@@ -911,18 +915,18 @@ const isSystemLoading = computed(()=> {
 						<el-dropdown-menu v-if="!multiDeleteConversationModel.visible">
 							<el-dropdown-item class="settings-item">
 								<div class="settings-row">
-									<span class="settings-label">新对话自动记录工具调用</span>
+									<span class="settings-label">{{ t('message.assistant.settings.autoRecordToolCalls') }}</span>
 									<el-switch v-model="showToolCalls" size="small" />
 								</div>
 							</el-dropdown-item>
 							<el-dropdown-item @click="redirectToModelManager">
-								<span class="settings-label">模型管理</span>
+								<span class="settings-label">{{ t('message.assistant.settings.modelManagement') }}</span>
 							</el-dropdown-item>
 							<el-dropdown-item @click="promptDialogVisible = true">
-								<span class="settings-label">提示词管理</span>
+								<span class="settings-label">{{ t('message.assistant.settings.promptManagement') }}</span>
 							</el-dropdown-item>
 							<el-dropdown-item @click="multiDeleteConversationModel.visible = true">
-								<span class="settings-label">对话管理</span>
+								<span class="settings-label">{{ t('message.assistant.settings.conversationManagement') }}</span>
 							</el-dropdown-item>
 						</el-dropdown-menu>
 						<el-dropdown-menu v-else>
@@ -930,13 +934,13 @@ const isSystemLoading = computed(()=> {
 								<el-icon>
 									<Close />
 								</el-icon>
-								<span>取消选择</span>
+								<span>{{ t('message.assistant.settings.cancelSelection') }}</span>
 							</el-dropdown-item>
 							<el-dropdown-item @click="startMultidelete">
 								<el-icon>
 									<Delete />
 								</el-icon>
-								<span>删除选中</span>
+								<span>{{ t('message.assistant.settings.deleteSelected') }}</span>
 							</el-dropdown-item>
 						</el-dropdown-menu>
 					</template>
@@ -977,7 +981,7 @@ const isSystemLoading = computed(()=> {
 						<!-- 非编辑状态的三点菜单 -->
 						<template v-if="editingConversationId !== conv.session_id">
 							<el-dropdown trigger="click" placement="bottom-end" @click.stop>
-								<el-button type="primary" size="small" :icon="MoreFilled" class="action-btn more-btn" title="更多操作" plain circle @click.stop />
+								<el-button type="primary" size="small" :icon="MoreFilled" class="action-btn more-btn" :title="t('message.assistant.buttons.more')" plain circle @click.stop />
 								<template #dropdown>
 									<el-dropdown-menu>
 										<el-dropdown-item @click="exportConversation(conv.session_id)">
@@ -985,13 +989,13 @@ const isSystemLoading = computed(()=> {
 											<el-icon v-else>
 												<Download />
 											</el-icon>
-											<span>导出</span>
+											<span>{{ t('message.assistant.buttons.export') }}</span>
 										</el-dropdown-item>
 										<el-dropdown-item @click="editSummary(conv.session_id)">
 											<el-icon>
 												<Edit />
 											</el-icon>
-											<span>编辑</span>
+											<span>{{ t('message.assistant.buttons.edit') }}</span>
 										</el-dropdown-item>
 										<el-dropdown-item
 											@click="deleteConversation(conv.session_id)"
@@ -1000,7 +1004,7 @@ const isSystemLoading = computed(()=> {
 											<el-icon>
 												<Delete />
 											</el-icon>
-											<span>删除</span>
+											<span>{{ t('message.assistant.buttons.delete') }}</span>
 										</el-dropdown-item>
 									</el-dropdown-menu>
 								</template>
@@ -1016,7 +1020,7 @@ const isSystemLoading = computed(()=> {
 								:loading="loadingConfirmEdit"
 								@click.stop="confirmEdit(conv.session_id)"
 								class="action-btn confirm-btn"
-								title="确认修改"
+								:title="t('message.assistant.buttons.confirm')"
 								plain
 								circle
 							/>
@@ -1025,7 +1029,7 @@ const isSystemLoading = computed(()=> {
 								size="small"
 								@click.stop="cancelEdit(conv.session_id)"
 								class="action-btn cancel-btn"
-								title="取消编辑"
+								:title="t('message.assistant.buttons.cancel')"
 								plain
 								circle
 							>
@@ -1044,7 +1048,7 @@ const isSystemLoading = computed(()=> {
 				@click="createConversationAndSetItActive"
 				:loading="creatingConversation"
 				:disabled="isConversationActive"
-				>创建对话
+				>{{ t('message.assistant.sidebar.createConversation') }}
 			</el-button>
 		</el-aside>
 
@@ -1066,7 +1070,7 @@ const isSystemLoading = computed(()=> {
 											<span class="dot"></span>
 											<span class="dot"></span>
 										</div>
-										<span class="loading-text">AI正在思考中...</span>
+										<span class="loading-text">{{ t('message.assistant.status.aiThinking') }}</span>
 									</div>
 								</div>
 								<div class="ai-message-actions">
@@ -1105,7 +1109,7 @@ const isSystemLoading = computed(()=> {
 											:key="file.path"
 											class="file-item"
 											@click="openFile(file.full_path)"
-											:title="`点击打开: ${file.name}`"
+											:title="t('message.assistant.file.clickToOpen', { name: file.name })"
 										>
 											<el-icon class="file-icon">
 												<Document v-if="file.type.includes('text') || file.type.includes('document')" />
@@ -1128,7 +1132,7 @@ const isSystemLoading = computed(()=> {
 										plain
 										:disabled="isConversationActive"
 									>
-										重试
+										{{ t('message.assistant.buttons.retry') }}
 									</el-button>
 								</div>
 							</div>
@@ -1147,27 +1151,27 @@ const isSystemLoading = computed(()=> {
 							</el-icon>
 						</div>
 						<div class="empty-text">
-							<h2 class="empty-title">暂无收藏消息</h2>
-							<p class="empty-description">您还没有收藏任何对话消息</p>
+							<h2 class="empty-title">{{ t('message.assistant.empty.noBookmarks') }}</h2>
+							<p class="empty-description">{{ t('message.assistant.empty.noBookmarksDescription') }}</p>
 						</div>
 						<div class="empty-tips">
 							<div class="tip-item">
 								<el-icon color="#409eff">
 									<InfoFilled />
 								</el-icon>
-								<span>在对话中点击 ⭐ 按钮即可收藏消息</span>
+								<span>{{ t('message.assistant.empty.bookmarkTip1') }}</span>
 							</div>
 							<div class="tip-item">
 								<el-icon color="#67c23a">
 									<Search />
 								</el-icon>
-								<span>收藏的消息支持关键词搜索</span>
+								<span>{{ t('message.assistant.empty.bookmarkTip2') }}</span>
 							</div>
 							<div class="tip-item">
 								<el-icon color="#e6a23c">
 									<Collection />
 								</el-icon>
-								<span>收藏消息会保存在云端,永不丢失</span>
+								<span>{{ t('message.assistant.empty.bookmarkTip3') }}</span>
 							</div>
 						</div>
 					</div>
@@ -1180,18 +1184,18 @@ const isSystemLoading = computed(()=> {
 							</el-icon>
 						</div>
 						<div class="empty-text">
-							<h2 class="empty-title">开始新的对话</h2>
+							<h2 class="empty-title">{{ t('message.assistant.empty.startNewConversation') }}</h2>
 						</div>
 						<div class="example-questions">
-							<h4>试试这些问题:</h4>
+							<h4>{{ t('message.assistant.empty.tryTheseQuestions') }}</h4>
 							<div class="question-tags">
-								<el-tag class="question-tag" @click="inputMessage = '帮我查看设备运行状态和告警信息'" type="info">
-									帮我查看设备运行状态和告警信息
+								<el-tag class="question-tag" @click="inputMessage = t('message.assistant.examples.deviceStatus')" type="info">
+									{{ t('message.assistant.examples.deviceStatus') }}
 								</el-tag>
-								<el-tag class="question-tag" @click="inputMessage = '分析用户权限配置和角色分配情况'" type="success">
-									分析用户权限配置和角色分配情况
+								<el-tag class="question-tag" @click="inputMessage = t('message.assistant.examples.userPermissions')" type="success">
+									{{ t('message.assistant.examples.userPermissions') }}
 								</el-tag>
-								<el-tag class="question-tag" @click="inputMessage = '检查系统性能和在线用户统计'" type="warning"> 检查系统性能和在线用户统计 </el-tag>
+								<el-tag class="question-tag" @click="inputMessage = t('message.assistant.examples.systemPerformance')" type="warning"> {{ t('message.assistant.examples.systemPerformance') }} </el-tag>
 							</div>
 						</div>
 					</div>
@@ -1226,8 +1230,8 @@ const isSystemLoading = computed(()=> {
 								</div>
 								<!-- 无附件时的提示信息 -->
 								<div v-if="selectedFiles.length === 0" class="attachment-hint">
-									<span v-if="!isOverDropZone">点击右侧+上传文件</span>
-									<span v-else>松开鼠标上传文件...</span>
+									<span v-if="!isOverDropZone">{{ t('message.assistant.status.clickToUpload') }}</span>
+									<span v-else>{{ t('message.assistant.status.uploadProgress') }}</span>
 								</div>
 							</div>
 						</el-scrollbar>
@@ -1242,7 +1246,7 @@ const isSystemLoading = computed(()=> {
 					<textarea
 						v-model="inputMessage"
 						class="large-textarea"
-						placeholder="请输入您的问题..."
+						:placeholder="t('message.assistant.placeholders.inputQuestion')"
 						@keydown.enter.ctrl="sendMessage"
 						@keydown.enter.meta="sendMessage"
 						:disabled="isConversationActive"
@@ -1254,7 +1258,7 @@ const isSystemLoading = computed(()=> {
 						<!-- 左下角按钮组 -->
 						<div class="left-controls">
 							<!-- 模型选择按钮 -->
-							<el-dropdown trigger="click" placement="top-start" :disabled="loadingModels || modelLabel == '未配置模型'">
+							<el-dropdown trigger="click" placement="top-start" :disabled="loadingModels || modelLabel == t('message.assistant.status.noModelConfigured')">
 								<button class="control-btn model-btn">
 									<el-icon>
 										<Setting v-if="!loadingModels" />
@@ -1277,7 +1281,7 @@ const isSystemLoading = computed(()=> {
 							</el-dropdown>
 
 							<!-- 词嵌入模型选择按钮 -->
-							<el-dropdown trigger="click" placement="top-start" :disabled="loadingModels || promptLabel == '未配置提示词'">
+							<el-dropdown trigger="click" placement="top-start" :disabled="loadingModels || promptLabel == t('message.assistant.status.noPromptConfigured')">
 								<button class="control-btn embedding-model-btn">
 									<el-icon>
 										<CopyDocument v-if="!loadingPromptList" />
@@ -1326,19 +1330,19 @@ const isSystemLoading = computed(()=> {
 					<div class="bookmark-search">
 						<el-input
 							v-model="bookmarkOptions.keyWord"
-							placeholder="搜索收藏的消息..."
+							:placeholder="t('message.assistant.placeholders.searchBookmarks')"
 							:prefix-icon="Search"
 							clearable
 							@keydown.enter="handleBookmarkSearch"
 							@clear="handleBookmarkReset"
 							style="width: 300px"
 						/>
-						<el-button type="primary" :icon="Search" @click="handleBookmarkSearch" :loading="loadingMessage"> 搜索 </el-button>
+						<el-button type="primary" :icon="Search" @click="handleBookmarkSearch" :loading="loadingMessage"> {{ t('message.assistant.buttons.search') }} </el-button>
 					</div>
 
 					<!-- 分页和重置 -->
 					<div class="bookmark-pagination">
-						<el-button @click="handleBookmarkReset" :loading="loadingMessage"> 重置</el-button>
+						<el-button @click="handleBookmarkReset" :loading="loadingMessage"> {{ t('message.assistant.buttons.reset') }} </el-button>
 						<el-pagination
 							v-model:current-page="bookmarkOptions.pageNum"
 							v-model:page-size="bookmarkOptions.pageSize"
@@ -1358,22 +1362,22 @@ const isSystemLoading = computed(()=> {
 		</el-main>
 
 		<!-- 提示词管理对话框 -->
-		<el-dialog v-model="promptDialogVisible" title="提示词管理" width="60%" append-to-body>
+		<el-dialog v-model="promptDialogVisible" :title="t('message.assistant.prompt.management')" width="60%" append-to-body>
 			<div class="prompt-dialog-content">
 				<div class="prompt-input-section">
-					<h4>自定义提示词</h4>
+					<h4>{{ t('message.assistant.prompt.customPrompt') }}</h4>
 					<el-input
 						v-model="customPrompt"
 						type="textarea"
 						:autosize="{ minRows: 12, maxRows: 24 }"
-						placeholder="在此编写你的提示词...(将用于本次会话的系统提示)"
+						:placeholder="t('message.assistant.placeholders.customPrompt')"
 					/>
 				</div>
 			</div>
 			<template #footer>
 				<div class="dialog-footer">
-					<el-button @click="promptDialogVisible = false">取 消</el-button>
-					<el-button type="primary" @click="promptDialogVisible = false">确 认</el-button>
+					<el-button @click="promptDialogVisible = false">{{ t('message.assistant.buttons.cancelDialog') }}</el-button>
+					<el-button type="primary" @click="promptDialogVisible = false">{{ t('message.assistant.buttons.confirmDialog') }}</el-button>
 				</div>
 			</template>
 		</el-dialog>