v1.0.30 #40

Merged
timi merged 9 commits from dev into master 2026-09-01 17:38:50 +00:00
7 changed files with 318 additions and 0 deletions
Showing only changes of commit b7fcecfa7b - Show all commits
@@ -1,6 +1,7 @@
package com.imyeyu.api.modules.common.entity; package com.imyeyu.api.modules.common.entity;
import com.imyeyu.api.modules.common.bean.attachment.SettingSupport; import com.imyeyu.api.modules.common.bean.attachment.SettingSupport;
import com.imyeyu.api.modules.user.entity.User;
import com.imyeyu.spring.annotation.table.PageIgnore; import com.imyeyu.spring.annotation.table.PageIgnore;
import com.imyeyu.spring.annotation.table.Transient; import com.imyeyu.spring.annotation.table.Transient;
import com.imyeyu.spring.entity.UUIDEntity; import com.imyeyu.spring.entity.UUIDEntity;
@@ -30,6 +31,9 @@ public class Article extends UUIDEntity implements SettingSupport {
/** 博客 */ /** 博客 */
BLOG, BLOG,
/// GAO 门店日记
GAO_STORE_DIARY,
/// 反馈 /// 反馈
FEEDBACK FEEDBACK
} }
@@ -93,6 +97,12 @@ public class Article extends UUIDEntity implements SettingSupport {
/** 文章状态 */ /** 文章状态 */
protected Status status; protected Status status;
/// 最后更新用户 ID
protected String updatedBy;
@Transient
protected User updater;
@Transient @Transient
protected List<Setting> settingList; protected List<Setting> settingList;
@@ -21,6 +21,14 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
STORE_DELETE("STORE:DELETE", "门店删除", false, true), STORE_DELETE("STORE:DELETE", "门店删除", false, true),
STORE_DIARY_CREATE("STORE_DIARY:CREATE", "门店日记创建", true, true),
STORE_DIARY_READ("STORE_DIARY:READ", "门店日记读取", true, true),
STORE_DIARY_UPDATE("STORE_DIARY:UPDATE", "门店日记修改", true, true),
STORE_DIARY_DELETE("STORE_DIARY:DELETE", "门店日记删除", true, true),
CUSTOMER_CREATE("CUSTOMER:CREATE", "客户创建", false, false), CUSTOMER_CREATE("CUSTOMER:CREATE", "客户创建", false, false),
CUSTOMER_READ("CUSTOMER:READ", "客户读取", false, false), CUSTOMER_READ("CUSTOMER:READ", "客户读取", false, false),
@@ -0,0 +1,129 @@
package com.imyeyu.api.modules.gao.controller;
import com.fasterxml.jackson.annotation.JsonView;
import com.imyeyu.api.modules.common.entity.Article;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.service.AttachmentService;
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
import com.imyeyu.api.modules.user.entity.User;
import com.imyeyu.api.modules.user.service.UserLoginService;
import com.imyeyu.api.modules.user.service.UserService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
import com.imyeyu.spring.util.ResponseView;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/// GAO 门店日记接口
///
/// @author Codex
/// @since 2026-08-31
@RestController
@RequiredArgsConstructor
@RequestMapping("/gao/store/diary")
public class GaoStoreDiaryController {
private final GaoStoreDiaryService service;
private final GaoStoreScopeService storeScopeService;
private final UserLoginService userLoginService;
private final UserService userService;
private final AttachmentService attachmentService;
/// 分页查询门店日记
///
/// @param page 分页查询条件
/// @return 门店日记分页结果
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_READ)
@PostMapping("/list")
@JsonView(ResponseView.Public.class)
public PageResult<Article> list(@RequestBody Page<Article> page) {
TimiException.required(page, "未找到分页参数");
Article example = TimiJava.defaultIfNull(page.getEqualsExample(), new Article());
example.setBizType(Article.BizType.GAO_STORE_DIARY);
example.setBizId(storeScopeService.resolveStoreId(example.getBizId()));
page.setEqualsExample(example);
return service.page(page);
}
/// 查询门店日记详情
///
/// @param id 日记 ID
/// @return 门店日记
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_READ)
@PostMapping("/detail")
@JsonView(ResponseView.Public.class)
public Article detail(@RequestParam String id) {
Article article = service.get(id);
storeScopeService.checkStoreId(article.getBizId());
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
if (TimiJava.isNotEmpty(article.getUpdatedBy())) {
User updater = userService.get(article.getUpdatedBy());
if (updater != null) {
updater.setAttachmentList(attachmentService.listByBizId(
Attachment.BizType.USER,
updater.getId(),
User.AttachType.AVATAR.toString()
));
}
article.setUpdater(updater);
}
return article;
}
/// 创建门店日记
///
/// @param article 门店日记
/// @return 日记 ID
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_CREATE)
@PostMapping("/create")
public String create(@RequestBody Article article) {
article.setBizId(storeScopeService.resolveStoreId(article.getBizId()));
service.create(article, userLoginService.getRequireLoginUserId());
return article.getId();
}
/// 修改门店日记
///
/// @param article 门店日记
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_UPDATE)
@PostMapping("/update")
public void update(@RequestBody Article article) {
TimiException.required(article, "未找到门店日记");
TimiException.required(article.getId(), "未找到门店日记 ID");
Article dbArticle = service.get(article.getId());
storeScopeService.checkStoreId(dbArticle.getBizId());
service.update(article, userLoginService.getRequireLoginUserId());
}
/// 删除门店日记
///
/// @param id 日记 ID
@AOPLog
@RequestRateLimit
@RequireGaoPermission(GaoPermissionCode.STORE_DIARY_DELETE)
@PostMapping("/delete")
public void delete(@RequestParam String id) {
Article article = service.get(id);
storeScopeService.checkStoreId(article.getBizId());
service.delete(article.getId());
}
}
@@ -0,0 +1,46 @@
package com.imyeyu.api.modules.gao.service;
import com.imyeyu.api.modules.common.entity.Article;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
/// GAO 门店日记服务
///
/// @author Codex
/// @since 2026-08-31
public interface GaoStoreDiaryService {
/// 分页查询门店日记
///
/// @param page 分页查询条件
/// @return 门店日记分页结果
PageResult<Article> page(Page<Article> page);
/// 查询门店日记详情
///
/// @param id 日记 ID
/// @return 门店日记
Article get(String id);
/// 创建门店日记
///
/// @param article 门店日记
/// @param userId 操作用户 ID
void create(Article article, String userId);
/// 修改门店日记
///
/// @param article 门店日记
/// @param userId 操作用户 ID
void update(Article article, String userId);
/// 删除门店日记
///
/// @param id 日记 ID
void delete(String id);
/// 删除门店下的全部日记
///
/// @param storeId 门店 ID
void deleteByStoreId(String storeId);
}
@@ -0,0 +1,113 @@
package com.imyeyu.api.modules.gao.service.implement;
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
import com.imyeyu.api.modules.common.entity.Article;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.mapper.ArticleMapper;
import com.imyeyu.api.modules.common.service.ArticleService;
import com.imyeyu.api.modules.common.service.AttachmentService;
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/// GAO 门店日记服务实现
///
/// @author Codex
/// @since 2026-08-31
@Service
@RequiredArgsConstructor
public class GaoStoreDiaryServiceImplement implements GaoStoreDiaryService {
private final ArticleService articleService;
private final AttachmentService attachmentService;
private final ArticleMapper articleMapper;
@Override
public PageResult<Article> page(Page<Article> page) {
return articleService.page(page);
}
@Override
public Article get(String id) {
Article article = articleService.get(id);
checkStoreDiary(article);
return article;
}
@Override
@Transactional(TimiServerDBConfig.ROLLBACKER)
public void create(Article article, String userId) {
prepare(article, userId);
articleService.create(article);
}
@Override
@Transactional(TimiServerDBConfig.ROLLBACKER)
public void update(Article article, String userId) {
TimiException.required(article, "未找到门店日记");
TimiException.required(article.getId(), "未找到门店日记 ID");
Article dbArticle = get(article.getId());
article.setBizType(dbArticle.getBizType());
article.setBizId(dbArticle.getBizId());
article.setCreatedAt(null);
article.setUpdatedAt(null);
article.setDeletedAt(null);
article.setReads(dbArticle.getReads());
article.setLikes(dbArticle.getLikes());
article.setUpdatedBy(userId);
articleService.update(article);
}
@Override
@Transactional(TimiServerDBConfig.ROLLBACKER)
public void delete(String id) {
Article article = get(id);
attachmentService.deleteByBizId(Attachment.BizType.ARTICLE, article.getId());
articleService.delete(article.getId());
}
@Override
@Transactional(TimiServerDBConfig.ROLLBACKER)
public void deleteByStoreId(String storeId) {
TimiException.required(storeId, "未找到门店 ID");
Article example = new Article();
example.setBizType(Article.BizType.GAO_STORE_DIARY);
example.setBizId(storeId);
for (Article article : articleMapper.selectAllByExample(example)) {
attachmentService.deleteByBizId(Attachment.BizType.ARTICLE, article.getId());
articleService.delete(article.getId());
}
}
/// 固定门店日记业务类型并写入更新用户
///
/// @param article 门店日记
/// @param userId 操作用户 ID
private void prepare(Article article, String userId) {
TimiException.required(article, "未找到门店日记");
TimiException.required(article.getBizId(), "未找到门店 ID");
TimiException.required(userId, "未找到更新用户 ID");
article.setBizType(Article.BizType.GAO_STORE_DIARY);
article.setCreatedAt(null);
article.setUpdatedAt(null);
article.setDeletedAt(null);
article.setUpdatedBy(userId);
article.setReads(0);
article.setLikes(0);
article.setStatus(TimiJava.defaultIfNull(article.getStatus(), Article.Status.NORMAL));
}
/// 校验文章确实是门店日记
///
/// @param article 文章
private void checkStoreDiary(Article article) {
TimiException.required(article, "未找到门店日记");
TimiException.requiredTrue(article.getBizType() == Article.BizType.GAO_STORE_DIARY, "门店日记类型无效");
TimiException.required(article.getBizId(), "未找到门店 ID");
}
}
@@ -11,6 +11,7 @@ import com.imyeyu.api.modules.gao.service.GaoEventService;
import com.imyeyu.api.modules.gao.service.GaoPointAccountService; import com.imyeyu.api.modules.gao.service.GaoPointAccountService;
import com.imyeyu.api.modules.gao.service.GaoPointRuleService; import com.imyeyu.api.modules.gao.service.GaoPointRuleService;
import com.imyeyu.api.modules.gao.service.GaoStoreBusinessDayService; import com.imyeyu.api.modules.gao.service.GaoStoreBusinessDayService;
import com.imyeyu.api.modules.gao.service.GaoStoreDiaryService;
import com.imyeyu.api.modules.gao.service.GaoStoreService; import com.imyeyu.api.modules.gao.service.GaoStoreService;
import com.imyeyu.api.modules.gao.service.GaoUserService; import com.imyeyu.api.modules.gao.service.GaoUserService;
import com.imyeyu.api.modules.gao.util.StoreXSSFBuilder; import com.imyeyu.api.modules.gao.util.StoreXSSFBuilder;
@@ -55,6 +56,7 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
private final GaoPointAccountService pointAccountService; private final GaoPointAccountService pointAccountService;
private final GaoPointRuleService pointRuleService; private final GaoPointRuleService pointRuleService;
private final GaoStoreBusinessDayService businessDayService; private final GaoStoreBusinessDayService businessDayService;
private final GaoStoreDiaryService storeDiaryService;
private final ObjectProvider<GaoUserService> gaoUserServiceProvider; private final ObjectProvider<GaoUserService> gaoUserServiceProvider;
private final TagService tagService; private final TagService tagService;
@@ -140,6 +142,7 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
deleteGaoUsers(store.getId()); deleteGaoUsers(store.getId());
deletePointAccounts(store.getId()); deletePointAccounts(store.getId());
deleteStoreTags(store.getId()); deleteStoreTags(store.getId());
deleteStoreDiaries(store.getId());
store.setStatus(GaoStore.Status.DELETED); store.setStatus(GaoStore.Status.DELETED);
super.update(store); super.update(store);
super.delete(id); super.delete(id);
@@ -208,6 +211,13 @@ public class GaoStoreServiceImplement extends AbstractEntityService<GaoStore, St
tagService.deleteByOwner(Tag.OwnerType.GAO_STORE, storeId); tagService.deleteByOwner(Tag.OwnerType.GAO_STORE, storeId);
} }
/// 删除门店日记及其附件
///
/// @param storeId 门店 ID
private void deleteStoreDiaries(String storeId) {
storeDiaryService.deleteByStoreId(storeId);
}
@Override @Override
public GaoStore getByUserId(String userId) { public GaoStore getByUserId(String userId) {
TimiException.required(userId, "not found userId"); TimiException.required(userId, "not found userId");
@@ -0,0 +1,2 @@
ALTER TABLE `article`
ADD COLUMN `updated_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '最后更新用户 ID' AFTER `updated_at`;