| | |
| | | <template> |
| | | <div class="h100 overflow-y-auto p-[16px]"> |
| | | <div class="mb-[10px] flex items-center"> |
| | | <div class="flex flex-col h100"> |
| | | <div class="mb-[10px] flex flex-shrink-0 items-center"> |
| | | <el-button style="margin-left: 8px; width: 40px" text @click="handleExitFlow"> |
| | | <el-icon style="font-size: 24px !important"> |
| | | <ArrowLeft /> |
| | |
| | | </el-button> |
| | | <span class="text-[24px] text-[#26244c] font-[700]">{{ state.detailTitle }}</span> |
| | | </div> |
| | | <div class="relative"> |
| | | <div class="relative transition-[opacity 0.3s]"> |
| | | <div class="set-form-height"> |
| | | <div class="flex flex-col"> |
| | | <el-form :model="state.categoryForm" label-width="120px" label-position="left"> |
| | | <el-form-item label="导入类目:"> |
| | | <label>{{ state.categoryForm.ImportCategory }}</label> |
| | | </el-form-item> |
| | | <el-form-item label="类目类型:"> |
| | | <label>{{ state.categoryForm.CategoryType }}</label> |
| | | </el-form-item> |
| | | <el-form-item label="导入方式:"> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | v-model:file-list="fileList" |
| | | class="upload-demo w-[530px]" |
| | | drag |
| | | :multiple="true" |
| | | :auto-upload="false" |
| | | :accept="state.allowType" |
| | | :limit="state.limit" |
| | | :before-upload="beforeAvatarUpload" |
| | | > |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text"> |
| | | <em>点击或拖拽上传文件</em> |
| | | </div> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | 支持格式:{{ state.allowType }};限制大小{{ state.size }}M,最多上传{{ state.limit }}个文件 |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | <el-form-item label="文档识别:"> |
| | | <div |
| | | class="bg-[#f6f5ff] border-[1px] border-solid border-[#0062be] py-[12px] w-[215px] px-[16px] rounded-lg cursor-pointer" |
| | | > |
| | | <el-radio-group v-model="state.categoryForm.DocumentRecognition"> |
| | | <el-radio value="1" size="large"> |
| | | <span class="font-[700] text[14px]">文档智能解析</span> |
| | | </el-radio> |
| | | </el-radio-group> |
| | | <el-tooltip :content="state.demoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="set-form-height" v-show="!state.showKnowledgeForm"> |
| | | <el-form |
| | | :model="state.knowledgeForm" |
| | | label-width="120px" |
| | | label-position="left" |
| | | ref="knowledgeFormRef" |
| | | :rules="knowledgeFormRules" |
| | | > |
| | | <el-divider content-position="left"><span class="text-[18px] font-[500]">知识库基础信息</span></el-divider> |
| | | <el-form-item label="知识库名称:" prop="title"> |
| | | <el-input |
| | | v-model="state.knowledgeForm.title" |
| | | style="width: 532px" |
| | | maxlength="20" |
| | | placeholder="请输入知识库名称" |
| | | show-word-limit |
| | | type="text" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="知识库描述:" prop="prompt"> |
| | | <el-input |
| | | v-model="state.knowledgeForm.prompt" |
| | | maxlength="1000" |
| | | style="width: 532px" |
| | | placeholder="请输入知识库描述。对知识库包含的内容和数据的用途进行描述。" |
| | | show-word-limit |
| | | :rows="5" |
| | | type="textarea" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="数据类型:"> |
| | | <div v-for="(item, index) in state.dataTypeList" :key="index"> |
| | | <div |
| | | class="bg-[#fff] border-[1px] border-solid border-[#d8d9e6] py-[12px] w-[215px] mr-[10px] px-[16px] rounded-lg cursor-pointer" |
| | | :class="{ activeColor: state.knowledgeForm.dataType === item.ID }" |
| | | @click="activeDataType(item.ID)" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="data_left"> |
| | | <img :src="item.ImageURL" class="w-[40px] h-[40px] mr-[10px]" /> |
| | | </div> |
| | | <div class="data_right"> |
| | | <el-radio v-model="state.knowledgeForm.dataType" size="large" :label="item.ID"> |
| | | <span class="font-[500] text[16px]">{{ item.Name }}</span> |
| | | </el-radio> |
| | | |
| | | <el-tooltip :content="item.DemoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="text-[#878aab] text-[12px] mx-0 mt-[2px] mb-0 set-desc"> |
| | | {{ state.demoDesc }} |
| | | {{ item.DemoDesc }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="set-form-footer"> |
| | | <el-button type="primary" @click="onSubmit">确 认</el-button> |
| | | <el-button>取消</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | <el-divider content-position="left"><span class="text-[18px]">知识库配置</span></el-divider> |
| | | <el-form-item label="配置模式:"> |
| | | <div class="flex-auto flex flex-col"> |
| | | <div class="flex"> |
| | | <div v-for="(item, index) in state.configurationList" :key="index"> |
| | | <div |
| | | class="bg-[#fff] border-[1px] border-solid border-[#d8d9e6] py-[12px] w-[215px] mr-[10px] px-[16px] rounded-lg cursor-pointer" |
| | | :class="{ activeColor: state.knowledgeForm.configurationMode === item.ID }" |
| | | @click="activeConfigurationType(item.ID)" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="data_left"> |
| | | <img :src="item.ImageURL" class="w-[40px] h-[40px] mr-[10px]" /> |
| | | </div> |
| | | <div class="data_right"> |
| | | <el-radio v-model="state.knowledgeForm.configurationMode" size="large" :label="item.ID"> |
| | | <span class="font-[500] text[16px]">{{ item.Name }}</span> |
| | | </el-radio> |
| | | |
| | | <el-tooltip :content="item.DemoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="text-[#878aab] text-[12px] mx-0 mt-[2px] mb-0 set-desc"> |
| | | {{ item.DemoDesc }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="set_model_desc"> |
| | | <div v-for="(item, index) in state.modeList" :key="index"> |
| | | <div class="flex items-center mb-[16px]"> |
| | | <div class="relative w-[148px] text-[14px] text-[#26244c]">{{ item.Name }}</div> |
| | | <div class="text-[14px] text-[#26244c]" :class="`min-w-[${item.NameFnWidthStyle}]`">{{ item.NameFn }}</div> |
| | | <div v-show="item.ID == 3"> |
| | | <div class="min-w-[148px] text-[14px] text-[#26244c]">{{ item.NameOrder }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="set-form-height" v-show="state.showKnowledgeForm"> |
| | | <el-form |
| | | :model="state.knowledgeFile" |
| | | label-width="120px" |
| | | label-position="left" |
| | | ref="knowledgeFileRef" |
| | | :rules="knowledgeFormRules" |
| | | > |
| | | <el-divider content-position="left"><span class="text-[18px] font-[500]">选择文件</span></el-divider> |
| | | |
| | | <el-divider content-position="left"><span class="text-[18px]">数据处理</span></el-divider> |
| | | <el-form-item label="配置模式:"> |
| | | <div class="flex-auto flex flex-col"> |
| | | <div class="flex"> |
| | | <div v-for="(item, index) in state.configurationList" :key="index"> |
| | | <div |
| | | class="bg-[#fff] border-[1px] border-solid border-[#d8d9e6] py-[12px] w-[215px] mr-[10px] px-[16px] rounded-lg cursor-pointer" |
| | | :class="{ activeColor: state.knowledgeForm.configurationMode === item.ID }" |
| | | @click="activeConfigurationType(item.ID)" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="data_left"> |
| | | <img :src="item.ImageURL" class="w-[40px] h-[40px] mr-[10px]" /> |
| | | </div> |
| | | <div class="data_right"> |
| | | <el-radio v-model="state.knowledgeForm.configurationMode" size="large" :label="item.ID"> |
| | | <span class="font-[500] text[16px]">{{ item.Name }}</span> |
| | | </el-radio> |
| | | |
| | | <el-tooltip :content="item.DemoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="text-[#878aab] text-[12px] mx-0 mt-[2px] mb-0 set-desc"> |
| | | {{ item.DemoDesc }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="set_model_desc"> |
| | | <div v-for="(item, index) in state.modeList" :key="index"> |
| | | <div class="flex items-center mb-[16px]"> |
| | | <div class="relative w-[148px] text-[14px] text-[#26244c]">{{ item.Name }}</div> |
| | | <div class="text-[14px] text-[#26244c]" :class="`min-w-[${item.NameFnWidthStyle}]`">{{ item.NameFn }}</div> |
| | | <div v-show="item.ID == 3"> |
| | | <div class="min-w-[148px] text-[14px] text-[#26244c]">{{ item.NameOrder }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="set-form-footer"> |
| | | <div v-show="!state.showKnowledgeForm"> |
| | | <el-button type="primary" @click="nextKnowledge">下一步</el-button> |
| | | <el-button @click="emptyKnowledgeBase">创建空知识库</el-button> |
| | | </div> |
| | | <div v-show="state.showKnowledgeForm"> |
| | | <el-button @click="importCompleted" type="primary">导入完成</el-button> |
| | | <el-button @click="backKnowledge" v-show="state.showKnowledgeForm">上一步</el-button> |
| | | </div> |
| | | <el-button @click="handleExitFlow">取消</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import type { UploadUserFile } from 'element-plus'; |
| | | import { ElMessage, ElMessage } from 'element-plus'; |
| | | import { ElMessage, type FormRules } from 'element-plus'; |
| | | import moment from 'moment'; |
| | | import { reactive, ref } from 'vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import { add_docvector_name } from '/@/api/knowledge/docvector'; |
| | | import mittBus from '/@/utils/mitt'; |
| | | // 定义变量内容 |
| | | const state = reactive({ |
| | | detailTitle: '导入数据', |
| | | categoryForm: { |
| | | ImportCategory: '默认类目', |
| | | CategoryType: '本地类目', |
| | | DocumentRecognition: '1', |
| | | soliderValue: 0, |
| | | detailTitle: '创建知识库', |
| | | knowledgeForm: { |
| | | title: '', |
| | | prompt: '', |
| | | dataType: 1, |
| | | configurationMode: 1, |
| | | }, |
| | | allowType: '.pdf,.doc,.docx,.txt,.md,.pptx,.ppt', |
| | | limit: 5, |
| | | size: 5, |
| | | demoDesc: '使用阿里云文档智能解析服务据解析文档,抽取文档内容、层级结构等信息。', |
| | | knowledgeFile: {}, |
| | | dataTypeList: [ |
| | | { |
| | | ID: 1, |
| | | Name: '非结构化数据', |
| | | ImageURL: 'static/images/knowledge/data_type_1.png', |
| | | DemoDesc: '选择数据管理功能中已上传的doc、pdf、md、txt等文件', |
| | | }, |
| | | { |
| | | ID: 2, |
| | | Name: '结构化数据', |
| | | ImageURL: 'static/images/knowledge/data_type_2.png', |
| | | DemoDesc: '选择数据管理功能中已创建的数据表', |
| | | }, |
| | | ], |
| | | configurationList: [ |
| | | { |
| | | ID: 1, |
| | | Name: '推荐配置', |
| | | ImageURL: 'static/images/knowledge/data_type_3.png', |
| | | DemoDesc: '百炼推荐配置,在效果、推理成本、检索时延等方面的最佳实践', |
| | | }, |
| | | { |
| | | ID: 3, |
| | | Name: '自定义', |
| | | ImageURL: 'static/images/knowledge/data_type_4.png', |
| | | DemoDesc: '完全开放的离线知识库配置,按照检索需求自由配置,获得推理效果和时延方面的不同体验', |
| | | }, |
| | | ], |
| | | modeList: [ |
| | | { |
| | | ID: 1, |
| | | Name: '多轮对话改写', |
| | | NameFn: '开启', |
| | | NameOrder: null, |
| | | NameFnWidthStyle: '380px', |
| | | }, |
| | | { |
| | | ID: 2, |
| | | Name: 'Embedding模型', |
| | | NameFn: '官方向量', |
| | | NameOrder: null, |
| | | NameFnWidthStyle: '380px', |
| | | }, |
| | | { |
| | | ID: 3, |
| | | Name: '排序配置', |
| | | NameFn: 'Rank模型', |
| | | NameOrder: '官方排序', |
| | | NameFnWidthStyle: '148px', |
| | | }, |
| | | { |
| | | ID: 4, |
| | | Name: '', |
| | | NameFn: '相似度阈值', |
| | | NameOrder: null, |
| | | NameFnWidthStyle: '148px', |
| | | }, |
| | | ], |
| | | showKnowledgeForm: false, |
| | | }); |
| | | const fileList = ref<UploadUserFile[]>([]); |
| | | const knowledgeFormRules = reactive<FormRules>({ |
| | | title: [ |
| | | { |
| | | required: true, |
| | | message: '必填项', |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | prompt: [ |
| | | { |
| | | required: true, |
| | | message: '必填项', |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }); |
| | | const knowledgeFormRef = ref(); |
| | | const router = useRouter(); |
| | | //返回 |
| | | const handleExitFlow = () => { |
| | | //是否显示返回 |
| | | router.back(); |
| | | //清空表单 |
| | | knowledgeFormRef.value.resetFields(); |
| | | state.showKnowledgeForm = false; |
| | | }; |
| | | const flag = ref(true); |
| | | const beforeAvatarUpload = () => { |
| | | fileList.value.forEach((item: any) => { |
| | | console.log(item); |
| | | const type = item.name.split('.')[1]; |
| | | if (state.allowType.indexOf(type) == -1) { |
| | | ElMessage({ |
| | | type: 'error', |
| | | message: `格式错误,支持格式:${state.allowType}!`, |
| | | }); |
| | | flag.value = false; |
| | | return; |
| | | } else if (item.size / 1024 / 1024 > state.size) { |
| | | ElMessage.error(`文件最大${state.size}MB!`); |
| | | flag.value = false; |
| | | return; |
| | | } |
| | | }); |
| | | return flag.value; |
| | | //选择数据类型 |
| | | const activeDataType = (id: number) => { |
| | | state.knowledgeForm.dataType = id; |
| | | }; |
| | | //确认 |
| | | const onSubmit = () => {}; |
| | | //选择配置模式 |
| | | const activeConfigurationType = (id: number) => { |
| | | state.knowledgeForm.configurationMode = id; |
| | | }; |
| | | //下一步 |
| | | const nextKnowledge = async () => { |
| | | const valid = await knowledgeFormRef.value.validate().catch(() => {}); |
| | | if (!valid) return; |
| | | state.showKnowledgeForm = true; |
| | | }; |
| | | const backKnowledge = () => { |
| | | state.showKnowledgeForm = false; |
| | | }; |
| | | //创建一个空知识库 |
| | | const emptyKnowledgeBase = async () => { |
| | | var currentTime = moment().format('YYYY-MM-DD HH:mm:ss'); |
| | | const valid = await knowledgeFormRef.value.validate().catch(() => {}); |
| | | if (!valid) return; |
| | | const res = await add_docvector_name({ title: state.knowledgeForm.title, prompt: state.knowledgeForm.prompt }); |
| | | if (res.json_ok) { |
| | | ElMessage.success('创建成功'); |
| | | let obj = { |
| | | id: res.knowlg_id, |
| | | title: state.knowledgeForm.title, |
| | | prompt: state.knowledgeForm.prompt, |
| | | publish: '', |
| | | create_time: currentTime, |
| | | user_name: '', |
| | | }; |
| | | mittBus.emit('addKnowledgeBaseObj', obj); |
| | | router.push({ name: 'Knowledge' }); |
| | | } |
| | | }; |
| | | const importCompleted = () => { |
| | | return; |
| | | ElMessage.success('导入完成'); |
| | | router.push({ name: 'Knowledge' }); |
| | | }; |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .set-form-height { |
| | | height: calc(100% - 62px); |
| | | background: #fff; |
| | | border-radius: 16px 16px 0 0; |
| | | border-radius: 12px 12px 0 0; |
| | | flex: 1; |
| | | margin: 0 24px 64px; |
| | | margin: 0 24px; |
| | | overflow-y: auto; |
| | | padding: 20px; |
| | | padding: 20px 16px; |
| | | height: 100%; |
| | | } |
| | | .set-desc { |
| | | -webkit-line-clamp: 2; |
| | |
| | | gap: 8px; |
| | | height: 64px; |
| | | padding-left: 24px; |
| | | position: fixed; |
| | | // position: fixed; |
| | | width: 100%; |
| | | left: 220px; |
| | | } |
| | | |
| | | .activeColor { |
| | | border-color: #0062be; |
| | | background-color: #f6f5ff; |
| | | } |
| | | .set_model_desc { |
| | | background: #f7f8fe; |
| | | border-radius: 8px; |
| | | margin-top: 12px; |
| | | padding: 16px 24px; |
| | | } |
| | | .slider-demo-block { |
| | | max-width: 600px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | </style> |
| | | <style> |
| | | .set_tooltip_demo { |