sync: 同步 v1.0.4 并脱敏配置与镜像

This commit is contained in:
MiFaZhan
2026-10-29 14:36:49 +08:00
parent 743e8e6e6e
commit 2206a393f7
516 changed files with 18119 additions and 2253 deletions
+138 -27
View File
@@ -1,17 +1,20 @@
// Package gen
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2026 LiXiujie
// @Author Lxj <li@xiujie.cn>
// @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
// @AutoGenerate Version
package iot
import (
"context"
"errors"
"fmt"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchinput/text"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/exportcenter"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/hook"
@@ -21,15 +24,13 @@ import (
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/do"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/convert"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/excel"
"strings"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
type sIotTSimCardInfo struct{}
@@ -66,6 +67,14 @@ func (s *sIotTSimCardInfo) Model(ctx context.Context, option ...*handler.Option)
// List 获取卡信息表列表
func (s *sIotTSimCardInfo) List(ctx context.Context, in *model.TSimCardInfoListParam) (list []*model.TSimCardInfoListModel, totalCount int, err error) {
var batchCondition string
var batchArgs []interface{}
if in.BatchInput != nil {
batchCondition, batchArgs, err = simCardBatchCondition(ctx, *in.BatchInput)
if err != nil {
return nil, 0, err
}
}
mod := s.Model(ctx)
cardInfoTable := dao.TSimCardInfo.Table()
simChannels := dao.TSimChannels.Table()
@@ -116,6 +125,9 @@ func (s *sIotTSimCardInfo) List(ctx context.Context, in *model.TSimCardInfoListP
dao.TSimCardInfo.Columns().Imsi + " = ?)"
mod = mod.Where(cardValueCondition, in.CardValue, in.CardValue, in.CardValue)
}
if batchCondition != "" {
mod = mod.Where(batchCondition, batchArgs...)
}
if in.Remark != "" {
mod = mod.Where(dao.TSimCardInfo.Columns().Remark+" LIKE ?", "%"+in.Remark+"%")
}
@@ -254,6 +266,7 @@ func (s *sIotTSimCardInfo) List(ctx context.Context, in *model.TSimCardInfoListP
err = gerror.Wrap(err, "获取卡信息表列表失败,请稍后重试!")
return
}
applyCardChannelDisplayNames(ctx, list)
if resolver, resolverErr := newCardDeptDisplayResolver(ctx); resolverErr != nil {
logCardDeptDisplayResolverError(ctx, resolverErr)
} else {
@@ -266,31 +279,127 @@ func (s *sIotTSimCardInfo) List(ctx context.Context, in *model.TSimCardInfoListP
return
}
// Export 导出卡信息表
// exportColumns 取前端传入的导出列。
// 优先解析 JSON 字符串形式(数组绑定可能丢失内容),失败再退回对象数组。
func (s *sIotTSimCardInfo) exportColumns(in *model.TSimCardInfoListParam) []model.ExportColumn {
if raw := strings.TrimSpace(in.ExportColumnsJson); raw != "" {
cols := make([]model.ExportColumn, 0)
if err := gjson.New(raw).Scan(&cols); err == nil && len(cols) > 0 {
return cols
}
}
return in.ExportColumns
}
const simCardBatchMaxRows = 1000
// simCardBatchCondition 将批量查询输入编译为查询条件。
// 每行支持 1 至 3 个号码值,同一行的多个值表示同一张卡的多个字段值。
// 同一行的值互不相同,必然落在不同字段上,因此“该行每个值都命中这张卡的某个字段”
// 已等价于“这些值都属于这张卡”,无需判断某个值具体是 ICCID、MSISDN 还是 IMSI。
func simCardBatchCondition(ctx context.Context, input string) (string, []interface{}, error) {
lines, err := text.ParseWhitespaceFields(ctx, input)
if errors.Is(err, text.ErrEmptyInput) {
return "", nil, gerror.New("批量查询卡号不能为空")
}
if err != nil {
return "", nil, err
}
if len(lines) > simCardBatchMaxRows {
return "", nil, gerror.New("批量查询最多支持1000行")
}
columns := dao.TSimCardInfo.Columns()
// 单值行之间相互独立,合并成 IN 列表后语义不变,可显著降低条件求值成本。
singleValues := make([]string, 0, len(lines))
singleIndex := make(map[string]struct{}, len(lines))
// 多值行需要保留同一行内的配对关系,不能跨行合并。
multiConditions := make([]string, 0, len(lines))
multiArgs := make([]interface{}, 0, len(lines)*9)
multiIndex := make(map[string]struct{}, len(lines))
for _, line := range lines {
switch len(line.Fields) {
case 1:
value := line.Fields[0]
if _, exists := singleIndex[value]; exists {
continue
}
singleIndex[value] = struct{}{}
singleValues = append(singleValues, value)
case 2, 3:
key := strings.Join(line.Fields, "\x00")
if _, exists := multiIndex[key]; exists {
continue
}
multiIndex[key] = struct{}{}
groups := make([]string, 0, len(line.Fields))
for _, value := range line.Fields {
groups = append(groups, "("+columns.Iccid+" = ? OR "+
columns.Msisdn+" = ? OR "+
columns.Imsi+" = ?)")
multiArgs = append(multiArgs, value, value, value)
}
multiConditions = append(multiConditions, "("+strings.Join(groups, " AND ")+")")
default:
return "", nil, gerror.Newf("第%d行格式错误,每行支持 1 至 3 个号码值", line.RowNo)
}
}
parts := make([]string, 0, 2)
args := make([]interface{}, 0, len(singleValues)*3+len(multiArgs))
if len(singleValues) > 0 {
placeholders := "(" + strings.TrimSuffix(strings.Repeat("?,", len(singleValues)), ",") + ")"
parts = append(parts, "("+columns.Iccid+" IN "+placeholders+" OR "+
columns.Msisdn+" IN "+placeholders+" OR "+
columns.Imsi+" IN "+placeholders+")")
for repeat := 0; repeat < 3; repeat++ {
for _, value := range singleValues {
args = append(args, value)
}
}
}
if len(multiConditions) > 0 {
parts = append(parts, "("+strings.Join(multiConditions, " OR ")+")")
args = append(args, multiArgs...)
}
return "(" + strings.Join(parts, " OR ") + ")", args, nil
}
// Export 导出卡信息(异步:提交任务后到下载中心取文件)
// 导出的列由前端按当前列表显示列传入,未传时按列表模型字段顺序全量导出。
func (s *sIotTSimCardInfo) Export(ctx context.Context, in *model.TSimCardInfoListParam) (err error) {
list, totalCount, err := s.List(ctx, in)
if err != nil {
return
if in.BatchInput != nil {
if _, _, err = simCardBatchCondition(ctx, *in.BatchInput); err != nil {
return err
}
}
// 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
tags, err := convert.GetEntityDescTags(model.TSimCardInfoExportModel{})
if err != nil {
return
}
var (
fileName = "导出卡信息表-" + gctx.CtxId(ctx)
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, (totalCount+in.PageSize-1)/in.PageSize, in.Page, len(list))
exports []*model.TSimCardInfoExportModel
)
if err = gconv.Scan(list, &exports); err != nil {
return
}
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
return
_, err = exportcenter.Submit(ctx, &exportcenter.Request{
BizKey: "tSimCardInfo",
BizName: "卡信息",
PermCode: "cpm:iot:tSimCardInfo:export",
QueryParam: in,
Columns: s.exportColumns(in),
Tags: func() ([]string, error) {
return convert.GetEntityDescTags(model.TSimCardInfoListModel{})
},
Fetch: func(ctx context.Context, page, pageSize int) (rows []interface{}, total int, err error) {
query := *in
query.Page = page
query.PageSize = pageSize
list, count, err := s.List(ctx, &query)
if err != nil {
return nil, 0, err
}
rows = make([]interface{}, 0, len(list))
for _, item := range list {
rows = append(rows, item)
}
return rows, count, nil
},
})
return err
}
// Edit 修改/新增卡信息表
@@ -428,6 +537,7 @@ func (s *sIotTSimCardInfo) View(ctx context.Context, in *model.TSimCardInfoViewP
return
}
if res != nil {
res.ChanName = channelDisplayName(canViewChannelFullName(ctx), res.ChanName, res.ChanAlias)
if resolver, resolverErr := newCardDeptDisplayResolver(ctx); resolverErr != nil {
logCardDeptDisplayResolverError(ctx, resolverErr)
} else {
@@ -940,6 +1050,7 @@ func (s *sIotTSimCardInfo) GetCardsByPackageCodes(ctx context.Context, req *mode
err = gerror.Wrap(err, "获取卡列表失败,请稍后重试!")
return
}
applyCardChannelDisplayNames(ctx, list)
if resolver, resolverErr := newCardDeptDisplayResolver(ctx); resolverErr != nil {
logCardDeptDisplayResolverError(ctx, resolverErr)
} else {