diff --git a/core/backend/src/main/java/io/dataease/controller/datafill/DataFillController.java b/core/backend/src/main/java/io/dataease/controller/datafill/DataFillController.java index 5f3ec554e1..ded0b2acb1 100644 --- a/core/backend/src/main/java/io/dataease/controller/datafill/DataFillController.java +++ b/core/backend/src/main/java/io/dataease/controller/datafill/DataFillController.java @@ -1,7 +1,9 @@ package io.dataease.controller.datafill; +import com.alibaba.excel.EasyExcel; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; +import com.google.gson.Gson; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.PageUtils; import io.dataease.commons.utils.Pager; @@ -14,15 +16,18 @@ import io.dataease.dto.datafill.DataFillTaskDTO; import io.dataease.dto.datafill.DataFillUserTaskDTO; import io.dataease.plugins.common.base.domain.DataFillFormWithBLOBs; import io.dataease.plugins.common.dto.datafill.ExtTableField; -import io.dataease.service.datafill.DataFillDataService; -import io.dataease.service.datafill.DataFillLogService; -import io.dataease.service.datafill.DataFillService; -import io.dataease.service.datafill.DataFillTaskService; +import io.dataease.service.datafill.*; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import springfox.documentation.annotations.ApiIgnore; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -103,13 +108,13 @@ public class DataFillController { @ApiIgnore @PostMapping("/form/{formId}/rowData/save") public String newRowData(@PathVariable String formId, @RequestBody Map data) throws Exception { - return dataFillDataService.updateRowData(formId, null, data, true); + return dataFillDataService.updateOrInsertRowData(formId, Collections.singletonList(new RowDataDatum().setData(data))).get(0); } @ApiIgnore @PostMapping("/form/{formId}/rowData/save/{id}") public String updateRowData(@PathVariable String formId, @PathVariable String id, @RequestBody Map data) throws Exception { - return dataFillDataService.updateRowData(formId, id, data, false); + return dataFillDataService.updateOrInsertRowData(formId, Collections.singletonList(new RowDataDatum().setId(id).setData(data))).get(0); } @@ -180,4 +185,39 @@ public class DataFillController { dataFillService.fillFormData(taskId, data); } + @ApiIgnore + @PostMapping("/form/{formId}/excel/template") + public void userFillData(@PathVariable String formId, HttpServletResponse response) throws Exception { + try { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + // 这里URLEncoder.encode可以防止中文乱码 + String fileName = URLEncoder.encode("template", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + // 这里需要设置不关闭流 + EasyExcel.write(response.getOutputStream()) + .head(dataFillService.getExcelHead(formId)) + .autoCloseStream(Boolean.FALSE) + .sheet("模板") + .doWrite(new ArrayList()); + } catch (Exception e) { + // 重置response + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + + ResultHolder resultHolder = ResultHolder.error("get template excel error", e); + response.getWriter().println(new Gson().toJson(resultHolder)); + } + } + + @ApiIgnore + @PostMapping("/form/{formId}/excel/upload") + public void excelUpload(@RequestParam("file") MultipartFile file, @PathVariable String formId) throws Exception { + String filename = file.getOriginalFilename(); + System.out.println(filename); + System.out.println(formId); + dataFillDataService.importExcelData(file, formId); + } + } diff --git a/core/backend/src/main/java/io/dataease/provider/ext/MysqlExtDDLProvider.java b/core/backend/src/main/java/io/dataease/provider/ext/MysqlExtDDLProvider.java index c87d114c0b..14d852a555 100644 --- a/core/backend/src/main/java/io/dataease/provider/ext/MysqlExtDDLProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/ext/MysqlExtDDLProvider.java @@ -143,10 +143,18 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider { } @Override - public String deleteDataByIdSql(String table, DatasourceRequest.TableFieldWithValue pk) { - String deleteSql = "DELETE FROM `$TABLE_NAME$` WHERE `$PRIMARY_KEY$` = ?;"; + public String deleteDataByIdsSql(String table, List pks) { + String deleteSql = "DELETE FROM `$TABLE_NAME$` WHERE `$PRIMARY_KEY$` IN ($PRIMARY_KEY_GROUP$);"; + StringBuilder groupStr = new StringBuilder(); + for (int i = 0; i < pks.size(); i++) { + groupStr.append("?"); + if (i < pks.size() - 1) { + groupStr.append(", "); + } + } return deleteSql.replace("$TABLE_NAME$", table) - .replace("$PRIMARY_KEY$", pk.getFiledName()); + .replace("$PRIMARY_KEY$", pks.get(0).getFiledName()) + .replace("$PRIMARY_KEY_GROUP$", groupStr); } private String convertFields(List fields) { @@ -175,12 +183,23 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider { return builder.toString(); } + private String convertInsertValueFields(List fields, int count) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < count; i++) { + builder.append("(").append(convertValueFields(fields)).append(")"); + if (i < count - 1) { + builder.append(", "); + } + } + return builder.toString(); + } + @Override - public String insertDataSql(String tableName, List fields) { - String sql = "INSERT INTO `$TABLE_NAME$`($Column_Fields$) VALUES ($Value_Fields$);"; + public String insertDataSql(String tableName, List fields, int count) { + String sql = "INSERT INTO `$TABLE_NAME$`($Column_Fields$) VALUES $Value_Fields$;"; return sql.replace("$TABLE_NAME$", tableName) .replace("$Column_Fields$", convertFields(fields)) - .replace("$Value_Fields$", convertValueFields(fields)); + .replace("$Value_Fields$", convertInsertValueFields(fields, count)); } private String convertUpdateFields(List fields) { diff --git a/core/backend/src/main/java/io/dataease/service/datafill/DataFillDataService.java b/core/backend/src/main/java/io/dataease/service/datafill/DataFillDataService.java index 25635ea3ed..e19a4c9a8f 100644 --- a/core/backend/src/main/java/io/dataease/service/datafill/DataFillDataService.java +++ b/core/backend/src/main/java/io/dataease/service/datafill/DataFillDataService.java @@ -1,5 +1,11 @@ package io.dataease.service.datafill; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.read.metadata.ReadSheet; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import io.dataease.auth.service.AuthUserService; @@ -23,6 +29,7 @@ import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.provider.datasource.JdbcProvider; import io.dataease.service.datasource.DatasourceService; import io.dataease.service.sys.SysAuthService; +import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -30,14 +37,13 @@ import org.pentaho.di.core.util.UUIDUtil; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.math.BigDecimal; +import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Service @@ -240,6 +246,10 @@ public class DataFillDataService { public void deleteRowData(String formId, String id) throws Exception { + deleteRowData(formId, List.of(id)); + } + + public void deleteRowData(String formId, List ids) throws Exception { DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId); if (StringUtils.equals(dataFillForm.getNodeType(), "folder")) { @@ -262,37 +272,38 @@ public class DataFillDataService { } TableField key = tableFields.get(0); - DatasourceRequest.TableFieldWithValue pk = new DatasourceRequest.TableFieldWithValue() - .setValue(id) //todo 有可能是数字 - .setFiledName(key.getFieldName()) - .setTypeName(key.getFieldType()) - .setType(key.getType()); + List pks = new ArrayList<>(); + for (String id : ids) { + DatasourceRequest.TableFieldWithValue pk = new DatasourceRequest.TableFieldWithValue() + .setValue(id) //todo 有可能是数字 + .setFiledName(key.getFieldName()) + .setTypeName(key.getFieldType()) + .setType(key.getType()); + pks.add(pk); + } - String deleteSql = extDDLProvider.deleteDataByIdSql(dataFillForm.getTableName(), pk); + String deleteSql = extDDLProvider.deleteDataByIdsSql(dataFillForm.getTableName(), pks); datasourceRequest.setQuery(deleteSql); - datasourceRequest.setTableFieldWithValues(List.of(pk)); + datasourceRequest.setTableFieldWithValues(pks); JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class); jdbcProvider.execWithPreparedStatement(datasourceRequest); - dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_DELETE, dataFillForm.getId(), id); + for (String id : ids) { + dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_DELETE, dataFillForm.getId(), id); + } } - public String updateRowData(String formId, String rowId, Map data, boolean insert) throws Exception { + public List updateOrInsertRowData(String formId, List datumList) throws Exception { if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) { DataEaseException.throwException("invalid"); } - if (rowId == null) { - insert = true; - //先默认主键是uuid - rowId = UUIDUtil.getUUIDAsString(); - } - DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId); + List results = new ArrayList<>(); List fields = gson.fromJson(dataFillForm.getForms(), new TypeToken>() { }.getType()); @@ -308,28 +319,215 @@ public class DataFillDataService { List tableFields = datasourceProvider.getTableFields(datasourceRequest); + //实际的表内字段 Map tableFieldMap = new HashMap<>(); - - List searchFields = new ArrayList<>(); - List uniqueFields = new ArrayList<>(); - Map extTableFields = new HashMap<>(); - - DatasourceRequest.TableFieldWithValue pk = null; + DatasourceRequest.TableFieldWithValue pkField = null; for (TableField tableField : tableFields) { if (tableField.isPrimaryKey()) { - pk = new DatasourceRequest.TableFieldWithValue() - .setValue(rowId) + pkField = new DatasourceRequest.TableFieldWithValue() .setFiledName(tableField.getFieldName()) .setTypeName(tableField.getFieldType()) .setType(tableField.getType()); - if (insert) { - searchFields.add(pk); - } continue; } tableFieldMap.put(tableField.getFieldName(), tableField); } + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + + Map extTableFields = new HashMap<>(); + + Map> uniqueMap = new HashMap<>(); + + for (RowDataDatum row : datumList) { + String rowId = row.getId(); + if (rowId == null) { + //默认主键是uuid + rowId = UUIDUtil.getUUIDAsString(); + + //再设置回去 + row.setInsert(true); + row.setId(rowId); + } + if (row.isInsert()) { + insertList.add(row); + } else { + updateList.add(row); + } + + Map data = row.getData(); + for (ExtTableField field : fields) { + String name = field.getSettings().getMapping().getColumnName(); + + if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) { + String name1 = field.getSettings().getMapping().getColumnName1(); + String name2 = field.getSettings().getMapping().getColumnName2(); + if (tableFieldMap.containsKey(name1)) { + extTableFields.put(name1, field); + } + if (tableFieldMap.containsKey(name2)) { + extTableFields.put(name2, field); + } + } else { + extTableFields.put(name, field); + } + + if (StringUtils.equalsIgnoreCase(field.getType(), "input")) { //input框支持unique + if (field.getSettings().isUnique() && data.get(name) != null) { + uniqueMap.putIfAbsent(name, new ArrayList<>()); + if (uniqueMap.get(name).contains(data.get(name).toString())) { + //提前判断录入的数据有没有unique字段重复的 + DataEaseException.throwException(extTableFields.get(name).getSettings().getName() + " 值不能重复"); + } else { + uniqueMap.get(name).add(data.get(name).toString()); + } + } + } + } + } + + //进入数据库查询是否有重复 + for (RowDataDatum row : datumList) { + boolean insert = row.isInsert(); + String rowId = row.getId(); + DatasourceRequest.TableFieldWithValue pk = gson.fromJson(gson.toJson(pkField), DatasourceRequest.TableFieldWithValue.class).setValue(rowId); + Map data = row.getData(); + //一条条去判断 + for (ExtTableField field : fields) { + String name = field.getSettings().getMapping().getColumnName(); + if (StringUtils.equalsIgnoreCase(field.getType(), "input")) { //input框支持unique + if (field.getSettings().isUnique() && data.get(name) != null) { + DatasourceRequest.TableFieldWithValue uniqueField = new DatasourceRequest.TableFieldWithValue() + .setValue(data.get(name)) + .setFiledName(name) + .setTypeName(tableFieldMap.get(name).getFieldType()) + .setType(tableFieldMap.get(name).getType()); + + String sql = extDDLProvider.checkUniqueValueSql(dataFillForm.getTableName(), uniqueField, insert ? null : pk); + datasourceRequest.setQuery(sql); + List fs = new ArrayList<>(); + fs.add(uniqueField); + if (!insert) { + fs.add(pk); + } + datasourceRequest.setTableFieldWithValues(fs); + List countData = datasourceProvider.getData(datasourceRequest); + long count = NumberUtils.toLong(countData.get(0)[0]); + + if (count > 0) { + DataEaseException.throwException(extTableFields.get(uniqueField.getFiledName()).getSettings().getName() + " 值不能重复"); + } + + } + } + } + } + + JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class); + + for (RowDataDatum rowDataDatum : updateList) { + String rowId = rowDataDatum.getId(); + Map data = rowDataDatum.getData(); + + //只能一个个更新 + String result = updateRowData(rowId, data, pkField, fields, tableFieldMap, dataFillForm, datasourceRequest, jdbcProvider, extDDLProvider); + results.add(result); + } + + List result = insertRowData(insertList, pkField, fields, tableFieldMap, dataFillForm, datasourceRequest, jdbcProvider, extDDLProvider); + + if (result != null) { + results.addAll(result); + } + return results; + } + + private List insertRowData(List insertList, DatasourceRequest.TableFieldWithValue pkField, List fields, Map tableFieldMap, DataFillFormWithBLOBs dataFillForm, DatasourceRequest datasourceRequest, JdbcProvider jdbcProvider, ExtDDLProvider extDDLProvider) throws Exception { + if (CollectionUtils.isEmpty(insertList)) { + //批量插入 + return null; + } + List baseSearchFields = null; + List allSearchFields = new ArrayList<>(); + + List ids = new ArrayList<>(); + for (RowDataDatum row : insertList) { + String rowId = row.getId(); + ids.add(rowId); + Map data = row.getData(); + + List searchFields = new ArrayList<>(); + + DatasourceRequest.TableFieldWithValue pk = gson.fromJson(gson.toJson(pkField), DatasourceRequest.TableFieldWithValue.class).setValue(rowId); + searchFields.add(pk); + + for (ExtTableField field : fields) { + if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) { + String name1 = field.getSettings().getMapping().getColumnName1(); + String name2 = field.getSettings().getMapping().getColumnName2(); + if (tableFieldMap.containsKey(name1)) { + DatasourceRequest.TableFieldWithValue value1 = new DatasourceRequest.TableFieldWithValue() + .setValue(data.get(name1) != null ? new java.sql.Date((long) data.get(name1)) : null) + .setFiledName(name1) + .setTypeName(tableFieldMap.get(name1).getFieldType()) + .setType(tableFieldMap.get(name1).getType()); + searchFields.add(value1); + + } + if (tableFieldMap.containsKey(name2)) { + DatasourceRequest.TableFieldWithValue value2 = new DatasourceRequest.TableFieldWithValue() + .setValue(data.get(name2) != null ? new java.sql.Date((long) data.get(name2)) : null) + .setFiledName(name2) + .setTypeName(tableFieldMap.get(name2).getFieldType()) + .setType(tableFieldMap.get(name2).getType()); + searchFields.add(value2); + + } + } else { + String name = field.getSettings().getMapping().getColumnName(); + if (tableFieldMap.containsKey(name)) { + DatasourceRequest.TableFieldWithValue value = new DatasourceRequest.TableFieldWithValue() + .setValue(data.get(name)) + .setFiledName(name) + .setTypeName(tableFieldMap.get(name).getFieldType()) + .setType(tableFieldMap.get(name).getType()); + + if (StringUtils.equalsIgnoreCase(field.getType(), "date")) { + value.setValue(data.get(name) != null ? new java.sql.Date((long) data.get(name)) : null); + } + searchFields.add(value); + + } + } + } + + if (baseSearchFields == null) { + baseSearchFields = searchFields; + } + allSearchFields.addAll(searchFields); + + } + + String sql = extDDLProvider.insertDataSql(dataFillForm.getTableName(), baseSearchFields, insertList.size()); + datasourceRequest.setQuery(sql); + + + datasourceRequest.setTableFieldWithValues(allSearchFields); + + + int result = jdbcProvider.execWithPreparedStatement(datasourceRequest); + + dataFillLogService.saveCommitOperations(DataFillLogService.COMMIT_OPERATE_INSERT, dataFillForm.getId(), ids); + + return ids; + } + + private String updateRowData(String rowId, Map data, DatasourceRequest.TableFieldWithValue pkField, List fields, Map tableFieldMap, DataFillFormWithBLOBs dataFillForm, DatasourceRequest datasourceRequest, JdbcProvider jdbcProvider, ExtDDLProvider extDDLProvider) throws Exception { + List searchFields = new ArrayList<>(); + + DatasourceRequest.TableFieldWithValue pk = gson.fromJson(gson.toJson(pkField), DatasourceRequest.TableFieldWithValue.class).setValue(rowId); + for (ExtTableField field : fields) { if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) { String name1 = field.getSettings().getMapping().getColumnName1(); @@ -341,7 +539,6 @@ public class DataFillDataService { .setTypeName(tableFieldMap.get(name1).getFieldType()) .setType(tableFieldMap.get(name1).getType()); searchFields.add(value1); - extTableFields.put(name1, field); } if (tableFieldMap.containsKey(name2)) { DatasourceRequest.TableFieldWithValue value2 = new DatasourceRequest.TableFieldWithValue() @@ -350,7 +547,6 @@ public class DataFillDataService { .setTypeName(tableFieldMap.get(name2).getFieldType()) .setType(tableFieldMap.get(name2).getType()); searchFields.add(value2); - extTableFields.put(name2, field); } } else { String name = field.getSettings().getMapping().getColumnName(); @@ -366,67 +562,214 @@ public class DataFillDataService { } searchFields.add(value); - extTableFields.put(name, field); - - // 关于unique的字段判断 - if (field.getSettings().isUnique() && data.get(name) != null) { - - uniqueFields.add(value); - } } } } - if (CollectionUtils.isNotEmpty(uniqueFields)) { - for (DatasourceRequest.TableFieldWithValue uniqueField : uniqueFields) { - - String sql = extDDLProvider.checkUniqueValueSql(dataFillForm.getTableName(), uniqueField, insert ? null : pk); - datasourceRequest.setQuery(sql); - List fs = new ArrayList<>(); - fs.add(uniqueField); - if (!insert) { - fs.add(pk); - } - datasourceRequest.setTableFieldWithValues(fs); - List countData = datasourceProvider.getData(datasourceRequest); - long count = NumberUtils.toLong(countData.get(0)[0]); - - if (count > 0) { - DataEaseException.throwException(extTableFields.get(uniqueField.getFiledName()).getSettings().getName() + " 值不能重复"); - } - } - } - - String sql = insert ? - extDDLProvider.insertDataSql(dataFillForm.getTableName(), searchFields) : - extDDLProvider.updateDataByIdSql(dataFillForm.getTableName(), searchFields, pk); + String sql = extDDLProvider.updateDataByIdSql(dataFillForm.getTableName(), searchFields, pk); datasourceRequest.setQuery(sql); boolean skip = false; - if (!insert && CollectionUtils.isEmpty(searchFields)) { + if (CollectionUtils.isEmpty(searchFields)) { //DataEaseException.throwException("没有修改"); skip = true; } - JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class); - // 主键在最后传进去 - if (!insert) { - searchFields.add(pk); - } + searchFields.add(pk); datasourceRequest.setTableFieldWithValues(searchFields); if (!skip) { int result = jdbcProvider.execWithPreparedStatement(datasourceRequest); } - if (insert) { - dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_INSERT, dataFillForm.getId(), rowId); - } else { - dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_UPDATE, dataFillForm.getId(), rowId); - } + dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_UPDATE, dataFillForm.getId(), rowId); return rowId; } + @Data + public static class ExcelDataListener extends AnalysisEventListener> { + private List> data = new ArrayList<>(); + private List header = new ArrayList<>(); + + + @Override + public void invokeHead(Map headMap, AnalysisContext context) { + super.invokeHead(headMap, context); + for (Integer key : headMap.keySet()) { + CellData cellData = headMap.get(key); + String value = cellData.getStringValue(); + if (StringUtils.isEmpty(value)) { + value = "none_" + key; + } + header.add(value); + } + } + + @Override + public void invoke(Map dataMap, AnalysisContext context) { + List line = new ArrayList<>(); + for (Integer key : dataMap.keySet()) { + String value = dataMap.get(key); + if (StringUtils.isEmpty(value)) { + value = ""; + } + line.add(value); + } + ; + int size = line.size(); + if (size < header.size()) { + for (int i = 0; i < header.size() - size; i++) { + line.add(""); + } + } + data.add(line); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + } + + public void clear() { + data.clear(); + header.clear(); + } + } + + public void importExcelData(MultipartFile file, String formId) throws Exception { + if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) { + DataEaseException.throwException("invalid"); + } + + DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId); + + List formFields = gson.fromJson(dataFillForm.getForms(), new TypeToken>() { + }.getType()); + + List fields = new ArrayList<>(); + for (ExtTableField field : formFields) { + if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) { + ExtTableField start = gson.fromJson(gson.toJson(field), ExtTableField.class); + start.getSettings().getMapping().setColumnName(start.getSettings().getMapping().getColumnName1()); + fields.add(start); + + ExtTableField end = gson.fromJson(gson.toJson(field), ExtTableField.class); + end.getSettings().getMapping().setColumnName(end.getSettings().getMapping().getColumnName2()); + fields.add(end); + } else { + fields.add(field); + } + } + + ExcelDataListener listener = new ExcelDataListener(); + ExcelReader excelReader = EasyExcel.read(file.getInputStream(), listener).build(); + List sheets = excelReader.excelExecutor().sheetList(); + excelReader.read(sheets.get(0)); + + List excelHeaders = listener.getHeader(); + List> excelData = listener.getData(); + + if (excelHeaders.size() != fields.size()) { + DataEaseException.throwException("模板字段个数不匹配"); + } + + List dataList = new ArrayList<>(); + for (List excelDatum : excelData) { + Map rowData = new HashMap<>(); + for (int i = 0; i < fields.size(); i++) { + ExtTableField field = fields.get(i); + + String excelRowData = null; + if (i < excelDatum.size()) { + excelRowData = excelDatum.get(i); + } + if (StringUtils.isBlank(excelRowData)) { //处理必填,这里如果是字符串格式的,强制改成空字符串防止报错,其他类型都直接报错 + if (field.getSettings().isRequired()) { + if (field.getSettings().getMapping().getType().equals(ExtTableField.BaseType.nvarchar) || + field.getSettings().getMapping().getType().equals(ExtTableField.BaseType.text)) { + excelRowData = StringUtils.EMPTY; + } else { + DataEaseException.throwException(field.getSettings().getName() + "不能为空"); + } + } + } + if (excelRowData == null) { + continue; + } + try { + switch (field.getSettings().getMapping().getType()) { + case decimal: + BigDecimal decimalValue = new BigDecimal(excelRowData); + rowData.put(field.getSettings().getMapping().getColumnName(), decimalValue); + break; + case number: + BigDecimal longValue = new BigDecimal(excelRowData); + rowData.put(field.getSettings().getMapping().getColumnName(), longValue.longValue()); + break; + case datetime: + Date date = getDate(field, excelRowData); + rowData.put(field.getSettings().getMapping().getColumnName(), date.getTime()); + break; + default: + if (StringUtils.equalsIgnoreCase(field.getType(), "checkbox") || + StringUtils.equalsIgnoreCase(field.getType(), "select") && field.getSettings().isMultiple()) { + List list = new ArrayList<>(); + String[] strArr = excelRowData.split(","); + for (String str : strArr) { + if (StringUtils.isNotBlank(str)) { + list.add(str); + } + } + if (field.getSettings().isRequired()) { + if (CollectionUtils.isEmpty(list)) { + DataEaseException.throwException(field.getSettings().getName() + "不能为空"); + } + } + rowData.put(field.getSettings().getMapping().getColumnName(), gson.toJson(list)); + } else { + rowData.put(field.getSettings().getMapping().getColumnName(), excelRowData); + } + } + + } catch (DataEaseException e) { + DataEaseException.throwException(e.getMessage()); + } catch (Exception e) { + DataEaseException.throwException(field.getSettings().getName() + "格式错误"); + } + } + + if (rowData.isEmpty()) { + continue; + } + + dataList.add(new RowDataDatum().setData(rowData)); + } + + if (CollectionUtils.isNotEmpty(dataList)) { + + updateOrInsertRowData(formId, dataList); + + } + + } + + private static Date getDate(ExtTableField field, String excelRowData) throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //默认会拿到这种格式的 + if (field.getSettings().isEnableTime()) { + sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + } + Date date = null; + try { + date = sdf.parse(excelRowData); + } catch (ParseException e) { + sdf = new SimpleDateFormat("yyyy/MM/dd"); //以防万一也加上这种 + if (field.getSettings().isEnableTime()) { + sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + } + date = sdf.parse(excelRowData); + } + return date; + } + } diff --git a/core/backend/src/main/java/io/dataease/service/datafill/DataFillLogService.java b/core/backend/src/main/java/io/dataease/service/datafill/DataFillLogService.java index f14db1fe68..1bc324af3c 100644 --- a/core/backend/src/main/java/io/dataease/service/datafill/DataFillLogService.java +++ b/core/backend/src/main/java/io/dataease/service/datafill/DataFillLogService.java @@ -48,4 +48,10 @@ public class DataFillLogService { dataFillCommitLogMapper.insertSelective(log); } + + public void saveCommitOperations(String operate, String formId, List dataIds) { + for (String dataId : dataIds) { + saveCommitOperation(operate, formId, dataId); + } + } } diff --git a/core/backend/src/main/java/io/dataease/service/datafill/DataFillService.java b/core/backend/src/main/java/io/dataease/service/datafill/DataFillService.java index 07afcad184..00fc50be02 100644 --- a/core/backend/src/main/java/io/dataease/service/datafill/DataFillService.java +++ b/core/backend/src/main/java/io/dataease/service/datafill/DataFillService.java @@ -39,10 +39,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Service @@ -344,7 +341,7 @@ public class DataFillService { } } - rowId = dataFillDataService.updateRowData(formId, rowId, data, rowId == null); + rowId = dataFillDataService.updateOrInsertRowData(formId, Collections.singletonList(new RowDataDatum().setId(rowId).setData(data))).get(0); task.setValueId(rowId); task.setFinishTime(new Date()); @@ -352,4 +349,59 @@ public class DataFillService { dataFillUserTaskMapper.updateByPrimaryKeySelective(task); } + + public List> getExcelHead(String formId) { + List> list = new ArrayList<>(); + + DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId); + List fields = gson.fromJson(dataFillForm.getForms(), new TypeToken>() { + }.getType()); + for (ExtTableField formField : fields) { + String name = formField.getSettings().getName(); + String required = formField.getSettings().isRequired() ? "\n必填" : ""; + + if (StringUtils.equalsIgnoreCase(formField.getType(), "dateRange")) { + String name1 = formField.getSettings().getName() + "(开始时间) "; + String name2 = formField.getSettings().getName() + "(结束时间) "; + String example = "\n(日期格式: yyyy/MM/dd" + (formField.getSettings().isEnableTime() ? " HH:mm:ss" : "") + ")"; + + List head1 = List.of(name1 + required + example); + List head2 = List.of(name2 + required + example); + + list.add(head1); + list.add(head2); + } else { + String example = ""; + switch (formField.getSettings().getMapping().getType()) { + case datetime: + example = "\n(日期格式: yyyy/MM/dd" + (formField.getSettings().isEnableTime() ? " HH:mm:ss" : "") + ")"; + list.add(List.of(name + required + example)); + break; + case number: + example = "\n(整形数字)"; + list.add(List.of(name + required + example)); + break; + case decimal: + example = "\n(小数数字)"; + list.add(List.of(name + required + example)); + break; + case text: + case nvarchar: + if (StringUtils.equalsIgnoreCase("select", formField.getType()) || StringUtils.equalsIgnoreCase("checkbox", formField.getType())) { + example = "\n(多个值使用分号\";\"分割)"; + } else if (StringUtils.equalsIgnoreCase("email", formField.getSettings().getInputType())) { + example = "\n(邮箱格式)"; + } else if (StringUtils.equalsIgnoreCase("phone", formField.getSettings().getInputType())) { + example = "\n(手机号格式)"; + } + list.add(List.of(name + required + example)); + break; + } + } + } + + return list; + + } + } diff --git a/core/backend/src/main/java/io/dataease/service/datafill/RowDataDatum.java b/core/backend/src/main/java/io/dataease/service/datafill/RowDataDatum.java new file mode 100644 index 0000000000..dcded27f71 --- /dev/null +++ b/core/backend/src/main/java/io/dataease/service/datafill/RowDataDatum.java @@ -0,0 +1,21 @@ +package io.dataease.service.datafill; + + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Map; + +@Data +@Accessors(chain = true) +public class RowDataDatum implements Serializable { + + private static final long serialVersionUID = -2838784450721979776L; + + private String id; + + private Map data; + + private boolean insert; +} diff --git a/core/frontend/src/lang/en.js b/core/frontend/src/lang/en.js index 5317b47621..6a90faf5d7 100644 --- a/core/frontend/src/lang/en.js +++ b/core/frontend/src/lang/en.js @@ -538,7 +538,7 @@ export default { confirm: 'Confirm' }, deDataset: { - goto:', go to ', + goto: ', go to ', search_by_name: 'Search by name', new_folder: 'New Folder', search_fields: 'Search Fields', @@ -680,6 +680,7 @@ export default { data: { confirm_delete: 'Confirm delete?', add_data: 'Add Data', + download_template: 'Download Template', insert_data: 'Insert Data', update_data: 'Update Data', delete_data: 'Delete Data', @@ -3213,7 +3214,7 @@ export default { onlinemap: 'Online map', empty_desc: 'No map key' }, - data_export:{ + data_export: { export_center: 'Data Export Center', export_info: 'View progress and download', exporting: 'Exporting in the background, you can go to', diff --git a/core/frontend/src/lang/tw.js b/core/frontend/src/lang/tw.js index a5d9de64c9..a6dc7998df 100644 --- a/core/frontend/src/lang/tw.js +++ b/core/frontend/src/lang/tw.js @@ -538,7 +538,7 @@ export default { confirm: '確 定' }, deDataset: { - goto:', 前往 ', + goto: ', 前往 ', search_by_name: '通過名稱搜索', new_folder: '新建資料夾', search_fields: '搜索欄位', @@ -680,6 +680,7 @@ export default { data: { confirm_delete: '確認刪除?', add_data: '添加數據', + download_template: '下載模板', insert_data: '插入數據', update_data: '更新數據', delete_data: '刪除數據', @@ -3205,7 +3206,7 @@ export default { onlinemap: '在線地圖', empty_desc: '暫無在線地圖key' }, - data_export:{ + data_export: { export_center: '資料匯出中心', export_info: '查看進度,進行下載', exporting: '後台匯出中,可前往', diff --git a/core/frontend/src/lang/zh.js b/core/frontend/src/lang/zh.js index 70669a4217..a935edb5e9 100644 --- a/core/frontend/src/lang/zh.js +++ b/core/frontend/src/lang/zh.js @@ -678,6 +678,7 @@ export default { data: { confirm_delete: '确认删除?', add_data: '添加数据', + download_template: '下载模板', insert_data: '插入数据', update_data: '更新数据', delete_data: '删除数据', @@ -1806,7 +1807,7 @@ export default { sub_axis_label: '副轴标签' }, dataset: { - goto:', 前往 ', + goto: ', 前往 ', scope_edit: '仅编辑时生效', scope_all: '数据集预览时全局生效', spend_time: '耗时', @@ -3206,7 +3207,7 @@ export default { onlinemap: '在线地图', empty_desc: '暂无在线地图key' }, - data_export:{ + data_export: { export_center: '数据导出中心', export_info: '查看进度,进行下载', exporting: '后台导出中,可前往', diff --git a/core/frontend/src/views/dataFilling/form/ViewTable.vue b/core/frontend/src/views/dataFilling/form/ViewTable.vue index 094a36e493..f73571e0ff 100644 --- a/core/frontend/src/views/dataFilling/form/ViewTable.vue +++ b/core/frontend/src/views/dataFilling/form/ViewTable.vue @@ -101,12 +101,38 @@ >