mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-25 07:46:40 +08:00
bugfix
This commit is contained in:
10
pom.xml
10
pom.xml
@@ -51,6 +51,16 @@
|
|||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
<version>5.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<version>5.2.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
|||||||
411
src/main/java/cn/lihongjie/coal/common/ExcelUtils.java
Normal file
411
src/main/java/cn/lihongjie/coal/common/ExcelUtils.java
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
package cn.lihongjie.coal.common;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
|
||||||
|
import io.vavr.Function2;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.poi.ss.formula.functions.T;
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
|
import org.apache.poi.ss.util.CellReference;
|
||||||
|
import org.apache.poi.xssf.usermodel.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class ExcelUtils {
|
||||||
|
|
||||||
|
public static String getCode(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof String) {
|
||||||
|
return Splitter.on("-")
|
||||||
|
.trimResults()
|
||||||
|
.omitEmptyStrings()
|
||||||
|
.splitToList((String) value)
|
||||||
|
.get(0);
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDate getLocalDate(Object value) {
|
||||||
|
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof LocalDate) {
|
||||||
|
return (LocalDate) value;
|
||||||
|
}
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return ((Date) value).toInstant().atZone(TimeZone.getDefault().toZoneId()).toLocalDate();
|
||||||
|
}
|
||||||
|
if (value instanceof LocalDateTime) {
|
||||||
|
return ((LocalDateTime) value).toLocalDate();
|
||||||
|
}
|
||||||
|
if (value instanceof Number) {
|
||||||
|
return LocalDate.ofEpochDay(((Number) value).longValue());
|
||||||
|
}
|
||||||
|
if (value instanceof String) {
|
||||||
|
return LocalDate.parse((String) value);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> readFirstSheetToObjectList(
|
||||||
|
InputStream inputStream,
|
||||||
|
Supplier<T> objectCreator,
|
||||||
|
CellValueToObjectSetter<T> valueSetter) {
|
||||||
|
ArrayList<T> ans = new ArrayList<>();
|
||||||
|
readFirstSheet(
|
||||||
|
inputStream,
|
||||||
|
row -> {
|
||||||
|
return objectCreator.get();
|
||||||
|
},
|
||||||
|
(headerCell, dataCell, object, value) -> {
|
||||||
|
valueSetter.set(headerCell.getStringCellValue(), (T) object, value);
|
||||||
|
});
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void readFirstSheet(
|
||||||
|
InputStream inputStream,
|
||||||
|
Function<Row, Object> rowMapper,
|
||||||
|
CellValueHandler cellValueHandler) {
|
||||||
|
|
||||||
|
try (Workbook workbook = WorkbookFactory.create(inputStream)) {
|
||||||
|
Sheet sheet = workbook.getSheetAt(0);
|
||||||
|
Row headerRow = sheet.getRow(0);
|
||||||
|
|
||||||
|
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
|
||||||
|
Row row = sheet.getRow(i);
|
||||||
|
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object object = rowMapper.apply(row);
|
||||||
|
|
||||||
|
for (int j = 0; j < headerRow.getLastCellNum(); j++) {
|
||||||
|
Cell cell = row.getCell(j);
|
||||||
|
if (cell == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object value = null;
|
||||||
|
switch (cell.getCellType()) {
|
||||||
|
case STRING:
|
||||||
|
{
|
||||||
|
value = cell.getStringCellValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NUMERIC:
|
||||||
|
{
|
||||||
|
|
||||||
|
if (DateUtil.isCellDateFormatted(cell)) {
|
||||||
|
value = cell.getDateCellValue();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
value = cell.getNumericCellValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BOOLEAN:
|
||||||
|
{
|
||||||
|
value = cell.getBooleanCellValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FORMULA:
|
||||||
|
{
|
||||||
|
switch (cell.getCachedFormulaResultType()) {
|
||||||
|
case STRING:
|
||||||
|
{
|
||||||
|
value = cell.getStringCellValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NUMERIC:
|
||||||
|
{
|
||||||
|
value = cell.getNumericCellValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BOOLEAN:
|
||||||
|
{
|
||||||
|
value = cell.getBooleanCellValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BLANK, ERROR, _NONE:
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BLANK, ERROR, _NONE:
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cellValueHandler.handle(headerRow.getCell(j), cell, object, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void genSingleSheetToHttp(
|
||||||
|
String wbName,
|
||||||
|
List<String> headers,
|
||||||
|
HeaderCellCustomizer headerCellCustomizer,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
genSingleSheetToHttp(
|
||||||
|
wbName,
|
||||||
|
null,
|
||||||
|
headers,
|
||||||
|
headerCellCustomizer,
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void genSingleSheetToHttp(
|
||||||
|
String wbName,
|
||||||
|
String sheetName,
|
||||||
|
List<String> headers,
|
||||||
|
HeaderCellCustomizer headerCellCustomizer,
|
||||||
|
Iterable<?> data,
|
||||||
|
Function2<String, Object, Object> valueGetter,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
genSingleSheet(
|
||||||
|
wbName,
|
||||||
|
sheetName,
|
||||||
|
headers,
|
||||||
|
headerCellCustomizer,
|
||||||
|
data,
|
||||||
|
valueGetter,
|
||||||
|
WorkbookConsumer.httpResponseConsumer(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void genSingleSheet(
|
||||||
|
String wbName,
|
||||||
|
String sheetName,
|
||||||
|
List<String> headers,
|
||||||
|
HeaderCellCustomizer headerCellCustomizer,
|
||||||
|
Iterable<?> data,
|
||||||
|
Function2<String, Object, Object> valueGetter,
|
||||||
|
WorkbookConsumer workbookConsumer) {
|
||||||
|
genSingleSheet(
|
||||||
|
wbName,
|
||||||
|
sheetName,
|
||||||
|
headers,
|
||||||
|
headerCellCustomizer,
|
||||||
|
data,
|
||||||
|
valueGetter,
|
||||||
|
null,
|
||||||
|
workbookConsumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void genSingleSheet(
|
||||||
|
String wbName,
|
||||||
|
String sheetName,
|
||||||
|
List<String> headers,
|
||||||
|
HeaderCellCustomizer headerCellCustomizer,
|
||||||
|
Iterable<?> data,
|
||||||
|
Function2<String, Object, Object> valueGetter,
|
||||||
|
DataCellCustomizer dataCellCustomizer,
|
||||||
|
WorkbookConsumer workbookConsumer) {
|
||||||
|
|
||||||
|
try (Workbook workbook = new XSSFWorkbook()) {
|
||||||
|
|
||||||
|
Sheet sheet =
|
||||||
|
StringUtils.isEmpty(sheetName)
|
||||||
|
? workbook.createSheet()
|
||||||
|
: workbook.createSheet(sheetName);
|
||||||
|
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
for (int i = 0, headersSize = headers.size(); i < headersSize; i++) {
|
||||||
|
String header = headers.get(i);
|
||||||
|
|
||||||
|
Cell cell = headerRow.createCell(i);
|
||||||
|
cell.setCellValue(header);
|
||||||
|
if (headerCellCustomizer != null) {
|
||||||
|
|
||||||
|
headerCellCustomizer.customize(header, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowNum = 1;
|
||||||
|
|
||||||
|
for (Object d : data) {
|
||||||
|
Row row = sheet.createRow(rowNum++);
|
||||||
|
for (int i = 0, headersSize = headers.size(); i < headersSize; i++) {
|
||||||
|
String header = headers.get(i);
|
||||||
|
Cell cell = row.createCell(i);
|
||||||
|
Object value = valueGetter == null ? null : valueGetter.apply(header, d);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
|
||||||
|
cell.setBlank();
|
||||||
|
} else if (value instanceof CharSequence) {
|
||||||
|
cell.setCellValue(value.toString());
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
cell.setCellValue(((Number) value).doubleValue());
|
||||||
|
} else if (value instanceof Date) {
|
||||||
|
cell.setCellValue((Date) value);
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
cell.setCellValue((Boolean) value);
|
||||||
|
} else if (value instanceof LocalDateTime) {
|
||||||
|
|
||||||
|
cell.setCellValue((LocalDateTime) value);
|
||||||
|
} else if (value instanceof LocalDate) {
|
||||||
|
|
||||||
|
cell.setCellValue((LocalDate) value);
|
||||||
|
} else if (value instanceof Calendar) {
|
||||||
|
cell.setCellValue((Calendar) value);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (value instanceof Iterable) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Object o : (Iterable<?>) value) {
|
||||||
|
list.add(o.toString());
|
||||||
|
}
|
||||||
|
cell.setCellValue(String.join(",", list));
|
||||||
|
} else {
|
||||||
|
cell.setCellValue(value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataCellCustomizer != null) {
|
||||||
|
|
||||||
|
dataCellCustomizer.customize(header, d, value, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
workbookConsumer.accept(wbName, workbook);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CellValueHandler {
|
||||||
|
void handle(Cell headerCell, Cell dataCell, Object rowObject, Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CellValueToObjectSetter<T> {
|
||||||
|
void set(String header, T object, Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface WorkbookConsumer {
|
||||||
|
|
||||||
|
static WorkbookConsumer httpResponseConsumer(HttpServletResponse response) {
|
||||||
|
return (name, workbook) -> {
|
||||||
|
try {
|
||||||
|
response.setHeader(
|
||||||
|
"Content-Disposition",
|
||||||
|
"attachment; filename=" + URLEncoder.encode(name, StandardCharsets.UTF_8) + ".xlsx");
|
||||||
|
workbook.write(response.getOutputStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void accept(String name, org.apache.poi.ss.usermodel.Workbook workbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface DataCellCustomizer {
|
||||||
|
|
||||||
|
void customize(String header, Object model, Object value, Cell cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface HeaderCellCustomizer {
|
||||||
|
|
||||||
|
static HeaderCellCustomizer validationCustomizer(
|
||||||
|
Function<String, List<String>> validationGetter) {
|
||||||
|
|
||||||
|
return new HeaderCellCustomizer() {
|
||||||
|
|
||||||
|
private Sheet hiddenSheet;
|
||||||
|
|
||||||
|
private int rowIndex = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(String name, Cell cell) {
|
||||||
|
|
||||||
|
List<String> list = validationGetter.apply(name);
|
||||||
|
if (!CollectionUtils.isNotEmpty(list)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hiddenSheet == null) {
|
||||||
|
hiddenSheet = cell.getSheet().getWorkbook().createSheet("hidden");
|
||||||
|
cell.getSheet()
|
||||||
|
.getWorkbook()
|
||||||
|
.setSheetHidden(
|
||||||
|
hiddenSheet.getWorkbook().getSheetIndex(hiddenSheet), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Row row = hiddenSheet.createRow(rowIndex);
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
|
||||||
|
row.createCell(i).setCellValue(list.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name wbName = hiddenSheet.getWorkbook().createName();
|
||||||
|
wbName.setNameName("validate_" + (rowIndex));
|
||||||
|
CellReference cellReference =
|
||||||
|
new CellReference(
|
||||||
|
hiddenSheet.getSheetName(), rowIndex, list.size(), true, true);
|
||||||
|
wbName.setRefersToFormula(cellReference.formatAsString());
|
||||||
|
XSSFDataValidationHelper dvHelper =
|
||||||
|
new XSSFDataValidationHelper((XSSFSheet) cell.getSheet());
|
||||||
|
XSSFDataValidationConstraint dvConstraint =
|
||||||
|
(XSSFDataValidationConstraint)
|
||||||
|
dvHelper.createFormulaListConstraint(wbName.getNameName());
|
||||||
|
CellRangeAddressList addressList =
|
||||||
|
new CellRangeAddressList(
|
||||||
|
cell.getRowIndex() + 1,
|
||||||
|
cell.getRowIndex() + 100000,
|
||||||
|
cell.getColumnIndex(),
|
||||||
|
cell.getColumnIndex());
|
||||||
|
XSSFDataValidation validation =
|
||||||
|
(XSSFDataValidation)
|
||||||
|
dvHelper.createValidation(dvConstraint, addressList);
|
||||||
|
validation.setSuppressDropDownArrow(true);
|
||||||
|
validation.setShowErrorBox(true);
|
||||||
|
cell.getSheet().addValidationData(validation);
|
||||||
|
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void customize(String name, Cell cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,6 +70,11 @@ public class TreeUtils {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T>void dfsList(Iterable<T> src, Function<T, Iterable<T>> getter, Consumer<DFSCtx<T>> handler, Function<T, Object> hashFn){
|
||||||
|
|
||||||
|
src.forEach(t -> dfs(t, getter, handler, hashFn));
|
||||||
|
}
|
||||||
|
|
||||||
public static <T>void dfs(T src, Function<T, Iterable<T>> getter, Consumer<DFSCtx<T>> handler, Function<T, Object> hashFn){
|
public static <T>void dfs(T src, Function<T, Iterable<T>> getter, Consumer<DFSCtx<T>> handler, Function<T, Object> hashFn){
|
||||||
|
|
||||||
var seen = new HashSet<>();
|
var seen = new HashSet<>();
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ import org.springframework.stereotype.Repository;
|
|||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface DepartmentRepository extends BaseRepository<DepartmentEntity> {
|
public interface DepartmentRepository extends BaseRepository<DepartmentEntity> {
|
||||||
|
|
||||||
|
DepartmentEntity findByNameAndOrganizationId(String name, String organizationId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package cn.lihongjie.coal.department.service;
|
|||||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||||
import cn.lihongjie.coal.base.service.BaseService;
|
import cn.lihongjie.coal.base.service.BaseService;
|
||||||
|
import cn.lihongjie.coal.common.Ctx;
|
||||||
import cn.lihongjie.coal.common.TreeUtils;
|
import cn.lihongjie.coal.common.TreeUtils;
|
||||||
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
|
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
|
||||||
import cn.lihongjie.coal.department.dto.CreateDepartmentDto;
|
import cn.lihongjie.coal.department.dto.CreateDepartmentDto;
|
||||||
@@ -145,4 +146,12 @@ class DepartmentService extends BaseService<DepartmentEntity, DepartmentReposito
|
|||||||
|
|
||||||
return page.map(this.mapper::toDto);
|
return page.map(this.mapper::toDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DepartmentDto findByName(String name) {
|
||||||
|
|
||||||
|
DepartmentEntity entity =
|
||||||
|
repository.findByNameAndOrganizationId(name, Ctx.currentUser().getOrganizationId());
|
||||||
|
|
||||||
|
return mapper.toDto(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import cn.lihongjie.coal.base.dto.CommonQuery;
|
|||||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||||
import cn.lihongjie.coal.base.dto.TreeDto;
|
import cn.lihongjie.coal.base.dto.TreeDto;
|
||||||
import cn.lihongjie.coal.base.service.BaseService;
|
import cn.lihongjie.coal.base.service.BaseService;
|
||||||
|
import cn.lihongjie.coal.common.TreeUtils;
|
||||||
import cn.lihongjie.coal.dictionary.dto.*;
|
import cn.lihongjie.coal.dictionary.dto.*;
|
||||||
import cn.lihongjie.coal.dictionary.entity.DictionaryEntity;
|
import cn.lihongjie.coal.dictionary.entity.DictionaryEntity;
|
||||||
import cn.lihongjie.coal.dictionary.entity.DictionaryItemEntity;
|
import cn.lihongjie.coal.dictionary.entity.DictionaryItemEntity;
|
||||||
@@ -39,6 +40,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -260,4 +262,18 @@ class DictionaryService extends BaseService<DictionaryEntity, DictionaryReposito
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getExcelValidation(String s) {
|
||||||
|
|
||||||
|
|
||||||
|
DictTreeRequest request = new DictTreeRequest();
|
||||||
|
request.setCode(s);
|
||||||
|
DictionaryTreeDto tree = tree(request);
|
||||||
|
|
||||||
|
ArrayList<String> list = new ArrayList<>();
|
||||||
|
|
||||||
|
TreeUtils.dfsList(tree.getTree(), (TreeDto x )->x.getChildren(), object -> list.add(object.getCurrent().getCode() + "-" + object.getCurrent().getName()), (TreeDto x )->x.getId());
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import cn.lihongjie.coal.base.dto.CommonQuery;
|
|||||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||||
import cn.lihongjie.coal.employee.dto.CreateEmployeeDto;
|
import cn.lihongjie.coal.employee.dto.CreateEmployeeDto;
|
||||||
import cn.lihongjie.coal.employee.dto.EmployeeDto;
|
import cn.lihongjie.coal.employee.dto.EmployeeDto;
|
||||||
|
import cn.lihongjie.coal.employee.dto.ImportEmpFromExcelRequest;
|
||||||
import cn.lihongjie.coal.employee.dto.UpdateEmployeeDto;
|
import cn.lihongjie.coal.employee.dto.UpdateEmployeeDto;
|
||||||
import cn.lihongjie.coal.employee.service.EmployeeService;
|
import cn.lihongjie.coal.employee.service.EmployeeService;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -51,4 +54,19 @@ public class EmployeeController {
|
|||||||
public Page<EmployeeDto> list(@RequestBody CommonQuery request) {
|
public Page<EmployeeDto> list(@RequestBody CommonQuery request) {
|
||||||
return this.service.list(request);
|
return this.service.list(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/importTemplate")
|
||||||
|
public void importTemplate(HttpServletResponse response) {
|
||||||
|
this.service.generateImportTemplate(response);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/import")
|
||||||
|
public Object importData(@RequestBody ImportEmpFromExcelRequest request) {
|
||||||
|
this.service.importFromExcel(request);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package cn.lihongjie.coal.employee.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ImportEmpFromExcelRequest {
|
||||||
|
|
||||||
|
private String fileId;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,14 +3,32 @@ package cn.lihongjie.coal.employee.service;
|
|||||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||||
import cn.lihongjie.coal.base.service.BaseService;
|
import cn.lihongjie.coal.base.service.BaseService;
|
||||||
|
import cn.lihongjie.coal.common.ExcelUtils;
|
||||||
|
import cn.lihongjie.coal.department.dto.CreateDepartmentDto;
|
||||||
|
import cn.lihongjie.coal.department.dto.DepartmentDto;
|
||||||
|
import cn.lihongjie.coal.department.entity.DepartmentEntity;
|
||||||
|
import cn.lihongjie.coal.department.service.DepartmentService;
|
||||||
|
import cn.lihongjie.coal.dictionary.service.DictionaryService;
|
||||||
import cn.lihongjie.coal.employee.dto.CreateEmployeeDto;
|
import cn.lihongjie.coal.employee.dto.CreateEmployeeDto;
|
||||||
import cn.lihongjie.coal.employee.dto.EmployeeDto;
|
import cn.lihongjie.coal.employee.dto.EmployeeDto;
|
||||||
|
import cn.lihongjie.coal.employee.dto.ImportEmpFromExcelRequest;
|
||||||
import cn.lihongjie.coal.employee.dto.UpdateEmployeeDto;
|
import cn.lihongjie.coal.employee.dto.UpdateEmployeeDto;
|
||||||
import cn.lihongjie.coal.employee.entity.EmployeeEntity;
|
import cn.lihongjie.coal.employee.entity.EmployeeEntity;
|
||||||
import cn.lihongjie.coal.employee.mapper.EmployeeMapper;
|
import cn.lihongjie.coal.employee.mapper.EmployeeMapper;
|
||||||
import cn.lihongjie.coal.employee.repository.EmployeeRepository;
|
import cn.lihongjie.coal.employee.repository.EmployeeRepository;
|
||||||
import cn.lihongjie.coal.file.service.FileService;
|
import cn.lihongjie.coal.file.service.FileService;
|
||||||
|
import cn.lihongjie.coal.jobPost.dto.CreateJobPostDto;
|
||||||
|
import cn.lihongjie.coal.jobPost.entity.JobPostEntity;
|
||||||
|
import cn.lihongjie.coal.jobPost.service.JobPostService;
|
||||||
|
|
||||||
|
import io.vavr.Function1;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.Cleanup;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
@@ -22,11 +40,18 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Transactional
|
@Transactional
|
||||||
public
|
public class EmployeeService extends BaseService<EmployeeEntity, EmployeeRepository> {
|
||||||
class EmployeeService extends BaseService<EmployeeEntity, EmployeeRepository> {
|
public static final List<String> HEADERS =
|
||||||
|
List.of(
|
||||||
|
"姓名", "性别", "民族", "婚姻状况", "入职时间", "身份证号", "学历", "毕业学校", "籍贯", "住址", "手机号", "部门",
|
||||||
|
"岗位", "银行卡号", "收款人姓名");
|
||||||
@Autowired private EmployeeRepository repository;
|
@Autowired private EmployeeRepository repository;
|
||||||
|
|
||||||
@Autowired private EmployeeMapper mapper;
|
@Autowired private EmployeeMapper mapper;
|
||||||
@@ -70,7 +95,6 @@ class EmployeeService extends BaseService<EmployeeEntity, EmployeeRepository> {
|
|||||||
if (CollectionUtils.isNotEmpty(x.getFileIds()))
|
if (CollectionUtils.isNotEmpty(x.getFileIds()))
|
||||||
x.setFiles(fileService.findAllByIds(x.getFileIds()));
|
x.setFiles(fileService.findAllByIds(x.getFileIds()));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(dto.getCars())) {
|
if (CollectionUtils.isNotEmpty(dto.getCars())) {
|
||||||
dto.getCars()
|
dto.getCars()
|
||||||
@@ -79,7 +103,6 @@ class EmployeeService extends BaseService<EmployeeEntity, EmployeeRepository> {
|
|||||||
if (CollectionUtils.isNotEmpty(x.getFileIds()))
|
if (CollectionUtils.isNotEmpty(x.getFileIds()))
|
||||||
x.setFiles(fileService.findAllByIds(x.getFileIds()));
|
x.setFiles(fileService.findAllByIds(x.getFileIds()));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
@@ -95,4 +118,95 @@ class EmployeeService extends BaseService<EmployeeEntity, EmployeeRepository> {
|
|||||||
|
|
||||||
return page.map(this::toDto);
|
return page.map(this::toDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired DictionaryService dictionaryService;
|
||||||
|
@Autowired DepartmentService departmentService;
|
||||||
|
@Autowired JobPostService jobPostService;
|
||||||
|
@PersistenceContext private EntityManager entityManager;
|
||||||
|
|
||||||
|
public void generateImportTemplate(HttpServletResponse response) {
|
||||||
|
|
||||||
|
ExcelUtils.genSingleSheetToHttp(
|
||||||
|
"员工导入模板",
|
||||||
|
HEADERS,
|
||||||
|
ExcelUtils.HeaderCellCustomizer.validationCustomizer(
|
||||||
|
name ->
|
||||||
|
switch (name) {
|
||||||
|
case "性别" -> dictionaryService.getExcelValidation("sex");
|
||||||
|
case "民族" -> dictionaryService.getExcelValidation("nation");
|
||||||
|
case "婚姻状况" -> dictionaryService.getExcelValidation("marriage");
|
||||||
|
case "学历" -> dictionaryService.getExcelValidation("education");
|
||||||
|
default -> new ArrayList<>();
|
||||||
|
}),
|
||||||
|
response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public void importFromExcel(ImportEmpFromExcelRequest request) {
|
||||||
|
|
||||||
|
@Cleanup InputStream download = fileService.download(request.getFileId());
|
||||||
|
|
||||||
|
io.vavr.Function1<String, String> getDepartmentId =
|
||||||
|
Function1.of(
|
||||||
|
(String name) -> {
|
||||||
|
DepartmentDto department =
|
||||||
|
departmentService.findByName(name);
|
||||||
|
|
||||||
|
if (department == null) {
|
||||||
|
CreateDepartmentDto dto = new CreateDepartmentDto();
|
||||||
|
dto.setName(name);
|
||||||
|
department = departmentService.create(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
return department == null ? null : department.getId();
|
||||||
|
})
|
||||||
|
.memoized();
|
||||||
|
|
||||||
|
io.vavr.Function1<String, String> getJobPostId =
|
||||||
|
Function1.of(
|
||||||
|
(String name) -> {
|
||||||
|
var jobPost = jobPostService.findByName(name);
|
||||||
|
if (jobPost == null) {
|
||||||
|
CreateJobPostDto dto = new CreateJobPostDto();
|
||||||
|
dto.setName(name);
|
||||||
|
jobPost = jobPostService.create(dto);
|
||||||
|
}
|
||||||
|
return jobPost == null ? null : jobPost.getId();
|
||||||
|
})
|
||||||
|
.memoized();
|
||||||
|
|
||||||
|
List<EmployeeEntity> list =
|
||||||
|
ExcelUtils.readFirstSheetToObjectList(
|
||||||
|
download,
|
||||||
|
EmployeeEntity::new,
|
||||||
|
(header, emp, value) -> {
|
||||||
|
switch (header) {
|
||||||
|
case "姓名" -> emp.setName((String) value);
|
||||||
|
case "性别" -> emp.setSex(ExcelUtils.getCode(value));
|
||||||
|
case "民族" -> emp.setNation(ExcelUtils.getCode(value));
|
||||||
|
case "婚姻状况" -> emp.setMarriage(ExcelUtils.getCode(value));
|
||||||
|
case "入职时间" -> emp.setEntryDate(ExcelUtils.getLocalDate(value));
|
||||||
|
case "身份证号" -> emp.setIdCard((String) value);
|
||||||
|
case "学历" -> emp.setEducation(ExcelUtils.getCode(value));
|
||||||
|
case "毕业学校" -> emp.setSchool((String) value);
|
||||||
|
case "籍贯" -> emp.setNativePlace((String) value);
|
||||||
|
case "住址" -> emp.setAddress((String) value);
|
||||||
|
case "手机号" -> emp.setPhone((String) value);
|
||||||
|
case "部门" ->
|
||||||
|
emp.setDepartment(
|
||||||
|
entityManager.getReference(
|
||||||
|
DepartmentEntity.class,
|
||||||
|
getDepartmentId.apply((String) value)));
|
||||||
|
case "岗位" ->
|
||||||
|
emp.setJobPost(
|
||||||
|
entityManager.getReference(
|
||||||
|
JobPostEntity.class,
|
||||||
|
getJobPostId.apply((String) value)));
|
||||||
|
case "银行卡号" -> emp.setBank(ExcelUtils.getCode(value));
|
||||||
|
case "收款人姓名" -> emp.setBankName((String) value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.repository.saveAll(list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import cn.lihongjie.coal.spring.config.HwCloudProperty;
|
|||||||
import com.aliyun.oss.OSSClient;
|
import com.aliyun.oss.OSSClient;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.obs.services.ObsClient;
|
import com.obs.services.ObsClient;
|
||||||
|
import com.obs.services.model.ObsObject;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -24,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.tika.Tika;
|
import org.apache.tika.Tika;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
@@ -96,6 +98,11 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
|
|||||||
|
|
||||||
@Autowired ObjectMapper objectMapper;
|
@Autowired ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static String getObjectKey(FileEntity fileEntity) {
|
||||||
|
return fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
|
||||||
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public FileDto upload(
|
public FileDto upload(
|
||||||
MultipartFile file,
|
MultipartFile file,
|
||||||
@@ -129,7 +136,7 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
|
|||||||
fileEntity.setMimeType(tika.detect(inputStream));
|
fileEntity.setMimeType(tika.detect(inputStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
|
String objectKey = getObjectKey(fileEntity);
|
||||||
|
|
||||||
fileEntity.setPublicUrl(uploadToOSS(objectKey, file.getInputStream()));
|
fileEntity.setPublicUrl(uploadToOSS(objectKey, file.getInputStream()));
|
||||||
|
|
||||||
@@ -138,48 +145,6 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
|
|||||||
return getById(fileEntity.getId());
|
return getById(fileEntity.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public FileDto upload(
|
|
||||||
InputStream file,
|
|
||||||
String name,
|
|
||||||
String dir,
|
|
||||||
String sortKey,
|
|
||||||
String code,
|
|
||||||
String remarks) {
|
|
||||||
FileEntity fileEntity = new FileEntity();
|
|
||||||
fileEntity.setFileName(name);
|
|
||||||
fileEntity.setFileSize(Long.valueOf(file.available()));
|
|
||||||
fileEntity.setCode(code);
|
|
||||||
fileEntity.setRemarks(remarks);
|
|
||||||
try {
|
|
||||||
|
|
||||||
fileEntity.setSortKey(Integer.parseInt(sortKey));
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
fileEntity.setSortKey(1);
|
|
||||||
}
|
|
||||||
fileEntity.setDirectory(
|
|
||||||
"%s/%s/%s"
|
|
||||||
.formatted(
|
|
||||||
activateProfile,
|
|
||||||
Ctx.currentUser().getOrganizationId(),
|
|
||||||
StringUtils.defaultIfBlank(dir, "public")));
|
|
||||||
InputStream inputStream = file;
|
|
||||||
fileEntity.setObjectId(
|
|
||||||
UUID.randomUUID() + "." + FilenameUtils.getExtension(name.replace(":", "_")));
|
|
||||||
try (inputStream) {
|
|
||||||
fileEntity.setMimeType(tika.detect(inputStream));
|
|
||||||
}
|
|
||||||
|
|
||||||
String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
|
|
||||||
|
|
||||||
fileEntity.setPublicUrl(uploadToOSS(objectKey, file));
|
|
||||||
|
|
||||||
this.save(fileEntity);
|
|
||||||
|
|
||||||
return getById(fileEntity.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String uploadToOSS(String objectKey, InputStream inputStream) {
|
private String uploadToOSS(String objectKey, InputStream inputStream) {
|
||||||
String objectUrl;
|
String objectUrl;
|
||||||
try {
|
try {
|
||||||
@@ -213,4 +178,61 @@ public class FileService extends BaseService<FileEntity, FileRepository> {
|
|||||||
objectKey);
|
objectKey);
|
||||||
return objectUrl;
|
return objectUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public FileDto upload(
|
||||||
|
InputStream file,
|
||||||
|
String name,
|
||||||
|
String dir,
|
||||||
|
String sortKey,
|
||||||
|
String code,
|
||||||
|
String remarks) {
|
||||||
|
FileEntity fileEntity = new FileEntity();
|
||||||
|
fileEntity.setFileName(name);
|
||||||
|
fileEntity.setFileSize(Long.valueOf(file.available()));
|
||||||
|
fileEntity.setCode(code);
|
||||||
|
fileEntity.setRemarks(remarks);
|
||||||
|
try {
|
||||||
|
|
||||||
|
fileEntity.setSortKey(Integer.parseInt(sortKey));
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
fileEntity.setSortKey(1);
|
||||||
|
}
|
||||||
|
fileEntity.setDirectory(
|
||||||
|
"%s/%s/%s"
|
||||||
|
.formatted(
|
||||||
|
activateProfile,
|
||||||
|
Ctx.currentUser().getOrganizationId(),
|
||||||
|
StringUtils.defaultIfBlank(dir, "public")));
|
||||||
|
InputStream inputStream = file;
|
||||||
|
fileEntity.setObjectId(
|
||||||
|
UUID.randomUUID() + "." + FilenameUtils.getExtension(name.replace(":", "_")));
|
||||||
|
try (inputStream) {
|
||||||
|
fileEntity.setMimeType(tika.detect(inputStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
String objectKey = getObjectKey(fileEntity);
|
||||||
|
|
||||||
|
fileEntity.setPublicUrl(uploadToOSS(objectKey, file));
|
||||||
|
|
||||||
|
this.save(fileEntity);
|
||||||
|
|
||||||
|
return getById(fileEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream download(String fileId) {
|
||||||
|
|
||||||
|
FileEntity fileEntity = repository.get(fileId);
|
||||||
|
String objectKey = getObjectKey(fileEntity);
|
||||||
|
try {
|
||||||
|
ObsObject object =
|
||||||
|
obsClient.getObject(aliyunProperty.getOSS().getBucketName(), objectKey);
|
||||||
|
return
|
||||||
|
object.getObjectContent();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("下载文件失败", e);
|
||||||
|
throw new BizException("下载文件失败 %s".formatted(e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,6 @@ import cn.lihongjie.coal.jobPost.entity.JobPostEntity;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface JobPostRepository extends BaseRepository<JobPostEntity> {}
|
public interface JobPostRepository extends BaseRepository<JobPostEntity> {
|
||||||
|
JobPostEntity findByNameAndOrganizationId(String name, String organizationId);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package cn.lihongjie.coal.jobPost.service;
|
|||||||
import cn.lihongjie.coal.base.dto.CommonQuery;
|
import cn.lihongjie.coal.base.dto.CommonQuery;
|
||||||
import cn.lihongjie.coal.base.dto.IdRequest;
|
import cn.lihongjie.coal.base.dto.IdRequest;
|
||||||
import cn.lihongjie.coal.base.service.BaseService;
|
import cn.lihongjie.coal.base.service.BaseService;
|
||||||
|
import cn.lihongjie.coal.common.Ctx;
|
||||||
import cn.lihongjie.coal.jobPost.dto.CreateJobPostDto;
|
import cn.lihongjie.coal.jobPost.dto.CreateJobPostDto;
|
||||||
import cn.lihongjie.coal.jobPost.dto.JobPostDto;
|
import cn.lihongjie.coal.jobPost.dto.JobPostDto;
|
||||||
import cn.lihongjie.coal.jobPost.dto.UpdateJobPostDto;
|
import cn.lihongjie.coal.jobPost.dto.UpdateJobPostDto;
|
||||||
@@ -68,4 +69,12 @@ class JobPostService extends BaseService<JobPostEntity, JobPostRepository> {
|
|||||||
|
|
||||||
return page.map(this.mapper::toDto);
|
return page.map(this.mapper::toDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JobPostDto findByName(String name) {
|
||||||
|
|
||||||
|
JobPostEntity post = repository.findByNameAndOrganizationId(name, Ctx.currentUser().getOrganizationId());
|
||||||
|
|
||||||
|
return mapper.toDto(post);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user