chore: 并入 iotlcm-admin-svr 历史到 admin-svr/(原提交 49818c6)
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
package warningnotify
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type groupKey struct {
|
||||
Business string
|
||||
TenantID string
|
||||
DeptID int64
|
||||
CreatedBy int64
|
||||
Method string
|
||||
Recipients string
|
||||
Category string
|
||||
}
|
||||
|
||||
func BuildBatches(events []Event) []Batch {
|
||||
if len(events) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
grouped := make(map[groupKey]*Batch)
|
||||
for _, event := range events {
|
||||
event = normalizeEvent(event)
|
||||
for _, method := range methodsForEvent(event) {
|
||||
for _, recipients := range recipientGroupsForMethod(method, event) {
|
||||
if methodRequiresRecipient(method) && len(recipients) == 0 {
|
||||
continue
|
||||
}
|
||||
key := groupKeyForEvent(method, recipients, event)
|
||||
batch := grouped[key]
|
||||
if batch == nil {
|
||||
batch = &Batch{
|
||||
Business: event.Business,
|
||||
Method: method,
|
||||
TenantID: event.TenantID,
|
||||
DeptID: event.DeptID,
|
||||
DeptName: event.DeptName,
|
||||
CreatedBy: event.CreatedBy,
|
||||
Category: event.Category,
|
||||
Recipients: recipients,
|
||||
Items: make([]Event, 0),
|
||||
}
|
||||
grouped[key] = batch
|
||||
} else if strings.TrimSpace(batch.DeptName) == "" {
|
||||
batch.DeptName = event.DeptName
|
||||
}
|
||||
batch.Items = append(batch.Items, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys := make([]groupKey, 0, len(grouped))
|
||||
for key := range grouped {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return compareGroupKey(keys[i], keys[j]) < 0
|
||||
})
|
||||
|
||||
batches := make([]Batch, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
batch := grouped[key]
|
||||
sort.SliceStable(batch.Items, func(i, j int) bool {
|
||||
if batch.Items[i].WarnStage != batch.Items[j].WarnStage {
|
||||
return batch.Items[i].WarnStage > batch.Items[j].WarnStage
|
||||
}
|
||||
if batch.Items[i].ItemCode != batch.Items[j].ItemCode {
|
||||
return batch.Items[i].ItemCode < batch.Items[j].ItemCode
|
||||
}
|
||||
return batch.Items[i].EventID < batch.Items[j].EventID
|
||||
})
|
||||
batch.WarnStage = highestStage(batch.Items)
|
||||
applyContent(batch)
|
||||
batches = append(batches, *batch)
|
||||
}
|
||||
return batches
|
||||
}
|
||||
|
||||
func groupKeyForEvent(method string, recipients []string, event Event) groupKey {
|
||||
key := groupKey{
|
||||
Business: event.Business,
|
||||
TenantID: event.TenantID,
|
||||
DeptID: event.DeptID,
|
||||
CreatedBy: event.CreatedBy,
|
||||
Method: method,
|
||||
Recipients: strings.Join(recipients, ","),
|
||||
Category: event.Category,
|
||||
}
|
||||
if method == MethodSMS || method == MethodEmail {
|
||||
key.DeptID = 0
|
||||
key.CreatedBy = 0
|
||||
}
|
||||
if method == MethodWechat {
|
||||
key.DeptID = 0
|
||||
key.CreatedBy = 0
|
||||
key.Recipients = ""
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func compareGroupKey(left, right groupKey) int {
|
||||
leftParts := []string{left.TenantID, left.Business, left.Method, left.Recipients, left.Category}
|
||||
rightParts := []string{right.TenantID, right.Business, right.Method, right.Recipients, right.Category}
|
||||
for i := range leftParts {
|
||||
if leftParts[i] < rightParts[i] {
|
||||
return -1
|
||||
}
|
||||
if leftParts[i] > rightParts[i] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if left.DeptID != right.DeptID {
|
||||
if left.DeptID < right.DeptID {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
if left.CreatedBy != right.CreatedBy {
|
||||
if left.CreatedBy < right.CreatedBy {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func normalizeEvent(event Event) Event {
|
||||
event.Business = strings.TrimSpace(event.Business)
|
||||
if event.Business == "" {
|
||||
event.Business = BusinessSimWarning
|
||||
}
|
||||
event.TenantID = strings.TrimSpace(event.TenantID)
|
||||
event.DeptName = strings.TrimSpace(event.DeptName)
|
||||
event.Category = strings.TrimSpace(event.Category)
|
||||
if event.Category == "" {
|
||||
event.Category = "预警"
|
||||
}
|
||||
event.Kind = strings.TrimSpace(event.Kind)
|
||||
event.ItemCode = strings.TrimSpace(event.ItemCode)
|
||||
event.MSISDN = strings.TrimSpace(event.MSISDN)
|
||||
event.WarnMethods = strings.TrimSpace(event.WarnMethods)
|
||||
event.WarnPhones = strings.TrimSpace(event.WarnPhones)
|
||||
event.WarnEmails = strings.TrimSpace(event.WarnEmails)
|
||||
event.UnitText = strings.TrimSpace(event.UnitText)
|
||||
event.Remark = strings.TrimSpace(event.Remark)
|
||||
event.OperationText = strings.TrimSpace(event.OperationText)
|
||||
event.BatchNo = strings.TrimSpace(event.BatchNo)
|
||||
return event
|
||||
}
|
||||
|
||||
func methodsForEvent(event Event) []string {
|
||||
values := splitList(event.WarnMethods)
|
||||
seen := map[string]struct{}{MethodPlatform: {}}
|
||||
result := []string{MethodPlatform}
|
||||
for _, value := range values {
|
||||
switch value {
|
||||
case MethodSMS, MethodEmail, MethodPhone, MethodPlatform:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[value]; exists {
|
||||
continue
|
||||
}
|
||||
seen[value] = struct{}{}
|
||||
result = append(result, value)
|
||||
}
|
||||
sort.SliceStable(result, func(i, j int) bool {
|
||||
return methodOrder(result[i]) < methodOrder(result[j])
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func methodOrder(method string) int {
|
||||
switch method {
|
||||
case MethodPlatform:
|
||||
return 1
|
||||
case MethodEmail:
|
||||
return 2
|
||||
case MethodSMS:
|
||||
return 3
|
||||
case MethodPhone:
|
||||
return 4
|
||||
case MethodWechat:
|
||||
return 5
|
||||
default:
|
||||
return 99
|
||||
}
|
||||
}
|
||||
|
||||
func recipientGroupsForMethod(method string, event Event) [][]string {
|
||||
switch method {
|
||||
case MethodSMS:
|
||||
return singleRecipientGroups(splitList(event.WarnPhones))
|
||||
case MethodEmail:
|
||||
return singleRecipientGroups(splitList(event.WarnEmails))
|
||||
default:
|
||||
return [][]string{{}}
|
||||
}
|
||||
}
|
||||
|
||||
func methodRequiresRecipient(method string) bool {
|
||||
return method == MethodSMS || method == MethodEmail
|
||||
}
|
||||
|
||||
func singleRecipientGroups(recipients []string) [][]string {
|
||||
groups := make([][]string, 0, len(recipients))
|
||||
for _, recipient := range recipients {
|
||||
recipient = strings.TrimSpace(recipient)
|
||||
if recipient == "" {
|
||||
continue
|
||||
}
|
||||
groups = append(groups, []string{recipient})
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
func splitList(value string) []string {
|
||||
parts := strings.FieldsFunc(value, func(r rune) bool {
|
||||
switch r {
|
||||
case ',', ';', ',', ';', '|', '\n', '\r', '\t', ' ':
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
seen := make(map[string]struct{}, len(parts))
|
||||
result := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[part]; exists {
|
||||
continue
|
||||
}
|
||||
seen[part] = struct{}{}
|
||||
result = append(result, part)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func highestStage(items []Event) int {
|
||||
stage := 0
|
||||
for _, item := range items {
|
||||
if item.WarnStage > stage {
|
||||
stage = item.WarnStage
|
||||
}
|
||||
}
|
||||
return stage
|
||||
}
|
||||
Reference in New Issue
Block a user