mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-07-18 21:18:01 +08:00
新增当前用户待办接口和权限测试
This commit is contained in:
@@ -42,8 +42,8 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
|
|||||||
| 批次 | 范围 | 优先级 | 状态 | 验收结果 | Commit |
|
| 批次 | 范围 | 优先级 | 状态 | 验收结果 | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| B01 | 任务拆分、数据表和索引 | P0 | done | SQL 结构和索引评审通过 | `e65017ab2` |
|
| B01 | 任务拆分、数据表和索引 | P0 | done | SQL 结构和索引评审通过 | `e65017ab2` |
|
||||||
| B02 | 实体、命令模型、枚举、Mapper、Service | P0 | done | 模块编译和 Mapper XML 校验通过 | 本批提交 |
|
| B02 | 实体、命令模型、枚举、Mapper、Service | P0 | done | 模块编译和 Mapper XML 校验通过 | `181d4a5b4` |
|
||||||
| B03 | 当前用户查询、已读、完成、取消接口及测试 | P0 | todo | - | - |
|
| B03 | 当前用户查询、已读、完成、取消接口及测试 | P0 | done | 全量依赖编译、9 个专项测试通过 | 本批提交 |
|
||||||
| B04 | 前端 API、待办中心页面和路由跳转 | P0 | todo | - | - |
|
| B04 | 前端 API、待办中心页面和路由跳转 | P0 | todo | - | - |
|
||||||
| B05 | 首页待办卡片、数量展示和轮询刷新 | P0 | todo | - | - |
|
| B05 | 首页待办卡片、数量展示和轮询刷新 | P0 | todo | - | - |
|
||||||
| B06 | 菜单权限 SQL、联调和首期回归 | P0 | todo | - | - |
|
| B06 | 菜单权限 SQL、联调和首期回归 | P0 | todo | - | - |
|
||||||
@@ -84,7 +84,7 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
|
|||||||
|
|
||||||
- 优先级:P0
|
- 优先级:P0
|
||||||
- 批次:B03
|
- 批次:B03
|
||||||
- 状态:todo
|
- 状态:done
|
||||||
- 目标:实现未完成数量、首页列表、分页列表、详情、已读、全部已读、完成和取消接口。
|
- 目标:实现未完成数量、首页列表、分页列表、详情、已读、全部已读、完成和取消接口。
|
||||||
- 验收标准:
|
- 验收标准:
|
||||||
- 所有用户端查询和更新强制使用当前登录用户 ID。
|
- 所有用户端查询和更新强制使用当前登录用户 ID。
|
||||||
@@ -175,4 +175,5 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
|
|||||||
|
|
||||||
- 2026-07-16,B01:完成优先级拆分、任务跟踪文档和 `sys_todo_task` 建表脚本;通过 SQL 人工结构评审与 `git diff --check`;commit `e65017ab2`。
|
- 2026-07-16,B01:完成优先级拆分、任务跟踪文档和 `sys_todo_task` 建表脚本;通过 SQL 人工结构评审与 `git diff --check`;commit `e65017ab2`。
|
||||||
- 2026-07-16,B01 环境进展:用户已在测试数据库创建 `sys_todo_task` 表,可供后续接口联调。
|
- 2026-07-16,B01 环境进展:用户已在测试数据库创建 `sys_todo_task` 表,可供后续接口联调。
|
||||||
- 2026-07-16,B02:完成领域模型、创建/查询 DTO、状态常量、Mapper 和统一 Service;`mvn -pl jsowell-system -am -DskipTests compile` 与 Mapper XML 语法校验通过;commit hash 在下一批记录中回填。
|
- 2026-07-16,B02:完成领域模型、创建/查询 DTO、状态常量、Mapper 和统一 Service;`mvn -pl jsowell-system -am -DskipTests compile` 与 Mapper XML 语法校验通过;commit `181d4a5b4`。
|
||||||
|
- 2026-07-16,B03:完成当前用户数量、首页列表、分页列表、详情、已读、全部已读、完成和取消接口;`mvn -pl jsowell-admin -am -DskipTests compile` 通过,9 个 Service/Controller 专项测试通过;commit hash 在下一批记录中回填。
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.jsowell.web.controller.system;
|
||||||
|
|
||||||
|
import com.jsowell.common.annotation.Log;
|
||||||
|
import com.jsowell.common.core.controller.BaseController;
|
||||||
|
import com.jsowell.common.core.domain.AjaxResult;
|
||||||
|
import com.jsowell.common.core.page.TableDataInfo;
|
||||||
|
import com.jsowell.common.enums.BusinessType;
|
||||||
|
import com.jsowell.system.domain.SysTodoTask;
|
||||||
|
import com.jsowell.system.domain.dto.TodoTaskCancelRequest;
|
||||||
|
import com.jsowell.system.domain.dto.TodoTaskQuery;
|
||||||
|
import com.jsowell.system.service.TodoTaskService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前登录用户待办任务接口。
|
||||||
|
*
|
||||||
|
* @author jsowell
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/todo")
|
||||||
|
public class SysTodoTaskController extends BaseController {
|
||||||
|
@Autowired
|
||||||
|
private TodoTaskService todoTaskService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户待办数量。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:list')")
|
||||||
|
@GetMapping("/unreadCount")
|
||||||
|
public AjaxResult unreadCount() {
|
||||||
|
Long userId = getUserId();
|
||||||
|
Map<String, Integer> counts = new HashMap<>(2);
|
||||||
|
counts.put("activeCount", todoTaskService.countActive(userId));
|
||||||
|
counts.put("unreadCount", todoTaskService.countUnread(userId));
|
||||||
|
return AjaxResult.success(counts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取首页最近待办。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:list')")
|
||||||
|
@GetMapping("/homeList")
|
||||||
|
public AjaxResult homeList(@RequestParam(required = false) Integer limit) {
|
||||||
|
return AjaxResult.success(todoTaskService.homeList(getUserId(), limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询当前用户待办。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(TodoTaskQuery query) {
|
||||||
|
startPage();
|
||||||
|
List<SysTodoTask> list = todoTaskService.listForAssignee(query, getUserId());
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前用户待办详情。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:query')")
|
||||||
|
@GetMapping("/{todoId}")
|
||||||
|
public AjaxResult getInfo(@PathVariable Long todoId) {
|
||||||
|
return AjaxResult.success(todoTaskService.getForAssignee(todoId, getUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记当前用户的一条待办为已读。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:read')")
|
||||||
|
@PutMapping("/{todoId}/read")
|
||||||
|
public AjaxResult markRead(@PathVariable Long todoId) {
|
||||||
|
return toAjax(todoTaskService.markRead(todoId, getUserId(), getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记当前用户全部待办为已读。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:read')")
|
||||||
|
@PutMapping("/readAll")
|
||||||
|
public AjaxResult markAllRead() {
|
||||||
|
return AjaxResult.success(todoTaskService.markAllRead(getUserId(), getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 完成当前用户待办。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:complete')")
|
||||||
|
@Log(title = "待办任务", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/{todoId}/complete")
|
||||||
|
public AjaxResult complete(@PathVariable Long todoId) {
|
||||||
|
return toAjax(todoTaskService.complete(todoId, getUserId(), getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消当前用户待办。
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:todo:cancel')")
|
||||||
|
@Log(title = "待办任务", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/{todoId}/cancel")
|
||||||
|
public AjaxResult cancel(@PathVariable Long todoId,
|
||||||
|
@Validated @RequestBody TodoTaskCancelRequest request) {
|
||||||
|
return toAjax(todoTaskService.cancelForAssignee(todoId, getUserId(), getUsername(), request.getReason()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package com.jsowell.system.service;
|
||||||
|
|
||||||
|
import com.jsowell.common.exception.ServiceException;
|
||||||
|
import com.jsowell.system.constant.TodoTaskConstants;
|
||||||
|
import com.jsowell.system.domain.SysTodoTask;
|
||||||
|
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
|
||||||
|
import com.jsowell.system.domain.dto.TodoTaskQuery;
|
||||||
|
import com.jsowell.system.mapper.SysTodoTaskMapper;
|
||||||
|
import com.jsowell.system.service.impl.TodoTaskServiceImpl;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
class TodoTaskServiceImplTest {
|
||||||
|
@Test
|
||||||
|
void createTask_shouldSetDefaultsAndInsert() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
TodoTaskCreateCommand command = createCommand();
|
||||||
|
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(null);
|
||||||
|
doAnswer(invocation -> {
|
||||||
|
SysTodoTask task = invocation.getArgument(0);
|
||||||
|
task.setTodoId(11L);
|
||||||
|
return 1;
|
||||||
|
}).when(mapper).insertTodoTask(any(SysTodoTask.class));
|
||||||
|
|
||||||
|
SysTodoTask result = service.createTask(command);
|
||||||
|
|
||||||
|
ArgumentCaptor<SysTodoTask> captor = ArgumentCaptor.forClass(SysTodoTask.class);
|
||||||
|
verify(mapper).insertTodoTask(captor.capture());
|
||||||
|
SysTodoTask inserted = captor.getValue();
|
||||||
|
assertEquals(11L, result.getTodoId());
|
||||||
|
assertEquals(TodoTaskConstants.PRIORITY_NORMAL, inserted.getPriority());
|
||||||
|
assertEquals(TodoTaskConstants.STATUS_PENDING, inserted.getTaskStatus());
|
||||||
|
assertEquals(TodoTaskConstants.READ_UNREAD, inserted.getReadStatus());
|
||||||
|
assertEquals(inserted.getIdempotentKey(), inserted.getActiveIdempotentKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createTask_shouldReturnExistingTask() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
SysTodoTask existing = new SysTodoTask();
|
||||||
|
existing.setTodoId(12L);
|
||||||
|
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(existing);
|
||||||
|
|
||||||
|
SysTodoTask result = service.createTask(createCommand());
|
||||||
|
|
||||||
|
assertSame(existing, result);
|
||||||
|
verify(mapper, never()).insertTodoTask(any(SysTodoTask.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createTask_shouldRecoverFromConcurrentDuplicate() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
SysTodoTask existing = new SysTodoTask();
|
||||||
|
existing.setTodoId(13L);
|
||||||
|
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(null, existing);
|
||||||
|
doThrow(new DuplicateKeyException("duplicate"))
|
||||||
|
.when(mapper).insertTodoTask(any(SysTodoTask.class));
|
||||||
|
|
||||||
|
SysTodoTask result = service.createTask(createCommand());
|
||||||
|
|
||||||
|
assertSame(existing, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listForAssignee_shouldOverrideRequestedUser() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
TodoTaskQuery query = new TodoTaskQuery();
|
||||||
|
query.setAssigneeUserId(999L);
|
||||||
|
when(mapper.selectTodoList(query)).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
service.listForAssignee(query, 8L);
|
||||||
|
|
||||||
|
assertEquals(8L, query.getAssigneeUserId());
|
||||||
|
verify(mapper).selectTodoList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void complete_shouldBeIdempotentWhenAlreadyCompleted() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
SysTodoTask completed = new SysTodoTask();
|
||||||
|
completed.setTaskStatus(TodoTaskConstants.STATUS_COMPLETED);
|
||||||
|
when(mapper.completeTodoForAssignee(20L, 8L, 8L, "tester")).thenReturn(0);
|
||||||
|
when(mapper.selectTodoByIdForAssignee(20L, 8L)).thenReturn(completed);
|
||||||
|
|
||||||
|
assertTrue(service.complete(20L, 8L, "tester"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void complete_shouldRejectCancelledTask() {
|
||||||
|
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
|
||||||
|
TodoTaskServiceImpl service = newService(mapper);
|
||||||
|
SysTodoTask cancelled = new SysTodoTask();
|
||||||
|
cancelled.setTaskStatus(TodoTaskConstants.STATUS_CANCELLED);
|
||||||
|
when(mapper.completeTodoForAssignee(20L, 8L, 8L, "tester")).thenReturn(0);
|
||||||
|
when(mapper.selectTodoByIdForAssignee(20L, 8L)).thenReturn(cancelled);
|
||||||
|
|
||||||
|
assertThrows(ServiceException.class, () -> service.complete(20L, 8L, "tester"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TodoTaskCreateCommand createCommand() {
|
||||||
|
return TodoTaskCreateCommand.builder()
|
||||||
|
.taskType("INVOICE_REVIEW")
|
||||||
|
.title("司机开票申请")
|
||||||
|
.businessType("INVOICE_APPLY")
|
||||||
|
.businessId("100")
|
||||||
|
.routeName("InvoiceApplyDetail")
|
||||||
|
.assigneeUserId(8L)
|
||||||
|
.idempotentKey("INVOICE:100:8")
|
||||||
|
.createBy("tester")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TodoTaskServiceImpl newService(SysTodoTaskMapper mapper) {
|
||||||
|
TodoTaskServiceImpl service = new TodoTaskServiceImpl();
|
||||||
|
setField(service, "todoTaskMapper", mapper);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setField(Object target, String fieldName, Object value) {
|
||||||
|
try {
|
||||||
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(target, value);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package com.jsowell.web.controller.system;
|
||||||
|
|
||||||
|
import com.jsowell.common.core.domain.AjaxResult;
|
||||||
|
import com.jsowell.system.domain.SysTodoTask;
|
||||||
|
import com.jsowell.system.service.TodoTaskService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
class SysTodoTaskControllerTest {
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
void unreadCount_shouldUseCurrentLoginUser() {
|
||||||
|
TodoTaskService service = mock(TodoTaskService.class);
|
||||||
|
TestController controller = newController(service, 8L, "tester");
|
||||||
|
when(service.countActive(8L)).thenReturn(5);
|
||||||
|
when(service.countUnread(8L)).thenReturn(3);
|
||||||
|
|
||||||
|
AjaxResult result = controller.unreadCount();
|
||||||
|
|
||||||
|
Map<String, Integer> data = (Map<String, Integer>) result.get(AjaxResult.DATA_TAG);
|
||||||
|
assertEquals(5, data.get("activeCount"));
|
||||||
|
assertEquals(3, data.get("unreadCount"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getInfo_shouldNotAcceptAnotherAssignee() {
|
||||||
|
TodoTaskService service = mock(TodoTaskService.class);
|
||||||
|
TestController controller = newController(service, 8L, "tester");
|
||||||
|
SysTodoTask task = new SysTodoTask();
|
||||||
|
task.setTodoId(20L);
|
||||||
|
when(service.getForAssignee(20L, 8L)).thenReturn(task);
|
||||||
|
|
||||||
|
AjaxResult result = controller.getInfo(20L);
|
||||||
|
|
||||||
|
assertSame(task, result.get(AjaxResult.DATA_TAG));
|
||||||
|
verify(service).getForAssignee(20L, 8L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void complete_shouldPassCurrentUserAndOperator() {
|
||||||
|
TodoTaskService service = mock(TodoTaskService.class);
|
||||||
|
TestController controller = newController(service, 8L, "tester");
|
||||||
|
when(service.complete(20L, 8L, "tester")).thenReturn(true);
|
||||||
|
|
||||||
|
controller.complete(20L);
|
||||||
|
|
||||||
|
verify(service).complete(20L, 8L, "tester");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TestController newController(TodoTaskService service, Long userId, String username) {
|
||||||
|
TestController controller = new TestController(userId, username);
|
||||||
|
setField(controller, "todoTaskService", service);
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setField(Object target, String fieldName, Object value) {
|
||||||
|
try {
|
||||||
|
Field field = SysTodoTaskController.class.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(target, value);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestController extends SysTodoTaskController {
|
||||||
|
private final Long userId;
|
||||||
|
private final String username;
|
||||||
|
|
||||||
|
private TestController(Long userId, String username) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.jsowell.system.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消待办请求。
|
||||||
|
*
|
||||||
|
* @author jsowell
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TodoTaskCancelRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "取消原因不能为空")
|
||||||
|
@Size(max = 500, message = "取消原因不能超过500个字符")
|
||||||
|
private String reason;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user