最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

el-upload二次封裝帶表格校驗(yàn)組件

 更新時(shí)間:2026年03月24日 08:25:40   作者:雨季mo淺憶  
本文介紹了一個(gè)前端Excel文件上傳校驗(yàn)組件的實(shí)現(xiàn)方案,該組件基于Element UI的el-upload封裝,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

需求背景:項(xiàng)目里的附件上傳以往都是通過調(diào)用后端上傳附件接口,由后端接口負(fù)責(zé)校驗(yàn)附件以及表單規(guī)則,項(xiàng)目經(jīng)理現(xiàn)為了優(yōu)化性能,決定由前端先行校驗(yàn)表格內(nèi)部分基礎(chǔ)規(guī)則內(nèi)容(如判斷是否為空表格,列表項(xiàng)內(nèi)容是否滿足要求的格式,文件類型(.xls/.xlsx)等基礎(chǔ)校驗(yàn) Excel內(nèi)容校驗(yàn):通過xlsx庫解析Excel文件,實(shí)現(xiàn)以下校驗(yàn)規(guī)則: 非空校驗(yàn)(N) 長度限制校驗(yàn) 數(shù)字文本校驗(yàn)(VI) 評分校驗(yàn)(VII,0-100保留1位小數(shù)) 整數(shù)校驗(yàn)(IS,1-100整數(shù)) 合并單元格處理等等,校驗(yàn)結(jié)果反饋:通過Message組件展示提示詞),前端基礎(chǔ)校驗(yàn)通過后再調(diào)用后端上傳接口。

封裝組件:

webUploadFile.vue

<template>
  <div style="display: inline-flex">
    <el-upload
      class="upload-file"
      ref="attachUpload"
      accept="*"
      :auto-upload="autoUpload"
      :multiple="false"
      :limit="1"
      :action="uploadFileUrl"
      :headers="headers"
      :file-list="fileList"
      :before-upload="beforeAvatarUpload"
      :on-success="uploadSuccessHandle"
      :on-error="uploadErrorHandle"
      :data="fetchData"
    >
      <el-button size="mini" type="danger" icon="el-icon-upload2" :plain="plain">點(diǎn)擊上傳</el-button>
      <!-- <span v-if="successVisible">未選擇文件</span> -->
    </el-upload>
  </div>
</template>
<script>
import { getToken } from '@/utils/auth';
import uploadExcel from '@/utils/importValidate.js';
export default {
  name: 'uploadFile',
  props: {
    // 上傳文件接口地址
    uploadFileUrl: {
      type: String,
      default: () => ''
    },
    // 從第幾行開始校驗(yàn)數(shù)據(jù)
    num: {
      type: Number,
      default: 1
    },
    // 校驗(yàn)規(guī)則數(shù)組
    ruleArr: {
      type: Array,
      default: () => []
    },
    // 是否自動上傳
    autoUpload: {
      type: Boolean,
      default: false
    },
    // 是否補(bǔ)緊按鈕
    plain: {
      type: Boolean,
      default: false
    },
    fetchData: {
      type: Object
    },
    sucessText: {
      type: String,
      default: () => '附件導(dǎo)入成功'
    }
  },
  data() {
    return {
      fileAllowFiles: '.xls,.xlsx',
      // uploadFileUrl: `${process.env.VUE_APP_BASE_API}/api/common/upload`
      headers: {
        Authorization: getToken()
      },
      successVisible: true,
      fileListData: []
    };
  },
  computed: {
    // 商家名稱的值
    fileList: {
      get() {
        return this.fileListData;
      },
      set(val) {
        this.$emit('update:fileListData', val);
      }
    }
  },
  methods: {
    // 上傳文件之前的鉤子
    beforeAvatarUpload(file, fileList) {
      const size = file.size / 1024 / 1024 > 20;
      let arr = file.name.split('.');
      let fileType = arr[arr.length - 1].toLowerCase();
      return new Promise((resolve, reject) => {
        if (size) {
          this.$message.warning('上傳文件不能大于20M');
          this.$emit('getResult', false);
          return reject(false);
        } else if (!this.fileAllowFiles.includes(fileType)) {
          this.$message.warning(`不支持上傳${fileType}類型的文件,請重傳`);
          this.$emit('getResult', false);
          return reject(false);
        }
        uploadExcel(file, this.ruleArr, this.num).then((res) => {
          if (!res) {
            this.$emit('getResult', false);
            return reject(false);
          } else {
            return resolve(true);
          }
        });
      });
    },
    // 文件上傳成功時(shí)的鉤子
    uploadSuccessHandle(response, file, fileList) {
      if (response.code === 200) {
        if (fileList.length > 0) {
          this.$refs.attachUpload.uploadFiles = [];
          this.$refs.attachUpload.uploadFiles.push(file);
          this.successVisible = false;
        }
        // 在線簽署管理== 同一個(gè)接口既需要文件上傳又需要走公共的request code等于非200無法校驗(yàn)
        if (response.data === null) {
          this.$message.success(this.sucessText);
        }
        this.$emit('getResult', false, response);
        this.$emit('uploadSuccess', this.$refs.attachUpload.uploadFiles);
      } else {
        this.$emit('getResult', false, response);
      }
    },
    uploadErrorHandle(err) {
      this.$message.error('服務(wù)器開個(gè)小差,請稍后再試');
      this.$emit('getResult', false);
    }
  }
};
</script>
<style lang="less" scoped>
.upload-file {
  .el-upload {
    .el-button--default {
      width: 100px;
      height: 38px;
      background: #ffffff !important;
      font-family: MicrosoftYaHei;
      font-size: 14px;
      color: #9c9c9c;
      font-weight: 400;
      border: 1px solid rgba(221, 221, 221, 1);
    }
    /deep/ .el-upload-list__text {
      min-width: 250px;
    }
  }
}
</style>

