vue+elementui導入Excel文件(基於vue-element-admin中的uploadExcel組件)


vue+elementui導入Excel文件(基於vue-element-admin中的uploadExcel組件)

需求說明

實現Excel文件的上傳,將文件傳給后端完成數據的批量導入。並在前端進行解析,將上傳的Excel回顯到表格中。

備注:本功能僅實現了簡單excel表格數據的導入,限制一次只能上傳一個excel。

接下來就讓我們開動吧!

第一步:構建頁面

我這邊就拿我正在做的一個項目舉例,其中有一個功能是物品信息的管理。需要實現批量新增(即excel導入)。

首先我們在已有的頁面上新增一個按鈕,用以激活dialog。我這邊將導入excel的部分放到dialog中。

<el-button
        class="filter-item"
        size="mini"
        type="primary"
        icon="el-icon-upload"
        @click="dialogVisible = true"
      >批量導入</el-button>
<el-dialog title="導入表單" :visible.sync="dialogVisible">
        <!--   導入excel,一會會將這里補充  -->
      </el-dialog>
data(){
    return{
        dialogVisible: false,  //dialog是否可見
    }
}

如下圖所示,已經新增了一個批量導入的按鈕。當我們點擊時dialog會變為可見,即彈出dialog。

第二步:利用現成的組件

因為我這邊用到的是el-admin的開源項目進行二次開發,其中涉及到的excel上傳功能是來自於vue-element-admin開源項目的uploadExcel組件,所以我們直接去看封裝好的組件,進行修改。

vue-element-admin的在線文檔中,我們找到關於Excel的文檔說明。如下圖所示:

官方Demo(不涉及提交給后台的動作)

我們點擊在線代碼去查看示例代碼。方便起見,我直接搬運過來了。

<template>
  <div class="app-container">
    <upload-excel-component :on-success="handleSuccess" :before-upload="beforeUpload" />
    <el-table :data="tableData" border highlight-current-row style="width: 100%;margin-top:20px;">
      <el-table-column v-for="item of tableHeader" :key="item" :prop="item" :label="item" />
    </el-table>
  </div>
</template>

<script>
import UploadExcelComponent from '@/components/UploadExcel/index.vue'
export default {
  name: 'UploadExcel',
  components: { UploadExcelComponent },
  data() {
    return {
      tableData: [],
      tableHeader: []
    }
  },
  methods: {
    beforeUpload(file) {
      const isLt1M = file.size / 1024 / 1024 < 1
      if (isLt1M) {
        return true
      }
      this.$message({
        message: 'Please do not upload files larger than 1m in size.',
        type: 'warning'
      })
      return false
    },
    handleSuccess({ results, header }) {
      this.tableData = results
      this.tableHeader = header
    }
  }
}
</script>

核心:UploadExcelComponent組件

可以看到,其中有一個UploadExcelComponent組件,我們繼續去尋找該組件的代碼。如下:

<template>
  <div>
    <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
    <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
      Drop excel file here or
      <el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">
        Browse
      </el-button>
    </div>
  </div>
</template>

