diff --git a/src/main/java/com/imyeyu/api/modules/journal/controller/JournalController.java b/src/main/java/com/imyeyu/api/modules/journal/controller/JournalController.java index 6d9081b..c9a11a0 100644 --- a/src/main/java/com/imyeyu/api/modules/journal/controller/JournalController.java +++ b/src/main/java/com/imyeyu/api/modules/journal/controller/JournalController.java @@ -1,20 +1,20 @@ package com.imyeyu.api.modules.journal.controller; -import com.google.gson.Gson; import com.imyeyu.api.bean.wechat.InitCodeResponse; import com.imyeyu.api.modules.common.bean.MediaAttach; import com.imyeyu.api.modules.common.bean.SettingKey; import com.imyeyu.api.modules.common.entity.Attachment; import com.imyeyu.api.modules.common.service.AttachmentService; import com.imyeyu.api.modules.common.service.SettingService; +import com.imyeyu.api.modules.journal.bean.Location; import com.imyeyu.api.modules.journal.bean.Travel; import com.imyeyu.api.modules.journal.entity.Journal; import com.imyeyu.api.modules.journal.service.JournalService; -import com.imyeyu.api.modules.journal.vo.AppendRequest; import com.imyeyu.api.modules.journal.vo.ArchiveRequest; import com.imyeyu.api.modules.journal.vo.JournalPage; import com.imyeyu.api.modules.journal.vo.JournalRequest; import com.imyeyu.api.modules.journal.vo.JournalResponse; +import com.imyeyu.api.modules.journal.vo.UpdateRequest; import com.imyeyu.java.bean.timi.TimiCode; import com.imyeyu.java.bean.timi.TimiException; import com.imyeyu.network.ArgMap; @@ -22,11 +22,14 @@ import com.imyeyu.network.GsonRequest; import com.imyeyu.spring.annotation.AOPLog; import com.imyeyu.spring.annotation.RequestRateLimit; import com.imyeyu.spring.annotation.RequestSingleParam; +import com.imyeyu.spring.bean.Page; import com.imyeyu.spring.bean.PageResult; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -35,6 +38,8 @@ import org.springframework.web.bind.annotation.RestController; import java.util.List; /** + * 微信小程序糕雨日记接口 + * * @author 夜雨 * @since 2025-09-26 15:55 */ @@ -44,11 +49,16 @@ import java.util.List; @RequestMapping("/journal") public class JournalController { - private final Gson gson; private final JournalService service; private final SettingService settingService; private final AttachmentService attachmentService; + /** + * 初始化用户 OpenId + * + * @param code 微信授权码 + * @return OpenId + */ @AOPLog @RequestRateLimit @PostMapping("/openid") @@ -67,6 +77,31 @@ public class JournalController { } } + @AOPLog + @RequestRateLimit + @RequestMapping("/{id}") + public JournalResponse detail(@PathVariable Long id) { + Journal journal = service.get(id); + JournalResponse resp = new JournalResponse(); + Page attachPage = new Page<>(); + { + Attachment example = new Attachment(); + example.setBizType(Attachment.BizType.JOURNAL); + example.setBizId(journal.getId()); + attachPage.setEqualsExample(example); + } + attachPage.setIndex(0); + attachPage.setSize(Long.MAX_VALUE); + resp.setItems(attachmentService.page(attachPage).getList()); + BeanUtils.copyProperties(journal, resp); + return resp; + } + + /** + * 创建记录 + * + * @param request + */ @AOPLog @RequestRateLimit @PostMapping("/create") @@ -74,17 +109,35 @@ public class JournalController { service.create(request); } - @PostMapping("/append") - public void append(@RequestBody AppendRequest request) { - service.appendItems(request); + /** + * 更新记录(支持附件差分保存) + * + * @param request 更新请求,包含 id、基本信息、保留的附件 ID 列表和新上传的临时文件 ID 列表 + */ + @AOPLog + @RequestRateLimit + @PostMapping("/update") + public void update(@RequestBody @Valid UpdateRequest request) { + service.update(request); } + /** + * 删除记录 + * + * @param id 记录 ID + */ @AOPLog @PostMapping("/delete") - public void delete(@RequestBody Long thumbId) { - attachmentService.deleteMedia(thumbId); + public void delete(@RequestBody Long id) { + service.delete(id); } + /** + * 记录列表 + * + * @param page 查询页面 + * @return + */ @AOPLog @RequestRateLimit @RequestMapping("/list") @@ -95,13 +148,30 @@ public class JournalController { result.setTotal(pageResult.getTotal()); result.setList(pageResult.getList().stream().map(item -> { JournalResponse resp = new JournalResponse(); - resp.setItems(attachmentService.listByBizId(Attachment.BizType.JOURNAL, item.getId())); + Page attachPage = new Page<>(); + { + Attachment example = new Attachment(); + example.setBizType(Attachment.BizType.JOURNAL); + example.setBizId(item.getId()); + attachPage.setEqualsExample(example); + } + attachPage.setIndex(0); + attachPage.setSize(switch (page.getType()) { + case NORMAL -> Long.MAX_VALUE; + case PREVIEW -> 2; // 原图缩略图并存 + }); + resp.setItems(attachmentService.page(attachPage).getList()); BeanUtils.copyProperties(item, resp); return resp; }).toList()); return result; } + /** + * 所有记录日期列表 + * + * @return + */ @AOPLog @RequestRateLimit @GetMapping("/list/date") @@ -109,6 +179,22 @@ public class JournalController { return service.listDate(); } + /** + * 所有记录位置列表 + * + * @return + */ + @RequestRateLimit + @GetMapping("/list/location") + public List listLocation() { + return null; + } + + /** + * 已记录照片、视频数量 + * + * @return + */ @RequestRateLimit @GetMapping("/total") public long total() { @@ -117,6 +203,11 @@ public class JournalController { return journal + journalTravel; } + /** + * + * + * @return + */ @RequestRateLimit @GetMapping("/travel") public Travel getTravel() { @@ -130,6 +221,12 @@ public class JournalController { service.updateTravelLuggage(luggage); } + /** + * 创建瞬间(上传的临时文件持久化储存,微信限制单次上传数量) + * + * @param tempFileIds + * @return + */ @AOPLog @RequestRateLimit @PostMapping("/moment/create") @@ -137,13 +234,34 @@ public class JournalController { return service.createMoment(tempFileIds); } + /** + * 瞬间列表 + * + * @return + */ @AOPLog @RequestRateLimit @PostMapping("/moment/list") public List listMoment() { - return service.listMoment(); + Page page = new Page<>(); + { + Attachment example = new Attachment(); + example.setBizType(Attachment.BizType.JOURNAL_MOMENT); + example.setBizId(0L); + example.setAttachTypeValue(MediaAttach.Type.THUMB); + page.setEqualsExample(example); + } + page.setIndex(0); + page.setSize(Long.MAX_VALUE); + return attachmentService.page(page).getList(); } + /** + * 检查待上传文件是否已存在 + * + * @param md5s + * @return 不存在的文件 md5 列表 + */ @AOPLog @RequestRateLimit @PostMapping("/moment/filter") @@ -151,6 +269,11 @@ public class JournalController { return service.filterExistMoment(md5s); } + /** + * 删除瞬间 + * + * @param thumbIds 缩略图附件 ID 列表 + */ @AOPLog @RequestRateLimit @PostMapping("/moment/delete") @@ -158,6 +281,11 @@ public class JournalController { service.deleteMoment(thumbIds); } + /** + * 归档瞬间,归档记录 ID 不为空时表示归档到指定记录 + * + * @param request + */ @AOPLog @RequestRateLimit @PostMapping("/moment/archive") diff --git a/src/main/java/com/imyeyu/api/modules/journal/mapper/JournalMapper.java b/src/main/java/com/imyeyu/api/modules/journal/mapper/JournalMapper.java index f605a5c..b52a08e 100644 --- a/src/main/java/com/imyeyu/api/modules/journal/mapper/JournalMapper.java +++ b/src/main/java/com/imyeyu/api/modules/journal/mapper/JournalMapper.java @@ -4,20 +4,12 @@ import com.imyeyu.api.modules.journal.entity.Journal; import com.imyeyu.spring.mapper.BaseMapper; import org.apache.ibatis.annotations.Select; -import java.util.List; - /** * @author 夜雨 * @since 2025-09-26 15:54 */ public interface JournalMapper extends BaseMapper { - @Select("SELECT COUNT(1) FROM `journal` WHERE `type` = #{type}") - long countByType(Journal.Type type); - - @Select("SELECT * FROM `journal` WHERE `type` = #{type} AND `deleted_at` IS NULL ORDER BY `created_at` DESC LIMIT #{offset}, #{limit}") - List listByType(Journal.Type type, long offset, int limit); - @Select("SELECT created_at FROM `journal` WHERE `deleted_at` IS NULL") Long[] listDate(); } diff --git a/src/main/java/com/imyeyu/api/modules/journal/service/JournalService.java b/src/main/java/com/imyeyu/api/modules/journal/service/JournalService.java index e9a4ad3..3cc459a 100644 --- a/src/main/java/com/imyeyu/api/modules/journal/service/JournalService.java +++ b/src/main/java/com/imyeyu/api/modules/journal/service/JournalService.java @@ -3,13 +3,13 @@ package com.imyeyu.api.modules.journal.service; import com.imyeyu.api.modules.common.entity.Attachment; import com.imyeyu.api.modules.journal.bean.Travel; import com.imyeyu.api.modules.journal.entity.Journal; -import com.imyeyu.api.modules.journal.vo.AppendRequest; import com.imyeyu.api.modules.journal.vo.ArchiveRequest; -import com.imyeyu.api.modules.journal.vo.JournalPage; import com.imyeyu.api.modules.journal.vo.JournalRequest; +import com.imyeyu.api.modules.journal.vo.UpdateRequest; import com.imyeyu.java.bean.timi.TimiException; -import com.imyeyu.spring.bean.PageResult; import com.imyeyu.spring.service.DeletableService; +import com.imyeyu.spring.service.GettableService; +import com.imyeyu.spring.service.PageableService; import java.util.List; @@ -17,22 +17,25 @@ import java.util.List; * @author 夜雨 * @since 2025-09-26 15:53 */ -public interface JournalService extends DeletableService { - - PageResult page(JournalPage page) throws TimiException; +public interface JournalService extends PageableService, GettableService, DeletableService { Long[] listDate() throws TimiException; void create(JournalRequest request) throws TimiException; - void appendItems(AppendRequest request) throws TimiException; + void update(UpdateRequest request) throws TimiException; + /** + * 过滤已存在瞬间 + * + * @param md5s 原图文件 MD5 列表 + * @return 未持久化储存的 MD5 列表 + * @throws TimiException + */ String[] filterExistMoment(String[] md5s) throws TimiException; List createMoment(String[] tempFileIds) throws TimiException; - List listMoment() throws TimiException; - void deleteMoment(Long[] thumbIds) throws TimiException; void archiveMoment(ArchiveRequest request) throws TimiException; diff --git a/src/main/java/com/imyeyu/api/modules/journal/service/implement/JournalServiceImplement.java b/src/main/java/com/imyeyu/api/modules/journal/service/implement/JournalServiceImplement.java index 28aa03a..dc75716 100644 --- a/src/main/java/com/imyeyu/api/modules/journal/service/implement/JournalServiceImplement.java +++ b/src/main/java/com/imyeyu/api/modules/journal/service/implement/JournalServiceImplement.java @@ -15,16 +15,13 @@ import com.imyeyu.api.modules.journal.bean.Travel; import com.imyeyu.api.modules.journal.entity.Journal; import com.imyeyu.api.modules.journal.mapper.JournalMapper; import com.imyeyu.api.modules.journal.service.JournalService; -import com.imyeyu.api.modules.journal.vo.AppendRequest; import com.imyeyu.api.modules.journal.vo.ArchiveRequest; -import com.imyeyu.api.modules.journal.vo.JournalPage; import com.imyeyu.api.modules.journal.vo.JournalRequest; +import com.imyeyu.api.modules.journal.vo.UpdateRequest; import com.imyeyu.io.IO; import com.imyeyu.java.TimiJava; import com.imyeyu.java.bean.timi.TimiCode; import com.imyeyu.java.bean.timi.TimiException; -import com.imyeyu.spring.bean.Page; -import com.imyeyu.spring.bean.PageResult; import com.imyeyu.spring.mapper.BaseMapper; import com.imyeyu.spring.service.AbstractEntityService; import lombok.RequiredArgsConstructor; @@ -36,7 +33,6 @@ import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -63,14 +59,6 @@ public class JournalServiceImplement extends AbstractEntityService page(JournalPage page) { - PageResult result = new PageResult<>(); - result.setTotal(mapper.countByType(page.getType())); - result.setList(mapper.listByType(page.getType(), page.getOffset(), page.getLimit())); - return result; - } - @Override public Long[] listDate() throws TimiException { return mapper.listDate(); @@ -105,30 +93,53 @@ public class JournalServiceImplement extends AbstractEntityService dbAttachSet = attachmentService.listByBizId(Attachment.BizType.JOURNAL, journal.getId(), MediaAttach.Type.THUMB) + .stream() + .map(Attachment::getId) + .collect(Collectors.toSet()); + Set retainIds = Set.of(TimiJava.firstNotEmpty(request.getAttachmentIds(), new Long[0])); + dbAttachSet.removeAll(retainIds); + for (Long removeId : dbAttachSet) { + attachmentService.deleteMedia(removeId); + } + // 新增 String[] tempFileIds = request.getTempFileIds(); - for (int i = 0; i < tempFileIds.length; i++) { - TempFileMetaData metadata = tempFileService.metadata(tempFileIds[i]); - File file = tempFileService.get(tempFileIds[i]); + if (TimiJava.isNotEmpty(tempFileIds)) { + for (int i = 0; i < tempFileIds.length; i++) { + TempFileMetaData metadata = tempFileService.metadata(tempFileIds[i]); + File file = tempFileService.get(tempFileIds[i]); - AttachmentRequest sourceAttach = new AttachmentRequest(); - sourceAttach.setName(metadata.getOriginalName()); - sourceAttach.setBizType(Attachment.BizType.JOURNAL); - sourceAttach.setBizId(journal.getId()); - sourceAttach.setInputStream(IO.getInputStream(file)); - attachmentService.createMedia(sourceAttach); + AttachmentRequest sourceAttach = new AttachmentRequest(); + sourceAttach.setName(metadata.getOriginalName()); + sourceAttach.setBizType(Attachment.BizType.JOURNAL); + sourceAttach.setBizId(journal.getId()); + sourceAttach.setInputStream(IO.getInputStream(file)); + attachmentService.createMedia(sourceAttach); + } } } catch (Exception e) { - log.error("create journal error", e); - throw new TimiException(TimiCode.ERROR).msgKey("TODO create journal error"); + log.error("update journal error", e); + throw new TimiException(TimiCode.ERROR).msgKey("TODO update journal error"); } } + @Transactional(TimiServerDBConfig.ROLLBACKER) + @Override + public void delete(Long id) { + super.delete(id); + attachmentService.deleteByBizId(Attachment.BizType.JOURNAL, id); + } + @Override public String[] filterExistMoment(String[] md5s) throws TimiException { if (TimiJava.isEmpty(md5s)) { @@ -168,15 +179,6 @@ public class JournalServiceImplement extends AbstractEntityService listMoment() throws TimiException { - Page page = new Page(0, Integer.MAX_VALUE); - LinkedHashMap orderMap = new LinkedHashMap<>(); - orderMap.put("created_at", BaseMapper.OrderType.DESC); - page.setOrderMap(orderMap); - return attachmentService.pageByBizId(Attachment.BizType.JOURNAL_MOMENT, 0L, List.of(MediaAttach.Type.THUMB), page).getList(); - } - @Override public void deleteMoment(Long[] thumbIds) throws TimiException { for (int i = 0; i < thumbIds.length; i++) { @@ -187,10 +189,16 @@ public class JournalServiceImplement extends AbstractEntityService { - private Journal.Type type; + /** + * + * + * @author 夜雨 + * @since 2025-12-08 16:01 + */ + public enum Type { + + NORMAL, + + PREVIEW + } + + @NotNull + private Type type; } \ No newline at end of file diff --git a/src/main/java/com/imyeyu/api/modules/journal/vo/JournalRequest.java b/src/main/java/com/imyeyu/api/modules/journal/vo/JournalRequest.java index e0eaa57..67f7d08 100644 --- a/src/main/java/com/imyeyu/api/modules/journal/vo/JournalRequest.java +++ b/src/main/java/com/imyeyu/api/modules/journal/vo/JournalRequest.java @@ -6,6 +6,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; /** + * 创建日志记录 + * * @author 夜雨 * @since 2025-09-26 15:56 */ @@ -13,6 +15,7 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class JournalRequest extends Journal { + /** 临时文件 ID 列表 */ @Transient private String[] tempFileIds; } diff --git a/src/main/java/com/imyeyu/api/modules/journal/vo/UpdateRequest.java b/src/main/java/com/imyeyu/api/modules/journal/vo/UpdateRequest.java new file mode 100644 index 0000000..1ad3a41 --- /dev/null +++ b/src/main/java/com/imyeyu/api/modules/journal/vo/UpdateRequest.java @@ -0,0 +1,25 @@ +package com.imyeyu.api.modules.journal.vo; + +import com.imyeyu.api.modules.journal.entity.Journal; +import com.imyeyu.spring.annotation.table.Transient; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 更新日志记录请求 + * + * @author 夜雨 + * @since 2025-12-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UpdateRequest extends Journal { + + /** 临时文件 ID 列表(新上传的附件) */ + @Transient + private String[] tempFileIds; + + /** 保留的附件 ID 列表(用于差分删除) */ + @Transient + private Long[] attachmentIds; +}