浏览代码

增加批量导入餐厅和餐桌的接口以及修改退款失败的提示

houweiyu 4 年之前
父节点
当前提交
40af0f7df6

+ 38 - 0
dinner-core/pom.xml

@@ -14,6 +14,10 @@
 
 
     <packaging>jar</packaging>
     <packaging>jar</packaging>
 
 
+    <properties>
+        <poi.version>3.15</poi.version>
+    </properties>
+
 
 
     <dependencyManagement>
     <dependencyManagement>
         <dependencies>
         <dependencies>
@@ -40,6 +44,40 @@
                 <artifactId>dom4j</artifactId>
                 <artifactId>dom4j</artifactId>
                 <version>1.6.1</version>
                 <version>1.6.1</version>
             </dependency>
             </dependency>
+        <!-- POI依赖 ,处理EXCEL WORD  PDF-->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-schemas</artifactId>
+            <version>${poi.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>stax-api</artifactId>
+                    <groupId>stax</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.xmlbeans</groupId>
+            <artifactId>xmlbeans</artifactId>
+            <version>2.6.0</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>stax-api</artifactId>
+                    <groupId>stax</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- POI依赖 ,处理EXCEL WORD  PDF-->
 
 
         <!-- Rpc feign依赖 -->
         <!-- Rpc feign依赖 -->
        <!-- <dependency>
        <!-- <dependency>

+ 12 - 0
dinner-core/src/main/java/com/fdage/base/enums/XssfDataType.java

@@ -0,0 +1,12 @@
+package com.fdage.base.enums;
+
+/**
+ * XSSFDataType
+ *
+ * @author lipengjun
+ * @email 939961241@qq.com
+ * @date 2017年10月28日 13:11:27
+ */
+public enum XssfDataType {
+    BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, DATETIME, TIME,
+}

+ 129 - 3
dinner-core/src/main/java/com/fdage/base/service/impl/TmCanteenServiceImpl.java

@@ -10,17 +10,18 @@ import com.fdage.base.enums.IdPreEnum;
 import com.fdage.base.service.ITmCanteenService;
 import com.fdage.base.service.ITmCanteenService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdage.base.utils.LocationUtils;
 import com.fdage.base.utils.LocationUtils;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
 import fdage.back.sdk.base.uuid.SnowFlakeUUidUtils;
 import fdage.back.sdk.base.uuid.SnowFlakeUUidUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
 
 
 /**
 /**
  * <p>
  * <p>
@@ -33,6 +34,7 @@ import java.util.List;
 @Service
 @Service
 public class TmCanteenServiceImpl extends ServiceImpl<TmCanteenDao, TmCanteen> implements ITmCanteenService {
 public class TmCanteenServiceImpl extends ServiceImpl<TmCanteenDao, TmCanteen> implements ITmCanteenService {
 
 
+    @Transactional(rollbackFor = Exception.class)
     public int addNew(TmCanteen tmCanteen){
     public int addNew(TmCanteen tmCanteen){
         if(null == tmCanteen){
         if(null == tmCanteen){
             return -1;
             return -1;
@@ -44,6 +46,130 @@ public class TmCanteenServiceImpl extends ServiceImpl<TmCanteenDao, TmCanteen> i
          return getBaseMapper().insert(tmCanteen);
          return getBaseMapper().insert(tmCanteen);
     }
     }
 
 
+    @Transactional(rollbackFor = Exception.class)
+    public List<TmCanteen> addNewFromExcel(List<String[]> excelList){
+        List<TmCanteen> resultList = new ArrayList<>();
+        if(CollectionUtils.isEmpty(excelList)){
+            return resultList;
+        }
+        for (int i = 1; i < excelList.size(); i++) {
+            List<String> line = Arrays.asList(excelList.get(i));
+            if(CollectionUtils.isEmpty(line)){
+                continue;
+            }
+            TmCanteen tmCanteen = new TmCanteen();
+            //直接跳过第1列(序号),从第二列开始,餐厅名称
+            if(line.get(1) instanceof String){
+                tmCanteen.setCanteenName(line.get(1).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列B的数据类型不为字符串");
+            }
+            //简介
+            if(line.get(2) instanceof String){
+                tmCanteen.setSimpleDesc(line.get(2).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列C的数据类型不为字符串");
+            }
+
+            //分数
+            if(line.get(3) instanceof String){
+                tmCanteen.setScore(new Double(line.get(3).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列D的数据类型不为字符串");
+            }
+
+            //排序
+            if(line.get(4) instanceof String){
+                tmCanteen.setSort(new Integer(line.get(4).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列E的数据类型不为字符串");
+            }
+
+            //类型
+            if(line.get(5) instanceof String){
+                tmCanteen.setType(new Integer(line.get(5).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列F的数据类型不为字符串");
+            }
+            //场景码
+            if(line.get(6) instanceof String){
+                tmCanteen.setSceneNum(line.get(6).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列G的数据类型不为字符串");
+            }
+
+            //VR链接
+            if(line.get(7) instanceof String){
+                tmCanteen.setVrLink(line.get(7).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列H的数据类型不为字符串");
+            }
+
+            //详细地址
+            if(line.get(8) instanceof String){
+                tmCanteen.setAddress(line.get(8).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列I的数据类型不为字符串");
+            }
+
+            //封面
+            if(line.get(9) instanceof String){
+                tmCanteen.setCoverPicLink(line.get(9).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列J的数据类型不为字符串");
+            }
+
+            //前台电话
+            if(line.get(10) instanceof String){
+                tmCanteen.setReceptionistPhone(line.get(10).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列K的数据类型不为字符串");
+            }
+
+            //前台名称
+            if(line.get(11) instanceof String){
+                tmCanteen.setReceptionistName(line.get(11).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列L的数据类型不为字符串");
+            }
+
+            //前台头像
+            if(line.get(12) instanceof String){
+                tmCanteen.setReceptionistAvatar(line.get(12).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列M的数据类型不为字符串");
+            }
+
+            //经度
+            if(line.get(13) instanceof String){
+                tmCanteen.setLongitude(new Double(line.get(13).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列N的数据类型不为字符串");
+            }
+
+            //纬度
+            if(line.get(14) instanceof String){
+                tmCanteen.setLatitude(new Double(line.get(14).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列O的数据类型不为字符串");
+            }
+
+            //季度销量
+            if(line.get(15) instanceof String){
+                tmCanteen.setQuarterlyNum(new Integer(line.get(15).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列P的数据类型不为字符串");
+            }
+
+            int add = addNew(tmCanteen);
+            if(add != 1){
+                throw new CommonBaseException(ResultCodeEnum.D101 , "插入一行数据失败,全部回滚");
+            }
+            resultList.add(tmCanteen);
+        }
+        return resultList;
+    }
+
     public IPage<TmCanteen> getCanteenList(long pageNum , long pageSize , String name){
     public IPage<TmCanteen> getCanteenList(long pageNum , long pageSize , String name){
         IPage<TmCanteen> page = new Page<TmCanteen>(pageNum , pageSize);
         IPage<TmCanteen> page = new Page<TmCanteen>(pageNum , pageSize);
         LambdaQueryWrapper<TmCanteen> lambdaQueryWrapper  = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<TmCanteen> lambdaQueryWrapper  = new LambdaQueryWrapper<>();

+ 84 - 0
dinner-core/src/main/java/com/fdage/base/service/impl/TmDeskServiceImpl.java

@@ -5,12 +5,18 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fdage.base.dao.MyDeskDao;
 import com.fdage.base.dao.MyDeskDao;
+import com.fdage.base.entity.TmCanteen;
 import com.fdage.base.entity.TmDesk;
 import com.fdage.base.entity.TmDesk;
 import com.fdage.base.dao.TmDeskDao;
 import com.fdage.base.dao.TmDeskDao;
 import com.fdage.base.entity.TmOrder;
 import com.fdage.base.entity.TmOrder;
+import com.fdage.base.enums.IdPreEnum;
 import com.fdage.base.service.ITmDeskService;
 import com.fdage.base.service.ITmDeskService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import fdage.back.sdk.base.uuid.SnowFlakeUUidUtils;
 import net.bytebuddy.asm.Advice;
 import net.bytebuddy.asm.Advice;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -18,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
+import java.util.Arrays;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -95,4 +102,81 @@ public class TmDeskServiceImpl extends ServiceImpl<TmDeskDao, TmDesk> implements
         return getBaseMapper().updateById(tmDesk);
         return getBaseMapper().updateById(tmDesk);
     }
     }
 
 
+    @Transactional(rollbackFor = Exception.class)
+    public int addNewFromExcel(List<String[]> excelList){
+        if(CollectionUtils.isEmpty(excelList)){
+            return -1;
+        }
+        for (int i = 1; i < excelList.size(); i++) {
+            List<String> line = Arrays.asList(excelList.get(i));
+            if(CollectionUtils.isEmpty(line)){
+                continue;
+            }
+            TmDesk desk = new TmDesk();
+            //直接跳过第1列(序号),从第二列开始,餐桌名称
+            if(line.get(1) instanceof String){
+                desk.setDeskName(line.get(1).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列B的数据类型不为字符串");
+            }
+            //简介
+            if(line.get(2) instanceof String){
+                desk.setSimpleDesc(line.get(2).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列C的数据类型不为字符串");
+            }
+
+            //所属餐厅ID
+            if(line.get(3) instanceof String){
+                desk.setCanteenId(line.get(3).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列D的数据类型不为字符串");
+            }
+
+            //类型
+            if(line.get(4) instanceof String){
+                desk.setType(new Integer(line.get(4).trim()));
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列E的数据类型不为字符串");
+            }
+
+            //热点ID
+            if(line.get(5) instanceof String){
+                desk.setHotId(line.get(5).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列F的数据类型不为字符串");
+            }
+            //热点标题
+            if(line.get(6) instanceof String){
+                desk.setHotTag(line.get(6).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列G的数据类型不为字符串");
+            }
+
+            //预览图链接
+            if(line.get(7) instanceof String){
+                desk.setCoverImage(line.get(7).trim());
+            }else{
+                throw new CommonBaseException(ResultCodeEnum.D101 , "数据列H的数据类型不为字符串");
+            }
+            int add = addNew(desk);
+            if(add != 1){
+                throw new CommonBaseException(ResultCodeEnum.D101 , "插入一行数据失败,全部回滚");
+            }
+        }
+        return 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public int addNew(TmDesk tmDesk){
+        if(null == tmDesk){
+            return -1;
+        }
+        tmDesk.setId(SnowFlakeUUidUtils.generaUUid(null , null , IdPreEnum.DESK_PRE.getPre()));
+        tmDesk.setCreateTime(LocalDateTime.now());
+        tmDesk.setUpdateTime(LocalDateTime.now());
+        tmDesk.setIsDelete(0);
+        return getBaseMapper().insert(tmDesk);
+    }
+
 }
 }

+ 284 - 0
dinner-core/src/main/java/com/fdage/base/utils/excel/Excel2003Reader.java

@@ -0,0 +1,284 @@
+package com.fdage.base.utils.excel;
+
+
+import org.apache.poi.hssf.eventusermodel.*;
+import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
+import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
+import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.record.*;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.springframework.util.CollectionUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Excel2003格式解析
+ *
+ * @author lipengjun
+ * @email 939961241@qq.com
+ * @date 2017年10月28日 13:11:27
+ */
+public class Excel2003Reader implements HSSFListener {
+    private int minColumns = -1;
+
+    private POIFSFileSystem fs;
+
+    /**
+     * 最后一行行号
+     */
+    private int lastRowNumber;
+
+    /**
+     * 最后一列列号
+     */
+    private int lastColumnNumber;
+
+    /**
+     * Should we output the formula, or the value it has?
+     */
+    private boolean outputFormulaValues = true;
+
+    /**
+     * For parsing Formulas
+     */
+    private SheetRecordCollectingListener workbookBuildingListener;
+
+    // 工作薄
+    private HSSFWorkbook stubWorkbook;
+
+    // Records we pick up as we process
+    private SSTRecord sstRecord;
+
+    private FormatTrackingHSSFListener formatListener;
+
+    // 表索引
+    private int sheetIndex = -1;
+
+    private BoundSheetRecord[] orderedBSRs;
+
+    @SuppressWarnings("rawtypes")
+    private ArrayList boundSheetRecords = new ArrayList();
+
+    // For handling formulas with string results
+    private int nextRow;
+
+    private int nextColumn;
+
+    private boolean outputNextStringRecord;
+
+    // 存储行记录的容器
+    private List<String> rowlist = new ArrayList<String>();
+    ;
+
+    // 单Sheet数据
+    private List<String[]> sheetData = new ArrayList<String[]>();
+
+    // 多Sheet数据
+    private Map<Integer, List<String[]>> workData = new HashMap<Integer, List<String[]>>();
+
+
+
+    /**
+     * 遍历excel下所有的sheet
+     *
+     * @param fileStream 处理文件流
+     * @throws IOException 抛出IO异常
+     */
+    public void process(InputStream fileStream)
+            throws IOException {
+        this.fs = new POIFSFileSystem(fileStream);
+        MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(
+                this);
+        formatListener = new FormatTrackingHSSFListener(listener);
+        HSSFEventFactory factory = new HSSFEventFactory();
+        HSSFRequest request = new HSSFRequest();
+        if (outputFormulaValues) {
+            request.addListenerForAllRecords(formatListener);
+        } else {
+            workbookBuildingListener = new SheetRecordCollectingListener(
+                    formatListener);
+            request.addListenerForAllRecords(workbookBuildingListener);
+        }
+        factory.processWorkbookEvents(request, fs);
+    }
+
+    /**
+     * HSSFListener 监听方法,处理 Record
+     *
+     * @param record 行记录
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public void processRecord(Record record) {
+        int thisRow = -1;
+        int thisColumn = -1;
+        String thisStr = null;
+        String value = null;
+        switch (record.getSid()) {
+            case BoundSheetRecord.sid:
+                boundSheetRecords.add(record);
+                break;
+            case BOFRecord.sid:
+                BOFRecord br = (BOFRecord) record;
+                if (br.getType() == BOFRecord.TYPE_WORKSHEET) {
+                    // 如果有需要,则建立子工作薄
+                    if (workbookBuildingListener != null && stubWorkbook == null) {
+                        stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
+                    }
+                    if (sheetIndex >= 0) {
+                        List<String[]> data = new ArrayList<String[]>();
+                        data.addAll(sheetData);
+                        workData.put(sheetIndex, data);
+                        sheetData.clear();
+                    }
+                    sheetIndex++;
+                    if (orderedBSRs == null) {
+                        orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
+                    }
+                }
+                break;
+            case SSTRecord.sid:
+                sstRecord = (SSTRecord) record;
+                break;
+            case BlankRecord.sid:
+                BlankRecord brec = (BlankRecord) record;
+                thisRow = brec.getRow();
+                thisColumn = brec.getColumn();
+                thisStr = "";
+                rowlist.add(thisColumn, thisStr);
+                break;
+            case BoolErrRecord.sid: // 单元格为布尔类型
+                BoolErrRecord berec = (BoolErrRecord) record;
+                thisRow = berec.getRow();
+                thisColumn = berec.getColumn();
+                thisStr = berec.getBooleanValue() + "";
+                rowlist.add(thisColumn, thisStr);
+                break;
+            case FormulaRecord.sid: // 单元格为公式类型
+                FormulaRecord frec = (FormulaRecord) record;
+                thisRow = frec.getRow();
+                thisColumn = frec.getColumn();
+                if (outputFormulaValues) {
+                    if (Double.isNaN(frec.getValue())) {
+                        // Formula result is a string
+                        // This is stored in the next record
+                        outputNextStringRecord = true;
+                        nextRow = frec.getRow();
+                        nextColumn = frec.getColumn();
+                    } else {
+                        thisStr = formatListener.formatNumberDateCell(frec);
+                    }
+                } else {
+                    thisStr = '"' + HSSFFormulaParser.toFormulaString(
+                            stubWorkbook, frec.getParsedExpression()) + '"';
+                }
+                rowlist.add(thisColumn, thisStr);
+                break;
+            case StringRecord.sid:// 单元格中公式的字符串
+                if (outputNextStringRecord) {
+                    // String for formula
+                    StringRecord srec = (StringRecord) record;
+                    thisStr = srec.getString();
+                    thisRow = nextRow;
+                    thisColumn = nextColumn;
+                    outputNextStringRecord = false;
+                }
+                break;
+            case LabelRecord.sid:
+                LabelRecord lrec = (LabelRecord) record;
+                thisColumn = lrec.getColumn();
+                value = lrec.getValue().trim();
+                value = value.equals("") ? " " : value;
+                this.rowlist.add(thisColumn, value);
+                break;
+            case LabelSSTRecord.sid: // 单元格为字符串类型
+                LabelSSTRecord lsrec = (LabelSSTRecord) record;
+                thisColumn = lsrec.getColumn();
+                if (sstRecord == null) {
+                    rowlist.add(thisColumn, " ");
+                } else {
+                    value = sstRecord.getString(lsrec.getSSTIndex()).toString().trim();
+                    value = value.equals("") ? " " : value;
+                    rowlist.add(thisColumn, value);
+                }
+                break;
+            case NumberRecord.sid: // 单元格为数字类型
+                NumberRecord numrec = (NumberRecord) record;
+                thisColumn = numrec.getColumn();
+                value = formatListener.formatNumberDateCell(numrec).trim();
+                value = value.equals("") ? " " : value;
+                // 向容器加入列值
+                rowlist.add(thisColumn, value);
+                break;
+            default:
+                break;
+        }
+
+        // 遇到新行的操作
+        if (thisRow != -1 && thisRow != lastRowNumber) {
+            lastColumnNumber = -1;
+        }
+
+        // 空值的操作
+        if (record instanceof MissingCellDummyRecord) {
+            MissingCellDummyRecord mc = (MissingCellDummyRecord) record;
+            thisColumn = mc.getColumn();
+            rowlist.add(thisColumn, "");
+        }
+
+        // 更新行和列的值
+        if (thisRow > -1) {
+            lastRowNumber = thisRow;
+        }
+        if (thisColumn > -1) {
+            lastColumnNumber = thisColumn;
+        }
+
+        // 行结束时的操作
+        if (record instanceof LastCellOfRowDummyRecord) {
+            if (minColumns > 0) {
+                // 列值重新置空
+                if (lastColumnNumber == -1) {
+                    lastColumnNumber = 0;
+                }
+            }
+            lastColumnNumber = -1;
+            // 每行结束时, 数据写入集合
+            sheetData.add(rowlist.toArray(new String[]{}));
+            // 清空容器
+            rowlist.clear();
+        }
+    }
+
+    /**
+     * 获取数据(单Sheet)
+     *
+     * @param sheetIndex sheet下标
+     * @return List<String[]> 数据
+     */
+    public List<String[]> getSheetData(Integer sheetIndex) {
+        List<String[]> list = workData.get(sheetIndex);
+        if(CollectionUtils.isEmpty(list)){
+            return sheetData;
+        }
+        return list;
+    }
+
+
+
+    /**
+     * 获取数据(多Sheet)
+     *
+     * @return Map<Integer, List<String[]>> 多sheet的数据
+     */
+    public Map<Integer, List<String[]>> getSheetData() {
+        return workData;
+    }
+}

+ 674 - 0
dinner-core/src/main/java/com/fdage/base/utils/excel/Excel2007Reader.java

@@ -0,0 +1,674 @@
+
+package com.fdage.base.utils.excel;
+
+import com.fdage.base.enums.XssfDataType;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * Excel2007解析器
+ *
+ * @author lipengjun
+ * @email 939961241@qq.com
+ * @date 2017年10月28日 13:11:27
+ */
+public class Excel2007Reader extends DefaultHandler {
+
+    /**
+     * Table with unique strings
+     */
+    private ReadOnlySharedStringsTable sharedStringsTable;
+
+    /**
+     * 总共解析多少列
+     */
+    private final int minColumnCount = 0;
+
+    /**
+     * 判断是否值标签‘V’
+     */
+    private boolean vIsOpen;
+
+    /**
+     * 单元数据类型,startElement中确认赋值,endElement中使用判断
+     */
+    private XssfDataType nextDataType;
+
+    /**
+     * 当前解析列下标
+     */
+    private int thisColumn = -1;
+
+    /**
+     * 已完成解析列最近下标
+     */
+    private int lastColumnNumber = 0;
+
+    /**
+     * 单元格值内容临时存储
+     */
+    private StringBuffer value = new StringBuffer();
+
+    /**
+     * 单行数据集合
+     */
+    private List<String> rowlist = new ArrayList<String>();
+
+    /**
+     * 当前sheet
+     */
+    private int sheetIndex = -1;
+
+    /**
+     * 单Sheet数据
+     */
+    private List<String[]> sheetData = new ArrayList<String[]>();
+
+    /**
+     * 多Sheet数据
+     */
+    private Map<Integer, List<String[]>> workData = new HashMap<Integer, List<String[]>>();
+
+    private DataFormatter formatter;
+
+    /**
+     * 格式索引暂时不用
+     */
+    private short formatIndex;
+
+    private String formatString;
+
+    /**
+     * 样式表暂时不用
+     */
+    private StylesTable stylesTable;
+
+    /**
+     * 解析单Sheet内容
+     *
+     * @param strings          字符串
+     * @param sheetInputStream 输入流
+     * @throws IOException                  IO异常
+     * @throws ParserConfigurationException 解析异常
+     * @throws SAXException                 SAX异常
+     */
+    private void processSheet(ReadOnlySharedStringsTable strings,
+                              InputStream sheetInputStream)
+            throws IOException, ParserConfigurationException, SAXException {
+        sheetIndex++;
+        this.sharedStringsTable = strings;
+        InputSource sheetSource = new InputSource(sheetInputStream);
+        SAXParserFactory saxFactory = SAXParserFactory.newInstance();
+        //防止外部实体注入
+        saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+        saxFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        SAXParser saxParser = saxFactory.newSAXParser();
+        XMLReader sheetParser = saxParser.getXMLReader();
+        sheetParser.setContentHandler(this);
+        sheetParser.parse(sheetSource);
+    }
+
+    /**
+     * 解析多Sheet内容
+     * 异常处理暂时不完整
+     *
+     * @param fileStream 文件流
+     * @param isMuti     是否多个sheet
+     */
+    public void process(InputStream fileStream, boolean isMuti) {
+        OPCPackage xlsxPackage;
+        try {
+            xlsxPackage = OPCPackage.open(fileStream);
+
+            ReadOnlySharedStringsTable sharedStringsTable = new ReadOnlySharedStringsTable(
+                    xlsxPackage);
+            XSSFReader xssfReader = new XSSFReader(xlsxPackage);
+            this.stylesTable = xssfReader.getStylesTable();
+            this.formatter = new DataFormatter();
+            XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
+            while (iter.hasNext()) {
+                InputStream stream = iter.next();
+                processSheet(sharedStringsTable, stream);
+                stream.close();
+                List<String[]> data = new ArrayList<String[]>();
+                data.addAll(sheetData);
+                workData.put(sheetIndex, data);
+                sheetData.clear();
+                if (!isMuti) {// 如果只加载一个sheet内容,直接跳出循环
+                    break;
+                }
+            }
+        } catch (InvalidFormatException e) {
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"解析EXCEL出错");
+        } catch (IOException e) {
+
+            e.printStackTrace();
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"解析EXCEL出错");
+        } catch (SAXException e) {
+
+            e.printStackTrace();
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"解析EXCEL出错");
+        } catch (OpenXML4JException e) {
+
+            e.printStackTrace();
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"解析EXCEL出错");
+        } catch (ParserConfigurationException e) {
+            e.printStackTrace();
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"解析EXCEL出错");
+        }
+
+    }
+
+    /**
+     * Receive notification of the start of an element.
+     * <p>
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each element (such as allocating a new tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri        The Namespace URI, or the empty string if the
+     *                   element has no Namespace URI or if Namespace
+     *                   processing is not being performed.
+     * @param localName  The local name (without prefix), or the
+     *                   empty string if Namespace processing is not being
+     *                   performed.
+     * @param name       The qualified name (with prefix), or the
+     *                   empty string if qualified names are not available.
+     * @param attributes The attributes attached to the element.  If
+     *                   there are no attributes, it shall be an empty
+     *                   Attributes object.
+     * @throws SAXException Any SAX exception, possibly
+     *                      wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startElement
+     */
+    @Override
+    public void startElement(String uri, String localName, String name,
+                             Attributes attributes)
+            throws SAXException {
+        if ("inlineStr".equals(name) || "v".equals(name)) {// v=> value
+            vIsOpen = true;
+            value.setLength(0);
+        } else if ("c".equals(name)) {// c => cell
+            vIsOpen = false;
+            String r = attributes.getValue("r");
+            int firstDigit = -1;
+            for (int c = 0; c < r.length(); ++c) {
+                if (Character.isDigit(r.charAt(c))) {
+                    firstDigit = c;
+                    break;
+                }
+            }
+            thisColumn = nameToColumn(r.substring(0, firstDigit));
+            this.nextDataType = XssfDataType.NUMBER;
+            String cellType = attributes.getValue("t");
+            String cellStyleStr = attributes.getValue("s");
+            if ("b".equals(cellType)) {
+                nextDataType = XssfDataType.BOOL;
+            } else if ("e".equals(cellType)) {
+                nextDataType = XssfDataType.ERROR;
+            } else if ("inlineStr".equals(cellType)) {
+                nextDataType = XssfDataType.INLINESTR;
+            } else if ("s".equals(cellType)) {
+                nextDataType = XssfDataType.SSTINDEX;
+            } else if ("str".equals(cellType)) {
+                nextDataType = XssfDataType.FORMULA;
+            } else if (cellStyleStr != null) {
+                // if (cellStyleStr.equals("2")) {// 判断是否是日期
+                // nextDataType = XssfDataType.DATE;
+                // }
+                int styleIndex = Integer.parseInt(cellStyleStr);
+                XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
+                this.formatIndex = style.getDataFormat();
+                this.formatString = style.getDataFormatString();
+                if (formatIndex == 14 || formatIndex == 15 || formatIndex == 16
+                        || formatIndex == 17) {
+                    nextDataType = XssfDataType.DATE;
+                } else if (formatIndex == 18 || formatIndex == 19 || formatIndex == 20
+                        || formatIndex == 21 || formatIndex == 45 || formatIndex == 46
+                        || formatIndex == 47) {
+                    nextDataType = XssfDataType.TIME;
+                } else if (formatIndex == 22) {
+                    nextDataType = XssfDataType.DATETIME;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Receive notification of the end of an element.
+     * <p>
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each element (such as finalising a tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri       The Namespace URI, or the empty string if the
+     *                  element has no Namespace URI or if Namespace
+     *                  processing is not being performed.
+     * @param localName The local name (without prefix), or the
+     *                  empty string if Namespace processing is not being
+     *                  performed.
+     * @param name      The qualified name (with prefix), or the
+     *                  empty string if qualified names are not available.
+     * @throws SAXException Any SAX exception, possibly
+     *                      wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endElement
+     */
+    @Override
+    public void endElement(String uri, String localName, String name)
+            throws SAXException {
+        String thisStr = null;
+        // v标识单元格值标签
+        if ("v".equals(name)) {
+            // Process the value contents as required.
+            // Do now, as characters() may be called more than once
+            switch (nextDataType) {
+                case BOOL:
+                    char first = value.charAt(0);
+                    thisStr = first == '0' ? "FALSE" : "TRUE";
+                    break;
+
+                case ERROR:
+                    thisStr = "\"ERROR:" + value.toString() + '"';
+                    break;
+
+                case FORMULA:
+                    // A formula could result in a string value,
+                    // so always add double-quote characters.
+                    thisStr = '"' + value.toString() + '"';
+                    break;
+
+                case INLINESTR:
+                    // TODO: have seen an example of this, so it's untested.
+                    XSSFRichTextString rtsi = new XSSFRichTextString(
+                            value.toString());
+                    thisStr = rtsi.toString();
+                    break;
+
+                case SSTINDEX:
+                    String sstIndex = value.toString();
+                    try {
+                        int idx = Integer.parseInt(sstIndex);
+                        XSSFRichTextString rtss = new XSSFRichTextString(
+                                sharedStringsTable.getEntryAt(idx));
+                        thisStr = rtss.toString();
+                    } catch (NumberFormatException ex) {
+                        // @TODO
+                    }
+                    break;
+
+                case NUMBER:
+                    String n = value.toString();
+                    BigDecimal bd = new BigDecimal(n);
+
+                    // 未移除最后的0,按默认string处理
+                    thisStr = bd.toString();
+                    break;
+                case DATE:
+                    Date date = HSSFDateUtil.getJavaDate(Double.valueOf(value.toString()));
+                    thisStr = new SimpleDateFormat("yyyy-MM-dd").format(date);
+                    break;
+                case DATETIME:
+                    Date dateTime = HSSFDateUtil.getJavaDate(Double.valueOf(value.toString()));
+                    thisStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dateTime);
+                    break;
+                case TIME:
+                    Date time = HSSFDateUtil.getJavaDate(Double.valueOf(value.toString()));
+                    thisStr = new SimpleDateFormat("HH:mm:ss").format(time);
+                    break;
+                default:
+                    thisStr = "(TODO: Unexpected type: " + nextDataType + ")";
+                    break;
+            }
+            // 判定已解析列下标与当前下标差异,超过1则表示前面有空单元格,自动填入空串
+            for (int i = lastColumnNumber; i < thisColumn - 1; ++i) {
+                // 使用"" 作为空串
+                rowlist.add("");
+            }
+            rowlist.add(thisStr);
+            // 更新已解析列下标
+            if (thisColumn > -1) {
+                lastColumnNumber = thisColumn;
+            }
+
+        } else if ("row".equals(name)) {// 标识当前行结束,行数据写入结果
+            for (int i = lastColumnNumber; i < (this.minColumnCount); i++) {
+                rowlist.add("");
+            }
+            lastColumnNumber = -1;
+            sheetData.add(rowlist.toArray(new String[]{}));
+            rowlist.clear();
+        }
+
+    }
+
+    /**
+     * 添加字符
+     *
+     * @param ch     char[] 添加字符串
+     * @param start  开始位置
+     * @param length 长度
+     * @throws SAXException SAX异常
+     */
+    @Override
+    public void characters(char[] ch, int start, int length)
+            throws SAXException {
+        if (vIsOpen) {
+            value.append(ch, start, length);
+        }
+    }
+
+    /**
+     * 获取当前列索引下标
+     *
+     * @param name 名字
+     * @return 整型
+     */
+    private int nameToColumn(String name) {
+        int column = -1;
+        for (int i = 0; i < name.length(); ++i) {
+            int c = name.charAt(i);
+            column = (column + 1) * 26 + c - 'A';
+        }
+        return column;
+    }
+
+    /**
+     * 获取数据(单Sheet)
+     *
+     * @param sheetIndex sheet下标
+     * @return List<String[]>
+     */
+    public List<String[]> getSheetData(Integer sheetIndex) {
+        return workData.get(sheetIndex);
+    }
+
+    /**
+     * 获取数据(多Sheet)
+     *
+     * @return Map<Integer,List<String[]>>  对应列的Map
+     */
+    public Map<Integer, List<String[]>> getSheetData() {
+        return workData;
+    }
+
+    /**
+     * 取得sharedStringsTable的值
+     *
+     * @return sharedStringsTable值.
+     */
+    public ReadOnlySharedStringsTable getSharedStringsTable() {
+        return sharedStringsTable;
+    }
+
+    /**
+     * 设定sharedStringsTable的值
+     *
+     * @param sharedStringsTable 设定值
+     */
+    public void setSharedStringsTable(ReadOnlySharedStringsTable sharedStringsTable) {
+        this.sharedStringsTable = sharedStringsTable;
+    }
+
+    /**
+     * 取得vIsOpen的值
+     *
+     * @return vIsOpen值.
+     */
+    public boolean isvIsOpen() {
+        return vIsOpen;
+    }
+
+    /**
+     * 设定vIsOpen的值
+     *
+     * @param vIsOpen 设定值
+     */
+    public void setvIsOpen(boolean vIsOpen) {
+        this.vIsOpen = vIsOpen;
+    }
+
+    /**
+     * 取得nextDataType的值
+     *
+     * @return nextDataType值.
+     */
+    public XssfDataType getNextDataType() {
+        return nextDataType;
+    }
+
+    /**
+     * 设定nextDataType的值
+     *
+     * @param nextDataType 设定值
+     */
+    public void setNextDataType(XssfDataType nextDataType) {
+        this.nextDataType = nextDataType;
+    }
+
+    /**
+     * 取得thisColumn的值
+     *
+     * @return thisColumn值.
+     */
+    public int getThisColumn() {
+        return thisColumn;
+    }
+
+    /**
+     * 设定thisColumn的值
+     *
+     * @param thisColumn 设定值
+     */
+    public void setThisColumn(int thisColumn) {
+        this.thisColumn = thisColumn;
+    }
+
+    /**
+     * 取得lastColumnNumber的值
+     *
+     * @return lastColumnNumber值.
+     */
+    public int getLastColumnNumber() {
+        return lastColumnNumber;
+    }
+
+    /**
+     * 设定lastColumnNumber的值
+     *
+     * @param lastColumnNumber 设定值
+     */
+    public void setLastColumnNumber(int lastColumnNumber) {
+        this.lastColumnNumber = lastColumnNumber;
+    }
+
+    /**
+     * 取得value的值
+     *
+     * @return value值.
+     */
+    public StringBuffer getValue() {
+        return value;
+    }
+
+    /**
+     * 设定value的值
+     *
+     * @param value 设定值
+     */
+    public void setValue(StringBuffer value) {
+        this.value = value;
+    }
+
+    /**
+     * 取得rowlist的值
+     *
+     * @return rowlist值.
+     */
+    public List<String> getRowlist() {
+        return rowlist;
+    }
+
+    /**
+     * 设定rowlist的值
+     *
+     * @param rowlist 设定值
+     */
+    public void setRowlist(List<String> rowlist) {
+        this.rowlist = rowlist;
+    }
+
+    /**
+     * 取得sheetIndex的值
+     *
+     * @return sheetIndex值.
+     */
+    public int getSheetIndex() {
+        return sheetIndex;
+    }
+
+    /**
+     * 设定sheetIndex的值
+     *
+     * @param sheetIndex 设定值
+     */
+    public void setSheetIndex(int sheetIndex) {
+        this.sheetIndex = sheetIndex;
+    }
+
+    /**
+     * 取得workData的值
+     *
+     * @return workData值.
+     */
+    public Map<Integer, List<String[]>> getWorkData() {
+        return workData;
+    }
+
+    /**
+     * 设定workData的值
+     *
+     * @param workData 设定值
+     */
+    public void setWorkData(Map<Integer, List<String[]>> workData) {
+        this.workData = workData;
+    }
+
+    /**
+     * 取得formatter的值
+     *
+     * @return formatter值.
+     */
+    public DataFormatter getFormatter() {
+        return formatter;
+    }
+
+    /**
+     * 设定formatter的值
+     *
+     * @param formatter 设定值
+     */
+    public void setFormatter(DataFormatter formatter) {
+        this.formatter = formatter;
+    }
+
+    /**
+     * 取得formatIndex的值
+     *
+     * @return formatIndex值.
+     */
+    public short getFormatIndex() {
+        return formatIndex;
+    }
+
+    /**
+     * 设定formatIndex的值
+     *
+     * @param formatIndex 设定值
+     */
+    public void setFormatIndex(short formatIndex) {
+        this.formatIndex = formatIndex;
+    }
+
+    /**
+     * 取得formatString的值
+     *
+     * @return formatString值.
+     */
+    public String getFormatString() {
+        return formatString;
+    }
+
+    /**
+     * 设定formatString的值
+     *
+     * @param formatString 设定值
+     */
+    public void setFormatString(String formatString) {
+        this.formatString = formatString;
+    }
+
+    /**
+     * 取得stylesTable的值
+     *
+     * @return stylesTable值.
+     */
+    public StylesTable getStylesTable() {
+        return stylesTable;
+    }
+
+    /**
+     * 设定stylesTable的值
+     *
+     * @param stylesTable 设定值
+     */
+    public void setStylesTable(StylesTable stylesTable) {
+        this.stylesTable = stylesTable;
+    }
+
+    /**
+     * 取得minColumnCount的值
+     *
+     * @return minColumnCount值.
+     */
+    public int getMinColumnCount() {
+        return minColumnCount;
+    }
+
+    /**
+     * 设定sheetData的值
+     *
+     * @param sheetData 设定值
+     */
+    public void setSheetData(List<String[]> sheetData) {
+        this.sheetData = sheetData;
+    }
+
+}

+ 610 - 0
dinner-core/src/main/java/com/fdage/base/utils/excel/ExcelExport.java

@@ -0,0 +1,610 @@
+package com.fdage.base.utils.excel;
+
+import com.aliyun.oss.common.utils.StringUtils;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.sql.Timestamp;
+import java.text.DecimalFormat;
+import java.util.*;
+
+/**
+ * 导出EXCEL功能包主类
+ * 使用POI进行EXCEL导出的功能类。
+ * 目前简单处理,未设置内存优化。 数据量偏大,出现性能问题时再处理。
+ *
+ * @author lipengjun
+ * @email 939961241@qq.com
+ * @date 2017年10月28日 13:11:27
+ */
+public class ExcelExport {
+
+    /**
+     * EXCEL 2003 扩展名
+     */
+    public static final String EXCEL03_EXTENSION = ".xls";
+
+    /**
+     * EXCEL 2007 扩展名
+     */
+    public static final String EXCEL07_EXTENSION = ".xls";
+
+    /**
+     * 工作表
+     */
+    private Workbook workBook;
+
+    /**
+     * 导出文件名
+     */
+    private String exportFileName;
+
+    /**
+     * 日志
+     */
+    private Log logger = LogFactory.getLog(ExcelExport.class);
+
+    /**
+     * 默认构造方法。
+     * 自动生成工作表。
+     */
+    public ExcelExport() {
+
+        this("workbook.xlsx");
+
+    }
+
+    /**
+     * 指定导出文件名的构造方法
+     * 指定导出文件名。 同时根据指定文件名的扩展名确定导出格式是03或是07 。
+     * 不带扩展名默认为07格式。(POI 07格式支持内存优化)
+     *
+     * @param exportFileName 要导出的文件名(带扩展名。不带扩展名默认为07)
+     */
+    public ExcelExport(String exportFileName) {
+
+        if (StringUtils.isNullOrEmpty(exportFileName)) {
+            exportFileName = "workbook.xlsx";
+        }
+
+        String fileName = exportFileName.toLowerCase();
+
+        // 根据文件名扩展名生成EXCEL格式。
+        if (fileName.endsWith(ExcelExport.EXCEL03_EXTENSION)) {
+            workBook = new HSSFWorkbook();
+        } else if (exportFileName.endsWith(ExcelExport.EXCEL07_EXTENSION)) {
+            workBook = new XSSFWorkbook();
+        } else {
+            workBook = new XSSFWorkbook();
+            fileName += ".xlsx";
+            // 按正则替换? 处理文件名最后一个字符为“.” 的问题
+            // fileName = fileName.replaceAll("..", ".");
+        }
+
+        // 最后按小写文件名输出
+        this.exportFileName = fileName;
+    }
+
+    /**
+     * 主要功能: 导出EXCEL到response
+     * 注意事项:无
+     *
+     * @param response HttpServletResponse
+     */
+    public void export(HttpServletResponse response) {
+
+        // response.setHeader("Content-Disposition","attachment;filename=totalExcel.xls");
+        response.reset();
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
+        // response.setContentType("text/html;charset=UTF-8");
+        // response.setContentType("APPLICATION/*");
+        String fileName = null;
+
+        // 处理编码
+        try {
+
+            //modify by ld 2017年4月10日19:04:37 根据浏览器编码文件名
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            String userAgent = request.getHeader("User-Agent");
+            //针对IE或者以IE为内核的浏览器:
+            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
+                fileName = URLEncoder.encode(exportFileName, "UTF-8");
+            } else {
+                //非IE浏览器的处理:
+                fileName = new String(exportFileName.getBytes("UTF-8"), "ISO-8859-1");
+            }
+        } catch (UnsupportedEncodingException e) {
+
+            fileName = "export.xls";
+        }
+
+        response.setHeader("Content-Disposition", "attachment;filename="
+                + fileName);
+
+        ServletOutputStream output;
+
+        try {
+            output = response.getOutputStream();
+            workBook.write(output);
+            output.flush();
+            output.close();
+        } catch (IOException e) {
+            logger.error("导出文件出错了", e);
+            throw new CommonBaseException(ResultCodeEnum.D101 , "文件导出错误");
+        }
+
+    }
+
+    /**
+     * 主要功能:简单测试
+     * 注意事项:无
+     *
+     * @param args 参数
+     */
+    public static void main(String[] args) {
+        ExcelExport ee1 = new ExcelExport();
+
+        List<Object[]> list1 = new ArrayList<Object[]>();
+
+        List<Object> obj = new ArrayList<Object>();
+
+        obj.add("370681198002042214");
+        obj.add(new Date());
+        obj.add(new Timestamp(System.currentTimeMillis()));
+        obj.add(1);
+        obj.add(11111111111111L);
+        obj.add(123456.123456f);
+        obj.add(123456789.12345678);
+        obj.add(new BigDecimal("123456789123456789.1234"));
+        obj.add(true);
+
+        list1.add(obj.toArray());
+
+        String[] header = new String[]{"身份证号", "日期", "时间", "整型", "长整", "浮点",
+                "双精度", "大数", "布尔"};
+        ee1.addSheetByArray("测试1", list1, header);
+
+        OutputStream fis;
+        try {
+            fis = new FileOutputStream("D:\\test1.xlsx");
+
+            ee1.getWorkbook().write(fis);
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * 主要功能: 在EXCEL中添加一个Sheet
+     * 注意事项:添加Sheet 并将List<Object[]> 中的数据填充
+     *
+     * @param sheetName  表单名字
+     * @param list       要填充的数据  以Object[] 表示单条记录
+     * @param colCaption 要生成的表头
+     */
+    public void addSheetByArray(String sheetName, List<Object[]> list,
+                                String[] colCaption) {
+
+        // 创建表单
+        Sheet sheet;
+
+        if (StringUtils.isNullOrEmpty(sheetName)) {
+            sheet = workBook.createSheet();
+        } else {
+            sheet = workBook.createSheet(sheetName);
+        }
+
+        // 生成标题行 (表头)
+        createCaptionRow(colCaption, sheet);
+        // 记录列数
+        int colNum = 0;
+        // 从第二行开始
+        int startRow = 1;
+        for (Object[] obj : list) {
+
+            Row row = sheet.createRow(startRow++);
+            int cols = createRowData(row, Arrays.asList(obj));
+            row.setHeight((short) 400);
+            colNum = colNum > cols ? colNum : cols;
+        }
+
+        adjustCellWidth(colNum, startRow, sheet);
+
+    }
+
+    /**
+     * 主要功能:在EXCEL中添加一个Sheet
+     * 注意事项:添加Sheet 并将List<Object[]> 中的数据填充
+     *
+     * @param sheetName  表单名字
+     * @param list       要填充的数据  以Map<String,Object> 表示单条记录
+     * @param colCaption 要生成的表头
+     */
+    public void addSheetByMap(String sheetName, List<Map<String, Object>> list,
+                              String[] colCaption) {
+
+        // 创建表单
+        Sheet sheet;
+
+        if (StringUtils.isNullOrEmpty(sheetName)) {
+            sheet = workBook.createSheet();
+        } else {
+            sheet = workBook.createSheet(sheetName);
+        }
+
+        // 生成标题行 (表头)
+        createCaptionRow(colCaption, sheet);
+
+        int colNum = 0;
+        // 转换数据
+        // 从第二行开始
+        int startRow = 1;
+        for (Map<String, Object> map : list) {
+            Row row = sheet.createRow(startRow++);
+            int cols = createRowData(row, map.values());
+            row.setHeight((short) 400);
+            colNum = colNum > cols ? colNum : cols;
+        }
+
+        adjustCellWidth(colNum, startRow, sheet);
+
+        // 处理宽度
+
+    }
+
+    /**
+     * 主要功能: 判断fiel
+     * 注意事项:无
+     *
+     * @param name    要判断的字符
+     * @param ignores 要忽略的数组
+     * @return 存在返回true
+     */
+    private boolean isInIgnors(String name, String[] ignores) {
+
+        for (String ignore : ignores) {
+            if (name.equals(ignore)) {
+                return true;
+            }
+        }
+
+        return false;
+
+    }
+
+    /**
+     * 主要功能: 生成每一行的数据
+     * 注意事项:无
+     *
+     * @param row  要处理的行
+     * @param coll 集合类型(List Map.values) 要处理的数据
+     * @return int  列数
+     */
+    private int createRowData(Row row, Collection<Object> coll) {
+
+        int cellNum = 0;
+        for (Object obj : coll) {
+
+            // 空值 按照 "" 字符串处理
+            if (obj == null) {
+                obj = "";
+            }
+            // 转换一个字符串值, 以方便判断
+            String strValue = obj.toString();
+
+            // 创建单元格
+            Cell cell = row.createCell(cellNum);
+
+            // 根据单元格的类型设置值
+            // 公式型(普通BEAN和MAP中暂时并不存在)
+            if (strValue.startsWith("FORMULA:")) {
+
+            } else {
+                // 处理宽度
+
+                // 设置单元格的值
+                setCellValue(cell, obj);
+
+            }
+
+            // 处理下一个单元格
+            cellNum++;
+
+        }
+
+        return cellNum;
+
+    }
+
+    /**
+     * 主要功能: 设置某单元格的值
+     * 注意事项: 同时根据值类型设置样式
+     * TODO: 对数字类型做进一步解析和判断。 对需要按%显示的进行处理。 %可以从表头中获取?
+     * 对于CellType 和CellValue 的设置还需要详细参考文档,避免产生不必要的错误转换
+     * 日期类型格式以通用格式。 待替换为全局变量
+     * 数字保留小数和显示百分比格式暂时未设置
+     *
+     * @param cell 单元格
+     * @param obj  原始值( null已转换为"" 空字符串)
+     */
+    private void setCellValue(Cell cell, Object obj) {
+
+        CreationHelper createHelper = workBook.getCreationHelper();
+        String strValue = obj.toString();
+
+        // 时间戳类型 要先判断时间戳类型再判断时期类型
+        if (obj instanceof Timestamp) {
+            // 转换为Date后赋值
+            Date dt = (Timestamp) obj;
+            // String value = DateUtil.format(dt, "yyyy-MM-dd HH:mm:ss");
+            CellStyle cellStyle = workBook.createCellStyle();
+            cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(
+                    "yyyy-MM-dd HH:mm:ss"));
+
+            cell.setCellValue(dt);
+            cell.setCellStyle(cellStyle);
+
+        }
+        // 日期型
+        else if (obj instanceof Date) {
+
+            // String value = DateUtil.format((Date)obj, "yyyy-MM-dd");
+            // cell.setCellValue(value);
+
+            CellStyle cellStyle = workBook.createCellStyle();
+            cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(
+                    "yyyy-MM-dd"));
+
+            cell.setCellValue((Date) obj);
+            cell.setCellStyle(cellStyle);
+
+        }
+
+        /*
+         * 由于数字类型有int、long、double、BigDecimal 多种类型 输出格式可能要求数字、百分比、保留几位小数等多种格式. 目前仅按照数字格式输出
+         */
+        else if (obj instanceof Integer) {
+            cell.setCellType(CellType.NUMERIC);
+            DecimalFormat df = new DecimalFormat("0");
+            String value = df.format(obj);
+            cell.setCellValue(value);
+
+        } else if (obj instanceof Long) {
+            cell.setCellType(CellType.NUMERIC);
+            DecimalFormat df = new DecimalFormat("0");
+            String value = df.format(obj);
+            cell.setCellValue(value);
+        } else if (obj instanceof Float) {
+            cell.setCellType(CellType.NUMERIC);
+            DecimalFormat df = new DecimalFormat("0.0000");
+            String value = df.format(obj);
+            cell.setCellValue(value);
+        } else if (obj instanceof Double) {
+            cell.setCellType(CellType.NUMERIC);
+            DecimalFormat df = new DecimalFormat("0.0000");
+            String value = df.format(obj);
+            cell.setCellValue(value);
+
+        }
+        // BigDecimal
+        else if (obj instanceof BigDecimal) {
+            cell.setCellType(CellType.STRING);
+
+            cell.setCellValue(strValue);
+
+        }
+
+        // 数字 //数字型要判断 对于百分比显示 、单位是万元等的显示细节要处理
+        // else if (StringUtil.isFloatNumeric(strValue)) {
+
+        // cell.setCellType(CellType.NUMERIC);
+
+        // 暂时未处理BigDecimal 类型的数据,如果有问题,只能使用String
+        // cell.setCellValue(Double.valueOf(strValue));
+
+        // modi by zhang @2016年11月14日14:13:11 处理浮点小数格式 暂时无法统一位数
+        // DecimalFormat df = new DecimalFormat("0.0000");
+        // String whatYourWant = df.format();
+        // 按String 方式输出数字
+        // BigDecimal bd = new BigDecimal(strValue);
+        // cell.setCellValue(bd.toPlainString());
+
+        // 主要处理小数的位数格式,暂时不好判断,输出原值
+        // cell.setCellValue(strValue);
+
+        // CellStyle style = workBook.createCellStyle();
+        // style.setDataFormat(workBook.createDataFormat().getFormat("0.00%"));
+
+        // }
+        // 字符串类型
+        else if (obj instanceof String) {
+            // modi at 2016年11月14日14:27:51 by zhang
+            // 补充设置单元格类型,避免编码类被当作数字类型
+            cell.setCellType(CellType.STRING);
+            // end modi
+
+            cell.setCellValue(strValue);
+
+        } else {
+            cell.setCellType(CellType.STRING);
+            cell.setCellValue(strValue);
+        }
+
+    }
+
+    /**
+     * 主要功能: 生成EXCEL的第一行表头
+     * 注意事项: 默认按第一行生成表头。
+     *
+     * @param colCaption 表头字符数组
+     * @param sheet      表单
+     */
+    private void createCaptionRow(String[] colCaption, Sheet sheet) {
+        // 默认第一行
+        Row row = sheet.createRow(0);
+        row.setHeight((short) 400);
+
+        if (colCaption == null) {
+            return;
+        }
+        // 按列生成表头
+        for (int i = 0; i < colCaption.length; i++) {
+            Cell cell = row.createCell(i);
+            cell.setCellStyle(getStyle("title"));
+            cell.setCellType(CellType.STRING);
+            cell.setCellValue(colCaption[i]);
+
+        }
+
+    }
+
+    /**
+     * 主要功能: 调整列宽
+     * 注意事项:无
+     *
+     * @param cols  列数
+     * @param rows  行数
+     * @param sheet sheet
+     */
+    private void adjustCellWidth(int cols, int rows, Sheet sheet) {
+
+        int[] cellWidth = new int[cols];
+
+        // 取列中最长的行
+        for (int col = 0; col < cols; col++) {
+            for (int row = 0; row < rows; row++) {
+                Cell cell = sheet.getRow(row).getCell(col);
+                String value = getCellValue(cell);
+                int length = value.getBytes().length;
+                if (length > cellWidth[col]) {
+                    cellWidth[col] = length;
+                }
+            }
+        }
+
+        for (int j = 0; j < cellWidth.length; j++) {
+            if (cellWidth[j] > 254) {
+                cellWidth[j] = 254;
+            }
+
+            // 设置列宽度 单位为 1/256 个字符 设置加10%
+            sheet.setColumnWidth(j,
+                    cellWidth[j] * 12 > 255 ? (255 * 256 / 10) : (cellWidth[j] * 12 * 256 / 10));
+        }
+
+    }
+
+    /**
+     * 主要功能: 取单元格的值
+     * 注意事项:按数字和字符两种类型先处理。 BOOLEAN FORMULA 先不处理。 日期格式如何判断?
+     *
+     * @param cell 单元格
+     * @return 单元格的值
+     */
+    @SuppressWarnings("deprecation")
+    private String getCellValue(Cell cell) {
+
+        String value = "";
+
+        try {
+            // 按数字和字符两种类型先处理。 BOOLEAN FORMULA 先不处理。 日期格式如何判断?
+            switch (cell.getCellTypeEnum()) {
+                case NUMERIC:
+                    value = cell.getNumericCellValue() + "1111"; // 增加4位的长度
+                    // 数字格式包含日期格式,但暂时无法判断日期格式
+                    // 除非使用固定宽度。。。。。。。
+
+                    break;
+                case STRING:
+                    value = cell.getStringCellValue();
+                    break;
+                default:
+                    break;
+
+            }
+        } catch (Exception e) {
+            // 不对异常做处理。仅打印到控制台以供调试 
+            // 占不打印
+            // e.printStackTrace();
+        }
+
+        return value;
+
+    }
+
+    /**
+     * 主要功能: 生成表头样式(默认样式)
+     * 注意事项:仅生成默认样式
+     *
+     * @param type 类型 title 或  data
+     * @return CellStyle
+     */
+    private CellStyle getStyle(String type) {
+        CellStyle cs = workBook.createCellStyle();// 创建一个style
+        if ("title".equals(type)) {// 表头样式
+            Font font = workBook.createFont();// 创建一个字体
+            // font.setBoldweight(Font.BOLDWEIGHT_BOLD); // 粗体
+            font.setBold(true);
+            // cs.setAlignment(CellStyle.ALIGN_CENTER);// 水平居中
+            cs.setAlignment(HorizontalAlignment.CENTER);
+            cs.setFillBackgroundColor(HSSFColor.SKY_BLUE.index);// 设置背景色
+            cs.setFont(font);
+        }
+        return cs;
+    }
+
+    /**
+     * 取得wb的值
+     *
+     * @return wb值.
+     */
+    public Workbook getWorkbook() {
+        return workBook;
+    }
+
+    /**
+     * 设定wb的值
+     *
+     * @param workBook 设定值
+     */
+    public void setWorkbook(Workbook workBook) {
+        this.workBook = workBook;
+    }
+
+    /**
+     * 取得exportFileName的值
+     *
+     * @return exportFileName值.
+     */
+    public String getExportFileName() {
+        return exportFileName;
+    }
+
+    /**
+     * 设定exportFileName的值
+     *
+     * @param exportFileName 设定值
+     */
+    public void setExportFileName(String exportFileName) {
+        this.exportFileName = exportFileName;
+    }
+
+}

+ 154 - 0
dinner-core/src/main/java/com/fdage/base/utils/excel/ExcelImport.java

@@ -0,0 +1,154 @@
+package com.fdage.base.utils.excel;
+
+
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Excel文件导入的基本功能类
+ * 可导入EXCEL2003 和 EXCEL2007格式。
+ *
+ * @author lipengjun
+ * @email 939961241@qq.com
+ * @date 2017年10月28日 13:11:27
+ */
+public class ExcelImport {
+    /**
+     * excel2003扩展名
+     */
+    public static final String EXCEL03_EXTENSION = ".xls";
+
+    /**
+     * excel2007扩展名
+     */
+    public static final String EXCEL07_EXTENSION = ".xlsx";
+
+    private ExcelImport() {
+    }
+
+    /**
+     * 解析EXCEL数据为 List<String[]>
+     *
+     * @param excelFile 要解析的上传EXCEL文件
+     * @return List<String[]) 行(列)
+     */
+    public static List<String[]> getExcelData07(MultipartFile excelFile) {
+        List<String[]> resultList = null;
+
+        if (null == excelFile || excelFile.isEmpty()) {
+            throw new CommonBaseException(ResultCodeEnum.D101 , "文件内容为空!");
+
+        }
+
+        Excel2007Reader excel07 = new Excel2007Reader();
+        try {
+            excel07.process(excelFile.getInputStream(), false);
+        } catch (Exception e) {
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+        }
+        resultList = excel07.getSheetData(0);
+
+        return resultList;
+    }
+
+    /**
+     * 解析EXCEL数据为 List<String[]>
+     *
+     * @param excelFile 要解析的上传EXCEL文件
+     * @return List<String[]) 行(列)
+     */
+    public static List<String[]> getExcelData03(MultipartFile excelFile) {
+        List<String[]> resultList = null;
+
+        if (null == excelFile || excelFile.isEmpty()) {
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"文件内容为空!");
+
+        }
+
+        Excel2003Reader excel03 = new Excel2003Reader();// 实例化excel处理对象
+        try {
+            excel03.process(excelFile.getInputStream());
+        } catch (IOException e) {
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+        }
+        resultList = excel03.getSheetData(0);
+
+        return resultList;
+    }
+
+    /**
+     * 通过解析MultipartFile对象获取excel内容,并且将其拼装为List<String[]>对象返回
+     *
+     * @param excelFile
+     * @return
+     * @throws Exception
+     */
+    public static List<String[]> getExcelData(MultipartFile excelFile)
+            throws CommonBaseException {
+        List<String[]> resultList = null;
+
+        if (!excelFile.isEmpty()) {// 上传的文件不能为空
+            String excelFileName = excelFile.getOriginalFilename();// 文件名(带后缀)
+            if (excelFileName.toLowerCase().endsWith(EXCEL03_EXTENSION)) {// 如果文件是以.xls为后缀
+                Excel2003Reader excel03 = new Excel2003Reader();// 实例化excel处理对象
+                try {
+                    excel03.process(excelFile.getInputStream());
+                } catch (IOException e) {
+                    throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+                }
+                resultList = excel03.getSheetData(0);
+            } else if (excelFileName.toLowerCase().endsWith(EXCEL07_EXTENSION)) {// 如果文件是以.xlsx为后缀
+                Excel2007Reader excel07 = new Excel2007Reader();
+                try {
+                    excel07.process(excelFile.getInputStream(), false);
+                } catch (Exception e) {
+                    throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+                }
+                resultList = excel07.getSheetData(0);
+            }
+        }
+
+        return resultList;
+    }
+
+    /**
+     * 通过解析MultipartFile对象获取excel内容,并且将其拼装为Map<Integer, List<String[]>>对象返回
+     *
+     * @param excelFile
+     * @return
+     * @throws Exception
+     */
+    public static Map<Integer, List<String[]>> getExcelDataAll(MultipartFile excelFile)
+            throws CommonBaseException {
+        Map<Integer, List<String[]>> result = null;
+
+        if (!excelFile.isEmpty()) {// 上传的文件不能为空
+            String excelFileName = excelFile.getOriginalFilename();// 文件名(带后缀)
+            if (excelFileName.toLowerCase().endsWith(EXCEL03_EXTENSION)) {// 如果文件是以.xls为后缀
+                Excel2003Reader excel03 = new Excel2003Reader();// 实例化excel处理对象
+                try {
+                    excel03.process(excelFile.getInputStream());
+                } catch (IOException e) {
+                    throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+                }
+                result = excel03.getSheetData();
+            } else if (excelFileName.toLowerCase().endsWith(EXCEL07_EXTENSION)) {// 如果文件是以.xlsx为后缀
+                Excel2007Reader excel07 = new Excel2007Reader();
+                try {
+                    excel07.process(excelFile.getInputStream(), true);
+                } catch (Exception e) {
+                    throw new CommonBaseException(ResultCodeEnum.D101 ,"excel解析失败!");
+                }
+                result = excel07.getSheetData();
+            }
+        }
+
+        return result;
+    }
+}

+ 1 - 1
dinner-core/src/main/java/com/fdage/controller/app/AppOrderController.java

@@ -165,7 +165,7 @@ public class AppOrderController extends BaseController {
             if(!tmOrderService.updateById(dbOrder)){
             if(!tmOrderService.updateById(dbOrder)){
                 throw new CommonBaseException(ResultCodeEnum.D101 , "更新订单状态为退款成功失败");
                 throw new CommonBaseException(ResultCodeEnum.D101 , "更新订单状态为退款成功失败");
             }
             }
-            return Result.failure( "退款失败");
+            return Result.failure( "退款失败,请稍后重试");
         }
         }
     }
     }
     @PostMapping("/addNew")
     @PostMapping("/addNew")

