feat: i18n
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Typos Check / Spell Check with Typos (push) Waiting to run

This commit is contained in:
wangdan-fit2cloud 2025-01-14 19:28:30 +08:00
parent 3dcc31b3b9
commit 04a255af23
24 changed files with 547 additions and 221 deletions

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
title="生成问题"
:title="$t('views.document.setting.generateQuestion')"
v-model="dialogVisible"
width="650"
:close-on-click-modal="false"

View File

@ -14,6 +14,8 @@ export default {
submitSuccess: 'Submitted successfully',
edit: 'Edit',
editSuccess: 'Edit Successful',
modify: 'Modify',
modifySuccess: 'Modify Successful',
cancel: 'Cancel',
confirm: 'Confirm',
tip: 'Prompt',
@ -35,7 +37,6 @@ export default {
paramSetting: 'Parameter Settings',
creator: 'Creator',
debug: 'Debug',
modify: 'Modify',
required: 'Required',
noData: 'No data',
status: {

View File

@ -14,6 +14,8 @@ export default {
submitSuccess: '提交成功',
edit: '编辑',
editSuccess: '编辑成功',
modify: '修改',
modifySuccess: '修改成功',
cancel: '取消',
confirm: '确定',
tip: '提示',
@ -35,7 +37,6 @@ export default {
paramSetting: '参数设置',
creator: '创建者',
debug: '调试',
modify: '修改',
required: '必填',
noData: '暂无数据',
status: {

View File

@ -1,6 +1,7 @@
export default {
title: '知识库',
createDataset: '创建知识库',
selectDataset: '选择知识库',
general: '通用型',
web: 'web 站点',
relatedApplications: '关联应用',
@ -57,11 +58,26 @@ export default {
label: '选择器',
placeholder: '默认为 body可输入 .classname/#idname/tagname'
}
},
buttons: {},
dialog: {
}
},
ResultSuccess: {
title: '知识库创建成功',
paragraph: '分段',
paragraph_count: '个分段',
documentList: '文档列表',
loading: '导入中',
buttons: {
toDataset: '返回知识库列表',
toDocument: '前往文档'
}
},
syncWeb: {
title: '同步知识库',
syncMethod: '同步方式',
replace: '替换同步',
replaceText: '重新获取 Web 站点文档,覆盖替换本地知识库中的文档',
complete: '整体同步',
completeText: '先删除本地知识库所有文档,重新获取 Web 站点文档',
tip: '注意:所有同步都会删除已有数据重新获取新数据,请谨慎操作。'
}
}

View File

@ -0,0 +1,182 @@
export default {
uploadDocument: '上传文档',
importDocument: '导入文档',
syncDocument: '同步文档',
selected: '已选',
items: '项',
searchBar: {
placeholder: '按 文档名称 搜索'
},
setting: {
migration: '迁移',
generateQuestion: '生成问题',
cancelGenerateQuestion: '取消生成问题',
cancelVectorization: '取消向量化',
cancelGenerate: '取消生成'
},
tip: {
saveMessage: '当前的更改尚未保存,确认退出吗?',
cancelSuccessMessage: '批量取消成功',
sendMessage: '发送成功',
vectorizationSuccessMessage: '批量向量化成功',
nameMessage: '文件名称不能为空!',
importMessage: '导入成功'
},
upload: {
selectFile: '选择文件',
selectFiles: '选择文件夹',
uploadMessage: '拖拽文件至此上传或',
formats: '支持格式:',
requiredMessage: '请上传文件',
errorMessage1: '请上传文件',
errorMessage2: '文件格式不支持',
errorMessage3: '文件不能为空',
errorMessage4: '每次最多上传50个文件',
template: '模版',
download: '下载'
},
fileType: {
txt: {
label: '文本文件',
tip1: '1、文件上传前建议规范文件的分段标识',
tip2: '2、每次最多上传 50 个文件,每个文件不超过 100MB'
},
table: {
label: '表格',
tip1: '1、点击下载对应模版并完善信息',
tip2: '2、第一行必须是列标题且列标题必须是有意义的术语表中每条记录将作为一个分段',
tip3: '3、上传的表格文件中每个 sheet 会作为一个文档sheet名称为文档名称',
tip4: '4、每次最多上传 50 个文件,每个文件不超过 100MB'
},
QA: {
label: 'QA 问答对',
tip1: '1、点击下载对应模版并完善信息',
tip2: '2、上传的表格文件中每个 sheet 会作为一个文档sheet名称为文档名称',
tip3: '3、每次最多上传 50 个文件,每个文件不超过 100MB'
}
},
setRules: {
title: {
setting: '设置分段规则',
preview: '分段预览'
},
intelligent: {
label: '智能分段(推荐)',
text: '不了解如何设置分段规则推荐使用智能分段'
},
advanced: {
label: '高级分段',
text: '用户可根据文档规范自行设置分段标识符、分段长度以及清洗规则'
},
patterns: {
label: '分段标识',
tooltip: '按照所选符号先后顺序做递归分割,分割结果超出分段长度将截取至分段长度。',
placeholder: '请选择'
},
limit: {
label: '分段长度'
},
with_filter: {
label: '自动清洗',
text: '去掉重复多余符号空格、空行、制表符'
},
checkedConnect: {
label: '导入时添加分段标题为关联问题(适用于标题为问题的问答对)'
}
},
buttons: {
prev: '上一步',
next: '下一步',
import: '开始导入',
preview: '生成预览'
},
table: {
name: '文件名称',
char_length: '字符数',
paragraph: '分段',
all: '全部',
updateTime: '更新时间'
},
fileStatus: {
label: '文件状态',
SUCCESS: '成功',
FAILURE: '失败',
EMBEDDING: '索引中',
PENDING: '排队中',
GENERATE: '生成中',
SYNC: '同步中',
REVOKE: '取消中'
},
enableStatus: {
label: '启用状态',
enable: '开启',
close: '关闭'
},
sync: {
label: '同步',
confirmTitle: '确认同步文档?',
confirmMessage1: '同步将删除已有数据重新获取新数据,请谨慎操作。',
confirmMessage2: '无法同步,请先去设置文档 URL地址',
successMessage: '同步文档成功'
},
delete: {
confirmTitle1: '是否批量删除',
confirmTitle2: '个文档?',
confirmMessage: '所选文档中的分段会跟随删除,请谨慎操作。',
successMessage: '批量删除成功',
confirmTitle3: '是否删除文档:',
confirmMessage1: '此文档下的',
confirmMessage2: '个分段都会被删除,请谨慎操作。'
},
form: {
source_url: {
label: '文档地址',
placeholder: '请输入文档地址,一行一个,地址不正确文档会导入失败。',
requiredMessage: '请输入文档地址'
},
selector: {
label: '选择器',
placeholder: '默认为 body可输入 .classname/#idname/tagname'
},
hit_handling_method: {
label: '命中处理方式',
tooltip: '用户提问时,命中文档下的分段时按照设置的方式进行处理。'
},
similarity: {
label: '相似度高于',
placeholder: '直接返回分段内容',
requiredMessage: '请输入相似度'
},
selectVectorization: {
label: '选择向量化内容',
error: '向量化未成功的分段',
all: '全部分段'
}
},
paragraph: {
title: '段落',
editParagraph: '编辑分段',
character_count: '个字符',
delete: {
confirmTitle: '是否删除分段:',
confirmMessage: '删除后将不会存入知识库,对本地文档无影响。'
},
relatedProblem: {
title: '关联问题',
placeholder: '请选择问题'
},
form: {
paragraphTitle: {
label: '分段标题',
placeholder: '请输入分段标题'
},
content: {
label: '分段内容',
placeholder: '请输入分段内容',
requiredMessage1: '请输入分段内容',
requiredMessage2: '内容最多不超过 100000 个字'
}
}
}
}

View File

@ -7,6 +7,7 @@ import functionLib from './function-lib';
import user from './user';
import team from './team';
import template from './template';
import document from './document';
export default {
notFound,
application,
@ -16,5 +17,6 @@ export default {
functionLib,
user,
team,
template
template,
document
};

View File

@ -14,6 +14,8 @@ export default {
submitSuccess: '提交成功',
edit: '編輯',
editSuccess: '編輯成功',
modify: '修改',
modifySuccess: '修改成功',
cancel: '取消',
confirm: '確認',
tip: '提示',
@ -35,7 +37,6 @@ export default {
paramSetting: '參數設定',
creator: '建立者',
debug: '調試',
modify: '修改',
required: '必填',
noData: '暂无数据',
status: {

View File

@ -1,5 +1,5 @@
<template>
<LayoutContainer header="上传文档" class="create-dataset">
<LayoutContainer :header="$t('views.document.uploadDocument')" class="create-dataset">
<template #backButton>
<back-button @click="back"></back-button>
</template>
@ -22,17 +22,23 @@
</div>
</div>
<div class="create-dataset__footer text-right border-t" v-if="active !== 2">
<el-button @click="router.go(-1)" :disabled="SetRulesRef?.loading || loading">{{$t('common.cancel')}}</el-button>
<el-button @click="prev" v-if="active === 1" :disabled="SetRulesRef?.loading || loading"
>上一步</el-button
>
<el-button @click="router.go(-1)" :disabled="SetRulesRef?.loading || loading">{{
$t('common.cancel')
}}</el-button>
<el-button @click="prev" v-if="active === 1" :disabled="SetRulesRef?.loading || loading">{{
$t('views.document.buttons.prev')
}}</el-button>
<el-button
@click="next"
type="primary"
v-if="active === 0"
:disabled="SetRulesRef?.loading || loading"
>
{{ documentsType === 'txt' ? '下一步' : '开始导入' }}
{{
documentsType === 'txt'
? $t('views.document.buttons.next')
: $t('views.document.buttons.import')
}}
</el-button>
<el-button
@click="submit"
@ -40,7 +46,7 @@
v-if="active === 1"
:disabled="SetRulesRef?.loading || loading"
>
开始导入
{{ $t('views.document.buttons.import') }}
</el-button>
</div>
</LayoutContainer>
@ -151,7 +157,7 @@ function submit() {
}
function back() {
if (documentsFiles.value?.length > 0) {
MsgConfirm(t('common.tip'), `当前的更改尚未保存,确认退出吗?`, {
MsgConfirm(t('common.tip'), t('views.document.tip.saveMessage'), {
confirmButtonText: t('common.confirm'),
type: 'warning'
})

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
title="编辑分段"
:title="$t('views.document.paragraph.editParagraph')"
v-model="dialogVisible"
width="80%"
destroy-on-close
@ -15,7 +15,7 @@
<el-col :span="6" class="border-l" style="width: 300px">
<p class="bold title p-24" style="padding-bottom: 0">
<span class="flex align-center">
<span>关联问题</span>
<span>{{ $t('views.document.paragraph.relatedProblem.title') }}</span>
<el-divider direction="vertical" class="mr-4" />
<el-button text @click="addProblem">
<el-icon><Plus /></el-icon>
@ -27,7 +27,7 @@
<el-input
v-if="isAddProblem"
v-model="problemValue"
placeholder="请选择问题"
:placeholder="$t('views.document.paragraph.relatedProblem.placeholder')"
@change="addProblemHandle"
@blur="isAddProblem = false"
ref="inputRef"
@ -56,8 +56,8 @@
<template #footer>
<span class="dialog-footer">
<el-button @click.prevent="dialogVisible = false"> {{$t('common.cancel')}} </el-button>
<el-button type="primary" @click="submitHandle"> {{$t('common.save')}} </el-button>
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submitHandle"> {{ $t('common.save') }} </el-button>
</span>
</template>
</el-dialog>

View File

@ -31,7 +31,9 @@
{{ child.content }}
</div>
<div class="lighter mt-12">
<el-text type="info"> {{ child.content.length }} 个字符 </el-text>
<el-text type="info">
{{ child.content.length }} {{ $t('views.document.paragraph.character_count') }}
</el-text>
</div>
</el-card>
</InfiniteScroll>
@ -48,6 +50,7 @@ import { cloneDeep } from 'lodash'
import { ref, computed } from 'vue'
import EditParagraphDialog from './EditParagraphDialog.vue'
import { MsgConfirm } from '@/utils/message'
import { t } from '@/locales'
const page_size = ref<number>(30)
const current_page = ref<number>(1)
const currentCIndex = ref<number>(0)
@ -78,10 +81,14 @@ const updateContent = (data: any) => {
}
const deleteHandle = (item: any, cIndex: number) => {
MsgConfirm(`是否删除分段:${item.title || '-'} ?`, `删除后将不会存入知识库,对本地文档无影响。`, {
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger'
})
MsgConfirm(
`${t('views.document.paragraph.delete.confirmTitle')}${item.title || '-'} ?`,
t('views.document.paragraph.delete.confirmMessage'),
{
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger'
}
)
.then(() => {
const new_value = [...props.modelValue]
new_value.splice(cIndex, 1)

View File

@ -9,7 +9,9 @@
</div>
</template>
<div class="mb-16">
<el-text type="info">{{ item.content.length }} 段落</el-text>
<el-text type="info"
>{{ item.content.length }} {{ $t('views.document.paragraph.title') }}</el-text
>
</div>
<div class="paragraph-list" v-if="activeName == index">
<el-scrollbar>

View File

@ -1,27 +1,31 @@
<template>
<el-scrollbar>
<el-result icon="success" title="🎉 知识库创建成功 🎉">
<el-result icon="success" :title="`🎉 ${$t('views.dataset.ResultSuccess.title')} 🎉`">
<template #sub-title>
<div class="mt-8">
<span class="bold">{{ data?.document_list.length || 0 }}</span>
<el-text type="info" class="ml-4">文档</el-text>
<el-text type="info" class="ml-4">{{ $t('common.document') }}</el-text>
<el-divider direction="vertical" />
<span class="bold">{{ paragraph_count || 0 }}</span>
<el-text type="info" class="ml-4">分段</el-text>
<el-text type="info" class="ml-4">{{
$t('views.dataset.ResultSuccess.paragraph')
}}</el-text>
<el-divider direction="vertical" />
<span class="bold">{{ numberFormat(char_length) || 0 }}</span>
<el-text type="info" class="ml-4">字符</el-text>
<el-text type="info" class="ml-4">{{ $t('common.character') }} </el-text>
</div>
</template>
<template #extra>
<el-button @click="router.push({ path: `/dataset` })">返回知识库列表</el-button>
<el-button type="primary" @click="router.push({ path: `/dataset/${data?.id}/document` })"
>前往文档</el-button
>
<el-button @click="router.push({ path: `/dataset` })">{{
$t('views.dataset.ResultSuccess.buttons.toDataset')
}}</el-button>
<el-button type="primary" @click="router.push({ path: `/dataset/${data?.id}/document` })">{{
$t('views.dataset.ResultSuccess.buttons.toDocument')
}}</el-button>
</template>
</el-result>
<div class="result-success">
<p class="bolder">文档列表</p>
<p class="bolder">{{ $t('views.dataset.ResultSuccess.documentList') }}</p>
<el-card
shadow="never"
class="file-List-card mt-8"
@ -37,7 +41,10 @@
</div>
</div>
<div>
<el-text type="info" class="mr-16">{{ item && item?.paragraph_count }} 个分段</el-text>
<el-text type="info" class="mr-16"
>{{ item && item?.paragraph_count }}
{{ $t('views.dataset.ResultSuccess.paragraph_count') }}</el-text
>
<el-text v-if="item.status === '1'">
<el-icon class="success"><SuccessFilled /></el-icon>
</el-text>
@ -45,7 +52,7 @@
<el-icon class="danger"><CircleCloseFilled /></el-icon>
</el-text>
<el-text v-else-if="item.status === '0'">
<el-icon class="is-loading primary"><Loading /></el-icon> ...
<el-icon class="is-loading primary"><Loading /></el-icon> {{ $t('views.dataset.ResultSuccess.loading') }}...
</el-text>
</div>
</div>

View File

@ -2,22 +2,24 @@
<div class="set-rules">
<el-row>
<el-col :span="10" class="p-24">
<h4 class="title-decoration-1 mb-16">设置分段规则</h4>
<h4 class="title-decoration-1 mb-16">{{ $t('views.document.setRules.title.setting') }}</h4>
<div class="set-rules__right">
<el-scrollbar>
<div class="left-height" @click.stop>
<el-radio-group v-model="radio" class="set-rules__radio">
<el-card shadow="never" class="mb-16" :class="radio === '1' ? 'active' : ''">
<el-radio value="1" size="large">
<p class="mb-4">智能分段推荐)</p>
<el-text type="info">不了解如何设置分段规则推荐使用智能分段</el-text>
<p class="mb-4">{{ $t('views.document.setRules.intelligent.label') }}</p>
<el-text type="info">{{
$t('views.document.setRules.intelligent.text')
}}</el-text>
</el-radio>
</el-card>
<el-card shadow="never" class="mb-16" :class="radio === '2' ? 'active' : ''">
<el-radio value="2" size="large">
<p class="mb-4">高级分段</p>
<el-text type="info"
>用户可根据文档规范自行设置分段标识符分段长度以及清洗规则
<p class="mb-4">{{ $t('views.document.setRules.advanced.label') }}</p>
<el-text type="info">
{{ $t('views.document.setRules.advanced.text') }}
</el-text>
</el-radio>
@ -30,10 +32,12 @@
<div class="set-rules__form">
<div class="form-item mb-16">
<div class="title flex align-center mb-8">
<span style="margin-right: 4px">分段标识</span>
<span style="margin-right: 4px">{{
$t('views.document.setRules.patterns.label')
}}</span>
<el-tooltip
effect="dark"
content="按照所选符号先后顺序做递归分割,分割结果超出分段长度将截取至分段长度。"
:content="$t('views.document.setRules.patterns.tooltip')"
placement="right"
>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
@ -46,7 +50,7 @@
allow-create
default-first-option
filterable
placeholder="请选择"
:placeholder="$t('views.document.setRules.patterns.placeholder')"
>
<el-option
v-for="(item, index) in splitPatternList"
@ -59,7 +63,9 @@
</div>
</div>
<div class="form-item mb-16">
<div class="title mb-8">分段长度</div>
<div class="title mb-8">
{{ $t('views.document.setRules.limit.label') }}
</div>
<el-slider
v-model="form.limit"
show-input
@ -69,10 +75,14 @@
/>
</div>
<div class="form-item mb-16">
<div class="title mb-8">自动清洗</div>
<div class="title mb-8">
{{ $t('views.document.setRules.with_filter.label') }}
</div>
<el-switch size="small" v-model="form.with_filter" />
<div style="margin-top: 4px">
<el-text type="info">去掉重复多余符号空格空行制表符</el-text>
<el-text type="info">
{{ $t('views.document.setRules.with_filter.text') }}</el-text
>
</div>
</div>
</div>
@ -82,19 +92,23 @@
</div>
</el-scrollbar>
<div>
<el-checkbox v-model="checkedConnect" @change="changeHandle" style="white-space: normal;">
导入时添加分段标题为关联问题适用于标题为问题的问答对
<el-checkbox
v-model="checkedConnect"
@change="changeHandle"
style="white-space: normal"
>
{{ $t('views.document.setRules.checkedConnect.label') }}
</el-checkbox>
</div>
<div class="text-right mt-8">
<el-button @click="splitDocument">生成预览</el-button>
<el-button @click="splitDocument"> {{ $t('views.document.setRules.buttons.preview') }}</el-button>
</div>
</div>
</el-col>
<el-col :span="14" class="p-24 border-l">
<div v-loading="loading">
<h4 class="title-decoration-1 mb-8">分段预览</h4>
<h4 class="title-decoration-1 mb-8">{{ $t('views.document.setRules.title.preview') }}</h4>
<ParagraphPreview v-model:data="paragraphList" :isConnect="checkedConnect" />
</div>

View File

@ -1,32 +1,32 @@
<template>
<el-dialog
title="同步知识库"
:title="$t('views.dataset.syncWeb.title')"
v-model="dialogVisible"
width="600px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
>
<p class="mb-8">同步方式</p>
<p class="mb-8">{{ $t('views.dataset.syncWeb.syncMethod') }}</p>
<el-radio-group v-model="method" class="card__radio">
<el-card shadow="never" class="mb-16" :class="method === 'replace' ? 'active' : ''">
<el-radio value="replace" size="large">
<p class="mb-4">替换同步</p>
<el-text type="info">重新获取 Web 站点文档覆盖替换本地知识库中的文档</el-text>
<p class="mb-4">{{ $t('views.dataset.syncWeb.replace') }}</p>
<el-text type="info">{{ $t('views.dataset.syncWeb.replaceText') }}</el-text>
</el-radio>
</el-card>
<el-card shadow="never" class="mb-16" :class="method === 'complete' ? 'active' : ''">
<el-radio value="complete" size="large">
<p class="mb-4">整体同步</p>
<el-text type="info">先删除本地知识库所有文档重新获取 Web 站点文档</el-text>
<p class="mb-4">{{ $t('views.dataset.syncWeb.complete') }}</p>
<el-text type="info">{{ $t('views.dataset.syncWeb.completeText') }}</el-text>
</el-radio>
</el-card>
</el-radio-group>
<p class="danger">注意所有同步都会删除已有数据重新获取新数据请谨慎操作</p>
<p class="danger">{{ $t('views.dataset.syncWeb.tip') }}</p>
<template #footer>
<span class="dialog-footer">
<el-button @click.prevent="dialogVisible = false"> {{$t('common.cancel')}} </el-button>
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submit" :loading="loading">
{{ $t('common.confirm') }}
</el-button>

View File

@ -1,5 +1,5 @@
<template>
<h4 class="title-decoration-1 mb-8">上传文档</h4>
<h4 class="title-decoration-1 mb-8">{{ $t('views.document.uploadDocument') }}</h4>
<el-form
ref="FormRef"
:model="form"
@ -9,9 +9,11 @@
>
<div class="mt-16 mb-16">
<el-radio-group v-model="form.fileType" @change="radioChange" class="app-radio-button-group">
<el-radio-button value="txt">文本文件</el-radio-button>
<el-radio-button value="table">表格</el-radio-button>
<el-radio-button value="QA">QA 问答对</el-radio-button>
<el-radio-button value="txt">{{ $t('views.document.fileType.txt.label') }}</el-radio-button>
<el-radio-button value="table">{{
$t('views.document.fileType.table.label')
}}</el-radio-button>
<el-radio-button value="QA">{{ $t('views.document.fileType.QA.label') }}</el-radio-button>
</el-radio-group>
</div>
@ -22,16 +24,18 @@
</div>
<div class="ml-16 lighter">
<p>
1点击下载对应模版并完善信息
{{ $t('views.document.fileType.QA.tip1') }}
<el-button type="primary" link @click="downloadTemplate('excel')">
下载 Excel 模版
{{ $t('views.document.upload.download') }} Excel
{{ $t('views.document.upload.template') }}
</el-button>
<el-button type="primary" link @click="downloadTemplate('csv')">
下载 CSV 模版
{{ $t('views.document.upload.download') }} CSV
{{ $t('views.document.upload.template') }}
</el-button>
</p>
<p>2上传的表格文件中每个 sheet 会作为一个文档sheet名称为文档名称</p>
<p>3每次最多上传 50 个文件每个文件不超过 100MB</p>
<p>{{ $t('views.document.fileType.QA.tip2') }}</p>
<p>{{ $t('views.document.fileType.QA.tip3') }}</p>
</div>
</div>
<el-upload
@ -52,12 +56,16 @@
<img src="@/assets/upload-icon.svg" alt="" />
<div class="el-upload__text">
<p>
拖拽文件至此上传或
<em class="hover" @click.prevent="handlePreview(false)"> 选择文件 </em>
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
{{ $t('views.document.upload.uploadMessage') }}
<em class="hover" @click.prevent="handlePreview(false)">
{{ $t('views.document.upload.selectFile') }}
</em>
<em class="hove ml-4" @click.prevent="handlePreview(true)">
{{ $t('views.document.upload.selectFiles') }}
</em>
</p>
<div class="upload__decoration">
<p>支持格式XLSXLSXCSVZIP</p>
<p>{{ $t('views.document.upload.formats') }}XLSXLSXCSVZIP</p>
</div>
</div>
</el-upload>
@ -69,17 +77,19 @@
</div>
<div class="ml-16 lighter">
<p>
1点击下载对应模版并完善信息
{{ $t('views.document.fileType.table.tip1') }}
<el-button type="primary" link @click="downloadTableTemplate('excel')">
下载 Excel 模版
{{ $t('views.document.upload.download') }} Excel
{{ $t('views.document.upload.template') }}
</el-button>
<el-button type="primary" link @click="downloadTableTemplate('csv')">
下载 CSV 模版
{{ $t('views.document.upload.download') }} CSV
{{ $t('views.document.upload.template') }}
</el-button>
</p>
<p>2第一行必须是列标题且列标题必须是有意义的术语表中每条记录将作为一个分段</p>
<p>3上传的表格文件中每个 sheet 会作为一个文档sheet名称为文档名称</p>
<p>4每次最多上传 50 个文件每个文件不超过 100MB</p>
<p>{{ $t('views.document.fileType.table.tip2') }}</p>
<p>{{ $t('views.document.fileType.table.tip3') }}</p>
<p>{{ $t('views.document.fileType.table.tip4') }}</p>
</div>
</div>
<el-upload
@ -100,12 +110,16 @@
<img src="@/assets/upload-icon.svg" alt="" />
<div class="el-upload__text">
<p>
拖拽文件至此上传或
<em class="hover" @click.prevent="handlePreview(false)"> 选择文件 </em>
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
{{ $t('views.document.upload.uploadMessage') }}
<em class="hover" @click.prevent="handlePreview(false)">
{{ $t('views.document.upload.selectFile') }}
</em>
<em class="hover ml-4" @click.prevent="handlePreview(true)">
{{ $t('views.document.upload.selectFiles') }}
</em>
</p>
<div class="upload__decoration">
<p>支持格式XLSXLSXCSVZIP</p>
<p>{{ $t('views.document.upload.formats') }}XLSXLSXCSVZIP</p>
</div>
</div>
</el-upload>
@ -116,8 +130,8 @@
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
</div>
<div class="ml-16 lighter">
<p>1文件上传前建议规范文件的分段标识</p>
<p>2每次最多上传 50 个文件每个文件不超过 100MB</p>
<p>{{ $t('views.document.fileType.table.tip1') }}</p>
<p>{{ $t('views.document.fileType.table.tip2') }}</p>
</div>
</div>
<el-upload
@ -138,12 +152,16 @@
<img src="@/assets/upload-icon.svg" alt="" />
<div class="el-upload__text">
<p>
拖拽文件至此上传或
<em class="hover" @click.prevent="handlePreview(false)"> 选择文件 </em>
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
{{ $t('views.document.upload.uploadMessage') }}
<em class="hover" @click.prevent="handlePreview(false)">
{{ $t('views.document.upload.selectFile') }}
</em>
<em class="hover ml-4" @click.prevent="handlePreview(true)">
{{ $t('views.document.upload.selectFiles') }}
</em>
</p>
<div class="upload__decoration">
<p>支持格式TXTMarkdownPDFDOCXHTMLXLSXLSXCSVZIP</p>
<p>{{ $t('views.document.upload.formats') }}TXTMarkdownPDFDOCXHTMLXLSXLSXCSVZIP</p>
</div>
</div>
</el-upload>
@ -179,6 +197,7 @@ import { filesize, getImgUrl, isRightType } from '@/utils/utils'
import { MsgError } from '@/utils/message'
import documentApi from '@/api/document'
import useStore from '@/stores'
import { t } from '@/locales'
const { dataset } = useStore()
const documentsFiles = computed(() => dataset.documentsFiles)
const documentsType = computed(() => dataset.documentsType)
@ -188,7 +207,7 @@ const form = ref({
})
const rules = reactive({
fileList: [{ required: true, message: '请上传文件', trigger: 'change' }]
fileList: [{ required: true, message: t('views.document.upload.requiredMessage'), trigger: 'change' }]
})
const FormRef = ref()
@ -198,11 +217,11 @@ watch(form.value, (value) => {
})
function downloadTemplate(type: string) {
documentApi.exportQATemplate(`${type}模版.${type == 'csv' ? type : 'xlsx'}`, type)
documentApi.exportQATemplate(`${type}${t('views.document.upload.template')}.${type == 'csv' ? type : 'xlsx'}`, type)
}
function downloadTableTemplate(type: string) {
documentApi.exportTableTemplate(`${type}模版.${type == 'csv' ? type : 'xlsx'}`, type)
documentApi.exportTableTemplate(`${type}${t('views.document.upload.template')}.${type == 'csv' ? type : 'xlsx'}`, type)
}
function radioChange() {
@ -218,24 +237,24 @@ const fileHandleChange = (file: any, fileList: UploadFiles) => {
//1100M
const isLimit = file?.size / 1024 / 1024 < 100
if (!isLimit) {
MsgError('文件大小超过 100MB')
MsgError(t('views.document.upload.errorMessage1'))
fileList.splice(-1, 1) //
return false
}
if (!isRightType(file?.name, form.value.fileType)) {
MsgError('文件格式不支持')
MsgError(t('views.document.upload.errorMessage2'))
fileList.splice(-1, 1)
return false
}
if (file?.size === 0) {
MsgError('文件不能为空')
MsgError(t('views.document.upload.errorMessage3'))
fileList.splice(-1, 1)
return false
}
}
const onExceed = () => {
MsgError('每次最多上传50个文件')
MsgError(t('views.document.upload.errorMessage4'))
}
const handlePreview = (bool: boolean) => {

View File

@ -1,13 +1,22 @@
<template>
<el-dialog v-model="dialogVisible" title="选择向量化内容" width="500" :before-close="close">
<el-dialog
v-model="dialogVisible"
:title="$t('views.document.form.selectVectorization.label')"
width="500"
:before-close="close"
>
<el-radio-group v-model="state">
<el-radio value="error" size="large">向量化未成功的分段</el-radio>
<el-radio value="all" size="large">全部分段</el-radio>
<el-radio value="error" size="large">{{
$t('views.document.form.selectVectorization.error')
}}</el-radio>
<el-radio value="all" size="large">{{
$t('views.document.form.selectVectorization.all')
}}</el-radio>
</el-radio-group>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submit"> 提交 </el-button>
<el-button @click="close">{{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submit"> {{ $t('common.submit') }} </el-button>
</div>
</template>
</el-dialog>

View File

@ -13,34 +13,43 @@
:model="form"
require-asterisk-position="right"
>
<el-form-item label="文档地址" prop="source_url" v-if="isImport">
<el-form-item
:label="$t('views.document.form.source_url.label')"
prop="source_url"
v-if="isImport"
>
<el-input
v-model="form.source_url"
placeholder="请输入文档地址,一行一个,地址不正确文档会导入失败。"
:placeholder="$t('views.document.form.source_url.placeholder')"
:rows="10"
type="textarea"
/>
</el-form-item>
<el-form-item
v-else-if="!isImport && documentType === '1'"
label="文档地址"
:label="$t('views.document.form.source_url.label')"
prop="source_url"
>
<el-input v-model="form.source_url" placeholder="请输入文档地址" />
<el-input
v-model="form.source_url"
:placeholder="$t('views.document.form.source_url.requiredMessage')"
/>
</el-form-item>
<el-form-item label="选择器" v-if="documentType === '1'">
<el-form-item :label="$t('views.document.form.selector.label')" v-if="documentType === '1'">
<el-input
v-model="form.selector"
placeholder="默认为 body可输入 .classname/#idname/tagname"
:placeholder="$t('views.document.form.selector.placeholder')"
/>
</el-form-item>
<el-form-item v-if="!isImport">
<template #label>
<div class="flex align-center">
<span class="mr-4">命中处理方式</span>
<span class="mr-4">{{
$t('views.document.form.hit_handling_method.requiredMessage')
}}</span>
<el-tooltip
effect="dark"
content="用户提问时,命中文档下的分段时按照设置的方式进行处理。"
:content="$t('views.document.form.hit_handling_method.tooltip')"
placement="right"
>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
@ -58,7 +67,7 @@
v-if="!isImport && form.hit_handling_method === 'directly_return'"
>
<div class="lighter w-full" style="margin-top: -20px">
<span>相似度高于</span>
<span>{{ $t('views.document.form.similarity.label') }}</span>
<el-input-number
v-model="form.directly_return_similarity"
:min="0"
@ -69,7 +78,7 @@
controls-position="right"
size="small"
class="ml-4 mr-4"
/><span></span>
/><span>{{ $t('views.document.form.similarity.placeholder') }}</span>
</div>
</el-form-item>
</el-form>
@ -90,7 +99,7 @@ import type { FormInstance } from 'element-plus'
import documentApi from '@/api/document'
import { MsgSuccess } from '@/utils/message'
import { hitHandlingMethod } from '@/enums/document'
import { t } from '@/locales'
const route = useRoute()
const {
params: { id }
@ -119,8 +128,20 @@ const documentType = ref<string | number>('') //文档类型1: web文档0:
const documentList = ref<Array<string>>([])
const rules = reactive({
source_url: [{ required: true, message: '请输入文档地址', trigger: 'blur' }],
directly_return_similarity: [{ required: true, message: '请输入相似度', trigger: 'blur' }]
source_url: [
{
required: true,
message: t('views.document.form.source_url.requiredMessage'),
trigger: 'blur'
}
],
directly_return_similarity: [
{
required: true,
message: t('views.document.form.similarity.requiredMessage'),
trigger: 'blur'
}
]
})
const dialogVisible = ref<boolean>(false)
@ -171,7 +192,7 @@ const submit = async (formEl: FormInstance | undefined) => {
selector: form.value.selector
}
documentApi.postWebDocument(id, obj, loading).then(() => {
MsgSuccess('导入成功')
MsgSuccess(t('views.document.tip.importMessage'))
emit('refresh')
dialogVisible.value = false
})
@ -186,7 +207,7 @@ const submit = async (formEl: FormInstance | undefined) => {
}
}
documentApi.putDocument(id, documentId.value, obj, loading).then(() => {
MsgSuccess('设置成功')
MsgSuccess(t('common.settingSuccess'))
emit('refresh')
dialogVisible.value = false
})
@ -198,7 +219,7 @@ const submit = async (formEl: FormInstance | undefined) => {
id_list: documentList.value
}
documentApi.batchEditHitHandling(id, obj, loading).then(() => {
MsgSuccess('设置成功')
MsgSuccess(t('common.settingSuccess'))
emit('refresh')
dialogVisible.value = false
})

View File

@ -1,6 +1,6 @@
<template>
<el-dialog
title="选择知识库"
:title="$t('views.dataset.selectDataset')"
v-model="dialogVisible"
width="600"
class="select-dataset-dialog"
@ -9,9 +9,9 @@
>
<template #header="{ titleId, titleClass }">
<div class="my-header flex">
<h4 :id="titleId" :class="titleClass">选择知识库</h4>
<h4 :id="titleId" :class="titleClass">{{$t('views.dataset.selectDataset')}}</h4>
<el-button link class="ml-16" @click="refresh">
<el-icon class="mr-4"><Refresh /></el-icon>
<el-icon class="mr-4"><Refresh /></el-icon>{{ $t('common.refresh') }}
</el-button>
</div>
</template>

View File

@ -42,6 +42,7 @@
import { computed, ref } from 'vue'
import { TaskType, State } from '@/utils/status'
import StatusTable from '@/views/document/component/StatusTable.vue'
import { t } from '@/locales'
const props = defineProps<{ status: string; statusMeta: any }>()
const visible = ref<boolean>(false)
const checkList: Array<string> = [
@ -65,22 +66,22 @@ const aggStatus = computed(() => {
return obj
})
const startedMap = {
[TaskType.EMBEDDING]: '索引中',
[TaskType.GENERATE_PROBLEM]: '生成中',
[TaskType.SYNC]: '同步中'
[TaskType.EMBEDDING]: t('views.document.fileStatus.EMBEDDING'),
[TaskType.GENERATE_PROBLEM]: t('views.document.fileStatus.GENERATE'),
[TaskType.SYNC]: t('views.document.fileStatus.SYNC')
}
const taskTypeMap = {
[TaskType.EMBEDDING]: '向量化',
[TaskType.GENERATE_PROBLEM]: '生成问题',
[TaskType.SYNC]: '同步'
[TaskType.EMBEDDING]: t('views.dataset.setting.vectorization'),
[TaskType.GENERATE_PROBLEM]: t('views.document.setting.generateQuestion'),
[TaskType.SYNC]: t('views.dataset.setting.sync')
}
const stateMap: any = {
[State.PENDING]: (type: number) => '排队中',
[State.PENDING]: (type: number) => t('views.document.fileStatus.PENDING'),
[State.STARTED]: (type: number) => startedMap[type],
[State.REVOKE]: (type: number) => '取消中',
[State.REVOKED]: (type: number) => '成功',
[State.FAILURE]: (type: number) => '失败',
[State.SUCCESS]: (type: number) => '成功'
[State.REVOKE]: (type: number) => t('views.document.fileStatus.REVOKE'),
[State.REVOKED]: (type: number) => t('views.document.fileStatus.SUCCESS'),
[State.FAILURE]: (type: number) => t('views.document.fileStatus.FAILURE'),
[State.SUCCESS]: (type: number) => t('views.document.fileStatus.SUCCESS'),
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<LayoutContainer header="文档" class="document-main">
<LayoutContainer :header="$t('common.document')" class="document-main">
<div class="main-calc-height">
<div class="p-24">
<div class="flex-between">
@ -8,28 +8,28 @@
v-if="datasetDetail.type === '0'"
type="primary"
@click="router.push({ path: '/dataset/upload', query: { id: id } })"
>上传文档</el-button
>
<el-button v-if="datasetDetail.type === '1'" type="primary" @click="importDoc"
>导入文档</el-button
>{{ $t('views.document.uploadDocument') }}</el-button
>
<el-button v-if="datasetDetail.type === '1'" type="primary" @click="importDoc">{{
$t('views.document.importDocument')
}}</el-button>
<el-button
@click="syncMulDocument"
:disabled="multipleSelection.length === 0"
v-if="datasetDetail.type === '1'"
>同步文档</el-button
>{{ $t('views.document.syncDocument') }}</el-button
>
<el-button @click="openDatasetDialog()" :disabled="multipleSelection.length === 0">
迁移
{{ $t('views.document.setting.migration') }}
</el-button>
<el-button @click="batchRefresh" :disabled="multipleSelection.length === 0">
向量化
{{ $t('views.dataset.setting.vectorization') }}
</el-button>
<el-button @click="openGenerateDialog()" :disabled="multipleSelection.length === 0">
生成问题
{{ $t('views.document.setting.generateQuestion') }}
</el-button>
<el-button @click="openBatchEditDocument" :disabled="multipleSelection.length === 0">
设置
{{ $t('common.setting') }}
</el-button>
<el-button @click="deleteMulDocument" :disabled="multipleSelection.length === 0">
{{ $t('common.delete') }}
@ -38,7 +38,7 @@
<el-input
v-model="filterText"
placeholder="按 文档名称 搜索"
:placeholder="$t('views.dataset.searchBar.placeholder')"
prefix-icon="Search"
class="w-240"
@change="getList"
@ -63,7 +63,7 @@
:storeKey="storeKey"
>
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column prop="name" label="文件名称" min-width="280">
<el-table-column prop="name" :label="$t('views.document.table.name')" min-width="280">
<template #default="{ row }">
<ReadWrite
@change="editName($event, row.id)"
@ -72,16 +72,28 @@
/>
</template>
</el-table-column>
<el-table-column prop="char_length" label="字符数" align="right">
<el-table-column
prop="char_length"
:label="$t('views.document.table.char_length')"
align="right"
>
<template #default="{ row }">
{{ numberFormat(row.char_length) }}
</template>
</el-table-column>
<el-table-column prop="paragraph_count" label="分段" align="right" />
<el-table-column prop="status" label="文件状态" width="130">
<el-table-column
prop="paragraph_count"
:label="$t('views.document.table.paragraph')"
align="right"
/>
<el-table-column
prop="status"
:label="$t('views.document.fileStatus.label')"
width="130"
>
<template #header>
<div>
<span>文件状态</span>
<span>{{ $t('views.document.fileStatus.label') }}</span>
<el-dropdown trigger="click" @command="dropdownHandle">
<el-button
style="margin-top: 1px"
@ -96,19 +108,19 @@
:class="filterMethod['status'] ? '' : 'is-active'"
:command="beforeCommand('status', '')"
class="justify-center"
>全部</el-dropdown-item
>{{ $t('views.document.table.all') }}</el-dropdown-item
>
<el-dropdown-item
:class="filterMethod['status'] === State.SUCCESS ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('status', State.SUCCESS)"
>成功</el-dropdown-item
>{{ $t('views.document.fileStatus.SUCCESS') }}</el-dropdown-item
>
<el-dropdown-item
:class="filterMethod['status'] === State.FAILURE ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('status', State.FAILURE)"
>失败</el-dropdown-item
>{{ $t('views.document.fileStatus.FAILURE') }}</el-dropdown-item
>
<el-dropdown-item
:class="
@ -119,13 +131,13 @@
"
class="justify-center"
:command="beforeCommand('status', State.STARTED, TaskType.EMBEDDING)"
>索引中</el-dropdown-item
>{{ $t('views.document.fileStatus.EMBEDDING') }}</el-dropdown-item
>
<el-dropdown-item
:class="filterMethod['status'] === State.PENDING ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('status', State.PENDING)"
>排队中</el-dropdown-item
>{{ $t('views.document.fileStatus.PENDING') }}</el-dropdown-item
>
<el-dropdown-item
:class="
@ -136,7 +148,7 @@
"
class="justify-center"
:command="beforeCommand('status', State.STARTED, TaskType.GENERATE_PROBLEM)"
>生成中</el-dropdown-item
>{{ $t('views.document.fileStatus.GENERATE') }}</el-dropdown-item
>
</el-dropdown-menu>
</template>
@ -150,7 +162,7 @@
<el-table-column width="130">
<template #header>
<div>
<span>启用状态</span>
<span>{{ $t('views.document.enableStatus.label') }}</span>
<el-dropdown trigger="click" @command="dropdownHandle">
<el-button
style="margin-top: 1px"
@ -165,19 +177,19 @@
:class="filterMethod['is_active'] === '' ? 'is-active' : ''"
:command="beforeCommand('is_active', '')"
class="justify-center"
>全部</el-dropdown-item
>{{ $t('views.document.table.all') }}</el-dropdown-item
>
<el-dropdown-item
:class="filterMethod['is_active'] === true ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('is_active', true)"
>开启</el-dropdown-item
>{{ $t('views.document.enableStatus.enable') }}</el-dropdown-item
>
<el-dropdown-item
:class="filterMethod['is_active'] === false ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('is_active', false)"
>关闭</el-dropdown-item
>{{ $t('views.document.enableStatus.close') }}</el-dropdown-item
>
</el-dropdown-menu>
</template>
@ -198,7 +210,7 @@
<el-table-column width="130">
<template #header>
<div>
<span>命中处理方式</span>
<span>{{ $t('views.document.form.hit_handling_method.label') }}</span>
<el-dropdown trigger="click" @command="dropdownHandle">
<el-button
style="margin-top: 1px"
@ -213,7 +225,7 @@
:class="filterMethod['hit_handling_method'] ? '' : 'is-active'"
:command="beforeCommand('hit_handling_method', '')"
class="justify-center"
>全部</el-dropdown-item
>{{ $t('views.document.table.all') }}</el-dropdown-item
>
<template v-for="(value, key) of hitHandlingMethod" :key="key">
<el-dropdown-item
@ -237,7 +249,11 @@
{{ datetimeFormat(row.create_time) }}
</template>
</el-table-column>
<el-table-column prop="update_time" label="更新时间" width="175">
<el-table-column
prop="update_time"
:label="$t('views.document.table.updateTime')"
width="175"
>
<template #default="{ row }">
{{ datetimeFormat(row.update_time) }}
</template>
@ -253,7 +269,7 @@
getTaskState(row.status, TaskType.EMBEDDING)
)
"
content="取消向量化"
:content="$t('views.document.setting.cancelVectorization')"
placement="top"
>
<el-button
@ -264,14 +280,19 @@
<AppIcon iconName="app-close" style="font-size: 16px"></AppIcon>
</el-button>
</el-tooltip>
<el-tooltip v-else effect="dark" content="向量化" placement="top">
<el-tooltip
v-else
effect="dark"
:content="$t('views.dataset.setting.vectorization')"
placement="top"
>
<el-button type="primary" text @click.stop="refreshDocument(row)">
<AppIcon iconName="app-document-refresh" style="font-size: 16px"></AppIcon>
</el-button>
</el-tooltip>
</span>
<span class="mr-4">
<el-tooltip effect="dark" content="设置" placement="top">
<el-tooltip effect="dark" :content="$t('common.setting')" placement="top">
<el-button type="primary" text @click.stop="settingDoc(row)">
<el-icon><Setting /></el-icon>
</el-button>
@ -293,23 +314,23 @@
@click="cancelTask(row, TaskType.GENERATE_PROBLEM)"
>
<el-icon><Connection /></el-icon>
取消生成问题
{{ $t('views.document.setting.cancelGenerateQuestion') }}
</el-dropdown-item>
<el-dropdown-item v-else @click="openGenerateDialog(row)">
<el-icon><Connection /></el-icon>
生成问题
{{ $t('views.document.setting.generateQuestion') }}
</el-dropdown-item>
<el-dropdown-item @click="openDatasetDialog(row)">
<AppIcon iconName="app-migrate"></AppIcon>
迁移
{{ $t('views.document.setting.migration') }}
</el-dropdown-item>
<el-dropdown-item @click="exportDocument(row)">
<AppIcon iconName="app-export"></AppIcon>
导出Excel
{{ $t('common.export') }}Excel
</el-dropdown-item>
<el-dropdown-item @click="exportDocumentZip(row)">
<AppIcon iconName="app-export"></AppIcon>
导出Zip
{{ $t('common.export') }}Zip
</el-dropdown-item>
<el-dropdown-item icon="Delete" @click.stop="deleteDocument(row)">{{
$t('common.delete')
@ -321,7 +342,11 @@
</div>
<div v-if="datasetDetail.type === '1'">
<span class="mr-4">
<el-tooltip effect="dark" content="同步" placement="top">
<el-tooltip
effect="dark"
:content="$t('views.dataset.setting.sync')"
placement="top"
>
<el-button type="primary" text @click.stop="syncDocument(row)">
<el-icon><Refresh /></el-icon>
</el-button>
@ -335,7 +360,7 @@
getTaskState(row.status, TaskType.EMBEDDING)
)
"
content="取消向量化"
:content="$t('views.document.setting.cancelVectorization')"
placement="top"
>
<el-button
@ -347,7 +372,12 @@
</el-button>
</el-tooltip>
<el-tooltip effect="dark" v-else content="向量化" placement="top">
<el-tooltip
effect="dark"
v-else
:content="$t('views.dataset.setting.vectorization')"
placement="top"
>
<el-button type="primary" text @click.stop="refreshDocument(row)">
<AppIcon iconName="app-document-refresh" style="font-size: 16px"></AppIcon>
</el-button>
@ -361,9 +391,9 @@
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="Setting" @click="settingDoc(row)"
>设置</el-dropdown-item
>
<el-dropdown-item icon="Setting" @click="settingDoc(row)">{{
$t('common.setting')
}}</el-dropdown-item>
<el-dropdown-item
v-if="
([State.STARTED, State.PENDING] as Array<string>).includes(
@ -373,23 +403,23 @@
@click="cancelTask(row, TaskType.GENERATE_PROBLEM)"
>
<el-icon><Connection /></el-icon>
取消生成问题
{{ $t('views.document.setting.cancelGenerateQuestion') }}
</el-dropdown-item>
<el-dropdown-item v-else @click="openGenerateDialog(row)">
<el-icon><Connection /></el-icon>
生成问题
{{ $t('views.document.setting.generateQuestion') }}
</el-dropdown-item>
<el-dropdown-item @click="openDatasetDialog(row)">
<AppIcon iconName="app-migrate"></AppIcon>
迁移</el-dropdown-item
{{ $t('views.document.setting.migration') }}</el-dropdown-item
>
<el-dropdown-item @click="exportDocument(row)">
<AppIcon iconName="app-export"></AppIcon>
导出Excel
{{ $t('common.export') }}Excel
</el-dropdown-item>
<el-dropdown-item @click="exportDocumentZip(row)">
<AppIcon iconName="app-export"></AppIcon>
导出Zip
{{ $t('common.export') }}Zip
</el-dropdown-item>
<el-dropdown-item icon="Delete" @click.stop="deleteDocument(row)">{{
$t('common.delete')
@ -412,15 +442,18 @@
</div>
<div class="mul-operation w-full flex" v-if="multipleSelection.length !== 0">
<el-button :disabled="multipleSelection.length === 0" @click="cancelTaskHandle(1)">
取消向量化
{{ $t('views.document.setting.cancelVectorization') }}
</el-button>
<el-button :disabled="multipleSelection.length === 0" @click="cancelTaskHandle(2)">
取消生成
{{ $t('views.document.setting.cancelGenerate') }}
</el-button>
<el-text type="info" class="secondary ml-24">
已选 {{ multipleSelection.length }}
{{ $t('views.document.selected') }} {{ multipleSelection.length }}
{{ $t('views.document.items') }}
</el-text>
<el-button class="ml-16" type="primary" link @click="clearSelection"> 清空 </el-button>
<el-button class="ml-16" type="primary" link @click="clearSelection">
{{ $t('common.clear') }}
</el-button>
</div>
<EmbeddingContentDialog ref="embeddingContentDialogRef"></EmbeddingContentDialog>
</LayoutContainer>
@ -442,6 +475,7 @@ import StatusVlue from '@/views/document/component/Status.vue'
import GenerateRelatedDialog from '@/components/generate-related-dialog/index.vue'
import EmbeddingContentDialog from '@/views/document/component/EmbeddingContentDialog.vue'
import { TaskType, State } from '@/utils/status'
import { t } from '@/locales'
const router = useRouter()
const route = useRoute()
const {
@ -496,14 +530,14 @@ const SelectDatasetDialogRef = ref()
const exportDocument = (document: any) => {
documentApi.exportDocument(document.name, document.dataset_id, document.id, loading).then(() => {
MsgSuccess('导出成功')
MsgSuccess(t('common.exportSuccess'))
})
}
const exportDocumentZip = (document: any) => {
documentApi
.exportDocumentZip(document.name, document.dataset_id, document.id, loading)
.then(() => {
MsgSuccess('导出成功')
MsgSuccess(t('common.exportSuccess'))
})
}
@ -519,7 +553,7 @@ function cancelTaskHandle(val: any) {
type: val
}
documentApi.batchCancelTask(id, obj, loading).then(() => {
MsgSuccess('批量取消成功')
MsgSuccess(t('views.document.tip.cancelSuccessMessage'))
multipleTableRef.value?.clearSelection()
})
}
@ -561,16 +595,16 @@ function beforeCommand(attr: string, val: any, task_type?: number) {
}
const cancelTask = (row: any, task_type: number) => {
documentApi.cancelTask(row.dataset_id, row.id, { type: task_type }).then(() => {
MsgSuccess('发送成功')
MsgSuccess(t('views.document.tip.sendMessage'))
})
}
function importDoc() {
title.value = '导入文档'
title.value = t('views.document.importDocument')
ImportDocumentDialogRef.value.open()
}
function settingDoc(row: any) {
title.value = '设置'
title.value = t('common.setting')
ImportDocumentDialogRef.value.open(row)
}
@ -579,7 +613,7 @@ const handleSelectionChange = (val: any[]) => {
}
function openBatchEditDocument() {
title.value = '设置'
title.value = t('common.setting')
const arr: string[] = multipleSelection.value.map((v) => v.id)
ImportDocumentDialogRef.value.open(null, arr)
}
@ -604,8 +638,8 @@ const closeInterval = () => {
function syncDocument(row: any) {
if (row.meta?.source_url) {
MsgConfirm(`确认同步文档?`, `同步将删除已有数据重新获取新数据,请谨慎操作。`, {
confirmButtonText: '同步',
MsgConfirm(t('views.document.sync.confirmTitle'), t('views.document.sync.confirmMessage1'), {
confirmButtonText: t('views.document.sync.label'),
confirmButtonClass: 'danger'
})
.then(() => {
@ -615,7 +649,7 @@ function syncDocument(row: any) {
})
.catch(() => {})
} else {
MsgConfirm(t('common.tip'), `无法同步,请先去设置文档 URL地址`, {
MsgConfirm(t('common.tip'), t('views.document.sync.confirmMessage2'), {
confirmButtonText: t('common.confirm'),
type: 'warning'
})
@ -666,15 +700,15 @@ function syncMulDocument() {
}
})
documentApi.delMulSyncDocument(id, arr, loading).then(() => {
MsgSuccess('同步文档成功')
MsgSuccess(t('views.document.sync.successMessage'))
getList()
})
}
function deleteMulDocument() {
MsgConfirm(
`是否批量删除 ${multipleSelection.value.length} 个文档?`,
`所选文档中的分段会跟随删除,请谨慎操作。`,
`${t('views.document.delete.confirmTitle1')} ${multipleSelection.value.length} ${t('views.document.delete.confirmTitle2')}`,
t('views.document.delete.confirmMessage'),
{
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger'
@ -688,7 +722,7 @@ function deleteMulDocument() {
}
})
documentApi.delMulDocument(id, arr, loading).then(() => {
MsgSuccess('批量删除成功')
MsgSuccess(t('views.document.delete.successMessage'))
multipleTableRef.value?.clearSelection()
getList()
})
@ -700,7 +734,7 @@ function batchRefresh() {
const arr: string[] = multipleSelection.value.map((v) => v.id)
const embeddingBatchDocument = (stateList: Array<string>) => {
documentApi.batchRefresh(id, arr, stateList, loading).then(() => {
MsgSuccess('批量向量化成功')
MsgSuccess(t('views.document.tip.vectorizationSuccessMessage'))
multipleTableRef.value?.clearSelection()
})
}
@ -709,8 +743,8 @@ function batchRefresh() {
function deleteDocument(row: any) {
MsgConfirm(
`是否删除文档:${row.name} ?`,
`此文档下的 ${row.paragraph_count} 个分段都会被删除,请谨慎操作。`,
`${t('views.document.delete.confirmTitle3')} ${row.name} ?`,
`${t('views.document.delete.confirmMessage1')} ${row.paragraph_count} ${t('views.document.delete.confirmMessage2')}`,
{
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger'
@ -746,7 +780,7 @@ function changeState(row: any) {
const obj = {
is_active: !row.is_active
}
const str = !row.is_active ? '启用成功' : '禁用成功'
const str = !row.is_active ? t('common.status.enableSuccess') : t('common.status.disableSuccess')
currentMouseId.value && updateData(row.id, obj, str)
}
@ -755,9 +789,9 @@ function editName(val: string, id: string) {
const obj = {
name: val
}
updateData(id, obj, '修改成功')
updateData(id, obj, t('common.modifySuccess'))
} else {
MsgError('文件名称不能为空!')
MsgError(t('views.document.tip.nameMessage'))
}
}

View File

@ -7,22 +7,22 @@
:rules="rules"
@submit.prevent
>
<el-form-item label="分段标题">
<el-form-item :label="$t('views.document.paragraph.form.paragraphTitle.label')">
<el-input
v-if="isEdit"
v-model="form.title"
placeholder="请输入分段标题"
:placeholder="$t('views.document.paragraph.form.paragraphTitle.placeholder')"
maxlength="256"
show-word-limit
>
</el-input>
<span class="lighter" v-else>{{ form.title || '-' }}</span>
</el-form-item>
<el-form-item label="分段内容" prop="content">
<el-form-item :label="$t('views.document.paragraph.form.content.label')" prop="content">
<MdEditor
v-if="isEdit"
v-model="form.content"
placeholder="请输入分段内容"
:placeholder="$t('views.document.paragraph.form.content.placeholder')"
:maxLength="100000"
:preview="false"
:toolbars="toolbars"
@ -48,6 +48,7 @@
import { ref, reactive, onUnmounted, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import imageApi from '@/api/image'
import { t } from '@/locales'
const props = defineProps({
data: {
type: Object,
@ -97,8 +98,8 @@ const form = ref<any>({
const rules = reactive<FormRules>({
content: [
{ required: true, message: '请输入分段内容', trigger: 'blur' },
{ max: 100000, message: '内容最多不超过 100000 个字', trigger: 'blur' }
{ required: true, message: t('views.document.paragraph.form.content.requiredMessage1'), trigger: 'blur' },
{ max: 100000, message: t('views.document.paragraph.form.content.requiredMessage2'), trigger: 'blur' }
]
})

View File

@ -1,7 +1,7 @@
<template>
<p class="bold title p-24" style="padding-bottom: 0">
<span class="flex align-center">
<span>关联问题</span>
<span>{{ $t('views.document.paragraph.relatedProblem.title') }}</span>
<el-divider direction="vertical" class="mr-4" />
<el-button text @click="addProblem">
<el-icon><Plus /></el-icon>
@ -18,7 +18,7 @@
allow-create
default-first-option
:reserve-keyword="false"
placeholder="请选择问题"
:placeholder="$t('views.document.paragraph.relatedProblem.placeholder')"
remote
:remote-method="remoteMethod"
:loading="optionLoading"

View File

@ -65,8 +65,10 @@
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click.prevent="dialogVisible = false"> {{$t('common.cancel')}} </el-button>
<el-button type="primary" @click="submitForm(formRef)" :loading="loading"> 迁移 </el-button>
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submitForm(formRef)" :loading="loading">
{{ $t('views.document.setting.migration') }}
</el-button>
</span>
</template>
</el-dialog>

View File

@ -124,11 +124,11 @@
<el-dropdown-menu>
<el-dropdown-item @click="openGenerateDialog(item)">
<el-icon><Connection /></el-icon>
生成问题</el-dropdown-item
{{ $t('views.document.setting.generateQuestion') }}</el-dropdown-item
>
<el-dropdown-item @click="openSelectDocumentDialog(item)">
<AppIcon iconName="app-migrate"></AppIcon>
迁移</el-dropdown-item
{{$t('views.document.setting.migration')}}</el-dropdown-item
>
<el-dropdown-item icon="Delete" @click.stop="deleteParagraph(item)">{{
$t('common.delete')
@ -148,10 +148,10 @@
<div class="mul-operation border-t w-full" v-if="isBatch === true">
<el-button :disabled="multipleSelection.length === 0" @click="openGenerateDialog()">
生成问题
{{ $t('views.document.setting.generateQuestion') }}
</el-button>
<el-button :disabled="multipleSelection.length === 0" @click="openSelectDocumentDialog()">
迁移
{{$t('views.document.setting.migration')}}
</el-button>
<el-button :disabled="multipleSelection.length === 0" @click="deleteMulParagraph">