yangyin
2024-09-02 c823e4a5e812af32f959542cfed4eab11c01d89b
src/views/project/yw/dataManage/knowledge/AddKnowledge.vue
@@ -1,6 +1,6 @@
<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 />
@@ -8,126 +8,330 @@
         </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;
@@ -149,10 +353,26 @@
   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 {