feat(app): 添加应用配置管理功能
- 创建应用配置表及实体类 - 实现应用配置的增删改查接口 - 添加配置值加密解密功能 - 支持按应用ID批量获取配置映射 - 实现配置的批量保存和删除功能 - 添加分页查询和列表查询支持 - 集成租户隔离和软删除功能
This commit is contained in:
19
docs/app_config.sql
Normal file
19
docs/app_config.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- 应用配置表
|
||||||
|
CREATE TABLE app_config (
|
||||||
|
config_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '配置ID',
|
||||||
|
website_id INT NOT NULL COMMENT '应用ID',
|
||||||
|
config_key VARCHAR(100) NOT NULL COMMENT '配置键',
|
||||||
|
config_value TEXT NOT NULL COMMENT '配置值(JSON或字符串)',
|
||||||
|
config_type VARCHAR(50) NOT NULL DEFAULT 'general' COMMENT '配置类型:general/api/callback/wechat/payment/git等',
|
||||||
|
is_encrypted TINYINT DEFAULT 0 COMMENT '是否加密 0否 1是',
|
||||||
|
is_secret TINYINT DEFAULT 0 COMMENT '是否敏感信息 0否 1是',
|
||||||
|
description VARCHAR(500) DEFAULT '' COMMENT '配置说明',
|
||||||
|
sort_number INT DEFAULT 0 COMMENT '排序号',
|
||||||
|
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '租户id',
|
||||||
|
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
deleted TINYINT DEFAULT 0 COMMENT '是否删除 0否 1是',
|
||||||
|
UNIQUE KEY uk_website_key (website_id, config_key, deleted),
|
||||||
|
INDEX idx_website_type (website_id, config_type),
|
||||||
|
INDEX idx_tenant (tenant_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用配置表';
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package com.gxwebsoft.app.controller;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.app.entity.AppConfig;
|
||||||
|
import com.gxwebsoft.app.param.AppConfigParam;
|
||||||
|
import com.gxwebsoft.app.service.AppConfigService;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表 Controller
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Tag(name = "应用配置管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/app/app-config")
|
||||||
|
public class AppConfigController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AppConfigService appConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询应用配置
|
||||||
|
*/
|
||||||
|
@Operation(summary = "分页查询应用配置")
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ApiResult<PageResult<AppConfig>> page(AppConfigParam param) {
|
||||||
|
return success(new PageResult<>(appConfigService.page(param)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用配置列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取应用配置列表")
|
||||||
|
@GetMapping()
|
||||||
|
public ApiResult<List<AppConfig>> list(AppConfigParam param) {
|
||||||
|
return success(appConfigService.list(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID获取配置映射
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据应用ID获取配置映射")
|
||||||
|
@GetMapping("/map/{websiteId}")
|
||||||
|
public ApiResult<Map<String, Object>> getConfigsByWebsiteId(@PathVariable Integer websiteId) {
|
||||||
|
return success(appConfigService.getConfigsByWebsiteId(websiteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单个配置值
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取单个配置值")
|
||||||
|
@GetMapping("/value")
|
||||||
|
public ApiResult<String> getConfigValue(@RequestParam Integer websiteId, @RequestParam String configKey) {
|
||||||
|
return success(appConfigService.getConfigValue(websiteId, configKey),null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存配置
|
||||||
|
*/
|
||||||
|
@Operation(summary = "保存配置")
|
||||||
|
@PostMapping()
|
||||||
|
public ApiResult<?> save(@RequestBody AppConfig config) {
|
||||||
|
appConfigService.saveConfig(config);
|
||||||
|
return success("保存成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存配置
|
||||||
|
*/
|
||||||
|
@Operation(summary = "批量保存配置")
|
||||||
|
@PostMapping("/batch")
|
||||||
|
public ApiResult<?> batchSave(@RequestBody BatchSaveRequest request) {
|
||||||
|
appConfigService.batchSaveConfig(request.getWebsiteId(), request.getConfigs());
|
||||||
|
return success("保存成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
*/
|
||||||
|
@Operation(summary = "更新配置")
|
||||||
|
@PutMapping()
|
||||||
|
public ApiResult<?> update(@RequestBody AppConfig config) {
|
||||||
|
appConfigService.updateConfig(config);
|
||||||
|
return success("更新成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
*/
|
||||||
|
@Operation(summary = "删除配置")
|
||||||
|
@DeleteMapping("/{configId}")
|
||||||
|
public ApiResult<?> delete(@PathVariable Integer configId) {
|
||||||
|
appConfigService.deleteConfig(configId);
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存请求对象
|
||||||
|
*/
|
||||||
|
public static class BatchSaveRequest {
|
||||||
|
private Integer websiteId;
|
||||||
|
private List<AppConfig> configs;
|
||||||
|
|
||||||
|
public Integer getWebsiteId() {
|
||||||
|
return websiteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebsiteId(Integer websiteId) {
|
||||||
|
this.websiteId = websiteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AppConfig> getConfigs() {
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigs(List<AppConfig> configs) {
|
||||||
|
this.configs = configs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/main/java/com/gxwebsoft/app/entity/AppConfig.java
Normal file
87
src/main/java/com/gxwebsoft/app/entity/AppConfig.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package com.gxwebsoft.app.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@TableName("app_config")
|
||||||
|
public class AppConfig implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "config_id", type = IdType.AUTO)
|
||||||
|
private Integer configId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
private Integer websiteId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置键
|
||||||
|
*/
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置值(JSON或字符串)
|
||||||
|
*/
|
||||||
|
private String configValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置类型:general/api/callback/wechat/payment/git等
|
||||||
|
*/
|
||||||
|
private String configType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否加密 0否 1是
|
||||||
|
*/
|
||||||
|
private Integer isEncrypted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否敏感信息 0否 1是
|
||||||
|
*/
|
||||||
|
private Integer isSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置说明
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序号
|
||||||
|
*/
|
||||||
|
private Integer sortNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户id
|
||||||
|
*/
|
||||||
|
private Long tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Long createdTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Long updatedTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否删除 0否 1是
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private Integer deleted;
|
||||||
|
}
|
||||||
43
src/main/java/com/gxwebsoft/app/mapper/AppConfigMapper.java
Normal file
43
src/main/java/com/gxwebsoft/app/mapper/AppConfigMapper.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package com.gxwebsoft.app.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.gxwebsoft.app.entity.AppConfig;
|
||||||
|
import com.gxwebsoft.app.param.AppConfigParam;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表 Mapper
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface AppConfigMapper extends BaseMapper<AppConfig> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量获取应用配置
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> selectConfigsByWebsiteId(Integer websiteId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*
|
||||||
|
* @param page 分页对象
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return List<AppConfig>
|
||||||
|
*/
|
||||||
|
List<AppConfig> selectPageRel(@Param("page") IPage<AppConfig> page,
|
||||||
|
@Param("param") AppConfigParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询全部
|
||||||
|
*
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return List<AppConfig>
|
||||||
|
*/
|
||||||
|
List<AppConfig> selectListRel(@Param("param") AppConfigParam param);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gxwebsoft.app.mapper.AppConfigMapper">
|
||||||
|
|
||||||
|
<!-- 关联查询sql -->
|
||||||
|
<sql id="selectSql">
|
||||||
|
SELECT a.*
|
||||||
|
FROM app_config a
|
||||||
|
<where>
|
||||||
|
a.deleted = 0
|
||||||
|
<if test="param.configId != null">
|
||||||
|
AND a.config_id = #{param.configId}
|
||||||
|
</if>
|
||||||
|
<if test="param.websiteId != null">
|
||||||
|
AND a.website_id = #{param.websiteId}
|
||||||
|
</if>
|
||||||
|
<if test="param.configKey != null and param.configKey != ''">
|
||||||
|
AND a.config_key LIKE CONCAT('%', #{param.configKey}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.configType != null and param.configType != ''">
|
||||||
|
AND a.config_type = #{param.configType}
|
||||||
|
</if>
|
||||||
|
<if test="param.isSecret != null">
|
||||||
|
AND a.is_secret = #{param.isSecret}
|
||||||
|
</if>
|
||||||
|
<if test="param.tenantId != null">
|
||||||
|
AND a.tenant_id = #{param.tenantId}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeStart != null">
|
||||||
|
AND a.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND a.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null and param.keywords != ''">
|
||||||
|
AND a.config_key LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 分页查询 -->
|
||||||
|
<select id="selectPageRel" resultType="com.gxwebsoft.app.entity.AppConfig">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询全部 -->
|
||||||
|
<select id="selectListRel" resultType="com.gxwebsoft.app.entity.AppConfig">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 批量获取应用配置(自动解密) -->
|
||||||
|
<select id="selectConfigsByWebsiteId" resultType="java.util.HashMap">
|
||||||
|
SELECT
|
||||||
|
config_key as configKey,
|
||||||
|
config_value as configValue,
|
||||||
|
config_type as configType,
|
||||||
|
is_encrypted as isEncrypted,
|
||||||
|
is_secret as isSecret,
|
||||||
|
description
|
||||||
|
FROM app_config
|
||||||
|
WHERE website_id = #{websiteId}
|
||||||
|
AND deleted = 0
|
||||||
|
ORDER BY config_type, sort_number, config_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
38
src/main/java/com/gxwebsoft/app/param/AppConfigParam.java
Normal file
38
src/main/java/com/gxwebsoft/app/param/AppConfigParam.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package com.gxwebsoft.app.param;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.web.BaseParam;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表查询参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class AppConfigParam extends BaseParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置ID
|
||||||
|
*/
|
||||||
|
private Integer configId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
private Integer websiteId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置键
|
||||||
|
*/
|
||||||
|
private String configKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置类型
|
||||||
|
*/
|
||||||
|
private String configType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否敏感信息
|
||||||
|
*/
|
||||||
|
private Integer isSecret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.gxwebsoft.app.service;
|
||||||
|
|
||||||
|
import com.gxwebsoft.app.entity.AppConfig;
|
||||||
|
import com.gxwebsoft.app.param.AppConfigParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表 Service
|
||||||
|
*/
|
||||||
|
public interface AppConfigService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询应用配置
|
||||||
|
*/
|
||||||
|
List<AppConfig> page(AppConfigParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用配置列表
|
||||||
|
*/
|
||||||
|
List<AppConfig> list(AppConfigParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID获取配置映射(自动解密)
|
||||||
|
*/
|
||||||
|
Map<String, Object> getConfigsByWebsiteId(Integer websiteId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单个配置值
|
||||||
|
*/
|
||||||
|
String getConfigValue(Integer websiteId, String configKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存配置
|
||||||
|
*/
|
||||||
|
void saveConfig(AppConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存配置
|
||||||
|
*/
|
||||||
|
void batchSaveConfig(Integer websiteId, List<AppConfig> configs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
*/
|
||||||
|
void updateConfig(AppConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
*/
|
||||||
|
void deleteConfig(Integer configId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID删除所有配置
|
||||||
|
*/
|
||||||
|
void deleteByWebsiteId(Integer websiteId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
package com.gxwebsoft.app.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.crypto.symmetric.AES;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gxwebsoft.app.entity.AppConfig;
|
||||||
|
import com.gxwebsoft.app.mapper.AppConfigMapper;
|
||||||
|
import com.gxwebsoft.app.param.AppConfigParam;
|
||||||
|
import com.gxwebsoft.app.service.AppConfigService;
|
||||||
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置表 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class AppConfigServiceImpl extends ServiceImpl<AppConfigMapper, AppConfig> implements AppConfigService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置加密密钥(从配置文件读取)
|
||||||
|
*/
|
||||||
|
@Value("${app.config.encrypt-key:GXWebsoft2024!@#$}")
|
||||||
|
private String encryptKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询应用配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<AppConfig> page(AppConfigParam param) {
|
||||||
|
PageParam<AppConfig, AppConfigParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("sort_number asc, config_id asc");
|
||||||
|
List<AppConfig> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return page.sortRecords(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询应用配置(返回PageResult)
|
||||||
|
*/
|
||||||
|
public PageResult<AppConfig> pageRel(AppConfigParam param) {
|
||||||
|
PageParam<AppConfig, AppConfigParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("sort_number asc, config_id asc");
|
||||||
|
List<AppConfig> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return new PageResult<>(list, page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用配置列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<AppConfig> list(AppConfigParam param) {
|
||||||
|
List<AppConfig> list = baseMapper.selectListRel(param);
|
||||||
|
PageParam<AppConfig, AppConfigParam> page = new PageParam<>();
|
||||||
|
page.setDefaultOrder("sort_number asc, config_id asc");
|
||||||
|
return page.sortRecords(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID获取配置映射(自动解密)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getConfigsByWebsiteId(Integer websiteId) {
|
||||||
|
List<Map<String, Object>> configs = baseMapper.selectConfigsByWebsiteId(websiteId);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
for (Map<String, Object> config : configs) {
|
||||||
|
String configKey = (String) config.get("configKey");
|
||||||
|
Object configValue = config.get("configValue");
|
||||||
|
Integer isEncrypted = (Integer) config.get("isEncrypted");
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
if (isEncrypted != null && isEncrypted == 1 && configValue != null) {
|
||||||
|
try {
|
||||||
|
configValue = decrypt((String) configValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("配置解密失败: {}", configKey, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put(configKey, configValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单个配置值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getConfigValue(Integer websiteId, String configKey) {
|
||||||
|
LambdaQueryWrapper<AppConfig> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(AppConfig::getWebsiteId, websiteId);
|
||||||
|
wrapper.eq(AppConfig::getConfigKey, configKey);
|
||||||
|
AppConfig config = getOne(wrapper);
|
||||||
|
|
||||||
|
if (config == null || config.getConfigValue() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
if (config.getIsEncrypted() != null && config.getIsEncrypted() == 1) {
|
||||||
|
return decrypt(config.getConfigValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.getConfigValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveConfig(AppConfig config) {
|
||||||
|
// 设置租户ID
|
||||||
|
Integer tenantId = getCurrentTenantId();
|
||||||
|
if (tenantId != null) {
|
||||||
|
config.setTenantId(Long.valueOf(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密敏感信息
|
||||||
|
if (config.getIsEncrypted() != null && config.getIsEncrypted() == 1 && config.getConfigValue() != null) {
|
||||||
|
config.setConfigValue(encrypt(config.getConfigValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
save(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchSaveConfig(Integer websiteId, List<AppConfig> configs) {
|
||||||
|
// 设置租户ID
|
||||||
|
Integer tenantId = getCurrentTenantId();
|
||||||
|
if (tenantId != null) {
|
||||||
|
for (AppConfig config : configs) {
|
||||||
|
config.setTenantId(Long.valueOf(tenantId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先删除该应用的所有配置
|
||||||
|
remove(new LambdaQueryWrapper<AppConfig>()
|
||||||
|
.eq(AppConfig::getWebsiteId, websiteId));
|
||||||
|
|
||||||
|
// 批量插入新配置
|
||||||
|
for (AppConfig config : configs) {
|
||||||
|
config.setWebsiteId(websiteId);
|
||||||
|
|
||||||
|
// 加密敏感信息
|
||||||
|
if (config.getIsEncrypted() != null && config.getIsEncrypted() == 1 && config.getConfigValue() != null) {
|
||||||
|
config.setConfigValue(encrypt(config.getConfigValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
save(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateConfig(AppConfig config) {
|
||||||
|
// 加密敏感信息
|
||||||
|
if (config.getIsEncrypted() != null && config.getIsEncrypted() == 1 && config.getConfigValue() != null) {
|
||||||
|
config.setConfigValue(encrypt(config.getConfigValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateById(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteConfig(Integer configId) {
|
||||||
|
removeById(configId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID删除所有配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteByWebsiteId(Integer websiteId) {
|
||||||
|
remove(new LambdaQueryWrapper<AppConfig>()
|
||||||
|
.eq(AppConfig::getWebsiteId, websiteId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询条件
|
||||||
|
*/
|
||||||
|
private LambdaQueryWrapper<AppConfig> buildQueryWrapper(AppConfigParam param) {
|
||||||
|
LambdaQueryWrapper<AppConfig> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
if (param.getConfigId() != null) {
|
||||||
|
wrapper.eq(AppConfig::getConfigId, param.getConfigId());
|
||||||
|
}
|
||||||
|
if (param.getWebsiteId() != null) {
|
||||||
|
wrapper.eq(AppConfig::getWebsiteId, param.getWebsiteId());
|
||||||
|
}
|
||||||
|
if (param.getConfigKey() != null) {
|
||||||
|
wrapper.like(AppConfig::getConfigKey, param.getConfigKey());
|
||||||
|
}
|
||||||
|
if (param.getConfigType() != null) {
|
||||||
|
wrapper.eq(AppConfig::getConfigType, param.getConfigType());
|
||||||
|
}
|
||||||
|
if (param.getIsSecret() != null) {
|
||||||
|
wrapper.eq(AppConfig::getIsSecret, param.getIsSecret());
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.orderByAsc(AppConfig::getConfigType)
|
||||||
|
.orderByAsc(AppConfig::getSortNumber)
|
||||||
|
.orderByAsc(AppConfig::getConfigId);
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 加密
|
||||||
|
*/
|
||||||
|
private String encrypt(String plainText) {
|
||||||
|
AES aes = SecureUtil.aes(encryptKey.getBytes());
|
||||||
|
return aes.encryptBase64(plainText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 解密
|
||||||
|
*/
|
||||||
|
private String decrypt(String cipherText) {
|
||||||
|
AES aes = SecureUtil.aes(encryptKey.getBytes());
|
||||||
|
return aes.decryptStr(cipherText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录用户的租户ID
|
||||||
|
*/
|
||||||
|
private Integer getCurrentTenantId() {
|
||||||
|
try {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication != null && authentication.getPrincipal() instanceof User) {
|
||||||
|
return ((User) authentication.getPrincipal()).getTenantId();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取当前用户租户ID失败", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user