476 lines
14 KiB
Vue
476 lines
14 KiB
Vue
<template>
|
|
<div class="gl-page-content-grey">
|
|
<div class="content">
|
|
<FileTree
|
|
ref="fileTreeRef"
|
|
:api="dataListDirApi"
|
|
:params="{ dirType: DIR_TYPE.KNOWLEDGE }"
|
|
@choseNode="choseNodeFun"
|
|
@updateNav="updateNavFun"
|
|
>
|
|
<template #options>
|
|
<el-button :icon="Plus" class="options" type="primary" @click="appendFun({})">
|
|
{{ $t('知识库.新增') }}
|
|
</el-button>
|
|
</template>
|
|
<template #treeAction="{ data, }">
|
|
<div>
|
|
<el-button type="primary" link @click.stop="appendFun(data)">
|
|
<el-icon>
|
|
<FolderAdd />
|
|
</el-icon>
|
|
</el-button>
|
|
<el-button type="primary" link @click.stop="updateFun(data)">
|
|
<el-icon>
|
|
<EditPen />
|
|
</el-icon>
|
|
</el-button>
|
|
<el-popconfirm
|
|
:title="$t('知识库.确认删除')"
|
|
:cancelButtonText="$t('通用.取消')"
|
|
:confirmButtonText="$t('通用.确定')"
|
|
@confirm="removeFun(data)"
|
|
>
|
|
<template #reference>
|
|
<el-button type="danger" link>
|
|
<el-icon>
|
|
<Delete />
|
|
</el-icon>
|
|
</el-button>
|
|
</template>
|
|
</el-popconfirm>
|
|
</div>
|
|
</template>
|
|
<template #table>
|
|
<TableSearch
|
|
v-if="searchItems.length > 0"
|
|
ref="tableSearchRef"
|
|
:searchItems="searchItems"
|
|
@search="searchFun"
|
|
@reset="resetFun"
|
|
/>
|
|
<BaseTable
|
|
ref="baseTableRef"
|
|
tableName="SIMULATION_KNOWLEDGE"
|
|
:api="apiName"
|
|
:params="searchParams"
|
|
showIndex
|
|
:actionsWidth="200"
|
|
:actionList="actionList"
|
|
@cell-dblclick="onCellDblclickFun"
|
|
:exportApi="dataExportKnowledgeListApi"
|
|
:exportFileName="$t('知识库.知识库列表')"
|
|
:exportDict="{
|
|
approvalStatus: 'KNOWLEDGE_APPROVE_STATUS'
|
|
}"
|
|
:exportParams="{
|
|
...searchParams,
|
|
parentDirId: currentFolder?.id || ''
|
|
}"
|
|
>
|
|
<template #leftOptions>
|
|
<div>
|
|
<el-button :icon="DArrowLeft" @click="backFun" :disabled="navList.length <= 1">{{ $t('通用.返回上一级')
|
|
}}</el-button>
|
|
<el-button type="primary" :icon="Plus" @click="openModalFun" :disabled="!currentFolder">
|
|
{{ $t('知识库.上传') }}
|
|
</el-button>
|
|
</div>
|
|
</template>
|
|
<template #originalName="{ row }">
|
|
<el-icon v-if="row.dataType === 1">
|
|
<Folder />
|
|
</el-icon>
|
|
<el-icon v-else>
|
|
<Document />
|
|
</el-icon>
|
|
{{ row.originalName }}
|
|
</template>
|
|
<template #fileSize="{ row }">
|
|
{{ formatFileSize(row.fileSize) }}
|
|
</template>
|
|
<template #approvalStatus="{ row, column }">
|
|
<template v-if="row.dataType === 2">
|
|
<el-button type="primary" link @click="openProcessFun(row)" v-if='row[column.field] === "pending"'>
|
|
{{ KNOWLEDGE_APPROVE_STATUS.O[row[column.field]] }}
|
|
</el-button>
|
|
<el-button type="primary" link @click="openProcessFun(row)" v-else>
|
|
{{ $t('知识库.审批完成') }}
|
|
</el-button>
|
|
</template>
|
|
</template>
|
|
<template #approveType="{ row, column }">
|
|
<el-button v-if="row.dataType === 2" type="primary" link @click="openProcessFun(row)"> {{
|
|
KNOWLEDGE_APPROVE_TYPE.O[row[column.field]] }}</el-button>
|
|
</template>
|
|
</BaseTable>
|
|
</template>
|
|
</FileTree>
|
|
</div>
|
|
<ApprovalProcess v-model="processVisible" :flowId="currentRow?.cidFlowId" />
|
|
<knowledgeDetailModal
|
|
v-model="visible"
|
|
:detail="currentRow"
|
|
:folder="currentFolder"
|
|
:tableName="TABLE_NAME.SIMULATION_KNOWLEDGE"
|
|
@confirm="onConfirmFun"
|
|
/>
|
|
<folderModal
|
|
v-model="folderModalVisible"
|
|
:detail="currentFolder"
|
|
:mode="currentFolderMode"
|
|
@confirm="onFolderConfirmFun"
|
|
/>
|
|
<FilePreview v-model="previewVisible" :fileId="currentRow?.id" />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, h, ref, watchEffect, type Ref } from 'vue';
|
|
import { DArrowLeft, Plus } from '@element-plus/icons-vue';
|
|
import BaseTable from '@/components/common/table/baseTable.vue';
|
|
import FileTree from '@/components/common/fileTree/index.vue';
|
|
import knowledgeDetailModal from './components/knowledgeDetailModal.vue';
|
|
import folderModal from './components/folderDetailModal.vue';
|
|
import { dataCreateDirApi, dataListDirApi, dataRenameDirApi, dataDelDirApi, dataQueryDirApi, dataFileSearchApi, dataDelFileApi, dataUpdateFileApi, batchAddFileInfoApi, dataExportKnowledgeListApi } from '@/api/data/data';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import type { RenderContentContext } from 'element-plus';
|
|
import { formatFileSize } from '@/utils/file';
|
|
import TableSearch from '@/components/common/table/tableSearch.vue';
|
|
import { cloneDeep } from 'lodash-es';
|
|
import { DIR_TYPE } from '@/utils/enum/data.ts';
|
|
import ApproveList from '@/components/common/approveList/index.vue';
|
|
import { useDict } from '@/utils/useDict';
|
|
import ApprovalProcess from '@/components/common/approvalProcess/index.vue';
|
|
import i18n from '@/utils/i18n';
|
|
import FilePreview from '@/components/common/filePreview/index.vue';
|
|
import emitter from '@/utils/eventBus';
|
|
import { TABLE_NAME } from '@/utils/enum/tableName';
|
|
import { downloadFileById } from '@/utils/file';
|
|
|
|
const { KNOWLEDGE_APPROVE_STATUS, KNOWLEDGE_APPROVE_TYPE } = useDict('KNOWLEDGE_APPROVE_STATUS', 'KNOWLEDGE_APPROVE_TYPE');
|
|
type Data = RenderContentContext['data']
|
|
const fileTreeRef = ref<any>();
|
|
const baseTableRef = ref<any>();
|
|
const navList = ref<any>([]);
|
|
const currentFolder = ref();
|
|
const memoryFolder = ref();
|
|
const currentFolderMode: Ref<'add' | 'edit'> = ref('add');
|
|
const choseNodeFun = (data: Data) => {
|
|
isSearching.value = false;
|
|
currentFolder.value = data;
|
|
memoryFolder.value = currentFolder.value;
|
|
};
|
|
|
|
const updateNavFun = (data: any) => {
|
|
navList.value = data;
|
|
};
|
|
|
|
const backFun = () => {
|
|
fileTreeRef.value.backFun();
|
|
};
|
|
|
|
const searchItems = ref<any[]>([
|
|
{ title: '名称', key: 'fileName', inputMode: 'input' },
|
|
{
|
|
title: '上传人', key: 'uploadUserId', inputMode: 'userSelectMultiple',
|
|
},
|
|
|
|
]);
|
|
const folderModalVisible = ref(false);
|
|
const appendFun = (data: Data) => {
|
|
currentFolder.value = data;
|
|
currentFolderMode.value = 'add';
|
|
folderModalVisible.value = true;
|
|
|
|
};
|
|
const updateFun = (data: Data) => {
|
|
currentFolder.value = data;
|
|
currentFolderMode.value = 'edit';
|
|
folderModalVisible.value = true;
|
|
|
|
};
|
|
const removeFun = async (data: Data) => {
|
|
const req = {
|
|
delDirId: data.id,
|
|
};
|
|
const res: any = await dataDelDirApi(req);
|
|
if (res.code === 200) {
|
|
refreshTreeAfterModifyOrRemove(data);
|
|
ElMessage.success(res.message);
|
|
} else {
|
|
ElMessage.error(res.message);
|
|
}
|
|
};
|
|
const refreshTreeRoot = () => {
|
|
fileTreeRef.value?.reloadFun();
|
|
baseTableRef.value?.resetFun();
|
|
};
|
|
const refreshTreeOpenDir = (dirId: number) => {
|
|
fileTreeRef.value?.openDirFun(dirId);
|
|
baseTableRef.value?.resetFun();
|
|
};
|
|
const refreshTreeAfterAdd = (parentNode?: any | null) => {
|
|
if (parentNode && typeof parentNode.id === 'number') {
|
|
refreshTreeOpenDir(parentNode.id);
|
|
} else {
|
|
refreshTreeRoot();
|
|
}
|
|
};
|
|
const isTopLevel = (node: any) => {
|
|
if (!node || !node.objectKey) return false;
|
|
const key = String(node.objectKey).replace(/\/$/, '');
|
|
const parts = key.split('/');
|
|
return parts.length === 2;
|
|
};
|
|
const refreshTreeAfterModifyOrRemove = (node?: any | null) => {
|
|
if (isTopLevel(node)) {
|
|
refreshTreeRoot();
|
|
} else {
|
|
refreshTreeOpenDir(node.parentId);
|
|
}
|
|
|
|
};
|
|
const isSearching = ref(false);
|
|
const searchParams = ref<any>({
|
|
fileId: currentFolder.value?.id || '',
|
|
|
|
});
|
|
|
|
const actionList = computed(() => {
|
|
return [
|
|
{
|
|
title: i18n?.global?.t('通用.预览'),
|
|
type: 'primary',
|
|
click: (row: any) => {
|
|
previewFileFun(row);
|
|
},
|
|
hide: (row: any) => {
|
|
return row.dataType !== 2;
|
|
},
|
|
},
|
|
{
|
|
title: i18n?.global?.t('通用.下载'),
|
|
type: 'primary',
|
|
click: (row: any) => {
|
|
downloadFileById(row.id);
|
|
},
|
|
hide: (row: any) => {
|
|
return row.dataType !== 2;
|
|
},
|
|
},
|
|
{
|
|
title: i18n?.global?.t('通用.编辑'),
|
|
type: 'primary',
|
|
click: (row: any) => {
|
|
editFileFun(row);
|
|
},
|
|
hide: (row: any) => {
|
|
return row.dataType !== 2 || row.approvalStatus === 'pending';
|
|
},
|
|
},
|
|
{
|
|
title: i18n?.global?.t('通用.删除'),
|
|
type: 'danger',
|
|
click: (row: any) => {
|
|
delFileFun(row);
|
|
},
|
|
hide: (row: any) => {
|
|
return row.dataType !== 2 || row.approvalStatus === 'pending';
|
|
},
|
|
},
|
|
];
|
|
|
|
});
|
|
const searchFun = (data: object) => {
|
|
isSearching.value = true;
|
|
if (!memoryFolder.value && currentFolder.value) {
|
|
memoryFolder.value = currentFolder.value;
|
|
currentFolder.value = null;
|
|
}
|
|
searchParams.value = cloneDeep(data);
|
|
searchParams.value.searchType = 1;
|
|
searchParams.value.parentDirId = memoryFolder.value?.id || '';
|
|
};
|
|
const resetFun = (data: object) => {
|
|
isSearching.value = false;
|
|
currentFolder.value = memoryFolder.value;
|
|
searchParams.value = cloneDeep(data);
|
|
searchParams.value.fileId = currentFolder.value?.id || '';
|
|
};
|
|
const refreshTableFun = async () => {
|
|
baseTableRef.value?.resetFun();
|
|
};
|
|
const onFolderConfirmFun = async (formData: any) => {
|
|
if (currentFolderMode.value === 'add') {
|
|
const req = {
|
|
dirType: DIR_TYPE.KNOWLEDGE,
|
|
parDirId: currentFolder.value?.id,
|
|
dirName: formData.name,
|
|
type: 0,
|
|
};
|
|
const res: any = await dataCreateDirApi(req);
|
|
if (res.code === 200) {
|
|
refreshTreeAfterAdd(currentFolder.value);
|
|
folderModalVisible.value = false;
|
|
ElMessage.success(res.message);
|
|
}
|
|
|
|
} else if (currentFolderMode.value === 'edit') {
|
|
const req = {
|
|
dirId: currentFolder.value.id,
|
|
oldName: currentFolder.value.originalName,
|
|
newName: formData.name,
|
|
type: 0,
|
|
};
|
|
const res: any = await dataRenameDirApi(req);
|
|
if (res.code === 200) {
|
|
refreshTreeAfterModifyOrRemove(currentFolder.value);
|
|
folderModalVisible.value = false;
|
|
ElMessage.success(res.message);
|
|
}
|
|
|
|
}
|
|
};
|
|
const visible = ref(false);
|
|
const currentRow = ref();
|
|
const openModalFun = () => {
|
|
visible.value = true;
|
|
currentRow.value = null;
|
|
};
|
|
const onConfirmFun = async (formData: any) => {
|
|
const req = {
|
|
...currentRow.value,
|
|
templateId: formData.templateId,
|
|
templateName: formData.templateName,
|
|
file: formData.file.raw,
|
|
fileName: formData.file.name,
|
|
size: formData.file.size,
|
|
projectName: formData.projectName,
|
|
path: currentFolder.value.objectKey,
|
|
dirId: currentFolder.value.id,
|
|
chunk: 0,
|
|
remarks: formData.remarks,
|
|
projectId: formData.projectId,
|
|
chunkTotal: 0,
|
|
encryptKey: null,
|
|
type: 0,
|
|
analysisDirectionId: formData.analysisDirectionId,
|
|
};
|
|
let res: any;
|
|
if (currentRow.value && currentRow.value.id) {
|
|
res = await dataUpdateFileApi(req);
|
|
} else {
|
|
const req = {
|
|
sourceFiles: formData.file,
|
|
uploadTaskId: new Date().getTime(),
|
|
dirId: currentFolder.value.id,
|
|
projectId: formData.projectId,
|
|
analysisDirectionId: formData.analysisDirectionId,
|
|
templateId: formData.templateId,
|
|
templateName: formData.templateName,
|
|
remarks: formData.remarks,
|
|
type: 0,
|
|
};
|
|
res = await batchAddFileInfoApi(req);
|
|
if (res.code === 200) {
|
|
res.data.forEach((item: any, index: number) => {
|
|
emitter.emit('ADD_UPLOAD_FILE', {
|
|
file: formData.originalName[index].raw, // 文件对象
|
|
data: { // 接口返回的文件目录信息,包括配置信息
|
|
...item,
|
|
isApprove: 1, // 0否 1是
|
|
taskType: 2, // 2知识库
|
|
},
|
|
});
|
|
});
|
|
}
|
|
}
|
|
if (res.code === 200) {
|
|
visible.value = false;
|
|
refreshTableFun();
|
|
ElMessage.success(res.message);
|
|
}
|
|
|
|
};
|
|
const previewVisible = ref(false);
|
|
const previewFileFun = (row: any) => {
|
|
currentRow.value = row;
|
|
previewVisible.value = true;
|
|
};
|
|
|
|
const editFileFun = (row: any) => {
|
|
currentRow.value = row;
|
|
visible.value = true;
|
|
};
|
|
const delFileFun = async (row: any) => {
|
|
const templateId = ref('');
|
|
const templateName = ref('');
|
|
ElMessageBox({
|
|
title: i18n?.global?.t('通用.审核模版'),
|
|
showCancelButton: true,
|
|
showConfirmButton: true,
|
|
confirmButtonText: i18n?.global?.t('通用.确定'),
|
|
cancelButtonText: i18n?.global?.t('通用.取消'),
|
|
message: () =>
|
|
h(ApproveList, {
|
|
modelValue: templateId.value,
|
|
'onChange': (val: any) => {
|
|
templateName.value = val.label;
|
|
templateId.value = val.value;
|
|
},
|
|
}),
|
|
}).then(async () => {
|
|
if (!templateId.value) {
|
|
ElMessage.error(i18n?.global?.t('通用.请选择审核模版'));
|
|
return;
|
|
}
|
|
const req = {
|
|
templateId: templateId.value,
|
|
templateName: templateName.value,
|
|
delFileId: row.id,
|
|
};
|
|
const res: any = await dataDelFileApi(req);
|
|
if (res.code === 200) {
|
|
refreshTableFun();
|
|
ElMessage.success(res.message);
|
|
}
|
|
});
|
|
|
|
};
|
|
const onCellDblclickFun = (e: any) => {
|
|
if (e.row.dataType === 1) {
|
|
fileTreeRef.value?.openDirFun(e.row.id);
|
|
}
|
|
};
|
|
const apiName: any = ref(null);
|
|
watchEffect(() => {
|
|
if (currentFolder.value && currentFolder.value.id && !isSearching.value) {
|
|
searchParams.value.fileId = currentFolder.value?.id || '';
|
|
apiName.value = dataQueryDirApi;
|
|
} else if (isSearching.value) {
|
|
apiName.value = dataFileSearchApi;
|
|
} else {
|
|
apiName.value = null;
|
|
}
|
|
});
|
|
|
|
const processVisible = ref(false);
|
|
const openProcessFun = (row: any) => {
|
|
currentRow.value = row;
|
|
processVisible.value = true;
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.gl-page-content-grey {
|
|
height: 100%;
|
|
.content {
|
|
height: 100%;
|
|
.options {
|
|
margin-bottom: var(--margin-small);
|
|
}
|
|
}
|
|
}
|
|
</style>
|