<script>
import XLSX from 'xlsx'
export default {
  props: {
    beforeUpload: Function, // eslint-disable-line
    onSuccess: Function// eslint-disable-line
  },
  data() {
    return {
      loading: false,
      excelData: {
        header: null,
        results: null
      }
    }
  },
  methods: {
    generateData({ header, results }) {
      this.excelData.header = header
      this.excelData.results = results
      this.onSuccess && this.onSuccess(this.excelData)
    },
    handleDrop(e) {
      e.stopPropagation()
      e.preventDefault()
      if (this.loading) return
      const files = e.dataTransfer.files
      if (files.length !== 1) {
        this.$message.error('Only support uploading one file!')
        return
      }
      const rawFile = files[0] // only use files[0]
      if (!this.isExcel(rawFile)) {
        this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
        return false
      }
      this.upload(rawFile)
      e.stopPropagation()
      e.preventDefault()
    },
    handleDragover(e) {
      e.stopPropagation()
      e.preventDefault()
      e.dataTransfer.dropEffect = 'copy'
    },
    handleUpload() {
      this.$refs['excel-upload-input'].click()
    },
    handleClick(e) {
      const files = e.target.files
      const rawFile = files[0] // only use files[0]
      if (!rawFile) return
      this.upload(rawFile)
    },
    upload(rawFile) {
      this.$refs['excel-upload-input'].value = null // fix can't select the same excel
      if (!this.beforeUpload) {
        this.readerData(rawFile)
        return
      }
      const before = this.beforeUpload(rawFile)
      if (before) {
        this.readerData(rawFile)
      }
    },
    readerData(rawFile) {
      this.loading = true
      return new Promise((resolve, reject) => {
        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 = this.getHeaderRow(worksheet)
          const results = XLSX.utils.sheet_to_json(worksheet)
          this.generateData({ header, results })
          this.loading = false
          resolve()
        }
        reader.readAsArrayBuffer(rawFile)
      })
    },
    getHeaderRow(sheet) {
      const headers = []
      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 })]
        /* 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)
      }
      return headers
    },
    isExcel(file) {
      return /\.(xlsx|xls|csv)$/.test(file.name)
    }
  }
}
</script>

<style scoped>
.excel-upload-input{
  display: none;
  z-index: -9999;
}
.drop{
  border: 2px dashed #bbb;
  width: 600px;
  height: 160px;
  line-height: 160px;
  margin: 0 auto;
  font-size: 24px;
  border-radius: 5px;
  text-align: center;
  color: #bbb;
  position: relative;
}
</style>

這個組件是用來解析我們所上傳的excel的,具體大家可以自行研究,主要是將excel中的內容解析成header和results,我們主要用解析后的信息回顯給table。

在demo的基礎上修改

了解了這些,我們就可以在dialog中完善相應的代碼了。這邊可以根據模板做修改。

<el-dialog title="導入表單" :visible.sync="dialogVisible">
        <div class="app-container">
          <div>
            <el-button
              class="filter-item"
              size="mini"
              type="primary"
              icon="el-icon-download"
              @click="downloadExceltoLocalFile()"
            >下載模板</el-button>
          </div>
          <upload-excel-component
            :on-success="handleSuccess"
            :before-upload="beforeUpload"
          />
          <el-table
            max-height="300"
            :data="tableData"
            border
            highlight-current-row
            style="width: 100%; margin-top: 20px"
          >
            <el-table-column
              v-for="item of tableHeader"
              :key="item"
              :prop="item"
              :label="item"
            >
              </template>
            </el-table-column>
          </el-table>
          <el-divider />
          <el-button
            style="float: right"
            type="primary"
            :loading="loading"
            @click="submitExcel()"
          >確認並導入</el-button>
        </div>
      </el-dialog>
  1. 這里我新增了一個下載模板的按鈕,同樣是調用后端接口去獲得模板excel,然后點擊進行下載。如果大家有需要我下次詳細的講怎么實現。

  2. 同時這邊跟demo一樣,用了uploadExcelComponent組件。怎么引入應該不用多說了吧。該組件提供了兩個回調函數,在官方文檔里都有描述。

    before-upload: 在上傳前所做的動作

    on-success: 解析成功后觸發的回調,我們在這里實現對表格中表頭和內容的賦值

  3. 最后是一個確認的按鈕,加入點擊事件。

第三步:實現各個方法

  1. 下載模板按鈕這邊有一個downloadExceltoLocalFile()事件。
	downloadExceltoLocalFile() {
      crudMaterial
        .downloadExcel()
        .then((res) => {
          downloadFile(res, '物料模板', 'xlsx')
        })
        .catch((err) => {
          this.$message.error = err.message
        })
    },

你會發現缺了一個downloadFile的方法,該方法這個框架已經提供了,我們只需要import { downloadFile } from '@/utils/index'即可,具體的內容自行查閱相關資料或評論。其中

 crudMaterial
        .downloadExcel()

這個是我自己調后台的API接口,請自行修改。

  1. 組件的回調函數
// before-upload
    beforeUpload(file) {
      this.files = file
      console.log(this.files)
      const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
      const isLt5M = file.size / 1024 / 1024 < 5
      if (extension !== 'xlsx' && extension !== 'xls') {
        this.$message({
          message: '只能上傳Excel(即后綴是.xlsx或者.xls)的文件.',
          type: 'warning'
        })
        return false
      }
      if (isLt5M) {
        return true
      }

      this.$message({
        message: '請不要上傳大於5MB的文件.',
        type: 'warning'
      })
      return false
    },

我這邊只是一些簡單的對后綴和大小的判斷,大家根據實際自行修改。

 handleSuccess({ header, results }) {
      this.tableData = results
      this.tableHeader = header
    },

該回調即對提交的excel文件進行解析,同時給表格賦值。

  1. 點擊提交的方法
submitExcel() {
      // 裝載成formdata數據
      const formdata = new FormData()
      formdata.append('file', this.files, this.files.name)
      this.loading = true
      this.doImport(formdata)
    },
    async doImport(data) {
      try {
        const res = await crudMaterial.importMaterial(data)
        console.log('importMaterial', res)
        this.loading = false
        this.$message.success('導入成功')
      } catch (err) {
        console.log('importMaterial', err)
        this.loading = false
        this.$message.error('導入失敗')
      }
    },

因為我們是要將excel傳給后台服務器,所以我們需要新建一個formdata的變量,將formdata包裝好數據傳給后台,否則會出錯。

doImport則是請求的方法,閱讀應該沒有難度。其中API接口如下:

至此,應該就差不多了。我們運行看一下效果。

點擊瀏覽或者拖拽都可以實現文件的上傳。

可以看到,上傳的excel能成功回顯,我們再點擊確認進行提交。

提示導入成功。功能基本實現。

完整代碼

api接口

import request from '@/utils/request'

export function downloadExcel() {
  return request({
    url: 'api/baseinfoMaterial/downloadExcel',
    method: 'get',
    responseType: 'blob'
  })
}

export function importMaterial(data) {
  return request({
    url: 'api/baseinfoMaterial/importExcel',
    method: 'post',
    data
  })
}

export default { downloadExcel, importMaterial }

index.vue 是這個頁面所有的內容,按需取用

<template>
  <div class="app-container">
    <!--工具欄-->
    <div class="head-container">
      <div v-if="crud.props.searchToggle">
        <!-- 搜索 -->
        <label class="el-form-item-label">物料類別</label>
        <el-select
          v-model="query.modelName"
          clearable
          filterable
          placeholder="請選擇"
          style="width: 185px"
          class="filter-item"
          @change="crud.toQuery"
        >
          <el-option
            v-for="item in dict.material_category"
            :key="item.id"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <label class="el-form-item-label">物料名稱</label>
        <el-input
          v-model="query.materialName"
          clearable
          size="small"
          placeholder="輸入物料名稱搜索"
          style="width: 185px"
          class="filter-item"
          @keyup.enter.native="crud.toQuery"
        />
        <label class="el-form-item-label">供應商</label>
        <el-input
          v-model="query.supplier"
          clearable
          placeholder="供應商"
          style="width: 185px"
          class="filter-item"
          @keyup.enter.native="crud.toQuery"
        />
        <label class="el-form-item-label">狀態</label>
        <el-select
          v-model="query.enabled"
          clearable
          size="small"
          placeholder="請選擇"
          class="filter-item"
          style="width: 90px"
          @change="crud.toQuery"
        >
          <el-option
            v-for="item in enabledTypeOptions"
            :key="item.key"
            :label="item.display_name"
            :value="item.key"
          />
        </el-select>
        <label class="el-form-item-label">創建時間</label>
        <date-range-picker v-model="query.createTime" class="date-item" />
        <rrOperation :crud="crud" />
      </div>
      <!--如果想在工具欄加入更多按鈕,可以使用插槽方式, slot = 'left' or 'right'-->
      <crudOperation :permission="permission" />

      <el-button
        class="filter-item"
        size="mini"
        type="primary"
        icon="el-icon-upload"
        @click="dialogVisible = true"
        >批量導入</el-button
      >
      <el-dialog title="導入表單" :visible.sync="dialogVisible">
        <div class="app-container">
          <div>
            <el-button
              class="filter-item"
              size="mini"
              type="primary"
              icon="el-icon-download"
              @click="downloadExceltoLocalFile()"
              >下載模板</el-button
            >
          </div>
          <upload-excel-component
            :on-success="handleSuccess"
            :before-upload="beforeUpload"
          />
          <el-table
            max-height="300"
            :data="tableData"
            border
            highlight-current-row
            style="width: 100%; margin-top: 20px"
          >
            <el-table-column
              v-for="item of tableHeader"
              :key="item"
              :prop="item"
              :label="item"
            >
              <template slot-scope="scope">
                <template>
                  {{
                    scope.row[scope.column.property] === true
                      ? '啟用'
                      : scope.row[scope.column.property] === false
                      ? '禁用'
                      : scope.row[scope.column.property]
                  }}
                </template>
              </template>
            </el-table-column>
          </el-table>
          <el-divider />
          <el-button
            style="float: right"
            type="primary"
            :loading="loading"
            @click="submitExcel()"
            >確認並導入</el-button
          >
        </div>
      </el-dialog>
    </div>
    <!--表單組件-->
    <el-dialog
      :close-on-click-modal="false"
      :before-close="crud.cancelCU"
      :visible.sync="crud.status.cu > 0"
      :title="crud.status.title"
      width="500px"
    >
      <el-form
        ref="form"
        :model="form"
        :rules="rules"
        size="small"
        label-width="80px"
      >
        <el-form-item label="物料名稱" prop="materialName">
          <el-autocomplete
            v-model="form.materialName"
            style="width: 370px"
            :fetch-suggestions="querySearchMaterials"
            placeholder="請輸入物料名稱"
            :trigger-on-focus="false"
          >
            <template slot-scope="{ item }">
              <div>{{ (item.value = item.materialName) }}</div>
            </template>
          </el-autocomplete>
        </el-form-item>
        <el-form-item label="類別名稱">
          <el-select
            v-model="form.modelName"
            filterable
            placeholder="請選擇所屬類別"
          >
            <el-option
              v-for="item in dict.material_category"
              :key="item.id"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="物料編號" prop="materialNum">
          <el-input
            v-model="form.materialNum"
            style="width: 370px"
            placeholder="請輸入物料編號"
          />
        </el-form-item>
        <el-form-item label="物料型號" prop="materialType">
          <el-input
            v-model="form.materialType"
            style="width: 370px"
            placeholder="請輸入物料型號"
          />
        </el-form-item>
        <el-form-item label="品牌" prop="brand">
          <el-input
            v-model="form.brand"
            style="width: 370px"
            placeholder="請輸入品牌"
          />
        </el-form-item>
        <el-form-item label="單位" prop="unit">
          <el-input
            v-model="form.unit"
            style="width: 370px"
            placeholder="請輸入單位"
          />
        </el-form-item>
        <el-form-item label="計價方式" prop="pricingMode">
          <el-input v-model="form.pricingMode" style="width: 370px" disabled />
        </el-form-item>
        <el-form-item label="參考價格" prop="referencePrice">
          <el-input
            v-model="form.referencePrice"
            style="width: 370px"
            placeholder="請輸入參考價格"
          >
            <template slot="append">元</template>
          </el-input>
        </el-form-item>
        <el-form-item label="供貨商" prop="supplier">
          <el-input
            v-model="form.supplier"
            style="width: 370px"
            placeholder="請輸入供貨商"
          />
        </el-form-item>

        <el-form-item label="狀態" prop="enabled">
          <el-radio
            v-for="item in dict.material_status"
            :key="item.id"
            v-model="form.enabled"
            :label="item.value === 'true'"
            >{{ item.label }}</el-radio
          >
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="text" @click="crud.cancelCU">取消</el-button>
        <el-button
          :loading="crud.status.cu === 2"
          type="primary"
          @click="crud.submitCU"
          >確認</el-button
        >
      </div>
    </el-dialog>
    <!--表格渲染-->
    <el-table
      ref="table"
      v-loading="crud.loading"
      lazy
      :data="crud.data"
      size="small"
      style="width: 100%"
      @selection-change="crud.selectionChangeHandler"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column prop="modelName" label="類別名稱">
        <template slot-scope="scope">
          {{ dict.label.material_category[scope.row.modelName] }}
        </template>
      </el-table-column>
      <el-table-column prop="materialNum" label="物料編號" />
      <el-table-column prop="materialName" label="物料名稱" />
      <el-table-column prop="materialType" label="物料型號" />
      <el-table-column prop="brand" label="品  牌" />
      <el-table-column prop="unit" label="單位" />
      <el-table-column prop="pricingMode" label="計價方式" />
      <el-table-column prop="referencePrice" label="參考價格" />
      <el-table-column prop="supplier" label="供貨商" />
      <el-table-column prop="enabled" label="狀態" align="center">
        <template slot-scope="scope">
          <a-switch
            v-model="scope.row.enabled"
            checked-children="啟用"
            un-checked-children="禁用"
            :disabled="scope.row.id === 1"
            @change="changeEnabled(scope.row, scope.row.enabled)"
          />
        </template>
      </el-table-column>

      <el-table-column prop="createTime" label="創建時間" />
      <el-table-column
        v-if="checkPer(['admin', 'material:edit', 'material:del'])"
        label="操作"
        width="150px"
        align="center"
      >
        <template slot-scope="scope">
          <udOperation :data="scope.row" :permission="permission" />
        </template>
      </el-table-column>
    </el-table>
    <!--分頁組件-->
    <pagination />
  </div>
</template>

<script>
import crudMaterial from '@/api/record/material'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
import DateRangePicker from '@/components/DateRangePicker'
import UploadExcelComponent from '@/components/UploadExcel/index.vue'
import { downloadFile } from '@/utils/index'
const defaultForm = {
  id: '',
  materialNum: null,
  materialName: null,
  materialType: null,
  unit: null,
  pricingMode: '加權平均法',
  referencePrice: null,
  supplier: null,
  createTime: null,
  enabled: true,
  modelName: null,
  brand: null
}
export default {
  name: 'Material',
  components: {
    pagination,
    crudOperation,
    rrOperation,
    udOperation,
    DateRangePicker,
    UploadExcelComponent
  },
  mixins: [presenter(), header(), form(defaultForm), crud()],
  dicts: ['material_category', 'material_status'],
  cruds() {
    return CRUD({
      title: '物料管理',
      url: 'api/baseinfoMaterial',
      sort: 'id,desc',
      crudMethod: { ...crudMaterial }
    })
  },
  data() {
    /* 金額格式校驗  */
    var validatePrice = (rule, value, callback) => {
      const reg = /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/
      if (value === '' || value === undefined || value == null) {
        callback()
      } else {
        if (!reg.test(value) && value !== '') {
          callback(new Error('請輸入正確的價格!整數或保留兩位小數'))
        } else {
          callback()
        }
      }
    }
    return {
      tableData: [],
      tableHeader: [],
      dialogVisible: false,
      loading: false,
      files: [],
      enabledTypeOptions: [
        { key: 'true', display_name: '正常' },
        { key: 'false', display_name: '禁用' }
      ],
      permission: {
        add: ['admin', 'material:add'],
        edit: ['admin', 'material:edit'],
        del: ['admin', 'material:del']
      },
      rules: {
        materialName: [
          {
            required: true,
            message: '請輸入物料名稱',
            trigger: 'blur'
          }
        ],
        materialNum: [
          { required: true, message: '請輸入物料編號', trigger: 'blur' }
        ],
        materialType: [
          { required: true, message: '請輸入物料型號', trigger: 'blur' }
        ],
        brand: [{ required: true, message: '請輸入品牌', trigger: 'blur' }],
        unit: [{ required: true, message: '請輸入單位', trigger: 'blur' }],
        referencePrice: [
          { required: true, message: '請輸入參考價格', trigger: 'blur' },
          {
            validator: validatePrice,
            trigger: 'blur'
          }
        ]
      },
      queryTypeOptions: [
        { key: 'materialName', display_name: '物料名稱' },
        { key: 'materialType', display_name: '物料型號' },
        { key: 'supplier', display_name: '供貨商' },
        { key: 'modelName', display_name: '類別名稱' }
      ]
    }
  },
  mounted() {
    this.loadAll()
  },

  methods: {
    // 導入
    submitExcel() {
      // 裝載成formdata數據
      const formdata = new FormData()
      formdata.append('file', this.files, this.files.name)
      this.loading = true
      this.doImport(formdata)
    },
    async doImport(data) {
      try {
        const res = await crudMaterial.importMaterial(data)
        console.log('importMaterial', res)
        this.loading = false
        this.$message.success('導入成功')
      } catch (err) {
        console.log('importMaterial', err)
        this.loading = false
        this.$message.error('導入失敗')
      }
    },
    // 導入功能
    beforeUpload(file) {
      this.files = file
      console.log(this.files)
      const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
      const isLt5M = file.size / 1024 / 1024 < 5
      if (extension !== 'xlsx' && extension !== 'xls') {
        this.$message({
          message: '只能上傳Excel(即后綴是.xlsx或者.xls)的文件.',
          type: 'warning'
        })
        return false
      }
      if (isLt5M) {
        return true
      }

      this.$message({
        message: '請不要上傳大於5MB的文件.',
        type: 'warning'
      })
      return false
    },
    transExcel(results) {
      const mapInfo = {
        類別名稱: 'modelName',
        物料編號: 'materialNum',
        物料名稱: 'materialName',
        物料型號: 'materialType',
        單位: 'unit',
        計價方式: 'pricingMode',
        參考價格: 'referencePrice',
        供貨商: 'supplier',
        狀態: 'enabled',
        品牌: 'brand'
      }
      return results.map((zhObj) => {
        const enObj = {}
        const zhKeys = Object.keys(zhObj)
        zhKeys.forEach((zhKey) => {
          const enKey = mapInfo[zhKey]
          enObj[enKey] = zhObj[zhKey]
        })
        return enObj
      })
    },
    handleSuccess({ header, results }) {
      this.tableData = results
      this.tableHeader = header
    },
    // 改變狀態
    changeEnabled(data, val) {
      this.$confirm(
        '此操作將 "' +
          this.dict.label.material_status[val] +
          '" ' +
          data.materialName +
          '倉庫, 是否繼續?',
        '提示',
        {
          confirmButtonText: '確定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      )
        .then(() => {
          // eslint-disable-next-line no-undef
          crudMaterial
            .edit(data)
            .then(() => {
              // eslint-disable-next-line no-undef
              this.crud.notify(
                this.dict.label.material_status[val] + '成功',
                'success'
              )
            })
            .catch((err) => {
              data.enabled = !data.enabled
              console.log(err.data.message)
            })
        })
        .catch(() => {
          data.enabled = !data.enabled
        })
    },

    loadAll() {
      crudMaterial.getAllMaterial().then((res) => {
        this.materials = res.content
      })
    },

    downloadExceltoLocalFile() {
      crudMaterial
        .downloadExcel()
        .then((res) => {
          downloadFile(res, '物料模板', 'xlsx')
        })
        .catch((err) => {
          this.$message.error = err.message
        })
    },

    querySearchMaterials(queryString, cb) {
      var materials = this.materials
      var results = queryString
        ? materials.filter(this.createFilter(queryString))
        : materials
      cb(results)
    },

    // 查詢輸入字符是否存在
    createFilter(queryString) {
      return (form) => {
        return (
          form.materialName.toLowerCase().indexOf(queryString.toLowerCase()) !==
          -1
        )
      }
    },
    // 鈎子:在獲取表格數據之前執行,false 則代表不獲取數據
    [CRUD.HOOK.beforeRefresh]() {
      return true
    }
  }
}
</script>

<style scoped></style>

PS:注意一個細節

該圖是后端controller層提供的接口,這邊需要額外注意一點。這邊的參數file需要和前面formdata中的第一個參數對應。否則會出現400錯誤。

總結

這次的開發僅僅是在單個頁面上進行編寫,還沒有封裝成一個通用的組件,同時由於本人能力有限,可能會存在一些疏漏,出現BUG。還望大家能夠指出。

參考資料

vue-element-admin開源項目,文檔地址
el-admin開源項目,文檔地址
element-ui, 文檔地址
element-ui/vue-element-admin上傳excel等文件到服務器,文章地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM