人生轨迹功能模块补充

This commit is contained in:
2025-12-22 14:50:14 +08:00
parent fa57938a9d
commit cd6d995d5a
48 changed files with 5359 additions and 316 deletions
@@ -121,6 +121,14 @@ public class AiConfigServiceImpl extends ServiceImpl<AiConfigMapper, AiConfig> i
BeanUtils.copyProperties(request, aiConfig);
aiConfig.setId(String.valueOf(snowflakeIdGenerator.nextId()));
// 处理JSON字段,防止空字符串导致数据库报错
if (!StringUtils.hasText(aiConfig.getCustomHeaders())) {
aiConfig.setCustomHeaders("{}");
}
if (!StringUtils.hasText(aiConfig.getCustomParams())) {
aiConfig.setCustomParams("{}");
}
boolean saved = this.save(aiConfig);
return saved ? convertToResponse(aiConfig) : null;
}
@@ -133,6 +141,15 @@ public class AiConfigServiceImpl extends ServiceImpl<AiConfigMapper, AiConfig> i
}
BeanUtils.copyProperties(request, aiConfig);
// 处理JSON字段,防止空字符串导致数据库报错
if (request.getCustomHeaders() != null && !StringUtils.hasText(request.getCustomHeaders())) {
aiConfig.setCustomHeaders("{}");
}
if (request.getCustomParams() != null && !StringUtils.hasText(request.getCustomParams())) {
aiConfig.setCustomParams("{}");
}
boolean updated = this.updateById(aiConfig);
return updated ? convertToResponse(aiConfig) : null;
}
@@ -0,0 +1,262 @@
package com.emotion.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.EpicScriptCreateRequest;
import com.emotion.dto.request.EpicScriptPageRequest;
import com.emotion.dto.request.EpicScriptUpdateRequest;
import com.emotion.dto.response.EpicScriptResponse;
import com.emotion.entity.EpicScript;
import com.emotion.mapper.EpicScriptMapper;
import com.emotion.service.EpicScriptService;
import com.emotion.service.LifePathService;
import com.emotion.util.UserContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 爽文剧本服务实现类
*
* @author huazhongmin
* @date 2025-12-22
*/
@Service
public class EpicScriptServiceImpl extends ServiceImpl<EpicScriptMapper, EpicScript>
implements EpicScriptService {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
@Lazy
private LifePathService lifePathService;
@Override
public PageResult<EpicScriptResponse> getPageByCurrentUser(EpicScriptPageRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return new PageResult<>();
}
Page<EpicScript> page = new Page<>(request.getCurrent(), request.getSize());
LambdaQueryWrapper<EpicScript> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EpicScript::getUserId, currentUserId)
.eq(EpicScript::getIsDeleted, 0);
// 风格筛选
if (StringUtils.hasText(request.getStyle())) {
wrapper.eq(EpicScript::getStyle, request.getStyle());
}
// 篇幅筛选
if (StringUtils.hasText(request.getLength())) {
wrapper.eq(EpicScript::getLength, request.getLength());
}
// 关键词搜索
if (StringUtils.hasText(request.getKeyword())) {
wrapper.and(w -> w.like(EpicScript::getTitle, request.getKeyword())
.or().like(EpicScript::getTheme, request.getKeyword()));
}
// 按创建时间倒序排列
wrapper.orderByDesc(EpicScript::getCreateTime);
Page<EpicScript> resultPage = this.page(page, wrapper);
List<EpicScriptResponse> responses = resultPage.getRecords().stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
PageResult<EpicScriptResponse> pageResult = new PageResult<>();
pageResult.setCurrent(resultPage.getCurrent());
pageResult.setSize(resultPage.getSize());
pageResult.setTotal(resultPage.getTotal());
pageResult.setPages(resultPage.getPages());
pageResult.setRecords(responses);
return pageResult;
}
@Override
public List<EpicScriptResponse> getListByCurrentUser() {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return List.of();
}
LambdaQueryWrapper<EpicScript> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EpicScript::getUserId, currentUserId)
.eq(EpicScript::getIsDeleted, 0)
.orderByDesc(EpicScript::getCreateTime);
return this.list(wrapper).stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
}
@Override
public EpicScriptResponse getScriptById(String id) {
EpicScript script = this.getById(id);
if (script == null || script.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!script.getUserId().equals(currentUserId)) {
return null;
}
return convertToResponse(script);
}
@Override
public EpicScriptResponse createScript(EpicScriptCreateRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return null;
}
EpicScript script = new EpicScript();
script.setUserId(currentUserId);
script.setTitle(request.getTitle());
script.setTheme(request.getTheme());
script.setStyle(StringUtils.hasText(request.getStyle()) ? request.getStyle() : "career");
script.setLength(StringUtils.hasText(request.getLength()) ? request.getLength() : "medium");
script.setPlotIntro(request.getPlotIntro());
script.setPlotTurning(request.getPlotTurning());
script.setPlotClimax(request.getPlotClimax());
script.setPlotEnding(request.getPlotEnding());
script.setPlotJson(request.getPlotJson());
script.setIsSelected(request.getIsSelected() != null && request.getIsSelected() ? 1 : 0);
this.save(script);
return convertToResponse(script);
}
@Override
public EpicScriptResponse updateScript(EpicScriptUpdateRequest request) {
EpicScript script = this.getById(request.getId());
if (script == null || script.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!script.getUserId().equals(currentUserId)) {
return null;
}
// 更新字段
if (StringUtils.hasText(request.getTitle())) {
script.setTitle(request.getTitle());
}
if (request.getTheme() != null) {
script.setTheme(request.getTheme());
}
if (StringUtils.hasText(request.getStyle())) {
script.setStyle(request.getStyle());
}
if (StringUtils.hasText(request.getLength())) {
script.setLength(request.getLength());
}
if (request.getPlotIntro() != null) {
script.setPlotIntro(request.getPlotIntro());
}
if (request.getPlotTurning() != null) {
script.setPlotTurning(request.getPlotTurning());
}
if (request.getPlotClimax() != null) {
script.setPlotClimax(request.getPlotClimax());
}
if (request.getPlotEnding() != null) {
script.setPlotEnding(request.getPlotEnding());
}
if (request.getPlotJson() != null) {
script.setPlotJson(request.getPlotJson());
}
if (request.getIsSelected() != null) {
script.setIsSelected(request.getIsSelected() ? 1 : 0);
}
this.updateById(script);
return convertToResponse(script);
}
@Override
public EpicScriptResponse selectScript(String id) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return null;
}
// 先取消所有选中
LambdaQueryWrapper<EpicScript> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EpicScript::getUserId, currentUserId)
.eq(EpicScript::getIsSelected, 1)
.eq(EpicScript::getIsDeleted, 0);
List<EpicScript> selectedScripts = this.list(wrapper);
for (EpicScript s : selectedScripts) {
s.setIsSelected(0);
this.updateById(s);
}
// 选中指定剧本
EpicScript script = this.getById(id);
if (script == null || script.getIsDeleted() == 1) {
return null;
}
if (!script.getUserId().equals(currentUserId)) {
return null;
}
script.setIsSelected(1);
this.updateById(script);
return convertToResponse(script);
}
@Override
public boolean deleteScript(String id) {
EpicScript script = this.getById(id);
if (script == null || script.getIsDeleted() == 1) {
return false;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!script.getUserId().equals(currentUserId)) {
return false;
}
// 删除关联的路径
lifePathService.deleteByScriptId(id);
script.setIsDeleted(1);
return this.updateById(script);
}
/**
* 转换为响应对象
*/
private EpicScriptResponse convertToResponse(EpicScript script) {
EpicScriptResponse response = new EpicScriptResponse();
BeanUtils.copyProperties(script, response);
response.setId(script.getId());
response.setIsSelected(script.getIsSelected() != null && script.getIsSelected() == 1);
if (script.getCreateTime() != null) {
response.setCreateTime(script.getCreateTime().format(DATE_TIME_FORMATTER));
}
if (script.getUpdateTime() != null) {
response.setUpdateTime(script.getUpdateTime().format(DATE_TIME_FORMATTER));
}
return response;
}
}
@@ -0,0 +1,237 @@
package com.emotion.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.LifeEventCreateRequest;
import com.emotion.dto.request.LifeEventPageRequest;
import com.emotion.dto.request.LifeEventUpdateRequest;
import com.emotion.dto.response.LifeEventResponse;
import com.emotion.entity.LifeEvent;
import com.emotion.mapper.LifeEventMapper;
import com.emotion.service.LifeEventService;
import com.emotion.util.UserContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 生命事件服务实现类
*
* @author huazhongmin
* @date 2025-12-22
*/
@Service
public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent>
implements LifeEventService {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_DATE_TIME;
@Override
public PageResult<LifeEventResponse> getPageByCurrentUser(LifeEventPageRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return new PageResult<>();
}
Page<LifeEvent> page = new Page<>(request.getCurrent(), request.getSize());
LambdaQueryWrapper<LifeEvent> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifeEvent::getUserId, currentUserId)
.eq(LifeEvent::getIsDeleted, 0);
// 事件类型筛选
if (StringUtils.hasText(request.getEventType())) {
wrapper.eq(LifeEvent::getEventType, request.getEventType());
}
// 情绪类型筛选
if (StringUtils.hasText(request.getEmotionType())) {
wrapper.eq(LifeEvent::getEmotionType, request.getEmotionType());
}
// 关键词搜索
if (StringUtils.hasText(request.getKeyword())) {
wrapper.and(w -> w.like(LifeEvent::getTitle, request.getKeyword())
.or().like(LifeEvent::getContent, request.getKeyword()));
}
// 按事件日期倒序排列
wrapper.orderByDesc(LifeEvent::getEventDate);
Page<LifeEvent> resultPage = this.page(page, wrapper);
List<LifeEventResponse> responses = resultPage.getRecords().stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
PageResult<LifeEventResponse> pageResult = new PageResult<>();
pageResult.setCurrent(resultPage.getCurrent());
pageResult.setSize(resultPage.getSize());
pageResult.setTotal(resultPage.getTotal());
pageResult.setPages(resultPage.getPages());
pageResult.setRecords(responses);
return pageResult;
}
@Override
public List<LifeEventResponse> getListByCurrentUser() {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return List.of();
}
LambdaQueryWrapper<LifeEvent> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifeEvent::getUserId, currentUserId)
.eq(LifeEvent::getIsDeleted, 0)
.orderByDesc(LifeEvent::getEventDate);
return this.list(wrapper).stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
}
@Override
public LifeEventResponse getEventById(String id) {
LifeEvent event = this.getById(id);
if (event == null || event.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!event.getUserId().equals(currentUserId)) {
return null;
}
return convertToResponse(event);
}
@Override
public LifeEventResponse createEvent(LifeEventCreateRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return null;
}
LifeEvent event = new LifeEvent();
event.setUserId(currentUserId);
event.setEventType(StringUtils.hasText(request.getEventType()) ? request.getEventType() : "daily_log");
event.setTitle(request.getTitle());
event.setContent(request.getContent());
event.setAiReply(request.getAiReply());
event.setEmotionType(request.getEmotionType());
event.setTags(request.getTags());
// 解析事件日期
if (StringUtils.hasText(request.getEventDate())) {
try {
event.setEventDate(LocalDateTime.parse(request.getEventDate(), ISO_FORMATTER));
} catch (Exception e) {
event.setEventDate(LocalDateTime.now());
}
} else {
event.setEventDate(LocalDateTime.now());
}
// 情绪评分
if (request.getEmotionScore() != null) {
event.setEmotionScore(BigDecimal.valueOf(request.getEmotionScore()));
}
this.save(event);
return convertToResponse(event);
}
@Override
public LifeEventResponse updateEvent(LifeEventUpdateRequest request) {
LifeEvent event = this.getById(request.getId());
if (event == null || event.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!event.getUserId().equals(currentUserId)) {
return null;
}
// 更新字段
if (StringUtils.hasText(request.getEventType())) {
event.setEventType(request.getEventType());
}
if (StringUtils.hasText(request.getTitle())) {
event.setTitle(request.getTitle());
}
if (StringUtils.hasText(request.getContent())) {
event.setContent(request.getContent());
}
if (request.getAiReply() != null) {
event.setAiReply(request.getAiReply());
}
if (request.getEmotionType() != null) {
event.setEmotionType(request.getEmotionType());
}
if (request.getTags() != null) {
event.setTags(request.getTags());
}
if (StringUtils.hasText(request.getEventDate())) {
try {
event.setEventDate(LocalDateTime.parse(request.getEventDate(), ISO_FORMATTER));
} catch (Exception ignored) {
}
}
if (request.getEmotionScore() != null) {
event.setEmotionScore(BigDecimal.valueOf(request.getEmotionScore()));
}
this.updateById(event);
return convertToResponse(event);
}
@Override
public boolean deleteEvent(String id) {
LifeEvent event = this.getById(id);
if (event == null || event.getIsDeleted() == 1) {
return false;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!event.getUserId().equals(currentUserId)) {
return false;
}
event.setIsDeleted(1);
return this.updateById(event);
}
/**
* 转换为响应对象
*/
private LifeEventResponse convertToResponse(LifeEvent event) {
LifeEventResponse response = new LifeEventResponse();
BeanUtils.copyProperties(event, response);
response.setId(event.getId());
if (event.getEventDate() != null) {
response.setEventDate(event.getEventDate().format(ISO_FORMATTER));
}
if (event.getEmotionScore() != null) {
response.setEmotionScore(event.getEmotionScore().doubleValue());
}
if (event.getCreateTime() != null) {
response.setCreateTime(event.getCreateTime().format(DATE_TIME_FORMATTER));
}
if (event.getUpdateTime() != null) {
response.setUpdateTime(event.getUpdateTime().format(DATE_TIME_FORMATTER));
}
return response;
}
}
@@ -0,0 +1,235 @@
package com.emotion.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.LifePathCreateRequest;
import com.emotion.dto.request.LifePathPageRequest;
import com.emotion.dto.request.LifePathUpdateRequest;
import com.emotion.dto.response.LifePathResponse;
import com.emotion.entity.LifePath;
import com.emotion.mapper.LifePathMapper;
import com.emotion.service.LifePathService;
import com.emotion.util.UserContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 实现路径服务实现类
*
* @author huazhongmin
* @date 2025-12-22
*/
@Service
public class LifePathServiceImpl extends ServiceImpl<LifePathMapper, LifePath>
implements LifePathService {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public PageResult<LifePathResponse> getPageByCurrentUser(LifePathPageRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return new PageResult<>();
}
Page<LifePath> page = new Page<>(request.getCurrent(), request.getSize());
LambdaQueryWrapper<LifePath> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifePath::getUserId, currentUserId)
.eq(LifePath::getIsDeleted, 0);
// 剧本ID筛选
if (StringUtils.hasText(request.getScriptId())) {
wrapper.eq(LifePath::getScriptId, request.getScriptId());
}
// 状态筛选
if (StringUtils.hasText(request.getStatus())) {
wrapper.eq(LifePath::getStatus, request.getStatus());
}
// 按创建时间倒序排列
wrapper.orderByDesc(LifePath::getCreateTime);
Page<LifePath> resultPage = this.page(page, wrapper);
List<LifePathResponse> responses = resultPage.getRecords().stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
PageResult<LifePathResponse> pageResult = new PageResult<>();
pageResult.setCurrent(resultPage.getCurrent());
pageResult.setSize(resultPage.getSize());
pageResult.setTotal(resultPage.getTotal());
pageResult.setPages(resultPage.getPages());
pageResult.setRecords(responses);
return pageResult;
}
@Override
public List<LifePathResponse> getListByCurrentUser() {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return List.of();
}
LambdaQueryWrapper<LifePath> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifePath::getUserId, currentUserId)
.eq(LifePath::getIsDeleted, 0)
.orderByDesc(LifePath::getCreateTime);
return this.list(wrapper).stream()
.map(this::convertToResponse)
.collect(Collectors.toList());
}
@Override
public LifePathResponse getByScriptId(String scriptId) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return null;
}
LambdaQueryWrapper<LifePath> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifePath::getUserId, currentUserId)
.eq(LifePath::getScriptId, scriptId)
.eq(LifePath::getIsDeleted, 0);
LifePath path = this.getOne(wrapper);
return path != null ? convertToResponse(path) : null;
}
@Override
public LifePathResponse getPathById(String id) {
LifePath path = this.getById(id);
if (path == null || path.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!path.getUserId().equals(currentUserId)) {
return null;
}
return convertToResponse(path);
}
@Override
public LifePathResponse createPath(LifePathCreateRequest request) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return null;
}
LifePath path = new LifePath();
path.setUserId(currentUserId);
path.setScriptId(request.getScriptId());
path.setTitle(request.getTitle());
path.setDescription(request.getDescription());
path.setSteps(request.getSteps());
path.setStatus(StringUtils.hasText(request.getStatus()) ? request.getStatus() : "active");
path.setProgress(request.getProgress() != null ? BigDecimal.valueOf(request.getProgress()) : BigDecimal.ZERO);
this.save(path);
return convertToResponse(path);
}
@Override
public LifePathResponse updatePath(LifePathUpdateRequest request) {
LifePath path = this.getById(request.getId());
if (path == null || path.getIsDeleted() == 1) {
return null;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!path.getUserId().equals(currentUserId)) {
return null;
}
// 更新字段
if (StringUtils.hasText(request.getTitle())) {
path.setTitle(request.getTitle());
}
if (request.getDescription() != null) {
path.setDescription(request.getDescription());
}
if (request.getSteps() != null) {
path.setSteps(request.getSteps());
}
if (StringUtils.hasText(request.getStatus())) {
path.setStatus(request.getStatus());
}
if (request.getProgress() != null) {
path.setProgress(BigDecimal.valueOf(request.getProgress()));
}
this.updateById(path);
return convertToResponse(path);
}
@Override
public boolean deletePath(String id) {
LifePath path = this.getById(id);
if (path == null || path.getIsDeleted() == 1) {
return false;
}
// 验证权限
String currentUserId = UserContextHolder.getCurrentUserId();
if (!path.getUserId().equals(currentUserId)) {
return false;
}
path.setIsDeleted(1);
return this.updateById(path);
}
@Override
public boolean deleteByScriptId(String scriptId) {
String currentUserId = UserContextHolder.getCurrentUserId();
if (currentUserId == null) {
return false;
}
LambdaQueryWrapper<LifePath> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LifePath::getUserId, currentUserId)
.eq(LifePath::getScriptId, scriptId)
.eq(LifePath::getIsDeleted, 0);
List<LifePath> paths = this.list(wrapper);
for (LifePath path : paths) {
path.setIsDeleted(1);
this.updateById(path);
}
return true;
}
/**
* 转换为响应对象
*/
private LifePathResponse convertToResponse(LifePath path) {
LifePathResponse response = new LifePathResponse();
BeanUtils.copyProperties(path, response);
response.setId(path.getId());
if (path.getProgress() != null) {
response.setProgress(path.getProgress().doubleValue());
}
if (path.getCreateTime() != null) {
response.setCreateTime(path.getCreateTime().format(DATE_TIME_FORMATTER));
}
if (path.getUpdateTime() != null) {
response.setUpdateTime(path.getUpdateTime().format(DATE_TIME_FORMATTER));
}
return response;
}
}