设置用户偏好.
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package com.orion.ops.framework.redis.core.utils;
|
package com.orion.ops.framework.redis.core.utils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.orion.lang.define.cache.CacheKeyDefine;
|
import com.orion.lang.define.cache.CacheKeyDefine;
|
||||||
import com.orion.lang.utils.Strings;
|
import com.orion.lang.utils.Strings;
|
||||||
|
|
||||||
@@ -20,6 +22,20 @@ public class RedisStrings extends RedisUtils {
|
|||||||
private RedisStrings() {
|
private RedisStrings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 json
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @return JSONObject
|
||||||
|
*/
|
||||||
|
public static JSONObject getJson(String key) {
|
||||||
|
String value = redisTemplate.opsForValue().get(key);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JSON.parseObject(value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 json
|
* 获取 json
|
||||||
*
|
*
|
||||||
@@ -28,7 +44,7 @@ public class RedisStrings extends RedisUtils {
|
|||||||
* @return T
|
* @return T
|
||||||
*/
|
*/
|
||||||
public static <T> T getJson(CacheKeyDefine define) {
|
public static <T> T getJson(CacheKeyDefine define) {
|
||||||
return getJson(define.getKey(), define);
|
return (T) getJson(define.getKey(), define.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,11 +56,37 @@ public class RedisStrings extends RedisUtils {
|
|||||||
* @return T
|
* @return T
|
||||||
*/
|
*/
|
||||||
public static <T> T getJson(String key, CacheKeyDefine define) {
|
public static <T> T getJson(String key, CacheKeyDefine define) {
|
||||||
|
return (T) getJson(key, define.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 json
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param type type
|
||||||
|
* @param <T> T
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
public static <T> T getJson(String key, Class<T> type) {
|
||||||
String value = redisTemplate.opsForValue().get(key);
|
String value = redisTemplate.opsForValue().get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (T) JSON.parseObject(value, define.getType());
|
return (T) JSON.parseObject(value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 json
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @return JSONArray
|
||||||
|
*/
|
||||||
|
public static JSONArray getJsonArray(String key) {
|
||||||
|
String value = redisTemplate.opsForValue().get(key);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JSON.parseArray(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +97,7 @@ public class RedisStrings extends RedisUtils {
|
|||||||
* @return T
|
* @return T
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> getJsonArray(CacheKeyDefine define) {
|
public static <T> List<T> getJsonArray(CacheKeyDefine define) {
|
||||||
return getJsonArray(define.getKey(), define);
|
return (List<T>) getJsonArray(define.getKey(), define.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,11 +109,23 @@ public class RedisStrings extends RedisUtils {
|
|||||||
* @return T
|
* @return T
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> getJsonArray(String key, CacheKeyDefine define) {
|
public static <T> List<T> getJsonArray(String key, CacheKeyDefine define) {
|
||||||
|
return (List<T>) getJsonArray(key, define.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 json
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param type type
|
||||||
|
* @param <T> T
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
public static <T> List<T> getJsonArray(String key, Class<T> type) {
|
||||||
String value = redisTemplate.opsForValue().get(key);
|
String value = redisTemplate.opsForValue().get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (List<T>) JSON.parseArray(value, define.getType());
|
return JSON.parseArray(value, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 偏好
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 13:54
|
||||||
|
*/
|
||||||
|
public interface PreferenceModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转为 map
|
||||||
|
*
|
||||||
|
* @return map
|
||||||
|
*/
|
||||||
|
default Map<String, Object> toMap() {
|
||||||
|
return JSON.parseObject(JSON.toJSONString(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.strategy;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.handler.preference.model.PreferenceModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 偏好处理策略
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 13:49
|
||||||
|
*/
|
||||||
|
public interface IPreferenceStrategy<Model extends PreferenceModel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认值
|
||||||
|
*
|
||||||
|
* @return 默认值
|
||||||
|
*/
|
||||||
|
Model getDefault();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ public class PermissionController {
|
|||||||
|
|
||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
@GetMapping("/user")
|
@GetMapping("/user")
|
||||||
@Operation(summary = "获取用户权限")
|
@Operation(summary = "获取用户权限聚合信息")
|
||||||
public UserPermissionVO getUserPermission() {
|
public UserPermissionVO getUserPermission() {
|
||||||
return permissionService.getUserPermission();
|
return permissionService.getUserPermission();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
### 更新用户偏好-全部
|
||||||
|
PUT {{baseUrl}}/infra/preference/update
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "SYSTEM",
|
||||||
|
"config": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### 更新用户偏好-部分
|
||||||
|
PUT {{baseUrl}}/infra/preference/update-partial
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "SYSTEM",
|
||||||
|
"config": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### 查询用户偏好
|
||||||
|
GET {{baseUrl}}/infra/preference/get?type=SYSTEM
|
||||||
|
Authorization: {{token}}
|
||||||
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.orion.ops.module.infra.controller;
|
||||||
|
|
||||||
|
import com.orion.ops.framework.common.annotation.RestWrapper;
|
||||||
|
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
|
||||||
|
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
|
||||||
|
import com.orion.ops.module.infra.service.PreferenceService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 api
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Tag(name = "infra - 用户偏好服务")
|
||||||
|
@Slf4j
|
||||||
|
@Validated
|
||||||
|
@RestWrapper
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/infra/preference")
|
||||||
|
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||||
|
public class PreferenceController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PreferenceService preferenceService;
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新用户偏好-整体")
|
||||||
|
public Integer updatePreference(@Validated @RequestBody PreferenceUpdateRequest request) {
|
||||||
|
return preferenceService.updatePreference(request, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update-partial")
|
||||||
|
@Operation(summary = "更新用户偏好-部分")
|
||||||
|
public Integer updatePreferencePartial(@Validated @RequestBody PreferenceUpdateRequest request) {
|
||||||
|
return preferenceService.updatePreference(request, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "查询用户偏好")
|
||||||
|
@Parameter(name = "type", description = "type", required = true)
|
||||||
|
public PreferenceVO getPreference(@RequestParam("type") String type) {
|
||||||
|
return preferenceService.getPreferenceByType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.orion.ops.module.infra.convert;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
|
||||||
|
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
|
||||||
|
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 内部对象转换器
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface PreferenceConvert {
|
||||||
|
|
||||||
|
PreferenceConvert MAPPER = Mappers.getMapper(PreferenceConvert.class);
|
||||||
|
|
||||||
|
@Mapping(target = "config", ignore = true)
|
||||||
|
PreferenceDO to(PreferenceUpdateRequest request);
|
||||||
|
|
||||||
|
@Mapping(target = "config", ignore = true)
|
||||||
|
PreferenceVO to(PreferenceDO domain);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import com.orion.ops.module.infra.entity.request.user.SystemUserQueryRequest;
|
|||||||
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateRequest;
|
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateRequest;
|
||||||
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateStatusRequest;
|
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateStatusRequest;
|
||||||
import com.orion.ops.module.infra.entity.vo.SystemUserVO;
|
import com.orion.ops.module.infra.entity.vo.SystemUserVO;
|
||||||
import com.orion.ops.module.infra.entity.vo.UserBaseInfoVO;
|
import com.orion.ops.module.infra.entity.vo.UserCollectInfoVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
@@ -39,6 +39,6 @@ public interface SystemUserConvert {
|
|||||||
|
|
||||||
LoginUser toLoginUser(SystemUserDO domain);
|
LoginUser toLoginUser(SystemUserDO domain);
|
||||||
|
|
||||||
UserBaseInfoVO toBaseInfo(LoginUser user);
|
UserCollectInfoVO toCollectInfo(LoginUser user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.orion.ops.module.infra.dao;
|
||||||
|
|
||||||
|
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||||
|
import com.orion.ops.framework.mybatis.core.query.Conditions;
|
||||||
|
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 Mapper 接口
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface PreferenceDAO extends IMapper<PreferenceDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 userId 删除
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
* @return effect
|
||||||
|
*/
|
||||||
|
default int deleteByUserId(Long userId) {
|
||||||
|
return this.delete(Conditions.eq(PreferenceDO::getUserId, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.orion.ops.module.infra.define;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.orion.lang.define.cache.CacheKeyBuilder;
|
||||||
|
import com.orion.lang.define.cache.CacheKeyDefine;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好缓存 key
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
public interface PreferenceCacheKeyDefine {
|
||||||
|
|
||||||
|
CacheKeyDefine PREFERENCE = new CacheKeyBuilder()
|
||||||
|
.key("user:preference:{}:{}")
|
||||||
|
.desc("用户偏好 ${userId} ${type}")
|
||||||
|
.type(JSONObject.class)
|
||||||
|
.timeout(1, TimeUnit.DAYS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.orion.ops.module.infra.entity.domain;
|
||||||
|
|
||||||
|
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.orion.ops.framework.mybatis.core.domain.BaseDO;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 实体对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName(value = "preference", autoResultMap = true)
|
||||||
|
@Schema(name = "PreferenceDO", description = "用户偏好 实体对象")
|
||||||
|
public class PreferenceDO extends BaseDO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "id")
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户id")
|
||||||
|
@TableField("user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "类型")
|
||||||
|
@TableField("type")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Schema(description = "偏好配置")
|
||||||
|
@TableField("config")
|
||||||
|
private String config;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.orion.ops.module.infra.entity.request.preference;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 更新请求对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PreferenceUpdateRequest", description = "用户偏好 更新请求对象")
|
||||||
|
public class PreferenceUpdateRequest implements Serializable {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(max = 12)
|
||||||
|
@Schema(description = "类型")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
@Schema(description = "偏好配置")
|
||||||
|
private Map<String, Object> config;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.infra.entity.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 视图响应对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "PreferenceVO", description = "用户偏好 视图响应对象")
|
||||||
|
public class PreferenceVO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "偏好配置")
|
||||||
|
private Map<String, Object> config;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户基本信息 视图响应对象
|
* 用户基本信息 视图响应对象
|
||||||
*
|
*
|
||||||
@@ -17,8 +19,8 @@ import lombok.NoArgsConstructor;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "UserBaseInfoVO", description = "用户基本信息 视图响应对象")
|
@Schema(name = "UserCollectInfoVO", description = "用户聚合信息 视图响应对象")
|
||||||
public class UserBaseInfoVO {
|
public class UserCollectInfoVO {
|
||||||
|
|
||||||
@Schema(description = "id")
|
@Schema(description = "id")
|
||||||
private Long id;
|
private Long id;
|
||||||
@@ -32,4 +34,10 @@ public class UserBaseInfoVO {
|
|||||||
@Schema(description = "头像地址")
|
@Schema(description = "头像地址")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
|
|
||||||
|
@Schema(description = "系统偏好")
|
||||||
|
private Map<String, Object> systemPreference;
|
||||||
|
|
||||||
|
@Schema(description = "提示偏好")
|
||||||
|
private Map<String, Object> tipsPreference;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,8 @@ import java.util.List;
|
|||||||
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
|
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
|
||||||
public class UserPermissionVO {
|
public class UserPermissionVO {
|
||||||
|
|
||||||
@Schema(description = "用户基本信息")
|
@Schema(description = "用户聚合信息")
|
||||||
private UserBaseInfoVO user;
|
private UserCollectInfoVO user;
|
||||||
|
|
||||||
@Schema(description = "该用户已启用的角色")
|
@Schema(description = "该用户已启用的角色")
|
||||||
private List<String> roles;
|
private List<String> roles;
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.orion.ops.module.infra.enums;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.handler.preference.model.PreferenceModel;
|
||||||
|
import com.orion.ops.module.infra.handler.preference.strategy.IPreferenceStrategy;
|
||||||
|
import com.orion.spring.SpringHolder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 偏好类型
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 11:31
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum PreferenceTypeEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统偏好
|
||||||
|
*/
|
||||||
|
SYSTEM("systemPreferenceStrategy"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示偏好
|
||||||
|
*/
|
||||||
|
TIPS("tipsPreferenceStrategy"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
PreferenceTypeEnum(String beanName) {
|
||||||
|
this.type = this.name();
|
||||||
|
this.beanName = beanName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策越 bean 名称
|
||||||
|
* 可能跨模块所以不用 class
|
||||||
|
*/
|
||||||
|
private final String beanName;
|
||||||
|
|
||||||
|
public static PreferenceTypeEnum of(String type) {
|
||||||
|
if (type == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (PreferenceTypeEnum value : values()) {
|
||||||
|
if (value.type.equals(type)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取策略
|
||||||
|
*
|
||||||
|
* @param <M> model
|
||||||
|
* @param <T> type
|
||||||
|
* @return IPreferenceStrategy
|
||||||
|
*/
|
||||||
|
public <M extends PreferenceModel, T extends IPreferenceStrategy<M>> T getStrategy() {
|
||||||
|
return SpringHolder.getBean(beanName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.model;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统偏好模型
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 13:59
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AppPreferenceModel implements PreferenceModel {
|
||||||
|
|
||||||
|
@Schema(description = "是否使用侧边菜单")
|
||||||
|
private Boolean menu;
|
||||||
|
|
||||||
|
@Schema(description = "是否使用顶部菜单")
|
||||||
|
private Boolean topMenu;
|
||||||
|
|
||||||
|
@Schema(description = "是否显示导航栏")
|
||||||
|
private Boolean navbar;
|
||||||
|
|
||||||
|
@Schema(description = "是否显示页脚")
|
||||||
|
private Boolean footer;
|
||||||
|
|
||||||
|
@Schema(description = "是否开启多页签")
|
||||||
|
private Boolean tabBar;
|
||||||
|
|
||||||
|
@Schema(description = "是否开启色弱模式")
|
||||||
|
private Boolean colorWeak;
|
||||||
|
|
||||||
|
@Schema(description = "菜单宽度")
|
||||||
|
private Number menuWidth;
|
||||||
|
|
||||||
|
@Schema(description = "主机视图")
|
||||||
|
private String hostView;
|
||||||
|
|
||||||
|
@Schema(description = "主机秘钥视图")
|
||||||
|
private String hostKeyView;
|
||||||
|
|
||||||
|
@Schema(description = "主机身份视图")
|
||||||
|
private String hostIdentityView;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.model;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示偏好模型
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 13:59
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TipsPreferenceModel implements PreferenceModel {
|
||||||
|
|
||||||
|
@Schema(description = "是否提示过系统偏好设置模态框")
|
||||||
|
private Boolean tippedSystemPreferenceModal;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.strategy;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.handler.preference.model.AppPreferenceModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统偏好处理策略
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 13:48
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SystemPreferenceStrategy implements IPreferenceStrategy<AppPreferenceModel> {
|
||||||
|
|
||||||
|
private static final String TABLE = "table";
|
||||||
|
|
||||||
|
private static final String CARD = "card";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppPreferenceModel getDefault() {
|
||||||
|
return AppPreferenceModel.builder()
|
||||||
|
.menu(true)
|
||||||
|
.topMenu(false)
|
||||||
|
.navbar(true)
|
||||||
|
.footer(true)
|
||||||
|
.tabBar(true)
|
||||||
|
.menuWidth(220)
|
||||||
|
.colorWeak(false)
|
||||||
|
.hostView(TABLE)
|
||||||
|
.hostKeyView(CARD)
|
||||||
|
.hostIdentityView(CARD)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.orion.ops.module.infra.handler.preference.strategy;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.handler.preference.model.TipsPreferenceModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示偏好处理策略
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/10/8 15:11
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TipsPreferenceStrategy implements IPreferenceStrategy<TipsPreferenceModel> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TipsPreferenceModel getDefault() {
|
||||||
|
return TipsPreferenceModel.builder()
|
||||||
|
.tippedSystemPreferenceModal(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.orion.ops.module.infra.service;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
|
||||||
|
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
|
||||||
|
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 服务类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
public interface PreferenceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户偏好
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @param partial 是否为部分更新
|
||||||
|
* @return effect
|
||||||
|
*/
|
||||||
|
Integer updatePreference(PreferenceUpdateRequest request, boolean partial);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户偏好
|
||||||
|
*
|
||||||
|
* @param type type
|
||||||
|
* @return row
|
||||||
|
*/
|
||||||
|
PreferenceVO getPreferenceByType(String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户偏好
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
* @param type type
|
||||||
|
* @return 偏好
|
||||||
|
*/
|
||||||
|
Future<Map<String, Object>> getPreference(Long userId, PreferenceTypeEnum type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户偏好
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
*/
|
||||||
|
void deletePreferenceByUserId(Long userId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ import com.orion.ops.module.infra.enums.FavoriteTypeEnum;
|
|||||||
import com.orion.ops.module.infra.service.FavoriteService;
|
import com.orion.ops.module.infra.service.FavoriteService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -111,6 +112,7 @@ public class FavoriteServiceImpl implements FavoriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
public void deleteFavoriteByUserId(Long userId) {
|
public void deleteFavoriteByUserId(Long userId) {
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return;
|
return;
|
||||||
@@ -127,6 +129,7 @@ public class FavoriteServiceImpl implements FavoriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
public void deleteFavoriteByUserIdList(List<Long> userIdList) {
|
public void deleteFavoriteByUserIdList(List<Long> userIdList) {
|
||||||
if (Lists.isEmpty(userIdList)) {
|
if (Lists.isEmpty(userIdList)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,20 +16,24 @@ import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
|
|||||||
import com.orion.ops.module.infra.entity.domain.SystemRoleMenuDO;
|
import com.orion.ops.module.infra.entity.domain.SystemRoleMenuDO;
|
||||||
import com.orion.ops.module.infra.entity.dto.SystemMenuCacheDTO;
|
import com.orion.ops.module.infra.entity.dto.SystemMenuCacheDTO;
|
||||||
import com.orion.ops.module.infra.entity.vo.SystemMenuVO;
|
import com.orion.ops.module.infra.entity.vo.SystemMenuVO;
|
||||||
import com.orion.ops.module.infra.entity.vo.UserBaseInfoVO;
|
import com.orion.ops.module.infra.entity.vo.UserCollectInfoVO;
|
||||||
import com.orion.ops.module.infra.entity.vo.UserPermissionVO;
|
import com.orion.ops.module.infra.entity.vo.UserPermissionVO;
|
||||||
import com.orion.ops.module.infra.enums.MenuStatusEnum;
|
import com.orion.ops.module.infra.enums.MenuStatusEnum;
|
||||||
import com.orion.ops.module.infra.enums.MenuTypeEnum;
|
import com.orion.ops.module.infra.enums.MenuTypeEnum;
|
||||||
|
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
|
||||||
import com.orion.ops.module.infra.enums.RoleStatusEnum;
|
import com.orion.ops.module.infra.enums.RoleStatusEnum;
|
||||||
import com.orion.ops.module.infra.service.PermissionService;
|
import com.orion.ops.module.infra.service.PermissionService;
|
||||||
|
import com.orion.ops.module.infra.service.PreferenceService;
|
||||||
import com.orion.ops.module.infra.service.SystemMenuService;
|
import com.orion.ops.module.infra.service.SystemMenuService;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -66,11 +70,14 @@ public class PermissionServiceImpl implements PermissionService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SystemMenuService systemMenuService;
|
private SystemMenuService systemMenuService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PreferenceService preferenceService;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@Override
|
@Override
|
||||||
public void initPermissionCache() {
|
public void initPermissionCache() {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
log.info("initRoleMenuCache-start");
|
log.info("initPermissionCache-start");
|
||||||
roleCache.clear();
|
roleCache.clear();
|
||||||
menuCache.clear();
|
menuCache.clear();
|
||||||
roleMenuCache.clear();
|
roleMenuCache.clear();
|
||||||
@@ -104,7 +111,7 @@ public class PermissionServiceImpl implements PermissionService {
|
|||||||
.map(SystemRoleDO::getCode)
|
.map(SystemRoleDO::getCode)
|
||||||
.ifPresent(code -> roleMenuCache.put(code, roleMenus));
|
.ifPresent(code -> roleMenuCache.put(code, roleMenus));
|
||||||
});
|
});
|
||||||
log.info("initRoleMenuCache-end used: {}ms", System.currentTimeMillis() - start);
|
log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -186,10 +193,16 @@ public class PermissionServiceImpl implements PermissionService {
|
|||||||
return systemMenuService.buildSystemMenuTree(menus);
|
return systemMenuService.buildSystemMenuTree(menus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public UserPermissionVO getUserPermission() {
|
public UserPermissionVO getUserPermission() {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
UserBaseInfoVO user = SystemUserConvert.MAPPER.toBaseInfo(SecurityUtils.getLoginUser());
|
UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser());
|
||||||
|
Long id = user.getId();
|
||||||
|
// 获取用户系统偏好
|
||||||
|
Future<Map<String, Object>> systemPreference = preferenceService.getPreference(id, PreferenceTypeEnum.SYSTEM);
|
||||||
|
// 获取用户提示偏好
|
||||||
|
Future<Map<String, Object>> tipsPreference = preferenceService.getPreference(id, PreferenceTypeEnum.TIPS);
|
||||||
// 获取用户角色
|
// 获取用户角色
|
||||||
List<String> roles = this.getUserEnabledRoles();
|
List<String> roles = this.getUserEnabledRoles();
|
||||||
// 获取用户权限
|
// 获取用户权限
|
||||||
@@ -213,6 +226,9 @@ public class PermissionServiceImpl implements PermissionService {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 获取异步结果
|
||||||
|
user.setSystemPreference(systemPreference.get());
|
||||||
|
user.setTipsPreference(tipsPreference.get());
|
||||||
// 组装数据
|
// 组装数据
|
||||||
return UserPermissionVO.builder()
|
return UserPermissionVO.builder()
|
||||||
.user(user)
|
.user(user)
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
package com.orion.ops.module.infra.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.orion.lang.utils.collect.Maps;
|
||||||
|
import com.orion.ops.framework.common.utils.Valid;
|
||||||
|
import com.orion.ops.framework.redis.core.utils.RedisStrings;
|
||||||
|
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||||
|
import com.orion.ops.module.infra.dao.PreferenceDAO;
|
||||||
|
import com.orion.ops.module.infra.define.PreferenceCacheKeyDefine;
|
||||||
|
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
|
||||||
|
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
|
||||||
|
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
|
||||||
|
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
|
||||||
|
import com.orion.ops.module.infra.service.PreferenceService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好 服务实现类
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023-9-27 18:37
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class PreferenceServiceImpl implements PreferenceService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PreferenceDAO preferenceDAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer updatePreference(PreferenceUpdateRequest request, boolean partial) {
|
||||||
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
String type = request.getType();
|
||||||
|
Valid.valid(PreferenceTypeEnum::of, type);
|
||||||
|
// 查询
|
||||||
|
PreferenceDO preference = preferenceDAO.of()
|
||||||
|
.wrapper(this.buildQueryWrapper(userId, type))
|
||||||
|
.getOne();
|
||||||
|
int effect;
|
||||||
|
if (preference == null) {
|
||||||
|
// 直接插入
|
||||||
|
PreferenceDO insertRecord = new PreferenceDO();
|
||||||
|
insertRecord.setUserId(userId);
|
||||||
|
insertRecord.setType(type);
|
||||||
|
insertRecord.setConfig(JSON.toJSONString(request.getConfig()));
|
||||||
|
effect = preferenceDAO.insert(insertRecord);
|
||||||
|
} else {
|
||||||
|
// 更新
|
||||||
|
PreferenceDO updateRecord = new PreferenceDO();
|
||||||
|
updateRecord.setId(preference.getId());
|
||||||
|
if (partial) {
|
||||||
|
// 部分更新
|
||||||
|
JSONObject config = JSON.parseObject(preference.getConfig());
|
||||||
|
config.putAll(request.getConfig());
|
||||||
|
updateRecord.setConfig(JSON.toJSONString(config));
|
||||||
|
} else {
|
||||||
|
// 全部更新
|
||||||
|
updateRecord.setConfig(JSON.toJSONString(request.getConfig()));
|
||||||
|
}
|
||||||
|
effect = preferenceDAO.updateById(updateRecord);
|
||||||
|
// 删除缓存
|
||||||
|
RedisStrings.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
|
||||||
|
}
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PreferenceVO getPreferenceByType(String type) {
|
||||||
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
|
PreferenceTypeEnum typeEnum = Valid.valid(PreferenceTypeEnum::of, type);
|
||||||
|
Map<String, Object> config = this.getPreferenceByCache(userId, typeEnum);
|
||||||
|
// 返回
|
||||||
|
return PreferenceVO.builder()
|
||||||
|
.config(config)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public Future<Map<String, Object>> getPreference(Long userId, PreferenceTypeEnum type) {
|
||||||
|
Map<String, Object> config = this.getPreferenceByCache(userId, type);
|
||||||
|
return CompletableFuture.completedFuture(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public void deletePreferenceByUserId(Long userId) {
|
||||||
|
// 删除
|
||||||
|
int effect = preferenceDAO.deleteByUserId(userId);
|
||||||
|
log.info("PreferenceService-deletePreferenceById userId: {}, effect: {}", userId, effect);
|
||||||
|
// 删除缓存
|
||||||
|
List<String> deleteKeys = Arrays.stream(PreferenceTypeEnum.values())
|
||||||
|
.map(s -> PreferenceCacheKeyDefine.PREFERENCE.format(userId, s))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
RedisStrings.delete(deleteKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过缓存获取偏好
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
* @param type type
|
||||||
|
* @return config
|
||||||
|
*/
|
||||||
|
private Map<String, Object> getPreferenceByCache(Long userId, PreferenceTypeEnum type) {
|
||||||
|
String typeValue = type.getType();
|
||||||
|
// 查询缓存 用 string 防止数据类型丢失
|
||||||
|
String key = PreferenceCacheKeyDefine.PREFERENCE.format(userId, type);
|
||||||
|
Map<String, Object> config = RedisStrings.getJson(key);
|
||||||
|
boolean setCache = Maps.isEmpty(config);
|
||||||
|
// 查询数据库
|
||||||
|
if (Maps.isEmpty(config)) {
|
||||||
|
config = preferenceDAO.of()
|
||||||
|
.wrapper(this.buildQueryWrapper(userId, typeValue))
|
||||||
|
.optionalOne()
|
||||||
|
.map(PreferenceDO::getConfig)
|
||||||
|
.map(JSON::parseObject)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
// 初始化
|
||||||
|
if (Maps.isEmpty(config)) {
|
||||||
|
config = type.getStrategy()
|
||||||
|
.getDefault()
|
||||||
|
.toMap();
|
||||||
|
// 插入
|
||||||
|
PreferenceDO entity = new PreferenceDO();
|
||||||
|
entity.setUserId(userId);
|
||||||
|
entity.setType(typeValue);
|
||||||
|
entity.setConfig(JSON.toJSONString(config));
|
||||||
|
preferenceDAO.insert(entity);
|
||||||
|
}
|
||||||
|
// 设置缓存
|
||||||
|
if (setCache) {
|
||||||
|
RedisStrings.setJson(key, PreferenceCacheKeyDefine.PREFERENCE, config);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询 wrapper
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
* @param type type
|
||||||
|
* @return wrapper
|
||||||
|
*/
|
||||||
|
private LambdaQueryWrapper<PreferenceDO> buildQueryWrapper(Long userId, String type) {
|
||||||
|
return preferenceDAO.wrapper()
|
||||||
|
.eq(PreferenceDO::getUserId, userId)
|
||||||
|
.eq(PreferenceDO::getType, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import com.orion.ops.module.infra.entity.vo.SystemUserVO;
|
|||||||
import com.orion.ops.module.infra.enums.UserStatusEnum;
|
import com.orion.ops.module.infra.enums.UserStatusEnum;
|
||||||
import com.orion.ops.module.infra.service.AuthenticationService;
|
import com.orion.ops.module.infra.service.AuthenticationService;
|
||||||
import com.orion.ops.module.infra.service.FavoriteService;
|
import com.orion.ops.module.infra.service.FavoriteService;
|
||||||
|
import com.orion.ops.module.infra.service.PreferenceService;
|
||||||
import com.orion.ops.module.infra.service.SystemUserService;
|
import com.orion.ops.module.infra.service.SystemUserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
@@ -52,6 +53,9 @@ public class SystemUserServiceImpl implements SystemUserService {
|
|||||||
@Resource
|
@Resource
|
||||||
private FavoriteService favoriteService;
|
private FavoriteService favoriteService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PreferenceService preferenceService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, String> redisTemplate;
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
|
|
||||||
@@ -169,6 +173,8 @@ public class SystemUserServiceImpl implements SystemUserService {
|
|||||||
redisTemplate.delete(UserCacheKeyDefine.USER_INFO.format(id));
|
redisTemplate.delete(UserCacheKeyDefine.USER_INFO.format(id));
|
||||||
// 删除用户收藏
|
// 删除用户收藏
|
||||||
favoriteService.deleteFavoriteByUserId(id);
|
favoriteService.deleteFavoriteByUserId(id);
|
||||||
|
// 删除用户偏好
|
||||||
|
preferenceService.deletePreferenceByUserId(id);
|
||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?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.orion.ops.module.infra.dao.PreferenceDAO">
|
||||||
|
|
||||||
|
<!-- 通用查询映射结果 -->
|
||||||
|
<resultMap id="BaseResultMap" type="com.orion.ops.module.infra.entity.domain.PreferenceDO">
|
||||||
|
<id column="id" property="id"/>
|
||||||
|
<result column="create_time" property="createTime"/>
|
||||||
|
<result column="update_time" property="updateTime"/>
|
||||||
|
<result column="creator" property="creator"/>
|
||||||
|
<result column="updater" property="updater"/>
|
||||||
|
<result column="deleted" property="deleted"/>
|
||||||
|
<result column="user_id" property="userId"/>
|
||||||
|
<result column="type" property="type"/>
|
||||||
|
<result column="config" property="config"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 通用查询结果列 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, user_id, type, config, create_time, update_time, creator, updater, deleted
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
40
orion-ops-ui/src/api/user/preference.ts
Normal file
40
orion-ops-ui/src/api/user/preference.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
type Preference = 'SYSTEM' | 'TIPS'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好更新请求
|
||||||
|
*/
|
||||||
|
export interface PreferenceUpdateRequest {
|
||||||
|
type: Preference;
|
||||||
|
config: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户偏好查询响应
|
||||||
|
*/
|
||||||
|
export interface PreferenceQueryResponse {
|
||||||
|
config: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户偏好-整体
|
||||||
|
*/
|
||||||
|
export function updatePreference(request: PreferenceUpdateRequest) {
|
||||||
|
return axios.put('/infra/preference/update', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户偏好-部分
|
||||||
|
*/
|
||||||
|
export function updatePreferencePartial(request: PreferenceUpdateRequest) {
|
||||||
|
return axios.put('/infra/preference/update-partial', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户偏好
|
||||||
|
*/
|
||||||
|
export function getPreference(type: Preference) {
|
||||||
|
return axios.get<PreferenceQueryResponse>('/infra/preference/get', { params: { type } });
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
<div v-for="option in options" :key="option.name" class="option-wrapper">
|
<div v-for="option in options" :key="option.name" class="option-wrapper">
|
||||||
<!-- 偏好项 -->
|
<!-- 偏好项 -->
|
||||||
<span>{{ option.name }}</span>
|
<span>{{ option.name }}</span>
|
||||||
<!-- input -->
|
<!-- 偏好值 -->
|
||||||
<form-wrapper :name="option.key"
|
<form-wrapper :name="option.key"
|
||||||
:type="option.type"
|
:type="option.type as string"
|
||||||
:default-value="option.defaultVal"
|
:default-value="option.defaultVal"
|
||||||
:options="option.options"
|
:options="option.options"
|
||||||
@input-change="handleChange" />
|
@input-change="handleChange" />
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import FormWrapper from './form-wrapper.vue';
|
import FormWrapper from './form-wrapper.vue';
|
||||||
import { RadioOption } from '@arco-design/web-vue/es/radio/interface';
|
import { RadioOption } from '@arco-design/web-vue/es/radio/interface';
|
||||||
|
import { updatePreferencePartial } from '@/api/user/preference';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
interface OptionsProps {
|
interface OptionsProps {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,10 +49,6 @@
|
|||||||
key: string;
|
key: string;
|
||||||
value: unknown;
|
value: unknown;
|
||||||
}) => {
|
}) => {
|
||||||
// 色弱模式
|
|
||||||
if (key === 'colorWeak') {
|
|
||||||
document.body.style.filter = value ? 'invert(80%)' : 'none';
|
|
||||||
}
|
|
||||||
// 顶部菜单
|
// 顶部菜单
|
||||||
if (key === 'topMenu') {
|
if (key === 'topMenu') {
|
||||||
appStore.updateSettings({
|
appStore.updateSettings({
|
||||||
@@ -57,9 +56,21 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 修改配置
|
// 修改配置
|
||||||
appStore.updateSettings({ [key]: value });
|
const updateConfig = { [key]: value };
|
||||||
// TODO 同步偏好
|
appStore.updateSettings(updateConfig);
|
||||||
|
// 同步偏好
|
||||||
|
Message.clear();
|
||||||
|
const loading = Message.loading('同步中...');
|
||||||
|
try {
|
||||||
|
await updatePreferencePartial({
|
||||||
|
type: 'SYSTEM',
|
||||||
|
config: updateConfig
|
||||||
|
});
|
||||||
|
Message.success('同步成功');
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
loading.close();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { AppState } from './types';
|
import { AppState } from './types';
|
||||||
|
import TimeScale from 'echarts/types/src/scale/Time';
|
||||||
|
|
||||||
const defaultConfig: AppState = {
|
const defaultConfig: AppState = {
|
||||||
// 应用设置
|
// 应用设置
|
||||||
@@ -36,16 +37,17 @@ export default defineStore('app', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
// 修改颜色主题
|
|
||||||
toggleTheme(dark: boolean) {
|
|
||||||
this.updateSettings({
|
|
||||||
theme: dark ? 'dark' : 'light'
|
|
||||||
});
|
|
||||||
document.body.setAttribute('arco-theme', dark ? 'dark' : 'light');
|
|
||||||
},
|
|
||||||
|
|
||||||
// 更新配置
|
// 更新配置
|
||||||
updateSettings(partial: Partial<AppState>) {
|
updateSettings(partial: Partial<AppState>) {
|
||||||
|
// 主题颜色
|
||||||
|
if (partial.theme !== undefined) {
|
||||||
|
document.body.setAttribute('arco-theme', partial.theme);
|
||||||
|
}
|
||||||
|
// 色弱模式
|
||||||
|
if (partial.colorWeak !== undefined) {
|
||||||
|
document.body.style.filter = partial.colorWeak ? 'invert(80%)' : 'none';
|
||||||
|
}
|
||||||
|
// 修改配置
|
||||||
this.$patch(partial as object);
|
this.$patch(partial as object);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { clearToken, setToken } from '@/utils/auth';
|
|||||||
import { md5 } from '@/utils';
|
import { md5 } from '@/utils';
|
||||||
import { removeRouteListener } from '@/utils/route-listener';
|
import { removeRouteListener } from '@/utils/route-listener';
|
||||||
import { UserState } from './types';
|
import { UserState } from './types';
|
||||||
import { useMenuStore, useTabBarStore } from '@/store';
|
import { useAppStore, useMenuStore, useTabBarStore } from '@/store';
|
||||||
|
|
||||||
export default defineStore('user', {
|
export default defineStore('user', {
|
||||||
state: (): UserState => ({
|
state: (): UserState => ({
|
||||||
@@ -30,7 +30,6 @@ export default defineStore('user', {
|
|||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
async info() {
|
async info() {
|
||||||
// TODO 查询偏好
|
|
||||||
const { data } = await getUserPermission();
|
const { data } = await getUserPermission();
|
||||||
// 设置用户信息
|
// 设置用户信息
|
||||||
this.setInfo({
|
this.setInfo({
|
||||||
@@ -41,8 +40,9 @@ export default defineStore('user', {
|
|||||||
roles: data.roles,
|
roles: data.roles,
|
||||||
permission: data.permissions,
|
permission: data.permissions,
|
||||||
});
|
});
|
||||||
// TODO 设置用户偏好
|
// 设置用户偏好
|
||||||
|
const appStore = useAppStore();
|
||||||
|
appStore.updateSettings(data.user.systemPreference);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
|
|||||||
Reference in New Issue
Block a user