feat: 优化管理后台页面UI、修复TS编译错误、新增人生事件模块
- 优化 AI 配置列表页面:重构统计卡片、搜索表单、表格列展示 - 修复 3 处 TypeScript TS6133 编译错误,恢复构建 - 新增管理员修改密码和重置密码功能 - 优化小程序多个页面样式和交互 - 人生事件模块完善 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -55,7 +55,7 @@ def run_command(cmd, cwd=None, shell=True, capture=True):
|
||||
"""执行本地命令"""
|
||||
try:
|
||||
if capture:
|
||||
result = subprocess.run(cmd, cwd=cwd, shell=shell, capture_output=True, text=True)
|
||||
result = subprocess.run(cmd, cwd=cwd, shell=shell, capture_output=True, text=True, encoding='utf-8')
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
else:
|
||||
result = subprocess.run(cmd, cwd=cwd, shell=shell)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.emotion.controller;
|
||||
|
||||
import com.emotion.common.Result;
|
||||
import com.emotion.dto.request.AdminChangePasswordRequest;
|
||||
import com.emotion.dto.request.AdminLoginRequest;
|
||||
import com.emotion.dto.request.RefreshTokenRequest;
|
||||
import com.emotion.dto.response.AdminAuthResponse;
|
||||
@@ -89,4 +90,22 @@ public class AdminAuthController {
|
||||
boolean isValid = adminAuthService.validateToken(request);
|
||||
return Result.success(isValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改管理员密码(修改自己的密码)
|
||||
*/
|
||||
@PostMapping("/changePassword")
|
||||
@Operation(summary = "修改管理员密码", description = "当前登录的管理员修改自己的密码,需要提供原密码")
|
||||
public Result<Void> changePassword(HttpServletRequest request, @Validated @RequestBody AdminChangePasswordRequest req) {
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||
return Result.unauthorized("未登录");
|
||||
}
|
||||
|
||||
String token = authHeader.substring(7);
|
||||
String adminId = jwtUtil.getUserIdFromToken(token);
|
||||
|
||||
adminAuthService.changePassword(adminId, req);
|
||||
return Result.success("密码修改成功", null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.emotion.common.Result;
|
||||
import com.emotion.dto.request.AiConfigCallStatsRequest;
|
||||
import com.emotion.dto.request.AdminCreateRequest;
|
||||
import com.emotion.dto.request.AdminPageRequest;
|
||||
import com.emotion.dto.request.AdminResetPasswordRequest;
|
||||
import com.emotion.dto.request.AdminUpdateRequest;
|
||||
import com.emotion.dto.response.AiConfigCallStatsResponse;
|
||||
import com.emotion.dto.response.AdminResponse;
|
||||
@@ -97,6 +98,16 @@ public class AdminController {
|
||||
return Result.success("删除成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置管理员密码(超级管理员操作)
|
||||
*/
|
||||
@Operation(summary = "重置管理员密码", description = "超级管理员重置指定管理员的密码")
|
||||
@PostMapping("/changePassword")
|
||||
public Result<Void> changePassword(@Validated @RequestBody AdminResetPasswordRequest request) {
|
||||
adminService.resetPassword(request.getId(), request.getNewPassword());
|
||||
return Result.success("密码重置成功", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仪表盘统计数据
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,11 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 生命事件控制器
|
||||
@@ -92,4 +96,76 @@ public class LifeEventController {
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
@PostMapping(value = "/ai-assist")
|
||||
public Result<Map<String, Object>> aiAssist(@RequestBody Map<String, Object> request) {
|
||||
String title = stringValue(request.get("title"), "这段经历");
|
||||
String content = stringValue(request.get("content"), "");
|
||||
List<String> tags = readTags(request.get("tags"));
|
||||
if (tags.isEmpty()) {
|
||||
tags.add("成长");
|
||||
tags.add("记录");
|
||||
}
|
||||
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("content", content.isBlank()
|
||||
? "那一天,我清楚地感受到自己正在经历一次变化。事情本身也许并不宏大,但它让我重新看见了自己的选择、情绪和力量。"
|
||||
: content + "\n\n我愿意把这段经历记录下来,因为它提醒我:每一次真实面对,都会成为未来的底气。");
|
||||
data.put("aiReply", "AI占位解读:" + title + "体现了你的自我观察和复盘能力。后续接入真实AI后,这里会返回更完整的情绪整理、能力映射和行动建议。");
|
||||
data.put("tags", tags);
|
||||
data.put("placeholder", true);
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/chat-placeholder")
|
||||
public Result<Map<String, Object>> chatPlaceholder(@RequestBody Map<String, Object> request) {
|
||||
String title = stringValue(request.get("title"), "这段经历");
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("reply", "我在这里陪你回看「" + title + "」。真实聊天能力后续接入AI工作流;当前先保留这个入口和上下文。");
|
||||
data.put("suggestions", List.of("这件事让我学到了什么?", "如果重来一次我会怎么选?", "它会怎样影响我的人生剧本?"));
|
||||
data.put("placeholder", true);
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/share-placeholder")
|
||||
public Result<Map<String, Object>> sharePlaceholder(@RequestBody Map<String, Object> request) {
|
||||
String title = stringValue(request.get("title"), "人生经历");
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("title", title);
|
||||
data.put("summary", "我刚刚记录了一段重要的人生轨迹。");
|
||||
data.put("shareText", "分享我的人生轨迹:" + title);
|
||||
data.put("placeholder", true);
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/favorite-placeholder")
|
||||
public Result<Map<String, Object>> favoritePlaceholder(@RequestBody Map<String, Object> request) {
|
||||
String id = stringValue(request.get("id"), "");
|
||||
Boolean favorite = Boolean.TRUE.equals(request.get("favorite"));
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("id", id);
|
||||
data.put("favorite", favorite);
|
||||
data.put("placeholder", true);
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
private String stringValue(Object value, String fallback) {
|
||||
if (value == null) {
|
||||
return fallback;
|
||||
}
|
||||
String text = String.valueOf(value).trim();
|
||||
return text.isEmpty() ? fallback : text;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<String> readTags(Object value) {
|
||||
List<String> tags = new ArrayList<>();
|
||||
if (value instanceof List<?>) {
|
||||
for (Object item : (List<Object>) value) {
|
||||
if (item != null && !String.valueOf(item).trim().isEmpty()) {
|
||||
tags.add(String.valueOf(item).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.emotion.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 管理员修改密码请求(修改自己的密码,需要原密码)
|
||||
*
|
||||
* @author huazhongmin
|
||||
* @date 2026-05-10
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "管理员修改密码请求")
|
||||
public class AdminChangePasswordRequest {
|
||||
|
||||
@NotBlank(message = "原密码不能为空")
|
||||
@Schema(description = "原密码")
|
||||
private String oldPassword;
|
||||
|
||||
@NotBlank(message = "新密码不能为空")
|
||||
@Schema(description = "新密码")
|
||||
private String newPassword;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.emotion.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 超级管理员重置其他管理员密码请求(不需要原密码)
|
||||
*
|
||||
* @author huazhongmin
|
||||
* @date 2026-05-10
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "管理员重置密码请求")
|
||||
public class AdminResetPasswordRequest {
|
||||
|
||||
@NotBlank(message = "管理员ID不能为空")
|
||||
@Schema(description = "管理员ID")
|
||||
private String id;
|
||||
|
||||
@NotBlank(message = "新密码不能为空")
|
||||
@Schema(description = "新密码")
|
||||
private String newPassword;
|
||||
}
|
||||
@@ -27,6 +27,21 @@ public class LifeEventCreateRequest extends BaseRequest {
|
||||
*/
|
||||
private String eventDate;
|
||||
|
||||
/**
|
||||
* 时间模式: date-具体日期, month-年月, season-季节, range-时间范围
|
||||
*/
|
||||
private String timeMode;
|
||||
|
||||
/**
|
||||
* 原始时间文本
|
||||
*/
|
||||
private String eventDateText;
|
||||
|
||||
/**
|
||||
* 结束日期,仅时间范围使用
|
||||
*/
|
||||
private String eventEndDate;
|
||||
|
||||
/**
|
||||
* 事件标题
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,21 @@ public class LifeEventUpdateRequest extends BaseRequest {
|
||||
*/
|
||||
private String eventDate;
|
||||
|
||||
/**
|
||||
* 时间模式: date-具体日期, month-年月, season-季节, range-时间范围
|
||||
*/
|
||||
private String timeMode;
|
||||
|
||||
/**
|
||||
* 原始时间文本
|
||||
*/
|
||||
private String eventDateText;
|
||||
|
||||
/**
|
||||
* 结束日期,仅时间范围使用
|
||||
*/
|
||||
private String eventEndDate;
|
||||
|
||||
/**
|
||||
* 事件标题
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,21 @@ public class LifeEventResponse extends BaseResponse {
|
||||
*/
|
||||
private String eventDate;
|
||||
|
||||
/**
|
||||
* 时间模式
|
||||
*/
|
||||
private String timeMode;
|
||||
|
||||
/**
|
||||
* 原始时间文本
|
||||
*/
|
||||
private String eventDateText;
|
||||
|
||||
/**
|
||||
* 结束日期
|
||||
*/
|
||||
private String eventEndDate;
|
||||
|
||||
/**
|
||||
* 事件标题
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,24 @@ public class LifeEvent extends BaseEntity {
|
||||
@TableField("event_date")
|
||||
private LocalDateTime eventDate;
|
||||
|
||||
/**
|
||||
* 时间模式: date-具体日期, month-年月, season-季节, range-时间范围
|
||||
*/
|
||||
@TableField("time_mode")
|
||||
private String timeMode;
|
||||
|
||||
/**
|
||||
* 原始时间文本: 2025-05, 2025-spring 等
|
||||
*/
|
||||
@TableField("event_date_text")
|
||||
private String eventDateText;
|
||||
|
||||
/**
|
||||
* 结束日期,仅时间范围使用
|
||||
*/
|
||||
@TableField("event_end_date")
|
||||
private LocalDateTime eventEndDate;
|
||||
|
||||
/**
|
||||
* 事件标题
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.emotion.service;
|
||||
|
||||
import com.emotion.dto.request.AdminChangePasswordRequest;
|
||||
import com.emotion.dto.request.AdminLoginRequest;
|
||||
import com.emotion.dto.response.AdminAuthResponse;
|
||||
import com.emotion.dto.response.AdminInfoResponse;
|
||||
@@ -61,4 +62,12 @@ public interface AdminAuthService {
|
||||
* @return 管理员ID
|
||||
*/
|
||||
String getAdminIdFromToken(String token);
|
||||
|
||||
/**
|
||||
* 修改管理员密码(需要原密码验证)
|
||||
*
|
||||
* @param adminId 管理员ID
|
||||
* @param request 修改密码请求
|
||||
*/
|
||||
void changePassword(String adminId, AdminChangePasswordRequest request);
|
||||
}
|
||||
|
||||
@@ -50,4 +50,9 @@ public interface AdminService extends IService<Admin> {
|
||||
* 根据手机号查询管理员
|
||||
*/
|
||||
Admin getByPhone(String phone);
|
||||
|
||||
/**
|
||||
* 重置指定管理员的密码
|
||||
*/
|
||||
void resetPassword(String adminId, String newPassword);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.emotion.service.impl;
|
||||
|
||||
import com.emotion.dto.request.AdminChangePasswordRequest;
|
||||
import com.emotion.dto.request.AdminLoginRequest;
|
||||
import com.emotion.dto.response.AdminAuthResponse;
|
||||
import com.emotion.dto.response.AdminInfoResponse;
|
||||
@@ -201,4 +202,25 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
BeanUtils.copyProperties(admin, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePassword(String adminId, AdminChangePasswordRequest request) {
|
||||
Admin admin = adminService.getById(adminId);
|
||||
if (admin == null) {
|
||||
throw new AuthException("管理员不存在");
|
||||
}
|
||||
|
||||
if (!passwordEncoder.matches(request.getOldPassword(), admin.getPassword())) {
|
||||
throw new AuthException("原密码不正确");
|
||||
}
|
||||
|
||||
admin.setPassword(passwordEncoder.encode(request.getNewPassword()));
|
||||
adminService.updateById(admin);
|
||||
|
||||
// 清除该管理员的Redis token,强制重新登录
|
||||
redisTemplate.delete(ADMIN_TOKEN_PREFIX + adminId);
|
||||
redisTemplate.delete(ADMIN_REFRESH_TOKEN_PREFIX + adminId);
|
||||
|
||||
log.info("管理员修改密码成功: adminId={}", adminId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ import com.emotion.entity.Admin;
|
||||
import com.emotion.exception.BusinessException;
|
||||
import com.emotion.mapper.AdminMapper;
|
||||
import com.emotion.service.AdminService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -29,11 +31,18 @@ import java.util.stream.Collectors;
|
||||
* @date 2025-10-27
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public AdminServiceImpl(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<AdminResponse> getPageWithResponse(AdminPageRequest request) {
|
||||
Page<Admin> page = new Page<>(request.getCurrent(), request.getSize());
|
||||
@@ -238,6 +247,23 @@ public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements
|
||||
return this.getOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPassword(String adminId, String newPassword) {
|
||||
Admin admin = this.getById(adminId);
|
||||
if (admin == null) {
|
||||
throw new BusinessException("管理员不存在");
|
||||
}
|
||||
|
||||
admin.setPassword(passwordEncoder.encode(newPassword));
|
||||
this.updateById(admin);
|
||||
|
||||
// 清除该管理员的Redis token,强制重新登录
|
||||
redisTemplate.delete("admin_token:" + adminId);
|
||||
redisTemplate.delete("admin_refresh_token:" + adminId);
|
||||
|
||||
log.info("管理员重置密码成功: adminId={}", adminId);
|
||||
}
|
||||
|
||||
private AdminResponse convertToResponse(Admin admin) {
|
||||
AdminResponse response = new AdminResponse();
|
||||
BeanUtils.copyProperties(admin, response);
|
||||
|
||||
@@ -21,7 +21,9 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.YearMonth;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -40,6 +42,7 @@ public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent
|
||||
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;
|
||||
private static final DateTimeFormatter DATE_ONLY_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
|
||||
|
||||
/**
|
||||
* Coze工作流配置键 - AI疗愈
|
||||
@@ -143,9 +146,12 @@ public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent
|
||||
event.setAiReply(request.getAiReply());
|
||||
event.setEmotionType(request.getEmotionType());
|
||||
event.setTags(request.getTags());
|
||||
event.setTimeMode(StringUtils.hasText(request.getTimeMode()) ? request.getTimeMode() : "date");
|
||||
event.setEventDateText(StringUtils.hasText(request.getEventDateText()) ? request.getEventDateText() : request.getEventDate());
|
||||
|
||||
// 解析事件日期,支持多种格式
|
||||
event.setEventDate(parseEventDate(request.getEventDate()));
|
||||
event.setEventDate(parseEventDate(request.getEventDate(), event.getTimeMode(), event.getEventDateText()));
|
||||
event.setEventEndDate(parseEventEndDate(request.getEventEndDate(), event.getTimeMode()));
|
||||
|
||||
// 情绪评分
|
||||
if (request.getEmotionScore() != null) {
|
||||
@@ -251,8 +257,17 @@ public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent
|
||||
if (request.getTags() != null) {
|
||||
event.setTags(request.getTags());
|
||||
}
|
||||
if (StringUtils.hasText(request.getTimeMode())) {
|
||||
event.setTimeMode(request.getTimeMode());
|
||||
}
|
||||
if (request.getEventDateText() != null) {
|
||||
event.setEventDateText(request.getEventDateText());
|
||||
}
|
||||
if (StringUtils.hasText(request.getEventDate())) {
|
||||
event.setEventDate(parseEventDate(request.getEventDate()));
|
||||
event.setEventDate(parseEventDate(request.getEventDate(), event.getTimeMode(), event.getEventDateText()));
|
||||
}
|
||||
if (request.getEventEndDate() != null) {
|
||||
event.setEventEndDate(parseEventEndDate(request.getEventEndDate(), event.getTimeMode()));
|
||||
}
|
||||
if (request.getEmotionScore() != null) {
|
||||
event.setEmotionScore(BigDecimal.valueOf(request.getEmotionScore()));
|
||||
@@ -295,6 +310,9 @@ public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent
|
||||
if (event.getEventDate() != null) {
|
||||
response.setEventDate(event.getEventDate().format(ISO_FORMATTER));
|
||||
}
|
||||
if (event.getEventEndDate() != null) {
|
||||
response.setEventEndDate(event.getEventEndDate().format(ISO_FORMATTER));
|
||||
}
|
||||
if (event.getEmotionScore() != null) {
|
||||
response.setEmotionScore(event.getEmotionScore().doubleValue());
|
||||
}
|
||||
@@ -314,30 +332,79 @@ public class LifeEventServiceImpl extends ServiceImpl<LifeEventMapper, LifeEvent
|
||||
* @param dateStr 日期字符串
|
||||
* @return 解析后的LocalDateTime,解析失败返回当前时间
|
||||
*/
|
||||
private LocalDateTime parseEventDate(String dateStr) {
|
||||
if (!StringUtils.hasText(dateStr)) {
|
||||
private LocalDateTime parseEventDate(String dateStr, String timeMode, String eventDateText) {
|
||||
String source = StringUtils.hasText(dateStr) ? dateStr : eventDateText;
|
||||
if (!StringUtils.hasText(source)) {
|
||||
return LocalDateTime.now();
|
||||
}
|
||||
|
||||
if ("month".equals(timeMode)) {
|
||||
try {
|
||||
return YearMonth.parse(source.substring(0, 7), YEAR_MONTH_FORMATTER).atDay(1).atStartOfDay();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if ("season".equals(timeMode)) {
|
||||
LocalDate seasonDate = parseSeasonStart(source);
|
||||
if (seasonDate != null) {
|
||||
return seasonDate.atStartOfDay();
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试ISO格式 (yyyy-MM-ddTHH:mm:ss.SSSZ)
|
||||
try {
|
||||
return LocalDateTime.parse(dateStr, ISO_FORMATTER);
|
||||
return LocalDateTime.parse(source, ISO_FORMATTER);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// 尝试日期时间格式 (yyyy-MM-dd HH:mm:ss)
|
||||
try {
|
||||
return LocalDateTime.parse(dateStr, DATE_TIME_FORMATTER);
|
||||
return LocalDateTime.parse(source, DATE_TIME_FORMATTER);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// 尝试纯日期格式 (yyyy-MM-dd),时间设为当天开始
|
||||
try {
|
||||
return java.time.LocalDate.parse(dateStr, DATE_ONLY_FORMATTER).atStartOfDay();
|
||||
return LocalDate.parse(source, DATE_ONLY_FORMATTER).atStartOfDay();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// 所有格式都失败,返回当前时间
|
||||
return LocalDateTime.now();
|
||||
}
|
||||
|
||||
private LocalDateTime parseEventEndDate(String dateStr, String timeMode) {
|
||||
if (!"range".equals(timeMode) || !StringUtils.hasText(dateStr)) {
|
||||
return null;
|
||||
}
|
||||
return parseEventDate(dateStr, "date", dateStr);
|
||||
}
|
||||
|
||||
private LocalDate parseSeasonStart(String value) {
|
||||
try {
|
||||
String[] parts = value.split("-");
|
||||
int year = Integer.parseInt(parts[0]);
|
||||
String season = parts.length > 1 ? parts[1] : "spring";
|
||||
int month;
|
||||
switch (season) {
|
||||
case "summer":
|
||||
month = 6;
|
||||
break;
|
||||
case "autumn":
|
||||
month = 9;
|
||||
break;
|
||||
case "winter":
|
||||
month = 12;
|
||||
break;
|
||||
case "spring":
|
||||
default:
|
||||
month = 3;
|
||||
break;
|
||||
}
|
||||
return LocalDate.of(year, month, 1);
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user