commit
This commit is contained in:
+24
-69
@@ -1,12 +1,8 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.controller.baseManage;
|
package io.v.nutz.zhgh.therapyRecuperation.controller.baseManage;
|
||||||
|
|
||||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
|
||||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
|
||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
|
||||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
import cn.hutool.core.date.DateField;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
@@ -22,6 +18,7 @@ import io.v.nutz.sys.models.SysHoliday;
|
|||||||
import io.v.nutz.sys.models.User;
|
import io.v.nutz.sys.models.User;
|
||||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
||||||
|
import io.v.nutz.zhgh.therapyRecuperation.mode.TheRapyBaseManagementExcelMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.*;
|
import io.v.nutz.zhgh.therapyRecuperation.model.*;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationEnrollService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationEnrollService;
|
||||||
@@ -48,9 +45,6 @@ import org.nutz.mvc.upload.UploadAdaptor;
|
|||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -454,7 +448,7 @@ public class TheRapyRecuperationBaseManagerController {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目的地导入模版
|
* 目的地导入模板
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response
|
||||||
*/
|
*/
|
||||||
@@ -463,45 +457,10 @@ public class TheRapyRecuperationBaseManagerController {
|
|||||||
@RequiresPermissions("theRapyRecuperation.TheBaseManagement")
|
@RequiresPermissions("theRapyRecuperation.TheBaseManagement")
|
||||||
public void exportTemplate(HttpServletResponse response) {
|
public void exportTemplate(HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
//查旅行社,转数组
|
ViTool.excelResponse(response, "目的地导入模板.xlsx");
|
||||||
List<TheRapyRecuperationTravelAgency> travelAgencys = dao.query(TheRapyRecuperationTravelAgency.class, Cnd.NEW().desc("serialNumber"));
|
|
||||||
List<String> excelTravelAgencyList = travelAgencys.stream().map(v -> v.getTravelAgencyName() + "_" + v.getId()).collect(Collectors.toList());
|
|
||||||
String[] excelTravelAgencyArrs = excelTravelAgencyList.toArray(new String[excelTravelAgencyList.size()]);
|
|
||||||
|
|
||||||
//查标段,转数组
|
|
||||||
List<TheRapyRecuperationLot> lots = dao.query(TheRapyRecuperationLot.class, Cnd.NEW().asc("id"));
|
|
||||||
List<String> excelLotList = lots.stream().map(v -> v.getLotName() + "_" + v.getId()).collect(Collectors.toList());
|
|
||||||
String[] excelLotArrs = excelLotList.toArray(new String[excelLotList.size()]);
|
|
||||||
|
|
||||||
ViTool.excelResponse(response, "目的地导入模版.xls");
|
|
||||||
Class<TheRapyRecuperationBaseManagement> excelModeClass = TheRapyRecuperationBaseManagement.class;
|
|
||||||
Field[] excelModeClassDeclaredFields = excelModeClass.getDeclaredFields();
|
|
||||||
//字段过滤
|
|
||||||
List<Field> needAddReplaceFields = Arrays.stream(excelModeClassDeclaredFields).filter(v -> List.of("travelAgencyId", "lotId", "regionalNature", "isDisabled", "createMode").contains(v.getName())).collect(Collectors.toList());
|
|
||||||
for (Field field : needAddReplaceFields) {
|
|
||||||
Excel excelAnnotation = field.getAnnotation(Excel.class);
|
|
||||||
if (Lang.isNotEmpty(excelAnnotation)) {
|
|
||||||
InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelAnnotation);
|
|
||||||
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
|
|
||||||
memberValues.setAccessible(true);
|
|
||||||
Map e = (Map) memberValues.get(invocationHandler);
|
|
||||||
e.put("addressList", true);
|
|
||||||
if (field.getName().equals("travelAgencyId")) {
|
|
||||||
e.put("replace", excelTravelAgencyArrs);
|
|
||||||
} else if (field.getName().equals("lotId")) {
|
|
||||||
e.put("replace", excelLotArrs);
|
|
||||||
} else if (field.getName().equals("regionalNature")) {
|
|
||||||
e.put("replace", new String[]{"省内_省内", "省外_省外"});
|
|
||||||
} else if (field.getName().equals("createMode")) {
|
|
||||||
e.put("replace", new String[]{"校工会_1", "分工会_2"});
|
|
||||||
} else if (field.getName().equals("isDisabled")) {
|
|
||||||
e.put("replace", new String[]{"是_1", "否_0"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExportParams exportParams = new ExportParams();
|
ExportParams exportParams = new ExportParams();
|
||||||
exportParams.setType(ExcelType.XSSF);
|
exportParams.setType(ExcelType.XSSF);
|
||||||
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, TheRapyRecuperationBaseManagement.class, new ArrayList<>());
|
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, TheRapyBaseManagementExcelMode.class, buildBaseTemplateExamples());
|
||||||
ServletOutputStream outputStream = response.getOutputStream();
|
ServletOutputStream outputStream = response.getOutputStream();
|
||||||
sheets.write(outputStream);
|
sheets.write(outputStream);
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
@@ -510,6 +469,23 @@ public class TheRapyRecuperationBaseManagerController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TheRapyBaseManagementExcelMode> buildBaseTemplateExamples() {
|
||||||
|
TheRapyBaseManagementExcelMode example = new TheRapyBaseManagementExcelMode();
|
||||||
|
example.setYear(DateUtil.thisYear());
|
||||||
|
example.setBaseName(TheRapyBaseManagementExcelMode.SAMPLE_BASE_NAME);
|
||||||
|
example.setTravelAgencySerialNumber("001");
|
||||||
|
example.setTravelAgencyPlace("杭州");
|
||||||
|
example.setRegionalNature("省内");
|
||||||
|
example.setAllowDay("3,2,2.5");
|
||||||
|
example.setMaxSignCount(30);
|
||||||
|
example.setBaseContactPerson("联系人");
|
||||||
|
example.setBaseContactNumber("13800000000");
|
||||||
|
example.setContent("目的地详细信息");
|
||||||
|
List<TheRapyBaseManagementExcelMode> examples = new ArrayList<>();
|
||||||
|
examples.add(example);
|
||||||
|
return examples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目的地导入
|
* 目的地导入
|
||||||
@@ -530,30 +506,9 @@ public class TheRapyRecuperationBaseManagerController {
|
|||||||
if (!List.of("xls", "xlsx").contains(extName.toLowerCase())) {
|
if (!List.of("xls", "xlsx").contains(extName.toLowerCase())) {
|
||||||
return Result.error("请上传xls,xlsx文件");
|
return Result.error("请上传xls,xlsx文件");
|
||||||
}
|
}
|
||||||
List<TheRapyRecuperationBaseManagement> excelList;
|
return theRapyRecuperationBaseManagerService.importBaseManager(file.getFile(),
|
||||||
try {
|
(String) ShiroUtil.getPrincipalProperty("id"),
|
||||||
ImportParams importParams = new ImportParams();
|
(String) ShiroUtil.getPrincipalProperty("unionid"));
|
||||||
excelList = ExcelImportUtil.importExcel(file.getFile(), TheRapyRecuperationBaseManagement.class, importParams);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return Result.error("读取不到数据,请检查excel文件格式");
|
|
||||||
}
|
|
||||||
if (Lang.isEmpty(excelList)) {
|
|
||||||
return Result.error("读取不到数据,请检查excel文件格式");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getBaseName())) || excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getTravelAgencyId()))) {
|
|
||||||
return Result.error("目的地名称和旅行社名称不能为空");
|
|
||||||
}
|
|
||||||
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getLotId())) || excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getRegionalNature()))) {
|
|
||||||
return Result.error("时间标段和活动范围不能为空");
|
|
||||||
}
|
|
||||||
excelList.forEach(v -> v.setOpBy((String) ShiroUtil.getPrincipalProperty("id")));
|
|
||||||
dao.insertOrUpdate(excelList);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
|
|||||||
+28
-95
@@ -1,28 +1,25 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.controller.basicManage;
|
package io.v.nutz.zhgh.therapyRecuperation.controller.basicManage;
|
||||||
|
|
||||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
|
||||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
|
||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.wizzer.framework.base.Result;
|
import cn.wizzer.framework.base.Result;
|
||||||
import io.v.nutz.base.annontation.ViReturn;
|
import io.v.nutz.base.annontation.ViReturn;
|
||||||
import io.v.nutz.base.model.Audit;
|
import io.v.nutz.base.model.Audit;
|
||||||
import io.v.nutz.base.utils.Vi;
|
|
||||||
import io.v.nutz.base.query.PageForm;
|
import io.v.nutz.base.query.PageForm;
|
||||||
import io.v.nutz.sys.models.User;
|
import io.v.nutz.base.utils.Vi;
|
||||||
|
import io.v.nutz.base.utils.ViTool;
|
||||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationLineCreateMode;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationLineCreateMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.mode.TheRapyTravelLineExcelMode;
|
import io.v.nutz.zhgh.therapyRecuperation.mode.TheRapyLineImportExcelMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnroll;
|
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationLineService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationLineService;
|
||||||
import io.v.nutz.base.utils.ViTool;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
@@ -45,12 +42,7 @@ import org.nutz.mvc.upload.UploadAdaptor;
|
|||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @FileName io.v.nutz.zhgh.therapyRecuperation.controller.basicManage.TheRapyRecuperationLineController
|
* @FileName io.v.nutz.zhgh.therapyRecuperation.controller.basicManage.TheRapyRecuperationLineController
|
||||||
@@ -318,56 +310,12 @@ public class TheRapyRecuperationLineController {
|
|||||||
if (!List.of("xls", "xlsx").contains(extName.toLowerCase())) {
|
if (!List.of("xls", "xlsx").contains(extName.toLowerCase())) {
|
||||||
return Result.error("请上传xls,xlsx文件");
|
return Result.error("请上传xls,xlsx文件");
|
||||||
}
|
}
|
||||||
List<TheRapyTravelLineExcelMode> excelList;
|
return lineService.importTravelLine(file.getFile());
|
||||||
try {
|
|
||||||
ImportParams importParams = new ImportParams();
|
|
||||||
excelList = ExcelImportUtil.importExcel(file.getFile(), TheRapyTravelLineExcelMode.class, importParams);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
return Result.error("读取不到数据,请检查excel文件格式");
|
|
||||||
}
|
|
||||||
if (Lang.isEmpty(excelList)) {
|
|
||||||
return Result.error("读取不到数据,请检查excel文件格式");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getTravelAgencyId()))) {
|
|
||||||
return Result.error("旅行社名称不能为空");
|
|
||||||
}
|
|
||||||
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getLotId())) || excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getRegionalNature()))) {
|
|
||||||
return Result.error("时间标段和活动范围不能为空");
|
|
||||||
}
|
|
||||||
List<TheRapyRecuperationLine> list = new ArrayList<>();
|
|
||||||
for (TheRapyTravelLineExcelMode mode : excelList) {
|
|
||||||
TheRapyRecuperationLine line = new TheRapyRecuperationLine();
|
|
||||||
line.setYear(mode.getYear());
|
|
||||||
line.setSerialNumber(mode.getSerialNumber());
|
|
||||||
line.setLineName(mode.getLineName());
|
|
||||||
line.setTravelAgencyId(mode.getTravelAgencyId());
|
|
||||||
line.setRegionalNature(mode.getRegionalNature());
|
|
||||||
line.setContent(mode.getContent());
|
|
||||||
line.setMinimumGroupSize(mode.getMinimumGroupSize());
|
|
||||||
if (mode.getIsDisabled().equals("是")) {
|
|
||||||
line.setDisabled(false);
|
|
||||||
} else if (mode.getIsDisabled().equals("否")) {
|
|
||||||
line.setDisabled(true);
|
|
||||||
}
|
|
||||||
line.setEstimatedCost(mode.getEstimatedCost());
|
|
||||||
line.setLotId(mode.getLotId());
|
|
||||||
// line.setLineContact(mode.getLineContact());
|
|
||||||
// line.setLineContactPhone(mode.getLineContactPhone());
|
|
||||||
list.add(line);
|
|
||||||
}
|
|
||||||
dao.insert(list);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
return Result.error("导入失败");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 线路导入模版
|
* 线路导入模板
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response
|
||||||
*/
|
*/
|
||||||
@@ -376,42 +324,10 @@ public class TheRapyRecuperationLineController {
|
|||||||
@RequiresPermissions("theRapyRecuperation.line")
|
@RequiresPermissions("theRapyRecuperation.line")
|
||||||
public void exportTemplate(HttpServletResponse response) {
|
public void exportTemplate(HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
//查旅行社,转数组
|
ViTool.excelResponse(response, "线路导入模板.xlsx");
|
||||||
List<TheRapyRecuperationTravelAgency> travelAgencys = dao.query(TheRapyRecuperationTravelAgency.class, Cnd.NEW().desc("serialNumber"));
|
ExportParams exportParams = new ExportParams();
|
||||||
List<String> excelTravelAgencys = travelAgencys.stream().map(v -> v.getTravelAgencyName() + "_" + v.getId()).collect(Collectors.toList());
|
exportParams.setType(ExcelType.XSSF);
|
||||||
String[] excelTravelAgencyArrs = excelTravelAgencys.toArray(new String[excelTravelAgencys.size()]);
|
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, TheRapyLineImportExcelMode.class, buildLineTemplateExamples());
|
||||||
|
|
||||||
//查标段,转数组
|
|
||||||
List<TheRapyRecuperationLot> lots = dao.query(TheRapyRecuperationLot.class, Cnd.NEW().asc("id"));
|
|
||||||
List<String> excelLots = lots.stream().map(v -> v.getLotName() + "_" + v.getId()).collect(Collectors.toList());
|
|
||||||
String[] excelLotArrs = excelLots.toArray(new String[excelLots.size()]);
|
|
||||||
|
|
||||||
ViTool.excelResponse(response, "线路导入模版.xls");
|
|
||||||
Class<TheRapyTravelLineExcelMode> excelModeClass = TheRapyTravelLineExcelMode.class;
|
|
||||||
Field[] excelModeClassDeclaredFields = excelModeClass.getDeclaredFields();
|
|
||||||
|
|
||||||
//字段过滤
|
|
||||||
List<Field> needAddReplaceFields = Arrays.stream(excelModeClassDeclaredFields).filter(v -> List.of("travelAgencyId", "lotId", "regionalNature").contains(v.getName())).collect(Collectors.toList());
|
|
||||||
|
|
||||||
//循环TheRapyTravelLineExcelMode需要下拉数据的字段
|
|
||||||
for (Field field : needAddReplaceFields) {
|
|
||||||
Excel excelAnnotation = field.getAnnotation(Excel.class);
|
|
||||||
if (Lang.isNotEmpty(excelAnnotation)) {
|
|
||||||
InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelAnnotation);
|
|
||||||
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
|
|
||||||
memberValues.setAccessible(true);
|
|
||||||
Map e = (Map) memberValues.get(invocationHandler);
|
|
||||||
e.put("addressList", true);
|
|
||||||
if (field.getName().equals("travelAgencyId")) {
|
|
||||||
e.put("replace", excelTravelAgencyArrs);
|
|
||||||
} else if (field.getName().equals("lotId")) {
|
|
||||||
e.put("replace", excelLotArrs);
|
|
||||||
} else if (field.getName().equals("regionalNature")) {
|
|
||||||
e.put("replace", new String[]{"省内_省内", "省外_省外"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Workbook sheets = ExcelExportUtil.exportExcel(new ExportParams(), TheRapyTravelLineExcelMode.class, new ArrayList<>());
|
|
||||||
ServletOutputStream outputStream = response.getOutputStream();
|
ServletOutputStream outputStream = response.getOutputStream();
|
||||||
sheets.write(outputStream);
|
sheets.write(outputStream);
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
@@ -419,4 +335,21 @@ public class TheRapyRecuperationLineController {
|
|||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TheRapyLineImportExcelMode> buildLineTemplateExamples() {
|
||||||
|
TheRapyLineImportExcelMode example = new TheRapyLineImportExcelMode();
|
||||||
|
example.setYear(DateUtil.thisYear());
|
||||||
|
example.setLineName(TheRapyLineImportExcelMode.SAMPLE_LINE_NAME);
|
||||||
|
example.setTravelAgencySerialNumber("001");
|
||||||
|
example.setTravelAgencyPlace("杭州");
|
||||||
|
example.setRegionalNature("省内线路");
|
||||||
|
example.setGroupType("常规团");
|
||||||
|
example.setLotName("两天一晚");
|
||||||
|
example.setEstimatedCost("1000");
|
||||||
|
example.setMaxGroupSize(30);
|
||||||
|
example.setContent("线路内容");
|
||||||
|
List<TheRapyLineImportExcelMode> examples = new ArrayList<>();
|
||||||
|
examples.add(example);
|
||||||
|
return examples;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package io.v.nutz.zhgh.therapyRecuperation.mode;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目的地导入模板字段,独立于数据库实体,避免模板导出时带出无关字段。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TheRapyBaseManagementExcelMode {
|
||||||
|
|
||||||
|
public static final String SAMPLE_BASE_NAME = "示例目的地(请删除)";
|
||||||
|
|
||||||
|
@Excel(name = "年度")
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
@Excel(name = "目的地名称")
|
||||||
|
private String baseName;
|
||||||
|
|
||||||
|
@Excel(name = "旅行社编号")
|
||||||
|
private String travelAgencySerialNumber;
|
||||||
|
|
||||||
|
@Excel(name = "旅行社地点")
|
||||||
|
private String travelAgencyPlace;
|
||||||
|
|
||||||
|
@Excel(name = "活动范围(省内/省外)")
|
||||||
|
private String regionalNature;
|
||||||
|
|
||||||
|
@Excel(name = "天数(填3,2,2.5)")
|
||||||
|
private String allowDay;
|
||||||
|
|
||||||
|
@Excel(name = "每日最高人数")
|
||||||
|
private Integer maxSignCount;
|
||||||
|
|
||||||
|
@Excel(name = "目的地联系人")
|
||||||
|
private String baseContactPerson;
|
||||||
|
|
||||||
|
@Excel(name = "联系电话")
|
||||||
|
private String baseContactNumber;
|
||||||
|
|
||||||
|
@Excel(name = "详细信息", width = 30d)
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package io.v.nutz.zhgh.therapyRecuperation.mode;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线路导入模板字段,独立于数据库实体,避免模板导出时带出旅行社、标段等内部ID。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TheRapyLineImportExcelMode {
|
||||||
|
|
||||||
|
public static final String SAMPLE_LINE_NAME = "示例线路(请删除)";
|
||||||
|
|
||||||
|
@Excel(name = "年度")
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
@Excel(name = "线路名称")
|
||||||
|
private String lineName;
|
||||||
|
|
||||||
|
@Excel(name = "旅行社编号")
|
||||||
|
private String travelAgencySerialNumber;
|
||||||
|
|
||||||
|
@Excel(name = "旅行社地点")
|
||||||
|
private String travelAgencyPlace;
|
||||||
|
|
||||||
|
@Excel(name = "线路类型(省内线路/省外线路)")
|
||||||
|
private String regionalNature;
|
||||||
|
|
||||||
|
@Excel(name = "成团类型(常规团/精品团)")
|
||||||
|
private String groupType;
|
||||||
|
|
||||||
|
@Excel(name = "时间标段")
|
||||||
|
private String lotName;
|
||||||
|
|
||||||
|
@Excel(name = "预计费用")
|
||||||
|
private String estimatedCost;
|
||||||
|
|
||||||
|
@Excel(name = "最多报名人数")
|
||||||
|
private Integer maxGroupSize;
|
||||||
|
|
||||||
|
@Excel(name = "线路内容", width = 30d)
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
+10
@@ -1,5 +1,6 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.service;
|
package io.v.nutz.zhgh.therapyRecuperation.service;
|
||||||
|
|
||||||
|
import cn.wizzer.framework.base.Result;
|
||||||
import cn.wizzer.framework.page.Pagination;
|
import cn.wizzer.framework.page.Pagination;
|
||||||
import io.v.nutz.base.query.PageForm;
|
import io.v.nutz.base.query.PageForm;
|
||||||
import io.v.nutz.base.service.ViService;
|
import io.v.nutz.base.service.ViService;
|
||||||
@@ -7,6 +8,7 @@ import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine;
|
|||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,4 +104,12 @@ public interface TheRapyRecuperationLineService extends ViService<TheRapyRecuper
|
|||||||
* @return 复制结果,包含来源数量、复制数量和跳过数量
|
* @return 复制结果,包含来源数量、复制数量和跳过数量
|
||||||
*/
|
*/
|
||||||
NutMap copySchoolUnionLines(Integer sourceYear, Integer targetYear);
|
NutMap copySchoolUnionLines(Integer sourceYear, Integer targetYear);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入线路模板数据,负责把模板展示值转换成线路保存字段。
|
||||||
|
*
|
||||||
|
* @param file 导入的Excel文件
|
||||||
|
* @return 导入结果
|
||||||
|
*/
|
||||||
|
Result importTravelLine(File file);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -1,7 +1,9 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.service.baseManage;
|
package io.v.nutz.zhgh.therapyRecuperation.service.baseManage;
|
||||||
|
|
||||||
|
import cn.wizzer.framework.base.Result;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,4 +31,14 @@ public interface TheRapyRecuperationBaseManagerService {
|
|||||||
* @return 复制结果,包含来源数量、复制数量和跳过数量
|
* @return 复制结果,包含来源数量、复制数量和跳过数量
|
||||||
*/
|
*/
|
||||||
NutMap copyLastYearBase(Integer sourceYear, Integer targetYear);
|
NutMap copyLastYearBase(Integer sourceYear, Integer targetYear);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入目的地模板数据,负责把模板里的中文展示值转换成数据库字段。
|
||||||
|
*
|
||||||
|
* @param file 导入的Excel文件
|
||||||
|
* @param opBy 当前操作人ID
|
||||||
|
* @param createUnionId 当前操作人所属工会ID
|
||||||
|
* @return 导入结果
|
||||||
|
*/
|
||||||
|
Result importBaseManager(File file, String opBy, String createUnionId);
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-17
@@ -806,7 +806,7 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl<TheRapyR
|
|||||||
int count = dao().count(TheRapyRecuperationEnroll.class,
|
int count = dao().count(TheRapyRecuperationEnroll.class,
|
||||||
Cnd.where("takePartInBaseManagementId", "=", currentEnroll.getTakePartInBaseManagementId())
|
Cnd.where("takePartInBaseManagementId", "=", currentEnroll.getTakePartInBaseManagementId())
|
||||||
.and("loginName", "=", loginName)
|
.and("loginName", "=", loginName)
|
||||||
.and("isNormal", "=", 2750)
|
.and("isNormal", "=", true)
|
||||||
.and("YEAR(signingUptime)", "=", DateUtil.thisYear())
|
.and("YEAR(signingUptime)", "=", DateUtil.thisYear())
|
||||||
.and("specificTime", "=", currentEnroll.getSpecificTime())
|
.and("specificTime", "=", currentEnroll.getSpecificTime())
|
||||||
//.and("playDay", "=", currentEnroll.getPlayDay())
|
//.and("playDay", "=", currentEnroll.getPlayDay())
|
||||||
@@ -1417,10 +1417,10 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl<TheRapyR
|
|||||||
Map<String, User> userMap = dao().query(User.class, Cnd.where("loginname", "in", loginNames))
|
Map<String, User> userMap = dao().query(User.class, Cnd.where("loginname", "in", loginNames))
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(User::getLoginname, v -> v, (oldValue, newValue) -> oldValue));
|
.collect(Collectors.toMap(User::getLoginname, v -> v, (oldValue, newValue) -> oldValue));
|
||||||
Map<String, TheRapyRecuperationEnroll> existEnrollMap = dao().query(TheRapyRecuperationEnroll.class, Cnd.where("loginName", "in", loginNames)
|
Map<String, List<TheRapyRecuperationEnroll>> existEnrollMap = dao().query(TheRapyRecuperationEnroll.class, Cnd.where("loginName", "in", loginNames)
|
||||||
.and("YEAR(signingUptime)", "in", importYears))
|
.and("YEAR(signingUptime)", "in", importYears))
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(v -> v.getLoginName() + "_" + DateUtil.year(v.getSigningUptime()), v -> v, (oldValue, newValue) -> oldValue));
|
.collect(Collectors.groupingBy(v -> v.getLoginName() + "_" + DateUtil.year(v.getSigningUptime())));
|
||||||
TheRapyRecuperationConfig lineConfig = configService.requireByYear(lineInfo.getYear());
|
TheRapyRecuperationConfig lineConfig = configService.requireByYear(lineInfo.getYear());
|
||||||
// 补录标段必须限定在所选线路年度配置内,避免不同年度同名标段匹配错。
|
// 补录标段必须限定在所选线路年度配置内,避免不同年度同名标段匹配错。
|
||||||
Map<String, TheRapyRecuperationLot> lotMap = dao().query(TheRapyRecuperationLot.class, Cnd.where("configId", "=", lineConfig.getId()))
|
Map<String, TheRapyRecuperationLot> lotMap = dao().query(TheRapyRecuperationLot.class, Cnd.where("configId", "=", lineConfig.getId()))
|
||||||
@@ -1428,30 +1428,42 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl<TheRapyR
|
|||||||
.collect(Collectors.toMap(TheRapyRecuperationLot::getLotName, v -> v, (oldValue, newValue) -> oldValue));
|
.collect(Collectors.toMap(TheRapyRecuperationLot::getLotName, v -> v, (oldValue, newValue) -> oldValue));
|
||||||
|
|
||||||
List<TheRapyRecuperationEnroll> supplementList = new ArrayList<>();
|
List<TheRapyRecuperationEnroll> supplementList = new ArrayList<>();
|
||||||
List<String> existInfos = new ArrayList<>();
|
List<NutMap> successList = new ArrayList<>();
|
||||||
List<String> errorInfos = new ArrayList<>();
|
List<NutMap> errorList = new ArrayList<>();
|
||||||
Set<String> supplementKeys = new HashSet<>();
|
Set<String> supplementKeys = new HashSet<>();
|
||||||
for (TheRapyRecuperationEnrollExcelMode excel : excelList) {
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
TheRapyRecuperationEnrollExcelMode excel = excelList.get(i);
|
||||||
String loginName = StrUtil.trim(excel.getLoginName());
|
String loginName = StrUtil.trim(excel.getLoginName());
|
||||||
int takePartInYear = DateUtil.year(excel.getTakePartInTime());
|
int takePartInYear = DateUtil.year(excel.getTakePartInTime());
|
||||||
String enrollKey = loginName + "_" + takePartInYear;
|
String enrollKey = loginName + "_" + takePartInYear;
|
||||||
if (existEnrollMap.containsKey(enrollKey) || supplementKeys.contains(enrollKey)) {
|
NutMap row = createSupplementImportRow(i + 2, excel, takePartInYear);
|
||||||
existInfos.add(loginName);
|
List<TheRapyRecuperationEnroll> existEnrollList = existEnrollMap.getOrDefault(enrollKey, Collections.emptyList());
|
||||||
|
if (Lang.isNotEmpty(existEnrollList)) {
|
||||||
|
row.setv("errors", buildSupplementExistReason(existEnrollList, lineUnionSelect));
|
||||||
|
errorList.add(row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (supplementKeys.contains(enrollKey)) {
|
||||||
|
row.setv("errors", "Excel中同一工号同一参加年度重复,请保留一条后重新导入");
|
||||||
|
errorList.add(row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = userMap.get(loginName);
|
User user = userMap.get(loginName);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
errorInfos.add("工号" + loginName + "的系统用户不存在");
|
row.setv("errors", "系统用户不存在");
|
||||||
|
errorList.add(row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TheRapyRecuperationLot lot = lotMap.get(excel.getLotId());
|
TheRapyRecuperationLot lot = lotMap.get(excel.getLotId());
|
||||||
if (lot == null) {
|
if (lot == null) {
|
||||||
errorInfos.add("工号" + loginName + "的标段时间不存在");
|
row.setv("errors", "标段时间不存在,当前年度没有【" + excel.getLotId() + "】");
|
||||||
|
errorList.add(row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (StrUtil.isNotBlank(lineInfo.getLotId()) && !lineInfo.getLotId().equals(lot.getId())) {
|
if (StrUtil.isNotBlank(lineInfo.getLotId()) && !lineInfo.getLotId().equals(lot.getId())) {
|
||||||
errorInfos.add("工号" + loginName + "的标段时间与所选线路不一致");
|
row.setv("errors", "标段时间与所选线路不一致,所选线路标段为【" + getLineLotName(lineInfo) + "】");
|
||||||
|
errorList.add(row);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1478,19 +1490,86 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl<TheRapyR
|
|||||||
enroll.setNormal(true);
|
enroll.setNormal(true);
|
||||||
supplementKeys.add(enrollKey);
|
supplementKeys.add(enrollKey);
|
||||||
supplementList.add(enroll);
|
supplementList.add(enroll);
|
||||||
|
row.setv("errors", "");
|
||||||
|
successList.add(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Lang.isNotEmpty(supplementList)) {
|
if (Lang.isNotEmpty(supplementList)) {
|
||||||
dao().insert(supplementList);
|
dao().insert(supplementList);
|
||||||
}
|
}
|
||||||
if (Lang.isEmpty(supplementList) && Lang.isNotEmpty(errorInfos) && Lang.isEmpty(existInfos)) {
|
NutMap importResult = NutMap.NEW()
|
||||||
return Result.error("补录失败:" + String.join(";", errorInfos));
|
.setv("totalCount", excelList.size())
|
||||||
|
.setv("successCount", successList.size())
|
||||||
|
.setv("errorCount", errorList.size())
|
||||||
|
.setv("successList", successList)
|
||||||
|
.setv("errorList", errorList);
|
||||||
|
String msg = "补录成功" + successList.size() + "人,失败" + errorList.size() + "人";
|
||||||
|
return Result.success().addMsg(msg).addData(importResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成补录导入结果行,前端错误表格和成功统计共用这一份数据。
|
||||||
|
*/
|
||||||
|
private NutMap createSupplementImportRow(int no, TheRapyRecuperationEnrollExcelMode excel, int takePartInYear) {
|
||||||
|
return NutMap.NEW()
|
||||||
|
.setv("no", no)
|
||||||
|
.setv("loginName", StrUtil.trim(excel.getLoginName()))
|
||||||
|
.setv("userName", excel.getUserName())
|
||||||
|
.setv("takePartInYear", takePartInYear)
|
||||||
|
.setv("takePartInTime", DateUtil.formatDate(excel.getTakePartInTime()))
|
||||||
|
.setv("lotName", excel.getLotId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将已存在记录转换成可读原因,说明人员为什么没有补录到本次选择的线路。
|
||||||
|
*/
|
||||||
|
private String buildSupplementExistReason(List<TheRapyRecuperationEnroll> existEnrollList, TheRapyRecuperationLineUnionSelect targetLineUnionSelect) {
|
||||||
|
List<String> reasons = new ArrayList<>();
|
||||||
|
for (TheRapyRecuperationEnroll existEnroll : existEnrollList) {
|
||||||
|
reasons.add(buildSingleSupplementExistReason(existEnroll, targetLineUnionSelect));
|
||||||
}
|
}
|
||||||
String msg = "补录成功" + supplementList.size() + "人,已存在" + existInfos.size() + "人";
|
return reasons.stream().distinct().collect(Collectors.joining(";"));
|
||||||
if (Lang.isNotEmpty(errorInfos)) {
|
}
|
||||||
msg += ",失败" + errorInfos.size() + "人:" + String.join(";", errorInfos);
|
|
||||||
|
private String buildSingleSupplementExistReason(TheRapyRecuperationEnroll existEnroll, TheRapyRecuperationLineUnionSelect targetLineUnionSelect) {
|
||||||
|
if (StrUtil.isNotBlank(existEnroll.getTakePartInLineId())) {
|
||||||
|
TheRapyRecuperationLineUnionSelect existLineUnionSelect = dao().fetch(TheRapyRecuperationLineUnionSelect.class, existEnroll.getTakePartInLineId());
|
||||||
|
TheRapyRecuperationLine existLine = existLineUnionSelect == null ? null : dao().fetch(TheRapyRecuperationLine.class, existLineUnionSelect.getLineId());
|
||||||
|
String lineName = existLine == null ? "未知线路" : existLine.getLineName();
|
||||||
|
String regionalNature = existLine == null ? "未知区域" : existLine.getRegionalNature();
|
||||||
|
String unionName = existLineUnionSelect == null ? "未知分工会" : getUnionName(existLineUnionSelect.getUnionId());
|
||||||
|
if (targetLineUnionSelect != null && existEnroll.getTakePartInLineId().equals(targetLineUnionSelect.getId())) {
|
||||||
|
return "该年度已存在本线路报名记录,线路【" + lineName + "】";
|
||||||
|
}
|
||||||
|
return "该年度已存在其他线路报名记录,线路【" + lineName + "】,区域【" + regionalNature + "】,线路分工会【" + unionName + "】";
|
||||||
}
|
}
|
||||||
return Result.success(msg);
|
if (StrUtil.isNotBlank(existEnroll.getTakePartInBaseManagementId())) {
|
||||||
|
TheRapyRecuperationBaseManagement baseManagement = dao().fetch(TheRapyRecuperationBaseManagement.class, existEnroll.getTakePartInBaseManagementId());
|
||||||
|
String baseName = baseManagement == null ? "未知目的地" : baseManagement.getBaseName();
|
||||||
|
return "该年度已存在酒店/目的地报名记录,目的地【" + baseName + "】";
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(existEnroll.getTakePartInTravelAgencyId())) {
|
||||||
|
TheRapyRecuperationTravelAgency travelAgency = dao().fetch(TheRapyRecuperationTravelAgency.class, existEnroll.getTakePartInTravelAgencyId());
|
||||||
|
String travelAgencyName = travelAgency == null ? "未知旅行社" : travelAgency.getTravelAgencyName();
|
||||||
|
return "该年度已存在旅行社报名记录,旅行社【" + travelAgencyName + "】";
|
||||||
|
}
|
||||||
|
return "该年度已存在报名记录,但未绑定线路、旅行社或目的地,请联系管理员核对记录【" + existEnroll.getId() + "】";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLineLotName(TheRapyRecuperationLine lineInfo) {
|
||||||
|
if (lineInfo == null || StrUtil.isBlank(lineInfo.getLotId())) {
|
||||||
|
return "未设置";
|
||||||
|
}
|
||||||
|
TheRapyRecuperationLot lot = dao().fetch(TheRapyRecuperationLot.class, lineInfo.getLotId());
|
||||||
|
return lot == null ? "未设置" : lot.getLotName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUnionName(String unionId) {
|
||||||
|
if (StrUtil.isBlank(unionId)) {
|
||||||
|
return "未设置";
|
||||||
|
}
|
||||||
|
Sys_union union = dao().fetch(Sys_union.class, unionId);
|
||||||
|
return union == null ? "未知分工会" : union.getUnionname();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+274
-1
@@ -1,20 +1,25 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.service.impl;
|
package io.v.nutz.zhgh.therapyRecuperation.service.impl;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.wizzer.framework.base.Result;
|
||||||
import cn.wizzer.framework.page.Pagination;
|
import cn.wizzer.framework.page.Pagination;
|
||||||
import io.v.nutz.base.utils.Vi;
|
|
||||||
import io.v.nutz.base.query.PageForm;
|
import io.v.nutz.base.query.PageForm;
|
||||||
import io.v.nutz.base.service.impl.ViServiceImpl;
|
import io.v.nutz.base.service.impl.ViServiceImpl;
|
||||||
|
import io.v.nutz.base.utils.Vi;
|
||||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationLineCreateMode;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationLineCreateMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationSignUpMode;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationSignUpMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
||||||
|
import io.v.nutz.zhgh.therapyRecuperation.mode.TheRapyLineImportExcelMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnroll;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnroll;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnrollCompanion;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnrollCompanion;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLineUnionSelect;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLineUnionSelect;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
||||||
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationLineService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationLineService;
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
@@ -26,11 +31,15 @@ import org.nutz.dao.sql.Sql;
|
|||||||
import org.nutz.ioc.aop.Aop;
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
import org.nutz.plugins.wkcache.annotation.CacheRemove;
|
import org.nutz.plugins.wkcache.annotation.CacheRemove;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @FileName io.v.nutz.zhgh.therapyRecuperation.service.impl.TheRapyRecuperationLineServiceImpl
|
* @FileName io.v.nutz.zhgh.therapyRecuperation.service.impl.TheRapyRecuperationLineServiceImpl
|
||||||
@@ -287,6 +296,270 @@ public class TheRapyRecuperationLineServiceImpl extends ViServiceImpl<TheRapyRec
|
|||||||
.setv("skipCount", skipCount);
|
.setv("skipCount", skipCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入线路时只读取模板展示字段,旅行社、时间标段和创建字段按系统数据转换。
|
||||||
|
*
|
||||||
|
* @param file Excel文件
|
||||||
|
* @return 导入结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result importTravelLine(File file) {
|
||||||
|
List<TheRapyLineImportExcelMode> excelList;
|
||||||
|
try {
|
||||||
|
excelList = ExcelImportUtil.importExcel(file, TheRapyLineImportExcelMode.class, new ImportParams());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(excelList)) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
List<TheRapyRecuperationLine> lineList = new ArrayList<>();
|
||||||
|
List<NutMap> successList = new ArrayList<>();
|
||||||
|
List<NutMap> errorList = new ArrayList<>();
|
||||||
|
int nextSerialNumber = getNextSerialNumber();
|
||||||
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
TheRapyLineImportExcelMode row = excelList.get(i);
|
||||||
|
int rowNumber = i + 2;
|
||||||
|
if (isBlankImportRow(row) || TheRapyLineImportExcelMode.SAMPLE_LINE_NAME.equals(StrUtil.trim(row.getLineName()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NutMap resultRow = createLineImportResultRow(rowNumber, row);
|
||||||
|
List<String> errors = validateLineImportRow(row);
|
||||||
|
TheRapyRecuperationConfig config = null;
|
||||||
|
TheRapyRecuperationTravelAgency travelAgency = null;
|
||||||
|
TheRapyRecuperationLot lot = null;
|
||||||
|
Integer groupType = null;
|
||||||
|
if (row.getYear() != null) {
|
||||||
|
try {
|
||||||
|
config = configService.requireByYear(row.getYear());
|
||||||
|
} catch (Exception e) {
|
||||||
|
errors.add(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(row.getTravelAgencySerialNumber())) {
|
||||||
|
travelAgency = dao().fetch(TheRapyRecuperationTravelAgency.class, Cnd.where("serialNumber", "=", StrUtil.trim(row.getTravelAgencySerialNumber())));
|
||||||
|
validateTravelAgency(row, travelAgency, errors);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(row.getGroupType())) {
|
||||||
|
groupType = parseGroupType(row.getGroupType(), errors);
|
||||||
|
}
|
||||||
|
if (config != null && groupType != null) {
|
||||||
|
validateGroupCountConfig(config, groupType, errors);
|
||||||
|
}
|
||||||
|
if (config != null) {
|
||||||
|
validateLineTimeConfig(config, errors);
|
||||||
|
}
|
||||||
|
if (config != null && StrUtil.isNotBlank(row.getLotName())) {
|
||||||
|
lot = findImportLot(config, row.getLotName());
|
||||||
|
if (lot == null) {
|
||||||
|
errors.add("时间标段不存在,当前年度没有【" + StrUtil.trim(row.getLotName()) + "】");
|
||||||
|
} else if (StrUtil.isBlank(lot.getLotValue()) || !StrUtil.trim(lot.getLotValue()).matches("\\d+")) {
|
||||||
|
errors.add("时间标段天数配置不正确");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Lang.isNotEmpty(errors)) {
|
||||||
|
resultRow.setv("errors", String.join(";", errors));
|
||||||
|
errorList.add(resultRow);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TheRapyRecuperationLine line = buildLineByExcel(row, config, travelAgency, lot, groupType, nextSerialNumber++);
|
||||||
|
lineList.add(line);
|
||||||
|
resultRow.setv("errors", "");
|
||||||
|
successList.add(resultRow);
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(lineList) && Lang.isEmpty(errorList)) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
if (Lang.isNotEmpty(lineList)) {
|
||||||
|
insert(lineList);
|
||||||
|
}
|
||||||
|
NutMap importResult = NutMap.NEW()
|
||||||
|
.setv("totalCount", successList.size() + errorList.size())
|
||||||
|
.setv("successCount", successList.size())
|
||||||
|
.setv("errorCount", errorList.size())
|
||||||
|
.setv("successList", successList)
|
||||||
|
.setv("errorList", errorList);
|
||||||
|
String msg = "导入完成,成功" + successList.size() + "条,失败" + errorList.size() + "条";
|
||||||
|
return Result.success().addMsg(msg).addData(importResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBlankImportRow(TheRapyLineImportExcelMode row) {
|
||||||
|
return row == null
|
||||||
|
|| (row.getYear() == null
|
||||||
|
&& row.getMaxGroupSize() == null
|
||||||
|
&& StrUtil.isAllBlank(row.getLineName(), row.getTravelAgencySerialNumber(), row.getTravelAgencyPlace(),
|
||||||
|
row.getRegionalNature(), row.getGroupType(), row.getLotName(), row.getEstimatedCost(), row.getContent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成线路导入结果行,前端错误表格和错误导出共用这一份数据。
|
||||||
|
*/
|
||||||
|
private NutMap createLineImportResultRow(int rowNumber, TheRapyLineImportExcelMode row) {
|
||||||
|
return NutMap.NEW()
|
||||||
|
.setv("no", rowNumber)
|
||||||
|
.setv("year", row.getYear())
|
||||||
|
.setv("lineName", StrUtil.trim(row.getLineName()))
|
||||||
|
.setv("travelAgencySerialNumber", StrUtil.trim(row.getTravelAgencySerialNumber()))
|
||||||
|
.setv("travelAgencyPlace", StrUtil.trim(row.getTravelAgencyPlace()))
|
||||||
|
.setv("regionalNature", StrUtil.trim(row.getRegionalNature()))
|
||||||
|
.setv("groupType", StrUtil.trim(row.getGroupType()))
|
||||||
|
.setv("lotName", StrUtil.trim(row.getLotName()))
|
||||||
|
.setv("estimatedCost", StrUtil.trim(row.getEstimatedCost()))
|
||||||
|
.setv("maxGroupSize", row.getMaxGroupSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验模板基础必填项和枚举项,只收集错误不抛出,保证前端能一次看到全部错误行。
|
||||||
|
*/
|
||||||
|
private List<String> validateLineImportRow(TheRapyLineImportExcelMode row) {
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
if (row.getYear() == null) {
|
||||||
|
errors.add("年度不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getLineName())) {
|
||||||
|
errors.add("线路名称不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getTravelAgencySerialNumber())) {
|
||||||
|
errors.add("旅行社编号不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getTravelAgencyPlace())) {
|
||||||
|
errors.add("旅行社地点不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getRegionalNature())) {
|
||||||
|
errors.add("线路类型不能为空");
|
||||||
|
} else if (parseRegionalNature(row.getRegionalNature()) == null) {
|
||||||
|
errors.add("线路类型只能填写省内线路或省外线路");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getGroupType())) {
|
||||||
|
errors.add("成团类型不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getLotName())) {
|
||||||
|
errors.add("时间标段不能为空");
|
||||||
|
}
|
||||||
|
if (row.getMaxGroupSize() == null) {
|
||||||
|
errors.add("最多报名人数不能为空");
|
||||||
|
} else if (row.getMaxGroupSize() < 0) {
|
||||||
|
errors.add("最多报名人数不能小于0");
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据旅行社编号核对旅行社、年度、启用状态和地点,避免线路导到不可用旅行社下。
|
||||||
|
*/
|
||||||
|
private void validateTravelAgency(TheRapyLineImportExcelMode row, TheRapyRecuperationTravelAgency travelAgency, List<String> errors) {
|
||||||
|
if (travelAgency == null) {
|
||||||
|
errors.add("旅行社编号不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (travelAgency.getYear() != null && row.getYear() != null && !travelAgency.getYear().equals(row.getYear())) {
|
||||||
|
errors.add("旅行社年度与模板年度不一致");
|
||||||
|
}
|
||||||
|
if (travelAgency.isDisabled()) {
|
||||||
|
errors.add("旅行社未启用");
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(travelAgency.getTravelAgencyPlaces()) || !travelAgency.getTravelAgencyPlaces().contains(StrUtil.trim(row.getTravelAgencyPlace()))) {
|
||||||
|
errors.add("旅行社地点不在该旅行社地点范围内");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer parseGroupType(String groupType, List<String> errors) {
|
||||||
|
String value = StrUtil.trim(groupType);
|
||||||
|
if ("常规团".equals(value)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ("精品团".equals(value)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
errors.add("成团类型只能填写常规团或精品团");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseRegionalNature(String regionalNature) {
|
||||||
|
String value = StrUtil.trim(regionalNature);
|
||||||
|
if ("省内线路".equals(value) || "省内".equals(value)) {
|
||||||
|
return "省内";
|
||||||
|
}
|
||||||
|
if ("省外线路".equals(value) || "省外".equals(value)) {
|
||||||
|
return "省外";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateGroupCountConfig(TheRapyRecuperationConfig config, Integer groupType, List<String> errors) {
|
||||||
|
if (groupType == 1 && config.getConventionalCount() == null) {
|
||||||
|
errors.add("年度配置未维护常规团最少成团人数");
|
||||||
|
}
|
||||||
|
if (groupType == 2 && config.getBoutiqueCount() == null) {
|
||||||
|
errors.add("年度配置未维护精品团最少成团人数");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateLineTimeConfig(TheRapyRecuperationConfig config, List<String> errors) {
|
||||||
|
if (config.getFragmentStartTime() == null || config.getFragmentEndTime() == null
|
||||||
|
|| config.getFragmentPlayStartTime() == null || config.getFragmentPlayEndTime() == null) {
|
||||||
|
errors.add("年度配置未维护报名或游玩时间");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheRapyRecuperationLot findImportLot(TheRapyRecuperationConfig config, String lotName) {
|
||||||
|
String name = StrUtil.trim(lotName);
|
||||||
|
if (Lang.isNotEmpty(config.getLots())) {
|
||||||
|
for (TheRapyRecuperationLot lot : config.getLots()) {
|
||||||
|
if (name.equals(StrUtil.trim(lot.getLotName()))) {
|
||||||
|
return lot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(config.getId())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return dao().fetch(TheRapyRecuperationLot.class, Cnd.where("configId", "=", config.getId()).and("lotName", "=", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按新建线路字段组装实体,导入默认不启用,旅行社联系人自动沿用旅行社基础信息。
|
||||||
|
*/
|
||||||
|
private TheRapyRecuperationLine buildLineByExcel(TheRapyLineImportExcelMode row, TheRapyRecuperationConfig config, TheRapyRecuperationTravelAgency travelAgency,
|
||||||
|
TheRapyRecuperationLot lot, Integer groupType, int serialNumber) {
|
||||||
|
TheRapyRecuperationLine line = new TheRapyRecuperationLine();
|
||||||
|
line.setSerialNumber(serialNumber);
|
||||||
|
line.setLineName(StrUtil.trim(row.getLineName()));
|
||||||
|
line.setTravelAgencyId(travelAgency.getId());
|
||||||
|
line.setTravelAgencyPlace(StrUtil.trim(row.getTravelAgencyPlace()));
|
||||||
|
line.setLineContact(travelAgency.getContact());
|
||||||
|
line.setLineContactPhone(travelAgency.getContactMobileNumber());
|
||||||
|
line.setRegionalNature(parseRegionalNature(row.getRegionalNature()));
|
||||||
|
line.setGroupType(groupType);
|
||||||
|
line.setMinimumGroupSize(groupType == 1 ? config.getConventionalCount() : config.getBoutiqueCount());
|
||||||
|
line.setYear(row.getYear());
|
||||||
|
line.setDisabled(true);
|
||||||
|
line.setCreateUnionId(Vi.getUnionId());
|
||||||
|
line.setSignUpStartTime(config.getFragmentStartTime());
|
||||||
|
line.setSignUpEndTime(config.getFragmentEndTime());
|
||||||
|
line.setChangeEndTime(config.getFragmentEndTime());
|
||||||
|
line.setPlayStartTime(config.getFragmentPlayStartTime());
|
||||||
|
line.setPlayEndTime(config.getFragmentPlayEndTime());
|
||||||
|
line.setEstimatedCost(row.getEstimatedCost());
|
||||||
|
line.setEstimatedFamilyNumbers(1);
|
||||||
|
line.setMaxGroupSize(Objects.requireNonNullElse(row.getMaxGroupSize(), 0));
|
||||||
|
line.setSignUpMode(ShiroUtil.hasAnyRoles("sysadmin, SchoolUnionAdmin")
|
||||||
|
? TheRapyRecuperationSignUpMode.FREE.getValue() : TheRapyRecuperationSignUpMode.PERSONAL.getValue());
|
||||||
|
line.setCreateMode(ShiroUtil.hasAnyRoles("sysadmin, SchoolUnionAdmin")
|
||||||
|
? TheRapyRecuperationLineCreateMode.SCHOOL.getValue() : TheRapyRecuperationLineCreateMode.UNION.getValue());
|
||||||
|
line.setLotId(lot.getId());
|
||||||
|
line.setPlayNumberOfDays(Integer.parseInt(lot.getLotValue()));
|
||||||
|
line.setContent(row.getContent());
|
||||||
|
line.setOpenChoose(false);
|
||||||
|
line.setSpecialLine(false);
|
||||||
|
line.setTogetherLine(false);
|
||||||
|
line.setStateId(groupType == 2 ? 1 : 4);
|
||||||
|
line.setOpBy(ShiroUtil.getUserId());
|
||||||
|
line.setOpAt(Long.valueOf(String.valueOf(new Date().getTime())));
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目标年度中已存在同名、同旅行社、同标段、同区域性质的校工会组织线路时,不再重复复制。
|
* 目标年度中已存在同名、同旅行社、同标段、同区域性质的校工会组织线路时,不再重复复制。
|
||||||
*
|
*
|
||||||
|
|||||||
+214
@@ -1,17 +1,22 @@
|
|||||||
package io.v.nutz.zhgh.therapyRecuperation.service.impl.baseManage;
|
package io.v.nutz.zhgh.therapyRecuperation.service.impl.baseManage;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.wizzer.framework.base.Result;
|
||||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||||
import io.v.nutz.base.utils.Vi;
|
import io.v.nutz.base.utils.Vi;
|
||||||
import io.v.nutz.sys.models.SysHoliday;
|
import io.v.nutz.sys.models.SysHoliday;
|
||||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState;
|
||||||
|
import io.v.nutz.zhgh.therapyRecuperation.mode.TheRapyBaseManagementExcelMode;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseDailyQuota;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseDailyQuota;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseManagement;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseManagement;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnroll;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationEnroll;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot;
|
||||||
|
import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService;
|
||||||
import io.v.nutz.zhgh.therapyRecuperation.service.baseManage.TheRapyRecuperationBaseManagerService;
|
import io.v.nutz.zhgh.therapyRecuperation.service.baseManage.TheRapyRecuperationBaseManagerService;
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
@@ -25,6 +30,7 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
|||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -264,6 +270,214 @@ public class TheRapyRecuperationBaseManagerServiceImpl extends BaseServiceImpl i
|
|||||||
.setv("skipCount", skipCount);
|
.setv("skipCount", skipCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入目的地时只读取模板基础字段,报名和活动时间统一取对应年度的疗休养配置。
|
||||||
|
*
|
||||||
|
* @param file Excel文件
|
||||||
|
* @param opBy 当前操作人ID
|
||||||
|
* @param createUnionId 当前操作人所属工会ID
|
||||||
|
* @return 导入结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result importBaseManager(File file, String opBy, String createUnionId) {
|
||||||
|
List<TheRapyBaseManagementExcelMode> excelList;
|
||||||
|
try {
|
||||||
|
excelList = ExcelImportUtil.importExcel(file, TheRapyBaseManagementExcelMode.class, new ImportParams());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(excelList)) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
List<TheRapyRecuperationBaseManagement> baseList = new ArrayList<>();
|
||||||
|
List<NutMap> successList = new ArrayList<>();
|
||||||
|
List<NutMap> errorList = new ArrayList<>();
|
||||||
|
int nextSortNumber = getNextSortNumber();
|
||||||
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
TheRapyBaseManagementExcelMode row = excelList.get(i);
|
||||||
|
int rowNumber = i + 2;
|
||||||
|
if (isBlankImportRow(row) || TheRapyBaseManagementExcelMode.SAMPLE_BASE_NAME.equals(StrUtil.trim(row.getBaseName()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NutMap resultRow = createBaseImportResultRow(rowNumber, row);
|
||||||
|
List<String> errors = validateImportRow(row);
|
||||||
|
TheRapyRecuperationConfig config = null;
|
||||||
|
TheRapyRecuperationTravelAgency travelAgency = null;
|
||||||
|
List<String> allowDayList = Collections.emptyList();
|
||||||
|
if (row.getYear() != null) {
|
||||||
|
try {
|
||||||
|
config = configService.requireByYear(row.getYear());
|
||||||
|
} catch (Exception e) {
|
||||||
|
errors.add(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(row.getTravelAgencySerialNumber())) {
|
||||||
|
travelAgency = dao().fetch(TheRapyRecuperationTravelAgency.class, Cnd.where("serialNumber", "=", StrUtil.trim(row.getTravelAgencySerialNumber())));
|
||||||
|
validateTravelAgency(row, travelAgency, errors);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(row.getAllowDay())) {
|
||||||
|
allowDayList = parseAllowDay(row.getAllowDay(), errors);
|
||||||
|
}
|
||||||
|
if (Lang.isNotEmpty(errors)) {
|
||||||
|
resultRow.setv("errors", String.join(";", errors));
|
||||||
|
errorList.add(resultRow);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TheRapyRecuperationBaseManagement baseManagement = buildBaseManagementByExcel(row, opBy, createUnionId, config, travelAgency, allowDayList, nextSortNumber++);
|
||||||
|
baseList.add(baseManagement);
|
||||||
|
resultRow.setv("errors", "");
|
||||||
|
successList.add(resultRow);
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(baseList) && Lang.isEmpty(errorList)) {
|
||||||
|
return Result.error("读取不到数据,请检查excel文件格式");
|
||||||
|
}
|
||||||
|
if (Lang.isNotEmpty(baseList)) {
|
||||||
|
dao().insertOrUpdate(baseList);
|
||||||
|
}
|
||||||
|
NutMap importResult = NutMap.NEW()
|
||||||
|
.setv("totalCount", successList.size() + errorList.size())
|
||||||
|
.setv("successCount", successList.size())
|
||||||
|
.setv("errorCount", errorList.size())
|
||||||
|
.setv("successList", successList)
|
||||||
|
.setv("errorList", errorList);
|
||||||
|
String msg = "导入完成,成功" + successList.size() + "条,失败" + errorList.size() + "条";
|
||||||
|
return Result.success().addMsg(msg).addData(importResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBlankImportRow(TheRapyBaseManagementExcelMode row) {
|
||||||
|
return row == null
|
||||||
|
|| (row.getYear() == null
|
||||||
|
&& row.getMaxSignCount() == null
|
||||||
|
&& StrUtil.isAllBlank(row.getBaseName(), row.getTravelAgencySerialNumber(), row.getTravelAgencyPlace(),
|
||||||
|
row.getRegionalNature(), row.getAllowDay(), row.getBaseContactPerson(), row.getBaseContactNumber(), row.getContent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成目的地导入结果行,前端错误表格和错误导出共用这一份数据。
|
||||||
|
*/
|
||||||
|
private NutMap createBaseImportResultRow(int rowNumber, TheRapyBaseManagementExcelMode row) {
|
||||||
|
return NutMap.NEW()
|
||||||
|
.setv("no", rowNumber)
|
||||||
|
.setv("year", row.getYear())
|
||||||
|
.setv("baseName", StrUtil.trim(row.getBaseName()))
|
||||||
|
.setv("travelAgencySerialNumber", StrUtil.trim(row.getTravelAgencySerialNumber()))
|
||||||
|
.setv("travelAgencyPlace", StrUtil.trim(row.getTravelAgencyPlace()))
|
||||||
|
.setv("regionalNature", StrUtil.trim(row.getRegionalNature()))
|
||||||
|
.setv("allowDay", StrUtil.trim(row.getAllowDay()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验模板基础必填项和枚举项,只收集错误不抛出,保证前端能一次看到全部错误行。
|
||||||
|
*/
|
||||||
|
private List<String> validateImportRow(TheRapyBaseManagementExcelMode row) {
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
if (row.getYear() == null) {
|
||||||
|
errors.add("年度不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getBaseName())) {
|
||||||
|
errors.add("目的地名称不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getTravelAgencySerialNumber())) {
|
||||||
|
errors.add("旅行社编号不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getTravelAgencyPlace())) {
|
||||||
|
errors.add("旅行社地点不能为空");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getRegionalNature())) {
|
||||||
|
errors.add("活动范围不能为空");
|
||||||
|
} else if (!List.of("省内", "省外").contains(StrUtil.trim(row.getRegionalNature()))) {
|
||||||
|
errors.add("活动范围只能填写省内或省外");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(row.getAllowDay())) {
|
||||||
|
errors.add("天数不能为空");
|
||||||
|
}
|
||||||
|
if (row.getMaxSignCount() != null && row.getMaxSignCount() < 0) {
|
||||||
|
errors.add("每日最高人数不能小于0");
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据旅行社编号核对旅行社、年度、启用状态和地点,避免目的地导到不可用旅行社下。
|
||||||
|
*/
|
||||||
|
private void validateTravelAgency(TheRapyBaseManagementExcelMode row, TheRapyRecuperationTravelAgency travelAgency, List<String> errors) {
|
||||||
|
if (travelAgency == null) {
|
||||||
|
errors.add("旅行社编号不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (travelAgency.getYear() != null && row.getYear() != null && !travelAgency.getYear().equals(row.getYear())) {
|
||||||
|
errors.add("旅行社年度与模板年度不一致");
|
||||||
|
}
|
||||||
|
if (travelAgency.isDisabled()) {
|
||||||
|
errors.add("旅行社未启用");
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(travelAgency.getTravelAgencyPlaces()) || !travelAgency.getTravelAgencyPlaces().contains(StrUtil.trim(row.getTravelAgencyPlace()))) {
|
||||||
|
errors.add("旅行社地点不在该旅行社地点范围内");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析模板天数字段,支持英文逗号和中文逗号,导入值限定为页面可选的3、2、2.5。
|
||||||
|
*
|
||||||
|
* @param allowDay 模板天数字段
|
||||||
|
* @param errors 当前行错误列表
|
||||||
|
* @return 可保存到目的地的天数列表
|
||||||
|
*/
|
||||||
|
private List<String> parseAllowDay(String allowDay, List<String> errors) {
|
||||||
|
Set<String> allowedValues = Set.of("3", "2", "2.5");
|
||||||
|
List<String> allowDayList = new ArrayList<>();
|
||||||
|
String[] values = StrUtil.trim(allowDay).replace(",", ",").split(",");
|
||||||
|
for (String value : values) {
|
||||||
|
String day = StrUtil.trim(value);
|
||||||
|
if (StrUtil.isBlank(day)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!allowedValues.contains(day)) {
|
||||||
|
errors.add("天数只能填写3、2、2.5");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!allowDayList.contains(day)) {
|
||||||
|
allowDayList.add(day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Lang.isEmpty(allowDayList)) {
|
||||||
|
errors.add("天数不能为空");
|
||||||
|
}
|
||||||
|
return allowDayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按新建目的地提交字段组装实体,导入默认不启用,时间统一沿用年度配置。
|
||||||
|
*/
|
||||||
|
private TheRapyRecuperationBaseManagement buildBaseManagementByExcel(TheRapyBaseManagementExcelMode row, String opBy, String createUnionId, TheRapyRecuperationConfig config,
|
||||||
|
TheRapyRecuperationTravelAgency travelAgency, List<String> allowDayList, int sortNumber) {
|
||||||
|
TheRapyRecuperationBaseManagement baseManagement = new TheRapyRecuperationBaseManagement();
|
||||||
|
baseManagement.setYear(row.getYear());
|
||||||
|
baseManagement.setSortNumber(sortNumber);
|
||||||
|
baseManagement.setBaseName(StrUtil.trim(row.getBaseName()));
|
||||||
|
baseManagement.setTravelAgencyId(travelAgency.getId());
|
||||||
|
baseManagement.setTravelAgencyPlace(StrUtil.trim(row.getTravelAgencyPlace()));
|
||||||
|
baseManagement.setRegionalNature(StrUtil.trim(row.getRegionalNature()));
|
||||||
|
baseManagement.setContent(row.getContent());
|
||||||
|
baseManagement.setIsDisabled(true);
|
||||||
|
baseManagement.setCreateUnionId(createUnionId);
|
||||||
|
baseManagement.setSignUpStartTime(config.getFragmentStartTime());
|
||||||
|
baseManagement.setSignUpEndTime(config.getFragmentEndTime());
|
||||||
|
baseManagement.setChangeEndTime(config.getFragmentEndTime());
|
||||||
|
baseManagement.setActivityStartTime(config.getFragmentPlayStartTime());
|
||||||
|
baseManagement.setActivityEndTime(config.getFragmentPlayEndTime());
|
||||||
|
baseManagement.setCreateMode(1);
|
||||||
|
baseManagement.setBaseContactPerson(StrUtil.blankToDefault(row.getBaseContactPerson(), travelAgency.getContact()));
|
||||||
|
baseManagement.setBaseContactNumber(StrUtil.blankToDefault(row.getBaseContactNumber(), travelAgency.getContactMobileNumber()));
|
||||||
|
baseManagement.setWeekCheckIn(Collections.emptyList());
|
||||||
|
baseManagement.setAllowDay(allowDayList);
|
||||||
|
baseManagement.setMaxSignCount(Objects.requireNonNullElse(row.getMaxSignCount(), 0));
|
||||||
|
baseManagement.setOpBy(opBy);
|
||||||
|
baseManagement.setOpAt(String.valueOf(new Date().getTime()));
|
||||||
|
return baseManagement;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目标年度存在同名、同旅行社、同地点、同区域、同标段的目的地时,不再重复复制。
|
* 目标年度存在同名、同旅行社、同地点、同区域、同标段的目的地时,不再重复复制。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<el-descriptions-item label="成团类型">{{ viewData.groupType === 1 ? '常规团' : '精品团' }}</el-descriptions-item>
|
<el-descriptions-item label="成团类型">{{ viewData.groupType === 1 ? '常规团' : '精品团' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="线路类型">{{ viewData.regionalNature }}</el-descriptions-item>
|
<el-descriptions-item label="线路类型">{{ viewData.regionalNature }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="最少成团人数">{{ viewData.minimumGroupSize }}</el-descriptions-item>
|
<el-descriptions-item label="最少成团人数">{{ viewData.minimumGroupSize }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="最多报名人数">{{ viewData.maxGroupSize === 0 ? '不限制' : viewData.maxGroupSize }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="时间标段">{{ viewData.lotName }}</el-descriptions-item>
|
<el-descriptions-item label="时间标段">{{ viewData.lotName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="预计费用">{{ viewData.estimatedCost }}</el-descriptions-item>
|
<el-descriptions-item label="预计费用">{{ viewData.estimatedCost }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="联系人">{{ viewData.lineContact }}</el-descriptions-item>
|
<el-descriptions-item label="联系人">{{ viewData.lineContact }}</el-descriptions-item>
|
||||||
|
|||||||
+125
-19
@@ -404,8 +404,8 @@ layout("/layouts/platform.html"){
|
|||||||
<el-upload
|
<el-upload
|
||||||
name="file"
|
name="file"
|
||||||
ref="upload"
|
ref="upload"
|
||||||
:on-remove="(file, fileList) => {importData.fileList = fileHandleRemove(file, fileList)}"
|
:on-remove="handleImportFileRemove"
|
||||||
:on-change="(file, fileList) => {importData.fileList = fileHandleChange(file, fileList,{type:['xls','xlsx']})}"
|
:on-change="handleImportFileChange"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:file-list="importData.fileList">
|
:file-list="importData.fileList">
|
||||||
@@ -419,14 +419,43 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-timeline-item>
|
</el-timeline-item>
|
||||||
|
<el-timeline-item timestamp="导入结果" placement="top">
|
||||||
|
<el-card shadow="never">
|
||||||
|
<p>总记录数:{{importResult.totalCount}}</p>
|
||||||
|
<p>成功数:<span class="text-success">{{importResult.successCount}}</span></p>
|
||||||
|
<p>失败数:<span class="text-danger">{{importResult.errorCount}}</span></p>
|
||||||
|
<el-link @click="openImportError" type="primary"
|
||||||
|
v-if="importResult.errorCount>0">查看错误记录
|
||||||
|
</el-link>
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
</el-timeline>
|
</el-timeline>
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="importVisible = false" :disabled="importLoading">取 消</el-button>
|
<el-button @click="closeImportDialog" :disabled="importLoading">取 消</el-button>
|
||||||
<el-button type="primary" @click="doImport" :loading="importLoading">确定</el-button>
|
<el-button type="primary" @click="doImport" :loading="importLoading">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog title="目的地导入错误记录" :visible.sync="importErrorVisible" append-to-body
|
||||||
|
:close-on-click-modal="false" width="80%">
|
||||||
|
<div style="text-align: right; margin-bottom: 10px">
|
||||||
|
<el-button size="small" type="primary" icon="el-icon-download"
|
||||||
|
@click="exportImportErrors">下载错误记录
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="importResult.errorList" size="small" border>
|
||||||
|
<el-table-column label="excel序号" prop="no" width="100px"></el-table-column>
|
||||||
|
<el-table-column label="年度" prop="year" width="100px"></el-table-column>
|
||||||
|
<el-table-column label="目的地名称" prop="baseName" width="160px"></el-table-column>
|
||||||
|
<el-table-column label="旅行社编号" prop="travelAgencySerialNumber" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="旅行社地点" prop="travelAgencyPlace" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="活动范围" prop="regionalNature" width="110px"></el-table-column>
|
||||||
|
<el-table-column label="天数" prop="allowDay" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="未导入原因" prop="errors" show-overflow-tooltip></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="沿用目的地"
|
title="沿用目的地"
|
||||||
:visible.sync="copyBaseVisible"
|
:visible.sync="copyBaseVisible"
|
||||||
@@ -464,6 +493,7 @@ layout("/layouts/platform.html"){
|
|||||||
</template>
|
</template>
|
||||||
</guava>
|
</guava>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="${base!}/assets/platform/plugins/xlsx/xlsx.full.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
@@ -599,8 +629,18 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
//目的地导入
|
//目的地导入
|
||||||
importVisible: false,
|
importVisible: false,
|
||||||
|
importErrorVisible: false,
|
||||||
importLoading: false,
|
importLoading: false,
|
||||||
importData: {},
|
importData: {
|
||||||
|
fileList: []
|
||||||
|
},
|
||||||
|
importResult: {
|
||||||
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
|
},
|
||||||
copyBaseVisible: false,
|
copyBaseVisible: false,
|
||||||
copyBaseLoading: false,
|
copyBaseLoading: false,
|
||||||
copyBaseForm: {
|
copyBaseForm: {
|
||||||
@@ -842,10 +882,17 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openImport() {
|
openImport() {
|
||||||
this.importData = {
|
this.$set(this.importData, 'fileList', [])
|
||||||
fileList: []
|
this.resetImportResult()
|
||||||
}
|
this.$set(this, 'importVisible', true)
|
||||||
this.importVisible = true;
|
},
|
||||||
|
handleImportFileRemove(file, fileList) {
|
||||||
|
this.$set(this.importData, 'fileList', this.fileHandleRemove(file, fileList))
|
||||||
|
this.resetImportResult()
|
||||||
|
},
|
||||||
|
handleImportFileChange(file, fileList) {
|
||||||
|
this.$set(this.importData, 'fileList', this.fileHandleChange(file, fileList, {type: ['xls', 'xlsx']}))
|
||||||
|
this.resetImportResult()
|
||||||
},
|
},
|
||||||
doImport() {
|
doImport() {
|
||||||
if (this.importData.fileList.length === 0) {
|
if (this.importData.fileList.length === 0) {
|
||||||
@@ -856,29 +903,88 @@ layout("/layouts/platform.html"){
|
|||||||
this.importData.fileList.forEach((val) => {
|
this.importData.fileList.forEach((val) => {
|
||||||
data.append("file", val.raw, val.raw.name);
|
data.append("file", val.raw, val.raw.name);
|
||||||
});
|
});
|
||||||
this.importLoading = true
|
this.$set(this, 'importLoading', true)
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: loc() + "/importBaseManager",
|
url: loc() + "/importBaseManager",
|
||||||
type: "post",
|
type: "post",
|
||||||
data: data,
|
data: data,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
success: (data) => {
|
success: (resp) => {
|
||||||
if (data.code === 0){
|
if (resp.code === 0) {
|
||||||
this.$message.success(data.msg)
|
const result = resp.data || this.emptyImportResult()
|
||||||
this.pageData();
|
this.$set(this, 'importResult', result)
|
||||||
this.importVisible = false
|
if (result.successCount > 0) {
|
||||||
this.importLoading = false
|
this.pageData()
|
||||||
}else {
|
}
|
||||||
this.importVisible = false
|
if (result.errorCount > 0) {
|
||||||
|
this.notifyWarning(resp.msg || '导入完成,存在未导入目的地')
|
||||||
|
} else {
|
||||||
|
this.notifySuccess(resp.msg || '导入成功')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.notifyWarning(resp.msg)
|
||||||
}
|
}
|
||||||
|
this.$set(this, 'importLoading', false)
|
||||||
},
|
},
|
||||||
error: (data) => {
|
error: () => {
|
||||||
this.notifyWarning("导入失败")
|
this.notifyWarning("导入失败")
|
||||||
this.importLoading = false
|
this.$set(this, 'importLoading', false)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
closeImportDialog() {
|
||||||
|
this.$set(this, 'importVisible', false)
|
||||||
|
this.$set(this, 'importErrorVisible', false)
|
||||||
|
},
|
||||||
|
emptyImportResult() {
|
||||||
|
return {
|
||||||
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetImportResult() {
|
||||||
|
this.$set(this, 'importResult', this.emptyImportResult())
|
||||||
|
this.$set(this, 'importErrorVisible', false)
|
||||||
|
},
|
||||||
|
openImportError() {
|
||||||
|
this.$set(this, 'importErrorVisible', true)
|
||||||
|
},
|
||||||
|
exportImportErrors() {
|
||||||
|
const data = this.importResult.errorList || []
|
||||||
|
if (data.length === 0) {
|
||||||
|
this.notifyWarning('暂无错误记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const exportData = data.map(item => {
|
||||||
|
return {
|
||||||
|
'excel序号': item.no,
|
||||||
|
'年度': item.year,
|
||||||
|
'目的地名称': item.baseName,
|
||||||
|
'旅行社编号': item.travelAgencySerialNumber,
|
||||||
|
'旅行社地点': item.travelAgencyPlace,
|
||||||
|
'活动范围': item.regionalNature,
|
||||||
|
'天数': item.allowDay,
|
||||||
|
'未导入原因': item.errors
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const workbook = XLSX.utils.book_new()
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(exportData)
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, '错误记录')
|
||||||
|
const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'})
|
||||||
|
const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = '目的地导入错误记录.xlsx'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
async getNumber() {
|
async getNumber() {
|
||||||
const resp = await $.post(loc() + '/getNo')
|
const resp = await $.post(loc() + '/getNo')
|
||||||
this.formData.sortNumber = resp.data
|
this.formData.sortNumber = resp.data
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ layout("/layouts/platform.html"){
|
|||||||
@click="openCopySchoolUnionLine"
|
@click="openCopySchoolUnionLine"
|
||||||
size="medium"
|
size="medium"
|
||||||
type="primary">沿用校工会线路</el-button>
|
type="primary">沿用校工会线路</el-button>
|
||||||
|
<el-button @click="openImport" size="medium" type="primary">导入线路</el-button>
|
||||||
<el-button @click="openAdd" size="medium" type="primary">新建线路</el-button>
|
<el-button @click="openAdd" size="medium" type="primary">新建线路</el-button>
|
||||||
</template>
|
</template>
|
||||||
</table-tool>
|
</table-tool>
|
||||||
@@ -479,12 +480,8 @@ layout("/layouts/platform.html"){
|
|||||||
<el-upload
|
<el-upload
|
||||||
name="file"
|
name="file"
|
||||||
ref="upload"
|
ref="upload"
|
||||||
:on-remove="(file, fileList) => {
|
:on-remove="handleImportFileRemove"
|
||||||
importData.fileList = fileHandleRemove(file, fileList)
|
:on-change="handleImportFileChange"
|
||||||
}"
|
|
||||||
:on-change="(file, fileList) => {
|
|
||||||
importData.fileList = fileHandleChange(file, fileList,{type:['xls','xlsx']})
|
|
||||||
}"
|
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:file-list="importData.fileList">
|
:file-list="importData.fileList">
|
||||||
@@ -498,14 +495,46 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-timeline-item>
|
</el-timeline-item>
|
||||||
|
<el-timeline-item timestamp="导入结果" placement="top">
|
||||||
|
<el-card shadow="never">
|
||||||
|
<p>总记录数:{{importResult.totalCount}}</p>
|
||||||
|
<p>成功数:<span class="text-success">{{importResult.successCount}}</span></p>
|
||||||
|
<p>失败数:<span class="text-danger">{{importResult.errorCount}}</span></p>
|
||||||
|
<el-link @click="openImportError" type="primary"
|
||||||
|
v-if="importResult.errorCount>0">查看错误记录
|
||||||
|
</el-link>
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
</el-timeline>
|
</el-timeline>
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="importVisible = false" :disabled="importLoading">取 消</el-button>
|
<el-button @click="closeImportDialog" :disabled="importLoading">取 消</el-button>
|
||||||
<el-button type="primary" @click="doImport" :loading="importLoading">确定</el-button>
|
<el-button type="primary" @click="doImport" :loading="importLoading">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog title="线路导入错误记录" :visible.sync="importErrorVisible" append-to-body
|
||||||
|
:close-on-click-modal="false" width="85%">
|
||||||
|
<div style="text-align: right; margin-bottom: 10px">
|
||||||
|
<el-button size="small" type="primary" icon="el-icon-download"
|
||||||
|
@click="exportImportErrors">下载错误记录
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="importResult.errorList" size="small" border>
|
||||||
|
<el-table-column label="excel序号" prop="no" width="100px"></el-table-column>
|
||||||
|
<el-table-column label="年度" prop="year" width="100px"></el-table-column>
|
||||||
|
<el-table-column label="线路名称" prop="lineName" width="160px"></el-table-column>
|
||||||
|
<el-table-column label="旅行社编号" prop="travelAgencySerialNumber" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="旅行社地点" prop="travelAgencyPlace" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="线路类型" prop="regionalNature" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="成团类型" prop="groupType" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="时间标段" prop="lotName" width="130px"></el-table-column>
|
||||||
|
<el-table-column label="预计费用" prop="estimatedCost" width="110px"></el-table-column>
|
||||||
|
<el-table-column label="最多报名人数" prop="maxGroupSize" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="未导入原因" prop="errors" show-overflow-tooltip></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="沿用校工会线路"
|
title="沿用校工会线路"
|
||||||
:visible.sync="copyLineVisible"
|
:visible.sync="copyLineVisible"
|
||||||
@@ -541,6 +570,7 @@ layout("/layouts/platform.html"){
|
|||||||
</guava>
|
</guava>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="${base!}/assets/platform/plugins/xlsx/xlsx.full.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const vue = new Vue({
|
const vue = new Vue({
|
||||||
@@ -692,8 +722,18 @@ layout("/layouts/platform.html"){
|
|||||||
lotList: [],
|
lotList: [],
|
||||||
//路线导入
|
//路线导入
|
||||||
importVisible: false,
|
importVisible: false,
|
||||||
|
importErrorVisible: false,
|
||||||
importLoading: false,
|
importLoading: false,
|
||||||
importData: {},
|
importData: {
|
||||||
|
fileList: []
|
||||||
|
},
|
||||||
|
importResult: {
|
||||||
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
|
},
|
||||||
copyLineVisible: false,
|
copyLineVisible: false,
|
||||||
copyLineLoading: false,
|
copyLineLoading: false,
|
||||||
copyLineForm: {
|
copyLineForm: {
|
||||||
@@ -832,7 +872,10 @@ layout("/layouts/platform.html"){
|
|||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
const data = resp.data
|
const data = resp.data
|
||||||
data.year = data.year.toString()
|
data.year = data.year.toString()
|
||||||
this.formData = {...data}
|
await this.getConfig(data.year)
|
||||||
|
await this.getLotList(data.year)
|
||||||
|
await this.getModifyConfig(data.year)
|
||||||
|
this.$set(this, 'formData', {...data})
|
||||||
} else {
|
} else {
|
||||||
this.notifyWarning(resp.msg)
|
this.notifyWarning(resp.msg)
|
||||||
}
|
}
|
||||||
@@ -945,10 +988,17 @@ layout("/layouts/platform.html"){
|
|||||||
this.$set(this, 'lotList', (data || {}).lots || [])
|
this.$set(this, 'lotList', (data || {}).lots || [])
|
||||||
},
|
},
|
||||||
openImport() {
|
openImport() {
|
||||||
this.importData = {
|
this.$set(this.importData, 'fileList', [])
|
||||||
fileList: []
|
this.resetImportResult()
|
||||||
}
|
this.$set(this, 'importVisible', true)
|
||||||
this.importVisible = true;
|
},
|
||||||
|
handleImportFileRemove(file, fileList) {
|
||||||
|
this.$set(this.importData, 'fileList', this.fileHandleRemove(file, fileList))
|
||||||
|
this.resetImportResult()
|
||||||
|
},
|
||||||
|
handleImportFileChange(file, fileList) {
|
||||||
|
this.$set(this.importData, 'fileList', this.fileHandleChange(file, fileList, {type: ['xls', 'xlsx']}))
|
||||||
|
this.resetImportResult()
|
||||||
},
|
},
|
||||||
async doImport() {
|
async doImport() {
|
||||||
if (this.importData.fileList.length === 0) {
|
if (this.importData.fileList.length === 0) {
|
||||||
@@ -959,24 +1009,91 @@ layout("/layouts/platform.html"){
|
|||||||
this.importData.fileList.forEach((val) => {
|
this.importData.fileList.forEach((val) => {
|
||||||
data.append("file", val.raw, val.raw.name);
|
data.append("file", val.raw, val.raw.name);
|
||||||
});
|
});
|
||||||
this.importLoading = true
|
this.$set(this, 'importLoading', true)
|
||||||
const resp = await $.ajax({
|
$.ajax({
|
||||||
url: loc() + '/travelLineImport',
|
url: loc() + '/travelLineImport',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: data,
|
data: data,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false
|
contentType: false,
|
||||||
|
success: (resp) => {
|
||||||
|
if (resp.code === 0) {
|
||||||
|
const result = resp.data || this.emptyImportResult()
|
||||||
|
this.$set(this, 'importResult', result)
|
||||||
|
if (result.successCount > 0) {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
if (result.errorCount > 0) {
|
||||||
|
this.notifyWarning(resp.msg || '导入完成,存在线路未导入')
|
||||||
|
} else {
|
||||||
|
this.notifySuccess(resp.msg || '导入成功')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.notifyWarning(resp.msg)
|
||||||
|
}
|
||||||
|
this.$set(this, 'importLoading', false)
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.notifyWarning("导入失败")
|
||||||
|
this.$set(this, 'importLoading', false)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if (resp.code === 0){
|
},
|
||||||
this.$message.success(resp.msg)
|
closeImportDialog() {
|
||||||
this.pageData();
|
this.$set(this, 'importVisible', false)
|
||||||
this.importVisible = false
|
this.$set(this, 'importErrorVisible', false)
|
||||||
this.importLoading = false
|
},
|
||||||
}else {
|
emptyImportResult() {
|
||||||
this.notifyWarning("导入失败")
|
return {
|
||||||
this.importLoading = false
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetImportResult() {
|
||||||
|
this.$set(this, 'importResult', this.emptyImportResult())
|
||||||
|
this.$set(this, 'importErrorVisible', false)
|
||||||
|
},
|
||||||
|
openImportError() {
|
||||||
|
this.$set(this, 'importErrorVisible', true)
|
||||||
|
},
|
||||||
|
exportImportErrors() {
|
||||||
|
const data = this.importResult.errorList || []
|
||||||
|
if (data.length === 0) {
|
||||||
|
this.notifyWarning('暂无错误记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const exportData = data.map(item => {
|
||||||
|
return {
|
||||||
|
'excel序号': item.no,
|
||||||
|
'年度': item.year,
|
||||||
|
'线路名称': item.lineName,
|
||||||
|
'旅行社编号': item.travelAgencySerialNumber,
|
||||||
|
'旅行社地点': item.travelAgencyPlace,
|
||||||
|
'线路类型': item.regionalNature,
|
||||||
|
'成团类型': item.groupType,
|
||||||
|
'时间标段': item.lotName,
|
||||||
|
'预计费用': item.estimatedCost,
|
||||||
|
'最多报名人数': item.maxGroupSize,
|
||||||
|
'未导入原因': item.errors
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const workbook = XLSX.utils.book_new()
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(exportData)
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, '错误记录')
|
||||||
|
const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'})
|
||||||
|
const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = '线路导入错误记录.xlsx'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
handleChangeYear() {
|
handleChangeYear() {
|
||||||
if (this.pageForm.startYear && this.pageForm.endYear) {
|
if (this.pageForm.startYear && this.pageForm.endYear) {
|
||||||
if (this.pageForm.startYear > this.pageForm.endYear) {
|
if (this.pageForm.startYear > this.pageForm.endYear) {
|
||||||
|
|||||||
+96
-4
@@ -344,7 +344,7 @@ layout("/layouts/platform.html"){
|
|||||||
title="参加人员补录"
|
title="参加人员补录"
|
||||||
:visible.sync="supplementVisible"
|
:visible.sync="supplementVisible"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
width="50%">
|
width="65%">
|
||||||
<el-timeline>
|
<el-timeline>
|
||||||
<el-timeline-item timestamp="选择线路" placement="top">
|
<el-timeline-item timestamp="选择线路" placement="top">
|
||||||
<el-card>
|
<el-card>
|
||||||
@@ -383,6 +383,16 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-timeline-item>
|
</el-timeline-item>
|
||||||
|
<el-timeline-item placement="top" timestamp="导入结果">
|
||||||
|
<el-card shadow="never">
|
||||||
|
<p>总记录数:{{supplementResult.totalCount}}</p>
|
||||||
|
<p>成功数:<span class="text-success">{{supplementResult.successCount}}</span></p>
|
||||||
|
<p>失败数:<span class="text-danger">{{supplementResult.errorCount}}</span></p>
|
||||||
|
<el-link @click="openSupplementError" type="primary"
|
||||||
|
v-if="supplementResult.errorCount>0">查看错误记录
|
||||||
|
</el-link>
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
</el-timeline>
|
</el-timeline>
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
@@ -390,6 +400,23 @@ layout("/layouts/platform.html"){
|
|||||||
<el-button type="primary" @click="doSupplementImport" :loading="supplementLoading">确定</el-button>
|
<el-button type="primary" @click="doSupplementImport" :loading="supplementLoading">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog title="补录错误记录" :visible.sync="supplementErrorVisible" append-to-body
|
||||||
|
:close-on-click-modal="false" width="75%">
|
||||||
|
<div style="text-align: right; margin-bottom: 10px">
|
||||||
|
<el-button size="small" type="primary" icon="el-icon-download"
|
||||||
|
@click="exportSupplementErrors">下载错误记录
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="supplementResult.errorList" size="small" border>
|
||||||
|
<el-table-column label="excel序号" prop="no" width="100px"></el-table-column>
|
||||||
|
<el-table-column label="工号" prop="loginName" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="姓名" prop="userName" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="参加时间" prop="takePartInTime" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="标段时间" prop="lotName" width="120px"></el-table-column>
|
||||||
|
<el-table-column label="未导入原因" prop="errors" show-overflow-tooltip></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -439,11 +466,19 @@ layout("/layouts/platform.html"){
|
|||||||
fileList: []
|
fileList: []
|
||||||
},
|
},
|
||||||
supplementVisible: false,
|
supplementVisible: false,
|
||||||
|
supplementErrorVisible: false,
|
||||||
supplementLoading: false,
|
supplementLoading: false,
|
||||||
supplementLines: [],
|
supplementLines: [],
|
||||||
supplementData: {
|
supplementData: {
|
||||||
takePartInLineId: '',
|
takePartInLineId: '',
|
||||||
fileList: []
|
fileList: []
|
||||||
|
},
|
||||||
|
supplementResult: {
|
||||||
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -563,14 +598,17 @@ layout("/layouts/platform.html"){
|
|||||||
openSupplementImport() {
|
openSupplementImport() {
|
||||||
this.$set(this.supplementData, 'takePartInLineId', this.pageForm.takePartInLineId || '')
|
this.$set(this.supplementData, 'takePartInLineId', this.pageForm.takePartInLineId || '')
|
||||||
this.$set(this.supplementData, 'fileList', [])
|
this.$set(this.supplementData, 'fileList', [])
|
||||||
|
this.resetSupplementResult()
|
||||||
this.getSupplementLines()
|
this.getSupplementLines()
|
||||||
this.$set(this, 'supplementVisible', true)
|
this.$set(this, 'supplementVisible', true)
|
||||||
},
|
},
|
||||||
handleSupplementFileRemove(file, fileList) {
|
handleSupplementFileRemove(file, fileList) {
|
||||||
this.$set(this.supplementData, 'fileList', this.fileHandleRemove(file, fileList))
|
this.$set(this.supplementData, 'fileList', this.fileHandleRemove(file, fileList))
|
||||||
|
this.resetSupplementResult()
|
||||||
},
|
},
|
||||||
handleSupplementFileChange(file, fileList) {
|
handleSupplementFileChange(file, fileList) {
|
||||||
this.$set(this.supplementData, 'fileList', this.fileHandleChange(file, fileList, {type: ['xls', 'xlsx']}))
|
this.$set(this.supplementData, 'fileList', this.fileHandleChange(file, fileList, {type: ['xls', 'xlsx']}))
|
||||||
|
this.resetSupplementResult()
|
||||||
},
|
},
|
||||||
doSupplementImport() {
|
doSupplementImport() {
|
||||||
if (!this.supplementData.takePartInLineId) {
|
if (!this.supplementData.takePartInLineId) {
|
||||||
@@ -595,9 +633,16 @@ layout("/layouts/platform.html"){
|
|||||||
contentType: false,
|
contentType: false,
|
||||||
success: (resp) => {
|
success: (resp) => {
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0) {
|
||||||
this.$set(this, 'supplementVisible', false)
|
const result = resp.data || this.emptySupplementResult()
|
||||||
this.$message.success(resp.msg || resp.data || '补录成功')
|
this.$set(this, 'supplementResult', result)
|
||||||
this.doSearch()
|
if (result.successCount > 0) {
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
if (result.errorCount > 0) {
|
||||||
|
this.$message.warning(resp.msg || '补录完成,存在未导入人员')
|
||||||
|
} else {
|
||||||
|
this.$message.success(resp.msg || '补录成功')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(resp.msg)
|
this.$message.warning(resp.msg)
|
||||||
}
|
}
|
||||||
@@ -611,8 +656,55 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
supplementVisibleClose() {
|
supplementVisibleClose() {
|
||||||
this.$set(this, 'supplementVisible', false)
|
this.$set(this, 'supplementVisible', false)
|
||||||
|
this.$set(this, 'supplementErrorVisible', false)
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
},
|
},
|
||||||
|
emptySupplementResult() {
|
||||||
|
return {
|
||||||
|
totalCount: 0,
|
||||||
|
successCount: 0,
|
||||||
|
errorCount: 0,
|
||||||
|
successList: [],
|
||||||
|
errorList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetSupplementResult() {
|
||||||
|
this.$set(this, 'supplementResult', this.emptySupplementResult())
|
||||||
|
this.$set(this, 'supplementErrorVisible', false)
|
||||||
|
},
|
||||||
|
openSupplementError() {
|
||||||
|
this.$set(this, 'supplementErrorVisible', true)
|
||||||
|
},
|
||||||
|
exportSupplementErrors() {
|
||||||
|
const data = this.supplementResult.errorList || []
|
||||||
|
if (data.length === 0) {
|
||||||
|
this.$message.warning('暂无错误记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const exportData = data.map(item => {
|
||||||
|
return {
|
||||||
|
'excel序号': item.no,
|
||||||
|
'工号': item.loginName,
|
||||||
|
'姓名': item.userName,
|
||||||
|
'参加时间': item.takePartInTime,
|
||||||
|
'标段时间': item.lotName,
|
||||||
|
'未导入原因': item.errors
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const workbook = XLSX.utils.book_new()
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(exportData)
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, '错误记录')
|
||||||
|
const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'})
|
||||||
|
const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = '补录错误记录.xlsx'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
getSupplementLines() {
|
getSupplementLines() {
|
||||||
$.post('/platform/theRapyRecuperation/schoolUnionUserQuery/supplementLineList', {
|
$.post('/platform/theRapyRecuperation/schoolUnionUserQuery/supplementLineList', {
|
||||||
year: this.pageForm.year,
|
year: this.pageForm.year,
|
||||||
|
|||||||
Reference in New Issue
Block a user