JavaScript 邏輯代碼文件:

importValidate.js

import * as XLSX from "xlsx";
import { Message } from "element-ui";
// 調(diào)用各種數(shù)據(jù)類型的校驗(yàn)函數(shù):
// "V": 類似varchar,可以任意字符,只需要校驗(yàn)長度
// "VM": 類似varchar,不能包含"'"及"&",需要校驗(yàn)長度
// "VA": 類似varchar,可以包括 /^[^'"\\()@$%^*<>&?]*$/,任意字符,只需要校驗(yàn)長度
// "VN": 類似varchar,任意字符但不可以包括/^[^<>\"]+$/,需要校驗(yàn)長度
// "C": 類似char,可以任意字符,只需要校驗(yàn)長度
// "N": 類似number(8.3)
// "I": 類似int
// "IS": 分?jǐn)?shù)校驗(yàn),只可以是1—100的整數(shù)
// "VI": 類似varchar,但只能是數(shù)字,要校驗(yàn)長度
// "VS": 類似varchar,但只能是數(shù)字,要校驗(yàn)長度,且只能輸入1至7
// "VT": 類似varchar,但只能是數(shù)字,要校驗(yàn)長度,且只能輸入1至10
// "VP": 類似varchar,但只能是數(shù)字,要校驗(yàn)長度,且只能輸入大于1
// "CI": 類似char,但只能是數(shù)字,要校驗(yàn)長度
// "ID": 業(yè)務(wù)編號校驗(yàn)
// "D": 日期,8位,yyyymmdd,規(guī)則必須是"D::N"或"D::Y"
// "M": 郵件地址,類似varchar,但其中允許有"@"
// "LN": 檢查輸入僅限英文半角字符和數(shù)字,檢查長度
// "CN": 檢查輸入僅限數(shù)字字符串,檢查長度
// "EN": 檢查輸入僅限英文半角字符串,檢查長度
function isDate1(str) {
  // YYYYMM
  if (String(str).length !== 6) {
    return false;
  }
  let y = String(str).substring(0, 4);
  let m = String(str).substring(4, 6) - 1;
  let date = new Date(y, m);
  if (date.getFullYear() === y && date.getMonth() === m) {
    return true;
  } else {
    return false;
  }
}
function isDate(str) {
  // YYYYMMDD
  if (String(str).length !== 8) {
    return false;
  }
  let y = String(str).substring(0, 4);
  let m = String(str).substring(4, 6) - 1;
  let d = String(str).substring(6, 8);
  let date = new Date(y, m, d);
  if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d) {
    return true;
  } else {
    return false;
  }
}
function trim(str) {
  let returnstr = "";
  if (str === "") return "";
  let i = 0;
  for (i = 0; i < str.length; i++) {
    if (str.charAt(i) === " ") {
      continue;
    }
    break;
  }
  // str = "" + str;
  str = str.substring(i, str.length);
  if (str === "") return "";
  for (i = str.length - 1; i >= 0; i--) {
    if (str.charAt(i) === " ") {
      continue;
    }
    break;
  }
  returnstr = str.substring(0, i + 1);
  return returnstr;
}
function isDigit(theNum) {
  let theMask = "0123456789";
  if (isEmpty(theNum)) return false;
  else if (theMask.indexOf(theNum) === -1) return false;
  return true;
}
function isEmpty(e) {
  let newString = trim(e);
  if (newString === null || newString === "") return true;
  else return false;
}
function isInt(theStr) {
  let flag = true;
  theStr = trim(theStr);
  if (isEmpty(theStr)) flag = true;
  else {
    if (theStr.substring(0, 1) === "-") {
      theStr = theStr.substring(1);
    }
    for (let i = 0; i < theStr.length; i++) {
      if (isDigit(theStr.substring(i, i + 1)) === false) {
        flag = false;
        break;
      }
    }
  }
  return flag;
}
/**
 * 處理合并單元格并填充數(shù)據(jù)
 * @param {Object} worksheet - Excel工作表對象
 * @returns {Object} 包含處理后的二維數(shù)組和合并區(qū)域信息
 */
