diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java b/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java
index ad2d290..6d8c419 100644
--- a/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java
+++ b/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java
@@ -14,8 +14,8 @@ public class NewCodeGet {
// 作者名称
public static final String author = "Bunny";
// 公共路径
- public static final String outputDir = "D:\\MyFolder\\auth-admin\\auth-server-java\\service";
- // public static final String outputDir = "D:\\Project\\web\\PC\\auth\\auth-server\\services";
+ // public static final String outputDir = "D:\\MyFolder\\auth-admin\\auth-server-java\\service";
+ public static final String outputDir = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service";
// 实体类名称
public static final String entity = "Bunny";
diff --git a/dao/src/main/java/cn/bunny/dao/dto/router/RouterManageDto.java b/dao/src/main/java/cn/bunny/dao/dto/router/RouterManageDto.java
new file mode 100644
index 0000000..1a2683f
--- /dev/null
+++ b/dao/src/main/java/cn/bunny/dao/dto/router/RouterManageDto.java
@@ -0,0 +1,21 @@
+package cn.bunny.dao.dto.router;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Schema(name = "RouterManageDto对象", title = "路由查询表单", description = "路由查询表单")
+public class RouterManageDto {
+
+ @Schema(name = "title", title = "路由标题")
+ private String title;
+
+ @Schema(name = "visible", title = "是否显示")
+ private Boolean visible;
+}
diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Router.java b/dao/src/main/java/cn/bunny/dao/entity/system/Router.java
index a8f0076..f3b4b54 100644
--- a/dao/src/main/java/cn/bunny/dao/entity/system/Router.java
+++ b/dao/src/main/java/cn/bunny/dao/entity/system/Router.java
@@ -1,11 +1,7 @@
package cn.bunny.dao.entity.system;
import cn.bunny.dao.entity.BaseEntity;
-import com.alibaba.fastjson2.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
@@ -14,17 +10,17 @@ import lombok.experimental.Accessors;
/**
*
- *
+ * 系统菜单表
*
*
* @author Bunny
- * @since 2024-09-27
+ * @since 2024-09-28
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("sys_router")
-@ApiModel(value = "Router对象", description = "系统路由表")
+@ApiModel(value = "Router对象", description = "系统菜单表")
public class Router extends BaseEntity {
@ApiModelProperty("在项目中路径")
@@ -34,21 +30,26 @@ public class Router extends BaseEntity {
private String routeName;
@ApiModelProperty("父级id")
- @JsonProperty("parentId")
- @JsonFormat(shape = JsonFormat.Shape.STRING)
- @JSONField(serializeUsing = ToStringSerializer.class)
private Long parentId;
+ @ApiModelProperty("菜单类型 (`0`代表菜单、`1`代表`iframe`、`2`代表外链、`3`代表按钮)")
+ private Integer menuType;
+
@ApiModelProperty("路由title")
private String title;
@ApiModelProperty("图标")
private String icon;
+ @ApiModelProperty("进入动画")
+ private String enterTransition;
+
+ @ApiModelProperty("退出动画")
+ private String leaveTransition;
+
@ApiModelProperty("等级")
private Integer routerRank;
@ApiModelProperty("是否显示")
private Boolean visible;
-
}
diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java b/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java
index edc8fd8..a810c2e 100644
--- a/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java
+++ b/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java
@@ -17,11 +17,11 @@ import java.util.List;
@Builder
public class PageResult implements Serializable {
// 当前页
- private Integer pageNo;
+ private Long pageNo;
// 每页记录数
- private Integer pageSize;
+ private Long pageSize;
// 总记录数
- private long total;
+ private Long total;
// 当前页数据集合
private List list;
}
\ No newline at end of file
diff --git a/dao/src/main/java/cn/bunny/dao/vo/router/RouterControllerVo.java b/dao/src/main/java/cn/bunny/dao/vo/router/RouterControllerVo.java
deleted file mode 100644
index e69a40c..0000000
--- a/dao/src/main/java/cn/bunny/dao/vo/router/RouterControllerVo.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package cn.bunny.dao.vo.router;
-
-import cn.bunny.dao.vo.BaseVo;
-import com.alibaba.fastjson2.annotation.JSONField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.*;
-
-import java.util.List;
-
-@EqualsAndHashCode(callSuper = true)
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@Builder
-@ApiModel(value = "RouterControllerVo对象", description = "路由管理端返回对象")
-public class RouterControllerVo extends BaseVo {
-
- @ApiModelProperty("在项目中路径")
- private String path;
-
- @ApiModelProperty("路由名称")
- private String routeName;
-
- @ApiModelProperty("父级id")
- @JsonFormat(shape = JsonFormat.Shape.STRING)
- @JSONField(serializeUsing = ToStringSerializer.class)
- private Long parentId;
-
- @ApiModelProperty("title名称")
- private String title;
-
- @ApiModelProperty("图标")
- private String icon;
-
- @ApiModelProperty("等级")
- private Integer routerRank;
-
- @ApiModelProperty("是否显示")
- private Boolean visible;
-
- @ApiModelProperty("子路由")
- private List children;
-}
diff --git a/dao/src/main/java/cn/bunny/dao/vo/router/RouterMeta.java b/dao/src/main/java/cn/bunny/dao/vo/router/RouterMeta.java
index 2dbd2d5..63bfd66 100644
--- a/dao/src/main/java/cn/bunny/dao/vo/router/RouterMeta.java
+++ b/dao/src/main/java/cn/bunny/dao/vo/router/RouterMeta.java
@@ -30,4 +30,7 @@ public class RouterMeta {
@ApiModelProperty(value = "权限列表")
private List auths;
+
+ @ApiModelProperty("路由动画")
+ private RouterTransition transition;
}
diff --git a/dao/src/main/java/cn/bunny/dao/vo/router/RouterTransition.java b/dao/src/main/java/cn/bunny/dao/vo/router/RouterTransition.java
new file mode 100644
index 0000000..5edba9e
--- /dev/null
+++ b/dao/src/main/java/cn/bunny/dao/vo/router/RouterTransition.java
@@ -0,0 +1,21 @@
+package cn.bunny.dao.vo.router;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "RouterTransition对象", description = "路由动画")
+public class RouterTransition {
+ @ApiModelProperty("进入动画")
+ private String enterTransition;
+
+ @ApiModelProperty("退出动画")
+ private String leaveTransition;
+}
diff --git a/dao/src/main/java/cn/bunny/dao/vo/router/UserRouterVo.java b/dao/src/main/java/cn/bunny/dao/vo/router/UserRouterVo.java
index 638fb32..72be190 100644
--- a/dao/src/main/java/cn/bunny/dao/vo/router/UserRouterVo.java
+++ b/dao/src/main/java/cn/bunny/dao/vo/router/UserRouterVo.java
@@ -35,10 +35,16 @@ public class UserRouterVo {
@ApiModelProperty("在项目中路径")
private String path;
+ @ApiModelProperty("菜单类型")
+ private Integer menuType;
+
@ApiModelProperty("路由名称")
@JsonProperty("name")
private String routeName;
+ @ApiModelProperty("路由动画")
+ private RouterTransition transition;
+
@ApiModelProperty("meta内容")
private RouterMeta meta;
diff --git a/service/src/main/java/cn/bunny/services/controller/RouterController.java b/service/src/main/java/cn/bunny/services/controller/RouterController.java
index d0f9fe8..135fafc 100644
--- a/service/src/main/java/cn/bunny/services/controller/RouterController.java
+++ b/service/src/main/java/cn/bunny/services/controller/RouterController.java
@@ -1,14 +1,22 @@
package cn.bunny.services.controller;
+import cn.bunny.dao.dto.router.RouterManageDto;
+import cn.bunny.dao.entity.system.Router;
+import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.pojo.result.Result;
+import cn.bunny.dao.vo.router.RouterManageVo;
import cn.bunny.dao.vo.router.UserRouterVo;
import cn.bunny.services.service.RouterService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
import java.util.List;
@@ -30,8 +38,30 @@ public class RouterController {
@Operation(summary = "获取用户菜单", description = "获取用户菜单")
@GetMapping("getRouterAsync")
- public Result> getRouterAsync() {
+ public Mono>> getRouterAsync() {
List voList = routerService.getRouterAsync();
- return Result.success(voList);
+ return Mono.just(Result.success(voList));
+ }
+
+ @Operation(summary = "分页管理菜单列表", description = "分页管理菜单列表")
+ @GetMapping("getMenusByPage/{page}/{limit}")
+ public Mono>> getMenusByPage(
+ @Parameter(name = "page", description = "当前页", required = true)
+ @PathVariable("page") Integer page,
+ @Parameter(name = "limit", description = "每页记录数", required = true)
+ @PathVariable("limit") Integer limit,
+ RouterManageDto dto) {
+ Page pageParams = new Page<>(page, limit);
+ PageResult voPageResult = routerService.getMenusByPage(pageParams, dto);
+
+ return Mono.just(Result.success(voPageResult));
+ }
+
+ @Operation(summary = "管理菜单列表", description = "管理菜单列表")
+ @GetMapping("getMenus")
+ public Mono>> getMenu(RouterManageDto dto) {
+ List voPageResult = routerService.getMenu(dto);
+
+ return Mono.just(Result.success(voPageResult));
}
}
diff --git a/service/src/main/java/cn/bunny/services/controller/UserController.java b/service/src/main/java/cn/bunny/services/controller/UserController.java
index 5f64f60..e9d4e93 100644
--- a/service/src/main/java/cn/bunny/services/controller/UserController.java
+++ b/service/src/main/java/cn/bunny/services/controller/UserController.java
@@ -38,9 +38,9 @@ public class UserController {
}
@Operation(summary = "退出登录", description = "退出登录")
- @PostMapping("logOut")
- public Result logOut() {
- userService.logOut();
+ @PostMapping("logout")
+ public Result logout() {
+ userService.logout();
return Result.success(ResultCodeEnum.LOGOUT_SUCCESS);
}
}
\ No newline at end of file
diff --git a/service/src/main/java/cn/bunny/services/mapper/RouterMapper.java b/service/src/main/java/cn/bunny/services/mapper/RouterMapper.java
index 0776098..b55d627 100644
--- a/service/src/main/java/cn/bunny/services/mapper/RouterMapper.java
+++ b/service/src/main/java/cn/bunny/services/mapper/RouterMapper.java
@@ -1,8 +1,13 @@
package cn.bunny.services.mapper;
+
+import cn.bunny.dao.dto.router.RouterManageDto;
import cn.bunny.dao.entity.system.Router;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -32,4 +37,13 @@ public interface RouterMapper extends BaseMapper {
* @return 路由列表
*/
List selectParentListByRouterId(List ids);
+
+ /**
+ * * 管理菜单列表
+ *
+ * @param pageParams 分页想去
+ * @param dto 路由查询表单
+ * @return 分页结果
+ */
+ IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") RouterManageDto dto);
}
diff --git a/service/src/main/java/cn/bunny/services/security/service/iml/CustomAuthorizationManagerServiceImpl.java b/service/src/main/java/cn/bunny/services/security/service/iml/CustomAuthorizationManagerServiceImpl.java
index 1fff064..cb8e63a 100644
--- a/service/src/main/java/cn/bunny/services/security/service/iml/CustomAuthorizationManagerServiceImpl.java
+++ b/service/src/main/java/cn/bunny/services/security/service/iml/CustomAuthorizationManagerServiceImpl.java
@@ -6,6 +6,8 @@ import cn.bunny.dao.entity.system.Power;
import cn.bunny.services.mapper.PowerMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
@@ -24,9 +26,11 @@ import java.util.function.Supplier;
@Component
@Slf4j
public class CustomAuthorizationManagerServiceImpl implements AuthorizationManager {
- private final PowerMapper powerMapper;
+ @Autowired
+ private RedisTemplate redisTemplate;
+ @Autowired
+ private PowerMapper powerMapper;
- public CustomAuthorizationManagerServiceImpl(PowerMapper powerMapper) {this.powerMapper = powerMapper;}
@Override
public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext context) {
@@ -47,16 +51,18 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
List roleCodeList = authentication.get().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();
// 校验权限
- return new AuthorizationDecision(hasAuth(requestURI, roleCodeList));
+ return new AuthorizationDecision(hasAuth(requestURI));
}
/**
* 查询用户所属的角色信息
*
- * @param requestURI 请求url地址
- * @param roleCodeList 角色列表
+ * @param requestURI 请求url地址
*/
- private Boolean hasAuth(String requestURI, List roleCodeList) {
+ private Boolean hasAuth(String requestURI) {
+ // 角色代码列表
+ List roleCodeList = BaseContext.getLoginVo().getRoles();
+
// 判断是否是 admin
boolean isAdmin = roleCodeList.stream().anyMatch(role -> role.equals("admin"));
if (isAdmin) return true;
diff --git a/service/src/main/java/cn/bunny/services/service/RouterService.java b/service/src/main/java/cn/bunny/services/service/RouterService.java
index 1f53e4f..b0e0cd0 100644
--- a/service/src/main/java/cn/bunny/services/service/RouterService.java
+++ b/service/src/main/java/cn/bunny/services/service/RouterService.java
@@ -1,7 +1,11 @@
package cn.bunny.services.service;
+import cn.bunny.dao.dto.router.RouterManageDto;
import cn.bunny.dao.entity.system.Router;
+import cn.bunny.dao.pojo.result.PageResult;
+import cn.bunny.dao.vo.router.RouterManageVo;
import cn.bunny.dao.vo.router.UserRouterVo;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@@ -21,4 +25,21 @@ public interface RouterService extends IService {
* @return 路遇列表
*/
List getRouterAsync();
+
+ /**
+ * * 管理菜单列表
+ *
+ * @param pageParams 分页想去
+ * @param dto 路由查询表单
+ * @return 系统菜单表分页
+ */
+ PageResult getMenusByPage(Page pageParams, RouterManageDto dto);
+
+ /**
+ * * 管理菜单列表
+ *
+ * @param dto 路由查询表单
+ * @return 系统菜单表
+ */
+ List getMenu(RouterManageDto dto);
}
diff --git a/service/src/main/java/cn/bunny/services/service/UserService.java b/service/src/main/java/cn/bunny/services/service/UserService.java
index bb52740..6996133 100644
--- a/service/src/main/java/cn/bunny/services/service/UserService.java
+++ b/service/src/main/java/cn/bunny/services/service/UserService.java
@@ -35,5 +35,5 @@ public interface UserService extends IService {
/**
* * 退出登录
*/
- void logOut();
+ void logout();
}
diff --git a/service/src/main/java/cn/bunny/services/service/impl/RouterServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/RouterServiceImpl.java
index c8db3ba..d66bcf6 100644
--- a/service/src/main/java/cn/bunny/services/service/impl/RouterServiceImpl.java
+++ b/service/src/main/java/cn/bunny/services/service/impl/RouterServiceImpl.java
@@ -2,15 +2,21 @@ package cn.bunny.services.service.impl;
import cn.bunny.common.service.context.BaseContext;
import cn.bunny.common.service.exception.BunnyException;
+import cn.bunny.dao.dto.router.RouterManageDto;
import cn.bunny.dao.entity.system.Router;
import cn.bunny.dao.pojo.constant.RedisUserConstant;
+import cn.bunny.dao.pojo.result.PageResult;
import cn.bunny.dao.pojo.result.ResultCodeEnum;
+import cn.bunny.dao.vo.router.RouterManageVo;
import cn.bunny.dao.vo.router.RouterMeta;
import cn.bunny.dao.vo.router.UserRouterVo;
import cn.bunny.dao.vo.user.LoginVo;
import cn.bunny.services.mapper.RouterMapper;
import cn.bunny.services.service.RouterService;
import cn.bunny.services.service.process.RouterServiceProcess;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,9 +69,8 @@ public class RouterServiceImpl extends ServiceImpl impleme
// 查询用户角色,判断是否是管理员角色
boolean isAdmin = roleList.stream().anyMatch(authUserRole -> authUserRole.equals("admin"));
- if (isAdmin) {
- routerList = list();
- } else {
+ if (isAdmin) routerList = list();
+ else {
List routerIds = baseMapper.selectListByUserId(loginVo.getId());
routerList = baseMapper.selectParentListByRouterId(routerIds);
}
@@ -100,4 +105,54 @@ public class RouterServiceImpl extends ServiceImpl impleme
return list;
}
+
+ /**
+ * * 管理菜单列表
+ *
+ * @param pageParams 分页想去
+ * @param dto 路由查询表单
+ * @return 系统菜单表分页
+ */
+ @Override
+ public PageResult getMenusByPage(Page pageParams, RouterManageDto dto) {
+ IPage page = baseMapper.selectListByPage(pageParams, dto);
+
+ // 构建返回对象
+ List voList = page.getRecords().stream().map(router -> {
+ RouterManageVo routerManageVo = new RouterManageVo();
+ BeanUtils.copyProperties(router, routerManageVo);
+ return routerManageVo;
+ }).toList();
+
+ return PageResult.builder()
+ .list(voList)
+ .pageNo(page.getCurrent())
+ .pageSize(page.getSize())
+ .total(page.getTotal())
+ .build();
+ }
+
+ /**
+ * * 管理菜单列表
+ *
+ * @param dto 路由查询表单
+ * @return 系统菜单表
+ */
+ @Override
+ public List getMenu(RouterManageDto dto) {
+ String title = dto.getTitle();
+ Boolean visible = dto.getVisible();
+
+ // 构建查询条件
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ lambdaQueryWrapper.like(title != null, Router::getTitle, title)
+ .or()
+ .eq(visible != null, Router::getVisible, visible);
+
+ return list().stream().map(router -> {
+ RouterManageVo routerManageVo = new RouterManageVo();
+ BeanUtils.copyProperties(router, routerManageVo);
+ return routerManageVo;
+ }).toList();
+ }
}
diff --git a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java
index 2916352..bf27843 100644
--- a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java
+++ b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java
@@ -93,7 +93,7 @@ public class UserServiceImpl extends ServiceImpl implemen
* 退出登录
*/
@Override
- public void logOut() {
+ public void logout() {
LoginVo loginVo = BaseContext.getLoginVo();
redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(loginVo.getUsername()));
}
diff --git a/service/src/main/java/cn/bunny/services/service/process/RouterServiceProcess.java b/service/src/main/java/cn/bunny/services/service/process/RouterServiceProcess.java
index 813f8ed..f894375 100644
--- a/service/src/main/java/cn/bunny/services/service/process/RouterServiceProcess.java
+++ b/service/src/main/java/cn/bunny/services/service/process/RouterServiceProcess.java
@@ -1,7 +1,7 @@
package cn.bunny.services.service.process;
import cn.bunny.dao.vo.common.TreeSelectVo;
-import cn.bunny.dao.vo.router.RouterControllerVo;
+import cn.bunny.dao.vo.router.RouterManageVo;
import cn.bunny.dao.vo.router.UserRouterVo;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
@@ -38,7 +38,7 @@ public class RouterServiceProcess {
* @param nodeList 返回VO列表
* @return 返回路由列表
*/
- public List handleGetChildrenWithRouterControllerVo(Long nodeId, List nodeList) {
+ public List handleGetChildrenWithRouterControllerVo(Long nodeId, List nodeList) {
return nodeList.stream()
.filter(node -> node.getParentId().equals(nodeId))
.peek(node -> node.setChildren(handleGetChildrenWithRouterControllerVo(node.getId(), nodeList)))
diff --git a/service/src/main/resources/mapper/RouterMapper.xml b/service/src/main/resources/mapper/RouterMapper.xml
deleted file mode 100644
index 145e26f..0000000
--- a/service/src/main/resources/mapper/RouterMapper.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- id, path, route_name, parent_id, title, icon, router_rank, visible, create_user, update_user, update_time, create_time, is_deleted
-
-
-
-
-
-
-