diff --git a/pom.xml b/pom.xml
index d751ab9..54394d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
com.imyeyu.timiserverapi
TimiServerAPI
- 1.0.1
+ 1.0.3
jar
TimiServerAPI
imyeyu.com API
@@ -178,7 +178,7 @@
com.imyeyu.network
timi-network
- 0.0.12
+ 0.0.13
com.imyeyu.lang
@@ -323,6 +323,11 @@
jsoup
1.18.1
+
+ org.apache.poi
+ poi-ooxml
+ 5.4.1
+
commons-codec
commons-codec
diff --git a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerController.java b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerController.java
index 8d30908..62e6d3f 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerController.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoCustomerController.java
@@ -17,9 +17,11 @@ import com.imyeyu.api.modules.gao.vo.GaoCustomerSearchReq;
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStatReq;
import com.imyeyu.api.modules.gao.vo.GaoQuickRegistrationEventRecordReq;
import com.imyeyu.spring.annotation.AOPLog;
+import com.imyeyu.spring.annotation.IgnoreGlobalReturn;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -27,6 +29,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import java.io.IOException;
+import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -67,6 +71,26 @@ public class GaoCustomerController {
return service.search(req);
}
+ @AOPLog
+ @RequestRateLimit
+ @RequireGaoPermission(GaoPermissionCode.CUSTOMER_READ)
+ @PostMapping("/search/page")
+ public PageResult searchPage(@RequestBody Page page) {
+ return service.searchPage(page);
+ }
+
+ @AOPLog
+ @RequestRateLimit
+ @IgnoreGlobalReturn
+ @RequireGaoPermission(GaoPermissionCode.CUSTOMER_READ)
+ @PostMapping("/export")
+ public void export(@RequestBody GaoCustomerSearchReq req, HttpServletResponse resp) throws IOException {
+ String fileName = URLEncoder.encode("客户列表.xlsx", "UTF-8").replace("+", "%20");
+ resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ resp.setHeader("Content-Disposition", "attachment; filename=\"gao-customer.xlsx\"; filename*=UTF-8''" + fileName);
+ resp.getOutputStream().write(service.exportSearchExcel(req));
+ }
+
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_READ)
@@ -95,8 +119,9 @@ public class GaoCustomerController {
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.CUSTOMER_CREATE)
@PostMapping("/create")
- public void create(@RequestBody GaoCustomer customer) {
+ public GaoCustomer create(@RequestBody GaoCustomer customer) {
service.create(customer);
+ return customer;
}
@AOPLog
diff --git a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoRegistrationEventRecordController.java b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoRegistrationEventRecordController.java
index cf2ea74..e01922d 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoRegistrationEventRecordController.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoRegistrationEventRecordController.java
@@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.net.URLEncoder;
import java.util.List;
///
@@ -53,6 +53,14 @@ public class GaoRegistrationEventRecordController {
return service.page(page);
}
+ @AOPLog
+ @RequestRateLimit
+ @RequireGaoPermission(GaoPermissionCode.REGISTRATION_EVENT_RECORD_READ)
+ @PostMapping("/range/page")
+ public PageResult rangePage(@RequestBody Page page) {
+ return service.pageByRange(page);
+ }
+
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.REGISTRATION_EVENT_RECORD_READ)
@@ -106,10 +114,10 @@ public class GaoRegistrationEventRecordController {
@RequireGaoPermission(GaoPermissionCode.REGISTRATION_EVENT_RECORD_READ)
@PostMapping("/range/export")
public void rangeExport(@RequestBody GaoRegistrationEventRecordRangeReq req, HttpServletResponse resp) throws IOException {
- List list = service.listByRange(req);
- resp.setContentType("application/vnd.ms-excel;charset=UTF-8");
- resp.setHeader("Content-Disposition", "attachment; filename=\"gao-registration-event-record.csv\"");
- resp.getOutputStream().write(buildCsv(list).getBytes(StandardCharsets.UTF_8));
+ String fileName = URLEncoder.encode("登记事件记录.xlsx", "UTF-8").replace("+", "%20");
+ resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ resp.setHeader("Content-Disposition", "attachment; filename=\"gao-registration-event-record.xlsx\"; filename*=UTF-8''" + fileName);
+ resp.getOutputStream().write(service.exportRangeExcel(req));
}
@AOPLog
@@ -163,30 +171,4 @@ public class GaoRegistrationEventRecordController {
public List allCustomerRegistrationEventDailyStat(@RequestBody GaoRegistrationEventRecordTrendStatReq req) {
return service.statDailyByRegistrationEvent(req);
}
-
- private String buildCsv(List list) {
- StringBuilder builder = new StringBuilder();
- builder.append((char) 65279);
- builder.append("客户编码,客户姓名,登记事件,登记时间,登记人用户 ID,备注\n");
- for (GaoRegistrationEventRecord record : list) {
- builder.append(csv(record.getCustomer() == null ? null : record.getCustomer().getCode())).append(',');
- builder.append(csv(record.getCustomer() == null ? null : record.getCustomer().getName())).append(',');
- builder.append(csv(record.getRegistrationEvent() == null ? null : record.getRegistrationEvent().getName())).append(',');
- builder.append(csv(record.getRegisteredAt())).append(',');
- builder.append(csv(record.getOperatorUserId())).append(',');
- builder.append(csv(record.getRemark())).append('\n');
- }
- return builder.toString();
- }
-
- private String csv(Object value) {
- if (value == null) {
- return "";
- }
- String text = value.toString();
- if (!text.contains(",") && !text.contains("\"") && !text.contains("\n") && !text.contains("\r")) {
- return text;
- }
- return "\"%s\"".formatted(text.replace("\"", "\"\""));
- }
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerMapper.java b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerMapper.java
index d0e8399..dcabc54 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerMapper.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoCustomerMapper.java
@@ -20,6 +20,10 @@ public interface GaoCustomerMapper extends BaseMapper {
List search(@Param("keyword") String keyword, @Param("introducerCustomerId") String introducerCustomerId);
+ Long countSearch(@Param("keyword") String keyword, @Param("introducerCustomerId") String introducerCustomerId);
+
+ List searchPage(@Param("keyword") String keyword, @Param("introducerCustomerId") String introducerCustomerId, @Param("offset") Long offset, @Param("size") Long size);
+
List selectInvitedList(@Param("introducerCustomerId") String introducerCustomerId);
Long countInvited(@Param("introducerCustomerId") String introducerCustomerId);
diff --git a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoRegistrationEventRecordMapper.java b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoRegistrationEventRecordMapper.java
index ad96232..bfb8655 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoRegistrationEventRecordMapper.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoRegistrationEventRecordMapper.java
@@ -103,4 +103,18 @@ public interface GaoRegistrationEventRecordMapper extends BaseMapper selectByRange(@Param("req") GaoRegistrationEventRecordRangeReq req);
+
+ /// 按任意时间范围统计登记事件记录
+ ///
+ /// @param req 范围查询请求
+ /// @return 登记事件记录数
+ Long countByRange(@Param("req") GaoRegistrationEventRecordRangeReq req);
+
+ /// 按任意时间范围分页查询登记事件记录
+ ///
+ /// @param req 范围查询请求
+ /// @param offset 偏移量
+ /// @param size 每页条数
+ /// @return 登记事件记录列表
+ List selectPageByRange(@Param("req") GaoRegistrationEventRecordRangeReq req, @Param("offset") Long offset, @Param("size") Long size);
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerService.java b/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerService.java
index a6e92bf..5b61f5d 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerService.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/GaoCustomerService.java
@@ -5,8 +5,11 @@ import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStatView;
import com.imyeyu.api.modules.gao.vo.GaoCustomerInviteUpdateReq;
import com.imyeyu.api.modules.gao.vo.GaoCustomerSearchReq;
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStatReq;
+import com.imyeyu.spring.bean.Page;
+import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.service.BaseService;
+import java.io.IOException;
import java.util.List;
///
@@ -40,6 +43,18 @@ public interface GaoCustomerService extends BaseService {
/// @return 客户列表
List search(GaoCustomerSearchReq req);
+ /// 分页搜索客户
+ ///
+ /// @param page 分页搜索请求
+ /// @return 客户分页结果
+ PageResult searchPage(Page page);
+
+ /// 按搜索条件导出客户 Excel
+ ///
+ /// @param req 搜索请求
+ /// @return xlsx 文件字节
+ byte[] exportSearchExcel(GaoCustomerSearchReq req) throws IOException;
+
/// 查询邀请的客户
///
/// @param introducerCustomerId 介绍人客户 ID
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/GaoRegistrationEventRecordService.java b/src/main/java/com/imyeyu/api/modules/gao/service/GaoRegistrationEventRecordService.java
index 29f0fd5..8985d94 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/GaoRegistrationEventRecordService.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/GaoRegistrationEventRecordService.java
@@ -10,8 +10,11 @@ import com.imyeyu.api.modules.gao.vo.GaoRegistrationEventRecordPeriodReq;
import com.imyeyu.api.modules.gao.vo.GaoRegistrationEventRecordRangeReq;
import com.imyeyu.api.modules.gao.vo.GaoRegistrationEventRecordStatReq;
import com.imyeyu.api.modules.gao.vo.GaoRegistrationEventRecordTrendStatReq;
+import com.imyeyu.spring.bean.Page;
+import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.service.BaseService;
+import java.io.IOException;
import java.util.List;
///
@@ -39,6 +42,18 @@ public interface GaoRegistrationEventRecordService extends BaseService listByRange(GaoRegistrationEventRecordRangeReq req);
+ /// 按任意时间范围分页查询登记事件记录
+ ///
+ /// @param page 分页参数
+ /// @return 登记事件记录分页结果
+ PageResult pageByRange(Page page);
+
+ /// 按任意时间范围导出登记事件记录 Excel
+ ///
+ /// @param req 范围查询请求
+ /// @return xlsx 文件字节
+ byte[] exportRangeExcel(GaoRegistrationEventRecordRangeReq req) throws IOException;
+
/// 按周期查询登记事件记录
///
/// @param req 周期请求
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerServiceImplement.java b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerServiceImplement.java
index 2ec356a..72d0222 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerServiceImplement.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoCustomerServiceImplement.java
@@ -14,12 +14,22 @@ import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStatReq;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
+import com.imyeyu.spring.bean.Page;
+import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
import lombok.RequiredArgsConstructor;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
@@ -40,6 +50,7 @@ import java.util.Map;
public class GaoCustomerServiceImplement extends AbstractEntityService implements GaoCustomerService {
private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
+ private static final DateTimeFormatter EXPORT_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
private final GaoCustomerMapper mapper;
private final AttachmentService attachmentService;
@@ -104,14 +115,75 @@ public class GaoCustomerServiceImplement extends AbstractEntityService search(GaoCustomerSearchReq req) {
- if (req == null) {
- req = new GaoCustomerSearchReq();
- }
+ req = resolveSearchReq(req);
List list = mapper.search(req.getKeyword(), req.getIntroducerCustomerId());
list.forEach(this::loadTransient);
return list;
}
+ @Override
+ public PageResult searchPage(Page page) {
+ TimiException.required(page, "not found page");
+ TimiException.required(page.getIndex(), "not found page.index");
+ TimiException.required(page.getSize(), "not found page.size");
+ TimiException.requiredTrue(0 <= page.getIndex(), "page.index lt 0");
+ TimiException.requiredTrue(0 < page.getSize(), "page.size lte 0");
+ GaoCustomerSearchReq req = resolveSearchReq(page.getEqualsExample());
+ Long total = TimiJava.defaultIfNull(mapper.countSearch(req.getKeyword(), req.getIntroducerCustomerId()), 0L);
+ List list = mapper.searchPage(req.getKeyword(), req.getIntroducerCustomerId(), page.getIndex() * page.getSize(), page.getSize());
+ list.forEach(this::loadTransient);
+ PageResult result = new PageResult<>();
+ result.setTotal(total);
+ result.setList(list);
+ return result;
+ }
+
+ @Override
+ public byte[] exportSearchExcel(GaoCustomerSearchReq req) throws IOException {
+ List list = search(req);
+ try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ Sheet sheet = workbook.createSheet("客户列表");
+ CellStyle titleStyle = workbook.createCellStyle();
+ Font titleFont = workbook.createFont();
+ titleFont.setBold(true);
+ titleFont.setFontHeightInPoints((short) 14);
+ titleStyle.setFont(titleFont);
+ CellStyle headerStyle = workbook.createCellStyle();
+ Font headerFont = workbook.createFont();
+ headerFont.setBold(true);
+ headerStyle.setFont(headerFont);
+
+ appendRow(sheet, 0, titleStyle, "客户列表导出");
+ appendRow(sheet, 1, null, "生成时间", EXPORT_TIME_FORMATTER.format(Instant.now()));
+ appendRow(sheet, 2, null, "关键词", req == null || req.getKeyword() == null || req.getKeyword().isBlank() ? "全部" : req.getKeyword().trim());
+ appendRow(sheet, 3, null, "记录总数", String.valueOf(list.size()));
+ appendRow(sheet, 5, headerStyle, "客户编码", "姓名", "性别", "年龄", "电话", "地址", "病症", "备注", "邀请人", "邀请客户数", "创建时间");
+ int rowIndex = 6;
+ for (GaoCustomer customer : list) {
+ appendRow(sheet, rowIndex, null,
+ text(customer.getCode()),
+ text(customer.getName()),
+ formatGender(customer),
+ customer.getAge() == null ? "" : String.valueOf(customer.getAge()),
+ text(customer.getTelephone()),
+ text(customer.getAddress()),
+ text(customer.getDisease()),
+ text(customer.getRemark()),
+ customer.getIntroducerCustomer() == null ? "" : text(customer.getIntroducerCustomer().getName()),
+ customer.getInvitedCount() == null ? "0" : String.valueOf(customer.getInvitedCount()),
+ formatExportTime(customer.getCreatedAt())
+ );
+ rowIndex++;
+ }
+ for (int index = 0; index < 11; index++) {
+ sheet.autoSizeColumn(index);
+ sheet.setColumnWidth(index, Math.min(Math.max(sheet.getColumnWidth(index), 10 * 256), 36 * 256));
+ }
+ workbook.write(output);
+ return output.toByteArray();
+ }
+ }
+
@Override
public List listInvited(String introducerCustomerId) {
TimiException.required(introducerCustomerId, "not found introducerCustomerId");
@@ -176,16 +248,21 @@ public class GaoCustomerServiceImplement extends AbstractEntityService "男";
+ case FEMALE -> "女";
+ };
+ }
+
+ private String formatExportTime(Long value) {
+ if (value == null) {
+ return "";
+ }
+ return EXPORT_TIME_FORMATTER.format(Instant.ofEpochMilli(value));
+ }
+
+ private String text(Object value) {
+ return value == null ? "" : value.toString();
+ }
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoRegistrationEventRecordServiceImplement.java b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoRegistrationEventRecordServiceImplement.java
index 1958453..5f61a61 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoRegistrationEventRecordServiceImplement.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoRegistrationEventRecordServiceImplement.java
@@ -26,13 +26,23 @@ import com.imyeyu.api.modules.user.service.UserLoginService;
import com.imyeyu.api.modules.user.service.UserService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
+import com.imyeyu.spring.bean.Page;
+import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
import com.imyeyu.utils.Time;
import lombok.RequiredArgsConstructor;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
@@ -43,6 +53,8 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
///
/// 登记事件记录服务实现
@@ -54,6 +66,7 @@ import java.util.Map;
public class GaoRegistrationEventRecordServiceImplement extends AbstractEntityService implements GaoRegistrationEventRecordService {
private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
+ private static final DateTimeFormatter EXPORT_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
private final GaoRegistrationEventRecordMapper mapper;
private final AttachmentService attachmentService;
@@ -148,6 +161,67 @@ public class GaoRegistrationEventRecordServiceImplement extends AbstractEntitySe
return list;
}
+ @Override
+ public PageResult pageByRange(Page page) {
+ TimiException.required(page, "not found page");
+ TimiException.required(page.getIndex(), "not found page.index");
+ TimiException.required(page.getSize(), "not found page.size");
+ TimiException.requiredTrue(0 <= page.getIndex(), "page.index lt 0");
+ TimiException.requiredTrue(0 < page.getSize(), "page.size lte 0");
+ GaoRegistrationEventRecordRangeReq req = TimiJava.defaultIfNull(page.getEqualsExample(), new GaoRegistrationEventRecordRangeReq());
+ checkStatRange(req.getBeginRegisteredAt(), req.getEndRegisteredAt());
+ Long total = TimiJava.defaultIfNull(mapper.countByRange(req), 0L);
+ List list = mapper.selectPageByRange(req, page.getIndex() * page.getSize(), page.getSize());
+ list.forEach(this::loadTransient);
+ PageResult result = new PageResult<>();
+ result.setTotal(total);
+ result.setList(list);
+ return result;
+ }
+
+ @Override
+ public byte[] exportRangeExcel(GaoRegistrationEventRecordRangeReq req) throws IOException {
+ List list = listByRange(req);
+ try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ Sheet sheet = workbook.createSheet("登记事件记录");
+ CellStyle titleStyle = workbook.createCellStyle();
+ Font titleFont = workbook.createFont();
+ titleFont.setBold(true);
+ titleFont.setFontHeightInPoints((short) 14);
+ titleStyle.setFont(titleFont);
+ CellStyle headerStyle = workbook.createCellStyle();
+ Font headerFont = workbook.createFont();
+ headerFont.setBold(true);
+ headerStyle.setFont(headerFont);
+
+ appendRow(sheet, 0, titleStyle, "登记事件记录导出");
+ appendRow(sheet, 1, null, "生成时间", EXPORT_TIME_FORMATTER.format(Instant.now()));
+ appendRow(sheet, 2, null, "时间范围", "%s ~ %s".formatted(formatExportTime(req.getBeginRegisteredAt()), formatExportTime(req.getEndRegisteredAt())));
+ appendRow(sheet, 3, null, "事件筛选", buildEventFilterText(req));
+ appendRow(sheet, 4, null, "关键词", req.getKeyword() == null || req.getKeyword().isBlank() ? "全部" : req.getKeyword().trim());
+ appendRow(sheet, 5, null, "记录总数", String.valueOf(list.size()));
+ appendRow(sheet, 7, headerStyle, "客户编码", "客户姓名", "登记事件", "登记时间", "登记人", "备注");
+ int rowIndex = 8;
+ for (GaoRegistrationEventRecord record : list) {
+ appendRow(sheet, rowIndex, null,
+ record.getCustomer() == null ? "" : text(record.getCustomer().getCode()),
+ record.getCustomer() == null ? "" : text(record.getCustomer().getName()),
+ record.getRegistrationEvent() == null ? "" : text(record.getRegistrationEvent().getName()),
+ formatExportTime(record.getRegisteredAt()),
+ getOperatorName(record),
+ text(record.getRemark())
+ );
+ rowIndex++;
+ }
+ for (int index = 0; index < 6; index++) {
+ sheet.autoSizeColumn(index);
+ sheet.setColumnWidth(index, Math.min(Math.max(sheet.getColumnWidth(index), 12 * 256), 40 * 256));
+ }
+ workbook.write(output);
+ return output.toByteArray();
+ }
+ }
+
@Override
public List statByRegistrationEventAndPeriodType(String registrationEventId, GaoRegistrationEventRecordPeriodReq.PeriodType periodType) {
TimiException.required(registrationEventId, "not found registrationEventId");
@@ -322,4 +396,53 @@ public class GaoRegistrationEventRecordServiceImplement extends AbstractEntitySe
}
return list;
}
+
+ private void appendRow(Sheet sheet, int rowIndex, CellStyle style, String... values) {
+ Row row = sheet.createRow(rowIndex);
+ for (int index = 0; index < values.length; index++) {
+ row.createCell(index).setCellValue(values[index]);
+ if (style != null) {
+ row.getCell(index).setCellStyle(style);
+ }
+ }
+ }
+
+ private String buildEventFilterText(GaoRegistrationEventRecordRangeReq req) {
+ if ((req.getRegistrationEventId() == null || req.getRegistrationEventId().isBlank()) && (req.getRegistrationEventIdList() == null || req.getRegistrationEventIdList().isEmpty())) {
+ return "全部事件";
+ }
+ if (req.getRegistrationEventId() != null && !req.getRegistrationEventId().isBlank()) {
+ return "事件 ID:" + req.getRegistrationEventId();
+ }
+ StringJoiner joiner = new StringJoiner("、");
+ req.getRegistrationEventIdList().stream()
+ .filter(Objects::nonNull)
+ .filter(item -> !item.isBlank())
+ .forEach(joiner::add);
+ return "事件 ID:" + joiner;
+ }
+
+ private String formatExportTime(Long value) {
+ if (value == null) {
+ return "";
+ }
+ return EXPORT_TIME_FORMATTER.format(Instant.ofEpochMilli(value));
+ }
+
+ private String getOperatorName(GaoRegistrationEventRecord record) {
+ if (record.getOperator() == null) {
+ return text(record.getOperatorUserId());
+ }
+ if (record.getOperator().getNick() != null && !record.getOperator().getNick().isBlank()) {
+ return record.getOperator().getNick();
+ }
+ if (record.getOperator().getName() != null && !record.getOperator().getName().isBlank()) {
+ return record.getOperator().getName();
+ }
+ return text(record.getOperatorUserId());
+ }
+
+ private String text(Object value) {
+ return value == null ? "" : value.toString();
+ }
}
diff --git a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoRegistrationEventRecordRangeReq.java b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoRegistrationEventRecordRangeReq.java
index 6e7f1d8..d579c34 100644
--- a/src/main/java/com/imyeyu/api/modules/gao/vo/GaoRegistrationEventRecordRangeReq.java
+++ b/src/main/java/com/imyeyu/api/modules/gao/vo/GaoRegistrationEventRecordRangeReq.java
@@ -2,6 +2,8 @@ package com.imyeyu.api.modules.gao.vo;
import lombok.Data;
+import java.util.List;
+
///
/// 登记事件记录范围查询请求
///
@@ -16,6 +18,12 @@ public class GaoRegistrationEventRecordRangeReq {
/// 登记事件 ID,为空查询全部登记事件
private String registrationEventId;
+ /// 登记事件 ID 列表,为空查询全部登记事件
+ private List registrationEventIdList;
+
+ /// 关键词,匹配客户、登记事件、备注、登记人
+ private String keyword;
+
/// 开始登记时间
private Long beginRegisteredAt;
diff --git a/src/main/resources/db/migration/timiserver/V15__create_gao_registration_event_tables.sql b/src/main/resources/db/migration/timiserver/V15__create_gao_registration_event_tables.sql
index 3906755..ca7b3ae 100644
--- a/src/main/resources/db/migration/timiserver/V15__create_gao_registration_event_tables.sql
+++ b/src/main/resources/db/migration/timiserver/V15__create_gao_registration_event_tables.sql
@@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS `gao_customer` (
`id` VARCHAR(36) NOT NULL,
- `code` VARCHAR(64) NOT NULL COMMENT '客户编码',
+ `code` VARCHAR(64) NULL COMMENT '客户编码',
`name` VARCHAR(64) NOT NULL COMMENT '姓名',
`gender` VARCHAR(16) NULL COMMENT '性别代码,MALE 男,FEMALE 女',
`age` INT NULL COMMENT '年龄',
diff --git a/src/main/resources/mapper/timi-server/GaoCustomerMapper.xml b/src/main/resources/mapper/timi-server/GaoCustomerMapper.xml
index f302e6f..15e9d46 100644
--- a/src/main/resources/mapper/timi-server/GaoCustomerMapper.xml
+++ b/src/main/resources/mapper/timi-server/GaoCustomerMapper.xml
@@ -1,29 +1,51 @@
+
+ 1 = 1
+ AND `deleted_at` IS NULL
+
+ AND (
+ `code` LIKE CONCAT('%', #{keyword}, '%')
+ OR `name` LIKE CONCAT('%', #{keyword}, '%')
+ OR `telephone` LIKE CONCAT('%', #{keyword}, '%')
+ OR `address` LIKE CONCAT('%', #{keyword}, '%')
+ OR `disease` LIKE CONCAT('%', #{keyword}, '%')
+ OR CAST(`conditioning_part` AS CHAR) LIKE CONCAT('%', #{keyword}, '%')
+ )
+
+
+ AND `introducer_customer_id` = #{introducerCustomerId}
+
+
+
+
+
+
+
+
+ r.`registered_at` >= #{req.beginRegisteredAt}
+ AND r.`registered_at` <= #{req.endRegisteredAt}
+ AND r.`deleted_at` IS NULL
+
+ AND r.`customer_id` = #{req.customerId}
+
+
+ AND r.`registration_event_id` = #{req.registrationEventId}
+
+
+ AND r.`registration_event_id` IN
+
+ #{registrationEventId}
+
+
+
+ AND (
+ c.`code` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR c.`name` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR e.`name` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR r.`remark` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR u.`name` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR u.`nick` LIKE CONCAT('%', #{req.keyword}, '%')
+ OR r.`operator_user_id` LIKE CONCAT('%', #{req.keyword}, '%')
+ )
+
+
+
+
+ FROM `gao_registration_event_record` r
+ LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id`
+ LEFT JOIN `gao_registration_event` e ON r.`registration_event_id` = e.`id`
+ LEFT JOIN `user` u ON r.`operator_user_id` = u.`id`
+
+
+
+
+
+