feat: 多组织功能 - 实体/Service/Controller/拦截器/租户隔离

This commit is contained in:
OpenCode
2026-07-24 09:31:21 +08:00
parent 80dc8a0c07
commit 87b743ae11
44 changed files with 1364 additions and 2 deletions
@@ -1,5 +1,6 @@
package com.cool.core.request;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
@@ -81,7 +82,17 @@ public class RequestParamsFilter implements Filter {
}
}
// app端,userId 为当前登录的用户id
case APP -> requestParams.set("userId", CoolSecurityUtil.getCurrentUserId());
case APP -> {
requestParams.set("userId", CoolSecurityUtil.getCurrentUserId());
// App端:从tokenInfo中读取orgId作为tenantId,实现组织级数据隔离
Object jwtObj = requestParams.get("tokenInfo");
if (jwtObj instanceof Map) {
Object orgId = ((Map<?, ?>) jwtObj).get("orgId");
if (ObjUtil.isNotNull(orgId)) {
requestParams.set("tenantId", Convert.toLong(orgId));
}
}
}
}
return CoolSecurityUtil.getTenantId(requestParams);
}
@@ -0,0 +1,92 @@
package com.cool.core.security;
import cn.hutool.core.util.StrUtil;
import com.cool.core.exception.CoolException;
import com.cool.core.util.CoolSecurityUtil;
import com.cool.modules.org.entity.AppOrgEntity;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import com.cool.modules.org.entity.AppOrgUserEntity;
import com.cool.modules.org.service.AppOrgModuleService;
import com.cool.modules.org.service.AppOrgUserService;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
@Component
@Order(3)
@RequiredArgsConstructor
public class AppOrgAuthFilter extends OncePerRequestFilter {
private final AppOrgUserService appOrgUserService;
private final AppOrgModuleService appOrgModuleService;
private static final Map<String, String> MODULE_PATH_MAP = Map.of(
"/app/fruit/", "fruit",
"/app/zoo/", "zoo",
"/app/order/", "order",
"/app/book/", "book",
"/app/ticket/", "ticket"
);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String uri = request.getRequestURI();
if (!uri.startsWith("/app/") || uri.startsWith("/app/org/") || uri.startsWith("/app/user/") || uri.startsWith("/app/base/") || uri.startsWith("/app/dict/")) {
chain.doFilter(request, response);
return;
}
if (com.cool.core.enums.UserTypeEnum.APP != CoolSecurityUtil.getCurrentUserType()) {
chain.doFilter(request, response);
return;
}
String moduleKey = resolveModuleKey(uri);
if (moduleKey == null) {
chain.doFilter(request, response);
return;
}
Long userId = CoolSecurityUtil.getCurrentUserId();
String orgIdStr = request.getHeader("X-Org-Id");
if (StrUtil.isBlank(orgIdStr)) {
throw new CoolException("缺少组织信息", 403);
}
Long orgId;
try {
orgId = Long.parseLong(orgIdStr);
} catch (NumberFormatException e) {
throw new CoolException("无效的组织ID", 403);
}
if (!appOrgUserService.isOrgMember(userId, orgId)) {
throw new CoolException("未加入该组织", 403);
}
if (!appOrgModuleService.isModuleAuthorized(orgId, moduleKey)) {
throw new CoolException("该组织未授权此模块", 403);
}
chain.doFilter(request, response);
}
private String resolveModuleKey(String uri) {
for (Map.Entry<String, String> entry : MODULE_PATH_MAP.entrySet()) {
if (uri.startsWith(entry.getKey())) {
return entry.getValue();
}
}
return null;
}
}
@@ -43,6 +43,7 @@ public class JwtSecurityConfig {
// 用户详情
final private UserDetailsService userDetailsService;
final private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
final private AppOrgAuthFilter appOrgAuthFilter;
// 401
final private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler;
// 403
@@ -72,6 +73,8 @@ public class JwtSecurityConfig {
.sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtAuthenticationTokenFilter,
UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(appOrgAuthFilter,
JwtAuthenticationTokenFilter.class)
.exceptionHandling(config -> {
config.authenticationEntryPoint(entryPointUnauthorizedHandler);
config.accessDeniedHandler(restAccessDeniedHandler);
@@ -0,0 +1,22 @@
package com.cool.modules.fruit.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.modules.fruit.entity.FruitGoodsEntity;
import com.cool.modules.fruit.service.FruitGoodsService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "水果管理", description = "水果商品管理")
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
public class AdminFruitGoodsController extends BaseController<FruitGoodsService, FruitGoodsEntity> {
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
}
@@ -0,0 +1,34 @@
package com.cool.modules.fruit.controller.app;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.request.R;
import com.cool.core.util.CoolSecurityUtil;
import com.cool.modules.fruit.entity.FruitGoodsEntity;
import com.cool.modules.fruit.service.FruitGoodsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "水果", description = "App端水果")
@CoolRestController
public class AppFruitGoodsController {
private final FruitGoodsService fruitGoodsService;
@Operation(summary = "水果列表")
@GetMapping("/list")
public R list(@RequestAttribute JSONObject requestParams) {
return R.ok(fruitGoodsService.list(requestParams, null));
}
@Operation(summary = "水果详情")
@GetMapping("/detail")
public R detail(@RequestAttribute JSONObject requestParams) {
Long id = requestParams.getLong("id");
return R.ok(fruitGoodsService.info(id));
}
}
@@ -0,0 +1,34 @@
package com.cool.modules.fruit.entity;
import com.cool.core.base.TenantEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Table(value = "fruit_goods", comment = "水果商品表")
public class FruitGoodsEntity extends TenantEntity<FruitGoodsEntity> {
@ColumnDefine(comment = "商品名称", notNull = true)
private String name;
@ColumnDefine(comment = "价格")
private Double price;
@ColumnDefine(comment = "单位")
private String unit;
@ColumnDefine(comment = "图片")
private String image;
@ColumnDefine(comment = "描述", type = "text")
private String description;
@ColumnDefine(comment = "分类ID", type = "bigint")
private Long categoryId;
@ColumnDefine(comment = "状态 0:下架 1:上架", defaultValue = "1")
private Integer status;
}
@@ -0,0 +1,7 @@
package com.cool.modules.fruit.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.fruit.entity.FruitGoodsEntity;
public interface FruitGoodsMapper extends BaseMapper<FruitGoodsEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.fruit.service;
import com.cool.core.base.BaseService;
import com.cool.modules.fruit.entity.FruitGoodsEntity;
public interface FruitGoodsService extends BaseService<FruitGoodsEntity> {
}
@@ -0,0 +1,12 @@
package com.cool.modules.fruit.service.impl;
import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.fruit.entity.FruitGoodsEntity;
import com.cool.modules.fruit.mapper.FruitGoodsMapper;
import com.cool.modules.fruit.service.FruitGoodsService;
import org.springframework.stereotype.Service;
@Service
public class FruitGoodsServiceImpl extends BaseServiceImpl<FruitGoodsMapper, FruitGoodsEntity> implements
FruitGoodsService {
}
@@ -0,0 +1,22 @@
package com.cool.modules.order.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.modules.order.entity.OrderInfoEntity;
import com.cool.modules.order.service.OrderInfoService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "订单管理", description = "订单信息管理")
@CoolRestController(api = {"delete", "update", "page", "info"}, cname = "orderInfo")
public class AdminOrderInfoController extends BaseController<OrderInfoService, OrderInfoEntity> {
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
}
@@ -0,0 +1,33 @@
package com.cool.modules.order.controller.app;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.request.R;
import com.cool.modules.order.entity.OrderInfoEntity;
import com.cool.modules.order.service.OrderInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "订单", description = "App端订单")
@CoolRestController
public class AppOrderInfoController {
private final OrderInfoService orderInfoService;
@Operation(summary = "订单列表")
@GetMapping("/list")
public R list(@RequestAttribute JSONObject requestParams) {
return R.ok(orderInfoService.list(requestParams, null));
}
@Operation(summary = "订单详情")
@GetMapping("/detail")
public R detail(@RequestAttribute JSONObject requestParams) {
Long id = requestParams.getLong("id");
return R.ok(orderInfoService.info(id));
}
}
@@ -0,0 +1,29 @@
package com.cool.modules.order.entity;
import com.cool.core.base.TenantEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
@Getter
@Setter
@Table(value = "order_info", comment = "订单信息表")
public class OrderInfoEntity extends TenantEntity<OrderInfoEntity> {
@ColumnDefine(comment = "订单号", notNull = true)
private String orderNo;
@ColumnDefine(comment = "用户ID", type = "bigint")
private Long userId;
@ColumnDefine(comment = "订单金额")
private BigDecimal amount;
@ColumnDefine(comment = "状态 0:待支付 1:已支付 2:已完成 3:已取消", defaultValue = "0")
private Integer status;
@ColumnDefine(comment = "备注", type = "text")
private String remark;
}
@@ -0,0 +1,7 @@
package com.cool.modules.order.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.order.entity.OrderInfoEntity;
public interface OrderInfoMapper extends BaseMapper<OrderInfoEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.order.service;
import com.cool.core.base.BaseService;
import com.cool.modules.order.entity.OrderInfoEntity;
public interface OrderInfoService extends BaseService<OrderInfoEntity> {
}
@@ -0,0 +1,12 @@
package com.cool.modules.order.service.impl;
import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.order.entity.OrderInfoEntity;
import com.cool.modules.order.mapper.OrderInfoMapper;
import com.cool.modules.order.service.OrderInfoService;
import org.springframework.stereotype.Service;
@Service
public class OrderInfoServiceImpl extends BaseServiceImpl<OrderInfoMapper, OrderInfoEntity> implements
OrderInfoService {
}
@@ -0,0 +1,23 @@
package com.cool.modules.org.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.core.request.R;
import com.cool.modules.org.entity.AppModuleEntity;
import com.cool.modules.org.service.AppModuleService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "模块市场", description = "功能模块管理")
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
public class AdminAppModuleController extends BaseController<AppModuleService, AppModuleEntity> {
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
}
@@ -0,0 +1,54 @@
package com.cool.modules.org.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.core.request.R;
import com.cool.modules.org.entity.AppOrgEntity;
import com.cool.modules.org.service.AppOrgService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@RequiredArgsConstructor
@Tag(name = "组织管理", description = "组织管理")
@CoolRestController(api = {"delete", "update", "page", "info"}, cname = "org")
public class AdminAppOrgController extends BaseController<AppOrgService, AppOrgEntity> {
private final AppOrgService appOrgService;
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
@Operation(summary = "创建组织")
@PostMapping("/add")
public R add(@RequestBody JSONObject requestParams) {
AppOrgEntity entity = requestParams.toBean(AppOrgEntity.class);
appOrgService.createOrg(requestParams, entity);
return R.ok();
}
@Operation(summary = "授权模块")
@PostMapping("/authorizeModules")
public R authorizeModules(@RequestBody JSONObject requestParams) {
Long orgId = requestParams.getLong("orgId");
List<String> moduleKeys = requestParams.getBeanList("moduleKeys", String.class);
appOrgService.authorizeModules(orgId, moduleKeys);
return R.ok();
}
@Operation(summary = "切换组织")
@PostMapping("/switch")
public R switchOrg(@RequestBody JSONObject requestParams) {
Long orgId = requestParams.getLong("orgId");
Long userId = com.cool.core.util.CoolSecurityUtil.getCurrentUserId();
appOrgService.switchOrg(userId, orgId, true);
return R.ok();
}
}
@@ -0,0 +1,22 @@
package com.cool.modules.org.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import com.cool.modules.org.service.AppOrgModuleService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "组织模块授权", description = "组织模块授权管理")
@CoolRestController(api = {"add", "delete", "update", "list"}, cname = "orgModule")
public class AdminAppOrgModuleController extends BaseController<AppOrgModuleService, AppOrgModuleEntity> {
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setListOption(createOp());
}
}
@@ -0,0 +1,50 @@
package com.cool.modules.org.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.core.request.R;
import com.cool.modules.org.entity.AppOrgUserEntity;
import com.cool.modules.org.service.AppOrgUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
@RequiredArgsConstructor
@Tag(name = "组织成员管理", description = "组织成员管理")
@CoolRestController(api = {"page", "list", "update", "delete"}, cname = "orgUser")
public class AdminAppOrgUserController extends BaseController<AppOrgUserService, AppOrgUserEntity> {
private final AppOrgUserService appOrgUserService;
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
@Operation(summary = "获取组织成员列表")
@PostMapping("/memberList")
public R memberList(@RequestAttribute JSONObject requestParams) {
Long orgId = requestParams.getLong("orgId");
List<Map<String, Object>> members = appOrgUserService.getMemberListByOrgId(orgId);
return R.ok(members);
}
@Operation(summary = "提升/降级App端管理员")
@PostMapping("/changeRole")
public R changeRole(@RequestBody JSONObject requestParams) {
Long orgUserId = requestParams.getLong("id");
String role = requestParams.getStr("role");
AppOrgUserEntity orgUser = appOrgUserService.getById(orgUserId);
com.cool.core.exception.CoolPreconditions.checkEmpty(orgUser, "记录不存在");
orgUser.setRole(role);
appOrgUserService.update(orgUser);
return R.ok();
}
}
@@ -0,0 +1,70 @@
package com.cool.modules.org.controller.app;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.request.R;
import com.cool.core.util.CoolSecurityUtil;
import com.cool.modules.org.service.AppOrgService;
import com.cool.modules.org.service.AppOrgUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
@RequiredArgsConstructor
@Tag(name = "组织", description = "App端组织管理")
@CoolRestController
public class AppOrgController {
private final AppOrgService appOrgService;
private final AppOrgUserService appOrgUserService;
@Operation(summary = "获取已加入的组织列表")
@GetMapping("/list")
public R list() {
Long userId = CoolSecurityUtil.getCurrentUserId();
List<Map<String, Object>> orgList = appOrgUserService.getOrgListByUserId(userId);
return R.ok(orgList);
}
@Operation(summary = "通过邀请码加入组织")
@PostMapping("/join")
public R join(@RequestBody JSONObject requestParams) {
Long userId = CoolSecurityUtil.getCurrentUserId();
String inviteCode = requestParams.getStr("inviteCode");
appOrgUserService.joinOrg(userId, inviteCode);
return R.ok();
}
@Operation(summary = "通过orgId加入组织")
@PostMapping("/joinById")
public R joinById(@RequestBody JSONObject requestParams) {
Long userId = CoolSecurityUtil.getCurrentUserId();
Long orgId = requestParams.getLong("orgId");
appOrgUserService.joinOrgById(userId, orgId);
return R.ok();
}
@Operation(summary = "退出组织")
@PostMapping("/quit")
public R quit(@RequestBody JSONObject requestParams) {
Long userId = CoolSecurityUtil.getCurrentUserId();
Long orgId = requestParams.getLong("orgId");
appOrgUserService.quitOrg(userId, orgId);
return R.ok();
}
@Operation(summary = "切换组织")
@PostMapping("/switch")
public R switchOrg(@RequestBody JSONObject requestParams) {
Long userId = CoolSecurityUtil.getCurrentUserId();
Long orgId = requestParams.getLong("orgId");
Object result = appOrgService.switchOrg(userId, orgId, false);
return R.ok(result);
}
}
@@ -0,0 +1,44 @@
package com.cool.modules.org.controller.app;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.exception.CoolPreconditions;
import com.cool.core.request.R;
import com.cool.core.util.CoolSecurityUtil;
import com.cool.modules.org.service.AppOrgUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@RequiredArgsConstructor
@Tag(name = "组织成员", description = "App端组织成员管理")
@CoolRestController
public class AppOrgUserController {
private final AppOrgUserService appOrgUserService;
@Operation(summary = "获取组织成员列表")
@PostMapping("/memberList")
public R memberList(@RequestBody JSONObject requestParams) {
Long orgId = requestParams.getLong("orgId");
Long userId = CoolSecurityUtil.getCurrentUserId();
CoolPreconditions.check(!appOrgUserService.isOrgMember(userId, orgId), "无权查看该组织成员");
List<Map<String, Object>> members = appOrgUserService.getMemberListByOrgId(orgId);
return R.ok(members);
}
@Operation(summary = "审批成员加入")
@PostMapping("/approve")
public R approve(@RequestBody JSONObject requestParams) {
Long orgId = requestParams.getLong("orgId");
Long targetUserId = requestParams.getLong("userId");
Boolean approved = requestParams.getBool("approved", true);
Long adminUserId = CoolSecurityUtil.getCurrentUserId();
appOrgUserService.approve(adminUserId, orgId, targetUserId, approved);
return R.ok();
}
}
@@ -0,0 +1,39 @@
package com.cool.modules.org.entity;
import com.cool.core.base.BaseEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Table(value = "app_module", comment = "功能模块注册表")
public class AppModuleEntity extends BaseEntity<AppModuleEntity> {
@UniIndex
@ColumnDefine(comment = "模块标识", notNull = true)
private String moduleKey;
@ColumnDefine(comment = "模块名称", notNull = true)
private String name;
@ColumnDefine(comment = "模块图标")
private String icon;
@ColumnDefine(comment = "模块描述", type = "text")
private String description;
@ColumnDefine(comment = "关联的admin菜单ID列表", type = "text")
private String menuIds;
@ColumnDefine(comment = "关联的App页面路由配置", type = "text")
private String appPages;
@ColumnDefine(comment = "要求的最低App版本号")
private String minAppVersion;
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
private Integer status;
}
@@ -0,0 +1,42 @@
package com.cool.modules.org.entity;
import com.cool.core.base.BaseEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Table(value = "app_org", comment = "组织表")
public class AppOrgEntity extends BaseEntity<AppOrgEntity> {
@ColumnDefine(comment = "组织名称", notNull = true)
private String name;
@ColumnDefine(comment = "组织类型")
private String type;
@ColumnDefine(comment = "组织图标/Logo")
private String icon;
@ColumnDefine(comment = "组织简介", type = "text")
private String description;
@UniIndex
@ColumnDefine(comment = "邀请码")
private String inviteCode;
@ColumnDefine(comment = "加入方式 0:自由加入 1:需审批", defaultValue = "0")
private Integer joinType;
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
private Integer status;
@ColumnDefine(comment = "Admin端组织管理员userId", type = "bigint")
private Long adminUserId;
@ColumnDefine(comment = "组织级扩展配置", type = "text")
private String config;
}
@@ -0,0 +1,29 @@
package com.cool.modules.org.entity;
import com.cool.core.base.BaseEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
import lombok.Getter;
import lombok.Setter;
import org.dromara.autotable.annotation.Index;
@Getter
@Setter
@Table(value = "app_org_module", comment = "组织模块关联表")
public class AppOrgModuleEntity extends BaseEntity<AppOrgModuleEntity> {
@Index
@ColumnDefine(comment = "组织ID", type = "bigint", notNull = true)
private Long orgId;
@Index
@ColumnDefine(comment = "模块标识", notNull = true)
private String moduleKey;
@ColumnDefine(comment = "组织级模块配置", type = "text")
private String config;
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
private Integer status;
}
@@ -0,0 +1,44 @@
package com.cool.modules.org.entity;
import com.cool.core.base.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
import lombok.Getter;
import lombok.Setter;
import org.dromara.autotable.annotation.Index;
import java.util.Date;
@Getter
@Setter
@Table(value = "app_org_user", comment = "组织用户关联表")
public class AppOrgUserEntity extends BaseEntity<AppOrgUserEntity> {
@Index
@ColumnDefine(comment = "组织ID", type = "bigint", notNull = true)
private Long orgId;
@Index
@ColumnDefine(comment = "App用户ID", type = "bigint", notNull = true)
private Long userId;
@ColumnDefine(comment = "角色 member/admin", defaultValue = "member")
private String role;
@ColumnDefine(comment = "状态 0:待审批 1:已加入 2:已拒绝 3:已退出", defaultValue = "0")
private Integer status;
@ColumnDefine(comment = "加入时间")
private Date joinTime;
@Column(ignore = true)
private String orgName;
@Column(ignore = true)
private String nickName;
@Column(ignore = true)
private String avatarUrl;
}
@@ -0,0 +1,7 @@
package com.cool.modules.org.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.org.entity.AppModuleEntity;
public interface AppModuleMapper extends BaseMapper<AppModuleEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.org.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.org.entity.AppOrgEntity;
public interface AppOrgMapper extends BaseMapper<AppOrgEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.org.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.org.entity.AppOrgModuleEntity;
public interface AppOrgModuleMapper extends BaseMapper<AppOrgModuleEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.org.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.org.entity.AppOrgUserEntity;
public interface AppOrgUserMapper extends BaseMapper<AppOrgUserEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.org.service;
import com.cool.core.base.BaseService;
import com.cool.modules.org.entity.AppModuleEntity;
public interface AppModuleService extends BaseService<AppModuleEntity> {
}
@@ -0,0 +1,12 @@
package com.cool.modules.org.service;
import com.cool.core.base.BaseService;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import java.util.List;
public interface AppOrgModuleService extends BaseService<AppOrgModuleEntity> {
List<String> getModuleKeysByOrgId(Long orgId);
boolean isModuleAuthorized(Long orgId, String moduleKey);
}
@@ -0,0 +1,16 @@
package com.cool.modules.org.service;
import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONObject;
import com.cool.core.base.BaseService;
import com.cool.modules.org.entity.AppOrgEntity;
import java.util.List;
public interface AppOrgService extends BaseService<AppOrgEntity> {
void createOrg(JSONObject requestParams, AppOrgEntity entity);
void authorizeModules(Long orgId, List<String> moduleKeys);
Dict switchOrg(Long userId, Long orgId, boolean isAdmin);
}
@@ -0,0 +1,25 @@
package com.cool.modules.org.service;
import com.cool.core.base.BaseService;
import com.cool.modules.org.entity.AppOrgUserEntity;
import java.util.List;
import java.util.Map;
public interface AppOrgUserService extends BaseService<AppOrgUserEntity> {
void joinOrg(Long userId, String inviteCode);
void joinOrgById(Long userId, Long orgId);
void quitOrg(Long userId, Long orgId);
void approve(Long adminUserId, Long orgId, Long targetUserId, boolean approved);
List<Map<String, Object>> getOrgListByUserId(Long userId);
List<Map<String, Object>> getMemberListByOrgId(Long orgId);
boolean isOrgAdmin(Long userId, Long orgId);
boolean isOrgMember(Long userId, Long orgId);
}
@@ -0,0 +1,12 @@
package com.cool.modules.org.service.impl;
import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.org.mapper.AppModuleMapper;
import com.cool.modules.org.entity.AppModuleEntity;
import com.cool.modules.org.service.AppModuleService;
import org.springframework.stereotype.Service;
@Service
public class AppModuleServiceImpl extends BaseServiceImpl<AppModuleMapper, AppModuleEntity> implements
AppModuleService {
}
@@ -0,0 +1,35 @@
package com.cool.modules.org.service.impl;
import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import com.cool.modules.org.mapper.AppOrgModuleMapper;
import com.cool.modules.org.service.AppOrgModuleService;
import com.mybatisflex.core.query.QueryWrapper;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
@Service
public class AppOrgModuleServiceImpl extends BaseServiceImpl<AppOrgModuleMapper, AppOrgModuleEntity> implements
AppOrgModuleService {
@Override
public List<String> getModuleKeysByOrgId(Long orgId) {
List<AppOrgModuleEntity> modules = list(QueryWrapper.create()
.eq(AppOrgModuleEntity::getOrgId, orgId)
.eq(AppOrgModuleEntity::getStatus, 1));
return modules.stream()
.map(AppOrgModuleEntity::getModuleKey)
.collect(Collectors.toList());
}
@Override
public boolean isModuleAuthorized(Long orgId, String moduleKey) {
AppOrgModuleEntity module = getOne(QueryWrapper.create()
.eq(AppOrgModuleEntity::getOrgId, orgId)
.eq(AppOrgModuleEntity::getModuleKey, moduleKey)
.eq(AppOrgModuleEntity::getStatus, 1));
return module != null;
}
}
@@ -0,0 +1,186 @@
package com.cool.modules.org.service.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.cool.core.base.BaseServiceImpl;
import com.cool.core.cache.CoolCache;
import com.cool.core.enums.UserTypeEnum;
import com.cool.core.exception.CoolPreconditions;
import com.cool.core.security.jwt.JwtTokenUtil;
import com.cool.core.security.jwt.JwtUser;
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
import com.cool.modules.base.entity.sys.BaseSysUserRoleEntity;
import com.cool.modules.base.mapper.sys.BaseSysRoleMapper;
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
import com.cool.modules.base.mapper.sys.BaseSysUserRoleMapper;
import com.cool.modules.base.service.sys.BaseSysPermsService;
import com.cool.modules.org.entity.AppModuleEntity;
import com.cool.modules.org.entity.AppOrgEntity;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import com.cool.modules.org.mapper.AppOrgMapper;
import com.cool.modules.org.mapper.AppModuleMapper;
import com.cool.modules.org.service.AppOrgModuleService;
import com.cool.modules.org.service.AppOrgService;
import com.cool.modules.org.service.AppOrgUserService;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.tenant.TenantManager;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class AppOrgServiceImpl extends BaseServiceImpl<AppOrgMapper, AppOrgEntity> implements
AppOrgService {
private final AppModuleMapper appModuleMapper;
private final BaseSysRoleMapper baseSysRoleMapper;
private final BaseSysUserRoleMapper baseSysUserRoleMapper;
private final BaseSysUserMapper baseSysUserMapper;
private final BaseSysPermsService baseSysPermsService;
private final AppOrgModuleService appOrgModuleService;
private final AppOrgUserService appOrgUserService;
private final CoolCache coolCache;
private final JwtTokenUtil jwtTokenUtil;
@Override
@Transactional
public void createOrg(JSONObject requestParams, AppOrgEntity entity) {
entity.setInviteCode(generateInviteCode());
this.add(entity);
Long orgId = entity.getId();
BaseSysRoleEntity role = new BaseSysRoleEntity();
role.setName(entity.getName() + "管理员");
role.setLabel("org_admin_" + orgId);
role.setRemark("组织[" + entity.getName() + "]自动创建的管理角色");
role.setStatus(1);
role.setTenantId(orgId);
TenantManager.withoutTenantCondition(() -> {
baseSysRoleMapper.insertSelective(role);
});
if (entity.getAdminUserId() != null) {
BaseSysUserRoleEntity userRole = new BaseSysUserRoleEntity();
userRole.setUserId(entity.getAdminUserId());
userRole.setRoleId(role.getId());
TenantManager.withoutTenantCondition(() -> {
baseSysUserRoleMapper.insertSelective(userRole);
});
com.cool.modules.base.entity.sys.BaseSysUserEntity adminUser = baseSysUserMapper.selectOneById(entity.getAdminUserId());
if (adminUser != null) {
adminUser.setTenantId(orgId);
TenantManager.withoutTenantCondition(() -> {
baseSysUserMapper.update(adminUser);
});
}
}
if (requestParams != null) {
List<String> moduleKeys = requestParams.getBeanList("moduleKeys", String.class);
if (moduleKeys != null && !moduleKeys.isEmpty()) {
authorizeModules(orgId, moduleKeys);
}
}
}
@Override
@Transactional
public void authorizeModules(Long orgId, List<String> moduleKeys) {
QueryWrapper qw = QueryWrapper.create()
.eq(AppOrgModuleEntity::getOrgId, orgId);
appOrgModuleService.remove(qw);
for (String moduleKey : moduleKeys) {
AppModuleEntity module = appModuleMapper.selectOneByQuery(
QueryWrapper.create().eq(AppModuleEntity::getModuleKey, moduleKey)
);
CoolPreconditions.checkEmpty(module, "模块{}不存在", moduleKey);
AppOrgModuleEntity orgModule = new AppOrgModuleEntity();
orgModule.setOrgId(orgId);
orgModule.setModuleKey(moduleKey);
orgModule.setStatus(1);
appOrgModuleService.add(orgModule);
}
BaseSysRoleEntity role = TenantManager.withoutTenantCondition(() ->
baseSysRoleMapper.selectOneByQuery(
QueryWrapper.create().eq(BaseSysRoleEntity::getLabel, "org_admin_" + orgId)
)
);
if (role != null) {
List<Long> menuIds = new java.util.ArrayList<>();
for (String moduleKey : moduleKeys) {
AppModuleEntity module = appModuleMapper.selectOneByQuery(
QueryWrapper.create().eq(AppModuleEntity::getModuleKey, moduleKey)
);
if (module != null && StrUtil.isNotBlank(module.getMenuIds())) {
cn.hutool.json.JSONArray arr = new cn.hutool.json.JSONArray(module.getMenuIds());
for (Object o : arr) {
menuIds.add(Long.valueOf(o.toString()));
}
}
}
baseSysPermsService.updatePerms(role.getId(), menuIds.toArray(new Long[0]), null);
}
}
@Override
public Dict switchOrg(Long userId, Long orgId, boolean isAdmin) {
if (isAdmin) {
BaseSysUserRoleEntity userRole = baseSysUserRoleMapper.selectOneByQuery(
QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId)
);
CoolPreconditions.checkEmpty(userRole, "无权切换到该组织");
BaseSysRoleEntity role = baseSysRoleMapper.selectOneById(userRole.getRoleId());
CoolPreconditions.checkEmpty(role, "角色不存在");
CoolPreconditions.check(!orgId.equals(role.getTenantId()), "无权切换到该组织");
} else {
CoolPreconditions.check(!appOrgUserService.isOrgMember(userId, orgId), "未加入该组织");
}
AppOrgEntity org = this.getById(orgId);
CoolPreconditions.checkEmpty(org, "组织不存在");
CoolPreconditions.check(org.getStatus() == 0, "组织已停用");
if (!isAdmin) {
Dict tokenInfo = Dict.create()
.set("userType", UserTypeEnum.APP.name())
.set("userId", userId)
.set("orgId", orgId);
String token = jwtTokenUtil.generateToken(tokenInfo);
String refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
JwtUser jwtUser = new JwtUser(userId,
List.of(new SimpleGrantedAuthority("ROLE_" + UserTypeEnum.APP.name())),
true);
coolCache.set("app:userDetails:" + userId, jwtUser);
return Dict.create()
.set("token", token)
.set("expire", jwtTokenUtil.getExpire())
.set("refreshToken", refreshToken)
.set("refreshExpire", jwtTokenUtil.getRefreshExpire())
.set("orgId", orgId);
}
return Dict.create().set("orgId", orgId);
}
private String generateInviteCode() {
String code;
do {
code = RandomUtil.randomStringUpper(6);
} while (this.getOne(
QueryWrapper.create().eq(AppOrgEntity::getInviteCode, code)
) != null);
return code;
}
}
@@ -0,0 +1,180 @@
package com.cool.modules.org.service.impl;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.cool.core.base.BaseServiceImpl;
import com.cool.core.exception.CoolPreconditions;
import com.cool.modules.org.entity.AppOrgEntity;
import com.cool.modules.org.entity.AppOrgModuleEntity;
import com.cool.modules.org.entity.AppOrgUserEntity;
import com.cool.modules.org.mapper.AppOrgMapper;
import com.cool.modules.org.mapper.AppOrgUserMapper;
import com.cool.modules.org.service.AppOrgModuleService;
import com.cool.modules.org.service.AppOrgUserService;
import com.cool.modules.user.entity.UserInfoEntity;
import com.cool.modules.user.mapper.UserInfoMapper;
import com.mybatisflex.core.query.QueryWrapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class AppOrgUserServiceImpl extends BaseServiceImpl<AppOrgUserMapper, AppOrgUserEntity> implements
AppOrgUserService {
private final AppOrgModuleService appOrgModuleService;
private final UserInfoMapper userInfoMapper;
private final AppOrgMapper appOrgMapper;
@Override
public void joinOrg(Long userId, String inviteCode) {
CoolPreconditions.check(StrUtil.isBlank(inviteCode), "邀请码不能为空");
AppOrgEntity orgEntity = appOrgMapper.selectOneByQuery(
QueryWrapper.create().eq(AppOrgEntity::getInviteCode, inviteCode)
);
CoolPreconditions.checkEmpty(orgEntity, "邀请码无效");
CoolPreconditions.check(orgEntity.getStatus() == 0, "组织已停用");
joinOrgById(userId, orgEntity.getId());
}
@Override
public void joinOrgById(Long userId, Long orgId) {
AppOrgUserEntity existing = getOne(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getUserId, userId));
CoolPreconditions.check(existing != null && existing.getStatus() == 1, "已加入该组织");
CoolPreconditions.check(existing != null && existing.getStatus() == 0, "已申请加入,等待审批");
AppOrgEntity orgEntity = appOrgMapper.selectOneById(orgId);
CoolPreconditions.checkEmpty(orgEntity, "组织不存在");
CoolPreconditions.check(orgEntity.getStatus() == 0, "组织已停用");
AppOrgUserEntity orgUser = new AppOrgUserEntity();
orgUser.setOrgId(orgId);
orgUser.setUserId(userId);
orgUser.setRole("member");
if (orgEntity.getJoinType() == 0) {
orgUser.setStatus(1);
orgUser.setJoinTime(new java.util.Date());
} else {
orgUser.setStatus(0);
}
if (existing != null) {
orgUser.setId(existing.getId());
this.update(orgUser);
} else {
this.add(orgUser);
}
}
@Override
public void quitOrg(Long userId, Long orgId) {
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getUserId, userId)
.eq(AppOrgUserEntity::getStatus, 1));
CoolPreconditions.checkEmpty(orgUser, "未加入该组织");
orgUser.setStatus(3);
this.update(orgUser);
}
@Override
public void approve(Long adminUserId, Long orgId, Long targetUserId, boolean approved) {
CoolPreconditions.check(!isOrgAdmin(adminUserId, orgId), "无审批权限");
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getUserId, targetUserId)
.eq(AppOrgUserEntity::getStatus, 0));
CoolPreconditions.checkEmpty(orgUser, "无待审批记录");
orgUser.setStatus(approved ? 1 : 2);
if (approved) {
orgUser.setJoinTime(new java.util.Date());
}
this.update(orgUser);
}
@Override
public List<Map<String, Object>> getOrgListByUserId(Long userId) {
List<AppOrgUserEntity> orgUsers = list(QueryWrapper.create()
.eq(AppOrgUserEntity::getUserId, userId)
.eq(AppOrgUserEntity::getStatus, 1));
List<Map<String, Object>> result = new ArrayList<>();
for (AppOrgUserEntity ou : orgUsers) {
Map<String, Object> item = new HashMap<>();
item.put("orgId", ou.getOrgId());
item.put("role", ou.getRole());
item.put("joinTime", ou.getJoinTime());
AppOrgEntity org = appOrgMapper.selectOneById(ou.getOrgId());
if (org != null) {
item.put("name", org.getName());
item.put("icon", org.getIcon());
item.put("type", org.getType());
item.put("status", org.getStatus());
}
// Get modules
List<String> moduleKeys = appOrgModuleService.getModuleKeysByOrgId(ou.getOrgId());
item.put("modules", moduleKeys);
result.add(item);
}
return result;
}
@Override
public List<Map<String, Object>> getMemberListByOrgId(Long orgId) {
List<AppOrgUserEntity> orgUsers = list(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getStatus, 1));
List<Map<String, Object>> result = new ArrayList<>();
for (AppOrgUserEntity ou : orgUsers) {
Map<String, Object> item = new HashMap<>();
item.put("id", ou.getId());
item.put("userId", ou.getUserId());
item.put("role", ou.getRole());
item.put("joinTime", ou.getJoinTime());
UserInfoEntity user = userInfoMapper.selectOneById(ou.getUserId());
if (user != null) {
item.put("nickName", user.getNickName());
item.put("avatarUrl", user.getAvatarUrl());
item.put("phone", user.getPhone());
}
result.add(item);
}
return result;
}
@Override
public boolean isOrgAdmin(Long userId, Long orgId) {
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getUserId, userId)
.eq(AppOrgUserEntity::getStatus, 1)
.eq(AppOrgUserEntity::getRole, "admin"));
return orgUser != null;
}
@Override
public boolean isOrgMember(Long userId, Long orgId) {
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
.eq(AppOrgUserEntity::getOrgId, orgId)
.eq(AppOrgUserEntity::getUserId, userId)
.eq(AppOrgUserEntity::getStatus, 1));
return orgUser != null;
}
}
@@ -0,0 +1,22 @@
package com.cool.modules.zoo.controller.admin;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController;
import com.cool.modules.zoo.entity.ZooAnimalEntity;
import com.cool.modules.zoo.service.ZooAnimalService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "动物管理", description = "动物信息管理")
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
public class AdminZooAnimalController extends BaseController<ZooAnimalService, ZooAnimalEntity> {
@Override
protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp());
}
}
@@ -0,0 +1,33 @@
package com.cool.modules.zoo.controller.app;
import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController;
import com.cool.core.request.R;
import com.cool.modules.zoo.entity.ZooAnimalEntity;
import com.cool.modules.zoo.service.ZooAnimalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
@RequiredArgsConstructor
@Tag(name = "动物", description = "App端动物")
@CoolRestController
public class AppZooAnimalController {
private final ZooAnimalService zooAnimalService;
@Operation(summary = "动物列表")
@GetMapping("/list")
public R list(@RequestAttribute JSONObject requestParams) {
return R.ok(zooAnimalService.list(requestParams, null));
}
@Operation(summary = "动物详情")
@GetMapping("/detail")
public R detail(@RequestAttribute JSONObject requestParams) {
Long id = requestParams.getLong("id");
return R.ok(zooAnimalService.info(id));
}
}
@@ -0,0 +1,31 @@
package com.cool.modules.zoo.entity;
import com.cool.core.base.TenantEntity;
import com.mybatisflex.annotation.Table;
import com.cool.core.annotation.ColumnDefine;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Table(value = "zoo_animal", comment = "动物信息表")
public class ZooAnimalEntity extends TenantEntity<ZooAnimalEntity> {
@ColumnDefine(comment = "动物名称", notNull = true)
private String name;
@ColumnDefine(comment = "分类")
private String category;
@ColumnDefine(comment = "展区")
private String area;
@ColumnDefine(comment = "图片")
private String image;
@ColumnDefine(comment = "描述", type = "text")
private String description;
@ColumnDefine(comment = "状态 0:离开 1:展出", defaultValue = "1")
private Integer status;
}
@@ -0,0 +1,7 @@
package com.cool.modules.zoo.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cool.modules.zoo.entity.ZooAnimalEntity;
public interface ZooAnimalMapper extends BaseMapper<ZooAnimalEntity> {
}
@@ -0,0 +1,7 @@
package com.cool.modules.zoo.service;
import com.cool.core.base.BaseService;
import com.cool.modules.zoo.entity.ZooAnimalEntity;
public interface ZooAnimalService extends BaseService<ZooAnimalEntity> {
}
@@ -0,0 +1,12 @@
package com.cool.modules.zoo.service.impl;
import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.zoo.entity.ZooAnimalEntity;
import com.cool.modules.zoo.mapper.ZooAnimalMapper;
import com.cool.modules.zoo.service.ZooAnimalService;
import org.springframework.stereotype.Service;
@Service
public class ZooAnimalServiceImpl extends BaseServiceImpl<ZooAnimalMapper, ZooAnimalEntity> implements
ZooAnimalService {
}
+1 -1
View File
@@ -153,7 +153,7 @@ cool:
queue-capacity-multiplier: 3
multi-tenant:
# 是否开启多租户,默认关闭
enable: false
enable: true
# AutoTable配置,根据实体类自动生成表
auto-table:
show-banner: false