+ 138 - 0
dinner-core/src/main/java/com/fdage/controller/web/WebCanteenController.java

@@ -0,0 +1,138 @@
+package com.fdage.controller.web;
+
+import com.alibaba.fastjson.JSON;
+import com.fdage.base.dto.OrderAppReqDto;
+import com.fdage.base.entity.TmCanteen;
+import com.fdage.base.service.impl.TmCanteenServiceImpl;
+import com.fdage.base.utils.excel.ExcelImport;
+import com.fdage.controller.BaseController;
+import fdage.back.sdk.base.entity.Result;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.*;
+
+/**
+ * 2 * @Author: Abner
+ * 3 * @Date: 2021/3/10 17:59
+ * 4
+ */
+@Api(tags = "WEB管理后台餐厅相关接口")
+@RestController
+@RequestMapping("/web/canteen")
+@Log4j2
+public class WebCanteenController extends BaseController {
+
+    @Autowired
+    private TmCanteenServiceImpl tmCanteenService;
+
+
+    @PostMapping("/excelBatchAdd")
+    @ApiOperation(value = "通过excel批量导入餐厅")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Object> excelBatchAdd(@RequestParam("file") MultipartFile file){
+        if(null == file){
+            return Result.failure("缺失excel文件");
+        }
+        List<String[]> resultList = ExcelImport.getExcelData(file);
+        checkExcel(resultList);
+        List<TmCanteen> totalList = tmCanteenService.addNewFromExcel(resultList);
+        List<Map<String , Object>> simpleResult = new ArrayList<>();
+        if(CollectionUtils.isEmpty(totalList)){
+            return Result.failure("插入失败");
+        }
+        for ( TmCanteen canteen : totalList) {
+            Map<String , Object> mp = new HashMap<>();
+            mp.put("canteenName" , canteen.getCanteenName());
+            mp.put("canteenId" , canteen.getId());
+            simpleResult.add(mp);
+        }
+        return Result.success(simpleResult);
+    }
+
+
+    public void checkExcel(List<String[]> resultList){
+        if(CollectionUtils.isEmpty(resultList)){
+            throw new CommonBaseException(ResultCodeEnum.D101 , "excel文件为空");
+        }
+        log.info("解析的excel数据为:{}" , JSON.toJSONString(resultList));
+        List<String> firstLine = Arrays.asList(resultList.get(0));
+        if(CollectionUtils.isEmpty(firstLine)){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第一行格式不对");
+        }
+        if(firstLine.size() != 16){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第一行列数不正确");
+        }
+        if(!StringUtils.equals("序列" , firstLine.get(0))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第1列名称不是:序列");
+        }
+        if(!StringUtils.equals("餐厅名称" , firstLine.get(1))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第2列名称不是:餐厅名称");
+        }
+        if(!StringUtils.equals("简介" , firstLine.get(2))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第3列名称不是:简介");
+        }
+        if(!StringUtils.equals("分数" , firstLine.get(3))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第4列名称不是:分数");
+        }
+        if(!StringUtils.equals("排序" , firstLine.get(4))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第5列名称不是:排序");
+        }
+        if(!StringUtils.equals("类型" , firstLine.get(5))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第6列名称不是:类型");
+        }
+
+        if(!StringUtils.equals("场景码" , firstLine.get(6))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第7列名称不是:场景码");
+        }
+
+        if(!StringUtils.equals("VR链接" , firstLine.get(7))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第8列名称不是:VR链接");
+        }
+
+
+        if(!StringUtils.equals("详细地址" , firstLine.get(8))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第9列名称不是:详细地址");
+        }
+
+        if(!StringUtils.equals("封面" , firstLine.get(9))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第10列名称不是:封面");
+        }
+
+        if(!StringUtils.equals("前台电话" , firstLine.get(10))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第11列名称不是:前台电话");
+        }
+
+        if(!StringUtils.equals("前台名称" , firstLine.get(11))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第12列名称不是:前台名称");
+        }
+
+        if(!StringUtils.equals("前台头像" , firstLine.get(12))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第13列名称不是:前台头像");
+        }
+
+        if(!StringUtils.equals("经度" , firstLine.get(13))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第14列名称不是:经度");
+        }
+
+        if(!StringUtils.equals("纬度" , firstLine.get(14))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第15列名称不是:纬度");
+        }
+
+        if(!StringUtils.equals("季度销量" , firstLine.get(15))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第16列名称不是:季度销量");
+        }
+    }
+
+
+
+}

