Merge pull request #9283 from ulleo/dev

feat(X-Pack): 数据填报支持excel上传数据
This commit is contained in:
ulleo 2024-04-23 17:58:21 +08:00 committed by GitHub
commit c6b0b46b1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 693 additions and 102 deletions

View File

@ -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<String, Object> 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<String, Object> 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);
}
}

View File

@ -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<DatasourceRequest.TableFieldWithValue> 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<DatasourceRequest.TableFieldWithValue> fields) {
@ -175,12 +183,23 @@ public class MysqlExtDDLProvider extends DefaultExtDDLProvider {
return builder.toString();
}
private String convertInsertValueFields(List<DatasourceRequest.TableFieldWithValue> 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<DatasourceRequest.TableFieldWithValue> fields) {
String sql = "INSERT INTO `$TABLE_NAME$`($Column_Fields$) VALUES ($Value_Fields$);";
public String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> 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<DatasourceRequest.TableFieldWithValue> fields) {

View File

@ -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<String> 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<DatasourceRequest.TableFieldWithValue> 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<String, Object> data, boolean insert) throws Exception {
public List<String> updateOrInsertRowData(String formId, List<RowDataDatum> 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<String> results = new ArrayList<>();
List<ExtTableField> fields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
@ -308,28 +319,215 @@ public class DataFillDataService {
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
//实际的表内字段
Map<String, TableField> tableFieldMap = new HashMap<>();
List<DatasourceRequest.TableFieldWithValue> searchFields = new ArrayList<>();
List<DatasourceRequest.TableFieldWithValue> uniqueFields = new ArrayList<>();
Map<String, ExtTableField> 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<RowDataDatum> insertList = new ArrayList<>();
List<RowDataDatum> updateList = new ArrayList<>();
Map<String, ExtTableField> extTableFields = new HashMap<>();
Map<String, List<String>> 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<String, Object> 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<String, Object> 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<DatasourceRequest.TableFieldWithValue> fs = new ArrayList<>();
fs.add(uniqueField);
if (!insert) {
fs.add(pk);
}
datasourceRequest.setTableFieldWithValues(fs);
List<String[]> 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<String, Object> data = rowDataDatum.getData();
//只能一个个更新
String result = updateRowData(rowId, data, pkField, fields, tableFieldMap, dataFillForm, datasourceRequest, jdbcProvider, extDDLProvider);
results.add(result);
}
List<String> result = insertRowData(insertList, pkField, fields, tableFieldMap, dataFillForm, datasourceRequest, jdbcProvider, extDDLProvider);
if (result != null) {
results.addAll(result);
}
return results;
}
private List<String> insertRowData(List<RowDataDatum> insertList, DatasourceRequest.TableFieldWithValue pkField, List<ExtTableField> fields, Map<String, TableField> tableFieldMap, DataFillFormWithBLOBs dataFillForm, DatasourceRequest datasourceRequest, JdbcProvider jdbcProvider, ExtDDLProvider extDDLProvider) throws Exception {
if (CollectionUtils.isEmpty(insertList)) {
//批量插入
return null;
}
List<DatasourceRequest.TableFieldWithValue> baseSearchFields = null;
List<DatasourceRequest.TableFieldWithValue> allSearchFields = new ArrayList<>();
List<String> ids = new ArrayList<>();
for (RowDataDatum row : insertList) {
String rowId = row.getId();
ids.add(rowId);
Map<String, Object> data = row.getData();
List<DatasourceRequest.TableFieldWithValue> 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<String, Object> data, DatasourceRequest.TableFieldWithValue pkField, List<ExtTableField> fields, Map<String, TableField> tableFieldMap, DataFillFormWithBLOBs dataFillForm, DatasourceRequest datasourceRequest, JdbcProvider jdbcProvider, ExtDDLProvider extDDLProvider) throws Exception {
List<DatasourceRequest.TableFieldWithValue> 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<DatasourceRequest.TableFieldWithValue> fs = new ArrayList<>();
fs.add(uniqueField);
if (!insert) {
fs.add(pk);
}
datasourceRequest.setTableFieldWithValues(fs);
List<String[]> 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<Map<Integer, String>> {
private List<List<String>> data = new ArrayList<>();
private List<String> header = new ArrayList<>();
@Override
public void invokeHead(Map<Integer, CellData> 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<Integer, String> dataMap, AnalysisContext context) {
List<String> 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<ExtTableField> formFields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
List<ExtTableField> 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<ReadSheet> sheets = excelReader.excelExecutor().sheetList();
excelReader.read(sheets.get(0));
List<String> excelHeaders = listener.getHeader();
List<List<String>> excelData = listener.getData();
if (excelHeaders.size() != fields.size()) {
DataEaseException.throwException("模板字段个数不匹配");
}
List<RowDataDatum> dataList = new ArrayList<>();
for (List<String> excelDatum : excelData) {
Map<String, Object> 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<String> 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;
}
}

View File

@ -48,4 +48,10 @@ public class DataFillLogService {
dataFillCommitLogMapper.insertSelective(log);
}
public void saveCommitOperations(String operate, String formId, List<String> dataIds) {
for (String dataId : dataIds) {
saveCommitOperation(operate, formId, dataId);
}
}
}

View File

@ -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<List<String>> getExcelHead(String formId) {
List<List<String>> list = new ArrayList<>();
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId);
List<ExtTableField> fields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.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<String> head1 = List.of(name1 + required + example);
List<String> 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;
}
}

View File

@ -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<String, Object> data;
private boolean insert;
}

View File

@ -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',

View File

@ -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: '後台匯出中,可前往',

View File

@ -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: '后台导出中,可前往',

View File

@ -101,12 +101,38 @@
>
<template>
<div style="margin-bottom: 12px; height: 32px;">
<div style="margin-bottom: 12px; height: 32px; display: flex; flex-direction: row;">
<el-button
icon="el-icon-plus"
size="small"
@click="addData"
>{{ $t('data_fill.data.add_data') }}</el-button>
<el-button
icon="el-icon-download"
size="small"
@click="downloadTemplate"
>{{ $t('data_fill.data.download_template') }}</el-button>
<el-upload
:action="`${baseUrl}dataFilling/form/${param.id}/excel/upload`"
:multiple="false"
:show-file-list="false"
:file-list="fileList"
:data="{}"
accept=".xlsx"
:before-upload="beforeUpload"
:on-success="uploadSuccess"
:on-error="uploadFail"
name="file"
:headers="headers"
>
<el-button
style="margin-left: 10px"
icon="el-icon-upload2"
size="small"
:disabled="uploading"
>{{ $t('deDataset.upload_data') }}
</el-button>
</el-upload>
</div>
<div style="flex: 1">
<grid-table
@ -483,7 +509,7 @@
<script>
import {
deleteData,
deleteFormTasks, disableFormTasks, enableFormTasks,
deleteFormTasks, disableFormTasks, downloadTemplate, enableFormTasks,
searchCommitLogs,
searchFormTasks,
searchTable
@ -492,6 +518,14 @@ import GridTable from '@/components/gridTable/index.vue'
import { forEach, forIn, includes, filter, map } from 'lodash-es'
import EditFormData from '@/views/dataFilling/form/EditFormData.vue'
import CreateTask from '@/views/dataFilling/form/CreateTask.vue'
import i18n from '@/lang'
import { getToken, setToken } from '@/utils/auth'
import { $alert } from '@/utils/message'
import store from '@/store'
import Config from '@/settings'
const token = getToken()
const RefreshTokenKey = Config.RefreshTokenKey
export default {
name: 'ViewTable',
@ -509,6 +543,13 @@ export default {
},
data() {
return {
baseUrl: process.env.VUE_APP_BASE_API,
headers: {
Authorization: token,
'Accept-Language': i18n.locale.replace('_', '-')
},
fileList: [],
uploading: false,
operateName: '',
taskName: '',
showDrawer: false,
@ -620,6 +661,52 @@ export default {
this.initTable(this.param.id)
},
methods: {
beforeUpload() {
this.uploading = true
},
uploadFail(response, file, fileList) {
let myError = response.toString()
myError = myError.replace('Error: ', '')
if (myError.indexOf('AuthenticationException') >= 0) {
const message = i18n.t('login.tokenError')
$alert(
message,
() => {
store.dispatch('user/logout').then(() => {
location.reload()
})
},
{
confirmButtonText: i18n.t('login.re_login'),
showClose: false
}
)
return
}
const errorMessage = JSON.parse(myError).message
this.fileList = []
this.uploading = false
this.$message({
type: 'error',
message: errorMessage,
showClose: true
})
},
uploadSuccess(response, file, fileList) {
this.uploading = false
this.fileList = fileList
if (response.headers && response.headers[RefreshTokenKey]) {
const refreshToken = response.headers[RefreshTokenKey]
setToken(refreshToken)
store.dispatch('user/refreshToken', refreshToken)
}
this.initTable()
},
entryKey(type) {
if (type === 'record') {
this.$refs.search2.focus()
@ -819,6 +906,18 @@ export default {
this.drawerReadonly = false
this.createTitle = this.$t('data_fill.data.add_data')
},
downloadTemplate() {
downloadTemplate(this.param.id).then(res => {
const blob = new Blob([res])
const link = document.createElement('a')
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.download = 'test.xlsx' //
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
},
deleteRow(id) {
this.$confirm(
this.$t('data_fill.data.confirm_delete'),

View File

@ -55,6 +55,14 @@ export function deleteData(formId, rowId) {
loading: true
})
}
export function downloadTemplate(formId) {
return request({
url: 'dataFilling/form/' + formId + '/excel/template',
method: 'post',
loading: true,
responseType: 'blob'
})
}
export function getWithPrivileges(id) {
return request({
url: 'dataFilling/manage/form/' + id,

View File

@ -43,12 +43,12 @@ public class DefaultExtDDLProvider extends ExtDDLProvider {
}
@Override
public String deleteDataByIdSql(String table, DatasourceRequest.TableFieldWithValue pk) {
public String deleteDataByIdsSql(String table, List<DatasourceRequest.TableFieldWithValue> pks) {
return null;
}
@Override
public String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields) {
public String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields, int count) {
return null;
}

View File

@ -23,9 +23,9 @@ public abstract class ExtDDLProvider {
public abstract List<String> createTableIndexSql(String table, List<ExtIndexField> indexFields);
public abstract String deleteDataByIdSql(String table, DatasourceRequest.TableFieldWithValue pk);
public abstract String deleteDataByIdsSql(String table, List<DatasourceRequest.TableFieldWithValue> pks);
public abstract String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields);
public abstract String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields, int count);
public abstract String updateDataByIdSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields, DatasourceRequest.TableFieldWithValue pk);