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