function processMergedCells(worksheet) {
  // 獲取工作表的范圍引用
  const range = XLSX.utils.decode_range(worksheet["!ref"]);
  // 創(chuàng)建二維數(shù)組保存數(shù)據(jù)
  const data = [];
  for (let R = range.s.r; R <= range.e.r; ++R) {
    data.push([]);
    for (let C = range.s.c; C <= range.e.c; ++C) {
      data[R].push(null);
    }
  }
  // 獲取所有合并單元格區(qū)域
  const merges = worksheet["!merges"] || [];
  const mergeMap = {};
  // 處理合并區(qū)域
  merges.forEach((merge) => {
    const start = merge.s; // 起始位置(左上角)
    const end = merge.e; // 結(jié)束位置(右下角)
    // 獲取起始位置單元格的值
    const address = XLSX.utils.encode_cell(start);
    const cellValue = worksheet[address] ? worksheet[address].v : null;
    // 將合并區(qū)域的所有單元格映射到起始單元格的值
    for (let R = start.r; R <= end.r; ++R) {
      for (let C = start.c; C <= end.c; ++C) {
        // 標(biāo)記單元格是否在合并區(qū)域中
        mergeMap[`${R}:${C}`] = true;
        // 左上角單元格標(biāo)記
        if (R === start.r && C === start.c) {
          mergeMap[`${R}:${C}`] = "top-left";
        }
        // 填充值
        data[R][C] = cellValue;
      }
    }
  });
  // 處理非合并單元格
  Object.keys(worksheet).forEach((key) => {
    if (key[0] === "!") return; // 跳過特殊鍵
    const cell = worksheet[key];
    const address = XLSX.utils.decode_cell(key);
    // 只填充尚未處理過的單元格(非合并區(qū)域)
    if (!mergeMap[`${address.r}:${address.c}`] && data[address.r][address.c] === null) {
      data[address.r][address.c] = cell.v;
    }
  });
  return { data, mergeMap };
}
function getfile(file, ruleData) {
  let listTitle = [];
  if (ruleData.length > 0) {
    for (let i = 0; i < ruleData.length; i++) {
      listTitle.push(ruleData[i].name);
    }
  } else {
    alert("請定義校驗(yàn)規(guī)則!");
    return false;
  }
  return new Promise(function (resolve, reject) {
    const reader = new FileReader();
    let result1 = [];
    reader.onload = function (e) {
      let binary = "";
      let bytes = new Uint8Array(reader.result);
      let lenth = bytes.byteLength;
      for (let i = 0; i < lenth; i++) {
        binary += String.fromCharCode(bytes[i]);
      }
      let workbook = XLSX.read(binary, { type: "binary" });
      const sheetName = workbook.SheetNames[0];
      const sheet = workbook.Sheets[sheetName];
      const { data: sheetData, mergeMap } = processMergedCells(sheet);
      const arr = { data: sheetData, mergeMap }.data;
      arr.forEach((item) => {
        const result = listTitle.reduce((obj, key, index) => {
          obj[key] = item[index];
          return obj;
        }, {});
        result1.push(result);
      });
      resolve(result1);
    };
    reader.readAsArrayBuffer(file);
  });
}
export async function uploadExcel(file, ruleData, num) {
  let result = true;
  const res = await getfile(file, ruleData);
  if (res.length === num) {
    alert("導(dǎo)入的Excel中沒有數(shù)據(jù),請校驗(yàn)");
    result = false;
    return false;
  }
  let tooptip = [];
  for (let i = num; i < res.length; i++) {
    for (let y = 0; y < ruleData.length; y++) {
      if (!res[i][ruleData[y].name] && ruleData[y].isnull === "N") {
        tooptip.push("請檢查第" + ruleData[y].name + "列第" + (i + 1) + "行有空數(shù)據(jù)請重新提交");
        result = false;
      }
      if (res[i][ruleData[y].name] && String(res[i][ruleData[y].name]).length > ruleData[y].leng) {
        tooptip.push(
          ruleData[y].name +
            "列第" +
            (i + 1) +
            "行數(shù)據(jù)不能超過" +
            ruleData[y].leng +
            "個(gè)字請重新提交",
        );
        result = false;
      }
      if (res[i][ruleData[y].name] && ruleData[y].rule === "VI") {
        let reg = /^[1-9]\d*$/;
        if (!reg.test(+res[i][ruleData[y].name])) {
          tooptip.push(ruleData[y].name + "列第" + (i + 1) + "行數(shù)據(jù)不是數(shù)字文本請重新提交");
          result = false;
        }
      }
      // 校驗(yàn)評分最大輸入100且保留一位小數(shù)
      if (res[i][ruleData[y].name] && ruleData[y].rule === "VII") {
        let reg = /^(([1-9]\d*)|(0{1}))(\.\d{1})?$/;
        if (!reg.test(res[i][ruleData[y].name])) {
          tooptip.push(
            ruleData[y].name +
              "列第" +
              (i + 1) +
              "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
          );
          result = false;
        }
        if (Number(res[i][ruleData[y].name]) !== 0 && !Number(res[i][ruleData[y].name])) {
          tooptip.push(
            ruleData[y].name +
              "列第" +
              (i + 1) +
              "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
          );
          result = false;
        }
        if (res[i][ruleData[y].name] > 100) {
          tooptip.push(
            ruleData[y].name +
              "列第" +
              (i + 1) +
              "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
          );
          result = false;
        }
      }
      if (res[i][ruleData[y].name] && ruleData[y].rule === "IS") {
        let reg = /^([0-9]|[1-9][0-9]|100)$/;
        if (!reg.test(res[i][ruleData[y].name])) {
          tooptip.push(ruleData[y].name + "列第" + (i + 1) + "行請輸入0-100的整數(shù)請重新提交");
          result = false;
        }
      }
    }
  }
  if (!result) {
    let tooptipStr = tooptip.join("
");
    Message.warning({
      dangerouslyUseHTMLString: true,
      showClose: true,
      message: tooptipStr,
    });
    result = false;
  }
  return result;
  // 遍歷行與列進(jìn)行校驗(yàn)
  //   for (let i = num; i < str.length; i++) {
  //     for (let y = 0; y < arr.length; y++) {
  //       // 校驗(yàn):非空(isnull === 'N' 時(shí)不能為空)
  //       if (!str[i][arr[y].name] && arr[y].isnull === "N") {
  //         tooptip.push("請檢查第" + arr[y].name + "列第" + (i + 1) + "行有空數(shù)據(jù)請重新提交");
  //         result = false;
  //       }
  //       if (str[i][arr[y].name] === "" && arr[y].isnull === "N") {
  //         tooptip.push("請檢查第" + arr[y].name + "列第" + (i + 1) + "行有空數(shù)據(jù)請重新提交");
  //         result = false;
  //       }
  //       if (!String(str[i][arr[y].name]) && arr[y].isnull === "N") {
  //         tooptip.push("請檢查第" + arr[y].name + "列第" + (i + 1) + "行有空數(shù)據(jù)請重新提交");
  //         result = false;
  //       }
  //       // 校驗(yàn):長度限制
  //       if (str[i][arr[y].name] && String(str[i][arr[y].name]).length > arr[y].leng) {
  //         tooptip.push(
  //           "第" +
  //             arr[y].name +
  //             "列第" +
  //             (i + 1) +
  //             "行數(shù)據(jù)不能超過" +
  //             arr[y].leng +
  //             "個(gè)字符請重新提交",
  //         );
  //         result = false;
  //       }
  //       // 規(guī)則 VI:數(shù)字文本校驗(yàn)
  //       let reg = new RegExp("[0-9+]");
  //       if (str[i][arr[y].name] && reg.test(String(str[i][arr[y].name])) && arr[y].rule === "VI") {
  //         tooptip.push("第" + arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)不是數(shù)字文本請重新提交");
  //         result = false;
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "VF") {
  //         let str1 = str[i][arr[y].name];
  //         if (str1.length === 1) {
  //           if (!(str1 >= 0 && str1 < 6)) {
  //             tooptip.push("第" + arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)不正確");
  //             result = false;
  //           }
  //         }
  //         // 長度3的小數(shù)校驗(yàn)(格式 x.xx,整數(shù)位0-8,小數(shù)位0-5)
  //         if (str1.length === 3) {
  //           let tmp = String(str1.split("."));
  //           if (tmp.length === 2) {
  //             // 是小數(shù)
  //             if (tmp[0] && tmp[1]) {
  //               if (!(tmp[0] >= 0 && tmp[0] < 8 && tmp[1] <= 5)) {
  //                 tooptip.push("第" + arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)不正確");
  //                 result = false;
  //               }
  //             }
  //           }
  //         }
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "VII") {
  //         var reg = /^(([1-9]{1}\d*)|(0{1}))(\.\d{1})?$/;
  //         if (!reg.test(str[i][arr[y].name])) {
  //           tooptip.push(
  //             arr[y].name + "列第" + (i + 1) + "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
  //           );
  //           result = false;
  //         }
  //         if (Number(str[i][arr[y].name]) !== 0 && !Number(str[i][arr[y].name])) {
  //           tooptip.push(
  //             arr[y].name + "列第" + (i + 1) + "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
  //           );
  //           result = false;
  //         }
  //         if (str[i][arr[y].name] > 100) {
  //           tooptip.push(
  //             arr[y].name + "列第" + (i + 1) + "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
  //           );
  //           result = false;
  //         }
  //         if (str[i][arr[y].name] < 0) {
  //           tooptip.push(
  //             arr[y].name + "列第" + (i + 1) + "行請輸入0-100的數(shù)字,最多保留一位小數(shù),請重新提交",
  //           );
  //           result = false;
  //         }
  //       }
  //       var reg = /^([0-9][0-9]{0,1}|100)$/;
  //       if (str[i][arr[y].name] && !reg.test(str[i][arr[y].name]) && arr[y].rule === "IS") {
  //         tooptip.push(arr[y].name + "列第" + (i + 1) + "行請輸入0~100的整數(shù)請重新提交");
  //         result = false;
  //       }
  //       if (str[i][arr[y].name] && !(str[i][arr[y].name] > 1) && arr[y].rule === "VP") {
  //         tooptip.push(arr[y].name + "列第" + (i + 1) + "行請輸入大于1的整數(shù)請重新提交");
  //         result = false;
  //       }
  //       let CIreg = new RegExp("^[0-9]*$");
  //       if (
  //         (str[i][arr[y].name] && !CIreg.test(str[i][arr[y].name]) && arr[y].rule === "CI") ||
  //         (String(str[i][arr[y].name]).length > arr[y].leng && arr[y].rule === "CI")
  //       ) {
  //         tooptip.push(
  //           arr[y].name + "列第" + (i + 1) + "行不能超過" + arr[y].leng + "個(gè)字符的整數(shù)請重新提交",
  //         );
  //         result = false;
  //       }
  //       let VNreg = /[^<>\""]+$/;
  //       if (str[i][arr[y].name] && !VNreg.test(str[i][arr[y].name]) && arr[y].rule === "VN") {
  //         tooptip.push(arr[y].name + "列第" + (i + 1) + "行不能包含特殊字符");
  //         result = false;
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "D") {
  //         if (!isDate(str[i][arr[y].name])) {
  //           tooptip.push(arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)請輸入日期(yyyymmdd)格式");
  //           result = false;
  //         }
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "D1") {
  //         if (!isDate1(str[i][arr[y].name])) {
  //           tooptip.push(arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)請輸入日期(yyyymm)格式");
  //           result = false;
  //         }
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "VE") {
  //         if (!(0 <= str[i][arr[y].name] && str[i][arr[y].name] <= 120)) {
  //           tooptip.push(arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)請輸入0~120的整數(shù)");
  //           result = false;
  //         }
  //       }
  //       if (str[i][arr[y].name] && arr[y].rule === "I") {
  //         if (!isInt(str[i][arr[y].name])) {
  //           tooptip.push(arr[y].name + "列第" + (i + 1) + "行數(shù)據(jù)不正確");
  //           result = false;
  //         }
  //       }
  //     }
  //   }
}

大致如此,大家可自行運(yùn)行嘗試調(diào)整一下代碼。

到此這篇關(guān)于el-upload二次封裝帶表格校驗(yàn)組件的文章就介紹到這了,更多相關(guān)el-upload封裝表格校驗(yàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

昌黎县| 新和县| 苏尼特右旗| 山东| 鸡西市| 榆树市| 定日县| 油尖旺区| 桂林市| 内乡县| 乌拉特后旗| 常宁市| 桐柏县| 息烽县| 大悟县| 保德县| 金寨县| 闽清县| 洛宁县| 贺兰县| 武山县| 三台县| 大庆市| 岳阳县| 江安县| 浙江省| 留坝县| 黎川县| 龙泉市| 榆中县| 榆树市| 化州市| 罗山县| 湘乡市| 南城县| 莒南县| 星座| 大庆市| 虎林市| 清原| 右玉县|