wujingjing
2024-09-05 bd7247878bf5258bf5c1f9deefbfa6c9ade066e3
Merge branch 'master' of http://47.103.154.90:83/r/WI/Web.Admin.V1.0
已修改3个文件
286 ■■■■ 文件已修改
src/api/knowledge/docvector.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/dataManage/knowledge/AddKnowledge.vue 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/dataManage/knowledge/EditKnowledge.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/knowledge/docvector.ts
@@ -39,3 +39,13 @@
        data: params,
    });
};
/**
 * @summary description 获取文件列表
 */
export const get_docvector_file_list = async (params) => {
    return request({
        url: '/admin/docvector/get_docvector_file_list',
        method: 'POST',
        data: params,
    });
};
src/views/project/yw/dataManage/knowledge/AddKnowledge.vue
@@ -113,19 +113,70 @@
                :model="state.knowledgeFile"
                label-width="120px"
                label-position="left"
                class="h100"
                ref="knowledgeFileRef"
                :rules="knowledgeFormRules"
            >
                <el-divider content-position="left"><span class="text-[18px] font-[500]">选择文件</span></el-divider>
                <div class="flex items-start gap-[16px] max-h-[686px] min-h-[360px] set-file-height">
                    <div class="min-h-[360px] h100 set_file_left">
                        <div class="font-[500] mb-2">请选择文档</div>
                        <div class="left_content">
                            <div class="file_menu">
                                <LeftTreeByMgr
                                    title-name="类目"
                                    ref="leftTreeRef"
                                    :treedata="state.knowledgeBaseData"
                                    :current-node-key="currentListID"
                                    :defaultProps="{
                                        children: 'Children',
                                        label: 'title',
                                        id: 'id',
                                    }"
                                    @click="handleClickNode"
                                >
                                </LeftTreeByMgr>
                            </div>
                            <div class="file_table">
                                <el-table
                                    :data="state.fileData"
                                    border
                                    @select="handleSelectItem"
                                    highlight-current-row
                                    ref="multipleTableRef"
                                    :class="{ 'hidden-checkbox-all': state.isRadio }"
                                    @select-all="
                                        (selection) => {
                                            handleSelectAll(selection, state.fileData);
                                        }
                                    "
                                >
                                    <el-table-column type="selection" width="55" />
                                    <el-table-column prop="name" label="文件名称" />
                                </el-table>
                            </div>
                        </div>
                    </div>
                    <div class="set_file_right">
                        <div class="h100">
                            <div class="font-[500] mb-[12px]">已选文档{{ multipleSelection.length }}/50个</div>
                            <div class="selected_file">
                                <div v-for="(item, index) in multipleSelection" :key="index" class="set_file_item">
                                    <span class="set_file_name">{{ item.name }}</span>
                                    <span class="ywifont ywicon-guanbi set_file_close" @click="handleRemoveItem(item)"></span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <el-divider content-position="left"><span class="text-[18px]">数据处理</span></el-divider>
                <el-form-item label="配置模式:">
                <el-form-item label="文档切分chunk:">
                    <div class="flex-auto flex flex-col">
                        <div class="flex">
                            <div v-for="(item, index) in state.configurationList" :key="index">
                            <div v-for="(item, index) in state.segmentationList" :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 }"
                                    :class="{ activeColor: state.knowledgeForm.segmentationMode === item.ID }"
                                    @click="activeConfigurationType(item.ID)"
                                >
                                    <div class="flex items-center">
@@ -133,7 +184,7 @@
                                            <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">
                                            <el-radio v-model="state.knowledgeForm.segmentationMode" size="large" :label="item.ID">
                                                <span class="font-[500] text[16px]">{{ item.Name }}</span>
                                            </el-radio>
