| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- <!-- 资料导入 -->
- <template>
- <hc-new-dialog v-model="dataModal" title="资料导入" :loading="confirmLoading" @close="closeModal">
- <div style="position: relative;">
- <el-upload
- ref="dialogUploadRef" :headers="getHeader()" drag
- action="/api/blade-manager/wbsTreeContract/import-node-excel"
- :data="{ nodeId, classify }"
- :on-success="handleSuccess" :on-error="handleError" accept=".xls,.xlsx"
- :auto-upload="false"
- :limit="1"
- :on-exceed="handleExceed"
- :before-upload="beforeUpload"
- :show-file-list="false"
- :on-change="handleChange"
- >
- <div class="mt-24px text-black">将文件拖动到此处,<span class="text-blue">或点击上传</span></div>
- <div class="mt-8px text-12px">支持的文件格式:.xls,.xlsx</div>
- </el-upload>
- <!-- 自定义文件列表 -->
- <div v-if="fileList.length > 0" class="upload-file-list mt-4">
- <div v-for="file in fileList" :key="file.uid" class="mb-2 flex items-center justify-between border rounded p-2">
- <div class="flex items-center">
- <HcIcon name="file-excel" class="mr-2 text-green-500" />
- <span>{{ file.name }}{{ file.uid }}</span>
- </div>
- <el-button type="danger" link @click="handleRemove(file)">
- <HcIcon name="delete" />
- </el-button>
- </div>
- </div>
- <div class="download-btn-container mt-2 text-right">
- <el-button hc-btn type="primary" :loading="downLoadTemplateLoading" @click="downLoadTemplate">
- <HcIcon name="download-2" />
- 下载模板
- </el-button>
- </div>
- </div>
- <template #footer>
- <el-button @click="closeModal">取消</el-button>
- <el-button type="primary" :loading="confirmLoading" @click="confirmTap">确认上传</el-button>
- </template>
- </hc-new-dialog>
- </template>
- <script setup>
- import { nextTick, ref, watch } from 'vue'
- import { isNullES } from 'js-fast-way'
- import { getHeader } from 'hc-vue3-ui'
- import divisionApi from '~api/data-fill/division'
- const props = defineProps({
- nodeId: {
- type: String,
- default: '',
- },
- classify: {
- type: String,
- default: '',
- },
-
-
- })
- //事件
- const emit = defineEmits(['close', 'save', 'success'])
- const nodeId = ref(props.nodeId)
- const classify = ref(props.classify)
- watch(
- () => [props.nodeId, props.classify],
- ([nid, clas]) => {
- nodeId.value = nid
- classify.value = clas
- fileList.value = []
- },
- )
- const dataModal = defineModel('modelValue', {
- default: false,
- })
- const closeModal = ()=>{
- dataModal.value = false
- fileList.value = []
-
- emit('close')
- }
- //上传文件
- const dialogUploadRef = ref(null)
- const pKeyIdData = ref('')
- // 文件类型验证
- const beforeUpload = (file) => {
- const extension = file.name.split('.').pop().toLowerCase()
- if (!['xls', 'xlsx'].includes(extension)) {
- window.$message.error('仅支持上传 .xls 或 .xlsx 格式的表格文件')
- return false
- }
- return true
- }
- // 添加以下数据和方法
- const fileList = ref([])
- const handleChange = (file) => {
- fileList.value = [file] // // 由于限制为1个文件,直接替换
- console.log('fileList', fileList)
- }
- const handleRemove = (file) => {
- fileList.value = fileList.value.filter(item => item.uid !== file.uid)
- dialogUploadRef.value?.clearFiles()
- }
- const handleExceed = (files) => {
- dialogUploadRef.value.clearFiles()
- const file = files[0]
- dialogUploadRef.value.handleStart(file)
- }
- //上传成功
- const confirmLoading = ref(false)
- const handleSuccess = (res) => {
- confirmLoading.value = false
- if (res.code === 200) {
- window.$message.success(res.msg || '上传成功')
- emit('success', res)
- nextTick(()=>{
- fileList.value = []
- })
- closeModal()
- } else {
-
- window.$message.error(res.msg || '上传失败')
- nextTick(()=>{
- fileList.value = []
- })
- }
- }
- //上传失败
- const handleError = (error) => {
- confirmLoading.value = false
- const { msg } = !isNullES(error.message) ? JSON.parse(error.message) : {}
- if (isNullES(msg)) {
- window.$message.error('上传失败')
- } else {
- window.$message.error(msg)
- }
- fileList.value = []
- }
- const confirmTap = async ()=>{
- if (!fileList.value.length) {
- window.$message.warning('请先选择文件')
- return
- }
- confirmLoading.value = true
- dialogUploadRef.value.submit()
- }
- const parseFileName = (disposition) => {
- const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
- const matches = filenameRegex.exec(disposition)
- if (matches && matches[1]) {
- return decodeURIComponent(matches[1].replace(/['"]/g, ''))
- }
- return 'unknown'
- }
- const downloadBlob1 = (data, disposition = '', type = 'application/vnd.ms-excel')=> {
- const blob = new Blob([data], { type: type })
- const blobURL = window.URL.createObjectURL(blob)
- const tempLink = document.createElement('a')
- tempLink.style.display = 'none'
- tempLink.href = blobURL
-
- // 1. 解析文件名
- let filename = parseFileName(disposition)
-
- // 2. 关键修复:过滤特殊字符并确保.xlsx后缀
- // 过滤不安全字符:#、/、%等,替换为_
- filename = filename.replace(/[#%/\\:*?"<>|]/g, '_')
- // 强制确保以.xlsx结尾(移除可能的多余字符)
- if (!filename.endsWith('.xlsx')) {
- // 先移除现有后缀(如果有),再补全.xlsx
- filename = filename.replace(/\.[^.]*$/, '') + '.xlsx'
- }
-
- tempLink.setAttribute('download', filename)
- if (typeof tempLink.download === 'undefined') {
- tempLink.setAttribute('target', '_blank')
- }
- document.body.appendChild(tempLink)
- tempLink.click()
- document.body.removeChild(tempLink)
- window.URL.revokeObjectURL(blobURL)
- }
- // 导入模板
- const downLoadTemplate = async ()=>{
- downLoadTemplateLoading.value = true
- const { error, disposition, res, msg } = await divisionApi.downloadNodeExcel({
- nodeId:nodeId.value,
- classify:classify.value,
- })
- downLoadTemplateLoading.value = false
- if (!error) {
- if (disposition) {
- downloadBlob1(res, disposition)
- } else {
- window.$message?.error(msg || '数据异常')
- }
- }
- }
- const downLoadTemplateLoading = ref(false)
- //获取两棵树的数据
- </script>
- <style lang='scss' scoped>
- .download-btn-container {
- overflow: hidden; /* 限制溢出,避免尺寸变化导致滚动 */
- white-space: nowrap; /* 防止按钮内容换行导致高度变化 */
- }
- </style>
|