From 041125fb7a76b1eba2bd1fc8b83d4fef0d15ab3a Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 27 Feb 2025 15:14:03 +0800 Subject: [PATCH 1/6] =?UTF-8?q?sql:=20SGW-C=E5=AF=BC=E5=87=BA=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=A4=9A=E8=AF=AD=E8=A8=80=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/install/sys_dict_data1_i18n_zh.sql | 1 + database/install/sys_dict_data2_i18n_en.sql | 1 + database/upgrade/upg_sys_dict_data1_i18n_zh.sql | 1 + database/upgrade/upg_sys_dict_data2_i18n_en.sql | 1 + 4 files changed, 4 insertions(+) diff --git a/database/install/sys_dict_data1_i18n_zh.sql b/database/install/sys_dict_data1_i18n_zh.sql index 6a774ed4..628642b1 100644 --- a/database/install/sys_dict_data1_i18n_zh.sql +++ b/database/install/sys_dict_data1_i18n_zh.sql @@ -696,5 +696,6 @@ INSERT INTO `sys_dict_data` VALUES (2185, 2185, 'config.sys.homePageRemark', ' INSERT INTO `sys_dict_data` VALUES (2186, 2186, 'menu.config.neOverview', '网元概览', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2187, 2187, 'menu.config.neOverviewRemark', '显示所有网元状态配置和license等概览信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2188, 2188, 'job.exportSGWCCDR', '定期从漫游数据话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2189, 2189, 'table.cdr_event_sgwc', '漫游数据话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_dict_data2_i18n_en.sql b/database/install/sys_dict_data2_i18n_en.sql index d1beb8bf..f9b72904 100644 --- a/database/install/sys_dict_data2_i18n_en.sql +++ b/database/install/sys_dict_data2_i18n_en.sql @@ -696,5 +696,6 @@ INSERT INTO `sys_dict_data` VALUES (4185, 4185, 'config.sys.homePageRemark', 'Se INSERT INTO `sys_dict_data` VALUES (4186, 4186, 'menu.config.neOverview', 'NE Overview', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4187, 4187, 'menu.config.neOverviewRemark', 'Displays overview information such as status, configuration and license of all network elements', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4188, 4188, 'job.exportSGWCCDR', 'Export regularly from Roaming Data CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4189, 4189, 'table.cdr_event_sgwc', 'Roaming Data CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql index ed2b9f0e..fc606455 100644 --- a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql +++ b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql @@ -703,5 +703,6 @@ REPLACE INTO `sys_dict_data` VALUES (2185, 2185, 'config.sys.homePageRemark', ' REPLACE INTO `sys_dict_data` VALUES (2186, 2186, 'menu.config.neOverview', '网元概览', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2187, 2187, 'menu.config.neOverviewRemark', '显示所有网元状态配置和license等概览信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2188, 2188, 'job.exportSGWCCDR', '定期从漫游数据话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2189, 2189, 'table.cdr_event_sgwc', '漫游数据话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_data2_i18n_en.sql b/database/upgrade/upg_sys_dict_data2_i18n_en.sql index 86ac7b15..5a929a3c 100644 --- a/database/upgrade/upg_sys_dict_data2_i18n_en.sql +++ b/database/upgrade/upg_sys_dict_data2_i18n_en.sql @@ -702,5 +702,6 @@ REPLACE INTO `sys_dict_data` VALUES (4185, 4185, 'config.sys.homePageRemark', 'S REPLACE INTO `sys_dict_data` VALUES (4186, 4186, 'menu.config.neOverview', 'NE Overview', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4187, 4187, 'menu.config.neOverviewRemark', 'Displays overview information such as status, configuration and license of all network elements', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4188, 4188, 'job.exportSGWCCDR', 'Export regularly from Roaming Data CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4189, 4189, 'table.cdr_event_sgwc', 'Roaming Data CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; From e0336bb0f3822cbe2f457455195ca2a79c1689f8 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Fri, 28 Feb 2025 19:53:34 +0800 Subject: [PATCH 2/6] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=202.2502.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ makefile | 2 +- mkpkg.sh | 2 +- restagent/makefile | 2 +- sshsvc/makefile | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c3665b..af491e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # 版本发布日志 +## 2.2502.4-20250228 + +- 修复 SGW-C导出管理多语言显示 +- 优化 网元状态告警处理逻辑,增加状态更新时间戳 +- 修复 CDR/Event 查询时间格式统一时间戳int64 + ## 2.2502.3-20250221 - 修复 网元授权序号查询 diff --git a/makefile b/makefile index da45b9ee..628f94aa 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ ProjectL = omc ProjectU = OMC PROJECT = $(ProjectL) -VERSION = 2.2502.3 +VERSION = 2.2502.4 RelDate = `date +%Y%m%d` Release = $(RelDate) RelVer = $(VERSION)-$(RelDate) diff --git a/mkpkg.sh b/mkpkg.sh index 6ffb2d3d..3af0f518 100755 --- a/mkpkg.sh +++ b/mkpkg.sh @@ -2,7 +2,7 @@ ProcList="restagent sshsvc" ProjectL=omc -VERSION=2.2502.3 +VERSION=2.2502.4 RelDate=`date +%Y%m%d` Release=${RelDate} RelVer=${VERSION}-${RelDate} diff --git a/restagent/makefile b/restagent/makefile index 6685169a..c4ac488c 100644 --- a/restagent/makefile +++ b/restagent/makefile @@ -1,7 +1,7 @@ # Makefile for rest agent project PROJECT = OMC -VERSION = 2.2502.3 +VERSION = 2.2502.4 PLATFORM = amd64 ARMPLATFORM = aarch64 BUILDDIR = ../../build diff --git a/sshsvc/makefile b/sshsvc/makefile index 13d215cf..781de273 100644 --- a/sshsvc/makefile +++ b/sshsvc/makefile @@ -1,7 +1,7 @@ # Makefile for OMC-OMC-crontask project PROJECT = OMC -VERSION = 2.2502.3 +VERSION = 2.2502.4 LIBDIR = be.ems/lib BINNAME = sshsvc From 32630fbb4adee93d03d35697ec4aaf1512bea10c Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 4 Mar 2025 14:51:15 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E5=91=8A=E8=AD=A6=E8=BD=AC=E5=8F=91?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/fm/email.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/features/fm/email.go b/features/fm/email.go index bd4d0c3a..cae7550f 100644 --- a/features/fm/email.go +++ b/features/fm/email.go @@ -15,6 +15,13 @@ import ( func AlarmEmailForward(alarmData *Alarm) error { log.Info("AlarmEmailForward processing... ") + alarmStatus := "Clear" + if alarmData.AlarmStatus == 1 { + alarmStatus = "Active" + } + severity := alarmData.OrigSeverity + subjectTime := fmt.Sprintf("%s-%s-%s", severity, alarmData.NeName, alarmData.AlarmTitle) + message := fmt.Sprintf(`
Alarm information
Sequence: %d
@@ -22,9 +29,9 @@ func AlarmEmailForward(alarmData *Alarm) error {Title: %s
Severity: %s
Event Time: %s
-Alarm Status: %d
+Alarm Status: %s
Automatic sent by OMC, please do not reply!
- `, alarmData.AlarmSeq, alarmData.NeName, alarmData.AlarmTitle, alarmData.OrigSeverity, alarmData.EventTime, alarmData.AlarmStatus) + `, alarmData.AlarmSeq, alarmData.NeName, alarmData.AlarmTitle, alarmData.OrigSeverity, alarmData.EventTime, alarmStatus) // message := fmt.Sprintf(` // Alarm information @@ -81,7 +88,7 @@ func AlarmEmailForward(alarmData *Alarm) error { //m.SetHeader("To", "zhangshuzhong@agrandtech.com", "simonzhangsz@outlook.com") // 收件人,可以多个收件人,但必须使用相同的 SMTP 连接 //m.SetHeader("Cc", "******@qq.com") // 抄送,可以多个 //m.SetHeader("Bcc", "******@qq.com") // 暗送,可以多个 - m.SetHeader("Subject", "Alarm from OMC!") // 邮件主题 + m.SetHeader("Subject", subjectTime) // 邮件主题 // text/html 的意思是将文件的 content-type 设置为 text/html 的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。 // 可以通过 text/html 处理文本格式进行特殊处理,如换行、缩进、加粗等等 From 986624c48f0b24edecd98670c116ff69252ce551 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 4 Mar 2025 14:51:52 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96UPF=E6=B5=81?= =?UTF-8?q?=E9=87=8F=E7=BB=9F=E8=AE=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/framework/redis/expand.go | 175 ++++++++++++++++++ src/framework/redis/redis.go | 109 ----------- src/modules/monitor/controller/sys_cache.go | 2 +- src/modules/network_data/controller/upf.go | 5 +- src/modules/network_data/network_data.go | 10 + .../network_data/service/all_perf_kpi.go | 120 +++++++++--- src/modules/ws/processor/upf_total_flow.go | 4 +- 7 files changed, 282 insertions(+), 143 deletions(-) create mode 100644 src/framework/redis/expand.go diff --git a/src/framework/redis/expand.go b/src/framework/redis/expand.go new file mode 100644 index 00000000..85a8076a --- /dev/null +++ b/src/framework/redis/expand.go @@ -0,0 +1,175 @@ +package redis + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + "be.ems/src/framework/logger" + "github.com/redis/go-redis/v9" +) + +// 连接Redis实例 +func ConnectPush(source string, rdb *redis.Client) { + if rdb == nil { + delete(rdbMap, source) + return + } + rdbMap[source] = rdb +} + +// 批量获得缓存数据 [key]result +func GetHashBatch(source string, keys []string) (map[string]map[string]string, error) { + result := make(map[string]map[string]string, 0) + if len(keys) == 0 { + return result, fmt.Errorf("not keys") + } + + // 数据源 + rdb := RDB(source) + if rdb == nil { + return result, fmt.Errorf("redis not client") + } + + // 创建一个有限的并发控制信号通道 + sem := make(chan struct{}, 10) + var wg sync.WaitGroup + var mt sync.Mutex + batchSize := 1000 + total := len(keys) + if total < batchSize { + batchSize = total + } + + for i := 0; i < total; i += batchSize { + wg.Add(1) + go func(start int) { + ctx := context.Background() + // 并发控制,限制同时执行的 Goroutine 数量 + sem <- struct{}{} + defer func() { + <-sem + ctx.Done() + wg.Done() + }() + + // 检查索引是否越界 + end := start + batchSize + if end > total { + end = total + } + pipe := rdb.Pipeline() + for _, key := range keys[start:end] { + pipe.HGetAll(ctx, key) + } + + cmds, err := pipe.Exec(ctx) + if err != nil { + logger.Errorf("Failed to get hash batch exec err: %v", err) + return + } + + // 将结果添加到 result map 并发访问 + mt.Lock() + defer mt.Unlock() + + // 处理命令结果 + for _, cmd := range cmds { + if cmd.Err() != nil { + logger.Errorf("Failed to get hash batch cmds err: %v", cmd.Err()) + continue + } + // 将结果转换为 *redis.StringStringMapCmd 类型 + rcmd, ok := cmd.(*redis.MapStringStringCmd) + if !ok { + logger.Errorf("Failed to get hash batch type err: %v", cmd.Err()) + continue + } + + key := "-" + args := rcmd.Args() + if len(args) > 0 { + key = fmt.Sprint(args[1]) + } + + result[key] = rcmd.Val() + } + }(i) + } + + wg.Wait() + return result, nil +} + +// GetHash 获得缓存数据 +func GetHash(source, key, field string) (string, error) { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return "", fmt.Errorf("redis not client") + } + + ctx := context.Background() + v, err := rdb.HGet(ctx, key, field).Result() + if errors.Is(err, redis.Nil) { + return "", fmt.Errorf("no key field") + } + if err != nil { + return "", err + } + return v, nil +} + +// SetHash 设置缓存数据 +func SetHash(source, key string, value map[string]any) error { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return fmt.Errorf("redis not client") + } + + ctx := context.Background() + err := rdb.HSet(ctx, key, value).Err() + if err != nil { + logger.Errorf("redis HSet err %v", err) + return err + } + return nil +} + +// IncrBy 累加统计数据 +func IncrBy(source, key, field string, value int64) error { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return fmt.Errorf("redis not client") + } + + // 使用HINCRBY命令进行累加统计 + ctx := context.Background() + err := rdb.HIncrBy(ctx, key, field, value).Err() + if err != nil { + logger.Errorf("redis HIncrBy err %v", err) + return err + } + return nil +} + +// Expire 过期时间设置 +func Expire(source, key string, expiration time.Duration) error { + // 数据源 + rdb := RDB(source) + if rdb == nil { + return fmt.Errorf("redis not client") + } + // 过期时间设置 + ctx := context.Background() + err := rdb.Expire(ctx, key, expiration).Err() + if err != nil { + logger.Errorf("redis HIncrBy err %v", err) + return err + } + return nil +} diff --git a/src/framework/redis/redis.go b/src/framework/redis/redis.go index 88e5cdd0..2a9e25b3 100644 --- a/src/framework/redis/redis.go +++ b/src/framework/redis/redis.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "strings" - "sync" "time" "be.ems/src/framework/config" @@ -31,15 +30,6 @@ if tonumber(current) == 1 then end return tonumber(current);`) -// 连接Redis实例 -func ConnectPush(source string, rdb *redis.Client) { - if rdb == nil { - delete(rdbMap, source) - return - } - rdbMap[source] = rdb -} - // 连接Redis实例 func Connect() { ctx := context.Background() @@ -237,105 +227,6 @@ func Get(source, key string) (string, error) { return value, nil } -// 获得缓存数据Hash -func GetHash(source, key string) (map[string]string, error) { - // 数据源 - rdb := DefaultRDB() - if source != "" { - rdb = RDB(source) - } - - ctx := context.Background() - value, err := rdb.HGetAll(ctx, key).Result() - if err == redis.Nil || err != nil { - return map[string]string{}, err - } - return value, nil -} - -// 批量获得缓存数据 [key]result -func GetHashBatch(source string, keys []string) (map[string]map[string]string, error) { - result := make(map[string]map[string]string, 0) - if len(keys) == 0 { - return result, fmt.Errorf("not keys") - } - - // 数据源 - rdb := DefaultRDB() - if source != "" { - rdb = RDB(source) - } - - // 创建一个有限的并发控制信号通道 - sem := make(chan struct{}, 10) - var wg sync.WaitGroup - var mt sync.Mutex - batchSize := 1000 - total := len(keys) - if total < batchSize { - batchSize = total - } - - for i := 0; i < total; i += batchSize { - wg.Add(1) - go func(start int) { - ctx := context.Background() - // 并发控制,限制同时执行的 Goroutine 数量 - sem <- struct{}{} - defer func() { - <-sem - ctx.Done() - wg.Done() - }() - - // 检查索引是否越界 - end := start + batchSize - if end > total { - end = total - } - pipe := rdb.Pipeline() - for _, key := range keys[start:end] { - pipe.HGetAll(ctx, key) - } - - cmds, err := pipe.Exec(ctx) - if err != nil { - logger.Errorf("Failed to get hash batch exec err: %v", err) - return - } - - // 将结果添加到 result map 并发访问 - mt.Lock() - defer mt.Unlock() - - // 处理命令结果 - for _, cmd := range cmds { - if cmd.Err() != nil { - logger.Errorf("Failed to get hash batch cmds err: %v", cmd.Err()) - continue - } - // 将结果转换为 *redis.StringStringMapCmd 类型 - rcmd, ok := cmd.(*redis.MapStringStringCmd) - if !ok { - logger.Errorf("Failed to get hash batch type err: %v", cmd.Err()) - continue - } - - key := "-" - args := rcmd.Args() - if len(args) > 0 { - key = fmt.Sprint(args[1]) - } - - result[key] = rcmd.Val() - } - }(i) - } - - wg.Wait() - return result, nil -} - // 判断是否存在 func Has(source string, keys ...string) (bool, error) { // 数据源 diff --git a/src/modules/monitor/controller/sys_cache.go b/src/modules/monitor/controller/sys_cache.go index 06c4c897..6743d0cb 100644 --- a/src/modules/monitor/controller/sys_cache.go +++ b/src/modules/monitor/controller/sys_cache.go @@ -159,7 +159,7 @@ func (s *SysCacheController) ClearCacheSafe(c *gin.Context) { model.NewSysCacheNames(i18n.TKey(language, "cache.name.ne_data"), cachekey.NE_DATA_KEY), } for _, v := range caches { - cacheKeys, err := redis.GetKeys("", v.CacheName+":*") + cacheKeys, err := redis.GetKeys("", v.CacheName+"*") if err != nil { continue } diff --git a/src/modules/network_data/controller/upf.go b/src/modules/network_data/controller/upf.go index fcd48f3b..c2c2ec1a 100644 --- a/src/modules/network_data/controller/upf.go +++ b/src/modules/network_data/controller/upf.go @@ -56,7 +56,6 @@ func (s *UPFController) TotalFlow(c *gin.Context) { return } - data := s.perfKPIService.SelectUPFTotalFlow(neInfo.NeType, neInfo.RmUID, querys.Day) - - c.JSON(200, result.OkData(data)) + up, down := s.perfKPIService.UPFTodayFlowFind(neInfo.RmUID, querys.Day) + c.JSON(200, result.OkData(map[string]int64{"up": up, "down": down})) } diff --git a/src/modules/network_data/network_data.go b/src/modules/network_data/network_data.go index 6f7cf295..018818d0 100644 --- a/src/modules/network_data/network_data.go +++ b/src/modules/network_data/network_data.go @@ -6,6 +6,7 @@ import ( "be.ems/src/framework/middleware/collectlogs" "be.ems/src/framework/middleware/repeat" "be.ems/src/modules/network_data/controller" + "be.ems/src/modules/network_data/service" "github.com/gin-gonic/gin" ) @@ -14,6 +15,9 @@ import ( func Setup(router *gin.Engine) { logger.Infof("开始加载 ====> network_data 模块路由") + // 启动时需要的初始参数 + InitLoad() + neDataGroup := router.Group("/neData") // 性能统计信息 @@ -318,3 +322,9 @@ func Setup(router *gin.Engine) { ) } } + +// InitLoad 初始参数 +func InitLoad() { + // 启动时,加载UPF上下行流量 + go service.NewPerfKPI.UPFTodayFlowLoad() +} diff --git a/src/modules/network_data/service/all_perf_kpi.go b/src/modules/network_data/service/all_perf_kpi.go index b4aef0c4..74b58b95 100644 --- a/src/modules/network_data/service/all_perf_kpi.go +++ b/src/modules/network_data/service/all_perf_kpi.go @@ -7,8 +7,10 @@ import ( "be.ems/src/framework/constants/cachekey" "be.ems/src/framework/redis" + "be.ems/src/framework/utils/parse" "be.ems/src/modules/network_data/model" "be.ems/src/modules/network_data/repository" + neModel "be.ems/src/modules/network_element/model" ) // 实例化数据层 PerfKPI 结构体 @@ -42,38 +44,100 @@ func (r *PerfKPI) SelectGoldKPITitle(neType string) []model.GoldKPITitle { return r.perfKPIRepository.SelectGoldKPITitle(neType) } -// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行 -func (r *PerfKPI) SelectUPFTotalFlow(neType, rmUID string, day int) map[string]any { - now := time.Now() +// UPFTodayFlowFind 查询UPF总流量 N3上行 N6下行 +func (r PerfKPI) UPFTodayFlowFind(rmUID string, day int) (int64, int64) { // 获取当前日期 - endDate := fmt.Sprint(now.UnixMilli()) - // 将当前日期前几天数 - startDate := fmt.Sprint(now.AddDate(0, 0, -day).Truncate(24 * time.Hour).UnixMilli()) + now := time.Now() + var upTotal, downTotal int64 - var info map[string]any + // 查询最近7天的数据 + for i := 0; i <= day; i++ { + dateKey := now.AddDate(0, 0, -i).Format("2006-01-02") + key := fmt.Sprintf("%sUPF_FLOW:%s:%s", cachekey.NE_DATA_KEY, rmUID, dateKey) - // 读取缓存数据 小于2分钟重新缓存 - key := fmt.Sprintf("%sUPF:totalFlow:%s_%d", cachekey.NE_DATA_KEY, rmUID, day) - infoStr, _ := redis.Get("", key) - if infoStr != "" { - json.Unmarshal([]byte(infoStr), &info) - expireSecond, _ := redis.GetExpire("", key) - if expireSecond > 120 { - return info + // 读取缓存数据 + up, err := redis.GetHash("", key, "up") + if err != nil || up == "" { + up = "0" + } + down, err := redis.GetHash("", key, "down") + if err != nil || down == "" { + down = "0" + } + + upTotal += parse.Number(up) + downTotal += parse.Number(down) + } + + return upTotal, downTotal +} + +// UPFTodayFlow UPF流量今日统计 +func (r PerfKPI) UPFTodayFlowUpdate(rmUID string, upValue, downValue int64, rest bool) error { + // 按日期存储统计数据 + dateKey := time.Now().Format("2006-01-02") + key := fmt.Sprintf("%sUPF_FLOW:%s:%s", cachekey.NE_DATA_KEY, rmUID, dateKey) + + // 重置数据 + if rest { + err := redis.SetHash("", key, map[string]any{ + "up": upValue, + "down": downValue, + }) + if err != nil { + return err + } + // 设置key的过期时间为30天,自动清理旧数据 + err = redis.Expire("", key, 30*24*time.Hour) + if err != nil { + return err } } - // down * 8 / 1000 / 1000 单位M - info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate) - if v, ok := info["up"]; ok && v == nil { - info["up"] = 0 - } - if v, ok := info["down"]; ok && v == nil { - info["down"] = 0 - } - // 保存到缓存 - infoJSON, _ := json.Marshal(info) - redis.SetByExpire("", key, string(infoJSON), time.Duration(10)*time.Minute) - - return info + // 使用HIncrBy实时累加统计值 + if err := redis.IncrBy("", key, "up", upValue); err != nil { + return err + } + if err := redis.IncrBy("", key, "down", downValue); err != nil { + return err + } + return nil +} + +// UPFTodayFlowLoad UPF上下行数据到redis +func (r PerfKPI) UPFTodayFlowLoad() { + cacheKeys, _ := redis.GetKeys("", cachekey.NE_KEY+"UPF:*") + if len(cacheKeys) == 0 { + return + } + + // 今日流量 + now := time.Now() + beginTime := now.Truncate(24 * time.Hour).UnixMilli() + endTime := beginTime + 24*60*60*1000 - 1 + + for _, key := range cacheKeys { + var v neModel.NeInfo + jsonStr, _ := redis.Get("", key) + if len(jsonStr) > 7 { + json.Unmarshal([]byte(jsonStr), &v) + } + if v.NeType == "UPF" && v.RmUID != "" { + // 查询历史数据 + // down * 8 / 1000 / 1000 单位M + info := r.perfKPIRepository.SelectUPFTotalFlow("UPF", v.RmUID, fmt.Sprint(beginTime), fmt.Sprint(endTime)) + if v, ok := info["up"]; ok && v == nil { + info["up"] = 0 + } + if v, ok := info["down"]; ok && v == nil { + info["down"] = 0 + } + + upTotal := parse.Number(info["up"]) + downTotal := parse.Number(info["down"]) + + // 将历史数据添加到Redis + r.UPFTodayFlowUpdate(v.RmUID, upTotal, downTotal, true) + } + } } diff --git a/src/modules/ws/processor/upf_total_flow.go b/src/modules/ws/processor/upf_total_flow.go index 0186dcd3..7c219e3f 100644 --- a/src/modules/ws/processor/upf_total_flow.go +++ b/src/modules/ws/processor/upf_total_flow.go @@ -34,11 +34,11 @@ func GetUPFTotalFlow(requestID string, data any) ([]byte, error) { return nil, fmt.Errorf("no matching network element information found") } - dataMap := neDataService.NewPerfKPI.SelectUPFTotalFlow(neInfo.NeType, neInfo.RmUID, querys.Day) + up, down := neDataService.NewPerfKPI.UPFTodayFlowFind(neInfo.RmUID, querys.Day) resultByte, err := json.Marshal(result.Ok(map[string]any{ "requestId": requestID, - "data": dataMap, + "data": map[string]int64{"up": up, "down": down}, })) return resultByte, err } From 8595a1c0cb1d133b96303b5a3defef415e480b67 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 4 Mar 2025 14:52:15 +0800 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E5=86=97?= =?UTF-8?q?=E4=BD=99=E9=94=99=E8=AF=AF=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=9F=A5=E8=AF=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/network_data/repository/udm_auth.go | 1 - src/modules/network_data/repository/udm_sub.go | 1 - src/modules/network_element/service/ne_info.go | 15 ++++++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/modules/network_data/repository/udm_auth.go b/src/modules/network_data/repository/udm_auth.go index 980ef003..147efdc4 100644 --- a/src/modules/network_data/repository/udm_auth.go +++ b/src/modules/network_data/repository/udm_auth.go @@ -43,7 +43,6 @@ func (r *UDMAuthUser) SelectPage(query map[string]any) (int64, []model.UDMAuthUs // 查询数量 长度为0直接返回 if err := tx.Count(&total).Error; err != nil || total <= 0 { - logger.Errorf("total err => %v", err) return total, rows } diff --git a/src/modules/network_data/repository/udm_sub.go b/src/modules/network_data/repository/udm_sub.go index 7f57dc50..e1457aa5 100644 --- a/src/modules/network_data/repository/udm_sub.go +++ b/src/modules/network_data/repository/udm_sub.go @@ -46,7 +46,6 @@ func (r *UDMSubUser) SelectPage(query map[string]any) (int64, []model.UDMSubUser // 查询数量 长度为0直接返回 if err := tx.Count(&total).Error; err != nil || total <= 0 { - logger.Errorf("total err => %v", err) return total, rows } diff --git a/src/modules/network_element/service/ne_info.go b/src/modules/network_element/service/ne_info.go index e3626a0e..87bd1b6b 100644 --- a/src/modules/network_element/service/ne_info.go +++ b/src/modules/network_element/service/ne_info.go @@ -84,12 +84,17 @@ func (r *NeInfo) ClearNeCacheByNeType(neType string) bool { func (r *NeInfo) SelectNeInfoByNeType(neType string) []model.NeInfo { neInfo := make([]model.NeInfo, 0) key := fmt.Sprintf("%s%s:*", cachekey.NE_KEY, strings.ToUpper(neType)) - jsonStr, _ := redis.Get("", key) - if len(jsonStr) > 7 { - err := json.Unmarshal([]byte(jsonStr), &neInfo) - if err != nil { - return neInfo + cacheKeys, _ := redis.GetKeys("", key) + if len(cacheKeys) > 0 { + for _, key := range cacheKeys { + var v model.NeInfo + jsonStr, _ := redis.Get("", key) + if len(jsonStr) > 7 { + json.Unmarshal([]byte(jsonStr), &v) + } + neInfo = append(neInfo, v) } + return neInfo } else { neInfo = r.neInfoRepository.SelectList(model.NeInfo{NeType: neType}) for _, v := range neInfo { From 74e6c75a053d6ce2e8fe2e2b4d88fa59cad32b8e Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 4 Mar 2025 15:14:46 +0800 Subject: [PATCH 6/6] =?UTF-8?q?sql:=20=E7=9C=8B=E6=9D=BF=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E9=83=A8=E5=88=86=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/install/sys_dict_data1_i18n_zh.sql | 4 ++++ database/install/sys_dict_data2_i18n_en.sql | 4 ++++ database/install/sys_menu.sql | 4 ++++ database/install/sys_role_menu.sql | 4 ++++ database/upgrade/upg_sys_dict_data1_i18n_zh.sql | 4 ++++ database/upgrade/upg_sys_dict_data2_i18n_en.sql | 4 ++++ database/upgrade/upg_sys_menu.sql | 4 ++++ database/upgrade/upg_sys_role_menu.sql | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/database/install/sys_dict_data1_i18n_zh.sql b/database/install/sys_dict_data1_i18n_zh.sql index 628642b1..9d83e25e 100644 --- a/database/install/sys_dict_data1_i18n_zh.sql +++ b/database/install/sys_dict_data1_i18n_zh.sql @@ -697,5 +697,9 @@ INSERT INTO `sys_dict_data` VALUES (2186, 2186, 'menu.config.neOverview', '网 INSERT INTO `sys_dict_data` VALUES (2187, 2187, 'menu.config.neOverviewRemark', '显示所有网元状态配置和license等概览信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2188, 2188, 'job.exportSGWCCDR', '定期从漫游数据话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2189, 2189, 'table.cdr_event_sgwc', '漫游数据话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2190, 2190, 'menu.dashboard.overview.smfUeNum', '展示数据会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2191, 2191, 'menu.dashboard.overview.imsUeNum', '展示语音会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBase', '展示5G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_dict_data2_i18n_en.sql b/database/install/sys_dict_data2_i18n_en.sql index f9b72904..689882e1 100644 --- a/database/install/sys_dict_data2_i18n_en.sql +++ b/database/install/sys_dict_data2_i18n_en.sql @@ -697,5 +697,9 @@ INSERT INTO `sys_dict_data` VALUES (4186, 4186, 'menu.config.neOverview', 'NE Ov INSERT INTO `sys_dict_data` VALUES (4187, 4187, 'menu.config.neOverviewRemark', 'Displays overview information such as status, configuration and license of all network elements', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4188, 4188, 'job.exportSGWCCDR', 'Export regularly from Roaming Data CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4189, 4189, 'table.cdr_event_sgwc', 'Roaming Data CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4190, 4190, 'menu.dashboard.overview.smfUeNum', 'Display data session number', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4191, 4191, 'menu.dashboard.overview.imsUeNum', 'Display the number of voice sessions', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBase', 'Display 5G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_menu.sql b/database/install/sys_menu.sql index 63cb9e4a..ca09cf93 100644 --- a/database/install/sys_menu.sql +++ b/database/install/sys_menu.sql @@ -214,5 +214,9 @@ INSERT INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/in INSERT INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2165, 'menu.config.neOverview', 4, 1, 'neOverview', 'configManage/neOverview/index', '1', '0', 'M', '1', '1', 'configManage:neOverview:index', 'icon-tubiaoku', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neOverviewRemark'); +INSERT INTO `sys_menu` VALUES (2166, 'menu.dashboard.overview.smfUeNum', 2132, 2, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:smfUeNum', '#', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_menu` VALUES (2167, 'menu.dashboard.overview.imsUeNum', 2132, 4, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:imsUeNum', '#', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_menu` VALUES (2168, 'menu.dashboard.overview.gnbBase', 2132, 6, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:gnbBase', '#', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_menu` VALUES (2169, 'menu.dashboard.overview.enbBase', 2132, 8, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:enbBase', '#', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_role_menu.sql b/database/install/sys_role_menu.sql index eda828a8..2c021de0 100644 --- a/database/install/sys_role_menu.sql +++ b/database/install/sys_role_menu.sql @@ -161,6 +161,10 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2160); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2162); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2163); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2165); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2166); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2167); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2168); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2169); INSERT IGNORE INTO `sys_role_menu` VALUES (3, 1); INSERT IGNORE INTO `sys_role_menu` VALUES (3, 4); diff --git a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql index fc606455..a10f69f3 100644 --- a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql +++ b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql @@ -704,5 +704,9 @@ REPLACE INTO `sys_dict_data` VALUES (2186, 2186, 'menu.config.neOverview', '网 REPLACE INTO `sys_dict_data` VALUES (2187, 2187, 'menu.config.neOverviewRemark', '显示所有网元状态配置和license等概览信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2188, 2188, 'job.exportSGWCCDR', '定期从漫游数据话单表导出文件至指定目录', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2189, 2189, 'table.cdr_event_sgwc', '漫游数据话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2190, 2190, 'menu.dashboard.overview.smfUeNum', '展示数据会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2191, 2191, 'menu.dashboard.overview.imsUeNum', '展示语音会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBase', '展示5G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_data2_i18n_en.sql b/database/upgrade/upg_sys_dict_data2_i18n_en.sql index 5a929a3c..ae5a4b98 100644 --- a/database/upgrade/upg_sys_dict_data2_i18n_en.sql +++ b/database/upgrade/upg_sys_dict_data2_i18n_en.sql @@ -703,5 +703,9 @@ REPLACE INTO `sys_dict_data` VALUES (4186, 4186, 'menu.config.neOverview', 'NE O REPLACE INTO `sys_dict_data` VALUES (4187, 4187, 'menu.config.neOverviewRemark', 'Displays overview information such as status, configuration and license of all network elements', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4188, 4188, 'job.exportSGWCCDR', 'Export regularly from Roaming Data CDR table', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4189, 4189, 'table.cdr_event_sgwc', 'Roaming Data CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4190, 4190, 'menu.dashboard.overview.smfUeNum', 'Display data session number', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4191, 4191, 'menu.dashboard.overview.imsUeNum', 'Display the number of voice sessions', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBase', 'Display 5G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_menu.sql b/database/upgrade/upg_sys_menu.sql index 44eeceda..0a5ea6c1 100644 --- a/database/upgrade/upg_sys_menu.sql +++ b/database/upgrade/upg_sys_menu.sql @@ -197,6 +197,10 @@ REPLACE INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/i REPLACE INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2165, 'menu.config.neOverview', 4, 1, 'neOverview', 'configManage/neOverview/index', '1', '0', 'M', '1', '1', 'configManage:neOverview:index', 'icon-tubiaoku', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neOverviewRemark'); +REPLACE INTO `sys_menu` VALUES (2166, 'menu.dashboard.overview.smfUeNum', 2132, 2, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:smfUeNum', '#', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_menu` VALUES (2167, 'menu.dashboard.overview.imsUeNum', 2132, 4, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:imsUeNum', '#', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_menu` VALUES (2168, 'menu.dashboard.overview.gnbBase', 2132, 6, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:gnbBase', '#', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_menu` VALUES (2169, 'menu.dashboard.overview.enbBase', 2132, 8, '#', '', '1', '1', 'B', '1', '1', 'dashboard:overview:enbBase', '#', 'supervisor', 1721902269805, '', 0, ''); -- 指定记录条件更新 diff --git a/database/upgrade/upg_sys_role_menu.sql b/database/upgrade/upg_sys_role_menu.sql index dc3b3b8b..5e2150e6 100644 --- a/database/upgrade/upg_sys_role_menu.sql +++ b/database/upgrade/upg_sys_role_menu.sql @@ -158,6 +158,10 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2160); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2162); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2163); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2165); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2166); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2167); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2168); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2169); INSERT IGNORE INTO `sys_role_menu` VALUES (3, 1); INSERT IGNORE INTO `sys_role_menu` VALUES (3, 4);