refactor(app-api): 按新口径撤除 App 侧创作者中心的 works / stats
为什么:用户口径变更「创作者中心是 web 端,和 app 客户端没关系」,契约已由 PM 提交 bb21920
移除两条 C 端定义;本提交把代码对齐到新契约,App 侧创作者相关只保留入驻申请。
- 删除 GET /app/creator/works、GET /app/creator/stats 两个端点及无用注入
- 删除 CreatorStatsService.java(213 行,与后台 07 看板重复的独立实现)
- 删除随之成为死代码的:CreatorAppService.requireActiveCreator / myWorks、
CreatorCenterService.pageMyDramasOf、ErrorCode.CREATOR_NOT_ACTIVE(200007)
- 删除对应测试 7 条(works/stats 契约 4 条 + requireActive 3 条);
保留 apply 幂等与协议版本校验、config 白名单、notices 空列表
- 不动 POST /app/creator/apply、GET /app/config、GET /app/notices;不改 docs/api-phase1.md
- 实测:mvn test 98 → 91 条全过;package 通过;/v3/api-docs 接口数 41 → 39,
creator 相关只剩 /app/creator/apply;两个已撤除路径对已登录客户端返回 404
This commit is contained in:
1 parent
bb219203bc
commit
4418a840ec
7 files changed
+23
-422
No files matched your search
+1
-62
@@ -4,7 +4,6 @@ package com.fruitshorts.app.controller;
|
||||
|
||||
import com.fruitshorts.app.service.AppConfigService;
|
||||
import com.fruitshorts.app.service.AppNoticeService;
|
||||
import com.fruitshorts.app.service.CreatorStatsService;
|
||||
import com.fruitshorts.app.support.ControllerContractSupport;
|
||||
import com.fruitshorts.common.exception.ErrorCode;
|
||||
import com.fruitshorts.common.exception.ServiceException;
|
||||
@@ -55,7 +54,6 @@ class AppCreatorAndConfigContractTest {
|
||||
private AppConfigService appConfigService;
|
||||
private AppNoticeService appNoticeService;
|
||||
private CreatorAppService creatorAppService;
|
||||
private CreatorStatsService creatorStatsService;
|
||||
private MockMvc configMvc;
|
||||
private MockMvc creatorMvc;
|
||||
|
||||
@@ -64,11 +62,10 @@ class AppCreatorAndConfigContractTest {
|
||||
appConfigService = mock(AppConfigService.class);
|
||||
appNoticeService = mock(AppNoticeService.class);
|
||||
creatorAppService = mock(CreatorAppService.class);
|
||||
creatorStatsService = mock(CreatorStatsService.class);
|
||||
configMvc = ControllerContractSupport.mockMvcOf(
|
||||
new AppConfigController(appConfigService, appNoticeService));
|
||||
creatorMvc = ControllerContractSupport.mockMvcOf(new AppCreatorController(
|
||||
creatorAppService, creatorStatsService, appConfigService));
|
||||
creatorAppService, appConfigService));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -155,67 +152,9 @@ class AppCreatorAndConfigContractTest {
|
||||
.andExpect(jsonPath("$.data.created").value(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_when_viewing_works_without_active_creator() throws Exception {
|
||||
login();
|
||||
given(creatorAppService.myWorks(eq(USER), any()))
|
||||
.willThrow(new ServiceException(ErrorCode.CREATOR_NOT_ACTIVE, "尚未提交创作者入驻申请"));
|
||||
|
||||
creatorMvc.perform(get("/app/creator/works"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(ErrorCode.CREATOR_NOT_ACTIVE.getCode()))
|
||||
.andExpect(jsonPath("$.message").value("尚未提交创作者入驻申请"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_return_my_works_when_creator_is_active() throws Exception {
|
||||
login();
|
||||
CreatorCenterDramaVO vo = new CreatorCenterDramaVO();
|
||||
vo.setId(5L);
|
||||
vo.setTitle("命运的相遇");
|
||||
vo.setStatus("draft");
|
||||
given(creatorAppService.myWorks(eq(USER), any())).willReturn(new PageResult<>(1L, List.of(vo)));
|
||||
|
||||
creatorMvc.perform(get("/app/creator/works").param("pageIndex", "1").param("pageSize", "10"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.total").value(1))
|
||||
.andExpect(jsonPath("$.data.list[0].id").value(5))
|
||||
.andExpect(jsonPath("$.data.list[0].title").value("命运的相遇"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_when_viewing_stats_without_active_creator() throws Exception {
|
||||
login();
|
||||
given(creatorAppService.requireActiveCreator(USER))
|
||||
.willThrow(new ServiceException(ErrorCode.CREATOR_NOT_ACTIVE, "入驻申请审核中,请耐心等待"));
|
||||
|
||||
creatorMvc.perform(get("/app/creator/stats"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(ErrorCode.CREATOR_NOT_ACTIVE.getCode()));
|
||||
verify(creatorStatsService, never()).overview(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_return_dashboard_with_null_and_notes_when_stats_is_requested() throws Exception {
|
||||
login();
|
||||
Creator creator = new Creator();
|
||||
creator.setId(7L);
|
||||
creator.setStatus(CreatorService.STATUS_APPROVED);
|
||||
given(creatorAppService.requireActiveCreator(USER)).willReturn(creator);
|
||||
Map<String, Object> dashboard = new LinkedHashMap<>();
|
||||
dashboard.put("drama", Map.of("total", 2));
|
||||
dashboard.put("daily", null);
|
||||
dashboard.put("notes", List.of("daily 暂无数据源"));
|
||||
given(creatorStatsService.overview(creator)).willReturn(dashboard);
|
||||
|
||||
creatorMvc.perform(get("/app/creator/stats"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.drama.total").value(2))
|
||||
// 取不到的指标是 null(不是 0),并在 notes 里说明
|
||||
.andExpect(jsonPath("$.data.daily").value(org.hamcrest.Matchers.nullValue()))
|
||||
.andExpect(jsonPath("$.data.notes[0]").value("daily 暂无数据源"));
|
||||
}
|
||||
|
||||
private CreatorApplyRespVO applyResp(Long id, String status, boolean created) {
|
||||
CreatorApplyRespVO vo = new CreatorApplyRespVO();
|
||||
|
||||
+12
-44
@@ -9,7 +9,6 @@ import com.fruitshorts.common.exception.ServiceException;
|
||||
import com.fruitshorts.creator.dal.entity.Creator;
|
||||
import com.fruitshorts.creator.dal.mapper.CreatorMapper;
|
||||
import com.fruitshorts.creator.service.CreatorAppService;
|
||||
import com.fruitshorts.creator.service.CreatorCenterService;
|
||||
import com.fruitshorts.creator.service.CreatorService;
|
||||
import com.fruitshorts.creator.vo.CreatorApplyReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorApplyRespVO;
|
||||
@@ -52,7 +51,7 @@ class CreatorAppServiceTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
creatorMapper = mock(CreatorMapper.class);
|
||||
creatorAppService = new CreatorAppService(creatorMapper, mock(CreatorCenterService.class));
|
||||
creatorAppService = new CreatorAppService(creatorMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,51 +97,9 @@ class CreatorAppServiceTest {
|
||||
assertThat(resp.getStatus()).isEqualTo(CreatorService.STATUS_PENDING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_when_agreement_version_is_not_the_current_one() {
|
||||
assertThatThrownBy(() -> creatorAppService.apply(USER, req("2026-09-01"), AGREEMENT))
|
||||
.isInstanceOf(ServiceException.class)
|
||||
.satisfies(ex -> assertThat(((ServiceException) ex).getCode())
|
||||
.isEqualTo(ErrorCode.BAD_REQUEST.getCode()))
|
||||
.hasMessageContaining("请先同意最新版协议");
|
||||
verify(creatorMapper, never()).insert(any(Creator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_return_creator_when_status_is_approved() {
|
||||
given(creatorMapper.selectOne(any())).willReturn(creator(CreatorService.STATUS_APPROVED));
|
||||
|
||||
Creator creator = creatorAppService.requireActiveCreator(USER);
|
||||
|
||||
assertThat(creator.getStatus()).isEqualTo(CreatorService.STATUS_APPROVED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_with_creator_not_active_when_status_is_not_approved() {
|
||||
for (String status : new String[]{CreatorService.STATUS_PENDING, CreatorService.STATUS_REJECTED,
|
||||
CreatorService.STATUS_FROZEN}) {
|
||||
Creator creator = creator(status);
|
||||
creator.setAuditNote("资料不全");
|
||||
given(creatorMapper.selectOne(any())).willReturn(creator);
|
||||
|
||||
assertThatThrownBy(() -> creatorAppService.requireActiveCreator(USER))
|
||||
.as("状态 %s 应被拒", status)
|
||||
.isInstanceOf(ServiceException.class)
|
||||
.satisfies(ex -> assertThat(((ServiceException) ex).getCode())
|
||||
.isEqualTo(ErrorCode.CREATOR_NOT_ACTIVE.getCode()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_with_creator_not_active_when_user_never_applied() {
|
||||
given(creatorMapper.selectOne(any())).willReturn(null);
|
||||
|
||||
assertThatThrownBy(() -> creatorAppService.requireActiveCreator(USER))
|
||||
.isInstanceOf(ServiceException.class)
|
||||
.satisfies(ex -> assertThat(((ServiceException) ex).getCode())
|
||||
.isEqualTo(ErrorCode.CREATOR_NOT_ACTIVE.getCode()))
|
||||
.hasMessage("尚未提交创作者入驻申请");
|
||||
}
|
||||
|
||||
private AtomicReference<Creator> captureInsert() {
|
||||
AtomicReference<Creator> saved = new AtomicReference<>();
|
||||
@@ -155,6 +112,17 @@ class CreatorAppServiceTest {
|
||||
return saved;
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_when_agreement_version_is_not_the_current_one() {
|
||||
// 协议版本必须等于 /app/config 下发的当前版本(保留用例:apply 的协议校验)
|
||||
assertThatThrownBy(() -> creatorAppService.apply(USER, req("2026-09-01"), AGREEMENT))
|
||||
.isInstanceOf(ServiceException.class)
|
||||
.satisfies(ex -> assertThat(((ServiceException) ex).getCode())
|
||||
.isEqualTo(ErrorCode.BAD_REQUEST.getCode()))
|
||||
.hasMessageContaining("请先同意最新版协议");
|
||||
verify(creatorMapper, never()).insert(any(Creator.class));
|
||||
}
|
||||
|
||||
private CreatorApplyReqVO req(String agreementVersion) {
|
||||
CreatorApplyReqVO req = new CreatorApplyReqVO();
|
||||
req.setName("星野工作室");
|
||||
|
||||
Reference in new issue
Block a user