feat: 导入样式调整

pull/1/head
刘释隆 1 year ago
parent c751e6baa7
commit 31f04b7ee1

@ -1,197 +1,200 @@
<script lang="ts" setup>
import { reactive, ref, unref } from 'vue'
import * as XLSX from 'xlsx'
import { arrayEquals } from '@/utils/index'
import { generateUuid } from '@/utils/uuid'
import { reactive, ref, unref } from "vue";
import * as XLSX from "xlsx";
import { arrayEquals } from "@/utils/index";
import { generateUuid } from "@/utils/uuid";
const props = defineProps<{
onSuccess: Function
headerConfig: string[]
}>()
onSuccess: Function;
headerConfig: string[];
}>();
interface ExcelData {
header: string[] | null
content: any[] | null
header: string[] | null;
content: any[] | null;
}
interface ParseResults {
fileName: string
results: any[]
uuid: string
fileName: string;
results: any[];
uuid: string;
}
const cardStyle = {
'width': '620px',
'--n-padding-bottom': '10px',
'--n-padding-left': '0px',
}
const inputRef = ref(null)
let loading = false
const excelData: ExcelData = { header: null, content: null }
const excelDatas: ParseResults[] = reactive([])
width: "620px",
"--n-padding-bottom": "10px",
"--n-padding-left": "0px",
};
const inputRef = ref(null);
let loading = false;
const excelData: ExcelData = { header: null, content: null };
const excelDatas: ParseResults[] = reactive([]);
function generateData(content) {
excelData.header = props.headerConfig
excelData.content = content
props.onSuccess && props.onSuccess(excelData)
excelData.header = props.headerConfig;
excelData.content = content;
props.onSuccess && props.onSuccess(excelData);
}
function handleDrop(e) {
e.stopPropagation()
e.preventDefault()
if (loading)
return
const files = e.dataTransfer.files
const rawFiles = Array.from(files)
e.stopPropagation();
e.preventDefault();
if (loading) return;
const files = e.dataTransfer.files;
const rawFiles = Array.from(files);
// eslint-disable-next-line dot-notation
const $message = window['$message']
const $message = window["$message"];
if (!isExcel(rawFiles)) {
$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
return false
$message.error("Only supports upload .xlsx, .xls, .csv suffix files");
return false;
}
uploadFiles(rawFiles)
e.stopPropagation()
e.preventDefault()
uploadFiles(rawFiles);
e.stopPropagation();
e.preventDefault();
}
async function uploadFiles(files) {
const inputEl: HTMLInputElement | null = unref(inputRef)
inputEl!.value = ''
const inputEl: HTMLInputElement | null = unref(inputRef);
inputEl!.value = "";
loading = true
loading = true;
for (const file of files) {
const fileData = await readFileData(file)
const message = validate(fileData)
const fileData = await readFileData(file);
const message = validate(fileData);
// TODO
if (message === undefined || true) {
const uuid = generateUuid()
const uuid = generateUuid();
excelDatas.push({
fileName: file.name,
results: (fileData as any).results,
uuid,
})
});
}
}
loading = false
loading = false;
}
function commitData() {
const mergeResults: any[] = []
const mergeResults: any[] = [];
if (excelDatas.length === 0)
return
if (excelDatas.length === 0) return;
excelDatas.forEach((item) => {
mergeResults.push(...item.results)
})
mergeResults.push(...item.results);
});
generateData(mergeResults)
generateData(mergeResults);
}
function validate(fileData) {
const { header } = fileData
const { header } = fileData;
//
const equal = arrayEquals(header, props.headerConfig)
const equal = arrayEquals(header, props.headerConfig);
if (!equal)
return '表头不匹配'
if (!equal) return "表头不匹配";
// TODO
}
function readFileData(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target!.result
const workbook = XLSX.read(data, { type: 'array' })
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
const header = getHeaderRow(worksheet)
const results = XLSX.utils.sheet_to_json(worksheet)
resolve({ header, results })
}
reader.readAsArrayBuffer(file)
})
const data = e.target!.result;
const workbook = XLSX.read(data, { type: "array" });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const header = getHeaderRow(worksheet);
const results = XLSX.utils.sheet_to_json(worksheet);
resolve({ header, results });
};
reader.readAsArrayBuffer(file);
});
}
function handleDragover(e) {
e.stopPropagation()
e.preventDefault()
e.dataTransfer.dropEffect = 'copy'
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
}
function handleUpload() {
(inputRef.value as any).click()
(inputRef.value as any).click();
}
function handleClick(e) {
const files = e.target.files
const rawFiles = Array.from(files)
uploadFiles(rawFiles)
const files = e.target.files;
const rawFiles = Array.from(files);
uploadFiles(rawFiles);
}
function getHeaderRow(sheet) {
const headers: string[] = []
const range = XLSX.utils.decode_range(sheet['!ref'])
let C
const R = range.s.r
const headers: string[] = [];
const range = XLSX.utils.decode_range(sheet["!ref"]);
let C;
const R = range.s.r;
/* start in the first row */
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
for (C = range.s.c; C <= range.e.c; ++C) {
/* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
/* find the cell in the first row */
let hdr = `UNKNOWN ${C}` // <-- replace with your desired default
if (cell && cell.t)
hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
let hdr = `UNKNOWN ${C}`; // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
headers.push(hdr);
}
return headers
return headers;
}
function isExcel(files) {
return files.every((file) => {
return /\.(xlsx|xls|csv)$/.test(file.name)
})
return /\.(xlsx|xls|csv)$/.test(file.name);
});
}
const show = ref(false)
const show = ref(false);
function showModal() {
show.value = true
show.value = true;
}
function closeModal() {
show.value = false
show.value = false;
}
async function handleSumbit(e: MouseEvent) {
e.preventDefault()
commitData()
closeModal()
e.preventDefault();
commitData();
closeModal();
}
defineExpose({
showModal,
})
});
function removeHandler(id: string) {
const index = excelDatas.findIndex(item => item.uuid === id)
excelDatas.splice(index, 1)
const index = excelDatas.findIndex((item) => item.uuid === id);
excelDatas.splice(index, 1);
}
function afterLeave() {
excelDatas.length = 0
excelDatas.length = 0;
}
</script>
<template>
<n-modal v-model:show="show" transform-origin="center" @after-leave="afterLeave">
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<n-card
:style="cardStyle"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<div class="wrapper">
<div class="wrapper-header">
<span class="wrapper-left">批量导入</span>
@ -203,17 +206,41 @@ function afterLeave() {
</div>
<n-divider />
<div class="wrapper-content">
<div class="wrapper-content-dragger" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
<input ref="inputRef" class="excel-upload-input" type="file" accept=".xlsx, .xls,.csv" @change="handleClick">
<SvgIcon style="margin-top: 30px;" size="45" name="upload" @click="handleUpload" />
<span style="margin-top: 20px;" class="wrapper-tip1">点击或拖拽审批文件到这里上传</span>
<span style="margin-top: 15px;margin-bottom: 20px;" class="wrapper-tip2">支持上传格式.xls .xlsx .csv的文件</span>
<div
class="wrapper-content-dragger"
@drop="handleDrop"
@dragover="handleDragover"
@dragenter="handleDragover"
>
<input
ref="inputRef"
class="excel-upload-input"
type="file"
accept=".xlsx, .xls,.csv"
@change="handleClick"
/>
<SvgIcon
style="margin-top: 32px; margin-bottom: 13px"
size="45"
name="upload"
@click="handleUpload"
/>
<span class="wrapper-tip1">点击或拖拽审批文件到这里上传</span>
<span style="margin-top: 3px; margin-bottom: 19px" class="wrapper-tip2"
>支持上传格式.xls .xlsx .csv的文件</span
>
</div>
<div v-for="(item, index) in excelDatas" :key="index" class="wrapper-content-files">
<div
v-for="(item, index) in excelDatas"
:key="index"
class="wrapper-content-files"
>
<div>{{ item.fileName }}</div>
<div>
<SvgIcon
size="16px" style="display: block; margin-left: auto; cursor: pointer" name="clear"
size="16px"
style="display: block; margin-left: auto; cursor: pointer"
name="clear"
@click="removeHandler(item.uuid)"
/>
</div>
@ -222,9 +249,7 @@ function afterLeave() {
</div>
<template #footer>
<div class="footer">
<n-button type="info" @click="handleSumbit">
确认
</n-button>
<n-button type="info" @click="handleSumbit"> </n-button>
</div>
</template>
</n-card>
@ -237,34 +262,41 @@ function afterLeave() {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
padding: 6px 0 0 24px;
// padding: 10px;
}
&-left {
font-weight: bold;
font-size: 16px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: bolder;
text-align: left;
color: #222222;
line-height: 24px;
}
&-right {
&-close {
width: 18px;
height: 18px;
width: 12px;
height: 12px;
cursor: pointer;
margin-right: 25px;
color: #999999;
}
&-icon {
background: #000;
display: inline-block;
width: 18px;
width: 12px;
height: 1px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
margin-bottom: 8px;
&:after {
content: '';
content: "";
display: block;
width: 18px;
width: 12px;
height: 1px;
background: #000;
transform: rotate(-90deg);
@ -274,19 +306,18 @@ function afterLeave() {
}
&-content {
margin-top: 20px;
margin: 33px 24px 0 25px;
&-dragger {
display: flex;
flex-direction: column;
align-items: center;
border: 1px dashed #1980FF;
width: 600px;
margin: 0 auto;
border: 1px dashed #1980ff;
// width: 600px;
font-size: 14px;
font-weight: bold;
border-radius: 2px;
text-align: center;
background: rgba(202, 210, 221, 0.1);
}
&-files {
@ -297,7 +328,6 @@ function afterLeave() {
justify-content: space-between;
}
}
}
.excel-upload-input {
@ -324,4 +354,19 @@ function afterLeave() {
margin-top: 0px;
margin-bottom: 0px;
}
.wrapper-tip1 {
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: lighter;
color: #666666;
line-height: 24px;
}
.wrapper-tip2 {
font-size: 12px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: lighter;
text-align: left;
color: #999999;
line-height: 22px;
}
</style>

Loading…
Cancel
Save