2025-06-29 00:36:30 +08:00
|
|
|
|
package utility
|
|
|
|
|
|
|
2025-07-04 19:59:06 +08:00
|
|
|
|
import (
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/shopspring/decimal"
|
|
|
|
|
|
)
|
2025-06-29 00:36:30 +08:00
|
|
|
|
|
|
|
|
|
|
// DesensitizeGeneric 通用脱敏函数:
|
|
|
|
|
|
// startReserveCount: 从字符串开头保留的字符数
|
|
|
|
|
|
// endReserveCount: 从字符串末尾保留的字符数
|
|
|
|
|
|
// asteriskChar: 用于替换的字符 (例如 '*')
|
|
|
|
|
|
// 例如:DesensitizeGeneric("这是一个秘密信息", 2, 2, '*') -> 这**信息
|
|
|
|
|
|
func DesensitizeGeneric(text string, startReserveCount int, endReserveCount int, asteriskChar rune) string {
|
|
|
|
|
|
if text == "" {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
runes := []rune(text)
|
|
|
|
|
|
length := len(runes)
|
|
|
|
|
|
|
|
|
|
|
|
// 计算实际需要保留的总字符数
|
|
|
|
|
|
totalReservedLength := startReserveCount + endReserveCount
|
|
|
|
|
|
|
|
|
|
|
|
// 如果需要保留的字符数大于等于总长度,则不脱敏
|
|
|
|
|
|
if totalReservedLength >= length {
|
|
|
|
|
|
return text
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确保保留位数不为负数
|
|
|
|
|
|
if startReserveCount < 0 {
|
|
|
|
|
|
startReserveCount = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if endReserveCount < 0 {
|
|
|
|
|
|
endReserveCount = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果保留总长度为0,且字符串不为空,则全部脱敏
|
|
|
|
|
|
if totalReservedLength == 0 && length > 0 {
|
|
|
|
|
|
return strings.Repeat(string(asteriskChar), length)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确保保留的长度不超过总长度
|
|
|
|
|
|
if startReserveCount > length {
|
|
|
|
|
|
startReserveCount = length
|
|
|
|
|
|
}
|
|
|
|
|
|
if endReserveCount > length-startReserveCount {
|
|
|
|
|
|
endReserveCount = length - startReserveCount
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构造脱敏字符串
|
|
|
|
|
|
var sb strings.Builder
|
|
|
|
|
|
// 写入前缀
|
|
|
|
|
|
if startReserveCount > 0 {
|
|
|
|
|
|
sb.WriteString(string(runes[0:startReserveCount]))
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写入星号
|
|
|
|
|
|
asteriskCount := length - startReserveCount - endReserveCount
|
|
|
|
|
|
if asteriskCount > 0 {
|
|
|
|
|
|
sb.WriteString(strings.Repeat(string(asteriskChar), asteriskCount))
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写入后缀
|
|
|
|
|
|
if endReserveCount > 0 && length-endReserveCount >= startReserveCount { // 确保后缀不与前缀重叠
|
|
|
|
|
|
sb.WriteString(string(runes[length-endReserveCount:]))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return sb.String()
|
|
|
|
|
|
}
|
2025-07-04 19:59:06 +08:00
|
|
|
|
|
|
|
|
|
|
func StringToDecimal(val string) decimal.Decimal {
|
|
|
|
|
|
cleanedNum := strings.TrimRight(val, "\x00") // 去除空字符
|
|
|
|
|
|
cleanedNum = strings.TrimSpace(cleanedNum) // 去除空格
|
|
|
|
|
|
cleanedNum = strings.ReplaceAll(cleanedNum, ",", "") // 去除逗号
|
|
|
|
|
|
d, err := decimal.NewFromString(cleanedNum)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return decimal.Zero
|
|
|
|
|
|
}
|
|
|
|
|
|
return d
|
|
|
|
|
|
}
|