diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java index aa29548..b83ec2f 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java @@ -20,17 +20,25 @@ public class LongJsonSerializer extends JsonSerializer { public static final LongJsonSerializer INSTANCE = new LongJsonSerializer(); + /** + * JS 安全整数范围 + * 根据 JS Number.MIN_SAFE_INTEGER 与 Number.MAX_SAFE_INTEGER 得来 + */ + private static final long JS_MIN_SAFE_INTEGER = -9007199254740991L; + private static final long JS_MAX_SAFE_INTEGER = 9007199254740991L; + + @Override public void serialize(Long value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { if (null == value) { gen.writeNull(); return; } - // js中最大安全整数16位 Number.MAX_SAFE_INTEGER - String longStr = String.valueOf(value); - if (longStr.length() > 16) { - gen.writeString(longStr); + // 如果超出了 JavaScript 安全整数范围,则序列化为字符串 + if (value < JS_MIN_SAFE_INTEGER || value > JS_MAX_SAFE_INTEGER) { + gen.writeString(Long.toString(value)); } else { + // 否则,序列化为数字 gen.writeNumber(value); } } diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java index 9164b35..257899e 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java @@ -2,6 +2,7 @@ package net.lab1024.sa.base.config; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; @@ -13,6 +14,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; +import java.math.BigDecimal; +import java.math.BigInteger; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeParseException; @@ -37,6 +40,9 @@ public class JsonConfig { builder.serializers(new LocalDateSerializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter())); builder.serializers(new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter())); builder.serializerByType(Long.class, LongJsonSerializer.INSTANCE); + builder.serializerByType(Long.TYPE, LongJsonSerializer.INSTANCE); + builder.serializerByType(BigInteger.class, ToStringSerializer.instance); + builder.serializerByType(BigDecimal.class, ToStringSerializer.instance); }; } diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java index eda2a32..5e04fcc 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java @@ -10,7 +10,6 @@ import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Set; @@ -54,7 +53,7 @@ public class RedisCacheServiceImpl implements CacheService { if (keys != null) { return keys.stream().map(key -> { - String redisKey = StrUtil.str(key, StandardCharsets.UTF_8); + String redisKey = StrUtil.str(key, "utf-8"); // 从 Redis 键中提取出最后一个冒号后面的字符串作为真正的键 return redisKey.substring(redisKey.lastIndexOf(":") + 1); }).collect(Collectors.toList()); diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/manager/CustomRedisCacheManager.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/manager/CustomRedisCacheManager.java deleted file mode 100644 index ce95926..0000000 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/manager/CustomRedisCacheManager.java +++ /dev/null @@ -1,144 +0,0 @@ -package net.lab1024.sa.base.module.support.cache.manager; - -import cn.hutool.core.util.StrUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.convert.DurationStyle; -import org.springframework.data.redis.cache.*; - -import java.time.Duration; - -import static net.lab1024.sa.base.common.constant.StringConst.COLON; - -/** - * 自定义 RedisCacheManager,支持在 cacheName 中通过 '#' 指定 TTL(过期时间)。 - * @Author CoderKK - * @Date 2025-08-15 13:01:01 - *

- * 支持格式:{@code cacheName#ttl},其中 ttl 支持 Spring 的 Duration 格式。 - * 特殊值:{@code -1} 表示永久缓存(永不过期)。 - *

- * - *

使用示例:

- *
- * // 10 秒后过期
- * @Cacheable(value = "user#10s", key = "#id")
- * // 2 小时后过期
- * @Cacheable(value = "report#2h", key = "#date")
- * // 30 分钟后过期
- * @Cacheable(value = "session#30m", key = "#token")
- * // 永不过期(永久缓存),适用于极少变化的配置数据
- * @Cacheable(value = "appConfig#-1", key = "'globalSettings'")
- * // 无 TTL,使用全局默认过期时间(如 7 天)
- * @Cacheable(value = "product", key = "#productId")
- * 
- * - *

生成的 Redis Key 格式:

- *
- * cache:cacheName:key
- * 例如:cache:user:123
- *      cache:appConfig:globalSettings
- * 
- * - *

支持的 TTL 单位:

- * - * - *

注意事项:

- * - */ -@Slf4j -public class CustomRedisCacheManager extends RedisCacheManager { - - /** - * 缓存全局前缀 - */ - private static final String CACHE_PREFIX = "cache"; - - /** - * 自定义 TTL 分隔符,用于在 cacheName 后附加过期时间 - */ - private static final String CUSTOM_TTL_SEPARATOR = "#"; - - /** - * 默认缓存过期时间:7 天 - */ - private static final Duration DEFAULT_TTL = Duration.ofDays(7); - - public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) { - super(cacheWriter, defaultCacheConfiguration); - } - - /** - * 创建 RedisCache 实例,支持从 cacheName 解析 TTL - * - * @param name 缓存名称(支持 name#ttl 格式) - * @param cacheConfig 默认缓存配置 - * @return RedisCache - */ - @Override - protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { - Duration ttl = parseTtlFromCacheName(name); - if (ttl == null) { - ttl = DEFAULT_TTL; - } - - CacheKeyPrefix keyPrefix = cacheName -> { - if (StrUtil.isBlank(cacheName)) { - return CACHE_PREFIX + COLON; - } - String[] parts = cacheName.split(CUSTOM_TTL_SEPARATOR, 2); - String cleanName = StrUtil.trim(parts[0]); - return CACHE_PREFIX + COLON + cleanName + COLON; - }; - - // 构建最终缓存配置:设置 key 前缀 + TTL - RedisCacheConfiguration config = cacheConfig.computePrefixWith(keyPrefix).entryTtl(ttl); - - return super.createRedisCache(name, config); - } - - /** - * 从 cacheName 中解析 TTL - * - * @param name 缓存名称,格式如:users#10m, products#2h, config#-1(永久) - * @return 解析出的 Duration若无效则返回 null;若为 -1,则返回 Duration.ofMillis(-1) 表示永久缓存 - */ - private Duration parseTtlFromCacheName(String name) { - if (StrUtil.isBlank(name)) { - return null; - } - - String[] parts = name.split(CUSTOM_TTL_SEPARATOR, 2); - if (parts.length < 2) { - return null; // 无 TTL 部分 - } - - String ttlStr = StrUtil.trim(parts[1]); - if (StrUtil.isBlank(ttlStr)) { - return null; - } - - // 特殊处理:-1 表示永久缓存 - if ("-1".equals(ttlStr)) { - return Duration.ofMillis(-1); // Spring Redis 中负数 Duration 表示永不过期 - } - - try { - Duration ttl = DurationStyle.detectAndParse(ttlStr); - return ttl.toSeconds() > 0 ? ttl : null; - } catch (IllegalArgumentException e) { - log.debug("解析缓存 TTL 失败,cacheName='{}', ttl='{}', 错误: {}", name, ttlStr, e.getMessage()); - return null; - } - } -} \ No newline at end of file diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java index aa29548..b83ec2f 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java @@ -20,17 +20,25 @@ public class LongJsonSerializer extends JsonSerializer { public static final LongJsonSerializer INSTANCE = new LongJsonSerializer(); + /** + * JS 安全整数范围 + * 根据 JS Number.MIN_SAFE_INTEGER 与 Number.MAX_SAFE_INTEGER 得来 + */ + private static final long JS_MIN_SAFE_INTEGER = -9007199254740991L; + private static final long JS_MAX_SAFE_INTEGER = 9007199254740991L; + + @Override public void serialize(Long value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { if (null == value) { gen.writeNull(); return; } - // js中最大安全整数16位 Number.MAX_SAFE_INTEGER - String longStr = String.valueOf(value); - if (longStr.length() > 16) { - gen.writeString(longStr); + // 如果超出了 JavaScript 安全整数范围,则序列化为字符串 + if (value < JS_MIN_SAFE_INTEGER || value > JS_MAX_SAFE_INTEGER) { + gen.writeString(Long.toString(value)); } else { + // 否则,序列化为数字 gen.writeNumber(value); } } diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java index 9164b35..257899e 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java @@ -2,6 +2,7 @@ package net.lab1024.sa.base.config; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; @@ -13,6 +14,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; +import java.math.BigDecimal; +import java.math.BigInteger; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeParseException; @@ -37,6 +40,9 @@ public class JsonConfig { builder.serializers(new LocalDateSerializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter())); builder.serializers(new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter())); builder.serializerByType(Long.class, LongJsonSerializer.INSTANCE); + builder.serializerByType(Long.TYPE, LongJsonSerializer.INSTANCE); + builder.serializerByType(BigInteger.class, ToStringSerializer.instance); + builder.serializerByType(BigDecimal.class, ToStringSerializer.instance); }; } diff --git a/smart-admin-web-javascript/package.json b/smart-admin-web-javascript/package.json index a4a1a21..af2ebe2 100644 --- a/smart-admin-web-javascript/package.json +++ b/smart-admin-web-javascript/package.json @@ -24,7 +24,7 @@ "axios": "1.6.8", "clipboard": "2.0.11", "crypto-js": "4.1.1", - "dayjs": "1.10.5", + "dayjs": "1.11.13", "decimal.js": "10.3.1", "diff": "5.2.0", "diff2html": "3.4.47", diff --git a/smart-admin-web-javascript/src/store/modules/system/spin.js b/smart-admin-web-javascript/src/store/modules/system/spin.js index fb9b811..f041ffe 100644 --- a/smart-admin-web-javascript/src/store/modules/system/spin.js +++ b/smart-admin-web-javascript/src/store/modules/system/spin.js @@ -8,6 +8,7 @@ * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 */ import { defineStore } from 'pinia'; +import { smartSentry } from '/@/lib/smart-sentry.js'; export const useSpinStore = defineStore({ id: 'spin', @@ -25,7 +26,7 @@ export const useSpinStore = defineStore({ spins.style.zIndex = '999'; } } catch (error) { - console.warn('Spin hide操作失败:', error); + smartSentry.captureError('Spin hide操作失败:', error); } }, show() { @@ -37,7 +38,7 @@ export const useSpinStore = defineStore({ spins.style.zIndex = '1001'; } } catch (error) { - console.warn('Spin show操作失败:', error); + smartSentry.captureError('Spin hide操作失败:', error); } }, }, diff --git a/smart-admin-web-javascript/src/views/system/account/components/center/index.vue b/smart-admin-web-javascript/src/views/system/account/components/center/index.vue index acec24e..1656068 100644 --- a/smart-admin-web-javascript/src/views/system/account/components/center/index.vue +++ b/smart-admin-web-javascript/src/views/system/account/components/center/index.vue @@ -233,11 +233,11 @@ });