<template>
|
<a-popover :popup-visible="visible" title="" trigger="click" position="tl">
|
<a-button type="text" style="border-radius: 24px" @click="visibleChange">
|
<icon-attachment size="28" style="color: #0960bd" />
|
</a-button>
|
<template #title>
|
<div style="display: flex; justify-content: space-between">
|
<div>上传文件</div>
|
<div>
|
<icon-upload />
|
</div>
|
</div>
|
</template>
|
<template #content>
|
<a-upload
|
draggable
|
action="/"
|
style="width: 100%"
|
:auto-upload="false"
|
ref="uploadRef"
|
@change="onChange"
|
multiple
|
:limit="1"
|
/>
|
<div
|
style="
|
width: 100%;
|
margin-top: 10px;
|
justify-content: space-between;
|
text-align: right;
|
"
|
class="upload-wrap"
|
>
|
<!-- <div>-->
|
<!-- <span>解析方法: </span>-->
|
<!-- <a-radio-group-->
|
<!-- v-model="parser_id"-->
|
<!-- style="width: 400px"-->
|
<!-- @change="parserChange"-->
|
<!-- >-->
|
<!-- <a-popover v-for="item in filterData" :key="item.value">-->
|
<!-- <a-radio :value="item.value" style="margin-right: 10px">{{-->
|
<!-- item.name-->
|
<!-- }}</a-radio>-->
|
|
<!-- <template #content>-->
|
<!-- <p>{{ item.parser_config_str }}</p>-->
|
<!-- </template>-->
|
<!-- </a-popover>-->
|
<!-- </a-radio-group>-->
|
<!-- </div>-->
|
<!-- <a-select-->
|
<!-- :style="{ width: '100px', margin: '0 10px' }"-->
|
<!-- :default-value="['通用', '多模态']"-->
|
<!-- v-model="parser_configs"-->
|
<!-- multiple-->
|
<!-- size="small"-->
|
<!-- >-->
|
<!-- <a-option v-for="item in parser_ids" :key="item.value">{{-->
|
<!-- item.name-->
|
<!-- }}</a-option>-->
|
<!-- </a-select>-->
|
<!-- <p class="config-text">更多配置</p>-->
|
<a-button
|
:loading="onFileSelectedLoading"
|
@click="upDataFile"
|
type="primary"
|
size="mini"
|
style="border-radius: 24px;"
|
>
|
<span style="font-size: 12px"> 上传 </span>
|
</a-button>
|
</div>
|
</template>
|
</a-popover>
|
</template>
|
|
<script lang="ts" setup>
|
import {
|
onMounted,
|
onBeforeMount,
|
reactive,
|
ref,
|
computed,
|
watch,
|
} from 'vue';
|
import axios from 'axios';
|
import { Message } from '@arco-design/web-vue';
|
import {
|
addSessionApi,
|
getParseMethodsListApi,
|
getSessionDetailsApi,
|
uploadWithoutKb,
|
uploadAndParse, upload_and_parse, getDocumentStatus
|
} from "@/api/session";
|
|
const visible = ref(false);
|
const loading = ref(false);
|
const chatDis = ref(false);
|
const directory = ref(false);
|
const filesBtn = ref(null);
|
const onFileSelectedLoading = ref(false);
|
const parser_id = ref('');
|
const parseridConfig = ref(false);
|
const uploaditemList = ref([]);
|
const activeSessionId = ref('');
|
let kbtenantInfo = reactive({
|
asr_id: 'paraformer-realtime-8k-v1',
|
embd_id: 'BAAI/bge-large-zh-v1.5',
|
img2txt_id: 'qwen-vl-max',
|
llm_id: 'qwen-plus',
|
name: 'wanghaos Kingdom',
|
// parser_ids: 'naive:General,qa:Q&A,resume:Resume,manual:Manual,table:Table,paper:Paper,book:Book,laws:Laws,presentation:Presentation,picture:Picture,one:One',
|
parser_ids:
|
'naive:通用,qa:Q&A,resume:简历,manual:说明书,table:表格,paper:多模态,book:书籍,laws:法律文件,presentation:PPT,picture:图片,one:整体',
|
rerank_id: 'BAAI/bge-reranker-v2-m3',
|
role: 'owner',
|
tenant_id: '948fc6fa41ab11ef8fb80242ac120004',
|
parser_idObj: {},
|
});
|
const parser = reactive({
|
naive: {
|
chunk_token_num: 676,
|
layout_recognize: true,
|
raptor: {
|
use_raptor: true,
|
prompt:
|
'请总结以下段落。 小心数字,不要编造。 段落如下:\n {cluster_content}\n以上就是你需要总结的内容。',
|
max_token: 600,
|
threshold: 0.32,
|
max_cluster: 233,
|
random_seed: 1500,
|
},
|
}, // 用户名
|
qa: {
|
entity_types: ['organization', 'person', 'location', 'event', 'time'],
|
raptor: {
|
use_raptor: false,
|
},
|
},
|
resume: {},
|
manual: {},
|
table: {},
|
paper: {},
|
book: {},
|
laws: {},
|
presentation: {},
|
picture: {},
|
one: {},
|
});
|
const parser_configs = ref(['通用', '多模态']);
|
const parser_ids = ref([
|
{
|
name: '通用',
|
value: 'naive',
|
parser_config: parser.naive,
|
parser_config_str: '支持的文件格式为DOCX、EXCEL、PPT、IMAGE、PDF、TXT',
|
},
|
{
|
name: 'Q&A',
|
value: 'qa',
|
parser_config: parser.qa,
|
parser_config_str:
|
'支持 excel 和 csv/txt 文件格式。 \n' +
|
'如果文件以 excel 格式,则应由两个列组成 没有标题:一个提出问题,另一个用于答案, 答案列之前的问题列。\n' +
|
'如果文件以 csv/txt 格式为 用作分开问题和答案的定界符。\n',
|
},
|
{
|
name: '简历',
|
value: 'resume',
|
parser_config: parser.resume,
|
parser_config_str: '支持的文件格式为DOCX、PDF、TXT',
|
},
|
{
|
name: '说明书',
|
value: 'manual',
|
parser_config: parser.manual,
|
parser_config_str: '仅支持PDF',
|
},
|
{
|
name: '表格',
|
value: 'table',
|
parser_config: parser.table,
|
parser_config_str:
|
'支持EXCEL和CSV/TXT格式文。 \n' +
|
'对于 csv 或 txt 文件,列之间的分隔符为 TAB,\n' +
|
'第一行必须是列标题。\n',
|
},
|
{
|
name: '多模态',
|
value: 'paper',
|
parser_config: parser.paper,
|
parser_config_str: '仅支持PDF文件',
|
},
|
{
|
name: '书籍',
|
value: 'book',
|
parser_config: parser.book,
|
parser_config_str: '支持的文件格式为DOCX、PDF、TXT',
|
},
|
{
|
name: '法律文件',
|
value: 'laws',
|
parser_config: parser.laws,
|
parser_config_str: '支持的文件格式为DOCX、PDF、TXT',
|
},
|
{
|
name: 'PPT',
|
value: 'presentation',
|
parser_config: parser.presentation,
|
parser_config_str: '支持的文件格式为PDF、PPTX',
|
},
|
{
|
name: '图片',
|
value: 'picture',
|
parser_config: parser.picture,
|
parser_config_str: '支持图像文件',
|
},
|
{
|
name: '整体',
|
value: 'one',
|
parser_config: parser.one,
|
parser_config_str: '支持的文件格式为DOCX、EXCEL、PDF、TXT',
|
},
|
]);
|
const parser_idsArr = ref([]);
|
const uploadList = ref([]);
|
const props = defineProps(['sessionId']);
|
const emit = defineEmits(['selectFileCallback']);
|
const uploadRef = ref();
|
const files = ref([]);
|
const acceptNameList = computed(() => {
|
return '.word, .pdf, .ppt, .excel, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .pptx, .ppt, .pdf, .mp4, .avi, .mp3,.wav, .wma, .wmv, .rm,';
|
});
|
|
const filterData = computed(() => {
|
const result = parser_ids.value
|
.filter((val) => parser_configs.value.includes(val.name))
|
.reverse()
|
.slice(0, 4)
|
.reverse();
|
result.unshift({
|
name: '智能识别',
|
value: '',
|
parser_config_str: '',
|
parser_config: '',
|
});
|
return result;
|
});
|
|
const init = () => {
|
// parser_ids.value = kbtenantInfo.parser_ids.split(",").map((item) => {
|
// const [value1, value2] = item.split(":");
|
// return {
|
// name: value2,
|
// value: value1
|
// };
|
// });
|
getParseMethodsList();
|
};
|
|
const chooseParser = (item) => {
|
console.log(item);
|
};
|
|
const onChange = (fileList) => {
|
files.value = fileList;
|
files.value.forEach((item) => {});
|
};
|
const parserChange = () => {
|
parseridConfig.value = false;
|
};
|
|
const visibleChange = (e) => {
|
e.stopPropagation();
|
visible.value = !visible.value;
|
};
|
|
const getIconByExtension = (extension) => {
|
const fileExtension = ref('');
|
fileExtension.value = extension.split('.').pop();
|
let type = '';
|
parser_idsArr.value.forEach((item) => {
|
// 包含元素
|
if (item.formats.includes(fileExtension.value)) {
|
type = item.id;
|
}
|
});
|
return type;
|
};
|
let status_timer;
|
const upDataFile = async () => {
|
if (!activeSessionId.value) {
|
//新建会话
|
const res = await addSessionApi({
|
dialog_id: '',
|
conversation_desc: '',
|
});
|
// console.log(res, "res");
|
if (res.code == 200) {
|
// console.log(res.data.conversation_id);
|
activeSessionId.value = res.data?.conversation_id;
|
const { code, data } = await getSessionDetailsApi(
|
res.data?.conversation_id
|
);
|
if (code === 200) {
|
console.log(data, '新建会话详情');
|
}
|
} else {
|
Message.error('创建会话失败,请重试');
|
}
|
}
|
|
console.log(files.value, 'files');
|
console.log(parser_ids.value, '解析方法');
|
if (files.value.length == 0) {
|
Message.warning('请选择文件');
|
return;
|
}
|
uploaditemList.value = files.value.map((item, index) => {
|
return {
|
index: index,
|
name: item.name,
|
size: (item.file.size / 1024).toFixed(2) + 'K',
|
};
|
});
|
onFileSelectedLoading.value = true;
|
const formData = new FormData();
|
for (let i = 0; i < files.value.length; i++) {
|
formData.append('file', files.value[i].file);
|
formData.append('conversation_id', activeSessionId.value);
|
formData.append('parser_config', '');
|
if (!parser_id.value) {
|
formData.append('parser_id', getIconByExtension(files.value[i].name));
|
} else {
|
formData.append('parser_id', parser_id.value);
|
}
|
}
|
console.log(formData, 'formData');
|
upload_and_parse(formData).then((res) => {
|
onFileSelectedLoading.value = false;
|
if (res.code == 0) {
|
//上传成功
|
Message.success("上传成功");
|
cancel();
|
emit("selectFileCallback", uploaditemList.value,activeSessionId.value);
|
} else {
|
Message.error('上传失败');
|
}
|
});
|
};
|
|
|
const checkStatus = async (doc_ids) => {
|
let res = await getDocumentStatus(doc_ids);
|
if (res.code == 200 && res.data.status == "success") {
|
//上传成功
|
Message.success("上传成功");
|
cancel();
|
emit("selectFileCallback", uploaditemList.value);
|
if (status_timer) {
|
clearTimeout(status_timer!);
|
}
|
}
|
};
|
|
const cancel = () => {
|
if (!onFileSelectedLoading.value) {
|
visible.value = false;
|
parser_id.value = '';
|
}
|
};
|
|
defineExpose({
|
cancel,
|
});
|
|
const getParseMethodsList = async () => {
|
let res = await getParseMethodsListApi();
|
parser_ids.value = res.data.map((item) => {
|
console.log(item, item.parser_config_str, 78787);
|
return {
|
name: item.name,
|
value: item.id,
|
parser_config: '',
|
parser_config_str: JSON.stringify(item.formats),
|
};
|
});
|
parser_idsArr.value = res.data;
|
};
|
|
onBeforeMount(() => {
|
init();
|
});
|
onMounted(() => {});
|
|
watch(
|
() => props.sessionId,
|
(value, oldValue) => {
|
activeSessionId.value = value;
|
}
|
);
|
</script>
|
<style>
|
.upload-wrap .arco-select-view-inner {
|
display: none;
|
}
|
</style>
|
<style scoped lang="less">
|
.aUpload {
|
width: 100%;
|
max-height: 500px;
|
overflow: hidden;
|
overflow-y: auto;
|
}
|
.upload-wrap {
|
position: relative;
|
}
|
.config-text {
|
position: absolute;
|
right: 70px;
|
bottom: -11px;
|
font-size: 12px;
|
}
|
</style>
|