Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 1h43m42s
- 迁移 000221:新增 tb_business_user_group、tb_business_user_group_member、tb_shop_business_owner_import_task,成员一账号一行由部分唯一索引保证,店铺所属组按当前负责人实时推导,不回填历史分组。 - 用户组 CRUD、成员改组/清空归属、店铺批量交接(原子失败不部分写入)。 - 店铺负责人 CSV 导入任务:逐行独立事务、逐行明细、任务级与行级失败分离。 - 读侧推导与筛选:未分组、业务线、停用组可筛出并带停用标记。 - 补齐操作审计动作与资源、openapi 清单、发布门禁巡检表清单。 - 归档 add-shop-salesperson-groups 变更并同步 openspec/specs/business-user-group,补齐 AUG26-003 验证证据链。
41 lines
1.3 KiB
Go
41 lines
1.3 KiB
Go
package utils
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
"unicode/utf8"
|
||
|
||
"golang.org/x/text/encoding/simplifiedchinese"
|
||
)
|
||
|
||
// utf8BOM 是 UTF-8 字节顺序标记,上传的 CSV 常带该前缀。
|
||
var utf8BOM = []byte{0xEF, 0xBB, 0xBF}
|
||
|
||
// replacementChar 是解码器无法映射字节时产生的替换字符。
|
||
const replacementChar = "\uFFFD"
|
||
|
||
// DecodeTextToUTF8 把上传文本解码为 UTF-8 字节。
|
||
// 先剥离 UTF-8 BOM;剥离后已是合法 UTF-8 时原样返回,否则按 GBK 回退解码。
|
||
// 仅在 UTF-8 校验失败时才尝试 GBK,避免对合法 UTF-8 内容做启发式改写;
|
||
// GBK 解码失败或仍残留无法映射的字节时返回错误,由调用方按任务级失败处理。
|
||
func DecodeTextToUTF8(data []byte) ([]byte, error) {
|
||
trimmed := data
|
||
if len(trimmed) >= len(utf8BOM) && string(trimmed[:len(utf8BOM)]) == string(utf8BOM) {
|
||
trimmed = trimmed[len(utf8BOM):]
|
||
}
|
||
if utf8.Valid(trimmed) {
|
||
return trimmed, nil
|
||
}
|
||
decoded, err := simplifiedchinese.GBK.NewDecoder().Bytes(trimmed)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("GBK 解码失败: %w", err)
|
||
}
|
||
if !utf8.Valid(decoded) {
|
||
return nil, fmt.Errorf("GBK 解码结果不是合法 UTF-8")
|
||
}
|
||
if strings.Contains(string(decoded), replacementChar) {
|
||
return nil, fmt.Errorf("GBK 解码存在无法映射的字节")
|
||
}
|
||
return decoded, nil
|
||
}
|