@@ -168,10 +219,13 @@
<script setup lang="ts">
import { ElMessage, type FormRules } from 'element-plus';
import moment from 'moment';
import { reactive, ref } from 'vue';
import { computed, nextTick, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { add_docvector_name } from '/@/api/knowledge/docvector';
import { get_knowledge_group_list, list_knowledge_file } from '/@/api/knowledge/group';
import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue';
import mittBus from '/@/utils/mitt';
import { convertListToTree } from '/@/utils/util';
// 定义变量内容
const state = reactive({
    soliderValue: 0,
@@ -181,6 +235,7 @@
        prompt: '',
        dataType: 1,
        configurationMode: 1,
        segmentationMode: 1,
    },
    knowledgeFile: {},
    dataTypeList: [
@@ -196,7 +251,7 @@
            ImageURL: 'static/images/knowledge/data_type_2.png',
            DemoDesc: '选择数据管理功能中已创建的数据表',
        },
    ],
    ], //数据类型
    configurationList: [
        {
            ID: 1,
@@ -209,6 +264,20 @@
            Name: '自定义',
            ImageURL: 'static/images/knowledge/data_type_4.png',
            DemoDesc: '完全开放的离线知识库配置,按照检索需求自由配置,获得推理效果和时延方面的不同体验',
        },
    ], //配置模式
    segmentationList: [
        {
            ID: 1,
            Name: '智能切分',
            ImageURL: 'static/images/knowledge/data_type_3.png',
            DemoDesc: '在通用文档上的最优chunk切分方法,经过评测可在多数文档上获得最佳的检索效果',
        },
        {
            ID: 3,
            Name: '自定义切分',
            ImageURL: 'static/images/knowledge/data_type_4.png',
            DemoDesc: '完全开放的chunk切分配置,按照实际文档情况自由配置,通过调试获得更好的检索效果',
        },
    ],
    modeList: [
@@ -242,6 +311,9 @@
        },
    ],
    showKnowledgeForm: false,
    knowledgeBaseData: [], //知识库类目
    fileData: [], //文件数据源
    isRadio: false, //是否单选
});
const knowledgeFormRules = reactive<FormRules>({
    title: [
@@ -261,6 +333,8 @@
});
const knowledgeFormRef = ref();
const router = useRouter();
//#region ====================== 知识库表单操作 ======================
//返回
const handleExitFlow = () => {
    //是否显示返回
@@ -282,10 +356,14 @@
    const valid = await knowledgeFormRef.value.validate().catch(() => {});
    if (!valid) return;
    state.showKnowledgeForm = true;
    getFileTreeData(true);
};
const backKnowledge = () => {
    state.showKnowledgeForm = false;
};
//#endregion
//#region ====================== 空知识库的创建 ======================
//创建一个空知识库
const emptyKnowledgeBase = async () => {
    var currentTime = moment().format('YYYY-MM-DD HH:mm:ss');
@@ -306,11 +384,91 @@
        router.push({ name: 'Knowledge' });
    }
};
//导入完成
const importCompleted = () => {
    return;
    ElMessage.success('导入完成');
    router.push({ name: 'Knowledge' });
};
//#endregion
//#region ====================== 知识库文件上传 ==========
const treeLoading = ref(false);
const currentTreeNode = ref(null);
const leftTreeRef = ref(null);
const currentListID = computed(() => currentTreeNode.value?.id);
//获取文件列表
const getFileTreeData = async (selectFirst = false) => {
    treeLoading.value = true;
    const res = await get_knowledge_group_list().finally(() => {
        treeLoading.value = false;
    });
    if (res?.json_ok) {
        const resData = (res.values || []) as [];
        state.knowledgeBaseData = convertListToTree(resData, {
            ID: 'id',
            Children: 'Children',
            ParentID: 'parent',
        });
        if (selectFirst) {
            const firstListTreeNode = state.knowledgeBaseData[0];
            if (firstListTreeNode) {
                handleClickNode(firstListTreeNode);
            } else {
                state.fileData = [];
                multipleSelection.value = [];
            }
        } else {
            currentTreeNode.value && handleClickNode(currentTreeNode.value);
        }
    }
};
const handleClickNode = (data: any) => {
    multipleSelection.value = [];
    nextTick(() => {
        leftTreeRef.value?.treeRef.setCurrentKey(data.id);
    });
    currentTreeNode.value = data;
    getFileTableData();
};
//获取文件表格列表
const getFileTableData = async () => {
    const res = await list_knowledge_file({
        group_id: currentListID.value,
    }).finally(() => {});
    if (res?.json_ok) {
        const resData = (res.values || []) as [];
        state.fileData = resData;
    } else {
        ElMessage.error('获取文档列表失败' + (res?.json_msg ? `,${JSON.stringify(res.json_msg)}` : ''));
    }
};
let multipleSelection = ref([]);
const multipleTableRef = ref(null);
//表格单选和多选
const handleSelectAll = (selection: any[], pageSelectionData: any[]) => {
    let checked = selection.length ? true : false; // selection为空数组时代表取消全选
    if (checked) {
        let mIds = multipleSelection.value.map((v) => v.id);
        let filterData = pageSelectionData.filter((v) => {
            // 筛选出非重复项
            return !mIds.includes(v.id);
        });
        multipleSelection.value = multipleSelection.value.concat(filterData);
    } else {
        let pIds = pageSelectionData.map((v) => v.id);
        multipleSelection.value = multipleSelection.value.filter((v) => !pIds.includes(v.id));
    }
};
const handleSelectItem = (selection: any[], row) => {
    multipleSelection.value = selection;
};
// 移除已选文件
const handleRemoveItem = (item) => {
    multipleSelection.value = multipleSelection.value.filter((v) => v.id !== item.id);
    multipleTableRef.value.toggleRowSelection(item, false);
};
//#endregion
</script>
<style scoped lang="scss">
.set-form-height {
@@ -357,10 +515,80 @@
    margin-top: 12px;
    padding: 16px 24px;
}
.slider-demo-block {
    max-width: 600px;
    display: flex;
    align-items: center;
.set-file-height {
    height: calc(100% - 48px);
}
.set_file_left {
    border: 1px solid #e7e8ee;
    border-radius: 12px;
    flex: 1;
    padding: 12px 16px 16px;
    box-sizing: border-box;
    .left_content {
        align-items: flex-start;
        display: flex;
        gap: 12px;
        height: calc(100% - 29px);
        .file_menu {
            flex-shrink: 0;
            height: 100%;
            overflow-y: auto;
            border: 1px solid #e7e8ee;
            border-radius: 6px;
            max-height: 627px;
            padding: 20px;
            width: 280px;
        }
        .file_table {
            flex-shrink: 0;
            height: 100%;
            overflow-y: auto;
            border-radius: 8px 8px 0 0;
            flex: 1;
        }
    }
}
.set_file_right {
    border: 1px solid #e7e8ee;
    border-radius: 6px;
    flex-shrink: 0;
    height: 100%;
    padding: 12px 16px 16px;
    width: 417px;
    min-height: 360px;
}
.selected_file {
    max-height: calc(100% - 36px);
    overflow-y: auto;
    box-sizing: border-box;
    .set_file_item {
        align-items: center;
        background: linear-gradient(0deg, #f7f8fe, #f7f8fe), #fff;
        border-radius: 8px;
        display: flex;
        font-size: 12px;
        gap: 8px;
        height: 40px;
        justify-content: space-between;
        padding: 0 16px;
        margin-bottom: 9px;
        .set_file_name {
            max-width: calc(100% - 22px);
        }
        .set_file_close {
            color: #878aab;
            cursor: pointer;
            flex-shrink: 0;
            font-size: 14px;
            align-items: center;
            display: inline-flex;
            justify-content: center;
        }
    }
}
.hidden-checkbox-all :deep(.el-table__header .el-table-column--selection .el-checkbox) {
    // 隐藏全选checkbox
    display: none;
}
</style>
<style>
src/views/project/yw/dataManage/knowledge/EditKnowledge.vue
@@ -44,7 +44,7 @@
            </el-form>
        </div>
        <div class="set-form-footer">
            <el-button @click="saveKnowledgeBase">保存</el-button>
            <el-button @click="saveKnowledgeBase" type="primary">保存</el-button>
            <el-button @click="handleExitFlow">取消</el-button>
        </div>
    </div>
@@ -52,11 +52,9 @@
<script setup lang="ts">
import { ElMessage, type FormRules } from 'element-plus';
import moment from 'moment';
import { onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { add_docvector_name } from '/@/api/knowledge/docvector';
import mittBus from '/@/utils/mitt';
import { update_docvector_name } from '/@/api/knowledge/docvector';
// 定义变量内容
const state = reactive({
    soliderValue: 0,
@@ -91,26 +89,18 @@
const handleExitFlow = () => {
    //是否显示返回
    router.back();
    //清空表单
    editKnowledgeFormRef.value.resetFields();
};
//创建一个空知识库
const saveKnowledgeBase = async () => {
    var currentTime = moment().format('YYYY-MM-DD HH:mm:ss');
    const valid = await editKnowledgeFormRef.value.validate().catch(() => {});
    if (!valid) return;
    const res = await add_docvector_name({ title: state.editKnowledgeForm.title, prompt: state.editKnowledgeForm.prompt });
    const res = await update_docvector_name({
        title: state.editKnowledgeForm.title,
        prompt: state.editKnowledgeForm.prompt,
        knowlg_id: state.editKnowledgeForm.id,
    });
    if (res.json_ok) {
        ElMessage.success('创建成功');
        let obj = {
            id: res.knowlg_id,
            title: state.editKnowledgeForm.title,
            prompt: state.editKnowledgeForm.prompt,
            publish: '',
            create_time: currentTime,
            user_name: '',
        };
        mittBus.emit('addKnowledgeBaseObj', obj);
        ElMessage.success('更新成功');
        router.push({ name: 'Knowledge' });
    }
};