Commit 2f669943 by wanglizhen

知识库导入

parent 755912ad
...@@ -104,3 +104,32 @@ export function delValue(data) { ...@@ -104,3 +104,32 @@ export function delValue(data) {
}) })
} }
/**
* 知识库 - 导出excel
* @param {*} data
* @returns
*/
export function exportExcel(data) {
return request({
url: '/core/dictionaryexcel/export',
method: 'post',
data: data,
responseType: 'blob'
})
}
/**
* 知识库 - 导入
* @param {*} data
* @returns
*/
export function importfile(data) {
return request({
url: '/core/dictionaryexcel/importfile',
method: 'post',
data: data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
\ No newline at end of file
<script setup lang="ts" name="CustomUpload">
import { ref, getCurrentInstance, computed, onMounted, watch } from 'vue'
import { getToken } from '@/utils/auth'
import { ElMessage, ElMessageBox } from 'element-plus'
import { parseTime } from '@/utils/ruoyi'
import axios from 'axios'
// import { filePreview } from '@/api/preview'
const { proxy } = getCurrentInstance() as any
// <CustomUpload v-model:file-list="fileList"/>
// const fileList = ref([
// {
// name: 'food.jpeg',
// fileSize: '23423',
// fileType: 'img',
// url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
// createTime: '2024-01-24 16:31'
// },
// {
// name: 'food.jpeg',
// fileSize: '23423',
// fileType: 'img',
// url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
// createTime: '2024-01-24 16:31'
// }
// ])
type IFileList = Array<any> | null | undefined
const emit = defineEmits<{
'update:fileList': [fileList: IFileList],
'onSuccess'
}>()
const props = withDefaults(defineProps<{
fileList: IFileList
buttonPermission?: Array<string>
needType?: boolean
needSize?: boolean
needTime?:boolean
needStatus?:boolean,
acceptTypeList?:Array<string>
limit?:number,
prompt?:string,
uploadType?:number,
listShow?: boolean
}>(), {
buttonPermission: () => ['upload', 'delete'],
needType: true,
needSize: true,
needTime: true,
needStatus: true,
limit: 100,
prompt: '点击或将文件拖拽到此处上传',
uploadType: 1,
listShow: false,
// acceptTypeList: () => ['png', 'jpg', 'doc', 'docx', 'pdf']
})
const uploadFileUrl = (props.uploadType === 1 ? ref(import.meta.env.VITE_APP_BASE_API + '/core/dictionaryexcel/importfile') : ref(import.meta.env.VITE_APP_BASE_API + '/eo/TTenantContractlabelTemplateController/uploadTemporary')) // 上传文件服务器地址
const headers = ref({
Token: getToken(),
'from-source': 'platformUi',
'Content-Type': 'mulipart/form-data'
})
// const FileList = ref<Array<any>>([])
const FileList = computed({
get() {
return props.fileList
},
set(val: any) {
// console.log('fileList computed', val)
emit('update:fileList', val)
}
})
const uploadLoading = computed(() => {
if (FileList.value != null && FileList.value.some(item => item.status === 'uploading')) {
return true
}
return false
})
// const fileListlengthCompute = computed(() => {
// return props.fileList.length
// })
// watch(() => props.fileList, (val: IFileList) => {
// console.log('props.fileList', val)
// if (!val) {
// FileList.value = []
// return
// }
// FileList.value = JSON.parse(JSON.stringify(props.fileList))
// }, { deep: true, immediate: true })
// watch(fileListlengthCompute, (val) => {
// console.log(val)
// if (val === 0) {
// emit('update:fileList', [])
// FileList.value = []
// }
// }, { deep: true, immediate: true })
function updateFileList() {
emit('onSuccess')
// emit('update:fileList', FileList.value.filter(item => item.status === 'success'))
}
function beforeUpload(file) {
console.log('beforeUpload', file)
let type = file.name.split('.')
type = type[type.length - 1]
if (props.acceptTypeList.indexOf(type) >= 0) {
const list = {}
for (const key in file) {
list[key] = file[key]
}
// status:uploading、success、error 文件上传状态
// progress 文件上传进度
FileList.value.push({ ...list, progress: 0, status: 'uploading' })
// updateFileList()
httpRequest(file, parms => {
showProgress(list, parms)
})
// 阻止 el-upload的默认上传
return false
}
proxy.$modal.msgError(`文件格式不正确, 请上传${props.acceptTypeList.join('/')}格式文件!`)
return false
}
async function httpRequest(file, callback) {
let formData = new FormData()
formData.append('fileUpload', file)
let progress = 0
axios({
headers: headers.value,
method: 'post',
url: uploadFileUrl.value,
data: formData,
onUploadProgress: progressEvent => { // 获取文件上传进度 axios自带的
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
callback({ progress, status: 'uploading' })
}
}).then((res) => { // 成功状态
// console.log('res', res)
let data = res.data.data
proxy.$emit('uploadSuccessCallback', data)
if (props.uploadType === 1) {
callback({ progress, status: 'success', url: data.url, id: '' })
} else {
callback({ progress, status: 'success', url: data.url, id: data.id })
updateFileList()
}
}).catch(() => { // 失败状态
callback({ progress, status: 'error' })
})
}
function showProgress(file, parms) {
const { progress, status, url } = parms
const arr = [...FileList.value].map(items => {
if (items.uid === file.uid) {
items.progress = progress
items.status = status
items.url = url
items.fileType = file.type
items.fileSize = file.size
items.createTime = parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')
items.id = parms.id
}
return items
})
FileList.value = [...arr]
// updateFileList()
}
function handleAvatarSuccess(response, uploadFile) {
console.log(response)
console.log(uploadFile)
}
function handlePreviewFile(file) {
console.log(file)
filePreview(file.url)
}
function handleDownFile(file) {
const fileUrl = file.url // 文件的URL地址
fetch(fileUrl)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.setAttribute('download', file.name)
document.body.appendChild(link)
link.click()
})
.catch(error => {
console.error(error)
})
}
function handleDeleteFile(index) {
FileList.value.splice(index, 1)
// updateFileList()
}
const cancelEvent = () => {
console.log('cancel!')
}
</script>
<template> <template>
<div class="custom-upload-container" v-loading="uploadLoading" element-loading-text="文件上传中,请耐心等待,期间切勿进行任何操作,避免文件上传失败导致丢失。"> <div style="padding: 10px 0;">
<el-upload <el-upload drag action="" :auto-upload="false" :file-list="fileList" :on-change="handleFileChange"
v-if="buttonPermission.indexOf('upload') >= 0" :show-file-list="false" :limit="limit" :on-exceed="handleExceed">
:file-list="FileList"
:show-file-list="false"
class="upload-demo"
action="/"
drag
multiple
:before-upload="beforeUpload"
:on-success="handleAvatarSuccess"
:limit="limit"
:prompt="prompt"
>
<!-- <el-button
icon="Upload"
type="primary"
:loading="uploadLoading">上传文件</el-button> -->
<div class="upload-back">
<div class="flex-container"> <div class="flex-container">
<!-- <img class="logo-upload" :src="logoUpload" alt=""> -->
<div> <div>
<el-icon :size="52" color="rgb(51, 153, 255)"> <el-icon :size="52" color="rgb(51, 153, 255)">
<upload-filled /> <upload-filled />
...@@ -255,122 +12,41 @@ const cancelEvent = () => { ...@@ -255,122 +12,41 @@ const cancelEvent = () => {
<div class="accept-type-container">{{ props.prompt }}</div> <div class="accept-type-container">{{ props.prompt }}</div>
</div> </div>
</div> </div>
</div>
</el-upload> </el-upload>
<el-row style="padding-top: 8px;" v-if="FileList&&FileList.length>0 && listShow"> </div>
<el-table :data="FileList"> </template>
<el-table-column
type="index"
width="65"
align="center"
fixed="left"
label="序号"/>
<el-table-column
prop="name"
align="left"
min-width="160"
:show-overflow-tooltip="true"
label="名称">
<template v-slot="scope">
{{ scope.row.name }}
</template>
</el-table-column>
<el-table-column
v-if="needType"
prop="fileType"
align="left"
:show-overflow-tooltip="true"
label="类型">
<template v-slot="scope">
{{ scope.row.fileType }}
</template>
</el-table-column>
<el-table-column
v-if="needSize"
align="left"
width="140"
prop="fileSize"
label="大小(KB)">
<template v-slot="scope">
{{ Number(scope.row.fileSize)/1000 }}
</template>
</el-table-column>
<el-table-column
v-if="needStatus"
align="center"
prop="name"
label="上传状态"
min-width="140">
<template v-slot="scope">
<template v-if="scope.row.status === 'success' || scope.row.name || scope.row.url"><el-tag class="ml-2" type="success">上传成功</el-tag></template>
<template v-else-if="scope.row.status === 'error'"><el-tag class="ml-2" type="danger">上传失败</el-tag></template>
<el-progress v-else :percentage="scope.row.progress"/>
</template>
</el-table-column>
<el-table-column
v-if="needTime"
align="left"
min-width="200"
prop="createTime"
label="上传时间" />
<el-table-column
align="center"
fixed="right"
label="操作"
width="200">
<template #default="scope">
<el-button
link
icon="View"
type="primary"
size="small"
:disabled="scope.row.status === 'error' || scope.row.status === 'uploading'"
@click="handlePreviewFile(scope.row)"
>预览</el-button>
<el-button
link
icon="Download"
type="primary"
size="small"
:disabled="scope.row.status === 'error' || scope.row.status === 'uploading'"
@click="handleDownFile(scope.row)">下载</el-button>
<el-popconfirm <script setup>
v-if="buttonPermission.indexOf('delete') >= 0" import { ref, watch, defineProps, defineEmits } from 'vue';
confirm-button-text="确认" const props = defineProps({
cancel-button-text="取消" prompt: {
icon-color="#626AEF" type: String,
title="确认删除?" default: '点击或拖拽文件到此处进行上传'
@confirm="handleDeleteFile(scope.$index)" },
@cancel="cancelEvent" loading: Boolean,
> limit: {
<template #reference> type: Number,
<el-button default: 1
link },
icon="Delete" fileList: {
type="primary" type: Array,
size="small" default: () => []
:disabled="scope.row.status === 'uploading'" }
>删除</el-button> });
</template> const emit = defineEmits(['file-change']);
</el-popconfirm>
// 处理文件数量超出限制
const handleExceed = (files, uploadFiles) => {
emit('file-change', files[0]);
};
</template> const handleFileChange = (file, fileList) => {
</el-table-column> emit('file-change', file, fileList);
</el-table> };
</el-row> </script>
</div>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
.custom-upload-container { :deep(.el-upload){
width: 100%;
border-radius: 8px;
}
:deep(.el-upload){
width: 100%; width: 100%;
.flex-container { .flex-container {
display: flex; display: flex;
...@@ -382,12 +58,4 @@ const cancelEvent = () => { ...@@ -382,12 +58,4 @@ const cancelEvent = () => {
} }
} }
} }
.upload-demo {
// padding-top: 24px;
// padding-bottom: 16px;
}
.upload-item {
margin-left: 5px;
}
</style> </style>
...@@ -8,7 +8,7 @@ import AddClass from './modules/AddClass.vue' // 分类 ...@@ -8,7 +8,7 @@ import AddClass from './modules/AddClass.vue' // 分类
import AddValue from './modules/AddValue.vue' // 值 import AddValue from './modules/AddValue.vue' // 值
import uploadModule from './modules/uploadModule.vue' // 上传模块 import uploadModule from './modules/uploadModule.vue' // 上传模块
import { dictinaryTypes, query, delDictionaryType, delValue } from '@/api/ruleConfig/dictionary' import { dictinaryTypes, query, delDictionaryType, delValue, exportExcel } from '@/api/ruleConfig/dictionary'
const splitNum = ref(0.31) // 左右分割比例 const splitNum = ref(0.31) // 左右分割比例
...@@ -118,7 +118,7 @@ const modalConfirm = () => { ...@@ -118,7 +118,7 @@ const modalConfirm = () => {
} }
if (value === queryParams.value.typecode) { if (value === queryParams.value.typecode) {
getData() getData()
}else{ } else {
getData('class') getData('class')
} }
}) })
...@@ -143,7 +143,7 @@ const modalConfirm = () => { ...@@ -143,7 +143,7 @@ const modalConfirm = () => {
// 分类查看 // 分类查看
const classView = (item) => { const classView = (item) => {
if(queryParams.value.typecode === item.value) return if (queryParams.value.typecode === item.value) return
queryParams.value.typecode = item.value queryParams.value.typecode = item.value
queryParams.value.typename = item.text queryParams.value.typename = item.text
getTableData() getTableData()
...@@ -159,6 +159,7 @@ const AddDomainConfirm = (item) => { ...@@ -159,6 +159,7 @@ const AddDomainConfirm = (item) => {
console.log('导入', item) console.log('导入', item)
getTableData() getTableData()
} }
modalPopData.type = ''
modalPopData.show = false modalPopData.show = false
} }
...@@ -172,7 +173,7 @@ const importClick = () => { ...@@ -172,7 +173,7 @@ const importClick = () => {
// 获取分类名称 // 获取分类名称
const getClassName = (value) => { const getClassName = (value) => {
const item = classList.value.find(item => item.value === value) const item = classList.value.find(item => item.value === value)
return item? item.text : '' return item ? item.text : ''
} }
// 获取列表数据 // 获取列表数据
...@@ -183,7 +184,7 @@ const getData = (type) => { ...@@ -183,7 +184,7 @@ const getData = (type) => {
if (classList.value.length <= 0) return if (classList.value.length <= 0) return
if (type === 'class') { if (type === 'class') {
getTableData() getTableData()
}else { } else {
queryParams.value.typecode = classList.value[0].value queryParams.value.typecode = classList.value[0].value
queryParams.value.typename = classList.value[0].text queryParams.value.typename = classList.value[0].text
getTableData() getTableData()
...@@ -200,6 +201,21 @@ const getTableData = () => { ...@@ -200,6 +201,21 @@ const getTableData = () => {
}) })
} }
// 导出excel
const exportExcelFunc = () => {
exportExcel({ typecode: queryParams.value.typecode }).then(response => {
const { data } = response;
const blob = new Blob([response], { type: 'application/vnd.ms-excel,charset=utf-8' });
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `${queryParams.value.typename}知识库.xlsx`
link.click()
URL.revokeObjectURL(link.href)
ElMessage.success('导出成功')
})
}
onMounted(() => { onMounted(() => {
getData() getData()
}) })
...@@ -249,7 +265,7 @@ onMounted(() => { ...@@ -249,7 +265,7 @@ onMounted(() => {
</el-form-item> </el-form-item>
<div style="display: flex;"> <div style="display: flex;">
<el-button icon="Upload" type="primary" @click="importClick">导入</el-button> <el-button icon="Upload" type="primary" @click="importClick">导入</el-button>
<el-button icon="Download" type="success">导出</el-button> <el-button icon="Download" type="success" @click="exportExcelFunc">导出</el-button>
<el-button icon="Plus" type="primary" @click="addValueClick('add')">新增值</el-button> <el-button icon="Plus" type="primary" @click="addValueClick('add')">新增值</el-button>
</div> </div>
</div> </div>
...@@ -287,8 +303,8 @@ onMounted(() => { ...@@ -287,8 +303,8 @@ onMounted(() => {
<template #content> <template #content>
<AddClass :itemData="addClassForm" :type="modalPopData.operation" @cancel="modalPopCancel" <AddClass :itemData="addClassForm" :type="modalPopData.operation" @cancel="modalPopCancel"
@confirm="AddDomainConfirm" v-if="modalPopData.type === 'class'" /> @confirm="AddDomainConfirm" v-if="modalPopData.type === 'class'" />
<AddValue :itemData="addValueForm" :type="modalPopData.operation" :classDict="classList" @cancel="modalPopCancel" <AddValue :itemData="addValueForm" :type="modalPopData.operation" :classDict="classList"
@confirm="AddDomainConfirm" v-if="modalPopData.type === 'value'" /> @cancel="modalPopCancel" @confirm="AddDomainConfirm" v-if="modalPopData.type === 'value'" />
<uploadModule @cancel="modalPopCancel" @confirm="AddDomainConfirm" v-if="modalPopData.type === 'upload'" /> <uploadModule @cancel="modalPopCancel" @confirm="AddDomainConfirm" v-if="modalPopData.type === 'upload'" />
</template> </template>
</ModalPop> </ModalPop>
......
<script setup lang="ts" name="AddClass"> <script setup lang="ts" name="AddClass">
import { ref } from "vue"; import { ref, reactive } from "vue";
import CustomUpload from "@/components/CustomUpload/index.vue" import { ElMessage } from "element-plus";
import CustomUpload from "@/components/CustomUpload/index.vue";
import { importfile } from "@/api/ruleConfig/dictionary";
const emit = defineEmits(["update:modelValue", "cancel", "confirm"]); const emit = defineEmits(["cancel", "confirm"]);
const radioValue = ref(1); const uploadLoading = ref(false);
const fileList = ref<File[]>([]); const uploadFile = ref({});
const smart = ref(1)
// 取消 // 取消
const cancel = () => { const cancel = () => {
...@@ -14,32 +17,45 @@ const cancel = () => { ...@@ -14,32 +17,45 @@ const cancel = () => {
// 确认 // 确认
const confirm = () => { const confirm = () => {
console.log(fileList.value);
// emit("confirm"); // emit("confirm");
if (!uploadFile.value.name) {
ElMessage.error("请先选择文件");
return;
}
uploadLoading.value = true;
const formData = new FormData();
formData.append('fileUpload', uploadFile.value.raw);
formData.append('smart', smart.value.toString());
importfile(formData).then((res) => {
const { flag } = res;
if (flag) {
uploadLoading.value = false;
ElMessage.success('导入成功');
emit("confirm");
}
});
}; };
const handleUpload = (file: File) => { const handleFileChange = (file) => {
console.log(file); uploadFile.value = file;
// 上传文件
// 处理上传结果
// 更新modelValue
}; };
</script> </script>
<template> <template>
<div> <div>
<div class="mb20"> <div class="mb20">
<CustomUpload v-model:file-list="fileList" :limit="1" :needType="false" :needSize="false" :listShow="false" prompt='点击或拖拽文件到此处上传' /> <CustomUpload :prompt='uploadFile ? uploadFile.name : ""' :loading="uploadLoading"
@file-change="handleFileChange" />
</div> </div>
<el-form-item label="上传方式" label-width="200px"> <el-form-item label="上传方式" label-width="200px">
<el-radio-group v-model="radioValue"> <el-radio-group v-model="smart">
<el-radio :label="1">覆盖原数据</el-radio> <el-radio :label="1">覆盖原数据</el-radio>
<el-radio :label="2">追加数据</el-radio> <el-radio :label="0">追加数据</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<div class="btn"> <div class="btn">
<el-button type="info" style="width: 150px;" @click="cancel">取消</el-button> <el-button type="info" style="width: 150px;" @click="cancel">取消</el-button>
<el-button type="primary" style="width: 150px;" @click="confirm">确认</el-button> <el-button type="primary" :loading="uploadLoading" style="width: 150px;" @click="confirm">确认</el-button>
</div> </div>
</div> </div>
</template> </template>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论