Publish apes-Authon via gitea-publish skill
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package cn.apes;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 账权独立服务 — 从 saas-service 提取的纯净认证/授权/用户/角色/权限/多租户体系
|
||||
*
|
||||
* 本服务包含:
|
||||
* - 用户认证(密码登录 / Redis 会话 / Token 管理)
|
||||
* - RBAC 权限模型(菜单 / 权限码 / 角色 / 成员角色)
|
||||
* - 多租户管理(客户/企业 / 组织架构 / 数据源切换)
|
||||
* - 套餐与配额管理
|
||||
* - SSO 单点登录(伙伴云)
|
||||
* - 操作日志
|
||||
* - 用户偏好
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
@MapperScan("cn.apes.cloud.mapper")
|
||||
public class AuthonApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthonApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.apes.cloud.config;
|
||||
|
||||
import cn.apes.cloud.filter.AccessTokenFilter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
/**
|
||||
* AccessToken 过滤器注册
|
||||
* 注册为最高优先级,确保在 Spring 其他拦截之前执行
|
||||
*/
|
||||
@Configuration
|
||||
public class AccessTokenFilterConfig {
|
||||
|
||||
@Autowired
|
||||
private AccessTokenFilter accessTokenFilter;
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<AccessTokenFilter> accessTokenFilterRegistration() {
|
||||
FilterRegistrationBean<AccessTokenFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(accessTokenFilter);
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setOrder(1); // 最高优先级
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setName("accessTokenFilter");
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package cn.apes.cloud.config;
|
||||
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.redisson.api.RBucket;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(1)
|
||||
public class DataSourceHeaderAspect {
|
||||
|
||||
|
||||
List<String> heads = CollUtil.newArrayList("user", "zx","plant");
|
||||
|
||||
@Around("@within(tenantSource)")
|
||||
public Object clazz(ProceedingJoinPoint pjp, TenantSource tenantSource) throws Throwable {
|
||||
return exc(pjp, tenantSource);
|
||||
}
|
||||
|
||||
@Around("@annotation(tenantSource)")
|
||||
public Object menthod(ProceedingJoinPoint pjp, TenantSource tenantSource) throws Throwable {
|
||||
return exc(pjp, tenantSource);
|
||||
}
|
||||
|
||||
Object exc(ProceedingJoinPoint pjp, TenantSource tenantSource) throws Throwable {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
// 保留 AccessToken 过滤器已设置的认证上下文
|
||||
if (request.getAttribute("accessTokenVerified") == null) {
|
||||
AuthContext.clean();
|
||||
}
|
||||
String head = request.getHeader("X-Tenant-ID");
|
||||
if (StrUtil.isEmpty(head)) {
|
||||
head="user";
|
||||
}
|
||||
if(!heads.contains(head)) {
|
||||
throw new RuntimeException("数据源ID有误");
|
||||
}
|
||||
DynamicDataSourceContextHolder.push(head);
|
||||
|
||||
return pjp.proceed();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.apes.cloud.config;
|
||||
|
||||
|
||||
public class HbTokenContext {
|
||||
|
||||
private static final ThreadLocal<String> LOGIN_THREAD_LOCAL = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 设置伙伴云token
|
||||
*
|
||||
* @param loginInfo 登录信息
|
||||
*/
|
||||
public static void setHbToken(String loginInfo) {
|
||||
LOGIN_THREAD_LOCAL.set(loginInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录token
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getHbToken() {
|
||||
return LOGIN_THREAD_LOCAL.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空登录用户信息
|
||||
*/
|
||||
public static void clean() {
|
||||
LOGIN_THREAD_LOCAL.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.apes.cloud.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "sit.config")
|
||||
public class SiteConfig {
|
||||
|
||||
@Value("${sit.config.payment.domain}")
|
||||
private String paymentDomain;
|
||||
|
||||
@Value("${sit.config.payment.cookieDomain}")
|
||||
private String cookieDomain;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.config;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface TenantSource {
|
||||
String value() default "user";
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysAccessToken;
|
||||
import cn.apes.cloud.service.SysAccessTokenService;
|
||||
import cn.apes.cloud.util.OperationLogUtil;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.commons.auth.LoginCustomer;
|
||||
import cn.apes.commons.auth.UserSession;
|
||||
import cn.apes.commons.Res;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AccessToken 管理接口
|
||||
*/
|
||||
@Login
|
||||
@RestController
|
||||
@RequestMapping("/sysAccessToken")
|
||||
public class AccessTokenController {
|
||||
|
||||
@Autowired
|
||||
private SysAccessTokenService accessTokenService;
|
||||
|
||||
/**
|
||||
* 创建 AccessToken
|
||||
*/
|
||||
@PostMapping("/create")
|
||||
public Res create(@RequestBody Map<String, Object> params) {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
LoginCustomer customer = authUserInfo.getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
|
||||
SysAccessToken record = new SysAccessToken();
|
||||
record.setCustomerId(customer.getId());
|
||||
record.setName((String) params.get("name"));
|
||||
record.setScope(params.get("scope") != null ? (String) params.get("scope") : "*");
|
||||
record.setWhitelistIps(params.get("whitelistIps") != null ? (String) params.get("whitelistIps") : "");
|
||||
record.setStatus(1);
|
||||
|
||||
if (params.get("expireTime") != null) {
|
||||
try {
|
||||
record.setExpireTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String) params.get("expireTime")));
|
||||
} catch (Exception e) {
|
||||
return Res.fail("过期时间格式错误,应为 yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
String token = accessTokenService.generateToken();
|
||||
record.setToken(token);
|
||||
record.setCreateBy(authUserInfo.getUser() != null ? authUserInfo.getUser().getId() : null);
|
||||
accessTokenService.save(record);
|
||||
|
||||
OperationLogUtil.log("AccessToken管理", "创建", "创建AccessToken[" + record.getName() + "]");
|
||||
|
||||
// 返回完整 Token(只在创建时展示一次)
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("id", record.getId());
|
||||
result.put("name", record.getName());
|
||||
result.put("token", token);
|
||||
result.put("customerId", record.getCustomerId());
|
||||
result.put("scope", record.getScope());
|
||||
result.put("expireTime", record.getExpireTime() != null ? sdf.format(record.getExpireTime()) : null);
|
||||
result.put("message", "Token 仅在创建时显示一次,请妥善保存");
|
||||
return Res.success(result);
|
||||
}
|
||||
|
||||
private Long parseId(Map<String, Object> params) {
|
||||
Object val = params.get("id");
|
||||
if (val == null) return null;
|
||||
return Long.parseLong(val.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询列表
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
public Res page(@RequestBody Map<String, Object> params) {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
LoginCustomer customer = authUserInfo.getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
|
||||
int pageIndex = params.get("pageIndex") != null ? Integer.parseInt(params.get("pageIndex").toString()) : 1;
|
||||
int pageSize = params.get("pageSize") != null ? Integer.parseInt(params.get("pageSize").toString()) : 10;
|
||||
|
||||
LambdaQueryWrapper<SysAccessToken> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SysAccessToken::getCustomerId, customer.getId());
|
||||
wrapper.orderByDesc(SysAccessToken::getCreateTime);
|
||||
|
||||
Page<SysAccessToken> page = accessTokenService.page(new Page<>(pageIndex, pageSize), wrapper);
|
||||
|
||||
// 脱敏:不返回完整 token
|
||||
for (SysAccessToken item : page.getRecords()) {
|
||||
if (item.getToken() != null && item.getToken().length() > 8) {
|
||||
item.setToken(item.getToken().substring(0, 6) + "****" + item.getToken().substring(item.getToken().length() - 2));
|
||||
}
|
||||
}
|
||||
|
||||
return Res.success(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销 Token
|
||||
*/
|
||||
@PostMapping("/revoke")
|
||||
public Res revoke(@RequestBody Map<String, Object> params) {
|
||||
Long id = parseId(params);
|
||||
if (id == null) return Res.fail("缺少 id 参数");
|
||||
SysAccessToken record = accessTokenService.getById(id);
|
||||
String name = record != null ? record.getName() : "id=" + id;
|
||||
accessTokenService.revoke(id);
|
||||
OperationLogUtil.log("AccessToken管理", "停用", "停用AccessToken[" + name + "]");
|
||||
return Res.success("已撤销");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用 Token
|
||||
*/
|
||||
@PostMapping("/enable")
|
||||
public Res enable(@RequestBody Map<String, Object> params) {
|
||||
Long id = parseId(params);
|
||||
if (id == null) return Res.fail("缺少 id 参数");
|
||||
SysAccessToken record = accessTokenService.getById(id);
|
||||
String name = record != null ? record.getName() : "id=" + id;
|
||||
accessTokenService.enable(id);
|
||||
OperationLogUtil.log("AccessToken管理", "启用", "启用AccessToken[" + name + "]");
|
||||
return Res.success("已启用");
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新生成 Token
|
||||
*/
|
||||
@PostMapping("/regenerate")
|
||||
public Res regenerate(@RequestBody Map<String, Object> params) {
|
||||
Long id = parseId(params);
|
||||
if (id == null) return Res.fail("缺少 id 参数");
|
||||
SysAccessToken record = accessTokenService.getById(id);
|
||||
String name = record != null ? record.getName() : "id=" + id;
|
||||
String newToken = accessTokenService.regenerate(id);
|
||||
OperationLogUtil.log("AccessToken管理", "重新生成", "重新生成AccessToken[" + name + "]");
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("token", newToken);
|
||||
result.put("message", "新 Token 已生成,旧 Token 立即失效");
|
||||
return Res.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Token
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public Res delete(@RequestBody Map<String, Object> params) {
|
||||
Long id = parseId(params);
|
||||
if (id == null) return Res.fail("缺少 id 参数");
|
||||
SysAccessToken record = accessTokenService.getById(id);
|
||||
String name = record != null ? record.getName() : "id=" + id;
|
||||
accessTokenService.removeById(id);
|
||||
OperationLogUtil.log("AccessToken管理", "删除", "删除AccessToken[" + name + "]");
|
||||
return Res.success("已删除");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.dto.AppSearchDTO;
|
||||
import cn.apes.cloud.domain.entity.AppInfo;
|
||||
import cn.apes.cloud.domain.entity.SysMenu;
|
||||
import cn.apes.cloud.domain.entity.SysPermission;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.CustomerApp;
|
||||
import cn.apes.cloud.service.impl.AppInfoServiceImpl;
|
||||
import cn.apes.cloud.service.impl.CustomerAppServiceImpl;
|
||||
import cn.apes.cloud.service.impl.CustomerInfoServiceImpl;
|
||||
import cn.apes.cloud.mapper.SysMenuMapper;
|
||||
import cn.apes.cloud.mapper.SysPermissionMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Login
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/app")
|
||||
public class AppController {
|
||||
@Autowired
|
||||
AppInfoServiceImpl appInfoService;
|
||||
|
||||
@Autowired
|
||||
CustomerAppServiceImpl customerAppService;
|
||||
|
||||
@Autowired
|
||||
CustomerInfoServiceImpl customerInfoService;
|
||||
|
||||
@Autowired
|
||||
SysMenuMapper sysMenuMapper;
|
||||
|
||||
@Autowired
|
||||
SysPermissionMapper sysPermissionMapper;
|
||||
|
||||
/**
|
||||
* 分页查询应用列表
|
||||
*/
|
||||
@PostMapping("/pageApp")
|
||||
public Res pageApp(@RequestBody AppSearchDTO searchDTO) {
|
||||
return appInfoService.pageApp(searchDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/编辑应用
|
||||
*/
|
||||
@PostMapping("/saveApp")
|
||||
public Res saveApp(@RequestBody AppInfo appInfo) {
|
||||
return appInfoService.saveApp(appInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应用
|
||||
*/
|
||||
@PostMapping("/deleteApp")
|
||||
public Res deleteApp(@RequestBody AppInfo appInfo) {
|
||||
return appInfoService.deleteApp(appInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用详情(基本信息 + 菜单 + 权限 + 关联客户)
|
||||
*/
|
||||
@PostMapping("/getAppDetail")
|
||||
public Res getAppDetail(@RequestBody AppInfo param) {
|
||||
String appKey = param.getAppKey();
|
||||
AppInfo appInfo = appInfoService.getById(appKey);
|
||||
if (appInfo == null) {
|
||||
return Res.fail("应用不存在");
|
||||
}
|
||||
|
||||
// 隐藏敏感字段
|
||||
appInfo.setRemark(null);
|
||||
|
||||
// 查询关联的菜单列表
|
||||
List<SysMenu> menuList = sysMenuMapper.selectList(
|
||||
new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getAppName, appKey)
|
||||
);
|
||||
|
||||
// 查询关联的权限列表
|
||||
List<SysPermission> permissionList = sysPermissionMapper.selectList(
|
||||
new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getAppName, appKey)
|
||||
);
|
||||
|
||||
// 查询关联的客户列表
|
||||
List<Long> customerIds = customerAppService.getCustomerIdsByAppKey(appKey);
|
||||
List<CustomerInfo> customerList = new ArrayList<>();
|
||||
if (!customerIds.isEmpty()) {
|
||||
customerList = customerInfoService.listByIds(customerIds);
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("appInfo", appInfo);
|
||||
result.put("menuList", menuList);
|
||||
result.put("permissionList", permissionList);
|
||||
result.put("customerList", customerList);
|
||||
|
||||
return Res.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.commons.auth.LoginCustomer;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.dto.CustomerSearchDTO;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.SsoConfig;
|
||||
import cn.apes.cloud.service.impl.CustomerAppServiceImpl;
|
||||
import cn.apes.cloud.service.impl.CustomerInfoServiceImpl;
|
||||
import cn.apes.cloud.service.impl.CustomerUserServiceImpl;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Login
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/customer")
|
||||
public class CustomerController {
|
||||
|
||||
@Autowired
|
||||
CustomerInfoServiceImpl customerInfoService;
|
||||
|
||||
@Autowired
|
||||
CustomerUserServiceImpl customerUserService;
|
||||
|
||||
@Autowired
|
||||
CustomerAppServiceImpl customerAppService;
|
||||
|
||||
@PostMapping("/pageCustomer")
|
||||
public Res pageCustomer(@RequestBody CustomerSearchDTO searchDTO) {
|
||||
return customerInfoService.pageCustomer(searchDTO);
|
||||
}
|
||||
|
||||
@GetMapping("/getCustomerDetail")
|
||||
public Res getCustomerDetail(@RequestParam("id") Long id) {
|
||||
return customerInfoService.getCustomerDetail(id);
|
||||
}
|
||||
|
||||
@GetMapping("/addUser")
|
||||
public Res addUser(Long customerId, Long userId) {
|
||||
return customerUserService.addUser(customerId, userId);
|
||||
}
|
||||
|
||||
@GetMapping("/delUser")
|
||||
public Res delUser(Long customerId, Long userId) {
|
||||
return customerUserService.delUser(customerId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询员工列表(customerId 从登录上下文获取)
|
||||
*/
|
||||
@PostMapping("/employee/page")
|
||||
public Res pageEmployee(@RequestBody JSONObject data) {
|
||||
int pageIndex = data.getIntValue("pageIndex");
|
||||
int pageSize = data.getIntValue("pageSize");
|
||||
Long orgId = data.getLong("orgId");
|
||||
if (pageIndex <= 0) pageIndex = 1;
|
||||
if (pageSize <= 0) pageSize = 10;
|
||||
return customerUserService.pageEmployee(pageIndex, pageSize, orgId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取员工详情(编辑用)
|
||||
*/
|
||||
@GetMapping("/employee/detail")
|
||||
public Res getEmployeeDetail(@RequestParam("userId") Long userId) {
|
||||
return customerUserService.getEmployeeDetail(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新员工信息
|
||||
*/
|
||||
@PostMapping("/employee/update")
|
||||
public Res updateEmployee(@RequestBody JSONObject data) {
|
||||
Long userId = data.getLong("userId");
|
||||
Long orgId = data.getLong("orgId");
|
||||
String name = data.getString("name");
|
||||
String title = data.getString("title");
|
||||
String position = data.getString("position");
|
||||
String appIds = data.getString("appIds");
|
||||
return customerUserService.updateEmployee(userId, orgId, name, title, position, appIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/编辑客户
|
||||
*/
|
||||
@PostMapping("/saveCustomer")
|
||||
public Res saveCustomer(@RequestBody CustomerInfo customerInfo) {
|
||||
return customerInfoService.saveCustomer(customerInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客户
|
||||
*/
|
||||
@PostMapping("/deleteCustomer")
|
||||
public Res deleteCustomer(@RequestBody CustomerInfo customerInfo) {
|
||||
return customerInfoService.deleteCustomer(customerInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录客户已关联的应用列表(从登录上下文获取 customerId)
|
||||
*/
|
||||
@GetMapping("/getMyApps")
|
||||
public Res getMyApps() {
|
||||
LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
return Res.success(customerAppService.getMyAppsWithSource(customer.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定客户已关联的应用列表(管理端用)
|
||||
*/
|
||||
@GetMapping("/getCustomerApps")
|
||||
public Res getCustomerApps(@RequestParam("customerId") Long customerId) {
|
||||
return Res.success(customerAppService.getApps(customerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联应用给客户
|
||||
*/
|
||||
@PostMapping("/addCustomerApp")
|
||||
public Res addCustomerApp(@RequestBody JSONObject data) {
|
||||
Long customerId = data.getLong("customerId");
|
||||
String appKey = data.getString("appKey");
|
||||
return customerAppService.addApp(customerId, appKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑客户的应用
|
||||
*/
|
||||
@PostMapping("/removeCustomerApp")
|
||||
public Res removeCustomerApp(@RequestBody JSONObject data) {
|
||||
Long customerId = data.getLong("customerId");
|
||||
String appKey = data.getString("appKey");
|
||||
return customerAppService.removeApp(customerId, appKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有应用(用于选择器)
|
||||
*/
|
||||
@GetMapping("/getAllApps")
|
||||
public Res getAllApps() {
|
||||
return Res.success(customerAppService.getAllApps());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户SSO配置(公司级别 user_id=0)
|
||||
*/
|
||||
@GetMapping("/getSSOConfig")
|
||||
public Res getSSOConfig(@RequestParam("customerId") Long customerId) {
|
||||
return customerInfoService.getSSOConfig(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存客户SSO配置(公司级别 user_id=0)
|
||||
*/
|
||||
@PostMapping("/saveSSOConfig")
|
||||
public Res saveSSOConfig(@RequestBody SsoConfig ssoConfig) {
|
||||
return customerInfoService.saveSSOConfig(ssoConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客户状态
|
||||
*/
|
||||
@PostMapping("/updateCustomerStatus")
|
||||
public Res updateCustomerStatus(@RequestBody CustomerInfo customerInfo) {
|
||||
return customerInfoService.updateCustomerStatus(customerInfo.getId(), customerInfo.getCustomerStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核企业认证(通过/拒绝)
|
||||
*/
|
||||
@PostMapping("/auditCertification")
|
||||
public Res auditCertification(@RequestBody JSONObject data) {
|
||||
Long customerId = data.getLong("customerId");
|
||||
Integer auditStatus = data.getInteger("customerStatus"); // 1=通过, 5=拒绝
|
||||
String auditRemark = data.getString("auditRemark"); // 拒绝原因
|
||||
return customerInfoService.auditCertification(customerId, auditStatus, auditRemark);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 同步全部租户信息到伙伴云(使用 upsetOne 接口)
|
||||
*/
|
||||
@PostMapping("/syncTenantsToHuoban")
|
||||
public Res syncTenantsToHuoban() {
|
||||
return customerInfoService.syncAllTenantsToHuoban();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.commons.auth.LoginCustomer;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import cn.apes.cloud.service.CustomerPackageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Login
|
||||
@RestController
|
||||
@RequestMapping("/customerPackage")
|
||||
public class CustomerPackageController {
|
||||
|
||||
@Autowired
|
||||
private CustomerPackageService customerPackageService;
|
||||
|
||||
/**
|
||||
* 获取客户的套餐列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public Object list(@RequestParam Long customerId) {
|
||||
return customerPackageService.getCustomerPackages(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增客户套餐
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public Object add(@RequestBody CustomerPackage customerPackage) {
|
||||
return customerPackageService.addCustomerPackage(customerPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑客户套餐
|
||||
*/
|
||||
@PostMapping("/edit")
|
||||
public Object edit(@RequestBody java.util.Map<String, Object> data) {
|
||||
return customerPackageService.editCustomerPackage(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客户套餐
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public Object delete(@RequestBody CustomerPackage customerPackage) {
|
||||
return customerPackageService.deleteCustomerPackage(customerPackage.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存客户套餐配额
|
||||
*/
|
||||
@PostMapping("/saveQuotas")
|
||||
public Object saveQuotas(@RequestBody java.util.Map<String, Object> data) {
|
||||
Long packageId = data.get("packageId") != null ? Long.parseLong(data.get("packageId").toString()) : null;
|
||||
@SuppressWarnings("unchecked")
|
||||
java.util.Map<String, Object> quotaValues = (java.util.Map<String, Object>) data.get("quotaValues");
|
||||
return customerPackageService.saveCustomerPackageQuotas(packageId, quotaValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户套餐配额
|
||||
*/
|
||||
@GetMapping("/getQuotas")
|
||||
public Object getQuotas(@RequestParam Long packageId) {
|
||||
return customerPackageService.getCustomerPackageQuotas(packageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录客户的套餐列表(从登录上下文获取 customerId)
|
||||
*/
|
||||
@GetMapping("/myPackages")
|
||||
public Res myPackages() {
|
||||
LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
return customerPackageService.getMyPackages(customer.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理端:查询所有客户的套餐概况
|
||||
*/
|
||||
@PostMapping("/overview")
|
||||
public Object overview(@RequestBody java.util.Map<String, Object> params) {
|
||||
return customerPackageService.getCustomerPackageOverview(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提交套餐延期申请
|
||||
*/
|
||||
@PostMapping("/submitExtendApply")
|
||||
public Object submitExtendApply(@RequestBody java.util.Map<String, Object> params) {
|
||||
params.put("userId", AuthContext.getLoginInfo().getCustomer().getId());
|
||||
return customerPackageService.submitExtendApply(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 管理端:查询套餐延期申请记录列表
|
||||
*/
|
||||
@PostMapping("/extendApplyList")
|
||||
public Object extendApplyList(@RequestBody java.util.Map<String, Object> params) {
|
||||
return customerPackageService.getExtendApplyList(params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 审核延期申请(同意/拒绝)
|
||||
*/
|
||||
@PostMapping("/reviewExtendApply")
|
||||
public Object reviewExtendApply(@RequestBody java.util.Map<String, Object> params) {
|
||||
return customerPackageService.reviewExtendApply(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加客户套餐额度
|
||||
*/
|
||||
@PostMapping("/increaseQuota")
|
||||
public Object increaseQuota(@RequestBody java.util.Map<String, Object> params) {
|
||||
return customerPackageService.increaseQuota(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少客户套餐额度
|
||||
*/
|
||||
@PostMapping("/decreaseQuota")
|
||||
public Object decreaseQuota(@RequestBody java.util.Map<String, Object> params) {
|
||||
return customerPackageService.decreaseQuota(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配额变更日志列表
|
||||
*/
|
||||
@GetMapping("/quotaChangeLogs")
|
||||
public Object getQuotaChangeLogs(@RequestParam java.util.Map<String, Object> params) {
|
||||
return customerPackageService.getQuotaChangeLogs(params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.UserSession;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.dto.RoleSearchDTO;
|
||||
import cn.apes.cloud.domain.entity.SysMenu;
|
||||
import cn.apes.cloud.domain.entity.SysPermission;
|
||||
import cn.apes.cloud.domain.entity.SysRole;
|
||||
import cn.apes.cloud.service.impl.PermissionServiceImpl;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.commons.auth.LoginCustomer;
|
||||
import cn.hutool.http.server.HttpServerResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Login
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/permission")
|
||||
public class PermissionController {
|
||||
|
||||
@Autowired
|
||||
PermissionServiceImpl permissionService;
|
||||
|
||||
@GetMapping("/currentMenus")
|
||||
public Res getCurrentMenus() {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
return permissionService.getMemberMenus(authUserInfo.getUser().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定应用的全部菜单树(按用户权限过滤)
|
||||
*/
|
||||
@GetMapping("/getAppMenus")
|
||||
public Res getAppMenus(@RequestParam("appName") String appName) {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
return permissionService.getAppMenus(authUserInfo.getUser().getId(), appName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户在当前企业的所有权限code,按应用名分组
|
||||
* 返回格式: {"BASE_APP": ["code1", "code2"], "guobang": ["code1"]}
|
||||
*/
|
||||
@GetMapping("/getMyPermissionCodes")
|
||||
public Res getMyPermissionCodes() {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
return permissionService.getMyPermissionCodesByApp(authUserInfo.getUser().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定应用的菜单树(按客户套餐权限过滤)
|
||||
*/
|
||||
@GetMapping("/getPackageAppMenus")
|
||||
public Res getPackageAppMenus(@RequestParam("appName") String appName) {
|
||||
UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
LoginCustomer customer = authUserInfo.getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
Long userId = authUserInfo.getUser() != null ? authUserInfo.getUser().getId() : null;
|
||||
if (userId == null) {
|
||||
return Res.fail("未找到当前登录用户信息");
|
||||
}
|
||||
return permissionService.getPackageAppMenus(userId, customer.getId(), appName);
|
||||
}
|
||||
|
||||
// @GetMapping("/getOldMemberMenus")
|
||||
// public Res getOldMemberMenus(@RequestHeader("version") String version){
|
||||
// AuthUserInfo authUserInfo = AuthContext.getLoginInfo();
|
||||
// AppInfo appInfo = AuthContext.getAppInfo();
|
||||
// return permissionService.getOldMemberMenus(authUserInfo.getMemberNo(),appInfo.getAppName(),version);
|
||||
// }
|
||||
|
||||
// @GetMapping("/getRolePermission")
|
||||
// public Res getRolePermission(){
|
||||
// UserSession authUserInfo = AuthContext.getLoginInfo();
|
||||
// return permissionService.getRolePermission(authUserInfo.getUser().getId());
|
||||
// }
|
||||
|
||||
@PostMapping("/saveMenu")
|
||||
public Res saveMenu(@RequestBody SysMenu menu) {
|
||||
return permissionService.saveMenu(menu);
|
||||
}
|
||||
|
||||
@GetMapping("/getAllMenu")
|
||||
public Res getAllMenu(@RequestParam("appName") String appName) {
|
||||
return permissionService.getAllMenu(appName);
|
||||
}
|
||||
|
||||
@PostMapping("/savePermission")
|
||||
public Res savePermission(@RequestBody SysPermission menu) {
|
||||
return permissionService.savePermission(menu);
|
||||
}
|
||||
|
||||
@GetMapping("/getAllPermission")
|
||||
public Res getAllPermission(String appName) {
|
||||
return permissionService.getAllPermission(appName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定套餐下指定应用的权限树(仅包含该套餐拥有的权限)
|
||||
*/
|
||||
@GetMapping("/getPlanPermissionTree")
|
||||
public Res getPlanPermissionTree(@RequestParam("planId") Long planId, @RequestParam("appName") String appName) {
|
||||
return permissionService.getPlanPermissionTree(planId, appName);
|
||||
}
|
||||
|
||||
@PostMapping("/deletePermission")
|
||||
public Res deletePermission(@RequestBody JSONObject data) {
|
||||
Long permissionId = data.getLong("permissionId");
|
||||
return permissionService.deletePermission(permissionId);
|
||||
}
|
||||
|
||||
@PostMapping("/deleteMenu")
|
||||
public Res deleteMenu(@RequestBody JSONObject data) {
|
||||
Long menuId = data.getLong("menuId");
|
||||
return permissionService.deleteMenu(menuId);
|
||||
}
|
||||
|
||||
@PostMapping("/getAllRole")
|
||||
public Res getAllRole(@RequestBody RoleSearchDTO searchDTO) {
|
||||
return permissionService.getAllRole(searchDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/getAllRoleByAppName")
|
||||
public Res getAllRoleByAppName(@RequestBody RoleSearchDTO searchDTO) {
|
||||
return permissionService.getAllRoleByAppName(searchDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/saveRole")
|
||||
public Res saveRole(@RequestBody SysRole role) {
|
||||
return permissionService.saveRole(role);
|
||||
}
|
||||
|
||||
@PostMapping("/deleteRole")
|
||||
public Res deleteRole(@RequestBody JSONObject data) {
|
||||
Long roleId = data.getLong("roleId");
|
||||
return permissionService.deleteRole(roleId);
|
||||
}
|
||||
|
||||
@PostMapping("/setRolePermission")
|
||||
public Res setRolePermission(@RequestBody JSONObject data) {
|
||||
return permissionService.setRolePermission(data);
|
||||
}
|
||||
|
||||
@GetMapping("/getRolePermission")
|
||||
public Res getRolePermission(Long roleId) {
|
||||
return permissionService.getRolePermission(roleId);
|
||||
}
|
||||
|
||||
@PostMapping("/setMemberRole")
|
||||
public Res setMemberRole(@RequestBody JSONObject data) {
|
||||
return permissionService.setMemberRole(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available roles for current customer (based on plan's apps)
|
||||
*/
|
||||
@GetMapping("/getMemberAvailableRoles")
|
||||
public Res getMemberAvailableRoles() {
|
||||
LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
return permissionService.getAvailableRolesForCustomer(customer.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get member's assigned roles (scoped by current customer)
|
||||
*/
|
||||
@GetMapping("/getMemberAssignedRoles")
|
||||
public Res getMemberAssignedRoles(@RequestParam("userId") Long userId) {
|
||||
LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
return permissionService.getMemberRolesByCustomer(customer.getId(), userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set member roles (scoped by current customer)
|
||||
*/
|
||||
@PostMapping("/setMemberRolesByCustomer")
|
||||
public Res setMemberRolesByCustomer(@RequestBody JSONObject data) {
|
||||
LoginCustomer customer = AuthContext.getLoginInfo().getCustomer();
|
||||
if (customer == null || customer.getId() == null) {
|
||||
return Res.fail("未找到当前登录客户信息");
|
||||
}
|
||||
data.put("customerId", customer.getId());
|
||||
return permissionService.setMemberRoleByCustomer(data);
|
||||
}
|
||||
|
||||
@GetMapping("/getHuoBanUrl")
|
||||
public Res getPageUrl(Long menuId) {
|
||||
return permissionService.getPageUrl(menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取伙伴云 SSO Token 信息(不需要菜单,不返回 pageUrl/menu)
|
||||
*/
|
||||
@GetMapping("/getHuobanToken")
|
||||
public Res getHuobanToken() {
|
||||
return permissionService.getHuobanToken();
|
||||
}
|
||||
|
||||
@GetMapping("/getMenu")
|
||||
public Res getMenu(Long menuId) {
|
||||
return permissionService.getMenu(menuId);
|
||||
}
|
||||
|
||||
@GetMapping("/getPaymentMenu")
|
||||
public Res getMenu(Long menuId, HttpServletResponse response, HttpServletRequest request) {
|
||||
return permissionService.getPaymentUrl(menuId, response, request);
|
||||
}
|
||||
|
||||
@GetMapping("/changePaymentGroup")
|
||||
public Res changePaymentGroup(Integer group, HttpServletRequest request){
|
||||
return permissionService.changePaymentGroup(group, request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.service.impl.SysOperationLogServiceImpl;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志控制器
|
||||
*/
|
||||
@Login
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/operationLog")
|
||||
public class SysOperationLogController {
|
||||
|
||||
@Autowired
|
||||
private SysOperationLogServiceImpl operationLogService;
|
||||
|
||||
/**
|
||||
* 分页查询操作日志
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
public Res pageLogs(@RequestBody Map<String, Object> params) {
|
||||
int pageIndex = params.get("pageIndex") != null ? ((Number) params.get("pageIndex")).intValue() : 1;
|
||||
int pageSize = params.get("pageSize") != null ? ((Number) params.get("pageSize")).intValue() : 10;
|
||||
Long customerId = params.get("customerId") != null ? ((Number) params.get("customerId")).longValue() : null;
|
||||
Long userId = params.get("userId") != null ? ((Number) params.get("userId")).longValue() : null;
|
||||
String startDate = params.get("startDate") != null ? params.get("startDate").toString() : null;
|
||||
String endDate = params.get("endDate") != null ? params.get("endDate").toString() : null;
|
||||
IPage<Map<String, Object>> result = operationLogService.pageLogs(
|
||||
pageIndex, pageSize, customerId, userId, startDate, endDate);
|
||||
Map<String, Object> pageData = new java.util.HashMap<>();
|
||||
pageData.put("records", result.getRecords());
|
||||
pageData.put("total", result.getTotal());
|
||||
return Res.success(pageData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业列表(用于下拉筛选)
|
||||
*/
|
||||
@GetMapping("/listCustomers")
|
||||
public Res listCustomers() {
|
||||
return Res.success(operationLogService.listCustomers());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.entity.SysOrganization;
|
||||
import cn.apes.cloud.service.impl.SysOrganizationServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 组织管理控制器
|
||||
*/
|
||||
@Login
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/organization")
|
||||
public class SysOrganizationController {
|
||||
|
||||
@Autowired
|
||||
private SysOrganizationServiceImpl organizationService;
|
||||
|
||||
/**
|
||||
* 分页查询组织列表
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
public Res pageOrganizations(@RequestParam(required = false) String orgName) {
|
||||
return organizationService.pageOrganizations(orgName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询组织树
|
||||
*/
|
||||
@GetMapping("/tree")
|
||||
public Res getOrganizationTree() {
|
||||
return organizationService.getOrganizationTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询组织详情
|
||||
*/
|
||||
@GetMapping("/detail")
|
||||
public Res detail(@RequestParam Long id) {
|
||||
return organizationService.getDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增组织
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public Res addOrganization(@RequestBody SysOrganization org) {
|
||||
return organizationService.addOrganization(org);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新组织
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public Res updateOrganization(@RequestBody SysOrganization org) {
|
||||
return organizationService.updateOrganization(org);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除组织
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public Res deleteOrganization(@RequestParam Long id) {
|
||||
return organizationService.deleteOrganization(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有启用的组织列表
|
||||
*/
|
||||
@GetMapping("/listAll")
|
||||
public Res listAllOrganizations() {
|
||||
return organizationService.listAllOrganizations();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import cn.apes.cloud.service.impl.SysPackagePlanServiceImpl;
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Login
|
||||
@RestController
|
||||
@RequestMapping("/packagePlan")
|
||||
public class SysPackagePlanController {
|
||||
|
||||
@Autowired
|
||||
private SysPackagePlanServiceImpl sysPackagePlanService;
|
||||
|
||||
@Autowired
|
||||
private cn.apes.cloud.service.SysPackagePlanQuotaService sysPackagePlanQuotaService;
|
||||
|
||||
@PostMapping("/page")
|
||||
public Res pagePackagePlan(@RequestBody JSONObject data) {
|
||||
int pageIndex = data.getIntValue("pageIndex");
|
||||
int pageSize = data.getIntValue("pageSize");
|
||||
if (pageIndex <= 0) pageIndex = 1;
|
||||
if (pageSize <= 0) pageSize = 10;
|
||||
String planName = data.getString("planName");
|
||||
return Res.success(sysPackagePlanService.pagePackagePlan(pageIndex, pageSize, planName));
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
public Res addPackagePlan(@RequestBody SysPackagePlan plan) {
|
||||
return sysPackagePlanService.addPackagePlan(plan);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public Res updatePackagePlan(@RequestBody SysPackagePlan plan) {
|
||||
return sysPackagePlanService.updatePackagePlan(plan);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public Res deletePackagePlan(@RequestBody JSONObject data) {
|
||||
Long id = data.getLong("id");
|
||||
return sysPackagePlanService.deletePackagePlan(id);
|
||||
}
|
||||
|
||||
@PostMapping("/toggleStatus")
|
||||
public Res toggleStatus(@RequestBody JSONObject data) {
|
||||
Long id = data.getLong("id");
|
||||
Integer status = data.getInteger("status");
|
||||
return sysPackagePlanService.toggleStatus(id, status);
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
public Res getDetail(@RequestParam Long id) {
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(id);
|
||||
if (plan == null) return Res.fail("套餐不存在");
|
||||
return Res.success(plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐已分配的权限
|
||||
*/
|
||||
@GetMapping("/getPermissions")
|
||||
public Res getPermissions(@RequestParam Long planId) {
|
||||
return Res.success(sysPackagePlanService.getPlanPermissions(planId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存套餐权限关联
|
||||
*/
|
||||
@PostMapping("/savePermissions")
|
||||
public Res savePermissions(@RequestBody JSONObject data) {
|
||||
Long planId = data.getLong("planId");
|
||||
Map<String, List<Long>> appPermissions = new java.util.HashMap<>();
|
||||
JSONObject appPermsObj = data.getJSONObject("appPermissions");
|
||||
if (appPermsObj != null) {
|
||||
for (String appKey : appPermsObj.keySet()) {
|
||||
List<Long> permIds = new java.util.ArrayList<>();
|
||||
Object val = appPermsObj.get(appKey);
|
||||
if (val instanceof List) {
|
||||
for (Object item : (List<?>) val) {
|
||||
if (item instanceof Number) {
|
||||
permIds.add(((Number) item).longValue());
|
||||
} else if (item != null) {
|
||||
try {
|
||||
permIds.add(Long.parseLong(item.toString()));
|
||||
} catch (NumberFormatException e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
appPermissions.put(appKey, permIds);
|
||||
}
|
||||
}
|
||||
return sysPackagePlanService.savePlanPermissions(planId, appPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐配额配置(已绑定的)
|
||||
*/
|
||||
@GetMapping("/getQuotas")
|
||||
public Res getPlanQuotas(@RequestParam Long planId) {
|
||||
return sysPackagePlanQuotaService.getPlanQuotas(planId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有配额模板 + 标记当前套餐是否已配置
|
||||
*/
|
||||
@GetMapping("/getAllQuotas")
|
||||
public Res getAllQuotas(@RequestParam Long planId) {
|
||||
return sysPackagePlanQuotaService.getAllQuotas(planId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐关联的应用列表
|
||||
*/
|
||||
@GetMapping("/getPlanApps")
|
||||
public Res getPlanApps(@RequestParam Long planId) {
|
||||
return sysPackagePlanService.getPlanApps(planId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存套餐配额配置
|
||||
*/
|
||||
@RequestMapping(value = "/saveQuotas", method = {org.springframework.web.bind.annotation.RequestMethod.GET, org.springframework.web.bind.annotation.RequestMethod.POST})
|
||||
public Res savePlanQuotas(@RequestBody(required = false) JSONObject data) {
|
||||
// 兼容 GET 请求(可能被重定向转换)
|
||||
if (data == null || data.isEmpty()) {
|
||||
// 尝试从 request parameters 获取
|
||||
javax.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) org.springframework.web.context.request.RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
Long planId = request.getParameter("planId") != null ? Long.parseLong(request.getParameter("planId")) : null;
|
||||
String quotaValuesStr = request.getParameter("quotaValues");
|
||||
Map<Long, String> quotaValues = new java.util.HashMap<>();
|
||||
if (quotaValuesStr != null) {
|
||||
try {
|
||||
JSONObject qv = JSONObject.parseObject(quotaValuesStr);
|
||||
for (String key : qv.keySet()) {
|
||||
Object val = qv.get(key);
|
||||
quotaValues.put(Long.parseLong(key), val != null ? val.toString() : null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return Res.fail("quotaValues格式错误");
|
||||
}
|
||||
}
|
||||
return sysPackagePlanQuotaService.savePlanQuotas(planId, quotaValues);
|
||||
}
|
||||
Long planId = data.getLong("planId");
|
||||
JSONObject quotaValuesObj = data.getJSONObject("quotaValues");
|
||||
Map<Long, String> quotaValues = new java.util.HashMap<>();
|
||||
if (quotaValuesObj != null) {
|
||||
for (String key : quotaValuesObj.keySet()) {
|
||||
Object val = quotaValuesObj.get(key);
|
||||
quotaValues.put(Long.parseLong(key), val != null ? val.toString() : null);
|
||||
}
|
||||
}
|
||||
return sysPackagePlanQuotaService.savePlanQuotas(planId, quotaValues);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysQuota;
|
||||
import cn.apes.cloud.service.impl.SysQuotaServiceImpl;
|
||||
import cn.apes.commons.Res;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/quota")
|
||||
public class SysQuotaController {
|
||||
|
||||
@Autowired
|
||||
private SysQuotaServiceImpl sysQuotaService;
|
||||
|
||||
@PostMapping("/page")
|
||||
public Res pageQuota(@RequestBody JSONObject data) {
|
||||
int pageIndex = data.getIntValue("pageIndex");
|
||||
int pageSize = data.getIntValue("pageSize");
|
||||
if (pageIndex <= 0) pageIndex = 1;
|
||||
if (pageSize <= 0) pageSize = 10;
|
||||
String appKey = data.getString("appKey");
|
||||
String quotaName = data.getString("quotaName");
|
||||
String quotaCode = data.getString("quotaCode");
|
||||
return Res.success(sysQuotaService.pageQuota(pageIndex, pageSize, appKey, quotaName, quotaCode));
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
public Res addQuota(@RequestBody SysQuota quota) {
|
||||
return sysQuotaService.addQuota(quota);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public Res updateQuota(@RequestBody SysQuota quota) {
|
||||
return sysQuotaService.updateQuota(quota);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public Res deleteQuota(@RequestBody JSONObject data) {
|
||||
Long id = data.getLong("id");
|
||||
return sysQuotaService.deleteQuota(id);
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
public Res getDetail(@RequestParam Long id) {
|
||||
SysQuota quota = sysQuotaService.getById(id);
|
||||
if (quota == null) return Res.fail("配额不存在");
|
||||
return Res.success(quota);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.dto.LoginDTO;
|
||||
import cn.apes.cloud.domain.dto.PwdDTO;
|
||||
import cn.apes.cloud.domain.dto.RegisterDTO;
|
||||
import cn.apes.cloud.domain.dto.SelectCustomerDTO;
|
||||
import cn.apes.cloud.domain.dto.UserSearchDTO;
|
||||
import cn.apes.cloud.domain.dto.EnterpriseCertifyDTO;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.UserInfo;
|
||||
import cn.apes.cloud.service.impl.UserInfoServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
UserInfoServiceImpl userInfoService;
|
||||
|
||||
@Login
|
||||
@PostMapping("/saveUserInfo")
|
||||
public Res saveUserInfo(@RequestBody UserInfo userInfo) {
|
||||
return userInfoService.saveUserInfo(userInfo);
|
||||
}
|
||||
|
||||
@Login
|
||||
// @CrossOrigin("*")
|
||||
@PostMapping("/pageUser")
|
||||
public Res pageUser(@RequestBody UserSearchDTO searchDTO) {
|
||||
return userInfoService.pageUser(searchDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/loginPwd")
|
||||
public Res loginPwd(@RequestBody LoginDTO loginDTO) {
|
||||
log.info("开始登录了");
|
||||
return userInfoService.loginPwd(loginDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public Res register(@RequestBody RegisterDTO dto) {
|
||||
return userInfoService.register(dto);
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("/resetPwd")
|
||||
public Res resetPwd(@RequestBody UserInfo userInfo) {
|
||||
return userInfoService.resetPwd(userInfo);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("/getCurrentUser")
|
||||
public Res getCurrentUser() {
|
||||
try {
|
||||
Object loginInfo = AuthContext.getLoginInfo();
|
||||
if (loginInfo == null) {
|
||||
return Res.fail("未登录");
|
||||
}
|
||||
return Res.success(loginInfo);
|
||||
} catch (Exception e) {
|
||||
return Res.fail("获取用户信息失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("/editPwd")
|
||||
public Res editPwd(@RequestBody PwdDTO pwdDTO) {
|
||||
return userInfoService.editPwd(pwdDTO);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("/getUserByPhone")
|
||||
public Res getUserByPhone(String phone) {
|
||||
return userInfoService.getUser(phone);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("/getCustomerUser")
|
||||
public Res getCustomerUser(Long customerId) {
|
||||
return userInfoService.getCustomerUser(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 多客户时用户选择企业
|
||||
*/
|
||||
@PostMapping("/selectCustomer")
|
||||
public Res selectCustomer(@RequestBody SelectCustomerDTO dto) {
|
||||
return userInfoService.selectCustomer(dto.getToken(), dto.getCustomerId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户关联的企业列表(用于切换企业场景)
|
||||
*/
|
||||
@Login
|
||||
@GetMapping("/getMyCustomers")
|
||||
public Res getMyCustomers() {
|
||||
return userInfoService.getMyCustomers();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑当前用户的个人资料(昵称、头像)
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/editProfile")
|
||||
public Res editProfile(@RequestBody UserInfo userInfo) {
|
||||
return userInfoService.editProfile(userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑当前企业信息(仅更新当前登录用户的所属企业)
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/customer/editCurrent")
|
||||
public Res editCurrentCustomer(@RequestBody CustomerInfo customerInfo) {
|
||||
return userInfoService.editCurrentCustomer(customerInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前企业信息(从数据库直接读取,不走Redis缓存)
|
||||
*/
|
||||
@Login
|
||||
@GetMapping("/customer/getCurrent")
|
||||
public Res getCurrentCustomer() {
|
||||
return userInfoService.getCurrentCustomerFromDb();
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业认证:用户提交认证表单,创建客户记录并关联当前用户
|
||||
* 使用登录返回的 token(无需额外登录态校验)
|
||||
*/
|
||||
@PostMapping("/certifyEnterprise")
|
||||
public Res certifyEnterprise(@RequestBody EnterpriseCertifyDTO dto) {
|
||||
if (dto == null || cn.hutool.core.util.StrUtil.isBlank(dto.getToken())) {
|
||||
return Res.fail("token不能为空");
|
||||
}
|
||||
CustomerInfo customerInfo = new CustomerInfo();
|
||||
customerInfo.setCustomerName(dto.getCustomerName());
|
||||
customerInfo.setLogo(dto.getLogo());
|
||||
customerInfo.setShortName(dto.getShortName());
|
||||
customerInfo.setCustomerType(dto.getCustomerType());
|
||||
customerInfo.setCustomerIdNumber(dto.getCustomerIdNumber());
|
||||
customerInfo.setLegalName(dto.getLegalName());
|
||||
customerInfo.setLegalIdFront(dto.getLegalIdFront());
|
||||
customerInfo.setLegalIdBack(dto.getLegalIdBack());
|
||||
customerInfo.setAdminName(dto.getAdminName());
|
||||
customerInfo.setAdminPhone(dto.getAdminPhone());
|
||||
customerInfo.setAdminIdNumber(dto.getAdminIdNumber());
|
||||
customerInfo.setResponsibleIdFront(dto.getResponsibleIdFront());
|
||||
customerInfo.setResponsibleIdBack(dto.getResponsibleIdBack());
|
||||
customerInfo.setIndustry(dto.getIndustry());
|
||||
customerInfo.setIndustrySub(dto.getIndustrySub());
|
||||
customerInfo.setSalesChannel(dto.getSalesChannel());
|
||||
customerInfo.setIndustryType(dto.getIndustryType());
|
||||
customerInfo.setProvince(dto.getProvince());
|
||||
customerInfo.setCity(dto.getCity());
|
||||
customerInfo.setBusinessLicense(dto.getBusinessLicense());
|
||||
return userInfoService.certifyEnterprise(dto.getToken(), customerInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的企业信息(用于重新编辑)
|
||||
*/
|
||||
@GetMapping("/getPendingCustomer")
|
||||
public Res getPendingCustomer(@RequestParam("token") String token) {
|
||||
return userInfoService.getPendingCustomer(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新提交企业认证
|
||||
*/
|
||||
@PostMapping("/recertifyEnterprise")
|
||||
public Res recertifyEnterprise(@RequestBody EnterpriseCertifyDTO dto) {
|
||||
CustomerInfo customerInfo = new CustomerInfo();
|
||||
customerInfo.setCustomerName(dto.getCustomerName());
|
||||
customerInfo.setShortName(dto.getShortName());
|
||||
customerInfo.setCustomerIdNumber(dto.getCustomerIdNumber());
|
||||
customerInfo.setAdminName(dto.getAdminName());
|
||||
customerInfo.setAdminPhone(dto.getAdminPhone());
|
||||
customerInfo.setAdminIdNumber(dto.getAdminIdNumber());
|
||||
customerInfo.setLegalName(dto.getLegalName());
|
||||
customerInfo.setLegalIdFront(dto.getLegalIdFront());
|
||||
customerInfo.setLegalIdBack(dto.getLegalIdBack());
|
||||
customerInfo.setResponsibleIdFront(dto.getResponsibleIdFront());
|
||||
customerInfo.setResponsibleIdBack(dto.getResponsibleIdBack());
|
||||
customerInfo.setLogo(dto.getLogo());
|
||||
customerInfo.setIndustry(dto.getIndustry());
|
||||
customerInfo.setIndustrySub(dto.getIndustrySub());
|
||||
customerInfo.setSalesChannel(dto.getSalesChannel());
|
||||
customerInfo.setIndustryType(dto.getIndustryType());
|
||||
customerInfo.setProvince(dto.getProvince());
|
||||
customerInfo.setCity(dto.getCity());
|
||||
customerInfo.setBusinessLicense(dto.getBusinessLicense());
|
||||
return userInfoService.recertifyEnterprise(dto.getToken(), customerInfo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package cn.apes.cloud.controller;
|
||||
|
||||
import cn.apes.cloud.config.TenantSource;
|
||||
import cn.apes.cloud.domain.entity.UserPreference;
|
||||
import cn.apes.cloud.service.impl.UserPreferenceServiceImpl;
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.commons.auth.Login;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 用户个性化配置控制器
|
||||
*
|
||||
* @author OpenClaw
|
||||
* @since 2026-08-06
|
||||
*/
|
||||
@RestController
|
||||
@TenantSource
|
||||
@RequestMapping("/userPreference")
|
||||
public class UserPreferenceController {
|
||||
|
||||
@Resource
|
||||
private UserPreferenceServiceImpl userPreferenceService;
|
||||
|
||||
/**
|
||||
* 查询指定用户的个性化配置
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - data: 个性化配置对象(未配置时返回默认值 uiSize=2)
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/get")
|
||||
public Res getUserPreference(@RequestParam Long userId) {
|
||||
return userPreferenceService.getUserPreference(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录用户的个性化配置
|
||||
*
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - data: 当前用户的个性化配置对象(未配置时返回默认值 uiSize=2)
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/mine")
|
||||
public Res getCurrentUserPreference() {
|
||||
return userPreferenceService.getCurrentUserPreference();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户个性化配置
|
||||
*
|
||||
* @param preference 配置对象
|
||||
* - userId: 用户ID(必填)
|
||||
* - uiSize: UI尺寸 1-最大 2-中等 3-最小(必填)
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - msg: 操作结果消息
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/add")
|
||||
public Res addUserPreference(@RequestBody UserPreference preference) {
|
||||
return userPreferenceService.addUserPreference(preference);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户个性化配置
|
||||
*
|
||||
* @param preference 配置对象
|
||||
* - userId: 用户ID(必填)
|
||||
* - uiSize: UI尺寸 1-最大 2-中等 3-最小(必填)
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - msg: 操作结果消息
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/update")
|
||||
public Res updateUserPreference(@RequestBody UserPreference preference) {
|
||||
return userPreferenceService.updateUserPreference(preference);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存当前登录用户的个性化配置(不存在则新增,已存在则更新)
|
||||
*
|
||||
* @param preference 配置对象
|
||||
* - uiSize: UI尺寸 1-最大 2-中等 3-最小(必填)
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - msg: 操作结果消息
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/save")
|
||||
public Res saveCurrentUserPreference(@RequestBody UserPreference preference) {
|
||||
return userPreferenceService.saveCurrentUserPreference(preference);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户个性化配置(逻辑删除)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return Res 响应对象
|
||||
* - code: 状态码,1表示成功
|
||||
* - msg: 操作结果消息
|
||||
*/
|
||||
@Login
|
||||
@PostMapping("/delete")
|
||||
public Res deleteUserPreference(@RequestParam Long userId) {
|
||||
return userPreferenceService.deleteUserPreference(userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppSearchDTO extends PageDTO {
|
||||
private String appName;
|
||||
private String appKey;
|
||||
private Boolean userVisible;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CustomerSearchDTO extends PageDTO{
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EnterpriseCertifyDTO {
|
||||
/** 企业名称 */
|
||||
private String customerName;
|
||||
/** 企业LOGO */
|
||||
private String logo;
|
||||
/** 企业简称 */
|
||||
private String shortName;
|
||||
/** 主体类型 1.个人 2.企业 3.个体户 4.政府 */
|
||||
private Integer customerType;
|
||||
/** 营业执照号/证件号 */
|
||||
private String customerIdNumber;
|
||||
/** 法人姓名 */
|
||||
private String legalName;
|
||||
/** 法人身份证正面 */
|
||||
private String legalIdFront;
|
||||
/** 法人身份证反面 */
|
||||
private String legalIdBack;
|
||||
/** 负责人姓名 */
|
||||
private String adminName;
|
||||
/** 负责人手机 */
|
||||
private String adminPhone;
|
||||
/** 负责人证件号 */
|
||||
private String adminIdNumber;
|
||||
/** 负责人身份证正面 */
|
||||
private String responsibleIdFront;
|
||||
/** 负责人身份证反面 */
|
||||
private String responsibleIdBack;
|
||||
/** 行业(一级) */
|
||||
private String industry;
|
||||
/** 行业(二级细分) */
|
||||
private String industrySub;
|
||||
/** 销售渠道 */
|
||||
private String salesChannel;
|
||||
/** 行业类型 */
|
||||
private String industryType;
|
||||
/** 省份 */
|
||||
private String province;
|
||||
/** 城市 */
|
||||
private String city;
|
||||
/** 营业执照 */
|
||||
private String businessLicense;
|
||||
|
||||
/**
|
||||
* Token from login response
|
||||
*/
|
||||
private String token;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginDTO {
|
||||
String phone;
|
||||
String password;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PageDTO {
|
||||
Integer pageIndex;
|
||||
Integer pageSize;
|
||||
|
||||
|
||||
Integer page;
|
||||
Integer perPage;
|
||||
|
||||
public IPage getPage() {
|
||||
if (page != null && perPage != null) {
|
||||
return new Page(page, perPage);
|
||||
}
|
||||
if (pageIndex != null && pageSize != null) {
|
||||
return new Page(pageIndex, pageSize);
|
||||
}
|
||||
return new Page(1, 10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PwdDTO {
|
||||
String oldPwd;
|
||||
String pwd1;
|
||||
String pwd2;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RegisterDTO {
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String phone;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class RelationDTO {
|
||||
String fieldName;
|
||||
Long fieldId;
|
||||
List<Long> dataIds =new ArrayList<>();
|
||||
List<JSONObject> dataList;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
public class RoleSearchDTO extends PageDTO{
|
||||
Long userNo;
|
||||
String appName;
|
||||
Set<String> appNames;
|
||||
Long planId;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SelectCustomerDTO {
|
||||
String token;
|
||||
Long customerId;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysRole;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* description
|
||||
*
|
||||
* @date 2024/7/9 09:44
|
||||
*/
|
||||
@Data
|
||||
public class SysRoleDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String appName;
|
||||
|
||||
private List<SysRole> SysRoleList;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserSearchDTO extends PageDTO{
|
||||
String nickName;
|
||||
String phone;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class AppInfo {
|
||||
@TableId
|
||||
private String appKey;
|
||||
private String appIcon;
|
||||
private String appName;
|
||||
private String appShortName;
|
||||
private String appType;
|
||||
private String remark;
|
||||
private Boolean userVisible;
|
||||
private String huobanSpaceId; // 伙伴云工作区ID
|
||||
private String huobanSpaceGroupId; // 伙伴云工作区用户组ID
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
@TableLogic
|
||||
private Boolean isDel;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class CustomerApp extends DbEntity implements Serializable {
|
||||
|
||||
private Long customerId;
|
||||
|
||||
private String appKey;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class CustomerInfo extends DbEntity implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客户类型 1.个人 2.企业 3.个体户 4.政府
|
||||
*/
|
||||
private Integer customerType;
|
||||
|
||||
/**
|
||||
* 客户名称
|
||||
*/
|
||||
private String customerName;
|
||||
|
||||
/**
|
||||
* 客户LOGO图片URL
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 客户名称
|
||||
*/
|
||||
private String shortName;
|
||||
|
||||
/**
|
||||
* 证件号,确保唯一性并不允许空值。
|
||||
*/
|
||||
private String customerIdNumber;
|
||||
|
||||
/**
|
||||
* 企业状态:0=待审核,1=使用中,3=已注销,4=暂停服务,5=审核拒绝
|
||||
*/
|
||||
private Integer customerStatus;
|
||||
|
||||
/**
|
||||
* 审核拒绝原因
|
||||
*/
|
||||
private String auditRemark;
|
||||
|
||||
/**
|
||||
* 审核时间
|
||||
*/
|
||||
private java.util.Date auditTime;
|
||||
|
||||
/**
|
||||
* 管理员姓名,不允许空值。
|
||||
*/
|
||||
private String adminName;
|
||||
|
||||
/**
|
||||
* 管理员手机号,不允许空值。
|
||||
*/
|
||||
private String adminPhone;
|
||||
|
||||
/**
|
||||
* 管理员证件号,确保唯一性并不允许空值。
|
||||
*/
|
||||
private String adminIdNumber;
|
||||
|
||||
// ========== 资质管理 ==========
|
||||
|
||||
/**
|
||||
* 营业执照图片URL
|
||||
*/
|
||||
private String businessLicense;
|
||||
|
||||
/**
|
||||
* 法人姓名
|
||||
*/
|
||||
private String legalName;
|
||||
|
||||
/**
|
||||
* 法人身份证正面图片URL
|
||||
*/
|
||||
private String legalIdFront;
|
||||
|
||||
/**
|
||||
* 法人身份证反面图片URL
|
||||
*/
|
||||
private String legalIdBack;
|
||||
|
||||
/**
|
||||
* 负责人身份证正面图片URL
|
||||
*/
|
||||
private String responsibleIdFront;
|
||||
|
||||
/**
|
||||
* 负责人身份证反面图片URL
|
||||
*/
|
||||
private String responsibleIdBack;
|
||||
|
||||
// ========== 行业 / 区域 / 渠道 ==========
|
||||
|
||||
/**
|
||||
* 行业(一级)
|
||||
*/
|
||||
private String industry;
|
||||
|
||||
/**
|
||||
* 行业(二级细分)
|
||||
*/
|
||||
private String industrySub;
|
||||
|
||||
/**
|
||||
* 销售渠道
|
||||
*/
|
||||
private String salesChannel;
|
||||
|
||||
/**
|
||||
* 行业类型:供应商/加工商/经销商/零售商
|
||||
*/
|
||||
private String industryType;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
private String province;
|
||||
|
||||
/**
|
||||
* 城市
|
||||
*/
|
||||
private String city;
|
||||
|
||||
/**
|
||||
* 关联套餐列表(非数据库字段)
|
||||
*/
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private List<SysPackagePlan> plans;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("customer_package")
|
||||
public class CustomerPackage extends DbEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 客户ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 套餐ID
|
||||
*/
|
||||
private Long planId;
|
||||
|
||||
/**
|
||||
* 到期时间
|
||||
*/
|
||||
private Date expireTime;
|
||||
|
||||
/**
|
||||
* 套餐名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String planName;
|
||||
|
||||
/**
|
||||
* 套餐级别(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer planLevel;
|
||||
|
||||
/**
|
||||
* 收费模式(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String chargeMode;
|
||||
|
||||
/**
|
||||
* 金额(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private java.math.BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("customer_package_extend_apply")
|
||||
public class CustomerPackageExtendApply extends DbEntity {
|
||||
|
||||
/** 客户ID */
|
||||
private Long customerId;
|
||||
|
||||
/** 套餐ID */
|
||||
private Long planId;
|
||||
|
||||
/** 申请用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 联系电话 */
|
||||
private String contactPhone;
|
||||
|
||||
/** 延期原因 */
|
||||
private String reason;
|
||||
|
||||
/** 申请延期天数 */
|
||||
private Integer applyDays;
|
||||
|
||||
/** 状态:0-申请中 1-已调整 2-已拒绝 */
|
||||
private Integer status;
|
||||
|
||||
/** 操作人ID(同意/拒绝的人) */
|
||||
private Long operatorId;
|
||||
|
||||
/** 操作人姓名 */
|
||||
private String operatorName;
|
||||
|
||||
/** 操作时间 */
|
||||
private java.util.Date operateTime;
|
||||
|
||||
/** 申请时间 */
|
||||
private java.util.Date applyTime;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@TableName("customer_package_quota")
|
||||
public class CustomerPackageQuota extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 客户套餐关联ID
|
||||
*/
|
||||
private Long customerPackageId;
|
||||
|
||||
/**
|
||||
* 配额模板ID
|
||||
*/
|
||||
private Long quotaId;
|
||||
|
||||
/**
|
||||
* 应用标识
|
||||
*/
|
||||
private String appKey;
|
||||
|
||||
/**
|
||||
* 配额编码
|
||||
*/
|
||||
private String quotaCode;
|
||||
|
||||
/**
|
||||
* 配额名称
|
||||
*/
|
||||
private String quotaName;
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType;
|
||||
|
||||
/**
|
||||
* 配额值
|
||||
*/
|
||||
private String quotaValue;
|
||||
|
||||
/**
|
||||
* 应用名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 单位(非数据库字段,来自sys_quota)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 重置周期(非数据库字段,来自sys_quota)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String resetCycle;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 客户配额变更日志
|
||||
*/
|
||||
@Data
|
||||
@TableName("customer_quota_change_log")
|
||||
public class CustomerQuotaChangeLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 客户套餐关联ID
|
||||
*/
|
||||
private Long customerPackageId;
|
||||
|
||||
/**
|
||||
* 配额编码
|
||||
*/
|
||||
private String quotaCode;
|
||||
|
||||
/**
|
||||
* 配额名称
|
||||
*/
|
||||
private String quotaName;
|
||||
|
||||
/**
|
||||
* 变更类型:1=增加,2=减少
|
||||
*/
|
||||
private Integer changeType;
|
||||
|
||||
/**
|
||||
* 变更数量
|
||||
*/
|
||||
private Integer changeAmount;
|
||||
|
||||
/**
|
||||
* 变更前值
|
||||
*/
|
||||
private String oldValue;
|
||||
|
||||
/**
|
||||
* 变更后值
|
||||
*/
|
||||
private String newValue;
|
||||
|
||||
/**
|
||||
* 变更原因
|
||||
*/
|
||||
private String reason;
|
||||
|
||||
/**
|
||||
* 操作人ID
|
||||
*/
|
||||
private Long operatorId;
|
||||
|
||||
/**
|
||||
* 操作人姓名
|
||||
*/
|
||||
private String operatorName;
|
||||
|
||||
/**
|
||||
* 操作时间
|
||||
*/
|
||||
private Date operateTime;
|
||||
|
||||
/**
|
||||
* 客户名称(非数据库字段,用于展示)
|
||||
*/
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String customerName;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class CustomerUser extends DbEntity implements Serializable {
|
||||
|
||||
private long userId;
|
||||
|
||||
private long customerId;
|
||||
|
||||
/** 所属组织ID */
|
||||
private Long orgId;
|
||||
|
||||
/** 姓名 */
|
||||
private String name;
|
||||
|
||||
/** 职称 */
|
||||
private String title;
|
||||
|
||||
/** 岗位 */
|
||||
private String position;
|
||||
|
||||
/** 应用ID集合(逗号分隔) */
|
||||
private String appIds;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SsoConfig extends DbEntity implements Serializable {
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long userId; // 用户ID
|
||||
private Long customerId;
|
||||
//伙伴云配置
|
||||
private String huobanMobile; // 伙伴云绑定手机号
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long huobanCompanyId; // 伙伴云公司ID
|
||||
private String huobanName; // 伙伴云用户名
|
||||
private Integer huobanStatus;
|
||||
private Long huobanUserId; // 伙伴云用户ID
|
||||
private String huobanUserName; // 伙伴云用户名(搜索返回的name)
|
||||
private String huobanAvatar; // 伙伴云用户头像
|
||||
|
||||
//交易平台配置
|
||||
private String paymentUserName;
|
||||
private String paymentPassword;
|
||||
private Integer paymentGroup;
|
||||
private Integer paymentStatus;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 外部系统调用用的 AccessToken 表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysAccessToken extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Token 值(明文存储)
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 名称,用于管理识别
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所属客户(企业)ID
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 接口范围:* 表示全部,否则为逗号分隔的 Ant 路径
|
||||
*/
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* IP 白名单,多个用逗号分隔,为空表示不限制
|
||||
*/
|
||||
private String whitelistIps;
|
||||
|
||||
/**
|
||||
* 状态 1=启用 2=停用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 过期时间,NULL 表示永不过期
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date expireTime;
|
||||
|
||||
/**
|
||||
* 最后使用时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date lastUsedTime;
|
||||
|
||||
/**
|
||||
* 最后使用 IP
|
||||
*/
|
||||
private String lastUsedIp;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long createBy;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SysMemberRole extends DbEntity implements Serializable {
|
||||
|
||||
|
||||
private String appName;
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 账号id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色附加数据 一般用于子账号保存主账号userno
|
||||
*/
|
||||
private String roleData;
|
||||
|
||||
/**
|
||||
* 角色所属客户(企业),系统角色为0
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author
|
||||
* @description sys_menu
|
||||
* @date 2023-06-29
|
||||
*/
|
||||
@Data
|
||||
public class SysMenu extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 菜单名称
|
||||
*/
|
||||
|
||||
private String menuTitle;
|
||||
|
||||
/**
|
||||
* 菜单路径
|
||||
*/
|
||||
private String menuPath;
|
||||
|
||||
/**
|
||||
* 菜单类型 1.vue菜单2.伙伴云菜单 3.交易系统菜单
|
||||
*/
|
||||
private Integer menuType;
|
||||
|
||||
private String configJson;
|
||||
|
||||
@TableField(exist = false)
|
||||
private JSONObject config;
|
||||
|
||||
private String vuePath;
|
||||
private String vueName;
|
||||
|
||||
private Long amisId;
|
||||
/**
|
||||
* 菜单图片
|
||||
*/
|
||||
private String menuIcon;
|
||||
|
||||
/**
|
||||
* 父级id 根为0
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 平台类型
|
||||
*/
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 对应的权限code
|
||||
*/
|
||||
private String permissionCode;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String remark;
|
||||
/**
|
||||
* 低版本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String lowVersion;
|
||||
/**
|
||||
* 高版本
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String highVersion;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private boolean hidden;
|
||||
|
||||
/**
|
||||
* 是否在看板显示
|
||||
*/
|
||||
private Boolean showOnBoard;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<SysMenu> child;
|
||||
|
||||
public SysMenu() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 操作日志表
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_operation_log")
|
||||
public class SysOperationLog {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 用户名 */
|
||||
private String userName;
|
||||
|
||||
/** 租户/企业ID */
|
||||
private Long customerId;
|
||||
|
||||
/** 企业名称 */
|
||||
private String customerName;
|
||||
|
||||
/** 模块名称 */
|
||||
private String module;
|
||||
|
||||
/** 操作名称 */
|
||||
private String action;
|
||||
|
||||
/** 日志说明 */
|
||||
private String description;
|
||||
|
||||
/** IP地址 */
|
||||
private String ip;
|
||||
|
||||
/** 浏览器/设备信息 */
|
||||
private String userAgent;
|
||||
|
||||
/** 登录地址(预留) */
|
||||
private String loginLocation;
|
||||
|
||||
/** 请求方法 */
|
||||
private String requestMethod;
|
||||
|
||||
/** 请求URL */
|
||||
private String requestUrl;
|
||||
|
||||
/** 请求参数 */
|
||||
private String requestParams;
|
||||
|
||||
/** 操作时间 */
|
||||
private Date operateTime;
|
||||
|
||||
private String createBy;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组织表
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_organization")
|
||||
public class SysOrganization {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 租户ID */
|
||||
private Long customerId;
|
||||
|
||||
/** 组织名称 */
|
||||
private String orgName;
|
||||
|
||||
/** 上级组织ID,根节点为0 */
|
||||
private Long parentId;
|
||||
|
||||
/** 组织类型 */
|
||||
private String orgType;
|
||||
|
||||
/** 组织说明 */
|
||||
private String description;
|
||||
|
||||
/** 排序 */
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 状态 1启用/0停用 */
|
||||
private Integer status;
|
||||
|
||||
/** 逻辑删除 0正常/1删除 */
|
||||
private Integer isDel;
|
||||
|
||||
private String createBy;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private String updateBy;
|
||||
|
||||
private Date updateTime;
|
||||
|
||||
/** 子节点列表(非数据库字段) */
|
||||
@TableField(exist = false)
|
||||
private List<SysOrganization> children;
|
||||
|
||||
/** 父级名称(非数据库字段) */
|
||||
@TableField(exist = false)
|
||||
private String parentName;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysPackagePlan extends DbEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
private String planName;
|
||||
|
||||
/**
|
||||
* 套餐级别: 1/2/3
|
||||
*/
|
||||
private Integer planLevel;
|
||||
|
||||
/**
|
||||
* 套餐说明
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 收费模式: monthly/yearly
|
||||
*/
|
||||
private String chargeMode;
|
||||
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private java.math.BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 状态: 1启用 0停用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 图标URL
|
||||
*/
|
||||
private String iconUrl;
|
||||
|
||||
/**
|
||||
* 应用ID集合,逗号分隔
|
||||
*/
|
||||
private String appIds;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("sys_package_plan_permission")
|
||||
public class SysPackagePlanPermission implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 套餐ID
|
||||
*/
|
||||
private Long planId;
|
||||
|
||||
/**
|
||||
* 应用Key
|
||||
*/
|
||||
private String appKey;
|
||||
|
||||
/**
|
||||
* 权限ID
|
||||
*/
|
||||
private Long permissionId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@TableName("sys_package_plan_quota")
|
||||
public class SysPackagePlanQuota extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐ID
|
||||
*/
|
||||
private Long planId;
|
||||
|
||||
/**
|
||||
* 配额模板ID
|
||||
*/
|
||||
private Long quotaId;
|
||||
|
||||
/**
|
||||
* 配额值
|
||||
*/
|
||||
private String quotaValue;
|
||||
|
||||
/**
|
||||
* 配额名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String quotaName;
|
||||
|
||||
/**
|
||||
* 配额编码(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String quotaCode;
|
||||
|
||||
/**
|
||||
* 数据类型(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String dataType;
|
||||
|
||||
/**
|
||||
* 应用标识(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String appKey;
|
||||
|
||||
/**
|
||||
* 应用名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 最大配额(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Long maxQuota;
|
||||
|
||||
/**
|
||||
* 最大配额值-小数(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private java.math.BigDecimal maxQuotaValue;
|
||||
|
||||
/**
|
||||
* 枚举值(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String enumValues;
|
||||
|
||||
/**
|
||||
* 单位(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 重置周期(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String resetCycle;
|
||||
|
||||
/**
|
||||
* 默认值(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 是否已在当前套餐中配置(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Boolean configured;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description sys_permission
|
||||
* @author zhengkai.blog.csdn.net
|
||||
* @date 2023-06-29
|
||||
*/
|
||||
@Data
|
||||
public class SysPermission extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 权限名称
|
||||
*/
|
||||
private String permissionName;
|
||||
|
||||
/**
|
||||
* 权限code
|
||||
*/
|
||||
private String permissionCode;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 父级id 根为0
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 平台类型
|
||||
*/
|
||||
private String appName;
|
||||
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<SysPermission> child;
|
||||
|
||||
|
||||
public SysPermission() {}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SysQuota extends DbEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 配额名称
|
||||
*/
|
||||
private String quotaName;
|
||||
|
||||
/**
|
||||
* 标识编码
|
||||
*/
|
||||
private String quotaCode;
|
||||
|
||||
/**
|
||||
* 数据类型: integer/decimal/boolean/enum
|
||||
*/
|
||||
private String dataType;
|
||||
|
||||
/**
|
||||
* 最大配额(整数类型)
|
||||
*/
|
||||
private Long maxQuota;
|
||||
|
||||
/**
|
||||
* 最大配额单位(整数类型)
|
||||
*/
|
||||
private String maxQuotaUnit;
|
||||
|
||||
/**
|
||||
* 最大配额值(小数类型)
|
||||
*/
|
||||
private java.math.BigDecimal maxQuotaValue;
|
||||
|
||||
/**
|
||||
* 单位(小数类型)
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 枚举值,JSON数组格式
|
||||
*/
|
||||
private String enumValues;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 重置周期: none/daily/weekly/monthly/yearly
|
||||
*/
|
||||
private String resetCycle;
|
||||
|
||||
/**
|
||||
* 是否显示: 1显示 0隐藏
|
||||
*/
|
||||
private Integer isVisible;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 关联应用标识
|
||||
*/
|
||||
private String appKey;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SysRole extends DbEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
private String roleName;
|
||||
|
||||
/**
|
||||
* 角色标识
|
||||
*/
|
||||
private String roleKey;
|
||||
|
||||
/**
|
||||
* 角色所属用户,系统角色为0
|
||||
*/
|
||||
private Long userNo;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 所属套餐ID
|
||||
*/
|
||||
private Long planId;
|
||||
|
||||
/**
|
||||
* @deprecated 已废弃,角色不再直接关联应用,改为通过套餐关联
|
||||
* 保留该字段是为了兼容存量数据
|
||||
*/
|
||||
@Deprecated
|
||||
private String appName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private cn.apes.cloud.domain.entity.SysPackagePlan planInfo;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @description 角色权限表
|
||||
* @author zhengkai.blog.csdn.net
|
||||
* @date 2023-06-29
|
||||
*/
|
||||
@Data
|
||||
public class SysRolePermission extends DbEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 权限id
|
||||
*/
|
||||
private Long permissionId;
|
||||
|
||||
/**
|
||||
* 应用Key
|
||||
*/
|
||||
private String appKey;
|
||||
|
||||
public SysRolePermission() {}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import cn.apes.commons.domain.DbEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户信息实体类
|
||||
*
|
||||
* @author [你的名字]
|
||||
* @since [创建时间]
|
||||
*/
|
||||
@Data
|
||||
|
||||
public class UserInfo extends DbEntity implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 用户头像链接
|
||||
*/
|
||||
private String portrait;
|
||||
|
||||
/**
|
||||
* 用户手机号码
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 备用邮箱
|
||||
*/
|
||||
private String backupEmail;
|
||||
|
||||
/**
|
||||
* 用户密码(加密存储)
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 用户状态(1.正常 2.禁止登录)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 用户备注信息
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
List<CustomerInfo> customerList;
|
||||
@TableField(exist = false)
|
||||
List<SysRole> roles;
|
||||
@TableField(exist = false)
|
||||
|
||||
private Integer paymentStatus;
|
||||
@TableField(exist = false)
|
||||
|
||||
private Integer huobanStatus;
|
||||
@TableField(exist = false)
|
||||
private Date bindTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.apes.cloud.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户个性化配置实体类
|
||||
* <p>
|
||||
* 注意:该表以 user_id 作为主键(无自增 id 列),因此不继承 DbEntity,
|
||||
* 避免父类 id 字段映射到不存在的列。
|
||||
*
|
||||
* @author OpenClaw
|
||||
* @since 2026-08-06
|
||||
*/
|
||||
@Data
|
||||
@TableName("user_preference")
|
||||
public class UserPreference {
|
||||
|
||||
/**
|
||||
* 用户ID(主键)
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* UI尺寸 1-最大 2-中等 3-最小
|
||||
*/
|
||||
private Integer uiSize;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除 0-正常 1-删除
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer isDel;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BulkDel {
|
||||
private String tableId;
|
||||
private List<Long> itemIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class CategoryConfig {
|
||||
private List<Option> options;
|
||||
private int isMulti;
|
||||
private int isTile;
|
||||
|
||||
@Data
|
||||
public static class Option {
|
||||
private String name;
|
||||
private Integer id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DataCreate {
|
||||
|
||||
public DataCreate() {
|
||||
|
||||
}
|
||||
|
||||
public DataCreate(Long tableId, JSONObject fields) {
|
||||
setFields(fields);
|
||||
setTableId(tableId);
|
||||
}
|
||||
|
||||
private Long tableId;
|
||||
private String tableName;
|
||||
|
||||
private JSONObject fields;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DataFilter {
|
||||
|
||||
public DataFilter() {
|
||||
|
||||
}
|
||||
|
||||
public DataFilter(Long tableId) {
|
||||
setTableId(tableId);
|
||||
setRelations(new ArrayList<>());
|
||||
}
|
||||
|
||||
private Long tableId;
|
||||
private String tableName;
|
||||
|
||||
private String orderField;
|
||||
private String orderType;
|
||||
|
||||
private Integer limit;
|
||||
private Integer offset;
|
||||
|
||||
private Object filter;
|
||||
|
||||
private List<String> relations;
|
||||
|
||||
List<DataFilterCondition> conditions = new ArrayList<>();
|
||||
|
||||
List<TableSub> subTables;
|
||||
|
||||
public void addSubTable(String tableName,Long tableId,String tableField) {
|
||||
if (subTables == null) {
|
||||
subTables = new ArrayList<>();
|
||||
}
|
||||
TableSub tableSub = new TableSub();
|
||||
tableSub.setTableId(tableId);
|
||||
tableSub.setTableName(tableName);
|
||||
tableSub.setTableField(tableField);
|
||||
subTables.add(tableSub);
|
||||
}
|
||||
|
||||
public void addCondition(String filedName, String oper, Object value) {
|
||||
DataFilterCondition condition = new DataFilterCondition();
|
||||
condition.setValue(value);
|
||||
condition.setFieldName(filedName);
|
||||
condition.setOperator(oper);
|
||||
if (conditions == null) {
|
||||
conditions = new ArrayList<DataFilterCondition>();
|
||||
}
|
||||
conditions.add(condition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DataFilterCondition {
|
||||
|
||||
public DataFilterCondition() {
|
||||
|
||||
}
|
||||
|
||||
public DataFilterCondition(String fieldName, String operator, Object value) {
|
||||
setFieldName(fieldName);
|
||||
setOperator(operator);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
private String fieldName;
|
||||
private Object value;
|
||||
|
||||
private String operator;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DataUpdate {
|
||||
public DataUpdate(){
|
||||
|
||||
}
|
||||
private Long tableId;
|
||||
private String tableName;
|
||||
|
||||
private Long itemId;
|
||||
|
||||
public DataUpdate(Long tableId, Long itemId,JSONObject fields) {
|
||||
setTableId(tableId);
|
||||
setItemId(itemId);
|
||||
setFields(fields);
|
||||
}
|
||||
|
||||
private JSONObject fields;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
public class DataUpsert {
|
||||
public DataUpsert(){
|
||||
|
||||
}
|
||||
public DataUpsert(Long tableId,String... _updateFields){
|
||||
setTableId(tableId);
|
||||
setUpdateFields(Arrays.asList(_updateFields));
|
||||
items = new ArrayList<>();
|
||||
}
|
||||
public DataUpsert(Long tableId,List<JSONObject> dataItems,String... _updateFields){
|
||||
setTableId(tableId);
|
||||
setUpdateFields(Arrays.asList(_updateFields));
|
||||
setItems(dataItems);
|
||||
}
|
||||
public void addItem(JSONObject data){
|
||||
items.add(data);
|
||||
}
|
||||
private Long tableId;
|
||||
private List<String> updateFields;
|
||||
private List<JSONObject> items;
|
||||
private String tableName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@TableName("huoban_table_column")
|
||||
@Data
|
||||
public class TableColumn {
|
||||
@TableId
|
||||
@JSONField(name = "field_id")
|
||||
private Long fieldId;
|
||||
private Long relationFieldId;
|
||||
|
||||
private Long tableId;
|
||||
private Long spaceId;
|
||||
|
||||
private String name;
|
||||
private String alias;
|
||||
private String formName;
|
||||
private String groupName;
|
||||
@JSONField(name = "field_type")
|
||||
private String fieldType;
|
||||
@JSONField(name = "data_type")
|
||||
private String dataType;
|
||||
private Boolean required;
|
||||
private String description;
|
||||
private String columnConfig;
|
||||
private Integer relationField;
|
||||
private Integer canAdd;
|
||||
private Integer canEdit;
|
||||
private String defaultValue;
|
||||
private Integer sortValue;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("huoban_table_info")
|
||||
@Data
|
||||
public class TableInfo {
|
||||
@TableId
|
||||
@JSONField(name = "table_id")
|
||||
private Long tableId;
|
||||
private String name;
|
||||
private String formName;
|
||||
private String showName;
|
||||
private String groupConfig;
|
||||
private String addButton;
|
||||
private String editButton;
|
||||
private String alias;
|
||||
@JSONField(name = "space_id")
|
||||
private Long spaceId;
|
||||
@JSONField(name = "created_on")
|
||||
private Date createdOn;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TableSub {
|
||||
private String tableName;
|
||||
private Long tableId;
|
||||
private String tableField;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.apes.cloud.domain.huoban;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class UpsertOne {
|
||||
public UpsertOne() {
|
||||
|
||||
}
|
||||
public UpsertOne(Long tableId, JSONObject fields) {
|
||||
setFields(fields);
|
||||
setTableId(tableId);
|
||||
}
|
||||
|
||||
private Long tableId;
|
||||
private String tableName;
|
||||
|
||||
private JSONObject fields;
|
||||
|
||||
private List<String> updateFields;
|
||||
|
||||
/**
|
||||
* 操作 one_update 发现一条数据更新,zero_create 未找到数据新增数据,one_none 有数据时不执行任何操作
|
||||
*/
|
||||
private String action;
|
||||
|
||||
public DataCreate getDataCreate() {
|
||||
DataCreate dataCreate = new DataCreate();
|
||||
dataCreate.setTableId(tableId);
|
||||
dataCreate.setTableName(tableName);
|
||||
dataCreate.setFields(fields);
|
||||
return dataCreate;
|
||||
}
|
||||
|
||||
public DataUpdate getDataUpdate(Long itemId) {
|
||||
DataUpdate dataUpdate = new DataUpdate();
|
||||
dataUpdate.setTableId(tableId);
|
||||
dataUpdate.setTableName(tableName);
|
||||
dataUpdate.setFields(fields);
|
||||
dataUpdate.setItemId(itemId);
|
||||
return dataUpdate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.apes.cloud.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CustomerAppVO implements Serializable {
|
||||
|
||||
private String appKey;
|
||||
private String appName;
|
||||
private String appShortName;
|
||||
private String appIcon;
|
||||
/**
|
||||
* 应用类型: basic=基础, internal=内部, paid=付费
|
||||
*/
|
||||
private String appType;
|
||||
private String remark;
|
||||
private Integer userVisible;
|
||||
private Date createTime;
|
||||
/**
|
||||
* 应用来源: package=套餐包含, app=客户直接关联
|
||||
*/
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 是否过期(仅 source=package 时有效)
|
||||
*/
|
||||
private Boolean expired;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.apes.cloud.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CustomerPackageExtendApplyVO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private Long customerId;
|
||||
private String customerName;
|
||||
private String shortName;
|
||||
private String adminPhone;
|
||||
private Long planId;
|
||||
private String planName;
|
||||
private Long userId;
|
||||
private String contactPhone;
|
||||
private String reason;
|
||||
private Integer applyDays;
|
||||
private Date applyTime;
|
||||
private Integer status;
|
||||
private String statusText;
|
||||
private Long operatorId;
|
||||
private String operatorName;
|
||||
private Date operateTime;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.apes.cloud.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CustomerPackageVO implements Serializable {
|
||||
|
||||
private Long customerId;
|
||||
private String shortName;
|
||||
private String customerName;
|
||||
private String adminPhone;
|
||||
private Long packageId;
|
||||
private Long planId;
|
||||
private String planName;
|
||||
private Date expireTime;
|
||||
/** 剩余天数(负数表示已过期) */
|
||||
private Long remainingDays;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package cn.apes.cloud.filter;
|
||||
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.LoginCustomer;
|
||||
import cn.apes.commons.auth.LoginUser;
|
||||
import cn.apes.commons.auth.UserSession;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.SysAccessToken;
|
||||
import cn.apes.cloud.service.impl.CustomerInfoServiceImpl;
|
||||
import cn.apes.cloud.service.SysAccessTokenService;
|
||||
import cn.apes.cloud.util.OperationLogUtil;
|
||||
import cn.apes.commons.Res;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.redisson.api.RBucket;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* AccessToken 校验过滤器
|
||||
*
|
||||
* 逻辑:
|
||||
* 1. 检查请求头是否携带 X-Access-Token 或 Authorization: Bearer <token>
|
||||
* 2. 如果有,走 AccessToken 校验逻辑
|
||||
* 3. 校验通过则:
|
||||
* - 将 Redis 数据写入 Redis(user + customer),使后续 @Login AOP 能正常读取
|
||||
* - 包装 request,将 token 注入 "token" header,使 @Login AOP 能取到
|
||||
* 4. 校验失败返回 401
|
||||
* 5. 如果没有携带 Token,放行,交给后续的 @Login AOP 处理
|
||||
*/
|
||||
@Component
|
||||
public class AccessTokenFilter implements Filter {
|
||||
|
||||
@Autowired
|
||||
private SysAccessTokenService accessTokenService;
|
||||
|
||||
@Autowired
|
||||
private CustomerInfoServiceImpl customerInfoService;
|
||||
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
String token = extractToken(request);
|
||||
|
||||
if (token != null && !token.isEmpty()) {
|
||||
// 有 Token → 校验
|
||||
String clientIp = getClientIp(request);
|
||||
SysAccessToken record = accessTokenService.validate(token, clientIp);
|
||||
|
||||
if (record == null) {
|
||||
// 无效 Token → 返回 401
|
||||
String method = request.getMethod();
|
||||
String uri = request.getRequestURI();
|
||||
OperationLogUtil.logDirect(0L, "外部系统", null, null, "AccessToken", "调用失败(无效Token)",
|
||||
method + " " + uri, clientIp, request.getHeader("User-Agent"));
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().write(JSON.toJSONString(Res.fail("无效或已失效的 AccessToken")));
|
||||
return;
|
||||
}
|
||||
|
||||
// 校验通过 → 将数据写入 Redis,使 @Login AOP 能正常读取
|
||||
String redisToken = record.getToken();
|
||||
writeTokenToRedis(redisToken, record);
|
||||
|
||||
// 包装 request,注入 "token" header
|
||||
final String finalToken = redisToken;
|
||||
request = new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
if ("token".equalsIgnoreCase(name)) {
|
||||
return finalToken;
|
||||
}
|
||||
return super.getHeader(name);
|
||||
}
|
||||
@Override
|
||||
public Enumeration<String> getHeaderNames() {
|
||||
List<String> names = Collections.list(super.getHeaderNames());
|
||||
if (!names.contains("token")) {
|
||||
names.add("token");
|
||||
}
|
||||
return Collections.enumeration(names);
|
||||
}
|
||||
};
|
||||
|
||||
// 标记 AccessToken 已验证
|
||||
request.setAttribute("accessTokenVerified", true);
|
||||
request.setAttribute("accessTokenCustomerId", record.getCustomerId());
|
||||
|
||||
// 记录外部系统调用日志
|
||||
String method = request.getMethod();
|
||||
String uri = request.getRequestURI();
|
||||
String userAgent = request.getHeader("User-Agent");
|
||||
OperationLogUtil.logDirect(0L, "AccessToken:" + record.getName(), record.getCustomerId(), null,
|
||||
"AccessToken", "调用", method + " " + uri, clientIp, userAgent);
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private void writeTokenToRedis(String redisToken, SysAccessToken record) {
|
||||
try {
|
||||
// 写入用户信息 (key = token)
|
||||
// 必须使用 JSONObject 对象写入,使 JsonJacksonCodec 能正确序列化
|
||||
// 这样 LoginAspect 反序列化时才能得到 JSONObject
|
||||
JSONObject userObj = new JSONObject();
|
||||
userObj.put("id", 0L);
|
||||
userObj.put("nickName", "AccessToken:" + record.getName());
|
||||
userObj.put("phone", "");
|
||||
RBucket<JSONObject> userBucket = redissonClient.getBucket(redisToken);
|
||||
userBucket.set(userObj, 1, TimeUnit.DAYS);
|
||||
|
||||
// 查询企业信息表,获取完整企业信息
|
||||
CustomerInfo customerInfo = customerInfoService.getById(record.getCustomerId());
|
||||
|
||||
// 写入企业信息 (key = token:customer)
|
||||
JSONObject customerObj = new JSONObject();
|
||||
if (customerInfo != null) {
|
||||
customerObj.put("id", customerInfo.getId());
|
||||
customerObj.put("customerType", customerInfo.getCustomerType());
|
||||
customerObj.put("customerName", customerInfo.getCustomerName());
|
||||
customerObj.put("logo", customerInfo.getLogo());
|
||||
customerObj.put("shortName", customerInfo.getShortName());
|
||||
customerObj.put("customerIdNumber", customerInfo.getCustomerIdNumber());
|
||||
customerObj.put("customerStatus", customerInfo.getCustomerStatus());
|
||||
customerObj.put("auditRemark", customerInfo.getAuditRemark());
|
||||
customerObj.put("auditTime", customerInfo.getAuditTime());
|
||||
customerObj.put("adminName", customerInfo.getAdminName());
|
||||
customerObj.put("adminPhone", customerInfo.getAdminPhone());
|
||||
customerObj.put("adminIdNumber", customerInfo.getAdminIdNumber());
|
||||
customerObj.put("businessLicense", customerInfo.getBusinessLicense());
|
||||
customerObj.put("legalName", customerInfo.getLegalName());
|
||||
customerObj.put("legalIdFront", customerInfo.getLegalIdFront());
|
||||
customerObj.put("legalIdBack", customerInfo.getLegalIdBack());
|
||||
customerObj.put("responsibleIdFront", customerInfo.getResponsibleIdFront());
|
||||
customerObj.put("responsibleIdBack", customerInfo.getResponsibleIdBack());
|
||||
customerObj.put("industry", customerInfo.getIndustry());
|
||||
customerObj.put("industrySub", customerInfo.getIndustrySub());
|
||||
customerObj.put("salesChannel", customerInfo.getSalesChannel());
|
||||
customerObj.put("industryType", customerInfo.getIndustryType());
|
||||
customerObj.put("province", customerInfo.getProvince());
|
||||
customerObj.put("city", customerInfo.getCity());
|
||||
} else {
|
||||
customerObj.put("id", record.getCustomerId());
|
||||
customerObj.put("customerName", "");
|
||||
}
|
||||
RBucket<JSONObject> customerBucket = redissonClient.getBucket(redisToken + ":customer");
|
||||
customerBucket.set(customerObj, 1, TimeUnit.DAYS);
|
||||
} catch (Exception e) {
|
||||
// Redis 写入失败不影响主流程
|
||||
}
|
||||
}
|
||||
|
||||
private String extractToken(HttpServletRequest request) {
|
||||
// 优先取 X-Access-Token
|
||||
String token = request.getHeader("X-Access-Token");
|
||||
if (token != null && !token.isEmpty()) {
|
||||
return token;
|
||||
}
|
||||
|
||||
// 其次取 Authorization: Bearer
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||
return authHeader.substring(7).trim();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getClientIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
if (ip != null && ip.contains(",")) {
|
||||
ip = ip.split(",")[0].trim();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.AppInfo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface AppInfoMapper extends BaseMapper<AppInfo> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerApp;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface CustomerAppMapper extends BaseMapper<CustomerApp> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface CustomerInfoMapper extends BaseMapper<CustomerInfo> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageExtendApply;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CustomerPackageExtendApplyMapper extends BaseMapper<CustomerPackageExtendApply> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import java.util.Date;
|
||||
|
||||
@Mapper
|
||||
public interface CustomerPackageMapper extends BaseMapper<CustomerPackage> {
|
||||
|
||||
/**
|
||||
* 绕过 @TableLogic 查询所有记录(含软删除)
|
||||
*/
|
||||
@Select("SELECT id, customer_id, plan_id, expire_time, is_del, create_time, update_time FROM customer_package WHERE customer_id = #{customerId} AND plan_id = #{planId} ORDER BY id DESC LIMIT 1")
|
||||
CustomerPackage selectOneIgnoreLogic(@Param("customerId") Long customerId, @Param("planId") Long planId);
|
||||
|
||||
/**
|
||||
* 绕过 @TableLogic 恢复软删除记录
|
||||
*/
|
||||
@Update("UPDATE customer_package SET is_del = 0, expire_time = #{expireTime}, update_time = NOW() WHERE id = #{id}")
|
||||
int restoreRecord(@Param("id") Long id, @Param("expireTime") Date expireTime);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageQuota;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CustomerPackageQuotaMapper extends BaseMapper<CustomerPackageQuota> {
|
||||
|
||||
/**
|
||||
* 物理删除(不走逻辑删除)
|
||||
*/
|
||||
@Delete("DELETE FROM customer_package_quota WHERE customer_package_id = #{packageId}")
|
||||
int physicalDeleteByPackageId(Long packageId);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerQuotaChangeLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CustomerQuotaChangeLogMapper extends BaseMapper<CustomerQuotaChangeLog> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerUser;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface CustomerUserMapper extends BaseMapper<CustomerUser> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SsoConfig;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SsoConfigMapper extends BaseMapper<SsoConfig> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysAccessToken;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* AccessToken Mapper
|
||||
*/
|
||||
public interface SysAccessTokenMapper extends BaseMapper<SysAccessToken> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysMemberRole;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SysMemberRoleMapper extends BaseMapper<SysMemberRole> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysMenu;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SysMenuMapper extends BaseMapper<SysMenu> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysOperationLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysOperationLogMapper extends BaseMapper<SysOperationLog> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysOrganization;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysOrganizationMapper extends BaseMapper<SysOrganization> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysPackagePlanMapper extends BaseMapper<SysPackagePlan> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlanPermission;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysPackagePlanPermissionMapper extends BaseMapper<SysPackagePlanPermission> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlanQuota;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysPackagePlanQuotaMapper extends BaseMapper<SysPackagePlanQuota> {
|
||||
@org.apache.ibatis.annotations.Delete("DELETE FROM sys_package_plan_quota WHERE plan_id = #{planId}")
|
||||
int physicalDeleteByPlanId(Long planId);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPermission;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SysPermissionMapper extends BaseMapper<SysPermission> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysQuota;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysQuotaMapper extends BaseMapper<SysQuota> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysRole;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysRoleMapper extends BaseMapper<SysRole> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysRolePermission;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface SysRolePermissionMapper extends BaseMapper<SysRolePermission> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.UserInfo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface UserInfoMapper extends BaseMapper<UserInfo> {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.apes.cloud.mapper;
|
||||
|
||||
import cn.apes.cloud.domain.entity.UserPreference;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
/**
|
||||
* 用户个性化配置 Mapper接口
|
||||
*
|
||||
* @author OpenClaw
|
||||
* @since 2026-08-06
|
||||
*/
|
||||
public interface UserPreferenceMapper extends BaseMapper<UserPreference> {
|
||||
|
||||
/**
|
||||
* 更新指定用户的配置(包含已逻辑删除的行,同时恢复 is_del=0)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param uiSize UI尺寸 1-最大 2-中等 3-最小
|
||||
* @return int 影响行数,0表示该用户不存在任何记录(含已删除)
|
||||
*/
|
||||
@Update("update user_preference set ui_size = #{uiSize}, is_del = 0 where user_id = #{userId}")
|
||||
int updateIncludeDeleted(@Param("userId") Long userId, @Param("uiSize") Integer uiSize);
|
||||
|
||||
/**
|
||||
* 统计指定用户的记录数(包含已逻辑删除的行)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return int 记录数(含已删除)
|
||||
*/
|
||||
@Select("select count(1) from user_preference where user_id = #{userId}")
|
||||
int countIncludeDeleted(@Param("userId") Long userId);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import cn.apes.cloud.domain.vo.CustomerPackageVO;
|
||||
import cn.apes.cloud.domain.vo.CustomerPackageExtendApplyVO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CustomerPackageService extends IService<CustomerPackage> {
|
||||
|
||||
/**
|
||||
* 获取客户的套餐列表
|
||||
*/
|
||||
cn.apes.commons.Res getCustomerPackages(Long customerId);
|
||||
|
||||
/**
|
||||
* 为客户添加套餐
|
||||
*/
|
||||
cn.apes.commons.Res addCustomerPackage(CustomerPackage customerPackage);
|
||||
|
||||
/**
|
||||
* 编辑客户套餐
|
||||
*/
|
||||
cn.apes.commons.Res editCustomerPackage(java.util.Map<String, Object> data);
|
||||
|
||||
/**
|
||||
* 删除客户套餐
|
||||
*/
|
||||
cn.apes.commons.Res deleteCustomerPackage(Long id);
|
||||
|
||||
/**
|
||||
* 保存客户套餐配额
|
||||
*/
|
||||
cn.apes.commons.Res saveCustomerPackageQuotas(Long packageId, java.util.Map<String, Object> quotaValues);
|
||||
|
||||
/**
|
||||
* 获取客户套餐配额
|
||||
*/
|
||||
cn.apes.commons.Res getCustomerPackageQuotas(Long packageId);
|
||||
|
||||
/**
|
||||
* 获取当前客户套餐详情(含配额,用于前端展示)
|
||||
*/
|
||||
cn.apes.commons.Res getMyPackages(Long customerId);
|
||||
|
||||
/**
|
||||
* 查询所有客户的套餐概况(管理端)
|
||||
*/
|
||||
cn.apes.commons.Res getCustomerPackageOverview(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 提交套餐延期申请
|
||||
*/
|
||||
cn.apes.commons.Res submitExtendApply(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询套餐延期申请记录列表(管理端)
|
||||
*/
|
||||
cn.apes.commons.Res getExtendApplyList(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 审核延期申请(同意/拒绝)
|
||||
*/
|
||||
cn.apes.commons.Res reviewExtendApply(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 增加客户套餐额度
|
||||
*/
|
||||
cn.apes.commons.Res increaseQuota(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 减少客户套餐额度
|
||||
*/
|
||||
cn.apes.commons.Res decreaseQuota(java.util.Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 获取配额变更日志列表
|
||||
*/
|
||||
cn.apes.commons.Res getQuotaChangeLogs(java.util.Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysAccessToken;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* AccessToken Service
|
||||
*/
|
||||
public interface SysAccessTokenService extends IService<SysAccessToken> {
|
||||
|
||||
/**
|
||||
* 校验 Token 是否有效
|
||||
* @param token token 值
|
||||
* @return 匹配的 SysAccessToken,无效则返回 null
|
||||
*/
|
||||
SysAccessToken validate(String token, String clientIp);
|
||||
|
||||
/**
|
||||
* 生成新的 Token 值
|
||||
*/
|
||||
String generateToken();
|
||||
|
||||
/**
|
||||
* 撤销 Token
|
||||
*/
|
||||
void revoke(Long id);
|
||||
|
||||
/**
|
||||
* 启用 Token
|
||||
*/
|
||||
void enable(Long id);
|
||||
|
||||
/**
|
||||
* 重新生成 Token(旧 Token 立即失效)
|
||||
*/
|
||||
String regenerate(Long id);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysOperationLog;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志服务接口
|
||||
*/
|
||||
public interface SysOperationLogService {
|
||||
|
||||
/**
|
||||
* 记录操作日志(公共方法)
|
||||
*/
|
||||
void log(Long userId, String userName, Long customerId, String customerName,
|
||||
String module, String action, String description);
|
||||
|
||||
/**
|
||||
* 记录操作日志(带完整参数)
|
||||
*/
|
||||
void log(Long userId, String userName, Long customerId, String customerName,
|
||||
String module, String action, String description, String ip, String userAgent);
|
||||
|
||||
/**
|
||||
* 分页查询日志列表
|
||||
*/
|
||||
IPage<Map<String, Object>> pageLogs(int pageIndex, int pageSize,
|
||||
Long customerId, Long userId,
|
||||
String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 获取企业列表(用于下拉筛选)
|
||||
*/
|
||||
java.util.List<Map<String, Object>> listCustomers();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlanQuota;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface SysPackagePlanQuotaService extends IService<SysPackagePlanQuota> {
|
||||
|
||||
/**
|
||||
* 获取套餐的配额配置列表
|
||||
*/
|
||||
cn.apes.commons.Res getPlanQuotas(Long planId);
|
||||
|
||||
/**
|
||||
* 保存套餐的配额配置
|
||||
* @param planId 套餐ID
|
||||
* @param quotaValues Map<quotaId, quotaValue>
|
||||
*/
|
||||
cn.apes.commons.Res savePlanQuotas(Long planId, Map<Long, String> quotaValues);
|
||||
|
||||
/**
|
||||
* 获取所有配额模板 + 标记是否已在当前套餐中配置
|
||||
*/
|
||||
cn.apes.commons.Res getAllQuotas(Long planId);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface SysPackagePlanService extends IService<SysPackagePlan> {
|
||||
|
||||
/**
|
||||
* 获取套餐已分配的权限
|
||||
*/
|
||||
Map<String, List<Long>> getPlanPermissions(Long planId);
|
||||
|
||||
/**
|
||||
* 保存套餐权限关联
|
||||
*/
|
||||
cn.apes.commons.Res savePlanPermissions(Long planId, Map<String, List<Long>> appPermissions);
|
||||
|
||||
/**
|
||||
* 获取套餐关联的应用列表
|
||||
*/
|
||||
cn.apes.commons.Res getPlanApps(Long planId);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.apes.cloud.service;
|
||||
|
||||
import cn.apes.cloud.domain.entity.SysQuota;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
public interface SysQuotaService extends IService<SysQuota> {
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package cn.apes.cloud.service.impl;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.cloud.domain.dto.AppSearchDTO;
|
||||
import cn.apes.cloud.domain.entity.AppInfo;
|
||||
import cn.apes.cloud.mapper.AppInfoMapper;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
public class AppInfoServiceImpl extends ServiceImpl<AppInfoMapper, AppInfo> {
|
||||
|
||||
public Res pageApp(AppSearchDTO searchDTO) {
|
||||
LambdaQueryWrapper<AppInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotEmpty(searchDTO.getAppName()),AppInfo::getAppName, searchDTO.getAppName());
|
||||
queryWrapper.eq(StrUtil.isNotEmpty(searchDTO.getAppKey()),AppInfo::getAppKey, searchDTO.getAppKey());
|
||||
queryWrapper.eq(searchDTO.getUserVisible() != null, AppInfo::getUserVisible, searchDTO.getUserVisible());
|
||||
|
||||
IPage<AppInfo> pageData=page(searchDTO.getPage(),queryWrapper);
|
||||
return Res.success(pageData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/编辑应用
|
||||
*/
|
||||
public Res saveApp(AppInfo appInfo) {
|
||||
if (StrUtil.isEmpty(appInfo.getAppName())) {
|
||||
return Res.fail("应用名称不能为空");
|
||||
}
|
||||
if (StrUtil.isEmpty(appInfo.getAppKey())) {
|
||||
return Res.fail("应用标识不能为空");
|
||||
}
|
||||
|
||||
// 检查 appKey 是否重复(编辑时排除自身)
|
||||
AppInfo existing = getOne(new LambdaQueryWrapper<AppInfo>().eq(AppInfo::getAppKey, appInfo.getAppKey()));
|
||||
if (existing != null) {
|
||||
// appKey 已存在,判断是否是编辑
|
||||
// 如果传入的 appIcon/remark 等不同,视为编辑
|
||||
existing.setAppName(appInfo.getAppName());
|
||||
existing.setAppShortName(appInfo.getAppShortName());
|
||||
existing.setAppType(appInfo.getAppType());
|
||||
existing.setAppIcon(appInfo.getAppIcon());
|
||||
existing.setRemark(appInfo.getRemark());
|
||||
existing.setUserVisible(appInfo.getUserVisible());
|
||||
existing.setHuobanSpaceId(appInfo.getHuobanSpaceId());
|
||||
existing.setHuobanSpaceGroupId(appInfo.getHuobanSpaceGroupId());
|
||||
existing.setUpdateTime(new Date());
|
||||
updateById(existing);
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
// 新增
|
||||
appInfo.setCreateTime(new Date());
|
||||
appInfo.setUpdateTime(new Date());
|
||||
if (appInfo.getUserVisible() == null) {
|
||||
appInfo.setUserVisible(true);
|
||||
}
|
||||
save(appInfo);
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应用
|
||||
*/
|
||||
public Res deleteApp(AppInfo appInfo) {
|
||||
if (StrUtil.isEmpty(appInfo.getAppKey())) {
|
||||
return Res.fail("应用标识不能为空");
|
||||
}
|
||||
LambdaQueryWrapper<AppInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(AppInfo::getAppKey, appInfo.getAppKey());
|
||||
remove(queryWrapper);
|
||||
return Res.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package cn.apes.cloud.service.impl;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.AppInfo;
|
||||
import cn.apes.cloud.domain.entity.CustomerApp;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageQuota;
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import cn.apes.cloud.domain.vo.CustomerAppVO;
|
||||
import cn.apes.cloud.mapper.AppInfoMapper;
|
||||
import cn.apes.cloud.mapper.CustomerAppMapper;
|
||||
import cn.apes.cloud.mapper.CustomerPackageMapper;
|
||||
import cn.apes.cloud.mapper.CustomerPackageQuotaMapper;
|
||||
import cn.apes.cloud.mapper.SysPackagePlanMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import cn.apes.cloud.service.impl.CustomerInfoServiceImpl;
|
||||
import cn.apes.cloud.util.OperationLogUtil;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CustomerAppServiceImpl extends ServiceImpl<CustomerAppMapper, CustomerApp> {
|
||||
|
||||
@Autowired
|
||||
private AppInfoMapper appInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerPackageMapper customerPackageMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerPackageQuotaMapper customerPackageQuotaMapper;
|
||||
|
||||
@Autowired
|
||||
private SysPackagePlanMapper sysPackagePlanMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerInfoServiceImpl customerInfoService;
|
||||
|
||||
/**
|
||||
* 查询客户可见的应用列表(含关联时间)
|
||||
* 条件(OR):1. 已关联的应用 2. appType 为 basic(基础应用对所有用户可见)
|
||||
*/
|
||||
public List<CustomerAppVO> getApps(Long customerId) {
|
||||
return buildAppList(customerId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录客户的应用列表(含套餐来源标识)
|
||||
* 合并客户关联的应用 + 套餐包含的应用,去重后返回。
|
||||
* source 字段: "package" = 应用在套餐中存在, "app" = 仅客户关联表中存在
|
||||
*/
|
||||
public List<CustomerAppVO> getMyAppsWithSource(Long customerId) {
|
||||
return buildAppList(customerId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心构建方法
|
||||
* @param customerId 客户ID
|
||||
* @param includeSource 是否填充 source 字段
|
||||
*/
|
||||
private List<CustomerAppVO> buildAppList(Long customerId, boolean includeSource) {
|
||||
// 1. 查出客户已关联的应用 appKeys
|
||||
LambdaQueryWrapper<CustomerApp> appRelWrapper = new LambdaQueryWrapper<>();
|
||||
appRelWrapper.eq(CustomerApp::getCustomerId, customerId);
|
||||
List<CustomerApp> appRelList = list(appRelWrapper);
|
||||
Set<String> associatedKeys = appRelList.stream()
|
||||
.map(CustomerApp::getAppKey)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, CustomerApp> appRelMap = appRelList.stream()
|
||||
.collect(Collectors.toMap(CustomerApp::getAppKey, c -> c));
|
||||
|
||||
// 2. 查出客户所有生效的套餐(未删除)
|
||||
LambdaQueryWrapper<CustomerPackage> pkgWrapper = new LambdaQueryWrapper<>();
|
||||
pkgWrapper.eq(CustomerPackage::getCustomerId, customerId);
|
||||
pkgWrapper.eq(CustomerPackage::getIsDel, 0);
|
||||
List<CustomerPackage> packages = customerPackageMapper.selectList(pkgWrapper);
|
||||
|
||||
// 2.1 从套餐对应的 sys_package_plan.appIds 获取应用列表
|
||||
Map<String, Boolean> appExpiredMap = new java.util.HashMap<>();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Set<String> packageKeys = new HashSet<>();
|
||||
if (!packages.isEmpty()) {
|
||||
for (CustomerPackage pkg : packages) {
|
||||
SysPackagePlan plan = sysPackagePlanMapper.selectById(pkg.getPlanId());
|
||||
if (plan != null && plan.getAppIds() != null && !plan.getAppIds().isEmpty()) {
|
||||
boolean expired = pkg.getExpireTime() != null
|
||||
&& now.isAfter(pkg.getExpireTime().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
|
||||
String[] keys = plan.getAppIds().split(",");
|
||||
for (String k : keys) {
|
||||
String trimmed = k.trim();
|
||||
if (!trimmed.isEmpty()) {
|
||||
packageKeys.add(trimmed);
|
||||
// 只要有一个未过期的套餐包含该app,就未过期
|
||||
if (!appExpiredMap.containsKey(trimmed) || !appExpiredMap.get(trimmed)) {
|
||||
appExpiredMap.put(trimmed, expired);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 合并所有 appKey
|
||||
Set<String> allKeys = new HashSet<>();
|
||||
allKeys.addAll(associatedKeys);
|
||||
allKeys.addAll(packageKeys);
|
||||
|
||||
// 5. 查询 basic 类型应用(对所有用户可见)
|
||||
LambdaQueryWrapper<AppInfo> basicWrapper = new LambdaQueryWrapper<>();
|
||||
basicWrapper.eq(AppInfo::getAppType, "basic");
|
||||
List<AppInfo> basicApps = appInfoMapper.selectList(basicWrapper);
|
||||
for (AppInfo app : basicApps) {
|
||||
allKeys.add(app.getAppKey());
|
||||
// basic 应用如果没有被套餐包含且没有被关联,source = "app"
|
||||
}
|
||||
|
||||
if (allKeys.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 6. 查出完整应用信息
|
||||
LambdaQueryWrapper<AppInfo> appWrapper = new LambdaQueryWrapper<>();
|
||||
appWrapper.in(AppInfo::getAppKey, allKeys);
|
||||
List<AppInfo> appInfoList = appInfoMapper.selectList(appWrapper);
|
||||
|
||||
// 7. 组装 VO
|
||||
List<CustomerAppVO> result = new ArrayList<>();
|
||||
for (AppInfo appInfo : appInfoList) {
|
||||
CustomerAppVO vo = new CustomerAppVO();
|
||||
BeanUtils.copyProperties(appInfo, vo);
|
||||
vo.setUserVisible(Boolean.TRUE.equals(appInfo.getUserVisible()) ? 1 : 0);
|
||||
CustomerApp rel = appRelMap.get(appInfo.getAppKey());
|
||||
if (rel != null) {
|
||||
vo.setCreateTime(rel.getCreateTime());
|
||||
}
|
||||
|
||||
// source 标识:优先 package
|
||||
if (includeSource) {
|
||||
if (packageKeys.contains(appInfo.getAppKey())) {
|
||||
vo.setSource("package");
|
||||
vo.setExpired(appExpiredMap.getOrDefault(appInfo.getAppKey(), true));
|
||||
} else {
|
||||
vo.setSource("app");
|
||||
vo.setExpired(false);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(vo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联应用给客户
|
||||
*/
|
||||
public Res addApp(Long customerId, String appKey) {
|
||||
LambdaQueryWrapper<CustomerApp> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerApp::getCustomerId, customerId);
|
||||
wrapper.eq(CustomerApp::getAppKey, appKey);
|
||||
if (count(wrapper) > 0) {
|
||||
return Res.fail("该应用已关联");
|
||||
}
|
||||
CustomerApp customerApp = new CustomerApp();
|
||||
customerApp.setCustomerId(customerId);
|
||||
customerApp.setAppKey(appKey);
|
||||
save(customerApp);
|
||||
|
||||
// 记录操作日志
|
||||
String customerName = "";
|
||||
CustomerInfo ci = customerInfoService.getById(customerId);
|
||||
if (ci != null) customerName = ci.getCustomerName();
|
||||
OperationLogUtil.log("企业管理", "关联应用", "关联应用给企业: " + customerName + " (" + appKey + ")");
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑客户的应用
|
||||
*/
|
||||
public Res removeApp(Long customerId, String appKey) {
|
||||
LambdaQueryWrapper<CustomerApp> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerApp::getCustomerId, customerId);
|
||||
wrapper.eq(CustomerApp::getAppKey, appKey);
|
||||
remove(wrapper);
|
||||
|
||||
// 记录操作日志
|
||||
String customerName = "";
|
||||
CustomerInfo ci = customerInfoService.getById(customerId);
|
||||
if (ci != null) customerName = ci.getCustomerName();
|
||||
OperationLogUtil.log("企业管理", "解绑应用", "解绑企业应用: " + customerName + " (" + appKey + ")");
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有应用(用于选择器)
|
||||
*/
|
||||
public List<AppInfo> getAllApps() {
|
||||
return appInfoMapper.selectList(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据应用标识查询关联的客户ID列表
|
||||
*/
|
||||
public List<Long> getCustomerIdsByAppKey(String appKey) {
|
||||
LambdaQueryWrapper<CustomerApp> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerApp::getAppKey, appKey);
|
||||
List<CustomerApp> list = list(wrapper);
|
||||
return list.stream().map(CustomerApp::getCustomerId).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
package cn.apes.cloud.service.impl;
|
||||
|
||||
import cn.apes.commons.Res;
|
||||
import cn.apes.cloud.service.impl.huoban.HuobanUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import cn.apes.cloud.domain.huoban.UpsertOne;
|
||||
import cn.apes.cloud.service.SysOperationLogService;
|
||||
import cn.apes.cloud.util.OperationLogUtil;
|
||||
import cn.apes.cloud.domain.dto.CustomerSearchDTO;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import cn.apes.cloud.domain.entity.SsoConfig;
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import cn.apes.cloud.domain.entity.UserInfo;
|
||||
import cn.apes.cloud.mapper.CustomerInfoMapper;
|
||||
import cn.apes.cloud.mapper.CustomerPackageMapper;
|
||||
import cn.apes.cloud.mapper.SsoConfigMapper;
|
||||
import cn.apes.cloud.service.SysPackagePlanService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> {
|
||||
|
||||
|
||||
@Autowired
|
||||
SsoConfigMapper ssoConfigMapper;
|
||||
|
||||
@Autowired
|
||||
CustomerPackageMapper customerPackageMapper;
|
||||
|
||||
@Autowired
|
||||
SysPackagePlanService sysPackagePlanService;
|
||||
|
||||
@Autowired
|
||||
SysOperationLogService sysOperationLogService;
|
||||
|
||||
@Autowired
|
||||
cn.apes.cloud.service.impl.huoban.HuobanData2ServiceImpl huobanData2Service;
|
||||
|
||||
public Res pageCustomer(CustomerSearchDTO searchDTO) {
|
||||
LambdaQueryWrapper<CustomerInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
IPage<CustomerInfo> pageData = page(searchDTO.getPage(), lambdaQueryWrapper);
|
||||
|
||||
// 关联填充每个客户的套餐信息
|
||||
for (CustomerInfo customer : pageData.getRecords()) {
|
||||
LambdaQueryWrapper<CustomerPackage> pkgWrapper = new LambdaQueryWrapper<>();
|
||||
pkgWrapper.eq(CustomerPackage::getCustomerId, customer.getId());
|
||||
List<CustomerPackage> packages = customerPackageMapper.selectList(pkgWrapper);
|
||||
if (!packages.isEmpty()) {
|
||||
List<SysPackagePlan> plans = packages.stream()
|
||||
.map(p -> sysPackagePlanService.getById(p.getPlanId()))
|
||||
.filter(p -> p != null)
|
||||
.collect(Collectors.toList());
|
||||
customer.setPlans(plans);
|
||||
}
|
||||
}
|
||||
|
||||
return Res.success(pageData);
|
||||
}
|
||||
|
||||
public Res getCustomerDetail(Long id) {
|
||||
if (id == null) {
|
||||
return Res.fail("客户ID不能为空");
|
||||
}
|
||||
CustomerInfo customerInfo = getById(id);
|
||||
return Res.success(customerInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增/编辑客户
|
||||
*/
|
||||
public Res saveCustomer(CustomerInfo customerInfo) {
|
||||
if (StrUtil.isEmpty(customerInfo.getCustomerName())) {
|
||||
return Res.fail("客户名称不能为空");
|
||||
}
|
||||
if (StrUtil.isEmpty(customerInfo.getAdminName())) {
|
||||
return Res.fail("负责人姓名不能为空");
|
||||
}
|
||||
if (StrUtil.isEmpty(customerInfo.getAdminPhone())) {
|
||||
return Res.fail("负责人手机号不能为空");
|
||||
}
|
||||
|
||||
if (customerInfo.getCustomerStatus() == null) {
|
||||
customerInfo.setCustomerStatus(1);
|
||||
}
|
||||
|
||||
boolean isNew = customerInfo.getId() == null;
|
||||
saveOrUpdate(customerInfo);
|
||||
|
||||
String action = isNew ? "新增企业" : "编辑企业";
|
||||
String desc = (isNew ? "新增企业: " : "编辑企业: ") + customerInfo.getCustomerName();
|
||||
OperationLogUtil.log("企业管理", action, desc);
|
||||
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除客户
|
||||
*/
|
||||
public Res deleteCustomer(CustomerInfo customerInfo) {
|
||||
if (customerInfo.getId() == null) {
|
||||
return Res.fail("客户ID不能为空");
|
||||
}
|
||||
String customerName = "";
|
||||
CustomerInfo existing = getById(customerInfo.getId());
|
||||
if (existing != null) customerName = existing.getCustomerName();
|
||||
|
||||
removeById(customerInfo.getId());
|
||||
OperationLogUtil.log("企业管理", "删除企业", "删除企业: " + customerName);
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户SSO配置(公司级别 user_id=0)
|
||||
*/
|
||||
public Res getSSOConfig(Long customerId) {
|
||||
LambdaQueryWrapper<SsoConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SsoConfig::getUserId, 0L);
|
||||
wrapper.eq(SsoConfig::getCustomerId, customerId);
|
||||
SsoConfig config = ssoConfigMapper.selectOne(wrapper);
|
||||
if (config == null) {
|
||||
config = new SsoConfig();
|
||||
config.setCustomerId(customerId);
|
||||
config.setUserId(0L);
|
||||
config.setHuobanCompanyId(5100000024031260L);
|
||||
config.setHuobanStatus(1);
|
||||
}
|
||||
return Res.success(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存客户SSO配置(公司级别 user_id=0)
|
||||
*/
|
||||
public Res saveSSOConfig(SsoConfig ssoConfig) {
|
||||
if (ssoConfig.getCustomerId() == null) {
|
||||
return Res.fail("客户ID不能为空");
|
||||
}
|
||||
// 查询是否已存在
|
||||
LambdaQueryWrapper<SsoConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SsoConfig::getUserId, 0L);
|
||||
wrapper.eq(SsoConfig::getCustomerId, ssoConfig.getCustomerId());
|
||||
SsoConfig existing = ssoConfigMapper.selectOne(wrapper);
|
||||
if (existing != null) {
|
||||
ssoConfig.setId(existing.getId());
|
||||
}
|
||||
// 设置公司级别
|
||||
ssoConfig.setUserId(0L);
|
||||
// 默认值
|
||||
if (ssoConfig.getHuobanStatus() == null) {
|
||||
ssoConfig.setHuobanStatus(1);
|
||||
}
|
||||
if (ssoConfig.getHuobanCompanyId() == null) {
|
||||
ssoConfig.setHuobanCompanyId(5100000024031260L);
|
||||
}
|
||||
ssoConfigMapper.insertOrUpdate(ssoConfig);
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客户状态
|
||||
*/
|
||||
public Res updateCustomerStatus(Long customerId, Integer customerStatus) {
|
||||
if (customerId == null) {
|
||||
return Res.fail("客户ID不能为空");
|
||||
}
|
||||
if (customerStatus == null || (customerStatus != 1 && customerStatus != 2 && customerStatus != 3 && customerStatus != 4)) {
|
||||
return Res.fail("无效的客户状态");
|
||||
}
|
||||
CustomerInfo customerInfo = getById(customerId);
|
||||
if (customerInfo == null) {
|
||||
return Res.fail("客户不存在");
|
||||
}
|
||||
customerInfo.setCustomerStatus(customerStatus);
|
||||
updateById(customerInfo);
|
||||
|
||||
String statusName = "";
|
||||
switch (customerStatus) {
|
||||
case 1: statusName = "使用中"; break;
|
||||
case 2: statusName = "待审核"; break;
|
||||
case 3: statusName = "已注销"; break;
|
||||
case 4: statusName = "暂停服务"; break;
|
||||
default: statusName = String.valueOf(customerStatus);
|
||||
}
|
||||
String action = customerStatus == 3 ? "注销企业" : (customerStatus == 4 ? "暂停服务" : (customerStatus == 1 ? "恢复服务" : "更新状态"));
|
||||
OperationLogUtil.log("企业管理", action, statusName + " - " + customerInfo.getCustomerName());
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核企业认证
|
||||
* @param customerId 企业ID
|
||||
* @param auditStatus 审核结果:1=通过,5=拒绝
|
||||
* @param auditRemark 拒绝原因(拒绝时必填)
|
||||
*/
|
||||
public Res auditCertification(Long customerId, Integer auditStatus, String auditRemark) {
|
||||
if (customerId == null) {
|
||||
return Res.fail("企业ID不能为空");
|
||||
}
|
||||
if (auditStatus == null || (auditStatus != 1 && auditStatus != 5)) {
|
||||
return Res.fail("无效的审核状态,1=通过,5=拒绝");
|
||||
}
|
||||
if (auditStatus == 5 && cn.hutool.core.util.StrUtil.isBlank(auditRemark)) {
|
||||
return Res.fail("审核拒绝时必须填写原因");
|
||||
}
|
||||
CustomerInfo customerInfo = getById(customerId);
|
||||
if (customerInfo == null) {
|
||||
return Res.fail("企业不存在");
|
||||
}
|
||||
customerInfo.setCustomerStatus(auditStatus);
|
||||
customerInfo.setAuditRemark(auditRemark);
|
||||
customerInfo.setAuditTime(new java.util.Date());
|
||||
updateById(customerInfo);
|
||||
log.info("企业认证审核完成: customerId=" + customerId + ", customerStatus=" + auditStatus + ", remark=" + auditRemark);
|
||||
|
||||
String auditAction = auditStatus == 1 ? "审核通过" : "审核拒绝";
|
||||
String auditDesc = auditAction + " - " + customerInfo.getCustomerName() + (auditStatus == 5 ? " (" + auditRemark + ")" : "");
|
||||
OperationLogUtil.log("企业认证", auditAction, auditDesc);
|
||||
return Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步全部租户到伙伴云
|
||||
* 遍历所有非删除状态的租户,通过 upsetOne 接口同步数据
|
||||
*/
|
||||
public Res syncAllTenantsToHuoban() {
|
||||
try {
|
||||
// 查询全部租户
|
||||
LambdaQueryWrapper<CustomerInfo> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerInfo::getIsDel, 0);
|
||||
List<CustomerInfo> allCustomers = list(wrapper);
|
||||
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
StringBuilder failMsg = new StringBuilder();
|
||||
|
||||
for (CustomerInfo customer : allCustomers) {
|
||||
try {
|
||||
// 构建 upsetOne 请求参数
|
||||
JSONObject fields = new JSONObject();
|
||||
fields.put("customerId", customer.getId());
|
||||
fields.put("customerName", customer.getCustomerName());
|
||||
fields.put("shortName", customer.getShortName());
|
||||
fields.put("customerType", customer.getCustomerType());
|
||||
fields.put("adminName", customer.getAdminName());
|
||||
fields.put("adminPhone", customer.getAdminPhone());
|
||||
fields.put("customerStatus", customer.getCustomerStatus());
|
||||
fields.put("industry", customer.getIndustry());
|
||||
fields.put("industrySub", customer.getIndustrySub());
|
||||
fields.put("salesChannel", customer.getSalesChannel());
|
||||
fields.put("industryType", customer.getIndustryType());
|
||||
fields.put("province", customer.getProvince());
|
||||
fields.put("city", customer.getCity());
|
||||
if (customer.getLogo() != null) fields.put("logo", customer.getLogo());
|
||||
if (customer.getCustomerIdNumber() != null) fields.put("customerIdNumber", customer.getCustomerIdNumber());
|
||||
|
||||
// 通过 HuobanData2ServiceImpl.upsetOne 调用
|
||||
UpsertOne upsertOne = new UpsertOne(2100000000008750L, fields);
|
||||
upsertOne.setUpdateFields(java.util.Collections.singletonList("customerId"));
|
||||
upsertOne.setAction("one_update");
|
||||
|
||||
Res res = huobanData2Service.upsetOne(upsertOne);
|
||||
if (res != null && res.getCode() == 1) {
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
failMsg.append(customer.getCustomerName()).append("(").append(res != null ? res.getMsg() : "null").append("); ");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
failMsg.append(customer.getCustomerName()).append("(").append(e.getMessage()).append("); ");
|
||||
}
|
||||
}
|
||||
|
||||
String result = "同步完成:成功 " + successCount + " 条";
|
||||
if (failCount > 0) {
|
||||
result += ",失败 " + failCount + " 条";
|
||||
if (failMsg.length() > 200) {
|
||||
result += ",详情:" + failMsg.substring(0, 200) + "...";
|
||||
} else {
|
||||
result += ",详情:" + failMsg.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (failCount == 0) {
|
||||
return Res.success(result);
|
||||
} else {
|
||||
return Res.fail(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return Res.fail("同步异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,887 @@
|
||||
package cn.apes.cloud.service.impl;
|
||||
|
||||
import cn.apes.cloud.domain.entity.AppInfo;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.LoginUser;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageExtendApply;
|
||||
import cn.apes.cloud.mapper.CustomerPackageExtendApplyMapper;
|
||||
import cn.apes.cloud.mapper.CustomerQuotaChangeLogMapper;
|
||||
import cn.apes.cloud.domain.entity.CustomerQuotaChangeLog;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackage;
|
||||
import cn.apes.cloud.domain.entity.CustomerInfo;
|
||||
import cn.apes.commons.auth.AuthContext;
|
||||
import cn.apes.commons.auth.LoginUser;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageExtendApply;
|
||||
import cn.apes.cloud.mapper.CustomerPackageExtendApplyMapper;
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import cn.apes.cloud.domain.vo.CustomerPackageVO;
|
||||
import cn.apes.cloud.domain.vo.CustomerPackageExtendApplyVO;
|
||||
import cn.apes.cloud.mapper.CustomerInfoMapper;
|
||||
import cn.apes.cloud.domain.entity.CustomerPackageQuota;
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlan;
|
||||
import cn.apes.cloud.domain.entity.SysPackagePlanQuota;
|
||||
import cn.apes.cloud.domain.entity.SysQuota;
|
||||
import cn.apes.cloud.mapper.AppInfoMapper;
|
||||
import cn.apes.cloud.mapper.CustomerPackageMapper;
|
||||
import cn.apes.cloud.mapper.CustomerPackageQuotaMapper;
|
||||
import cn.apes.cloud.mapper.SysPackagePlanQuotaMapper;
|
||||
import cn.apes.cloud.mapper.SysQuotaMapper;
|
||||
import cn.apes.cloud.service.CustomerPackageService;
|
||||
import cn.apes.cloud.service.impl.CustomerInfoServiceImpl;
|
||||
import cn.apes.cloud.service.SysPackagePlanService;
|
||||
import cn.apes.cloud.util.OperationLogUtil;
|
||||
import cn.apes.cloud.service.SysQuotaService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CustomerPackageServiceImpl extends ServiceImpl<CustomerPackageMapper, CustomerPackage> implements CustomerPackageService {
|
||||
|
||||
@Autowired
|
||||
private SysPackagePlanService sysPackagePlanService;
|
||||
|
||||
@Autowired
|
||||
private CustomerPackageQuotaMapper customerPackageQuotaMapper;
|
||||
|
||||
@Autowired
|
||||
private SysQuotaService sysQuotaService;
|
||||
|
||||
@Autowired
|
||||
private SysQuotaMapper sysQuotaMapper;
|
||||
|
||||
@Autowired
|
||||
private AppInfoMapper appInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerInfoServiceImpl customerInfoService;
|
||||
|
||||
@Autowired
|
||||
private SysPackagePlanQuotaMapper sysPackagePlanQuotaMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerInfoMapper customerInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerPackageExtendApplyMapper customerPackageExtendApplyMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerQuotaChangeLogMapper customerQuotaChangeLogMapper;
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getCustomerPackages(Long customerId) {
|
||||
if (customerId == null) {
|
||||
return cn.apes.commons.Res.fail("客户ID不能为空");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<CustomerPackage> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerPackage::getCustomerId, customerId);
|
||||
wrapper.orderByDesc(CustomerPackage::getCreateTime);
|
||||
List<CustomerPackage> list = list(wrapper);
|
||||
|
||||
// 填充套餐信息
|
||||
for (CustomerPackage cp : list) {
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(cp.getPlanId());
|
||||
if (plan != null) {
|
||||
cp.setPlanName(plan.getPlanName());
|
||||
cp.setPlanLevel(plan.getPlanLevel());
|
||||
cp.setChargeMode(plan.getChargeMode());
|
||||
cp.setAmount(plan.getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res addCustomerPackage(CustomerPackage customerPackage) {
|
||||
if (customerPackage.getCustomerId() == null) {
|
||||
return cn.apes.commons.Res.fail("客户ID不能为空");
|
||||
}
|
||||
if (customerPackage.getPlanId() == null) {
|
||||
return cn.apes.commons.Res.fail("套餐ID不能为空");
|
||||
}
|
||||
if (customerPackage.getExpireTime() == null) {
|
||||
return cn.apes.commons.Res.fail("到期时间不能为空");
|
||||
}
|
||||
|
||||
// 检查是否已存在(包括软删除的记录,避免唯一索引冲突)
|
||||
CustomerPackage existing = baseMapper.selectOneIgnoreLogic(customerPackage.getCustomerId(), customerPackage.getPlanId());
|
||||
if (existing != null) {
|
||||
if (existing.getIsDel() == 1) {
|
||||
// 存在已删除记录,恢复并更新
|
||||
baseMapper.restoreRecord(existing.getId(), customerPackage.getExpireTime());
|
||||
// 删除旧的配额记录后重新初始化
|
||||
customerPackageQuotaMapper.physicalDeleteByPackageId(existing.getId());
|
||||
// 重新初始化配额
|
||||
initCustomerPackageQuotas(existing.getId(), existing.getPlanId());
|
||||
return cn.apes.commons.Res.success(existing);
|
||||
}
|
||||
return cn.apes.commons.Res.fail("该客户已拥有此套餐");
|
||||
}
|
||||
|
||||
save(customerPackage);
|
||||
|
||||
// 获取套餐名称和企业名称用于日志
|
||||
String customerName = "";
|
||||
CustomerInfo ci = customerInfoService.getById(customerPackage.getCustomerId());
|
||||
if (ci != null) customerName = ci.getCustomerName();
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(customerPackage.getPlanId());
|
||||
String planName = plan != null ? plan.getPlanName() : "套餐ID:" + customerPackage.getPlanId();
|
||||
OperationLogUtil.log("企业管理", "分配套餐", "为企业 " + customerName + " 分配套餐: " + planName);
|
||||
|
||||
// MyBatis-Plus save() may not populate the auto-generated ID back into the entity
|
||||
// Query it back to ensure we have the correct packageId for quota init
|
||||
Long packageId = customerPackage.getId();
|
||||
if (packageId == null) {
|
||||
LambdaQueryWrapper<CustomerPackage> fetchWrapper = new LambdaQueryWrapper<>();
|
||||
fetchWrapper.eq(CustomerPackage::getCustomerId, customerPackage.getCustomerId());
|
||||
fetchWrapper.eq(CustomerPackage::getPlanId, customerPackage.getPlanId());
|
||||
fetchWrapper.orderByDesc(CustomerPackage::getId);
|
||||
fetchWrapper.last("LIMIT 1");
|
||||
CustomerPackage saved = getOne(fetchWrapper);
|
||||
if (saved != null) {
|
||||
packageId = saved.getId();
|
||||
customerPackage.setId(packageId);
|
||||
}
|
||||
}
|
||||
|
||||
if (packageId != null) {
|
||||
// 自动从套餐计划的配额定义初始化 customer_package_quota
|
||||
initCustomerPackageQuotas(packageId, customerPackage.getPlanId());
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success(customerPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res editCustomerPackage(java.util.Map<String, Object> data) {
|
||||
Long id = data.get("id") != null ? Long.parseLong(data.get("id").toString()) : null;
|
||||
if (id == null) {
|
||||
return cn.apes.commons.Res.fail("ID不能为空");
|
||||
}
|
||||
|
||||
CustomerPackage existing = getById(id);
|
||||
if (existing == null) {
|
||||
return cn.apes.commons.Res.fail("记录不存在");
|
||||
}
|
||||
|
||||
// 获取企业名称用于日志
|
||||
String customerName = "";
|
||||
CustomerInfo ci = customerInfoService.getById(existing.getCustomerId());
|
||||
if (ci != null) customerName = ci.getCustomerName();
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(existing.getPlanId());
|
||||
String planName = plan != null ? plan.getPlanName() : "";
|
||||
|
||||
CustomerPackage update = new CustomerPackage();
|
||||
update.setId(id);
|
||||
boolean hasChange = false;
|
||||
|
||||
if (data.get("planId") != null) {
|
||||
update.setPlanId(Long.parseLong(data.get("planId").toString()));
|
||||
hasChange = true;
|
||||
}
|
||||
if (data.get("expireTime") != null) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
update.setExpireTime(sdf.parse(data.get("expireTime").toString()));
|
||||
} catch (Exception e) {
|
||||
return cn.apes.commons.Res.fail("日期格式错误");
|
||||
}
|
||||
hasChange = true;
|
||||
}
|
||||
|
||||
if (!hasChange) {
|
||||
return cn.apes.commons.Res.fail("没有需要更新的字段");
|
||||
}
|
||||
|
||||
// 如果更换了套餐计划,重新初始化配额
|
||||
Long newPlanId = data.get("planId") != null ? Long.parseLong(data.get("planId").toString()) : null;
|
||||
updateById(update);
|
||||
|
||||
// 获取新套餐名称
|
||||
String newPlanName = planName;
|
||||
if (newPlanId != null) {
|
||||
SysPackagePlan newPlan = sysPackagePlanService.getById(newPlanId);
|
||||
newPlanName = newPlan != null ? newPlan.getPlanName() : "套餐ID:" + newPlanId;
|
||||
customerPackageQuotaMapper.physicalDeleteByPackageId(id);
|
||||
initCustomerPackageQuotas(id, newPlanId);
|
||||
}
|
||||
OperationLogUtil.log("企业管理", "编辑套餐", "编辑企业 " + customerName + " 套餐: " + newPlanName);
|
||||
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res deleteCustomerPackage(Long id) {
|
||||
if (id == null) {
|
||||
return cn.apes.commons.Res.fail("ID不能为空");
|
||||
}
|
||||
CustomerPackage existing = getById(id);
|
||||
String customerName = "";
|
||||
if (existing != null) {
|
||||
CustomerInfo ci = customerInfoService.getById(existing.getCustomerId());
|
||||
if (ci != null) customerName = ci.getCustomerName();
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(existing.getPlanId());
|
||||
String planName = plan != null ? plan.getPlanName() : "";
|
||||
OperationLogUtil.log("企业管理", "删除套餐", "删除企业 " + customerName + " 套餐: " + planName);
|
||||
}
|
||||
removeById(id);
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从套餐计划的配额定义初始化 customer_package_quota 记录
|
||||
*/
|
||||
private void initCustomerPackageQuotas(Long packageId, Long planId) {
|
||||
// 查询该套餐计划的所有配额定义
|
||||
LambdaQueryWrapper<SysPackagePlanQuota> planQuotaWrapper = new LambdaQueryWrapper<>();
|
||||
planQuotaWrapper.eq(SysPackagePlanQuota::getPlanId, planId);
|
||||
List<SysPackagePlanQuota> planQuotas = sysPackagePlanQuotaMapper.selectList(planQuotaWrapper);
|
||||
|
||||
if (planQuotas.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 预加载 quota_id -> SysQuota
|
||||
List<Long> quotaIds = planQuotas.stream()
|
||||
.map(SysPackagePlanQuota::getQuotaId)
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toList());
|
||||
if (quotaIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
java.util.Map<Long, SysQuota> quotaMap = sysQuotaService.listByIds(quotaIds).stream()
|
||||
.collect(java.util.stream.Collectors.toMap(SysQuota::getId, q -> q));
|
||||
|
||||
// 插入 customer_package_quota 记录
|
||||
for (SysPackagePlanQuota planQuota : planQuotas) {
|
||||
SysQuota sq = quotaMap.get(planQuota.getQuotaId());
|
||||
if (sq == null) continue;
|
||||
|
||||
CustomerPackageQuota entity = new CustomerPackageQuota();
|
||||
entity.setCustomerPackageId(packageId);
|
||||
entity.setQuotaId(sq.getId());
|
||||
entity.setQuotaCode(sq.getQuotaCode());
|
||||
entity.setQuotaName(sq.getQuotaName());
|
||||
entity.setDataType(sq.getDataType());
|
||||
entity.setAppKey(sq.getAppKey());
|
||||
entity.setQuotaValue(planQuota.getQuotaValue());
|
||||
customerPackageQuotaMapper.insert(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res saveCustomerPackageQuotas(Long packageId, java.util.Map<String, Object> quotaValues) {
|
||||
if (packageId == null) {
|
||||
return cn.apes.commons.Res.fail("套餐关联ID不能为空");
|
||||
}
|
||||
if (quotaValues == null) {
|
||||
quotaValues = new java.util.HashMap<>();
|
||||
}
|
||||
|
||||
// 物理删除旧的(避免逻辑删除后 uk_pkg_quota 冲突)
|
||||
customerPackageQuotaMapper.physicalDeleteByPackageId(packageId);
|
||||
|
||||
// 预加载 quota_code -> SysQuota 映射
|
||||
List<SysQuota> allQuotas = sysQuotaService.list();
|
||||
java.util.Map<String, SysQuota> quotaMap = new java.util.HashMap<>();
|
||||
for (SysQuota q : allQuotas) {
|
||||
quotaMap.put(q.getQuotaCode(), q);
|
||||
}
|
||||
|
||||
// 插入新的
|
||||
for (java.util.Map.Entry<String, Object> entry : quotaValues.entrySet()) {
|
||||
String quotaCode = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (value == null || value.toString().isEmpty()) continue;
|
||||
|
||||
SysQuota sysQuota = quotaMap.get(quotaCode);
|
||||
if (sysQuota == null) continue;
|
||||
|
||||
CustomerPackageQuota entity = new CustomerPackageQuota();
|
||||
entity.setCustomerPackageId(packageId);
|
||||
entity.setQuotaId(sysQuota.getId());
|
||||
entity.setQuotaCode(quotaCode);
|
||||
entity.setQuotaName(sysQuota.getQuotaName());
|
||||
entity.setDataType(sysQuota.getDataType());
|
||||
entity.setAppKey(sysQuota.getAppKey());
|
||||
entity.setQuotaValue(value.toString());
|
||||
customerPackageQuotaMapper.insert(entity);
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getCustomerPackageQuotas(Long packageId) {
|
||||
if (packageId == null) {
|
||||
return cn.apes.commons.Res.fail("套餐关联ID不能为空");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<CustomerPackageQuota> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerPackageQuota::getCustomerPackageId, packageId);
|
||||
java.util.List<CustomerPackageQuota> list = customerPackageQuotaMapper.selectList(wrapper);
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
java.util.Set<Long> quotaIds = list.stream()
|
||||
.map(CustomerPackageQuota::getQuotaId)
|
||||
.filter(id -> id != null)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
if (!quotaIds.isEmpty()) {
|
||||
java.util.List<SysQuota> templates = sysQuotaMapper.selectBatchIds(quotaIds);
|
||||
for (CustomerPackageQuota item : list) {
|
||||
if (item.getQuotaId() != null) {
|
||||
for (SysQuota t : templates) {
|
||||
if (t.getId().equals(item.getQuotaId())) {
|
||||
String u = t.getUnit() != null ? t.getUnit() : t.getMaxQuotaUnit();
|
||||
item.setUnit(u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getMyPackages(Long customerId) {
|
||||
if (customerId == null) {
|
||||
return cn.apes.commons.Res.fail("客户ID不能为空");
|
||||
}
|
||||
|
||||
// 1. 查询客户所有套餐
|
||||
LambdaQueryWrapper<CustomerPackage> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerPackage::getCustomerId, customerId);
|
||||
wrapper.orderByDesc(CustomerPackage::getCreateTime);
|
||||
List<CustomerPackage> packages = list(wrapper);
|
||||
|
||||
if (packages.isEmpty()) {
|
||||
return cn.apes.commons.Res.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
// 2. 填充套餐详情 + 配额
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (CustomerPackage cp : packages) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
|
||||
// 套餐基本信息
|
||||
item.put("id", cp.getId());
|
||||
item.put("customerId", cp.getCustomerId());
|
||||
item.put("planId", cp.getPlanId());
|
||||
item.put("expireTime", cp.getExpireTime());
|
||||
item.put("createTime", cp.getCreateTime());
|
||||
item.put("updateTime", cp.getUpdateTime());
|
||||
|
||||
// 套餐详情
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(cp.getPlanId());
|
||||
if (plan != null) {
|
||||
item.put("planName", plan.getPlanName());
|
||||
item.put("planLevel", plan.getPlanLevel());
|
||||
item.put("chargeMode", plan.getChargeMode());
|
||||
item.put("amount", plan.getAmount());
|
||||
item.put("description", plan.getDescription());
|
||||
item.put("status", plan.getStatus());
|
||||
item.put("iconUrl", plan.getIconUrl());
|
||||
}
|
||||
|
||||
// 配额配置
|
||||
LambdaQueryWrapper<CustomerPackageQuota> quotaWrapper = new LambdaQueryWrapper<>();
|
||||
quotaWrapper.eq(CustomerPackageQuota::getCustomerPackageId, cp.getId());
|
||||
List<CustomerPackageQuota> quotas = customerPackageQuotaMapper.selectList(quotaWrapper);
|
||||
|
||||
// 从 sys_quota 获取 unit 和 resetCycle 补充到配额列表中
|
||||
if (!quotas.isEmpty()) {
|
||||
List<Long> quotaIds = quotas.stream()
|
||||
.map(CustomerPackageQuota::getQuotaId)
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toList());
|
||||
if (!quotaIds.isEmpty()) {
|
||||
List<SysQuota> sysQuotas = sysQuotaService.listByIds(quotaIds);
|
||||
for (CustomerPackageQuota q : quotas) {
|
||||
if (q.getQuotaId() != null) {
|
||||
for (SysQuota sq : sysQuotas) {
|
||||
if (sq.getId().equals(q.getQuotaId())) {
|
||||
String u = sq.getUnit() != null ? sq.getUnit() : sq.getMaxQuotaUnit();
|
||||
q.setUnit(u);
|
||||
q.setResetCycle(sq.getResetCycle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
item.put("quotas", quotas);
|
||||
|
||||
// 应用列表:从套餐配置的 appIds 获取,与配额无关
|
||||
List<Map<String, Object>> appInfoList = new ArrayList<>();
|
||||
if (plan != null && plan.getAppIds() != null && !plan.getAppIds().isEmpty()) {
|
||||
List<String> appKeys = java.util.Arrays.stream(plan.getAppIds().split(","))
|
||||
.map(String::trim)
|
||||
.filter(k -> !k.isEmpty())
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
if (!appKeys.isEmpty()) {
|
||||
List<AppInfo> apps = appInfoMapper.selectBatchIds(appKeys);
|
||||
Map<String, String> appKeyToName = apps.stream()
|
||||
.collect(java.util.stream.Collectors.toMap(AppInfo::getAppKey, a -> a.getAppName() != null ? a.getAppName() : a.getAppKey()));
|
||||
for (String key : appKeys) {
|
||||
Map<String, Object> ai = new HashMap<>();
|
||||
ai.put("appKey", key);
|
||||
ai.put("appName", appKeyToName.getOrDefault(key, key));
|
||||
appInfoList.add(ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
item.put("appKeys", appInfoList);
|
||||
|
||||
result.add(item);
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getCustomerPackageOverview(java.util.Map<String, Object> params) {
|
||||
// 分页参数
|
||||
int pageNum = params.get("pageNum") != null ? Integer.parseInt(params.get("pageNum").toString()) : 1;
|
||||
int pageSize = params.get("pageSize") != null ? Integer.parseInt(params.get("pageSize").toString()) : 10;
|
||||
|
||||
// 查询所有未删除的客户套餐
|
||||
LambdaQueryWrapper<CustomerPackage> cpWrapper = new LambdaQueryWrapper<>();
|
||||
cpWrapper.eq(CustomerPackage::getIsDel, 0);
|
||||
cpWrapper.last("ORDER BY CASE WHEN expire_time IS NULL THEN 1 ELSE 0 END, expire_time ASC");
|
||||
List<CustomerPackage> allPackages = list(cpWrapper);
|
||||
|
||||
// 获取套餐详情(planName)
|
||||
List<CustomerPackageVO> fullList = new ArrayList<>();
|
||||
for (CustomerPackage cp : allPackages) {
|
||||
CustomerPackageVO vo = new CustomerPackageVO();
|
||||
vo.setPackageId(cp.getId());
|
||||
vo.setCustomerId(cp.getCustomerId());
|
||||
vo.setPlanId(cp.getPlanId());
|
||||
vo.setExpireTime(cp.getExpireTime());
|
||||
|
||||
// 查询客户信息
|
||||
CustomerInfo ci = customerInfoMapper.selectById(cp.getCustomerId());
|
||||
if (ci != null) {
|
||||
vo.setCustomerName(ci.getCustomerName());
|
||||
vo.setShortName(ci.getShortName());
|
||||
vo.setAdminPhone(ci.getAdminPhone());
|
||||
}
|
||||
|
||||
// 查询套餐名称
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(cp.getPlanId());
|
||||
if (plan != null) {
|
||||
vo.setPlanName(plan.getPlanName());
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
if (cp.getExpireTime() != null) {
|
||||
long diff = cp.getExpireTime().getTime() - System.currentTimeMillis();
|
||||
long days = diff / (1000 * 60 * 60 * 24);
|
||||
vo.setRemainingDays(days);
|
||||
} else {
|
||||
vo.setRemainingDays(-1L); // 无过期时间
|
||||
}
|
||||
|
||||
fullList.add(vo);
|
||||
}
|
||||
|
||||
// 分页
|
||||
int total = fullList.size();
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
List<CustomerPackageVO> pageData = fromIndex >= total ? new ArrayList<>() : fullList.subList(fromIndex, toIndex);
|
||||
|
||||
// 组装分页结果
|
||||
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
||||
result.put("list", pageData);
|
||||
result.put("total", total);
|
||||
result.put("pageNum", pageNum);
|
||||
result.put("pageSize", pageSize);
|
||||
result.put("totalPages", (total + pageSize - 1) / pageSize);
|
||||
|
||||
return cn.apes.commons.Res.success(result);
|
||||
}
|
||||
|
||||
|
||||
public cn.apes.commons.Res submitExtendApply(java.util.Map<String, Object> params) {
|
||||
Long customerId = params.get("customerId") != null ? Long.valueOf(params.get("customerId").toString()) : null;
|
||||
Long planId = params.get("planId") != null ? Long.valueOf(params.get("planId").toString()) : null;
|
||||
Long userId = params.get("userId") != null ? Long.valueOf(params.get("userId").toString()) : null;
|
||||
String contactPhone = params.get("contactPhone") != null ? params.get("contactPhone").toString() : null;
|
||||
String reason = params.get("reason") != null ? params.get("reason").toString() : null;
|
||||
Integer applyDays = params.get("applyDays") != null ? Integer.valueOf(params.get("applyDays").toString()) : null;
|
||||
|
||||
if (customerId == null || planId == null || userId == null) {
|
||||
return cn.apes.commons.Res.error("缺少必要参数");
|
||||
}
|
||||
if (applyDays == null || applyDays < 0 || applyDays > 180) {
|
||||
return cn.apes.commons.Res.error("延期天数需在0-180天之间");
|
||||
}
|
||||
|
||||
CustomerPackageExtendApply apply = new CustomerPackageExtendApply();
|
||||
apply.setCustomerId(customerId);
|
||||
apply.setPlanId(planId);
|
||||
apply.setUserId(userId);
|
||||
apply.setContactPhone(contactPhone);
|
||||
apply.setReason(reason);
|
||||
apply.setApplyDays(applyDays);
|
||||
apply.setStatus(0);
|
||||
apply.setApplyTime(new java.util.Date());
|
||||
|
||||
customerPackageExtendApplyMapper.insert(apply);
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getExtendApplyList(java.util.Map<String, Object> params) {
|
||||
// 分页参数
|
||||
int pageNum = params.get("pageNum") != null ? Integer.parseInt(params.get("pageNum").toString()) : 1;
|
||||
int pageSize = params.get("pageSize") != null ? Integer.parseInt(params.get("pageSize").toString()) : 10;
|
||||
|
||||
// 查询所有延期申请记录(不走 @TableLogic,查全部)
|
||||
LambdaQueryWrapper<CustomerPackageExtendApply> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.orderByDesc(CustomerPackageExtendApply::getApplyTime);
|
||||
List<CustomerPackageExtendApply> allList = customerPackageExtendApplyMapper.selectList(wrapper);
|
||||
|
||||
// 组装 VO
|
||||
List<CustomerPackageExtendApplyVO> fullList = new ArrayList<>();
|
||||
for (CustomerPackageExtendApply item : allList) {
|
||||
CustomerPackageExtendApplyVO vo = new CustomerPackageExtendApplyVO();
|
||||
vo.setId(item.getId());
|
||||
vo.setCustomerId(item.getCustomerId());
|
||||
vo.setPlanId(item.getPlanId());
|
||||
vo.setUserId(item.getUserId());
|
||||
vo.setContactPhone(item.getContactPhone());
|
||||
vo.setReason(item.getReason());
|
||||
vo.setApplyDays(item.getApplyDays());
|
||||
vo.setApplyTime(item.getApplyTime());
|
||||
vo.setStatus(item.getStatus());
|
||||
|
||||
// 状态文本
|
||||
if (item.getStatus() != null) {
|
||||
String[] statusTexts = {"申请中", "已调整", "已拒绝"};
|
||||
vo.setStatusText(item.getStatus() >= 0 && item.getStatus() < statusTexts.length ? statusTexts[item.getStatus()] : "未知");
|
||||
}
|
||||
|
||||
// 操作人信息
|
||||
vo.setOperatorId(item.getOperatorId());
|
||||
vo.setOperatorName(item.getOperatorName());
|
||||
vo.setOperateTime(item.getOperateTime());
|
||||
|
||||
// 查询企业信息
|
||||
CustomerInfo ci = customerInfoMapper.selectById(item.getCustomerId());
|
||||
if (ci != null) {
|
||||
vo.setCustomerName(ci.getCustomerName());
|
||||
vo.setShortName(ci.getShortName());
|
||||
vo.setAdminPhone(ci.getAdminPhone());
|
||||
}
|
||||
|
||||
// 查询套餐名称
|
||||
SysPackagePlan plan = sysPackagePlanService.getById(item.getPlanId());
|
||||
if (plan != null) {
|
||||
vo.setPlanName(plan.getPlanName());
|
||||
}
|
||||
|
||||
fullList.add(vo);
|
||||
}
|
||||
|
||||
// 前端筛选条件(可选)
|
||||
String keyword = params.get("keyword") != null ? params.get("keyword").toString() : null;
|
||||
Integer status = params.get("status") != null && !params.get("status").toString().isEmpty() ? Integer.parseInt(params.get("status").toString()) : null;
|
||||
if (keyword != null && !keyword.isEmpty()) {
|
||||
fullList = fullList.stream().filter(vo ->
|
||||
(vo.getCustomerName() != null && vo.getCustomerName().contains(keyword))
|
||||
|| (vo.getShortName() != null && vo.getShortName().contains(keyword))
|
||||
|| (vo.getPlanName() != null && vo.getPlanName().contains(keyword))
|
||||
).collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
if (status != null) {
|
||||
fullList = fullList.stream().filter(vo -> vo.getStatus() != null && vo.getStatus().equals(status)).collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
// 分页
|
||||
int total = fullList.size();
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
List<CustomerPackageExtendApplyVO> pageData = fromIndex >= total ? new ArrayList<>() : fullList.subList(fromIndex, toIndex);
|
||||
|
||||
// 组装结果
|
||||
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
||||
result.put("list", pageData);
|
||||
result.put("total", total);
|
||||
result.put("pageNum", pageNum);
|
||||
result.put("pageSize", pageSize);
|
||||
result.put("totalPages", (total + pageSize - 1) / pageSize);
|
||||
|
||||
return cn.apes.commons.Res.success(result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 审核延期申请(同意/拒绝)
|
||||
*/
|
||||
public cn.apes.commons.Res reviewExtendApply(java.util.Map<String, Object> params) {
|
||||
Long applyId = params.get("applyId") != null ? Long.valueOf(params.get("applyId").toString()) : null;
|
||||
Integer action = params.get("action") != null ? Integer.valueOf(params.get("action").toString()) : null;
|
||||
Integer newApplyDays = params.get("applyDays") != null ? Integer.valueOf(params.get("applyDays").toString()) : null;
|
||||
|
||||
if (applyId == null || action == null) {
|
||||
return cn.apes.commons.Res.error("缺少必要参数");
|
||||
}
|
||||
if (action != 1 && action != 2) {
|
||||
return cn.apes.commons.Res.error("操作类型无效");
|
||||
}
|
||||
|
||||
CustomerPackageExtendApply applyRecord = customerPackageExtendApplyMapper.selectById(applyId);
|
||||
if (applyRecord == null) {
|
||||
return cn.apes.commons.Res.error("申请记录不存在");
|
||||
}
|
||||
if (applyRecord.getStatus() != 0) {
|
||||
return cn.apes.commons.Res.error("该申请已处理");
|
||||
}
|
||||
|
||||
// 获取操作人
|
||||
LoginUser operator = AuthContext.getLoginInfo().getUser();
|
||||
String operatorName = operator.getNickName() != null ? operator.getNickName() : operator.getPhone();
|
||||
|
||||
// 更新状态
|
||||
applyRecord.setStatus(action);
|
||||
applyRecord.setOperatorId(operator.getId());
|
||||
applyRecord.setOperatorName(operatorName);
|
||||
applyRecord.setOperateTime(new java.util.Date());
|
||||
|
||||
// 使用操作人信息
|
||||
String logUserName = operator.getNickName() != null ? operator.getNickName() : operator.getPhone();
|
||||
|
||||
if (action == 1) {
|
||||
// 同意调整 - 延长套餐
|
||||
int days = (newApplyDays != null && newApplyDays > 0 && newApplyDays <= 180) ? newApplyDays : applyRecord.getApplyDays();
|
||||
applyRecord.setApplyDays(days);
|
||||
|
||||
// 查询当前套餐的 expire_time
|
||||
LambdaQueryWrapper<CustomerPackage> pkgWrapper = new LambdaQueryWrapper<>();
|
||||
pkgWrapper.eq(CustomerPackage::getCustomerId, applyRecord.getCustomerId())
|
||||
.eq(CustomerPackage::getPlanId, applyRecord.getPlanId())
|
||||
.eq(CustomerPackage::getIsDel, 0);
|
||||
CustomerPackage pkg = getOne(pkgWrapper);
|
||||
if (pkg != null && pkg.getExpireTime() != null) {
|
||||
// 延长
|
||||
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||
cal.setTime(pkg.getExpireTime());
|
||||
cal.add(java.util.Calendar.DAY_OF_YEAR, days);
|
||||
pkg.setExpireTime(cal.getTime());
|
||||
updateById(pkg);
|
||||
|
||||
OperationLogUtil.log("延期申请管理", "同意延期",
|
||||
"同意企业延期申请,延长套餐 " + days + " 天");
|
||||
} else {
|
||||
return cn.apes.commons.Res.error("未找到对应的套餐");
|
||||
}
|
||||
} else {
|
||||
// 拒绝
|
||||
OperationLogUtil.log("延期申请管理", "拒绝延期",
|
||||
"拒绝企业延期申请");
|
||||
}
|
||||
|
||||
customerPackageExtendApplyMapper.updateById(applyRecord);
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res increaseQuota(java.util.Map<String, Object> params) {
|
||||
Long packageId = params.get("packageId") != null ? Long.parseLong(params.get("packageId").toString()) : null;
|
||||
String quotaCode = params.get("quotaCode") != null ? params.get("quotaCode").toString() : null;
|
||||
Integer amount = params.get("amount") != null ? Integer.parseInt(params.get("amount").toString()) : null;
|
||||
String reason = params.get("reason") != null ? params.get("reason").toString() : "";
|
||||
|
||||
if (packageId == null || quotaCode == null || amount == null || amount <= 0) {
|
||||
return cn.apes.commons.Res.fail("参数错误");
|
||||
}
|
||||
|
||||
// 查询当前配额
|
||||
LambdaQueryWrapper<CustomerPackageQuota> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerPackageQuota::getCustomerPackageId, packageId)
|
||||
.eq(CustomerPackageQuota::getQuotaCode, quotaCode);
|
||||
CustomerPackageQuota quota = customerPackageQuotaMapper.selectOne(wrapper);
|
||||
|
||||
if (quota == null) {
|
||||
return cn.apes.commons.Res.fail("配额项不存在");
|
||||
}
|
||||
|
||||
// 更新配额值
|
||||
int oldValue = Integer.parseInt(quota.getQuotaValue());
|
||||
int newValue = oldValue + amount;
|
||||
quota.setQuotaValue(String.valueOf(newValue));
|
||||
customerPackageQuotaMapper.updateById(quota);
|
||||
|
||||
// 记录变更日志
|
||||
CustomerQuotaChangeLog log = new CustomerQuotaChangeLog();
|
||||
log.setCustomerPackageId(packageId);
|
||||
log.setQuotaCode(quotaCode);
|
||||
log.setQuotaName(quota.getQuotaName());
|
||||
log.setChangeType(1); // 1=增加
|
||||
log.setChangeAmount(amount);
|
||||
log.setOldValue(String.valueOf(oldValue));
|
||||
log.setNewValue(String.valueOf(newValue));
|
||||
log.setReason(reason);
|
||||
log.setOperateTime(new java.util.Date());
|
||||
try {
|
||||
log.setOperatorId(AuthContext.getLoginInfo().getUser().getId());
|
||||
log.setOperatorName(AuthContext.getLoginInfo().getUser().getNickName());
|
||||
} catch (Exception e) {
|
||||
// AccessToken 模式下可能没有登录信息
|
||||
log.setOperatorName("系统/外部调用");
|
||||
}
|
||||
customerQuotaChangeLogMapper.insert(log);
|
||||
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
|
||||
public cn.apes.commons.Res decreaseQuota(java.util.Map<String, Object> params) {
|
||||
Long packageId = params.get("packageId") != null ? Long.parseLong(params.get("packageId").toString()) : null;
|
||||
String quotaCode = params.get("quotaCode") != null ? params.get("quotaCode").toString() : null;
|
||||
Integer amount = params.get("amount") != null ? Integer.parseInt(params.get("amount").toString()) : null;
|
||||
String reason = params.get("reason") != null ? params.get("reason").toString() : "";
|
||||
|
||||
if (packageId == null || quotaCode == null || amount == null || amount <= 0) {
|
||||
return cn.apes.commons.Res.fail("参数错误");
|
||||
}
|
||||
|
||||
// 查询当前配额
|
||||
LambdaQueryWrapper<CustomerPackageQuota> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomerPackageQuota::getCustomerPackageId, packageId)
|
||||
.eq(CustomerPackageQuota::getQuotaCode, quotaCode);
|
||||
CustomerPackageQuota quota = customerPackageQuotaMapper.selectOne(wrapper);
|
||||
|
||||
if (quota == null) {
|
||||
return cn.apes.commons.Res.fail("配额项不存在");
|
||||
}
|
||||
|
||||
// 检查是否会导致负数
|
||||
int oldValue = Integer.parseInt(quota.getQuotaValue());
|
||||
int newValue = oldValue - amount;
|
||||
if (newValue < 0) {
|
||||
return cn.apes.commons.Res.fail("减少后配额不能为负数");
|
||||
}
|
||||
|
||||
// 更新配额值
|
||||
quota.setQuotaValue(String.valueOf(newValue));
|
||||
customerPackageQuotaMapper.updateById(quota);
|
||||
|
||||
// 记录变更日志
|
||||
CustomerQuotaChangeLog log = new CustomerQuotaChangeLog();
|
||||
log.setCustomerPackageId(packageId);
|
||||
log.setQuotaCode(quotaCode);
|
||||
log.setQuotaName(quota.getQuotaName());
|
||||
log.setChangeType(2); // 2=减少
|
||||
log.setChangeAmount(amount);
|
||||
log.setOldValue(String.valueOf(oldValue));
|
||||
log.setNewValue(String.valueOf(newValue));
|
||||
log.setReason(reason);
|
||||
log.setOperateTime(new java.util.Date());
|
||||
try {
|
||||
log.setOperatorId(AuthContext.getLoginInfo().getUser().getId());
|
||||
log.setOperatorName(AuthContext.getLoginInfo().getUser().getNickName());
|
||||
} catch (Exception e) {
|
||||
// AccessToken 模式下可能没有登录信息
|
||||
log.setOperatorName("系统/外部调用");
|
||||
}
|
||||
customerQuotaChangeLogMapper.insert(log);
|
||||
|
||||
return cn.apes.commons.Res.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public cn.apes.commons.Res getQuotaChangeLogs(java.util.Map<String, Object> params) {
|
||||
Long packageId = params.get("packageId") != null ? Long.parseLong(params.get("packageId").toString()) : null;
|
||||
String keyword = params.get("keyword") != null ? params.get("keyword").toString() : null;
|
||||
Integer pageNum = params.get("pageNum") != null ? Integer.parseInt(params.get("pageNum").toString()) : 1;
|
||||
Integer pageSize = params.get("pageSize") != null ? Integer.parseInt(params.get("pageSize").toString()) : 10;
|
||||
|
||||
com.baomidou.mybatisplus.extension.plugins.pagination.Page<CustomerQuotaChangeLog> page =
|
||||
new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNum, pageSize);
|
||||
|
||||
LambdaQueryWrapper<CustomerQuotaChangeLog> wrapper = new LambdaQueryWrapper<>();
|
||||
if (packageId != null) {
|
||||
wrapper.eq(CustomerQuotaChangeLog::getCustomerPackageId, packageId);
|
||||
}
|
||||
if (keyword != null && !keyword.trim().isEmpty()) {
|
||||
wrapper.and(w -> w.like(CustomerQuotaChangeLog::getQuotaName, keyword)
|
||||
.or().like(CustomerQuotaChangeLog::getQuotaCode, keyword)
|
||||
.or().like(CustomerQuotaChangeLog::getOperatorName, keyword)
|
||||
.or().like(CustomerQuotaChangeLog::getReason, keyword));
|
||||
}
|
||||
wrapper.orderByDesc(CustomerQuotaChangeLog::getOperateTime);
|
||||
|
||||
com.baomidou.mybatisplus.extension.plugins.pagination.Page<CustomerQuotaChangeLog> result =
|
||||
customerQuotaChangeLogMapper.selectPage(page, wrapper);
|
||||
|
||||
// 关联客户信息
|
||||
List<CustomerQuotaChangeLog> logs = result.getRecords();
|
||||
if (logs != null && !logs.isEmpty()) {
|
||||
// 收集所有 customerPackageId
|
||||
List<Long> packageIds = logs.stream()
|
||||
.map(CustomerQuotaChangeLog::getCustomerPackageId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询套餐对应的客户ID
|
||||
LambdaQueryWrapper<CustomerPackage> pkgWrapper = new LambdaQueryWrapper<>();
|
||||
pkgWrapper.in(CustomerPackage::getId, packageIds);
|
||||
List<CustomerPackage> packages = baseMapper.selectList(pkgWrapper);
|
||||
Map<Long, Long> packageToCustomerMap = packages.stream()
|
||||
.collect(Collectors.toMap(CustomerPackage::getId, CustomerPackage::getCustomerId));
|
||||
|
||||
// 查询客户信息
|
||||
List<Long> customerIds = packages.stream()
|
||||
.map(CustomerPackage::getCustomerId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<Long, String> customerNameMap = new HashMap<>();
|
||||
if (!customerIds.isEmpty()) {
|
||||
LambdaQueryWrapper<CustomerInfo> custWrapper = new LambdaQueryWrapper<>();
|
||||
custWrapper.in(CustomerInfo::getId, customerIds);
|
||||
List<CustomerInfo> customers = customerInfoMapper.selectList(custWrapper);
|
||||
customerNameMap = customers.stream()
|
||||
.collect(Collectors.toMap(CustomerInfo::getId, CustomerInfo::getCustomerName));
|
||||
}
|
||||
|
||||
// 设置客户名称到日志记录
|
||||
for (CustomerQuotaChangeLog log : logs) {
|
||||
Long customerId = packageToCustomerMap.get(log.getCustomerPackageId());
|
||||
if (customerId != null) {
|
||||
log.setCustomerName(customerNameMap.getOrDefault(customerId, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cn.apes.commons.Res.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user