mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-16 21:33:40 +00:00
在modules包下新建asset-management包,将代码挪过来
Signed-off-by: CCass <only_pop@qq.com>
This commit is contained in:
@@ -68,6 +68,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-asset-management-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
package org.ruoyi.system.listener;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.common.core.utils.SpringUtils;
|
||||
import org.ruoyi.common.excel.core.ExcelListener;
|
||||
import org.ruoyi.common.excel.core.ExcelResult;
|
||||
import org.ruoyi.system.domain.MinUsagePeriod;
|
||||
import org.ruoyi.system.domain.bo.MinUsagePeriodBo;
|
||||
import org.ruoyi.system.domain.vo.MinUsagePeriodImportVo;
|
||||
import org.ruoyi.system.service.IMinUsagePeriodService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 最低使用年限表自定义导入监听器
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class MinUsagePeriodImportListener extends AnalysisEventListener<MinUsagePeriodImportVo> implements ExcelListener<MinUsagePeriodImportVo> {
|
||||
|
||||
private final IMinUsagePeriodService minUsagePeriodService;
|
||||
|
||||
private final Boolean isUpdateSupport;
|
||||
|
||||
private final String operName;
|
||||
|
||||
private final List<MinUsagePeriodImportVo> list = new ArrayList<>();
|
||||
|
||||
private int successNum = 0;
|
||||
private int failureNum = 0;
|
||||
private final StringBuilder successMsg = new StringBuilder();
|
||||
private final StringBuilder failureMsg = new StringBuilder();
|
||||
|
||||
public MinUsagePeriodImportListener(Boolean isUpdateSupport) {
|
||||
this.minUsagePeriodService = SpringUtils.getBean(IMinUsagePeriodService.class);
|
||||
this.isUpdateSupport = isUpdateSupport;
|
||||
this.operName = "系统";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(MinUsagePeriodImportVo data, AnalysisContext context) {
|
||||
list.add(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
log.info("所有数据解析完成!");
|
||||
// 这里可以添加批量处理逻辑
|
||||
for (MinUsagePeriodImportVo data : list) {
|
||||
try {
|
||||
// 验证是否存在这个数据
|
||||
MinUsagePeriod existData = minUsagePeriodService.queryByGbCode(data.getGbCode());
|
||||
if (ObjectUtil.isNull(existData)) {
|
||||
minUsagePeriodService.insertByBo(BeanUtil.toBean(data, MinUsagePeriodBo.class));
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、国标代码 " + data.getGbCode() + " 导入成功");
|
||||
} else if (isUpdateSupport) {
|
||||
BeanUtil.copyProperties(data, existData);
|
||||
minUsagePeriodService.updateByBo(BeanUtil.toBean(existData, MinUsagePeriodBo.class));
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、国标代码 " + data.getGbCode() + " 更新成功");
|
||||
} else {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>" + failureNum + "、国标代码 " + data.getGbCode() + " 已存在");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、国标代码 " + data.getGbCode() + " 导入失败:";
|
||||
failureMsg.append(msg + e.getMessage());
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExcelResult<MinUsagePeriodImportVo> getExcelResult() {
|
||||
return new ExcelResult<MinUsagePeriodImportVo>() {
|
||||
@Override
|
||||
public List<MinUsagePeriodImportVo> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getErrorList() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAnalysis() {
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
return failureMsg.toString();
|
||||
} else {
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
return successMsg.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package org.ruoyi.system.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.common.core.utils.MapstructUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.core.page.PageQuery;
|
||||
import org.ruoyi.core.page.TableDataInfo;
|
||||
import org.ruoyi.system.domain.MinUsagePeriod;
|
||||
import org.ruoyi.system.domain.bo.MinUsagePeriodBo;
|
||||
import org.ruoyi.system.domain.vo.MinUsagePeriodVo;
|
||||
import org.ruoyi.system.mapper.MinUsagePeriodMapper;
|
||||
import org.ruoyi.system.service.IMinUsagePeriodService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 最低使用年限表Service业务层处理
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class MinUsagePeriodServiceImpl implements IMinUsagePeriodService {
|
||||
|
||||
private final MinUsagePeriodMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询最低使用年限表
|
||||
*/
|
||||
@Override
|
||||
public MinUsagePeriodVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据国标代码查询最低使用年限表
|
||||
*/
|
||||
@Override
|
||||
public MinUsagePeriod queryByGbCode(String gbCode) {
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(MinUsagePeriod::getGbCode, gbCode);
|
||||
return baseMapper.selectOne(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最低使用年限表列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<MinUsagePeriodVo> queryPageList(MinUsagePeriodBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = buildQueryWrapper(bo);
|
||||
Page<MinUsagePeriodVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最低使用年限表列表
|
||||
*/
|
||||
@Override
|
||||
public List<MinUsagePeriodVo> queryList(MinUsagePeriodBo bo) {
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<MinUsagePeriod> buildQueryWrapper(MinUsagePeriodBo bo) {
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getCategory()), MinUsagePeriod::getCategory, bo.getCategory());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getContent()), MinUsagePeriod::getContent, bo.getContent());
|
||||
lqw.eq(ObjectUtil.isNotNull(bo.getMinYears()), MinUsagePeriod::getMinYears, bo.getMinYears());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getGbCode()), MinUsagePeriod::getGbCode, bo.getGbCode());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增最低使用年限表
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(MinUsagePeriodBo bo) {
|
||||
MinUsagePeriod add = MapstructUtils.convert(bo, MinUsagePeriod.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改最低使用年限表
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(MinUsagePeriodBo bo) {
|
||||
MinUsagePeriod update = MapstructUtils.convert(bo, MinUsagePeriod.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(MinUsagePeriod entity) {
|
||||
// 校验国标代码唯一性
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(MinUsagePeriod::getGbCode, entity.getGbCode());
|
||||
if (ObjectUtil.isNotNull(entity.getId())) {
|
||||
lqw.ne(MinUsagePeriod::getId, entity.getId());
|
||||
}
|
||||
boolean exists = baseMapper.exists(lqw);
|
||||
if (exists) {
|
||||
throw new RuntimeException("国标代码已存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除最低使用年限表
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入最低使用年限表数据
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String importData(List<MinUsagePeriodVo> dataList, Boolean isUpdateSupport, String operName) {
|
||||
if (ObjectUtil.isNull(dataList) || dataList.size() == 0) {
|
||||
throw new RuntimeException("导入数据不能为空!");
|
||||
}
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
for (MinUsagePeriodVo data : dataList) {
|
||||
try {
|
||||
// 验证是否存在这个数据
|
||||
LambdaQueryWrapper<MinUsagePeriod> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(MinUsagePeriod::getGbCode, data.getGbCode());
|
||||
MinUsagePeriod existData = baseMapper.selectOne(lqw);
|
||||
if (ObjectUtil.isNull(existData)) {
|
||||
MinUsagePeriod addData = MapstructUtils.convert(data, MinUsagePeriod.class);
|
||||
baseMapper.insert(addData);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、国标代码 " + data.getGbCode() + " 导入成功");
|
||||
} else if (isUpdateSupport) {
|
||||
MapstructUtils.convert(data, existData);
|
||||
baseMapper.updateById(existData);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、国标代码 " + data.getGbCode() + " 更新成功");
|
||||
} else {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>" + failureNum + "、国标代码 " + data.getGbCode() + " 已存在");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、国标代码 " + data.getGbCode() + " 导入失败:";
|
||||
failureMsg.append(msg + e.getMessage());
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new RuntimeException(failureMsg.toString());
|
||||
} else {
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.ruoyi.system.domain.vo.MinUsagePeriodImportVo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单的Excel导入测试(不依赖Spring Boot)
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExcelImportSimpleTest {
|
||||
|
||||
/**
|
||||
* Excel文件路径
|
||||
*/
|
||||
private static final String EXCEL_FILE_PATH = "E:/z. WorkSpace/ruoyi-ai/workspace/教育部直属高校固定资产最低使用年限表.xlsx";
|
||||
|
||||
public static void main(String[] args) {
|
||||
ExcelImportSimpleTest test = new ExcelImportSimpleTest();
|
||||
test.testExcelFileRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试Excel文件读取和解析
|
||||
*/
|
||||
@Test
|
||||
public void testExcelFileRead() {
|
||||
try {
|
||||
File excelFile = new File(EXCEL_FILE_PATH);
|
||||
|
||||
if (!excelFile.exists()) {
|
||||
log.error("Excel文件不存在: {}", EXCEL_FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("=== Excel文件信息 ===");
|
||||
log.info("文件路径: {}", excelFile.getAbsolutePath());
|
||||
log.info("文件大小: {} bytes", excelFile.length());
|
||||
log.info("文件是否存在: {}", excelFile.exists());
|
||||
log.info("文件是否可读: {}", excelFile.canRead());
|
||||
|
||||
// 使用EasyExcel直接读取
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
List<MinUsagePeriodImportVo> dataList = EasyExcel.read(inputStream)
|
||||
.head(MinUsagePeriodImportVo.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
|
||||
log.info("=== 读取结果 ===");
|
||||
log.info("EasyExcel直接读取到 {} 条数据", dataList.size());
|
||||
|
||||
// 打印前10条数据
|
||||
for (int i = 0; i < Math.min(10, dataList.size()); i++) {
|
||||
MinUsagePeriodImportVo data = dataList.get(i);
|
||||
log.info("第{}条: 类别={}, 内容={}, 年限={}, 国标代码={}",
|
||||
i + 1, data.getCategory(), data.getContent(), data.getMinYears(), data.getGbCode());
|
||||
}
|
||||
|
||||
// 验证数据完整性
|
||||
validateData(dataList);
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel文件读取测试失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证数据完整性
|
||||
*/
|
||||
private void validateData(List<MinUsagePeriodImportVo> dataList) {
|
||||
log.info("=== 数据验证结果 ===");
|
||||
|
||||
int validCategoryCount = 0;
|
||||
int validContentCount = 0;
|
||||
int validMinYearsCount = 0;
|
||||
int validGbCodeCount = 0;
|
||||
|
||||
for (MinUsagePeriodImportVo data : dataList) {
|
||||
if (data.getCategory() != null && !data.getCategory().trim().isEmpty()) {
|
||||
validCategoryCount++;
|
||||
}
|
||||
if (data.getContent() != null && !data.getContent().trim().isEmpty()) {
|
||||
validContentCount++;
|
||||
}
|
||||
if (data.getMinYears() != null) {
|
||||
validMinYearsCount++;
|
||||
}
|
||||
if (data.getGbCode() != null && !data.getGbCode().trim().isEmpty()) {
|
||||
validGbCodeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
log.info("总行数: {}", dataList.size());
|
||||
log.info("有效固定资产类别: {}/{}", validCategoryCount, dataList.size());
|
||||
log.info("有效内容: {}/{}", validContentCount, dataList.size());
|
||||
log.info("有效最低使用年限: {}/{}", validMinYearsCount, dataList.size());
|
||||
log.info("有效国标代码: {}/{}", validGbCodeCount, dataList.size());
|
||||
|
||||
// 检查重复的国标代码
|
||||
long uniqueGbCodeCount = dataList.stream()
|
||||
.filter(data -> data.getGbCode() != null && !data.getGbCode().trim().isEmpty())
|
||||
.map(MinUsagePeriodImportVo::getGbCode)
|
||||
.distinct()
|
||||
.count();
|
||||
|
||||
log.info("唯一国标代码数量: {}", uniqueGbCodeCount);
|
||||
|
||||
if (uniqueGbCodeCount != validGbCodeCount) {
|
||||
log.warn("发现重复的国标代码!");
|
||||
}
|
||||
|
||||
// 检查数据质量
|
||||
if (validCategoryCount == dataList.size() &&
|
||||
validContentCount == dataList.size() &&
|
||||
validMinYearsCount == dataList.size() &&
|
||||
validGbCodeCount == dataList.size()) {
|
||||
log.info("✓ 数据质量检查通过,所有字段都完整");
|
||||
} else {
|
||||
log.warn("✗ 数据质量检查未通过,存在缺失字段");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试Excel文件格式
|
||||
*/
|
||||
@Test
|
||||
public void testExcelFormat() {
|
||||
try {
|
||||
File excelFile = new File(EXCEL_FILE_PATH);
|
||||
|
||||
if (!excelFile.exists()) {
|
||||
log.error("Excel文件不存在: {}", EXCEL_FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("=== 开始Excel格式测试 ===");
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
// 测试读取第一行(标题行)
|
||||
List<MinUsagePeriodImportVo> dataList = EasyExcel.read(inputStream)
|
||||
.head(MinUsagePeriodImportVo.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
|
||||
if (!dataList.isEmpty()) {
|
||||
MinUsagePeriodImportVo firstData = dataList.get(0);
|
||||
log.info("第一行数据示例:");
|
||||
log.info("- 固定资产类别: {}", firstData.getCategory());
|
||||
log.info("- 内容: {}", firstData.getContent());
|
||||
log.info("- 最低使用年限: {}", firstData.getMinYears());
|
||||
log.info("- 国标代码: {}", firstData.getGbCode());
|
||||
}
|
||||
|
||||
log.info("Excel格式测试完成,共读取 {} 行数据", dataList.size());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel格式测试失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 新Excel文件分析测试
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class NewExcelAnalysisTest {
|
||||
|
||||
/**
|
||||
* 新Excel文件路径
|
||||
*/
|
||||
private static final String NEW_EXCEL_FILE_PATH = "E:/z. WorkSpace/ruoyi-ai/workspace/高等学校固定资产分类与代码.xlsx";
|
||||
|
||||
/**
|
||||
* 分析新Excel文件结构
|
||||
*/
|
||||
@Test
|
||||
public void analyzeNewExcelFile() {
|
||||
try {
|
||||
log.info("=== 开始分析新Excel文件结构 ===");
|
||||
|
||||
File excelFile = new File(NEW_EXCEL_FILE_PATH);
|
||||
if (!excelFile.exists()) {
|
||||
log.error("Excel文件不存在: {}", NEW_EXCEL_FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("文件信息:");
|
||||
log.info("- 文件路径: {}", excelFile.getAbsolutePath());
|
||||
log.info("- 文件大小: {} bytes", excelFile.length());
|
||||
log.info("- 文件是否存在: {}", excelFile.exists());
|
||||
log.info("- 文件是否可读: {}", excelFile.canRead());
|
||||
|
||||
// 1. 读取原始数据(不指定头部)
|
||||
log.info("\n1. 读取原始数据(前20行)...");
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
List<Map<Integer, String>> rawData = EasyExcel.read(inputStream)
|
||||
.sheet()
|
||||
.headRowNumber(0) // 不跳过头部
|
||||
.doReadSync();
|
||||
|
||||
log.info(" 总共读取到 {} 行数据", rawData.size());
|
||||
|
||||
// 显示前20行数据
|
||||
for (int i = 0; i < Math.min(20, rawData.size()); i++) {
|
||||
Map<Integer, String> row = rawData.get(i);
|
||||
log.info(" 第{}行: {}", i + 1, row);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 分析数据结构
|
||||
log.info("\n2. 分析数据结构...");
|
||||
analyzeDataStructure(excelFile);
|
||||
|
||||
// 3. 尝试按指定字段读取
|
||||
log.info("\n3. 尝试按指定字段读取...");
|
||||
tryReadWithFields(excelFile);
|
||||
|
||||
log.info("=== 新Excel文件结构分析完成 ===");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("分析新Excel文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析数据结构
|
||||
*/
|
||||
private void analyzeDataStructure(File excelFile) throws Exception {
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
List<Map<Integer, String>> rawData = EasyExcel.read(inputStream)
|
||||
.sheet()
|
||||
.headRowNumber(0)
|
||||
.doReadSync();
|
||||
|
||||
log.info(" 数据行数: {}", rawData.size());
|
||||
|
||||
// 统计空行
|
||||
int emptyRows = 0;
|
||||
int headerRows = 0;
|
||||
int categoryTitleRows = 0;
|
||||
int dataRows = 0;
|
||||
|
||||
for (int i = 0; i < rawData.size(); i++) {
|
||||
Map<Integer, String> row = rawData.get(i);
|
||||
|
||||
// 检查是否为空行
|
||||
boolean isEmpty = row.values().stream().allMatch(value ->
|
||||
value == null || value.trim().isEmpty());
|
||||
|
||||
if (isEmpty) {
|
||||
emptyRows++;
|
||||
} else {
|
||||
// 检查是否是表头行
|
||||
String firstCell = row.get(0);
|
||||
if (firstCell != null && firstCell.contains("分类代码")) {
|
||||
headerRows++;
|
||||
} else if (firstCell != null && firstCell.trim().length() > 0 &&
|
||||
(row.get(1) == null || row.get(1).trim().isEmpty())) {
|
||||
// 只有第一列有值,其他列为空,可能是分类标题
|
||||
categoryTitleRows++;
|
||||
} else {
|
||||
dataRows++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info(" 空行数量: {}", emptyRows);
|
||||
log.info(" 表头行数量: {}", headerRows);
|
||||
log.info(" 分类标题行数量: {}", categoryTitleRows);
|
||||
log.info(" 数据行数量: {}", dataRows);
|
||||
|
||||
// 显示一些分类标题行的例子
|
||||
log.info(" 分类标题行示例:");
|
||||
int categoryCount = 0;
|
||||
for (int i = 0; i < rawData.size() && categoryCount < 5; i++) {
|
||||
Map<Integer, String> row = rawData.get(i);
|
||||
String firstCell = row.get(0);
|
||||
if (firstCell != null && firstCell.trim().length() > 0 &&
|
||||
(row.get(1) == null || row.get(1).trim().isEmpty())) {
|
||||
log.info(" - 第{}行: {}", i + 1, firstCell);
|
||||
categoryCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试按指定字段读取
|
||||
*/
|
||||
private void tryReadWithFields(File excelFile) throws Exception {
|
||||
// 创建一个简单的VO类来测试字段映射
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
List<Map<Integer, String>> rawData = EasyExcel.read(inputStream)
|
||||
.sheet()
|
||||
.headRowNumber(0)
|
||||
.doReadSync();
|
||||
|
||||
log.info(" 尝试识别有效数据行...");
|
||||
|
||||
int validDataCount = 0;
|
||||
for (int i = 0; i < rawData.size(); i++) {
|
||||
Map<Integer, String> row = rawData.get(i);
|
||||
|
||||
// 检查是否是有效的数据行
|
||||
// 有效数据行应该:第一列有值(分类代码),第二列有值(分类名称),第三列有值(国标名称)
|
||||
String code = row.get(0);
|
||||
String name = row.get(1);
|
||||
String gbName = row.get(2);
|
||||
|
||||
if (code != null && !code.trim().isEmpty() &&
|
||||
name != null && !name.trim().isEmpty() &&
|
||||
gbName != null && !gbName.trim().isEmpty() &&
|
||||
!code.contains("分类代码")) { // 排除表头行
|
||||
|
||||
validDataCount++;
|
||||
if (validDataCount <= 10) {
|
||||
log.info(" 有效数据第{}行: 代码={}, 名称={}, 国标名称={}",
|
||||
validDataCount, code, name, gbName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info(" 识别到 {} 条有效数据", validDataCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 简单的高等学校固定资产分类与代码导入测试
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class SimpleAssetClassificationTest {
|
||||
|
||||
/**
|
||||
* 新Excel文件路径
|
||||
*/
|
||||
private static final String NEW_EXCEL_FILE_PATH = "E:/z. WorkSpace/ruoyi-ai/workspace/高等学校固定资产分类与代码.xlsx";
|
||||
|
||||
/**
|
||||
* 数据库连接信息
|
||||
*/
|
||||
private static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
||||
private static final String DB_USERNAME = "root";
|
||||
private static final String DB_PASSWORD = "666666";
|
||||
|
||||
/**
|
||||
* 测试Excel数据导入到数据库
|
||||
*/
|
||||
@Test
|
||||
public void testAssetClassificationImportToDatabase() {
|
||||
try {
|
||||
log.info("=== 开始高等学校固定资产分类与代码导入测试 ===");
|
||||
|
||||
// 1. 连接数据库
|
||||
log.info("1. 连接数据库...");
|
||||
try (Connection connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD)) {
|
||||
log.info(" 数据库连接成功");
|
||||
|
||||
// 2. 创建表(如果不存在)
|
||||
log.info("2. 创建表(如果不存在)...");
|
||||
createTableIfNotExists(connection);
|
||||
log.info(" 表创建完成");
|
||||
|
||||
// 3. 清空测试数据
|
||||
log.info("3. 清空测试数据...");
|
||||
clearTestData(connection);
|
||||
log.info(" 清空完成");
|
||||
|
||||
// 4. 读取Excel文件
|
||||
log.info("4. 读取Excel文件...");
|
||||
List<Map<Integer, String>> dataList = readExcelFile();
|
||||
log.info(" 读取到 {} 条原始数据", dataList.size());
|
||||
|
||||
// 5. 数据清洗
|
||||
log.info("5. 数据清洗...");
|
||||
List<Map<Integer, String>> cleanedData = cleanData(dataList);
|
||||
log.info(" 清洗后有效数据: {} 条", cleanedData.size());
|
||||
|
||||
// 6. 批量插入数据库
|
||||
log.info("6. 批量插入数据库...");
|
||||
int successCount = insertDataToDatabase(connection, cleanedData);
|
||||
log.info(" 插入完成: 成功 {} 条", successCount);
|
||||
|
||||
// 7. 验证数据库中的数据
|
||||
log.info("7. 验证数据库中的数据...");
|
||||
int dbCount = getDatabaseRecordCount(connection);
|
||||
log.info(" 数据库中共有 {} 条记录", dbCount);
|
||||
|
||||
// 8. 显示部分数据
|
||||
log.info("8. 显示部分数据...");
|
||||
showSampleData(connection);
|
||||
|
||||
// 9. 数据质量分析
|
||||
log.info("9. 数据质量分析...");
|
||||
analyzeDataQuality(connection);
|
||||
|
||||
}
|
||||
|
||||
log.info("=== 高等学校固定资产分类与代码导入测试完成 ===");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("高等学校固定资产分类与代码导入测试失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建表(如果不存在)
|
||||
*/
|
||||
private void createTableIfNotExists(Connection connection) throws Exception {
|
||||
String createTableSql = """
|
||||
CREATE TABLE IF NOT EXISTS `asset_classification` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`classification_code` varchar(20) NOT NULL COMMENT '分类代码',
|
||||
`classification_name` varchar(200) NOT NULL COMMENT '分类名称',
|
||||
`gb_name` varchar(200) NOT NULL COMMENT '国标名称',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_classification_code` (`classification_code`),
|
||||
KEY `idx_classification_name` (`classification_name`),
|
||||
KEY `idx_gb_name` (`gb_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='高等学校固定资产分类与代码表'
|
||||
""";
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(createTableSql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空测试数据
|
||||
*/
|
||||
private void clearTestData(Connection connection) throws Exception {
|
||||
String deleteSql = "DELETE FROM asset_classification";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.executeUpdate(deleteSql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取Excel文件
|
||||
*/
|
||||
private List<Map<Integer, String>> readExcelFile() throws Exception {
|
||||
File excelFile = new File(NEW_EXCEL_FILE_PATH);
|
||||
if (!excelFile.exists()) {
|
||||
throw new RuntimeException("Excel文件不存在: " + NEW_EXCEL_FILE_PATH);
|
||||
}
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
return EasyExcel.read(inputStream)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据清洗
|
||||
*/
|
||||
private List<Map<Integer, String>> cleanData(List<Map<Integer, String>> dataList) {
|
||||
return dataList.stream()
|
||||
.filter(this::isValidData)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证数据是否有效
|
||||
*/
|
||||
private boolean isValidData(Map<Integer, String> data) {
|
||||
// 过滤空行
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String code = data.get(0);
|
||||
String name = data.get(1);
|
||||
String gbName = data.get(2);
|
||||
|
||||
// 过滤表头行
|
||||
if ("分类代码".equals(code) ||
|
||||
"分类名称".equals(name) ||
|
||||
"国标名称".equals(gbName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 过滤分类标题行(只有第一列有值,其他列为空)
|
||||
if (code != null && !code.trim().isEmpty() &&
|
||||
(name == null || name.trim().isEmpty()) &&
|
||||
(gbName == null || gbName.trim().isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 过滤包含"表"、"续表"等标题行
|
||||
if (code != null &&
|
||||
(code.contains("表") ||
|
||||
code.contains("续表"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证必填字段
|
||||
return code != null && !code.trim().isEmpty() &&
|
||||
name != null && !name.trim().isEmpty() &&
|
||||
gbName != null && !gbName.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据到数据库
|
||||
*/
|
||||
private int insertDataToDatabase(Connection connection, List<Map<Integer, String>> dataList) throws Exception {
|
||||
String insertSql = "INSERT INTO asset_classification (classification_code, classification_name, gb_name) VALUES (?, ?, ?)";
|
||||
|
||||
int successCount = 0;
|
||||
try (PreparedStatement statement = connection.prepareStatement(insertSql)) {
|
||||
for (Map<Integer, String> data : dataList) {
|
||||
try {
|
||||
String code = data.get(0);
|
||||
String name = data.get(1);
|
||||
String gbName = data.get(2);
|
||||
|
||||
statement.setString(1, code);
|
||||
statement.setString(2, name);
|
||||
statement.setString(3, gbName);
|
||||
|
||||
statement.executeUpdate();
|
||||
successCount++;
|
||||
|
||||
if (successCount <= 5) {
|
||||
log.info(" 插入成功: {} - {}", code, name);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(" 插入失败: {} - {}", data.get(0), data.get(1), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return successCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库记录数
|
||||
*/
|
||||
private int getDatabaseRecordCount(Connection connection) throws Exception {
|
||||
String countSql = "SELECT COUNT(*) FROM asset_classification";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(countSql);
|
||||
if (resultSet.next()) {
|
||||
return resultSet.getInt(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示部分数据
|
||||
*/
|
||||
private void showSampleData(Connection connection) throws Exception {
|
||||
String selectSql = "SELECT * FROM asset_classification LIMIT 10";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(selectSql);
|
||||
int count = 0;
|
||||
while (resultSet.next() && count < 10) {
|
||||
count++;
|
||||
String code = resultSet.getString("classification_code");
|
||||
String name = resultSet.getString("classification_name");
|
||||
String gbName = resultSet.getString("gb_name");
|
||||
|
||||
log.info(" 第{}条: 代码={}, 名称={}, 国标名称={}",
|
||||
count, code, name, gbName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据质量分析
|
||||
*/
|
||||
private void analyzeDataQuality(Connection connection) throws Exception {
|
||||
log.info(" 数据质量分析:");
|
||||
|
||||
// 总记录数
|
||||
int totalCount = getDatabaseRecordCount(connection);
|
||||
log.info(" - 总记录数: {}", totalCount);
|
||||
|
||||
// 统计分类代码长度分布
|
||||
String lengthSql = "SELECT LENGTH(classification_code) as code_length, COUNT(*) as count FROM asset_classification GROUP BY LENGTH(classification_code) ORDER BY code_length";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(lengthSql);
|
||||
log.info(" - 分类代码长度分布:");
|
||||
while (resultSet.next()) {
|
||||
int length = resultSet.getInt("code_length");
|
||||
int count = resultSet.getInt("count");
|
||||
log.info(" * {}位: {} 条", length, count);
|
||||
}
|
||||
}
|
||||
|
||||
// 统计国标名称分布
|
||||
String gbNameSql = "SELECT gb_name, COUNT(*) as count FROM asset_classification GROUP BY gb_name ORDER BY count DESC LIMIT 10";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(gbNameSql);
|
||||
log.info(" - 国标名称分布(前10):");
|
||||
while (resultSet.next()) {
|
||||
String gbName = resultSet.getString("gb_name");
|
||||
int count = resultSet.getInt("count");
|
||||
log.info(" * {}: {} 条", gbName, count);
|
||||
}
|
||||
}
|
||||
|
||||
log.info(" - 数据质量: 优秀 (所有字段都完整)");
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.ruoyi.system.domain.MinUsagePeriod;
|
||||
import org.ruoyi.system.domain.vo.MinUsagePeriodImportVo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单数据库测试(不依赖Spring Boot)
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class SimpleDatabaseTest {
|
||||
|
||||
/**
|
||||
* Excel文件路径
|
||||
*/
|
||||
private static final String EXCEL_FILE_PATH = "E:/z. WorkSpace/ruoyi-ai/workspace/教育部直属高校固定资产最低使用年限表.xlsx";
|
||||
|
||||
/**
|
||||
* 数据库连接信息
|
||||
*/
|
||||
private static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
||||
private static final String DB_USERNAME = "root";
|
||||
private static final String DB_PASSWORD = "666666";
|
||||
|
||||
/**
|
||||
* 测试Excel数据导入到数据库
|
||||
*/
|
||||
@Test
|
||||
public void testExcelImportToDatabase() {
|
||||
try {
|
||||
log.info("=== 开始Excel数据导入到数据库测试 ===");
|
||||
|
||||
// 1. 连接数据库
|
||||
log.info("1. 连接数据库...");
|
||||
try (Connection connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD)) {
|
||||
log.info(" 数据库连接成功");
|
||||
|
||||
// 2. 创建表(如果不存在)
|
||||
log.info("2. 创建表(如果不存在)...");
|
||||
createTableIfNotExists(connection);
|
||||
log.info(" 表创建完成");
|
||||
|
||||
// 3. 清空测试数据
|
||||
log.info("3. 清空测试数据...");
|
||||
clearTestData(connection);
|
||||
log.info(" 清空完成");
|
||||
|
||||
// 4. 读取Excel文件
|
||||
log.info("4. 读取Excel文件...");
|
||||
List<MinUsagePeriodImportVo> dataList = readExcelFile();
|
||||
log.info(" 读取到 {} 条数据", dataList.size());
|
||||
|
||||
// 5. 处理数据(填充固定资产类别)
|
||||
log.info("5. 处理数据...");
|
||||
processData(dataList);
|
||||
log.info(" 数据处理完成");
|
||||
|
||||
// 6. 批量插入数据库
|
||||
log.info("6. 批量插入数据库...");
|
||||
int successCount = insertDataToDatabase(connection, dataList);
|
||||
log.info(" 插入完成: 成功 {} 条", successCount);
|
||||
|
||||
// 7. 验证数据库中的数据
|
||||
log.info("7. 验证数据库中的数据...");
|
||||
int dbCount = getDatabaseRecordCount(connection);
|
||||
log.info(" 数据库中共有 {} 条记录", dbCount);
|
||||
|
||||
// 8. 显示部分数据
|
||||
log.info("8. 显示部分数据...");
|
||||
showSampleData(connection);
|
||||
|
||||
}
|
||||
|
||||
log.info("=== Excel数据导入到数据库测试完成 ===");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel数据导入到数据库测试失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建表(如果不存在)
|
||||
*/
|
||||
private void createTableIfNotExists(Connection connection) throws Exception {
|
||||
String createTableSql = """
|
||||
CREATE TABLE IF NOT EXISTS `min_usage_period` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`category` varchar(100) NOT NULL COMMENT '固定资产类别',
|
||||
`content` varchar(200) NOT NULL COMMENT '内容',
|
||||
`min_years` int(11) NOT NULL COMMENT '最低使用年限(年)',
|
||||
`gb_code` varchar(20) NOT NULL COMMENT '国标代码',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_gb_code` (`gb_code`),
|
||||
KEY `idx_category` (`category`),
|
||||
KEY `idx_content` (`content`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='最低使用年限表'
|
||||
""";
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(createTableSql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空测试数据
|
||||
*/
|
||||
private void clearTestData(Connection connection) throws Exception {
|
||||
String deleteSql = "DELETE FROM min_usage_period";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.executeUpdate(deleteSql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取Excel文件
|
||||
*/
|
||||
private List<MinUsagePeriodImportVo> readExcelFile() throws Exception {
|
||||
File excelFile = new File(EXCEL_FILE_PATH);
|
||||
if (!excelFile.exists()) {
|
||||
throw new RuntimeException("Excel文件不存在: " + EXCEL_FILE_PATH);
|
||||
}
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
return EasyExcel.read(inputStream)
|
||||
.head(MinUsagePeriodImportVo.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据,填充固定资产类别
|
||||
*/
|
||||
private void processData(List<MinUsagePeriodImportVo> dataList) {
|
||||
String currentCategory = null;
|
||||
|
||||
for (MinUsagePeriodImportVo data : dataList) {
|
||||
// 如果当前行有固定资产类别,更新当前类别
|
||||
if (data.getCategory() != null && !data.getCategory().trim().isEmpty()) {
|
||||
currentCategory = data.getCategory().trim();
|
||||
}
|
||||
|
||||
// 如果当前行没有固定资产类别,使用当前类别
|
||||
if (data.getCategory() == null || data.getCategory().trim().isEmpty()) {
|
||||
data.setCategory(currentCategory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据到数据库
|
||||
*/
|
||||
private int insertDataToDatabase(Connection connection, List<MinUsagePeriodImportVo> dataList) throws Exception {
|
||||
String insertSql = "INSERT INTO min_usage_period (category, content, min_years, gb_code) VALUES (?, ?, ?, ?)";
|
||||
|
||||
int successCount = 0;
|
||||
try (PreparedStatement statement = connection.prepareStatement(insertSql)) {
|
||||
for (MinUsagePeriodImportVo data : dataList) {
|
||||
try {
|
||||
statement.setString(1, data.getCategory());
|
||||
statement.setString(2, data.getContent());
|
||||
statement.setInt(3, data.getMinYears());
|
||||
statement.setString(4, data.getGbCode());
|
||||
|
||||
statement.executeUpdate();
|
||||
successCount++;
|
||||
|
||||
if (successCount <= 5) {
|
||||
log.info(" 插入成功: {} - {}", data.getContent(), data.getGbCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(" 插入失败: {} - {}", data.getContent(), data.getGbCode(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return successCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库记录数
|
||||
*/
|
||||
private int getDatabaseRecordCount(Connection connection) throws Exception {
|
||||
String countSql = "SELECT COUNT(*) FROM min_usage_period";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(countSql);
|
||||
if (resultSet.next()) {
|
||||
return resultSet.getInt(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示部分数据
|
||||
*/
|
||||
private void showSampleData(Connection connection) throws Exception {
|
||||
String selectSql = "SELECT * FROM min_usage_period LIMIT 10";
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
var resultSet = statement.executeQuery(selectSql);
|
||||
int count = 0;
|
||||
while (resultSet.next() && count < 10) {
|
||||
count++;
|
||||
String category = resultSet.getString("category");
|
||||
String content = resultSet.getString("content");
|
||||
int minYears = resultSet.getInt("min_years");
|
||||
String gbCode = resultSet.getString("gb_code");
|
||||
|
||||
log.info(" 第{}条: 类别={}, 内容={}, 年限={}, 国标代码={}",
|
||||
count, category, content, minYears, gbCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package org.ruoyi.system.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.system.domain.vo.MinUsagePeriodImportVo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单的Excel导入测试(不依赖Spring Boot)
|
||||
*
|
||||
* @author cass
|
||||
* @date 2025-09-24
|
||||
*/
|
||||
@Slf4j
|
||||
public class SimpleExcelImportTest {
|
||||
|
||||
/**
|
||||
* 测试Excel文件读取
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SimpleExcelImportTest test = new SimpleExcelImportTest();
|
||||
test.testExcelFileRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试Excel文件读取和解析
|
||||
*/
|
||||
public void testExcelFileRead() {
|
||||
try {
|
||||
String excelPath = "workspace/教育部直属高校固定资产最低使用年限表.xlsx";
|
||||
File excelFile = new File(excelPath);
|
||||
|
||||
if (!excelFile.exists()) {
|
||||
log.error("Excel文件不存在: {}", excelPath);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Excel文件信息:");
|
||||
log.info("文件路径: {}", excelFile.getAbsolutePath());
|
||||
log.info("文件大小: {} bytes", excelFile.length());
|
||||
log.info("文件是否存在: {}", excelFile.exists());
|
||||
log.info("文件是否可读: {}", excelFile.canRead());
|
||||
|
||||
// 使用EasyExcel直接读取
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
List<MinUsagePeriodImportVo> dataList = EasyExcel.read(inputStream)
|
||||
.head(MinUsagePeriodImportVo.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
|
||||
log.info("EasyExcel直接读取到 {} 条数据", dataList.size());
|
||||
|
||||
// 打印所有数据
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
MinUsagePeriodImportVo data = dataList.get(i);
|
||||
log.info("第{}条: 类别={}, 内容={}, 年限={}, 国标代码={}",
|
||||
i + 1, data.getCategory(), data.getContent(), data.getMinYears(), data.getGbCode());
|
||||
}
|
||||
|
||||
// 验证数据完整性
|
||||
validateData(dataList);
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel文件读取测试失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证数据完整性
|
||||
*/
|
||||
private void validateData(List<MinUsagePeriodImportVo> dataList) {
|
||||
log.info("开始数据验证...");
|
||||
|
||||
int validCategoryCount = 0;
|
||||
int validContentCount = 0;
|
||||
int validMinYearsCount = 0;
|
||||
int validGbCodeCount = 0;
|
||||
|
||||
for (MinUsagePeriodImportVo data : dataList) {
|
||||
if (data.getCategory() != null && !data.getCategory().trim().isEmpty()) {
|
||||
validCategoryCount++;
|
||||
}
|
||||
if (data.getContent() != null && !data.getContent().trim().isEmpty()) {
|
||||
validContentCount++;
|
||||
}
|
||||
if (data.getMinYears() != null) {
|
||||
validMinYearsCount++;
|
||||
}
|
||||
if (data.getGbCode() != null && !data.getGbCode().trim().isEmpty()) {
|
||||
validGbCodeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
log.info("数据验证结果:");
|
||||
log.info("- 总行数: {}", dataList.size());
|
||||
log.info("- 有效固定资产类别: {}/{}", validCategoryCount, dataList.size());
|
||||
log.info("- 有效内容: {}/{}", validContentCount, dataList.size());
|
||||
log.info("- 有效最低使用年限: {}/{}", validMinYearsCount, dataList.size());
|
||||
log.info("- 有效国标代码: {}/{}", validGbCodeCount, dataList.size());
|
||||
|
||||
// 检查重复的国标代码
|
||||
long uniqueGbCodeCount = dataList.stream()
|
||||
.filter(data -> data.getGbCode() != null && !data.getGbCode().trim().isEmpty())
|
||||
.map(MinUsagePeriodImportVo::getGbCode)
|
||||
.distinct()
|
||||
.count();
|
||||
|
||||
log.info("- 唯一国标代码数量: {}", uniqueGbCodeCount);
|
||||
|
||||
if (uniqueGbCodeCount != validGbCodeCount) {
|
||||
log.warn("发现重复的国标代码!");
|
||||
}
|
||||
|
||||
// 检查数据质量
|
||||
if (validCategoryCount == dataList.size() &&
|
||||
validContentCount == dataList.size() &&
|
||||
validMinYearsCount == dataList.size() &&
|
||||
validGbCodeCount == dataList.size()) {
|
||||
log.info("✓ 数据质量检查通过,所有字段都完整");
|
||||
} else {
|
||||
log.warn("✗ 数据质量检查未通过,存在缺失字段");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试Excel文件格式
|
||||
*/
|
||||
public void testExcelFormat() {
|
||||
try {
|
||||
String excelPath = "workspace/教育部直属高校固定资产最低使用年限表.xlsx";
|
||||
File excelFile = new File(excelPath);
|
||||
|
||||
if (!excelFile.exists()) {
|
||||
log.error("Excel文件不存在: {}", excelPath);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("开始Excel格式测试...");
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(excelFile)) {
|
||||
// 测试读取第一行(标题行)
|
||||
List<MinUsagePeriodImportVo> dataList = EasyExcel.read(inputStream)
|
||||
.head(MinUsagePeriodImportVo.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
|
||||
if (!dataList.isEmpty()) {
|
||||
MinUsagePeriodImportVo firstData = dataList.get(0);
|
||||
log.info("第一行数据示例:");
|
||||
log.info("- 固定资产类别: {}", firstData.getCategory());
|
||||
log.info("- 内容: {}", firstData.getContent());
|
||||
log.info("- 最低使用年限: {}", firstData.getMinYears());
|
||||
log.info("- 国标代码: {}", firstData.getGbCode());
|
||||
}
|
||||
|
||||
log.info("Excel格式测试完成,共读取 {} 行数据", dataList.size());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel格式测试失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
# 测试环境配置
|
||||
spring:
|
||||
# 数据源配置
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
dynamic:
|
||||
@@ -31,27 +32,45 @@ spring:
|
||||
database: 0
|
||||
timeout: 10S
|
||||
|
||||
# MyBatis Plus配置
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:mapper/**/*Mapper.xml
|
||||
type-aliases-package: org.ruoyi.**.domain
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
cache-enabled: false
|
||||
call-setters-on-nulls: true
|
||||
jdbc-type-for-null: 'null'
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: AUTO
|
||||
logic-delete-field: delFlag
|
||||
logic-delete-value: 2
|
||||
logic-not-delete-value: 0
|
||||
# MyBatis Plus配置
|
||||
mybatis-plus:
|
||||
# 搜索指定包别名
|
||||
typeAliasesPackage: org.ruoyi.**.domain
|
||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 加载全局的配置文件
|
||||
configLocation: classpath:mybatis/mybatis-config.xml
|
||||
configuration:
|
||||
# 自动驼峰命名规则(camel case)映射
|
||||
mapUnderscoreToCamelCase: true
|
||||
# MyBatis 自动映射策略
|
||||
# NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
|
||||
autoMappingBehavior: PARTIAL
|
||||
# MyBatis 自动映射时未知列或未知属性处理策
|
||||
# NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
|
||||
autoMappingUnknownColumnBehavior: NONE
|
||||
# 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
# 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
global-config:
|
||||
# 是否打印 Logo banner
|
||||
banner: true
|
||||
dbConfig:
|
||||
# 主键类型
|
||||
# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
|
||||
idType: ASSIGN_ID
|
||||
# 逻辑删除配置
|
||||
logicDeleteField: delFlag
|
||||
logicDeleteValue: 2
|
||||
logicNotDeleteValue: 0
|
||||
insertStrategy: NOT_NULL
|
||||
updateStrategy: NOT_NULL
|
||||
where-strategy: NOT_NULL
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
org.ruoyi: DEBUG
|
||||
org.springframework: WARN
|
||||
com.baomidou.mybatisplus: WARN
|
||||
pattern:
|
||||
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n'
|
||||
org.ruoyi: debug
|
||||
org.springframework: warn
|
||||
com.alibaba.excel: debug
|
||||
Reference in New Issue
Block a user