sxwz2.0/src/main/java/com/kexue/skills/service/impl/CmsContentServiceImpl.java
wangzhiwei 891f60d5a5 feat(account): 添加账户交易记录分页查询功能
- 新增充值记录、消费记录和赠送记录的分页查询接口
- 实现消费记录按callId分组查询功能
- 添加账户交易记录DTO和分组查询DTO定义
- 在AccountController中添加日志注解和相关API端点
- 优化AccountServiceImpl中的数据库操作方法调用
- 修改AccountTransactionMapper.xml增加相应的SQL查询语句
- 添加创建时间范围筛选功能到交易记录查询中
- 实现CMS内容管理的路径更新功能和标签查询优化
2026-04-21 09:32:17 +08:00

1199 lines
46 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.kexue.skills.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.kexue.skills.common.Assert;
import com.kexue.skills.common.LoginUserCacheUtil;
import com.kexue.skills.entity.CmsContent;
import com.kexue.skills.entity.CmsContentView;
import com.kexue.skills.entity.CmsContentLike;
import com.kexue.skills.entity.base.BaseQueryDto;
import com.kexue.skills.entity.dto.CmsContentDto;
import com.kexue.skills.entity.request.ImportPathDto;
import com.kexue.skills.mapper.CmsContentMapper;
import com.kexue.skills.mapper.CmsContentViewMapper;
import com.kexue.skills.mapper.CmsContentLikeMapper;
import com.kexue.skills.mapper.CmsTagMapper;
import com.kexue.skills.entity.CmsTag;
import com.kexue.skills.entity.dto.CmsTagDto;
import com.kexue.skills.service.CmsContentService;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import cn.dev33.satoken.stp.StpUtil;
/**
* (CmsContent)表服务实现类
*
* @author 王志维
* @since 2025-02-21 23:01:48
*/
@Service("cmsContentService")
@Transactional(rollbackFor = Exception.class)
public class CmsContentServiceImpl implements CmsContentService {
@Resource
private CmsContentMapper cmsContentMapper;
@Resource
private CmsContentViewMapper cmsContentViewMapper;
@Resource
private CmsContentLikeMapper cmsContentLikeMapper;
@Resource
private CmsTagMapper cmsTagMapper;
@Resource
private LoginUserCacheUtil loginUserCacheUtil;
/**
* 分页查询
*
* @param queryDto 筛选条件
* @return 查询结果
*/
@Override
public PageInfo<CmsContent> getPageList(CmsContentDto queryDto) {
// 添加参数校验,确保分页参数有效
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
}
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
}
// 使用 PageHelper 进行分页
PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
// 设置默认语言类型为中文
if (queryDto.getLanguageType() == null) {
queryDto.setLanguageType(0);
}
List<CmsContent> list = this.cmsContentMapper.getPageList(queryDto);
return new PageInfo<>(list);
}
/**
* 内存分页方法
*
* @param list 原始数据列表
* @param pageNum 页码
* @param pageSize 每页大小
* @return 当前页的 list对应的页码没有数据则返回空 list
*/
private List<CmsContent> memoryPagination(List<CmsContent> list, int pageNum, int pageSize) {
// 参数校验
if (list == null) {
return new ArrayList<>();
}
if (pageNum < 1) {
pageNum = 1;
}
if (pageSize < 1) {
pageSize = 10;
}
// 计算总记录数
int total = list.size();
// 计算分页参数
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, total);
// 截取分页数据
List<CmsContent> pageList = new ArrayList<>();
if (startIndex < total) {
pageList = list.subList(startIndex, endIndex);
}
return pageList;
}
/**
* 查询列表
*
* @param queryDto 筛选条件
* @return 查询结果
*/
@Override
public List<CmsContent> getList(CmsContentDto queryDto) {
// 设置默认语言类型为中文
if (queryDto.getLanguageType() == null) {
queryDto.setLanguageType(0);
}
return this.cmsContentMapper.getList(queryDto);
}
/**
* 通过主键查询单条数据
*
* @param contentId 主键
* @return 实例对象
*/
@Override
public CmsContent queryById(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
CmsContent content = this.cmsContentMapper.queryById(contentId);
if (content == null) {
return null;
}
try {
// 尝试获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 检查用户是否已经查看过该内容5分钟内
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
if (existingView == null) {
// 新增查看记录
CmsContentView viewRecord = new CmsContentView();
viewRecord.setUserId(userId);
viewRecord.setUserName(StpUtil.getLoginIdAsString());
viewRecord.setContentId(contentId);
viewRecord.setContentTitle(content.getTitle());
viewRecord.setViewTime(new Date());
viewRecord.setDeleteFlag(0);
viewRecord.setCreateBy(StpUtil.getLoginIdAsString());
viewRecord.setUpdateBy(StpUtil.getLoginIdAsString());
cmsContentViewMapper.insert(viewRecord);
} else {
// 检查是否超过5分钟
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
if (existingView.getViewTime().before(fiveMinutesAgo)) {
// 更新查看时间
existingView.setViewTime(new Date());
existingView.setUpdateBy(StpUtil.getLoginIdAsString());
cmsContentViewMapper.update(existingView);
}
}
} catch (Exception e) {
// 未登录用户,不记录查看历史
}
return content;
}
/**
* 通过主键查询单条数据,带权限检查
*
* @param contentId 主键
* @param userId 用户ID
* @return 实例对象
*/
public CmsContent queryByIdWithPermission(Long contentId, Long userId) {
Assert.notNull(contentId, "内容ID不能为空");
CmsContent content = this.cmsContentMapper.queryById(contentId);
if (content == null) {
return null;
}
// 如果是付费内容,检查用户是否购买过
if (content.getIsPaid() == 1) {
// 这里需要调用ContentPurchaseService检查权限但为了避免循环依赖我们返回完整内容
// 权限检查将在Controller层进行
}
return content;
}
/**
* 新增数据
*
* @param cmsContent 实例对象
* @return 实例对象
*/
@Override
public CmsContent insert(CmsContent cmsContent) {
// 设置创建时间和更新时间
Date now = new Date();
cmsContent.setCreateTime(now);
cmsContent.setUpdateTime(now);
// 设置默认值
cmsContent.setDeleteFlag(0);
if (cmsContent.getAuditStatus() == null) {
cmsContent.setAuditStatus(1); // 默认草稿状态
}
if (cmsContent.getPublishStatus() == null) {
cmsContent.setPublishStatus(1); // 默认未发布状态
}
if (cmsContent.getViewCount() == null) {
cmsContent.setViewCount(0);
}
if (cmsContent.getLikeCount() == null) {
cmsContent.setLikeCount(0);
}
if (cmsContent.getCommentCount() == null) {
cmsContent.setCommentCount(0);
}
if (cmsContent.getShareCount() == null) {
cmsContent.setShareCount(0);
}
if (cmsContent.getSort() == null) {
cmsContent.setSort(0);
}
if (cmsContent.getIsOfficial() == null) {
cmsContent.setIsOfficial(false);
}
cmsContent.setAuthorId(StpUtil.getLoginIdAsLong());
// 保存数据
this.cmsContentMapper.insert(cmsContent);
return cmsContent;
}
/**
* 更新数据
*
* @param cmsContent 实例对象
* @return 实例对象
*/
@Override
public CmsContent update(CmsContent cmsContent) {
Assert.notNull(cmsContent.getContentId(), "内容ID不能为空");
// 设置更新时间
cmsContent.setUpdateTime(new Date());
// 更新数据
this.cmsContentMapper.update(cmsContent);
return this.queryById(cmsContent.getContentId());
}
/**
* 更新审核状态
*
* @param contentId 内容ID
* @param auditStatus 审核状态
* @param reviewerId 审核人ID
* @param reviewerName 审核人名称
* @param auditComment 审核意见
* @param updateBy 更新人
* @return 影响行数
*/
@Override
public int updateAuditStatus(Long contentId, Integer auditStatus, Long reviewerId, String reviewerName, String auditComment, String updateBy) {
Assert.notNull(contentId, "内容ID不能为空");
return this.cmsContentMapper.updateAuditStatus(contentId, auditStatus, reviewerId, reviewerName, auditComment, updateBy);
}
/**
* 更新发布状态
*
* @param contentId 内容ID
* @param publishStatus 发布状态
* @param publishTime 发布时间
* @param updateBy 更新人
* @return 影响行数
*/
@Override
public int updatePublishStatus(Long contentId, Integer publishStatus, String publishTime, String updateBy) {
Assert.notNull(contentId, "内容ID不能为空");
return this.cmsContentMapper.updatePublishStatus(contentId, publishStatus, publishTime, updateBy);
}
/**
* 增加阅读量
*
* @param contentId 内容ID
* @return 影响行数
*/
@Override
public int increaseViewCount(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
// 增加阅读量
int result = this.cmsContentMapper.increaseViewCount(contentId);
try {
// 尝试获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 调用addView方法添加查看记录
this.addView(contentId);
} catch (Exception e) {
// 未登录用户,不记录查看历史
}
return result;
}
/**
* 通过主键逻辑删除
*
* @param contentId 主键
* @param updateBy 更新人
* @return 影响行数
*/
@Override
public int logicDeleteById(Long contentId, String updateBy) {
Assert.notNull(contentId, "内容ID不能为空");
return this.cmsContentMapper.logicDeleteById(contentId, updateBy);
}
/**
* 通过主键物理删除
*
* @param contentId 主键
* @return 影响行数
*/
@Override
public int deleteById(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
return this.cmsContentMapper.deleteById(contentId);
}
/**
* 添加/取消收藏
*
* @param contentId 内容ID
* @return 影响行数
*/
@Override
public int addFavorite(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 获取当前登录用户名
String userName = StpUtil.getLoginIdAsString();
// 检查内容是否存在
CmsContent content = this.cmsContentMapper.queryById(contentId);
if (content == null) {
return 0;
}
if(Objects.isNull(content.getLikeCount())){
content.setLikeCount(0);
}
// 检查用户是否已经收藏过该内容
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
int result = 0;
if (existingLike != null) {
// 已经收藏过,执行取消收藏操作
result = cmsContentLikeMapper.deleteById(existingLike.getLikeId());
// 减少内容的点赞数
if (content != null && content.getLikeCount() > 0) {
content.setLikeCount(content.getLikeCount() - 1);
this.cmsContentMapper.update(content);
}
} else {
// 未收藏过,执行添加收藏操作
CmsContentLike likeRecord = new CmsContentLike();
likeRecord.setUserId(userId);
likeRecord.setUserName(userName);
likeRecord.setContentId(contentId);
likeRecord.setContentTitle(content.getTitle());
likeRecord.setLikeTime(new Date());
likeRecord.setDeleteFlag(0);
// 增加内容的点赞数
content.setLikeCount(content.getLikeCount() + 1);
this.cmsContentMapper.update(content);
result = cmsContentLikeMapper.insert(likeRecord);
}
// 更新Redis中的LoginUser对象
if (result > 0) {
String token = loginUserCacheUtil.getTokenFromRequest();
if (token != null) {
loginUserCacheUtil.updateFavorites(token, userId);
}
}
return result;
}
/**
* 取消收藏
*
* @param contentId 内容ID
* @return 影响行数
*/
@Override
public int removeFavorite(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 检查用户是否已经收藏过该内容
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
if (existingLike == null) {
return 0; // 没有收藏过,无需取消
}
// 删除收藏记录
int result = cmsContentLikeMapper.deleteById(existingLike.getLikeId());
// 减少内容的点赞数
CmsContent content = this.cmsContentMapper.queryById(contentId);
if (content != null && content.getLikeCount() > 0) {
content.setLikeCount(content.getLikeCount() - 1);
this.cmsContentMapper.update(content);
}
// 更新Redis中的LoginUser对象
if (result > 0) {
String token = loginUserCacheUtil.getTokenFromRequest();
if (token != null) {
loginUserCacheUtil.updateFavorites(token, userId);
}
}
return result;
}
/**
* 检查用户是否已收藏该内容
*
* @param contentId 内容ID
* @return 是否已收藏
*/
@Override
public boolean isFavorited(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
try {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
return existingLike != null;
} catch (Exception e) {
// 未登录用户返回false
return false;
}
}
/**
* 添加查看记录
*
* @param contentId 内容ID
* @return 影响行数
*/
@Override
public int addView(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
try {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 获取当前登录用户名
String userName = StpUtil.getLoginIdAsString();
// 检查内容是否存在
CmsContent content = this.cmsContentMapper.queryById(contentId);
if (content == null) {
return 0;
}
// 检查用户是否已经查看过该内容5分钟内
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
int result = 0;
if (existingView == null) {
// 新增查看记录
CmsContentView viewRecord = new CmsContentView();
viewRecord.setUserId(userId);
viewRecord.setUserName(userName);
viewRecord.setContentId(contentId);
viewRecord.setContentTitle(content.getTitle());
viewRecord.setViewTime(new Date());
viewRecord.setDeleteFlag(0);
viewRecord.setCreateBy(userName);
viewRecord.setUpdateBy(userName);
result = cmsContentViewMapper.insert(viewRecord);
} else {
// 检查是否超过5分钟
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
if (existingView.getViewTime().before(fiveMinutesAgo)) {
// 更新查看时间
existingView.setViewTime(new Date());
existingView.setUpdateBy(userName);
result = cmsContentViewMapper.update(existingView);
}
// 5分钟内已查看过不重复记录
}
// 更新Redis中的LoginUser对象
if (result > 0) {
String token = loginUserCacheUtil.getTokenFromRequest();
if (token != null) {
loginUserCacheUtil.updateHistory(token, userId);
}
}
return result;
} catch (Exception e) {
// 未登录用户,不记录查看历史
return 0;
}
}
@Override
public PageInfo<CmsContent> getPageListByUserHistory(CmsContentDto queryDto) {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 添加参数校验,确保分页参数有效
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
}
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
}
// 计算偏移量
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
int limit = queryDto.getPageSize();
// 查询数据
List<CmsContent> list = this.cmsContentMapper.getPageListByUserHistory(userId, offset, limit);
int total = this.cmsContentMapper.getPageListByUserHistoryCount(userId);
// 构建分页结果
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
pageInfo.setTotal(total);
pageInfo.setPageNum(queryDto.getPageNum());
pageInfo.setPageSize(queryDto.getPageSize());
pageInfo.setPages((total + limit - 1) / limit);
return pageInfo;
}
@Override
public PageInfo<CmsContent> getPageListByUserFavorites(CmsContentDto queryDto) {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 添加参数校验,确保分页参数有效
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
}
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
}
// 计算偏移量
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
int limit = queryDto.getPageSize();
// 查询数据
List<CmsContent> list = this.cmsContentMapper.getPageListByUserFavorites(userId, offset, limit);
int total = this.cmsContentMapper.getPageListByUserFavoritesCount(userId);
// 构建分页结果
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
pageInfo.setTotal(total);
pageInfo.setPageNum(queryDto.getPageNum());
pageInfo.setPageSize(queryDto.getPageSize());
pageInfo.setPages((total + limit - 1) / limit);
return pageInfo;
}
@Override
public PageInfo<CmsContent> getPageListByUserPurchases(CmsContentDto queryDto) {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 添加参数校验,确保分页参数有效
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
}
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
}
// 计算偏移量
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
int limit = queryDto.getPageSize();
// 查询数据
List<CmsContent> list = this.cmsContentMapper.getPageListByUserPurchases(userId, offset, limit);
int total = this.cmsContentMapper.getPageListByUserPurchasesCount(userId);
// 构建分页结果
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
pageInfo.setTotal(total);
pageInfo.setPageNum(queryDto.getPageNum());
pageInfo.setPageSize(queryDto.getPageSize());
pageInfo.setPages((total + limit - 1) / limit);
return pageInfo;
}
@Override
public PageInfo<CmsContent> getPageListByUserCreated(CmsContentDto queryDto) {
// 获取当前登录用户ID
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
// 添加参数校验,确保分页参数有效
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
}
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
}
// 计算偏移量
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
int limit = queryDto.getPageSize();
// 查询数据
List<CmsContent> list = this.cmsContentMapper.getPageListByUserCreated(userId, queryDto.getPublishStatus(), offset, limit);
int total = this.cmsContentMapper.getPageListByUserCreatedCount(userId, queryDto.getPublishStatus());
// 构建分页结果
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
pageInfo.setTotal(total);
pageInfo.setPageNum(queryDto.getPageNum());
pageInfo.setPageSize(queryDto.getPageSize());
pageInfo.setPages((total + limit - 1) / limit);
return pageInfo;
}
@Override
public int importFromExcel(byte[] fileBytes, String createBy) {
int successCount = 0;
final int BATCH_SIZE = 10; // 批量处理大小
try (InputStream inputStream = new ByteArrayInputStream(fileBytes);
ExcelReader reader = ExcelUtil.getReader(inputStream)) {
// 获取总行数(包括标题行)
int totalRows = reader.getRowCount();
if (totalRows <= 1) {
// 只有标题行或空文件
return 0;
}
Date now = new Date();
List<CmsContent> batchList = new ArrayList<>(BATCH_SIZE);
// 读取标题行
List<Object> headerObjList = reader.readRow(0);
if (headerObjList == null || headerObjList.isEmpty()) {
return 0;
}
// 转换为List<String>
List<String> headerList = new ArrayList<>();
for (Object obj : headerObjList) {
headerList.add(obj != null ? obj.toString() : "");
}
// 从第二行开始读取数据(第一行为标题行)
for (int rowIndex = 1; rowIndex < totalRows; rowIndex++) {
try {
List<Object> rowList = reader.readRow(rowIndex);
if (rowList == null || rowList.isEmpty()) {
continue;
}
// 转换为Map<String, Object>
Map<String, Object> row = new HashMap<>();
for (int i = 0; i < headerList.size() && i < rowList.size(); i++) {
row.put(headerList.get(i), rowList.get(i));
}
if (row.isEmpty()) {
continue;
}
// 打印映射后的数据
System.out.println("映射后的数据:" + row);
CmsContent cmsContent = new CmsContent();
// 设置创建时间和更新时间
cmsContent.setCreateTime(now);
cmsContent.setUpdateTime(now);
cmsContent.setCreateBy(createBy);
cmsContent.setUpdateBy(createBy);
// 设置默认值
cmsContent.setDeleteFlag(0);
cmsContent.setAuditStatus(1); // 默认草稿状态
cmsContent.setPublishStatus(1); // 默认未发布状态
cmsContent.setViewCount(0);
cmsContent.setLikeCount(0);
cmsContent.setCommentCount(0);
cmsContent.setSort(0);
cmsContent.setIsOfficial(true); // 固定设置为1
// 读取Excel中的字段
// content_id - 数据库自动生成,不需要读取
cmsContent.setTitle(getStringValue(row, "title"));
cmsContent.setTitleEn(getStringValue(row, "title_en"));
cmsContent.setOrigin(getStringValue(row, "origin"));
// 处理tags字段避免NullPointerException
String tags = getStringValue(row, "tags");
if (tags == null) {
System.err.println("" + rowIndex + " 行数据的tags字段为null跳过该条记录");
continue;
}
cmsContent.setTags(tags.replaceAll(" ",""));
cmsContent.setIcon(getStringValue(row, "icon"));
cmsContent.setIsOfficial(true); // 固定设置为1
cmsContent.setPrice(getBigDecimalValue(row, "price"));
cmsContent.setLikeCount(100 + new Random().nextInt(3000));
cmsContent.setShareCount(100 + new Random().nextInt(1000));
cmsContent.setContentType(getIntegerValue(row, "content_type"));
cmsContent.setContent(getStringValue(row, "content"));
cmsContent.setContentEn(getStringValue(row, "content_en"));
cmsContent.setAuditStatus(getIntegerValue(row, "audit_status"));
cmsContent.setPublishStatus(getIntegerValue(row, "publish_status"));
cmsContent.setPublishTime(now); // 设置为与update_time一致
cmsContent.setViewCount(getIntegerValue(row, "view_count"));
cmsContent.setCommentCount(getIntegerValue(row, "comment_count"));
cmsContent.setIsPaid(getIntegerValue(row, "is_paid"));
cmsContent.setSupportPointsPay(getIntegerValue(row, "support_points_pay"));
cmsContent.setDescription(getStringValue(row, "description"));
cmsContent.setDescriptionEn(getStringValue(row, "description_en"));
cmsContent.setIntroduce(getStringValue(row, "introduce"));
cmsContent.setIntroduceEn(getStringValue(row, "introduce_en"));
// create_time - 由系统生成,不需要读取
// update_time - 由系统生成,不需要读取
cmsContent.setDeleteFlag(getIntegerValue(row, "delete_flag"));
batchList.add(cmsContent);
// 达到批量大小或最后一行时,执行批量插入
if (batchList.size() >= BATCH_SIZE) {
if (!batchList.isEmpty()) {
// 执行批量插入
this.cmsContentMapper.batchInsert(batchList);
successCount += batchList.size();
batchList.clear(); // 清空批次
}
}
} catch (Exception e) {
System.err.println("处理第 " + rowIndex + " 行数据时出错: " + e.getMessage());
e.printStackTrace();
// 跳过当前行,继续处理下一行
continue;
}
}
// 处理最后一批不足BATCH_SIZE的数据
if (!batchList.isEmpty()) {
this.cmsContentMapper.batchInsert(batchList);
successCount += batchList.size();
batchList.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
return successCount;
}
/**
* 从Map中获取字符串值
*/
private String getStringValue(Map<String, Object> row, String key) {
Object value = row.get(key);
return value != null ? value.toString() : null;
}
/**
* 从Map中获取布尔值
*/
private Boolean getBooleanValue(Map<String, Object> row, String key) {
Object value = row.get(key);
if (value == null) {
return null;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof String) {
return Boolean.parseBoolean((String) value);
}
return null;
}
/**
* 从Map中获取整数值
*/
private Integer getIntegerValue(Map<String, Object> row, String key) {
Object value = row.get(key);
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
if (value instanceof String) {
try {
return Integer.parseInt((String) value);
} catch (NumberFormatException e) {
return null;
}
}
return null;
}
/**
* 从Map中获取BigDecimal值
*/
private BigDecimal getBigDecimalValue(Map<String, Object> row, String key) {
Object value = row.get(key);
if (value == null) {
return null;
}
if (value instanceof Number) {
return BigDecimal.valueOf(((Number) value).doubleValue());
}
if (value instanceof String) {
try {
return new BigDecimal((String) value);
} catch (NumberFormatException e) {
return null;
}
}
return null;
}
/**
* 从Map中获取日期值
*/
private Date getDateValue(Map<String, Object> row, String key) {
Object value = row.get(key);
if (value == null) {
return null;
}
if (value instanceof Date) {
return (Date) value;
}
return null;
}
@Override
public String getContent(Long contentId, Integer languageType) {
Assert.notNull(contentId, "内容ID不能为空");
CmsContent cmsContent = this.cmsContentMapper.queryById(contentId);
if (cmsContent == null) {
return null;
}
// 当languageType为1时返回contentEn否则返回content
if (languageType != null && languageType == 1) {
return cmsContent.getContentEn();
} else {
return cmsContent.getContent();
}
}
@Override
public String getTitle(Long contentId) {
Assert.notNull(contentId, "内容ID不能为空");
CmsContent cmsContent = this.cmsContentMapper.queryById(contentId);
if (cmsContent == null) {
return null;
}
return cmsContent.getTitle();
}
@Override
public int importFromPath(ImportPathDto importPathDto, String createBy) {
int totalSuccessCount = 0;
try {
// 检查目录是否存在
File directory = new File(importPathDto.getFilePath());
if (!directory.exists() || !directory.isDirectory()) {
System.err.println("目录不存在或不是有效目录: " + importPathDto.getFilePath());
return 0;
}
// 如果不是追加模式,清空表
if (!importPathDto.isAppend()) {
cmsContentMapper.truncateTable();
}
// 读取目录下所有 Excel 文件(排除 Office 临时锁定文件)
File[] files = directory.listFiles((dir, name) -> {
// 跳过以 ~$ 开头的临时锁定文件
if (name.startsWith("~$")) {
return false;
}
return name.endsWith(".xls") || name.endsWith(".xlsx");
});
if (files == null || files.length == 0) {
return 0;
}
// 记录文件总数
int totalFiles = files.length;
System.out.println("总共发现 " + totalFiles + " 个 Excel 文件需要导入");
// 遍历所有 Excel 文件并导入
for (int i = 0; i < files.length; i++) {
File file = files[i];
System.out.println("当前处理第 " + (i + 1) + " 个文件,文件名称是:" + file.getName());
try (FileInputStream fis = new FileInputStream(file)) {
// 读取文件内容到字节数组
byte[] fileBytes = new byte[(int) file.length()];
fis.read(fileBytes);
// 调用现有的 importFromExcel 方法进行导入
int successCount = importFromExcel(fileBytes, createBy);
totalSuccessCount += successCount;
System.out.println("" + (i + 1) + " 个文件导入成功,导入了 " + successCount + " 条记录");
} catch (Exception e) {
System.err.println("导入文件失败: " + file.getAbsolutePath());
e.printStackTrace();
// 单个文件导入失败不影响其他文件
continue;
}
}
System.out.println("导入完成,共处理 " + totalFiles + " 个文件,成功导入 " + totalSuccessCount + " 条记录");
} catch (Exception e) {
System.err.println("导入操作失败: " + importPathDto.getFilePath());
e.printStackTrace();
}
return totalSuccessCount;
}
@Override
public int importFromZip(byte[] zipFileBytes, String createBy) {
int totalSuccessCount = 0;
int totalFiles = 0;
try (ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(zipFileBytes))) {
ZipEntry entry;
// 遍历ZIP文件中的所有条目
while ((entry = zipInputStream.getNextEntry()) != null) {
String fileName = entry.getName();
// 跳过目录和非Excel文件
if (entry.isDirectory() || (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx"))) {
zipInputStream.closeEntry();
continue;
}
// 跳过Office临时锁定文件
String simpleName = new File(fileName).getName();
if (simpleName.startsWith("~$")) {
zipInputStream.closeEntry();
continue;
}
totalFiles++;
System.out.println("当前处理第 " + totalFiles + " 个文件,文件名称是:" + fileName);
try {
// 读取Excel文件内容到字节数组
byte[] fileBytes = zipInputStream.readAllBytes();
// 调用现有的 importFromExcel 方法进行导入
int successCount = importFromExcel(fileBytes, createBy);
totalSuccessCount += successCount;
System.out.println("" + totalFiles + " 个文件导入成功,导入了 " + successCount + " 条记录");
} catch (Exception e) {
System.err.println("导入文件失败: " + fileName);
e.printStackTrace();
// 单个文件导入失败不影响其他文件
} finally {
zipInputStream.closeEntry();
}
}
System.out.println("导入完成,共处理 " + totalFiles + " 个文件,成功导入 " + totalSuccessCount + " 条记录");
} catch (Exception e) {
System.err.println("ZIP文件导入操作失败");
e.printStackTrace();
}
return totalSuccessCount;
}
@Override
public int updateFromPath(ImportPathDto importPathDto, String updateBy) {
int totalSuccessCount = 0;
try {
// 检查目录是否存在
File directory = new File(importPathDto.getFilePath());
if (!directory.exists() || !directory.isDirectory()) {
System.err.println("目录不存在或不是有效目录: " + importPathDto.getFilePath());
return 0;
}
// 读取目录下所有 Excel 文件(排除 Office 临时锁定文件)
File[] files = directory.listFiles((dir, name) -> {
// 跳过以 ~$ 开头的临时锁定文件
if (name.startsWith("~$")) {
return false;
}
return name.endsWith(".xls") || name.endsWith(".xlsx");
});
if (files == null || files.length == 0) {
return 0;
}
// 记录文件总数
int totalFiles = files.length;
System.out.println("总共发现 " + totalFiles + " 个 Excel 文件需要处理");
// 遍历所有 Excel 文件并处理
for (int i = 0; i < files.length; i++) {
File file = files[i];
System.out.println("当前处理第 " + (i + 1) + " 个文件,文件名称是:" + file.getName());
try (FileInputStream fis = new FileInputStream(file)) {
// 读取文件内容到字节数组
byte[] fileBytes = new byte[(int) file.length()];
fis.read(fileBytes);
// 调用 updateFromExcel 方法进行更新
int successCount = updateFromExcel(fileBytes, updateBy);
totalSuccessCount += successCount;
System.out.println("" + (i + 1) + " 个文件处理成功,更新了 " + successCount + " 条记录");
} catch (Exception e) {
System.err.println("处理文件失败: " + file.getAbsolutePath());
e.printStackTrace();
// 单个文件处理失败不影响其他文件
continue;
}
}
System.out.println("处理完成,共处理 " + totalFiles + " 个文件,成功更新 " + totalSuccessCount + " 条记录");
} catch (Exception e) {
System.err.println("更新操作失败: " + importPathDto.getFilePath());
e.printStackTrace();
}
return totalSuccessCount;
}
/**
* 从Excel文件读取数据并更新CmsContent
*
* @param fileBytes Excel文件字节数组
* @param updateBy 更新人
* @return 成功更新的记录数
*/
private int updateFromExcel(byte[] fileBytes, String updateBy) {
int successCount = 0;
try (InputStream inputStream = new ByteArrayInputStream(fileBytes);
ExcelReader reader = ExcelUtil.getReader(inputStream)) {
// 获取总行数(包括标题行)
int totalRows = reader.getRowCount();
if (totalRows <= 1) {
// 只有标题行或空文件
return 0;
}
Date now = new Date();
// 读取标题行
List<Object> headerObjList = reader.readRow(0);
if (headerObjList == null || headerObjList.isEmpty()) {
return 0;
}
// 转换为List<String>
List<String> headerList = new ArrayList<>();
for (Object obj : headerObjList) {
headerList.add(obj != null ? obj.toString() : "");
}
// 从第二行开始读取数据(第一行为标题行)
for (int rowIndex = 1; rowIndex < totalRows; rowIndex++) {
try {
List<Object> rowList = reader.readRow(rowIndex);
if (rowList == null || rowList.isEmpty()) {
continue;
}
// 转换为Map<String, Object>
Map<String, Object> row = new HashMap<>();
for (int i = 0; i < headerList.size() && i < rowList.size(); i++) {
row.put(headerList.get(i), rowList.get(i));
}
if (row.isEmpty()) {
continue;
}
// 读取关键字段用于查询
String title = getStringValue(row, "title");
String origin = getStringValue(row, "origin");
String tags = getStringValue(row, "tags");
// 去掉tags中的空格
if (tags != null) {
tags = tags.replaceAll(" ", "");
}
String icon = getStringValue(row, "icon");
// 根据关键字段查询记录
CmsContentDto queryDto = new CmsContentDto();
queryDto.setTitle(title);
queryDto.setOrigin(origin);
// queryDto.setTags(tags);
// queryDto.setIcon(icon);
queryDto.setDeleteFlag(0);
List<CmsContent> existingList = cmsContentMapper.getList(queryDto);
if (existingList != null && !existingList.isEmpty()) {
// 找到匹配的记录,进行更新
CmsContent existingContent = existingList.get(0);
// 更新字段
existingContent.setTitle(getStringValue(row, "title"));
existingContent.setTitleEn(getStringValue(row, "title_en"));
existingContent.setOrigin(getStringValue(row, "origin"));
existingContent.setTags(tags);
existingContent.setIcon(getStringValue(row, "icon"));
existingContent.setPrice(getBigDecimalValue(row, "price"));
existingContent.setContentType(getIntegerValue(row, "content_type"));
existingContent.setContent(getStringValue(row, "content"));
existingContent.setContentEn(getStringValue(row, "content_en"));
existingContent.setAuditStatus(getIntegerValue(row, "audit_status"));
existingContent.setPublishStatus(getIntegerValue(row, "publish_status"));
existingContent.setViewCount(getIntegerValue(row, "view_count"));
existingContent.setLikeCount(getIntegerValue(row, "like_count"));
existingContent.setCommentCount(getIntegerValue(row, "comment_count"));
existingContent.setIsPaid(getIntegerValue(row, "is_paid"));
existingContent.setSupportPointsPay(getIntegerValue(row, "support_points_pay"));
existingContent.setDescription(getStringValue(row, "description"));
existingContent.setDescriptionEn(getStringValue(row, "description_en"));
existingContent.setIntroduce(getStringValue(row, "introduce"));
existingContent.setIntroduceEn(getStringValue(row, "introduce_en"));
// 设置更新时间和更新人
existingContent.setUpdateTime(now);
existingContent.setUpdateBy(updateBy);
// 执行更新
cmsContentMapper.update(existingContent);
successCount++;
}
} catch (Exception e) {
System.err.println("处理第 " + rowIndex + " 行数据时出错: " + e.getMessage());
e.printStackTrace();
// 跳过当前行,继续处理下一行
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return successCount;
}
}