+ 101 - 0
dinner-core/src/main/java/com/fdage/controller/web/WebDeskController.java

@@ -0,0 +1,101 @@
+package com.fdage.controller.web;
+
+import com.alibaba.fastjson.JSON;
+import com.fdage.base.service.impl.TmDeskServiceImpl;
+import com.fdage.base.utils.excel.ExcelImport;
+import com.fdage.controller.BaseController;
+import fdage.back.sdk.base.entity.Result;
+import fdage.back.sdk.base.enums.ResultCodeEnum;
+import fdage.back.sdk.base.exception.CommonBaseException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 2 * @Author: Abner
+ * 3 * @Date: 2021/3/11 10:24
+ * 4
+ */
+@Api(tags = "WEB管理后台餐厅相关接口")
+@RestController
+@RequestMapping("/web/desk")
+@Log4j2
+public class WebDeskController extends BaseController {
+
+
+    @Autowired
+    private TmDeskServiceImpl deskService;
+
+
+    @PostMapping("/excelBatchAdd")
+    @ApiOperation(value = "通过excel批量导入餐桌")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Object> excelBatchAdd(@RequestParam("file") MultipartFile file){
+
+
+        if(null == file){
+            return Result.failure("缺失excel文件");
+        }
+        List<String[]> resultList = ExcelImport.getExcelData(file);
+        checkExcel(resultList);
+        int add = deskService.addNewFromExcel(resultList);
+        if(add != 1){
+            return Result.failure("插入失败");
+        }
+        return Result.success();
+    }
+
+    public void checkExcel(List<String[]> resultList){
+        if(CollectionUtils.isEmpty(resultList)){
+            throw new CommonBaseException(ResultCodeEnum.D101 , "excel文件为空");
+        }
+        log.info("解析的excel数据为:{}" , JSON.toJSONString(resultList));
+        List<String> firstLine = Arrays.asList(resultList.get(0));
+        if(CollectionUtils.isEmpty(firstLine)){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第一行格式不对");
+        }
+        if(firstLine.size() != 8){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第一行列数不正确");
+        }
+        if(!StringUtils.equals("序列" , firstLine.get(0))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第1列名称不是:序列");
+        }
+        if(!StringUtils.equals("餐桌名称" , firstLine.get(1))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第2列名称不是:餐桌名称");
+        }
+        if(!StringUtils.equals("简介" , firstLine.get(2))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第3列名称不是:简介");
+        }
+        if(!StringUtils.equals("所属餐厅ID" , firstLine.get(3))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第4列名称不是:所属餐厅ID");
+        }
+        if(!StringUtils.equals("类型" , firstLine.get(4))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第5列名称不是:类型");
+        }
+        if(!StringUtils.equals("热点ID" , firstLine.get(5))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第6列名称不是:热点ID");
+        }
+
+        if(!StringUtils.equals("热点标题" , firstLine.get(6))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第7列名称不是:热点标题");
+        }
+
+        if(!StringUtils.equals("预览图链接" , firstLine.get(7))){
+            throw new CommonBaseException(ResultCodeEnum.D101 ,"excel第1行第8列名称不是:预览图链接");
+        }
+    }
+
+
+}