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
@@ -10,6 +10,7 @@ import (
"net/http"
"net/url"
"os"
"sort"
"strconv"
"strings"
"sync"
@@ -83,7 +84,7 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
batch.DeptID,
batch.Category,
batch.WarnStage,
len(batch.Items),
batchItemCount(batch),
)
return nil
}
@@ -92,40 +93,61 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
return nil
}
deliveries := resolveTerminalPlatformDeliveries(ctx, batch)
deliveries := resolveWechatDeliveries(ctx, batch)
if len(deliveries) == 0 {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no terminal recipients, tenantId:%s, count:%d", batch.TenantID, len(batch.Items))
return nil
}
var sendErrs []string
for _, delivery := range deliveries {
if len(delivery.Group.UserIDs) == 0 || len(delivery.Batch.Items) == 0 {
if len(delivery.Group.UserIDs) == 0 || batchItemCount(delivery.Batch) == 0 {
continue
}
userID := delivery.Group.UserIDs[0]
if batch.Business == BusinessSimWarning {
enabled, err := warningWechatEnabled(ctx, batch.TenantID, userID)
if err != nil {
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query preference: %v", userID, err))
continue
}
if !enabled {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:user preference disabled, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, batchItemCount(delivery.Batch))
continue
}
}
bindings, err := queryWechatBindings(ctx, batch.TenantID, userID)
if err != nil {
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query binding: %v", userID, err))
continue
}
if len(bindings) == 0 {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no openid, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, len(delivery.Batch.Items))
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no openid, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, batchItemCount(delivery.Batch))
continue
}
acquired, sentKey, err := acquireWechatSendDedupe(ctx, delivery.Batch, userID)
if err != nil {
g.Log().Warningf(ctx, "WarningNotify wechat subscribe dedupe check failed, tenantId:%s, userId:%d, category:%s, stage:%d, count:%d, err:%+v",
batch.TenantID, userID, delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items), err)
batch.TenantID, userID, delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch), err)
} else if !acquired {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:duplicated, tenantId:%s, userId:%d, key:%s, category:%s, stage:%d, count:%d",
batch.TenantID, userID, sentKey, delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items))
batch.TenantID, userID, sentKey, delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch))
continue
}
successCount := 0
for _, binding := range bindings {
if batch.Business == BusinessSimWarning {
enabled, err := warningWechatEnabled(ctx, batch.TenantID, userID)
if err != nil {
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query preference: %v", userID, err))
continue
}
if !enabled {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:user preference disabled before send, tenantId:%s, userId:%d", batch.TenantID, userID)
continue
}
}
templateID := wechatTemplateID(delivery.Batch.Items, cfg.TemplateID)
if templateID == "" {
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d template id empty", userID))
@@ -135,11 +157,11 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
if err := sendWechatSubscription(ctx, cfg, payload); err != nil {
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d openid=%s: %v", userID, maskOpenID(binding.OpenID), err))
g.Log().Errorf(ctx, "WarningNotify wechat subscribe failed, tenantId:%s, userId:%d, openid:%s, category:%s, stage:%d, count:%d, err:%+v",
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items), err)
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch), err)
continue
}
g.Log().Infof(ctx, "WarningNotify wechat subscribe sent, tenantId:%s, userId:%d, openid:%s, category:%s, stage:%d, count:%d",
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items))
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch))
successCount++
}
if acquired && successCount == 0 {
@@ -153,6 +175,107 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
return nil
}
func resolveWechatDeliveries(ctx context.Context, batch Batch) []platformDelivery {
if batch.prepared != nil {
return []platformDelivery{{Group: *batch.prepared, Batch: batch}}
}
deliveries := resolveTerminalPlatformDeliveries(ctx, batch)
appendEnterpriseWechatDeliveries(ctx, batch, &deliveries)
if len(deliveries) == 0 {
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no eligible recipients, tenantId:%s, count:%d", batch.TenantID, batchItemCount(batch))
}
return deliveries
}
func appendEnterpriseWechatDeliveries(ctx context.Context, batch Batch, deliveries *[]platformDelivery) {
if batch.Business != BusinessSimWarning {
return
}
itemsByUser := make(map[int64][]Event)
seenByUser := make(map[int64]map[int]struct{})
for index, item := range batch.Items {
if item.ItemType != 1 {
continue
}
createdBy := item.CreatedBy
if createdBy <= 0 {
createdBy = batch.CreatedBy
}
if createdBy <= 0 || item.ItemID <= 0 {
continue
}
userID, ok, err := queryEnterpriseWarningUser(ctx, batch.TenantID, createdBy, item.ItemID)
if err != nil {
g.Log().Warningf(ctx, "WarningNotify query enterprise user failed, tenantId:%s, userId:%d, cardId:%d, err:%+v", batch.TenantID, createdBy, item.ItemID, err)
continue
}
if ok {
appendTerminalEvent(itemsByUser, seenByUser, userID, index, item)
}
}
userIDs := make([]int64, 0, len(itemsByUser))
for userID := range itemsByUser {
userIDs = append(userIDs, userID)
}
sort.Slice(userIDs, func(i, j int) bool { return userIDs[i] < userIDs[j] })
for _, userID := range userIDs {
items := itemsByUser[userID]
enterpriseBatch := batch
enterpriseBatch.Items = append([]Event(nil), items...)
enterpriseBatch.WarnStage = highestStage(enterpriseBatch.Items)
*deliveries = append(*deliveries, platformDelivery{
Group: platformRecipientGroup{SendUserType: sendUserTypeAgent, UserIDs: []int64{userID}},
Batch: enterpriseBatch,
})
}
}
func enterpriseWarningRecipientEligible(userType string, userDeptID, cardDeptID int64, ancestors string) bool {
if userType != consts.SysUserTypeSys || userDeptID <= 0 || cardDeptID <= 0 {
return false
}
if userDeptID == cardDeptID {
return true
}
target := strconv.FormatInt(userDeptID, 10)
for _, ancestor := range strings.Split(ancestors, ",") {
if strings.TrimSpace(ancestor) == target {
return true
}
}
return false
}
func queryEnterpriseWarningUser(ctx context.Context, tenantID string, userID, cardID int64) (int64, bool, error) {
if strings.TrimSpace(tenantID) == "" || userID <= 0 || cardID <= 0 {
return 0, false, nil
}
var result struct {
UserID int64 `orm:"user_id"`
UserType string `orm:"user_type"`
DeptID int64 `orm:"dept_id"`
CardDeptID int64 `orm:"card_dept_id"`
Ancestors string `orm:"ancestors"`
}
err := g.DB().Model(dao.TSimCardInfo.Table()+" c").Ctx(ctx).Safe().
LeftJoin(dao.SysUser.Table()+" u", "u.user_id = "+strconv.FormatInt(userID, 10)).
InnerJoin(dao.SysDept.Table()+" d", "d.dept_id = c.dept_id AND d.tenant_id = c.tenant_id").
InnerJoin(dao.SysDept.Table()+" ud", "ud.dept_id = u.dept_id AND ud.tenant_id = u.tenant_id").
Fields("u.user_id, u.user_type, u.dept_id, c.dept_id AS card_dept_id, d.ancestors").
Where("c.tenant_id", tenantID).
Where("c.id", cardID).
Where("u.tenant_id", tenantID).
Where("u.user_type", consts.SysUserTypeSys).
Where("u.status", consts.SysDeptStatusNormal).
Where("u.deleted_at IS NULL").
Where("d.deleted_at IS NULL").
Where("ud.deleted_at IS NULL").
Scan(&result)
if err != nil {
return 0, false, err
}
return result.UserID, result.UserID > 0 && enterpriseWarningRecipientEligible(result.UserType, result.DeptID, result.CardDeptID, result.Ancestors), nil
}
func loadWarningWechatConfig(ctx context.Context) (warningWechatConfig, bool) {
var cfg warningWechatConfig
loaded := false
@@ -358,6 +481,9 @@ func wechatBatchHasExpireKind(batch Batch) bool {
func wechatBatchTime(batch Batch) time.Time {
latest := latestEvent(batch.Items)
if !batch.LatestTime.IsZero() {
latest.WarnTime = batch.LatestTime
}
if latest.WarnTime.IsZero() {
return time.Now()
}
@@ -392,6 +518,9 @@ func wechatTemplateID(items []Event, fallback string) string {
func buildWechatPayload(batch Batch, openID string, templateID string, page string) warningWechatPayload {
latest := latestEvent(batch.Items)
if !batch.LatestTime.IsZero() {
latest.WarnTime = batch.LatestTime
}
return warningWechatPayload{
ToUser: strings.TrimSpace(openID),
TemplateID: strings.TrimSpace(templateID),
@@ -417,25 +546,25 @@ func latestEvent(items []Event) Event {
}
func wechatDeviceText(batch Batch) string {
if len(batch.Items) == 0 {
if batchItemCount(batch) == 0 {
return "--"
}
first := displayObjectCode(batch.Items[0])
if len(batch.Items) == 1 {
if batchItemCount(batch) == 1 {
return first
}
return fmt.Sprintf("%s等%d张卡", first, len(batch.Items))
return fmt.Sprintf("%s等%d张卡", first, batchItemCount(batch))
}
func wechatDeviceCharacterText(batch Batch) string {
if len(batch.Items) == 0 {
if batchItemCount(batch) == 0 {
return "NA"
}
first := displayObjectCode(batch.Items[0])
if len(batch.Items) == 1 {
if batchItemCount(batch) == 1 {
return first
}
return fmt.Sprintf("%sx%d", first, len(batch.Items))
return fmt.Sprintf("TOTAL-%d", batchItemCount(batch))
}
func wechatTypeText(batch Batch) string {
@@ -443,25 +572,28 @@ func wechatTypeText(batch Batch) string {
if title == "" {
title = "设备预警"
}
if len(batch.Items) > 1 {
return fmt.Sprintf("%s,共%d张卡", title, len(batch.Items))
if batchItemCount(batch) > 1 {
return fmt.Sprintf("%s,共%d张卡", title, batchItemCount(batch))
}
return title
}
func wechatReasonText(batch Batch) string {
if len(batch.Items) == 1 {
if batchItemCount(batch) == 1 {
return emailWarningReason(batch.Items[0])
}
reason := fmt.Sprintf("共%d张卡触发预警,最高级别:%s", len(batch.Items), levelText(highestLevel(batch.Items)))
if hasAffectOperation(batch.Items) {
reason := fmt.Sprintf("%s\uff0c\u5171%d\u5f20\u5361", levelText(batchHighestLevel(batch)), batchItemCount(batch))
if batchHasAffectOperation(batch) {
reason += ",涉及停机或断网"
}
return reason
}
func wechatValueText(batch Batch) string {
if len(batch.Items) == 0 {
if batchItemCount(batch) > 1 {
return fmt.Sprintf("TOTAL-%d", batchItemCount(batch))
}
if batchItemCount(batch) == 0 {
return "NA"
}
item := batch.Items[0]