Commit 22485358 by pangchong

refactor(api): 优化接口请求处理与表单提交方式

- 移除旧的错误信息智能识别和处理逻辑,精简响应码拦截代码
- 新增 postForm 方法支持自动处理 multipart/form-data,优化文件上传逻辑
- 删除下载文件相关的复杂实现,简化请求发送流程
- 在批量翻译功能中添加取消翻译支持,完善用户交互
- 优化编辑器选中节点逻辑,确保滚动时正确设置选中状态
- 调整编辑器工具栏分隔线的样式,提升界面一致性
- 修改搜索翻译模块的警示卡样式,增强视觉效果
- 移除多个无用的 utils 导入,精简编辑器相关代码
- 修正设置面板确认清空并退出弹窗调用,使用标准对象参数
- 新增 Splitter 组件的类型定义,调整相关实现导入方式
parent a05473b7
...@@ -466,7 +466,10 @@ const importPrefs = async () => { ...@@ -466,7 +466,10 @@ const importPrefs = async () => {
const clearAndLogout = async () => { const clearAndLogout = async () => {
try { try {
await window.$dialog.warning('确认清空并退出', '确定要清空所有本地缓存并退出登录吗?此操作不可逆。') await window.$dialog.warning({
title: '确认清空并退出',
content: '确定要清空所有本地缓存并退出登录吗?此操作不可逆。'
})
localStorage.clear() localStorage.clear()
router.push('/login') router.push('/login')
window.$message.success('已清空并退出') window.$message.success('已清空并退出')
......
...@@ -10,7 +10,6 @@ import { setupNaiveDefaults } from '@/plugins/naive-ui-defaults' ...@@ -10,7 +10,6 @@ import { setupNaiveDefaults } from '@/plugins/naive-ui-defaults'
// 设置 Naive UI 组件默认属性 // 设置 Naive UI 组件默认属性
setupNaiveDefaults() setupNaiveDefaults()
import { setupNaiveDiscreteApi } from '@/utils/naive'
const app = createApp(App) const app = createApp(App)
......
import type { Ref } from 'vue' import type { Ref } from 'vue'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import type { EditorState } from './types' import type { EditorState } from './types'
import { createDefaultAttributes, canAddChild } from '@/utils/dtdManager'
import { parseXmlToTree } from '@/utils/xmlParser'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/app'
import { CHINESE_FIRST_PARA_TAGS } from '@/configs/xmlTags' import { CHINESE_FIRST_PARA_TAGS } from '@/configs/xmlTags'
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { SettingsOutline } from '@vicons/ionicons5' import { SettingsOutline } from '@vicons/ionicons5'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import { getElementAttributes } from '@/utils/dtdManager'
import { useAttributeEditor } from './functionals' import { useAttributeEditor } from './functionals'
const props = defineProps<{ const props = defineProps<{
......
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import { serializeTreeToXml } from '@/utils/xmlParser'
import { getElementRule, isMixedContentElement } from '@/utils/dtdManager'
import type { EditAreaContextMenuProps } from '../constants' import type { EditAreaContextMenuProps } from '../constants'
// 导入共享弹窗状态 // 导入共享弹窗状态
......
...@@ -311,6 +311,9 @@ export function useEditorPanel() { ...@@ -311,6 +311,9 @@ export function useEditorPanel() {
return return
} }
el.scrollIntoView({ behavior: 'auto', block: 'center' }) el.scrollIntoView({ behavior: 'auto', block: 'center' })
if (foundNodeId && foundNodeId !== editorStore.selectedNodeId) {
editorStore.setSelectedNodeId(foundNodeId)
}
return return
} }
...@@ -344,6 +347,9 @@ export function useEditorPanel() { ...@@ -344,6 +347,9 @@ export function useEditorPanel() {
} }
if (targetEl) { if (targetEl) {
targetEl.scrollIntoView({ behavior: 'auto', block: 'center' }) targetEl.scrollIntoView({ behavior: 'auto', block: 'center' })
if (subFoundId && subFoundId !== editorStore.selectedNodeId) {
editorStore.setSelectedNodeId(subFoundId)
}
} }
}, 100) }, 100)
}) })
......
...@@ -73,6 +73,22 @@ export function useBatchTranslate() { ...@@ -73,6 +73,22 @@ export function useBatchTranslate() {
} }
} }
const cancelTranslation = () => {
if (!loading.value) return
if (pollInterval) {
clearInterval(pollInterval)
pollInterval = null
}
loading.value = false
completed.value = false
progress.value = 0
resultFileId.value = ''
resultDownloadUrl.value = ''
progressText.value = '正在准备翻译文档...'
addLog('翻译已取消,返回配置页面')
window.$message.info('已取消翻译')
}
const open = async () => { const open = async () => {
showModal.value = true showModal.value = true
if (loading.value || completed.value) { if (loading.value || completed.value) {
...@@ -80,7 +96,7 @@ export function useBatchTranslate() { ...@@ -80,7 +96,7 @@ export function useBatchTranslate() {
} }
reset() reset()
try { try {
const res = (await service.get('/xml/tags')) as any as { success: boolean; message: string; tags: string[] } const res = await service.get('/xml/tags')
if (res && res.success && res.tags && res.tags.length > 0) { if (res && res.success && res.tags && res.tags.length > 0) {
availableTags.value = res.tags availableTags.value = res.tags
// 自动勾选所有获取到的标签 // 自动勾选所有获取到的标签
...@@ -98,7 +114,7 @@ export function useBatchTranslate() { ...@@ -98,7 +114,7 @@ export function useBatchTranslate() {
pollInterval = setInterval(async () => { pollInterval = setInterval(async () => {
try { try {
const statusRes = (await service.get(`/translation/status/${fileId}`)) as any as TranslationStatusResponse const statusRes = await service.get(`/translation/status/${fileId}`)
if (statusRes) { if (statusRes) {
if (statusRes.status === 'completed') { if (statusRes.status === 'completed') {
clearInterval(pollInterval) clearInterval(pollInterval)
...@@ -159,28 +175,19 @@ export function useBatchTranslate() { ...@@ -159,28 +175,19 @@ export function useBatchTranslate() {
addLog(`文档序列化完成,大小: ${Math.round(blob.size / 1024)} KB。准备上传...`) addLog(`文档序列化完成,大小: ${Math.round(blob.size / 1024)} KB。准备上传...`)
addLog(`请求配置: 模型 = ${form.value.model_name}, 目标标签 = [${form.value.target_tags.join(', ')}]`) addLog(`请求配置: 模型 = ${form.value.model_name}, 目标标签 = [${form.value.target_tags.join(', ')}]`)
const formData = new FormData() const res = await service.postForm('/translate/xml', {
formData.append('files', blob, 'document.xml') query_partition_names: import.meta.env.VITE_PARTITION_NAME,
if (form.value.model_name) { files: [blob, 'document.xml'],
formData.append('model_name', form.value.model_name) ...(form.value.model_name ? { model_name: form.value.model_name } : {}),
} search_direction: form.value.search_direction,
formData.append('search_direction', form.value.search_direction) target_tags: form.value.target_tags.join(','),
formData.append('target_tags', form.value.target_tags.join(',')) ...(form.value.suffix ? { suffix: form.value.suffix } : {}),
if (form.value.suffix) { save_to_database: form.value.save_to_database,
formData.append('suffix', form.value.suffix) use_parallel_method: form.value.use_parallel_method,
} ...(form.value.save_to_database && form.value.database_partition_name
formData.append('save_to_database', String(form.value.save_to_database)) ? { database_partition_name: form.value.database_partition_name }
formData.append('use_parallel_method', String(form.value.use_parallel_method)) : {})
const dbPartition = form.value.save_to_database ? form.value.database_partition_name : undefined })
if (dbPartition) {
formData.append('database_partition_name', dbPartition)
}
const res = (await service.post('/translate/xml', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})) as any as TranslateXmlResponse
if (res && res.success && res.file_id) { if (res && res.success && res.file_id) {
resultFileId.value = res.file_id resultFileId.value = res.file_id
...@@ -259,6 +266,7 @@ export function useBatchTranslate() { ...@@ -259,6 +266,7 @@ export function useBatchTranslate() {
open, open,
reset, reset,
startTranslation, startTranslation,
cancelTranslation,
downloadResult, downloadResult,
importResult, importResult,
logs logs
......
...@@ -78,8 +78,9 @@ ...@@ -78,8 +78,9 @@
<template #footer> <template #footer>
<div class="flex justify-end gap-3 w-full"> <div class="flex justify-end gap-3 w-full">
<!-- 翻译中状态:允许隐入后台 --> <!-- 翻译中状态:允许隐入后台或取消 -->
<template v-if="loading"> <template v-if="loading">
<CommonButton type="error" secondary @click="cancelTranslation">取消翻译</CommonButton>
<CommonButton type="primary" secondary @click="showModal = false">后台运行 (隐藏)</CommonButton> <CommonButton type="primary" secondary @click="showModal = false">后台运行 (隐藏)</CommonButton>
</template> </template>
<!-- 翻译完成状态 --> <!-- 翻译完成状态 -->
...@@ -118,6 +119,7 @@ const { ...@@ -118,6 +119,7 @@ const {
open, open,
reset, reset,
startTranslation, startTranslation,
cancelTranslation,
downloadResult, downloadResult,
importResult, importResult,
logs logs
......
import { type ExtractResponse } from '../constants' import { type ExtractResponse } from '../constants'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { serializeTreeToXml } from '@/utils/xmlParser'
import { getBaseOrigin } from '@/utils/render'
export function useExtractTranslate() { export function useExtractTranslate() {
const editorStore = useEditorStore() const editorStore = useEditorStore()
......
import { type SearchResult, type SearchResponse, type SearchRequest } from '../constants' import { type SearchResult, type SearchResponse, type SearchRequest } from '../constants'
import { serviceManage } from '@/api'
import dayjs from 'dayjs' import dayjs from 'dayjs'
export function useSearchTranslate() { export function useSearchTranslate() {
......
...@@ -160,7 +160,7 @@ ...@@ -160,7 +160,7 @@
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<!-- 警示卡片:说明删除操作 --> <!-- 警示卡片:说明删除操作 -->
<div <div
class="bg-amber-50 dark:bg-amber-950/20 border border-amber-200 dark:border-amber-900 rounded-lg p-4 text-xs text-amber-800 dark:text-amber-300 flex items-start gap-2" class="bg-[color-mix(in_srgb,var(--warning-color)_10%,transparent)] border border-[color-mix(in_srgb,var(--warning-color)_25%,transparent)] rounded-lg p-4 text-xs text-warning flex items-start gap-2"
> >
<n-icon size="18" class="mt-0.5"><alert-circle-outline /></n-icon> <n-icon size="18" class="mt-0.5"><alert-circle-outline /></n-icon>
<div class="flex-1 flex flex-col gap-1"> <div class="flex-1 flex flex-col gap-1">
......
import { useEditorStore, createTableStructure } from '@/store/editor' import { useEditorStore, createTableStructure } from '@/store/editor'
import { useAppStore } from '@/store/app/index' import { useAppStore } from '@/store/app/index'
import { canAddChild } from '@/utils/dtdManager'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
/** /**
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<div class="w-[1px] h-4 bg-divider mx-1 flex-shrink-0"></div> <div class="w-px h-5 flex-shrink-0 mx-2" style="background: #d0d0d0"></div>
<!-- 组 2:插入元素按钮组 --> <!-- 组 2:插入元素按钮组 -->
<div class="flex items-center gap-0.5 flex-shrink-0"> <div class="flex items-center gap-0.5 flex-shrink-0">
...@@ -51,9 +51,8 @@ ...@@ -51,9 +51,8 @@
</button> </button>
</div> </div>
<div class="w-[1px] h-4 bg-divider mx-1 flex-shrink-0"></div> <div class="w-px h-5 flex-shrink-0 mx-3" style="background: #d0d0d0"></div>
<!-- 组 3:翻译辅助组 -->
<div class="flex items-center gap-0.5 flex-shrink-0"> <div class="flex items-center gap-0.5 flex-shrink-0">
<button <button
type="button" type="button"
...@@ -94,7 +93,7 @@ ...@@ -94,7 +93,7 @@
</button> </button>
</div> </div>
<div class="w-[1px] h-4 bg-divider mx-1 flex-shrink-0"></div> <div class="w-px h-5 flex-shrink-0 mx-3" style="background: #d0d0d0"></div>
<!-- 组 4:文件管理与导入导出 --> <!-- 组 4:文件管理与导入导出 -->
<div class="flex items-center gap-0.5 flex-shrink-0"> <div class="flex items-center gap-0.5 flex-shrink-0">
...@@ -136,7 +135,7 @@ ...@@ -136,7 +135,7 @@
</button> </button>
</div> </div>
<div class="w-[1px] h-4 bg-divider mx-1 flex-shrink-0"></div> <div class="w-px h-5 flex-shrink-0 mx-2" style="background: #d0d0d0"></div>
<!-- 组 5:历史操作 (撤销 / 重做) --> <!-- 组 5:历史操作 (撤销 / 重做) -->
<div class="flex items-center gap-0.5 flex-shrink-0"> <div class="flex items-center gap-0.5 flex-shrink-0">
......
import type { FormInst } from 'naive-ui' import type { FormInst } from 'naive-ui'
import { getElementAttributes, createDefaultAttributes, isTextOnlyElement, isMixedContentElement } from '@/utils/dtdManager'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/app'
......
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import type { BlockedNodeDetail, SafeNodeItem } from '../../../constants' import type { BlockedNodeDetail, SafeNodeItem } from '../../../constants'
import { canDeleteChild } from '@/utils/dtdManager'
export function useBatchDeleteConfirmModal(emit: (event: 'confirm') => void) { export function useBatchDeleteConfirmModal(emit: (event: 'confirm') => void) {
const editorStore = useEditorStore() const editorStore = useEditorStore()
......
...@@ -19,8 +19,6 @@ import { ...@@ -19,8 +19,6 @@ import {
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/app'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import { serializeTreeToXml } from '@/utils/xmlParser'
import { isMixedContentElement, isTextOnlyElement, sortChildrenByDtd } from '@/utils/dtdManager'
import type { CheckRuleData, InsertMode, FlatNode, TranslationResponse } from '../constants' import type { CheckRuleData, InsertMode, FlatNode, TranslationResponse } from '../constants'
import { DOCUMENT_LIKE_TAGS } from '../constants' import { DOCUMENT_LIKE_TAGS } from '../constants'
import { STRUCTURAL_TAGS, WARNING_LIKE_TAGS, NOTE_AND_REF_TAGS, COLORED_TAGS } from '@/configs/xmlTags' import { STRUCTURAL_TAGS, WARNING_LIKE_TAGS, NOTE_AND_REF_TAGS, COLORED_TAGS } from '@/configs/xmlTags'
......
export interface SplitterProps {
width: number
collapsed: boolean
collapseThreshold?: number
defaultWidth?: number
maxRatio?: number
}
export interface SplitterProps { import { type SplitterProps } from '../constants'
width: number
collapsed: boolean
collapseThreshold?: number
defaultWidth?: number
maxRatio?: number
}
export function useSplitter( export function useSplitter(
props: SplitterProps, props: SplitterProps,
......
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { loadDtdSchema, getElementRule } from '@/utils/dtdManager'
import { parseXmlToTreeAsync, serializeTreeToXml } from '@/utils/xmlParser'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import { DEFAULT_FILE_NAME } from '../constants' import { DEFAULT_FILE_NAME } from '../constants'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment