فهرست منبع

增加Excel导入导出示例功能

hwb2017 4 سال پیش
والد
کامیت
50f29633d5

+ 84 - 0
server/api/v1/exa_file_upload_download.go

@@ -6,6 +6,7 @@ import (
 	"gin-vue-admin/model/request"
 	"gin-vue-admin/model/response"
 	"gin-vue-admin/service"
+	"gin-vue-admin/utils"
 	"github.com/gin-gonic/gin"
 	"go.uber.org/zap"
 )
@@ -78,3 +79,86 @@ func GetFileList(c *gin.Context) {
 		},"获取成功", c)
 	}
 }
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 导出Excel
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce  application/octet-stream
+// @Param data body request.ExcelInfo true "导出Excel文件信息"
+// @Success 200
+// @Router /fileUploadAndDownload/exportExcel [post]
+func ExportExcel(c *gin.Context) {
+	var excelInfo request.ExcelInfo
+    c.ShouldBindJSON(&excelInfo)
+	filePath := global.GVA_CONFIG.Excel.Dir+excelInfo.FileName
+	err := service.ParseInfoList2Excel(excelInfo.InfoList, filePath)
+	if err != nil {
+		global.GVA_LOG.Error("转换Excel失败!", zap.Any("err", err))
+		response.FailWithMessage("转换Excel失败", c)
+		return
+	}
+	c.Writer.Header().Add("success", "true")
+	c.File(filePath)
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 导入Excel文件
+// @Security ApiKeyAuth
+// @accept multipart/form-data
+// @Produce  application/json
+// @Param file formData file true "导入Excel文件"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"导入成功"}"
+// @Router /fileUploadAndDownload/importExcel [post]
+func ImportExcel(c *gin.Context) {
+	_, header, err := c.Request.FormFile("file")
+	if err != nil {
+		global.GVA_LOG.Error("接收文件失败!", zap.Any("err", err))
+		response.FailWithMessage("接收文件失败", c)
+		return
+	}
+	c.SaveUploadedFile(header, 	global.GVA_CONFIG.Excel.Dir+"ExcelImport.xlsx")
+	response.OkWithMessage("导入成功", c)
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 加载Excel数据
+// @Security ApiKeyAuth
+// @Produce  application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"加载数据成功"}"
+// @Router /fileUploadAndDownload/loadExcel [get]
+func LoadExcel(c *gin.Context) {
+	menus, err := service.ParseExcel2InfoList()
+	if err != nil {
+		global.GVA_LOG.Error("加载数据失败", zap.Any("err", err))
+		response.FailWithMessage("加载数据失败", c)
+		return
+	}
+	response.OkWithDetailed(response.PageResult{
+		List: menus,
+		Total: int64(len(menus)),
+		Page: 1,
+		PageSize: 999,
+	},"加载数据成功", c)
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 下载模板
+// @Security ApiKeyAuth
+// @accept multipart/form-data
+// @Produce  application/json
+// @Param fileName query fileName true "模板名称"
+// @Success 200
+// @Router /fileUploadAndDownload/downloadTemplate [get]
+func DownloadTemplate(c *gin.Context) {
+	fileName := c.Query("fileName")
+	filePath := global.GVA_CONFIG.Excel.Dir+fileName
+	ok, err := utils.PathExists(filePath)
+	if !ok || err != nil {
+		global.GVA_LOG.Error("文件不存在", zap.Any("err", err))
+		response.FailWithMessage("文件不存在", c)
+		return
+	}
+	c.Writer.Header().Add("success", "true")
+	c.File(filePath)
+}

+ 5 - 1
server/config.yaml

@@ -76,4 +76,8 @@ qiniu:
   use-https: false
   access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
   secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
-  use-cdn-domains: false
+  use-cdn-domains: false
+
+# excel configuration
+excel:
+  dir: './resource/excel/'

+ 1 - 0
server/config/config.go

@@ -13,4 +13,5 @@ type Server struct {
 	// oss
 	Local Local `mapstructure:"local" json:"local" yaml:"local"`
 	Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
+	Excel Excel `mapstructure:"excel" json:"excel" yaml:"excel"`
 }

+ 5 - 0
server/config/excel.go

@@ -0,0 +1,5 @@
+package config
+
+type Excel struct {
+	Dir string `mapstructure:"dir" json:"dir" yaml:"dir"`
+}

+ 2 - 2
server/go.mod

@@ -3,6 +3,7 @@ module gin-vue-admin
 go 1.14
 
 require (
+	github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.2
 	github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
 	github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
 	github.com/casbin/casbin v1.9.1
@@ -47,8 +48,7 @@ require (
 	github.com/tebeka/strftime v0.1.3 // indirect
 	github.com/unrolled/secure v1.0.7
 	go.uber.org/zap v1.10.0
-	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
-	golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
+	golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
 	golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect
 	google.golang.org/protobuf v1.24.0 // indirect
 	gopkg.in/ini.v1 v1.55.0 // indirect

+ 8 - 0
server/model/request/exa_file_upload_and_download.go

@@ -0,0 +1,8 @@
+package request
+
+import "gin-vue-admin/model"
+
+type ExcelInfo struct {
+	FileName string `json:"fileName"`
+	InfoList []model.SysBaseMenu `json:"infoList"`
+}

BIN
server/resource/excel/ExcelExport.xlsx


BIN
server/resource/excel/ExcelImport.xlsx


BIN
server/resource/excel/ExcelTemplate.xlsx


+ 4 - 0
server/router/exp_file_upload_and_download.go

@@ -15,5 +15,9 @@ func InitFileUploadAndDownloadRouter(Router *gin.RouterGroup) {
 		FileUploadAndDownloadGroup.GET("/findFile", v1.FindFile)                                  // 查询当前文件成功的切片
 		FileUploadAndDownloadGroup.POST("/breakpointContinueFinish", v1.BreakpointContinueFinish) // 查询当前文件成功的切片
 		FileUploadAndDownloadGroup.POST("/removeChunk", v1.RemoveChunk)                           // 查询当前文件成功的切片
+		FileUploadAndDownloadGroup.POST("/importExcel", v1.ImportExcel)                          // 导入Excel
+		FileUploadAndDownloadGroup.GET("/loadExcel", v1.LoadExcel)                                // 加载Excel数据
+		FileUploadAndDownloadGroup.POST("/exportExcel", v1.ExportExcel)                           // 导出Excel
+		FileUploadAndDownloadGroup.GET("/downloadTemplate", v1.DownloadTemplate)                  // 下载模板文件
 	}
 }

+ 91 - 0
server/service/exa_excel_parse.go

@@ -0,0 +1,91 @@
+package service
+
+import (
+	"errors"
+	"fmt"
+	"gin-vue-admin/global"
+	"gin-vue-admin/model"
+	"github.com/360EntSecGroup-Skylar/excelize/v2"
+	"strconv"
+)
+
+func ParseInfoList2Excel(infoList []model.SysBaseMenu, filePath string) error {
+	excel := excelize.NewFile()
+		excel.SetSheetRow("Sheet1","A1",&[]string{"ID","路由Name","路由Path","是否隐藏","父节点","排序","文件名称"})
+    	for i, menu := range infoList {
+    		axis := fmt.Sprintf("A%d",i+2)
+    		excel.SetSheetRow("Sheet1",axis,&[]interface{}{
+    			menu.ID,
+    			menu.Name,
+    			menu.Path,
+    			menu.Hidden,
+    			menu.ParentId,
+    			menu.Sort,
+    			menu.Component,
+    		})
+		}
+	excel.SaveAs(filePath)
+	return nil
+}
+
+func ParseExcel2InfoList() ([]model.SysBaseMenu, error) {
+	skipHeader := true
+	fixedHeader := []string{"ID","路由Name","路由Path","是否隐藏","父节点","排序","文件名称"}
+	file, err := excelize.OpenFile(global.GVA_CONFIG.Excel.Dir+"ExcelImport.xlsx")
+	if err != nil {
+        return nil, err
+	}
+	menus := make([]model.SysBaseMenu, 0)
+	rows, err := file.Rows("Sheet1")
+	if err != nil {
+		return nil, err
+	}
+	for rows.Next() {
+		row, err := rows.Columns()
+		if err != nil {
+			return nil, err
+		}
+		if skipHeader {
+			if compareStrSlice(row, fixedHeader) {
+				skipHeader = false
+				continue
+			} else {
+				return nil, errors.New("Excel格式错误")
+			}
+		}
+		if len(row) != len(fixedHeader) {
+			continue
+		}
+		id, _ := strconv.Atoi(row[0])
+		hidden, _ := strconv.ParseBool(row[3])
+		sort, _ := strconv.Atoi(row[5])
+		menu := model.SysBaseMenu{
+			GVA_MODEL: global.GVA_MODEL{
+				ID: uint(id),
+			},
+			Name: row[1],
+			Path: row[2],
+			Hidden: hidden,
+			ParentId: row[4],
+			Sort: sort,
+			Component: row[6],
+		}
+		menus = append(menus, menu)
+	}
+	return menus, nil
+}
+
+func compareStrSlice(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	if (b == nil) != (a == nil) {
+		return false
+	}
+	for key, value := range a {
+		if value != b[key] {
+			return false
+		}
+	}
+	return true
+}

+ 62 - 89
web/package-lock.json

@@ -1,5 +1,5 @@
 {
-    "name": "qm-plus-vue-page",
+    "name": "gin-vue-admin",
     "version": "0.1.0",
     "lockfileVersion": 1,
     "requires": true,
@@ -3449,6 +3449,13 @@
                     "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=",
                     "dev": true
                 },
+                "emojis-list": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+                    "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+                    "dev": true,
+                    "optional": true
+                },
                 "fast-deep-equal": {
                     "version": "3.1.3",
                     "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz?cache=0&sync_timestamp=1591599659970&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-deep-equal%2Fdownload%2Ffast-deep-equal-3.1.3.tgz",
@@ -3476,12 +3483,31 @@
                         "path-exists": "^4.0.0"
                     }
                 },
+                "has-flag": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+                    "dev": true,
+                    "optional": true
+                },
                 "is-fullwidth-code-point": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz",
                     "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=",
                     "dev": true
                 },
+                "loader-utils": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+                    "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "big.js": "^5.2.2",
+                        "emojis-list": "^3.0.0",
+                        "json5": "^2.1.2"
+                    }
+                },
                 "locate-path": {
                     "version": "5.0.0",
                     "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz",
@@ -3647,6 +3673,16 @@
                         "ansi-regex": "^5.0.0"
                     }
                 },
+                "supports-color": {
+                    "version": "7.2.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+                    "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "has-flag": "^4.0.0"
+                    }
+                },
                 "terser": {
                     "version": "4.8.0",
                     "resolved": "https://registry.npm.taobao.org/terser/download/terser-4.8.0.tgz?cache=0&sync_timestamp=1599751633316&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser%2Fdownload%2Fterser-4.8.0.tgz",
@@ -3685,6 +3721,31 @@
                         "punycode": "^2.1.1"
                     }
                 },
+                "vue-loader-v16": {
+                    "version": "npm:[email protected]",
+                    "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz",
+                    "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==",
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "chalk": "^4.1.0",
+                        "hash-sum": "^2.0.0",
+                        "loader-utils": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "chalk": {
+                            "version": "4.1.0",
+                            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+                            "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "ansi-styles": "^4.1.0",
+                                "supports-color": "^7.1.0"
+                            }
+                        }
+                    }
+                },
                 "wrap-ansi": {
                     "version": "6.2.0",
                     "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz",
@@ -14937,94 +14998,6 @@
                 }
             }
         },
-        "vue-loader-v16": {
-            "version": "npm:[email protected]",
-            "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz",
-            "integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==",
-            "dev": true,
-            "optional": true,
-            "requires": {
-                "chalk": "^4.1.0",
-                "hash-sum": "^2.0.0",
-                "loader-utils": "^2.0.0"
-            },
-            "dependencies": {
-                "ansi-styles": {
-                    "version": "4.3.0",
-                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-                    "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "color-convert": "^2.0.1"
-                    }
-                },
-                "chalk": {
-                    "version": "4.1.0",
-                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
-                    "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "ansi-styles": "^4.1.0",
-                        "supports-color": "^7.1.0"
-                    }
-                },
-                "color-convert": {
-                    "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-                    "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "color-name": "~1.1.4"
-                    }
-                },
-                "color-name": {
-                    "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-                    "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-                    "dev": true,
-                    "optional": true
-                },
-                "emojis-list": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
-                    "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
-                    "dev": true,
-                    "optional": true
-                },
-                "has-flag": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-                    "dev": true,
-                    "optional": true
-                },
-                "loader-utils": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
-                    "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "big.js": "^5.2.2",
-                        "emojis-list": "^3.0.0",
-                        "json5": "^2.1.2"
-                    }
-                },
-                "supports-color": {
-                    "version": "7.2.0",
-                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-                    "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "has-flag": "^4.0.0"
-                    }
-                }
-            }
-        },
         "vue-particle-line": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/vue-particle-line/-/vue-particle-line-0.1.4.tgz",

+ 1 - 1
web/package.json

@@ -72,4 +72,4 @@
         "> 1%",
         "last 2 versions"
     ]
-}
+}

+ 86 - 1
web/src/api/fileUploadAndDownload.js

@@ -1,4 +1,31 @@
-import service from '@/utils/request'
+import service from '@/utils/request';
+import { Message } from 'element-ui';
+
+const handleFileError = (res, fileName) => {
+    if (typeof(res.data) !== "undefined") {
+        if (res.data.type == "application/json") {
+            const reader = new FileReader();
+            reader.onload = function() {
+                let message = JSON.parse(reader.result).msg;
+                Message({
+                    showClose: true,
+                    message: message,
+                    type: 'error'
+                })
+            };
+            reader.readAsText(new Blob([res.data]));
+        } 
+    } else {
+        var downloadUrl = window.URL.createObjectURL(new Blob([res]));
+        var a = document.createElement('a');
+        a.style.display = 'none';
+        a.href = downloadUrl;
+        a.download = fileName;
+        var event = new MouseEvent("click");
+        a.dispatchEvent(event);
+    }        
+} 
+
 // @Tags FileUploadAndDownload
 // @Summary 分页文件列表
 // @Security ApiKeyAuth
@@ -28,4 +55,62 @@ export const deleteFile = (data) => {
         method: "post",
         data
     })
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 导出Excel
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce  application/octet-stream
+// @Param data body request.ExcelInfo true "导出Excel文件信息"
+// @Success 200
+// @Router /fileUploadAndDownload/exportExcel [post]
+export const exportExcel = (tableData, fileName) => {
+    service({
+        url: "/fileUploadAndDownload/exportExcel",
+        method: 'post',
+        data: {
+            fileName: fileName,
+            infoList: tableData
+        },
+        responseType: 'blob'
+    }).then((res)=>{
+        handleFileError(res, fileName)
+    })
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 导入Excel文件
+// @Security ApiKeyAuth
+// @accept multipart/form-data
+// @Produce  application/json
+// @Param file formData file true "导入Excel文件"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"导入成功"}"
+// @Router /fileUploadAndDownload/importExcel [post]
+export const loadExcelData = () => {
+    return service({
+        url: "/fileUploadAndDownload/loadExcel",
+        method: 'get'
+    })
+}
+
+// @Tags ExaFileUploadAndDownload
+// @Summary 下载模板
+// @Security ApiKeyAuth
+// @accept multipart/form-data
+// @Produce  application/json
+// @Param fileName query fileName true "模板名称"
+// @Success 200
+// @Router /fileUploadAndDownload/downloadTemplate [get]
+export const downloadTemplate = (fileName) => {   
+    return service({
+        url: "/fileUploadAndDownload/downloadTemplate",
+        method: 'get',
+        params:{
+            fileName: fileName
+        },
+        responseType: 'blob'
+    }).then((res)=>{
+        handleFileError(res, fileName)        
+    })
 }

+ 54 - 49
web/src/view/example/excel/excel.vue

@@ -1,69 +1,74 @@
 <template>
-  <div>
-    <el-upload
-      :action="`${path}/fileUploadAndDownload/upload`"
-      :before-remove="beforeRemove"
-      :file-list="fileList"
-      :headers="{'x-token':token}"
-      :limit="10"
-      :on-exceed="handleExceed"
-      :on-preview="handlePreview"
-      :on-remove="handleRemove"
-      class="upload-demo"
-      multiple
-    >
-      <el-button size="small" type="primary">点击上传</el-button>
-      <div class="el-upload__tip" slot="tip">未对文件格式及大小做校验</div>
-    </el-upload>
+  <div class="upload">
+    <el-row>
+      <el-col :span="2">
+        <el-upload
+          :action="`${path}/fileUploadAndDownload/importExcel`"
+          :headers="{'x-token':token}"
+          :on-success="loadExcel"
+          :show-file-list="false"
+        >
+          <el-button size="small" type="primary" icon="el-icon-upload2">导入</el-button>
+        </el-upload>
+      </el-col>
+      <el-col :span="2">
+        <el-button size="small" type="primary" icon="el-icon-download" @click="handleExcelExport('ExcelExport.xlsx')">导出</el-button>
+      </el-col>
+      <el-col :span="2">
+        <el-button size="small" type="success" icon="el-icon-download" @click="downloadExcelTemplate()">下载模板</el-button>
+      </el-col>
+    </el-row>
+    <el-table :data="tableData" border row-key="ID" stripe>
+      <el-table-column label="ID" min-width="100" prop="ID"></el-table-column>
+      <el-table-column label="路由Name" min-width="160" prop="name"></el-table-column>
+      <el-table-column label="路由Path" min-width="160" prop="path"></el-table-column>
+      <el-table-column label="是否隐藏" min-width="100" prop="hidden">
+        <template slot-scope="scope">
+          <span>{{scope.row.hidden?"隐藏":"显示"}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="父节点" min-width="90" prop="parentId"></el-table-column>
+      <el-table-column label="排序" min-width="70" prop="sort"></el-table-column>
+      <el-table-column label="文件路径" min-width="360" prop="component"></el-table-column>
+    </el-table>
   </div>
 </template>
 <script>
-import { mapGetters } from 'vuex'
-const path = process.env.VUE_APP_BASE_API
+const path = process.env.VUE_APP_BASE_API;
+import { mapGetters } from 'vuex';
+import infoList from "@/mixins/infoList";
+import { exportExcel, loadExcelData, downloadTemplate } from "@/api/fileUploadAndDownload";
+import { getMenuList } from "@/api/menu";
 export default {
   name: 'Excel',
+  mixins: [infoList],
   data() {
     return {
-      path: path,
-
-      fileList: [
-        {
-          name: 'food.jpeg',
-          url:
-            'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
-        },
-        {
-          name: 'food2.jpeg',
-          url:
-            'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
-        }
-      ]
+      listApi: getMenuList,
+      path: path
     }
   },
   computed: {
     ...mapGetters('user', ['userInfo', 'token'])
   },
   methods: {
-    handleRemove(file, fileList) {
-      this.$message.warning(
-        `共有 ${fileList.length} 个文件,移除了${file.name}`
-      )
+    handleExcelExport(fileName) {
+      if (!fileName || typeof fileName !== "string") {
+        fileName = "ExcelExport.xlsx";
+      }
+      exportExcel(this.tableData, fileName);
     },
-    handlePreview(file) {
-      this.$message.warning(`${file.name}选择完成`)
+    loadExcel() {
+      this.listApi = loadExcelData;
+      this.getTableData();
     },
-    handleExceed(files, fileList) {
-      this.$message.warning(
-        `当前限制选择 3 个文件,本次选择了 ${
-          files.length
-        } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      )
-    },
-    beforeRemove(file, fileList) {
-      return this.$confirm(
-        `共有 ${fileList.length} 个文件,确定移除 ${file.name}?`
-      )
+    downloadExcelTemplate() {
+      downloadTemplate('ExcelTemplate.xlsx')
     }
+  },
+  created() {
+    this.pageSize = 999;
+    this.getTableData();
   }
 }
 </script>