Merge branch 'main-v2' into lite
This commit is contained in:
16
src/app.go
16
src/app.go
@@ -15,7 +15,8 @@ import (
|
||||
"be.ems/src/modules/monitor"
|
||||
networkdata "be.ems/src/modules/network_data"
|
||||
networkelement "be.ems/src/modules/network_element"
|
||||
"be.ems/src/modules/oauth2"
|
||||
"be.ems/src/modules/notification"
|
||||
"be.ems/src/modules/oam"
|
||||
"be.ems/src/modules/system"
|
||||
"be.ems/src/modules/tool"
|
||||
"be.ems/src/modules/trace"
|
||||
@@ -27,10 +28,6 @@ import (
|
||||
// 初始应用引擎
|
||||
func AppEngine() *gin.Engine {
|
||||
var app *gin.Engine
|
||||
|
||||
// 禁止控制台日志输出的颜色
|
||||
gin.DisableConsoleColor()
|
||||
|
||||
// 根据运行环境注册引擎
|
||||
if config.Env() == "prod" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
@@ -39,6 +36,8 @@ func AppEngine() *gin.Engine {
|
||||
} else {
|
||||
app = gin.Default()
|
||||
}
|
||||
// 禁止控制台日志输出的颜色
|
||||
gin.DisableConsoleColor()
|
||||
app.ForwardedByClientIP = true
|
||||
return app
|
||||
}
|
||||
@@ -84,8 +83,9 @@ func ModulesRoute(app *gin.Engine) {
|
||||
system.Setup(app)
|
||||
// 认证模块
|
||||
auth.Setup(app)
|
||||
// 开放客户端模块
|
||||
oauth2.Setup(app)
|
||||
// 网元OAM对接
|
||||
oam.Setup(app)
|
||||
oam.SetupOauth2(app)
|
||||
// 通用模块
|
||||
common.Setup(app)
|
||||
|
||||
@@ -94,6 +94,8 @@ func ModulesRoute(app *gin.Engine) {
|
||||
// 网元数据模块
|
||||
networkdata.Setup(app)
|
||||
|
||||
// 通知模块
|
||||
notification.Setup(app)
|
||||
// 跟踪模块
|
||||
trace.Setup(app)
|
||||
// 图表模块
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,29 @@ serverLoginAuth: true
|
||||
# 接口加密,默认关闭
|
||||
serverCryptoApi: false
|
||||
|
||||
# 路由服务配置
|
||||
# 服务监听 ipv4/v6 端口,支持多路由
|
||||
routeServer:
|
||||
- addr: "0.0.0.0:33030" # 路由 http 端口
|
||||
schema: "http"
|
||||
- addr: "0.0.0.0:33443" # 路由 https 端口
|
||||
schema: "https"
|
||||
certFile: "/usr/local/etc/omc/certs/www.omc.net.crt"
|
||||
keyFile: "/usr/local/etc/omc/certs/www.omc.net.key"
|
||||
|
||||
# Web 服务配置
|
||||
# 如果使用 nginx 接管,可以禁用
|
||||
webServer:
|
||||
enabled: true # Web 服务启用,默认 false
|
||||
rootDir: /usr/local/etc/omc/web
|
||||
listen:
|
||||
- addr: "0.0.0.0:80" # Web http 端口
|
||||
schema: "http"
|
||||
- addr: "0.0.0.0:443" # Web https 端口
|
||||
schema: "https"
|
||||
certFile: "/usr/local/etc/omc/certs/www.omc.net.crt"
|
||||
keyFile: "/usr/local/etc/omc/certs/www.omc.net.key"
|
||||
|
||||
# 日志
|
||||
logger:
|
||||
fileDir: "/var/log"
|
||||
@@ -158,7 +181,7 @@ database:
|
||||
# 内置轻量级数据库
|
||||
lite:
|
||||
type: "sqlite"
|
||||
database: "<database path>"
|
||||
database: "<database path>"
|
||||
logging: false
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
defaultDataSourceName: "std"
|
||||
|
||||
@@ -1,49 +1,47 @@
|
||||
# 日志
|
||||
# log
|
||||
logger:
|
||||
fileDir: "/var/log"
|
||||
fileName: "omc.log"
|
||||
level: 0 # 日志记录的等级 0:silent<1:info<2:warn<3:error
|
||||
maxDay: 7 # 日志会保留 180 天
|
||||
maxSize: 10 # 调整按 10MB 大小的切割
|
||||
fileDir: "/var/log" # Log File Dir
|
||||
fileName: "omc.log" # Log File Name
|
||||
level: 0 # Log Level of 0:silent<1:info<2:warn<3:error
|
||||
maxDay: 7 # Log retention Days
|
||||
maxSize: 10 # Log File cutting by size
|
||||
|
||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||
# static file resource access
|
||||
staticFile:
|
||||
# 默认资源,dir目录需要预先创建
|
||||
default:
|
||||
prefix: "/static"
|
||||
dir: "/usr/local/omc/static"
|
||||
# 文件上传资源目录映射,与项目目录同级
|
||||
prefix: "/static" # Static File Prefix
|
||||
dir: "/usr/local/omc/static" # Static File Dir
|
||||
upload:
|
||||
prefix: "/upload"
|
||||
dir: "/usr/local/omc/upload"
|
||||
prefix: "/upload" # Upload File Prefix
|
||||
dir: "/usr/local/omc/upload" # Upload File Dir
|
||||
|
||||
# DB 数据源
|
||||
# data source
|
||||
database:
|
||||
dataSource:
|
||||
# 默认数据库实例
|
||||
# std: standard
|
||||
std:
|
||||
type: "mysql"
|
||||
host: "127.0.0.1"
|
||||
port: 33066
|
||||
username: "root"
|
||||
password: "1000omc@kp!"
|
||||
database: "omc_db"
|
||||
host: "127.0.0.1" # mysql host
|
||||
port: 33066 # mysql port
|
||||
username: "root" # mysql username
|
||||
password: "1000omc@kp!" # mysql password
|
||||
database: "omc_db" # mysql database
|
||||
logging: true
|
||||
# 内置轻量级数据库
|
||||
# lite: lite
|
||||
lite:
|
||||
type: "sqlite"
|
||||
database: "/usr/local/etc/omc/database/omc_db.sqlite"
|
||||
database: "/usr/local/etc/omc/database/omc_db.sqlite" # sqlite database
|
||||
logging: true
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
# default data source name
|
||||
defaultDataSourceName: "std"
|
||||
|
||||
# Redis 缓存数据
|
||||
# redis cached data
|
||||
redis:
|
||||
dataSource:
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "127.0.0.1" # Redis host
|
||||
password: "helloearth"
|
||||
port: 6379 # redis port
|
||||
host: "127.0.0.1" # redis host
|
||||
password: "helloearth" # redis password
|
||||
db: 10 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
# default data source name
|
||||
defaultDataSourceName: "default"
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
# DB 数据源
|
||||
# data source
|
||||
database:
|
||||
dataSource:
|
||||
# 默认数据库实例
|
||||
# std: standard
|
||||
std:
|
||||
type: "mysql"
|
||||
host: "127.0.0.1"
|
||||
port: 33066
|
||||
username: "root"
|
||||
password: "1000omc@kp!"
|
||||
database: "omc_db"
|
||||
logging: false
|
||||
# 内置轻量级数据库
|
||||
host: "127.0.0.1" # mysql host
|
||||
port: 33066 # mysql port
|
||||
username: "root" # mysql username
|
||||
password: "1000omc@kp!" # mysql password
|
||||
database: "omc_db" # mysql database
|
||||
# lite: lite
|
||||
lite:
|
||||
type: "sqlite"
|
||||
database: "/usr/local/etc/omc/database/omc_db.sqlite"
|
||||
logging: false
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
database: "/usr/local/etc/omc/database/omc_db.sqlite" # sqlite database
|
||||
# default data source name
|
||||
defaultDataSourceName: "std"
|
||||
|
||||
# Redis 缓存数据
|
||||
# redis cached data
|
||||
redis:
|
||||
dataSource:
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "127.0.0.1" # Redis host
|
||||
password: "helloearth"
|
||||
port: 6379 # redis port
|
||||
host: "127.0.0.1" # redis host
|
||||
password: "helloearth" # redis password
|
||||
db: 10 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
# default data source name
|
||||
defaultDataSourceName: "default"
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
libConfig "be.ems/lib/config"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -21,11 +19,10 @@ var (
|
||||
)
|
||||
|
||||
// 程序配置
|
||||
var conf *viper.Viper
|
||||
var conf *viper.Viper = viper.New()
|
||||
|
||||
// 初始化程序配置
|
||||
func InitConfig(configDir *embed.FS) {
|
||||
conf = viper.New()
|
||||
initFlag()
|
||||
initViper(configDir)
|
||||
}
|
||||
@@ -97,16 +94,14 @@ func initViper(configDir *embed.FS) {
|
||||
// 外部文件配置
|
||||
externalConfig := conf.GetString("config")
|
||||
if externalConfig != "" {
|
||||
// readExternalConfig(externalConfig)
|
||||
// 处理旧配置,存在相同的配置项处理
|
||||
configInMerge(externalConfig)
|
||||
readExternalConfig(externalConfig)
|
||||
}
|
||||
|
||||
// 记录程序开始运行的时间点
|
||||
conf.Set("runTime", time.Now())
|
||||
}
|
||||
|
||||
// readExternalConfig 读取外部文件配置(放弃旧的配置序列化时候才用)
|
||||
// readExternalConfig 读取外部文件配置
|
||||
func readExternalConfig(configPaht string) {
|
||||
f, err := os.Open(configPaht)
|
||||
if err != nil {
|
||||
@@ -121,38 +116,6 @@ func readExternalConfig(configPaht string) {
|
||||
}
|
||||
}
|
||||
|
||||
// 配置文件读取进行内部参数合并
|
||||
func configInMerge(configFile string) {
|
||||
// 指定配置文件读取序列化
|
||||
libConfig.ReadConfig(configFile)
|
||||
uriPrefix := libConfig.GetYamlConfig().OMC.UriPrefix
|
||||
if uriPrefix != "" {
|
||||
libConfig.UriPrefix = uriPrefix
|
||||
}
|
||||
if libConfig.GetYamlConfig().TestConfig.Enabled {
|
||||
libConfig.ReadTestConfigYaml(libConfig.GetYamlConfig().TestConfig.File)
|
||||
}
|
||||
|
||||
// 配置文件读取
|
||||
var v = viper.New()
|
||||
// 设置配置文件路径
|
||||
v.SetConfigFile(configFile)
|
||||
v.SetConfigType("yaml")
|
||||
// 读取配置文件
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
fmt.Printf("failure to read configuration file: %v \n", err)
|
||||
return
|
||||
}
|
||||
// 合并外层lib和features使用配置
|
||||
for key, value := range v.AllSettings() {
|
||||
// 跳过配置
|
||||
if key == "testconfig" || key == "logger" {
|
||||
continue
|
||||
}
|
||||
conf.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Env 获取运行服务环境
|
||||
// local prod
|
||||
func Env() string {
|
||||
|
||||
30
src/framework/config/expand.go
Normal file
30
src/framework/config/expand.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// SedReplace 替换文件内容,文件来自外部文件配置config传入
|
||||
//
|
||||
// sed 's/port: [0-9]\+ # trace port/port: 6964 # trace port/' /usr/local/etc/omc/omc.yaml
|
||||
func SedReplace(pattern, replacement string) error {
|
||||
// 外部文件配置
|
||||
externalConfig := conf.GetString("config")
|
||||
if externalConfig == "" {
|
||||
return fmt.Errorf("config file path not found")
|
||||
}
|
||||
// 读取文件内容
|
||||
data, err := os.ReadFile(externalConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 定义正则表达式
|
||||
re := regexp.MustCompile(pattern)
|
||||
// 使用正则替换,将匹配到的部分替换为新的内容
|
||||
replacedData := re.ReplaceAll(data, []byte(replacement))
|
||||
// 写回文件
|
||||
return os.WriteFile(externalConfig, replacedData, 0644)
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
package constants
|
||||
|
||||
// 告警 alarmCode 常量
|
||||
const (
|
||||
// ALARM_EVENT_REBOOT 事件-网元重启
|
||||
ALARM_EVENT_REBOOT = 9000
|
||||
// ALARM_STATE_CHECK 告警-状态检查
|
||||
ALARM_STATE_CHECK = 10000
|
||||
// ALARM_RAM_CPU_CHECK 告警-内存/CPU/磁盘检查
|
||||
ALARM_CMD_CHECK = 10001
|
||||
// ALARM_LICENSE_CHECK 告警-网元License到期检查
|
||||
ALARM_LICENSE_CHECK = 10002
|
||||
ALARM_EVENT_REBOOT = 9000 // 告警Code-事件-网元重启
|
||||
ALARM_STATE_CHECK = 10000 // 告警Code-状态检查
|
||||
ALARM_CMD_CHECK = 10001 // 告警Code-内存/CPU/磁盘检查
|
||||
ALARM_LICENSE_CHECK = 10002 // 告警Code-网元License到期检查
|
||||
)
|
||||
|
||||
const (
|
||||
ALARM_ACK_STATE_NOT_ACK = "NotAck" // 告警确认状态-未确认
|
||||
ALARM_ACK_STATE_ACK = "Ack" // 告警确认状态-已确认
|
||||
)
|
||||
|
||||
const (
|
||||
ALARM_CLEAR_TYPE_NOT_CLEAR = "NotClear" // 告警清除状态-未清除
|
||||
ALARM_CLEAR_TYPE_AUTO_CLEAR = "AutoClear" // 告警清除状态-自动清除
|
||||
ALARM_CLEAR_TYPE_MANUAL_CLEAR = "ManualClear" // 告警清除状态-手动清除
|
||||
)
|
||||
|
||||
@@ -103,6 +103,10 @@ func processSQLFile(db *gorm.DB, filePath string) {
|
||||
} else if strings.Contains(errorStr, "duplicate key") {
|
||||
// 忽略重复索引错误
|
||||
// Error 1061 (42000): Duplicate key name 'key_name'
|
||||
} else if strings.Contains(errorStr, "duplicate entry") {
|
||||
// 忽略重复记录错误
|
||||
// Error 1062 (23000): Duplicate entry 'value' for key 'key_name'
|
||||
log.Println(err.Error())
|
||||
} else if strings.Contains(errorStr, "unknown column") {
|
||||
// 忽略未知字段错误
|
||||
// Error 1054 (42S22): Unknown column 'field_name' in 'table'
|
||||
@@ -110,6 +114,10 @@ func processSQLFile(db *gorm.DB, filePath string) {
|
||||
// 忽略删除字段或索引错误
|
||||
// Error 1091 (42000): Can't DROP COLUMN `field_name`; check that it exists
|
||||
// Error 1091 (42000): Can't DROP 'idx_ne_type_id'; check that column/key exists
|
||||
} else if strings.Contains(errorStr, "doesn't match") {
|
||||
// 忽略列数不匹配错误
|
||||
// Error 1136 (21S01): Column count doesn't match value count at row 1
|
||||
log.Println(err.Error())
|
||||
} else {
|
||||
// 其他错误终止程序
|
||||
log.Fatalln(errorStr)
|
||||
|
||||
@@ -2,7 +2,6 @@ package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -134,8 +133,15 @@ func OperateLog(options Options) gin.HandlerFunc {
|
||||
contentDisposition := c.Writer.Header().Get("Content-Disposition")
|
||||
contentType := c.Writer.Header().Get("Content-Type")
|
||||
content := contentType + contentDisposition
|
||||
msg := fmt.Sprintf(`{"status":"%d","size":%d,"content-type":"%s"}`, status, c.Writer.Size(), content)
|
||||
operaLog.OperaMsg = msg
|
||||
msgByte, err := json.Marshal(map[string]any{
|
||||
"status": status,
|
||||
"size": c.Writer.Size(),
|
||||
"content-type": content,
|
||||
})
|
||||
if err != nil {
|
||||
operaLog.OperaMsg = ""
|
||||
}
|
||||
operaLog.OperaMsg = string(msgByte)
|
||||
}
|
||||
|
||||
// 日志记录时间
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConnTCP 连接TCP客户端
|
||||
type ConnTCP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
|
||||
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
||||
|
||||
Client *net.Conn `json:"client"`
|
||||
LastResult string `json:"lastResult"` // 记最后一次发送消息的结果
|
||||
}
|
||||
|
||||
// New 创建TCP客户端
|
||||
func (c *ConnTCP) New() (*ConnTCP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "tcp"
|
||||
if strings.Contains(c.Addr, ":") {
|
||||
proto = "tcp6"
|
||||
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||
}
|
||||
address := net.JoinHostPort(c.Addr, fmt.Sprint(c.Port))
|
||||
|
||||
// 默认等待5s
|
||||
if c.DialTimeOut == 0 {
|
||||
c.DialTimeOut = 5 * time.Second
|
||||
}
|
||||
|
||||
// 连接到服务端
|
||||
client, err := net.DialTimeout(proto, address, c.DialTimeOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Client = &client
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前TCP客户端
|
||||
func (c *ConnTCP) Close() {
|
||||
if c.Client != nil {
|
||||
(*c.Client).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Send 发送消息
|
||||
func (c *ConnTCP) Send(msg []byte, timer time.Duration) (string, error) {
|
||||
if c.Client == nil {
|
||||
return "", fmt.Errorf("tcp client not connected")
|
||||
}
|
||||
conn := *c.Client
|
||||
|
||||
// 写入信息
|
||||
if len(msg) > 0 {
|
||||
if _, err := conn.Write(msg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
defer buf.Reset()
|
||||
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-time.After(timer):
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, fmt.Errorf("timeout")
|
||||
default:
|
||||
// 读取命令消息
|
||||
n, err := conn.Read(tmp)
|
||||
if n == 0 || err != nil {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
|
||||
tmpStr := string(tmp[:n])
|
||||
buf.WriteString(tmpStr)
|
||||
|
||||
// 是否有终止符
|
||||
if strings.HasSuffix(tmpStr, ">") || strings.HasSuffix(tmpStr, "> ") || strings.HasSuffix(tmpStr, "# ") {
|
||||
tmp = nil
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
)
|
||||
|
||||
// SocketTCP TCP服务端
|
||||
type SocketTCP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
Listener *net.TCPListener `json:"listener"`
|
||||
StopChan chan struct{} `json:"stop"` // 停止信号
|
||||
}
|
||||
|
||||
// New 创建TCP服务端
|
||||
func (s *SocketTCP) New() (*SocketTCP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "tcp"
|
||||
if strings.Contains(s.Addr, ":") {
|
||||
proto = "tcp6"
|
||||
s.Addr = fmt.Sprintf("[%s]", s.Addr)
|
||||
}
|
||||
address := fmt.Sprintf("%s:%d", s.Addr, s.Port)
|
||||
|
||||
// 解析 TCP 地址
|
||||
tcpAddr, err := net.ResolveTCPAddr(proto, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 监听 TCP 地址
|
||||
listener, err := net.ListenTCP(proto, tcpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Listener = listener
|
||||
s.StopChan = make(chan struct{}, 1)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前TCP服务端
|
||||
func (s *SocketTCP) Close() {
|
||||
if s.Listener != nil {
|
||||
s.StopChan <- struct{}{}
|
||||
(*s.Listener).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve 处理消息
|
||||
func (s *SocketTCP) Resolve(callback func(conn *net.Conn, err error)) {
|
||||
if s.Listener == nil {
|
||||
callback(nil, fmt.Errorf("tcp service not created"))
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
callback(nil, fmt.Errorf("tcp service panic err"))
|
||||
}
|
||||
}()
|
||||
|
||||
listener := *s.Listener
|
||||
for {
|
||||
select {
|
||||
case <-s.StopChan:
|
||||
callback(nil, fmt.Errorf("udp service stop"))
|
||||
return
|
||||
default:
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
logger.Errorf("Error accepting connection: %v ", err)
|
||||
continue
|
||||
}
|
||||
defer conn.Close()
|
||||
callback(&conn, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConnUDP 连接UDP客户端
|
||||
type ConnUDP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
|
||||
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
||||
|
||||
Client *net.Conn `json:"client"`
|
||||
LastResult string `json:"lastResult"` // 记最后一次发送消息的结果
|
||||
}
|
||||
|
||||
// New 创建UDP客户端
|
||||
func (c *ConnUDP) New() (*ConnUDP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "udp"
|
||||
if strings.Contains(c.Addr, ":") {
|
||||
proto = "udp6"
|
||||
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||
}
|
||||
address := net.JoinHostPort(c.Addr, fmt.Sprint(c.Port))
|
||||
|
||||
// 默认等待5s
|
||||
if c.DialTimeOut == 0 {
|
||||
c.DialTimeOut = 5 * time.Second
|
||||
}
|
||||
|
||||
// 连接到服务端
|
||||
client, err := net.DialTimeout(proto, address, c.DialTimeOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Client = &client
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前UDP客户端
|
||||
func (c *ConnUDP) Close() {
|
||||
if c.Client != nil {
|
||||
(*c.Client).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Send 发送消息
|
||||
func (c *ConnUDP) Send(msg []byte, ms int) (string, error) {
|
||||
if c.Client == nil {
|
||||
return "", fmt.Errorf("udp client not connected")
|
||||
}
|
||||
conn := *c.Client
|
||||
|
||||
// 写入信息
|
||||
if len(msg) > 0 {
|
||||
if _, err := conn.Write(msg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
defer buf.Reset()
|
||||
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Duration(time.Duration(ms).Milliseconds())):
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, fmt.Errorf("timeout")
|
||||
default:
|
||||
// 读取命令消息
|
||||
n, err := conn.Read(tmp)
|
||||
if n == 0 || err != nil {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
|
||||
tmpStr := string(tmp[:n])
|
||||
buf.WriteString(tmpStr)
|
||||
|
||||
// 是否有终止符
|
||||
if strings.HasSuffix(tmpStr, ">") || strings.HasSuffix(tmpStr, "> ") || strings.HasSuffix(tmpStr, "# ") {
|
||||
tmp = nil
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SocketUDP UDP服务端
|
||||
type SocketUDP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
Conn *net.UDPConn `json:"conn"`
|
||||
StopChan chan struct{} `json:"stop"` // 停止信号
|
||||
}
|
||||
|
||||
// New 创建UDP服务端
|
||||
func (s *SocketUDP) New() (*SocketUDP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "udp"
|
||||
if strings.Contains(s.Addr, ":") {
|
||||
proto = "udp6"
|
||||
s.Addr = fmt.Sprintf("[%s]", s.Addr)
|
||||
}
|
||||
address := fmt.Sprintf("%s:%d", s.Addr, s.Port)
|
||||
|
||||
// 解析 UDP 地址
|
||||
udpAddr, err := net.ResolveUDPAddr(proto, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 监听 UDP 地址
|
||||
conn, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Conn = conn
|
||||
s.StopChan = make(chan struct{}, 1)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// CloseService 关闭当前UDP服务端
|
||||
func (s *SocketUDP) Close() {
|
||||
if s.Conn != nil {
|
||||
s.StopChan <- struct{}{}
|
||||
(*s.Conn).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve 处理消息
|
||||
func (s *SocketUDP) Resolve(callback func(*net.UDPConn, error)) {
|
||||
if s.Conn == nil {
|
||||
callback(nil, fmt.Errorf("udp service not created"))
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
callback(nil, fmt.Errorf("udp service panic err"))
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.StopChan:
|
||||
callback(nil, fmt.Errorf("udp service not created"))
|
||||
return
|
||||
default:
|
||||
callback(s.Conn, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,14 @@ func (c *ConnTelnet) NewClient() (*ConnTelnet, error) {
|
||||
}
|
||||
|
||||
// 进行登录
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.User + "\r\n"))
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.Password + "\r\n"))
|
||||
if c.User != "" {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.User + "\r\n"))
|
||||
}
|
||||
if c.Password != "" {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.Password + "\r\n"))
|
||||
}
|
||||
// fmt.Fprintln(client, c.User)
|
||||
// fmt.Fprintln(client, c.Password)
|
||||
|
||||
@@ -103,6 +107,19 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
||||
return c.LastResult, nil
|
||||
}
|
||||
|
||||
// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
|
||||
func (s *ConnTelnet) WindowChange(h, w int) error {
|
||||
if s.Client == nil {
|
||||
return fmt.Errorf("client is nil to content write failed")
|
||||
}
|
||||
conn := *s.Client
|
||||
|
||||
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31})
|
||||
conn.Write([]byte{255, 250, 31, byte(w >> 8), byte(w & 0xFF), byte(h >> 8), byte(h & 0xFF), 255, 240})
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewClient 创建Telnet客户端会话对象
|
||||
func (c *ConnTelnet) NewClientSession(cols, rows int) (*TelnetClientSession, error) {
|
||||
if c.Client == nil {
|
||||
|
||||
@@ -54,9 +54,9 @@ func ParseDateToStr(date any, formatStr string) string {
|
||||
if v == 0 {
|
||||
return ""
|
||||
}
|
||||
if v > 9999999999 {
|
||||
if v > 1e12 {
|
||||
t = time.UnixMilli(v)
|
||||
} else if v > 999999999 {
|
||||
} else if v > 1e9 {
|
||||
t = time.Unix(v, 0)
|
||||
} else {
|
||||
logger.Infof("utils ParseDateToStr err %v", "Invalid timestamp")
|
||||
|
||||
44
src/framework/utils/expr/expr.go
Normal file
44
src/framework/utils/expr/expr.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/expr-lang/expr"
|
||||
)
|
||||
|
||||
// Eval 计算表达式返回结果
|
||||
func Eval(exprStr string, env map[string]any) (any, error) {
|
||||
return expr.Eval(exprStr, env)
|
||||
}
|
||||
|
||||
// ParseExprEnv 解析表达式环境变量
|
||||
// 比如 "('SMF.03'/'SMF.04')*100"
|
||||
// 变量传入"SMF.03": 3
|
||||
func ParseExprEnv(exprStr string, env map[string]any) (string, map[string]any) {
|
||||
// 使用正则表达式匹配带单引号的变量名
|
||||
re := regexp.MustCompile(`'([^']+)'`)
|
||||
tempEnv := make(map[string]any)
|
||||
tempExpr := exprStr
|
||||
varCount := 0
|
||||
matches := re.FindAllStringSubmatch(exprStr, -1)
|
||||
for _, match := range matches {
|
||||
paramName := match[1]
|
||||
tempVarName := fmt.Sprintf("var%d", varCount)
|
||||
tempEnv[tempVarName] = env[paramName]
|
||||
tempExpr = strings.Replace(tempExpr, match[0], tempVarName, 1)
|
||||
varCount++
|
||||
}
|
||||
|
||||
// 合并临时环境变量和原环境变量
|
||||
combinedEnv := make(map[string]any)
|
||||
for k, v := range env {
|
||||
combinedEnv[k] = v
|
||||
}
|
||||
for k, v := range tempEnv {
|
||||
combinedEnv[k] = v
|
||||
}
|
||||
|
||||
return tempExpr, combinedEnv
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func ValidUsername(username string) bool {
|
||||
if username == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
pattern := `^.{4,}$` //`^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
match, err := regexp.MatchString(pattern, username)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
@@ -23,38 +23,84 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
|
||||
// 账号身份操作
|
||||
account := controller.NewAccount
|
||||
accountGroup := router.Group("/auth")
|
||||
{
|
||||
router.POST("/auth/login",
|
||||
accountGroup.POST("/login",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewAccount.Login,
|
||||
account.Login,
|
||||
)
|
||||
router.POST("/auth/logout",
|
||||
accountGroup.POST("/logout",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 120,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewAccount.Logout,
|
||||
account.Logout,
|
||||
)
|
||||
router.POST("/auth/refresh-token",
|
||||
accountGroup.POST("/refresh-token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 5,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
controller.NewAccount.RefreshToken,
|
||||
account.RefreshToken,
|
||||
)
|
||||
router.GET("/me",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewAccount.Me,
|
||||
account.Me,
|
||||
)
|
||||
router.GET("/router",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewAccount.Router,
|
||||
account.Router,
|
||||
)
|
||||
}
|
||||
|
||||
// 登录认证源
|
||||
{
|
||||
accountGroup.GET("/login/source",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 300,
|
||||
Count: 60,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
account.LoginSource,
|
||||
)
|
||||
accountGroup.POST("/login/ldap",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
account.LDAP,
|
||||
)
|
||||
accountGroup.POST("/login/smtp",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
account.SMTP,
|
||||
)
|
||||
accountGroup.GET("/login/oauth2/authorize",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
account.OAuth2CodeURL,
|
||||
)
|
||||
accountGroup.POST("/login/oauth2/token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
account.OAuth2Token,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,4 +116,62 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
}
|
||||
|
||||
// 客户端授权管理
|
||||
oauth2Client := controller.NewOauth2Client
|
||||
oauth2ClientGroup := router.Group("/oauth2/client")
|
||||
{
|
||||
oauth2ClientGroup.GET("/list",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
oauth2Client.List,
|
||||
)
|
||||
oauth2ClientGroup.GET("/:clientId",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
oauth2Client.Info,
|
||||
)
|
||||
oauth2ClientGroup.POST("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_INSERT)),
|
||||
oauth2Client.Add,
|
||||
)
|
||||
oauth2ClientGroup.PUT("",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_UPDATE)),
|
||||
oauth2Client.Edit,
|
||||
)
|
||||
oauth2ClientGroup.DELETE("/:id",
|
||||
middleware.AuthorizeUser(map[string][]string{"matchRoles": {"admin"}}),
|
||||
middleware.OperateLog(middleware.OptionNew("log.operate.title.oauth2client", middleware.BUSINESS_TYPE_DELETE)),
|
||||
oauth2Client.Remove,
|
||||
)
|
||||
}
|
||||
|
||||
// 授权认证
|
||||
oauth2 := controller.NewOauth2
|
||||
oauth2Group := router.Group("/oauth2")
|
||||
{
|
||||
oauth2Group.GET("/authorize",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 30,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.Authorize,
|
||||
)
|
||||
oauth2Group.POST("/token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 180,
|
||||
Count: 15,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.Token,
|
||||
)
|
||||
oauth2Group.POST("/refresh-token",
|
||||
middleware.RateLimit(middleware.LimitOption{
|
||||
Time: 60,
|
||||
Count: 5,
|
||||
Type: middleware.LIMIT_IP,
|
||||
}),
|
||||
oauth2.RefreshToken,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,13 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/service"
|
||||
systemModelVO "be.ems/src/modules/system/model/vo"
|
||||
systemService "be.ems/src/modules/system/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -33,95 +30,6 @@ type AccountController struct {
|
||||
sysLogLoginService *systemService.SysLogLogin // 系统登录访问
|
||||
}
|
||||
|
||||
// Login 系统登录
|
||||
//
|
||||
// POST /auth/login
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/login [post]
|
||||
func (s AccountController) Login(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var body model.LoginBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 当前请求信息
|
||||
ipaddr, location := reqctx.IPAddrLocation(c)
|
||||
os, browser := reqctx.UaOsBrowser(c)
|
||||
|
||||
// 校验验证码 根据错误信息,创建系统访问记录
|
||||
if err := s.accountService.ValidateCaptcha(body.Code, body.UUID); err != nil {
|
||||
msg := fmt.Sprintf("%s code %s", err.Error(), body.Code)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, msg,
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info, err := s.accountService.ByUsername(body.Username, body.Password)
|
||||
if err != nil {
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, err.Error(),
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
if !config.IsSystemUser(info.UserId) {
|
||||
// 强制改密码
|
||||
forcePasswdChange, err := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
if forcePasswdChange {
|
||||
data["forcePasswdChange"] = true
|
||||
}
|
||||
}
|
||||
|
||||
deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId)
|
||||
|
||||
// 生成访问令牌
|
||||
accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access")
|
||||
if accessToken == "" || expiresIn == 0 {
|
||||
c.JSON(200, resp.ErrMsg("token generation failed"))
|
||||
return
|
||||
}
|
||||
// 生成刷新令牌
|
||||
refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh")
|
||||
|
||||
// 记录令牌,创建系统访问记录
|
||||
token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser})
|
||||
s.accountService.UpdateLoginDateAndIP(info)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_YES, "app.common.loginSuccess",
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
|
||||
data["tokenType"] = constants.HEADER_PREFIX
|
||||
data["accessToken"] = accessToken
|
||||
data["expiresIn"] = expiresIn
|
||||
data["refreshToken"] = refreshToken
|
||||
data["refreshExpiresIn"] = refreshExpiresIn
|
||||
data["userId"] = info.UserId
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// Logout 系统登出
|
||||
//
|
||||
// POST /auth/logout
|
||||
@@ -222,82 +130,10 @@ func (s AccountController) RefreshToken(c *gin.Context) {
|
||||
}))
|
||||
}
|
||||
|
||||
// Me 登录用户信息
|
||||
// LoginSource 登录认证源
|
||||
//
|
||||
// GET /me
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Login User Information
|
||||
// @Description Login User Information
|
||||
// @Router /me [get]
|
||||
func (s AccountController) Me(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
info, err := reqctx.LoginUser(c)
|
||||
if err != nil {
|
||||
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 角色权限集合,系统管理员拥有所有权限
|
||||
isSystemUser := config.IsSystemUser(info.UserId)
|
||||
roles, perms := s.accountService.RoleAndMenuPerms(info.UserId, isSystemUser)
|
||||
|
||||
info.User.NickName = i18n.TKey(language, info.User.NickName)
|
||||
info.User.Remark = i18n.TKey(language, info.User.Remark)
|
||||
info.User.Dept.DeptName = i18n.TKey(language, info.User.Dept.DeptName)
|
||||
for ri := range info.User.Roles {
|
||||
info.User.Roles[ri].RoleName = i18n.TKey(language, info.User.Roles[ri].RoleName)
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"user": info.User,
|
||||
"roles": roles,
|
||||
"permissions": perms,
|
||||
}
|
||||
if !isSystemUser {
|
||||
// 强制改密码
|
||||
forcePasswdChange, _ := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime)
|
||||
if forcePasswdChange {
|
||||
data["forcePasswdChange"] = true
|
||||
}
|
||||
}
|
||||
// GET /auth/login/source
|
||||
func (s AccountController) LoginSource(c *gin.Context) {
|
||||
data := s.accountService.LoginSource()
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// Router 登录用户路由信息
|
||||
//
|
||||
// GET /router
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Login User Routing Information
|
||||
// @Description Login User Routing Information
|
||||
// @Router /router [get]
|
||||
func (s AccountController) Router(c *gin.Context) {
|
||||
loginUserId := reqctx.LoginUserToUserID(c)
|
||||
|
||||
// 前端路由,系统管理员拥有所有
|
||||
isSystemUser := config.IsSystemUser(loginUserId)
|
||||
buildMenus := s.accountService.RouteMenus(loginUserId, isSystemUser)
|
||||
// 闭包函数处理多语言
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var converI18n func(language string, arr *[]systemModelVO.Router)
|
||||
converI18n = func(language string, arr *[]systemModelVO.Router) {
|
||||
for i := range *arr {
|
||||
(*arr)[i].Meta.Title = i18n.TKey(language, (*arr)[i].Meta.Title)
|
||||
if len((*arr)[i].Children) > 0 {
|
||||
converI18n(language, &(*arr)[i].Children)
|
||||
}
|
||||
}
|
||||
}
|
||||
converI18n(language, &buildMenus)
|
||||
|
||||
c.JSON(200, resp.OkData(buildMenus))
|
||||
}
|
||||
|
||||
93
src/modules/auth/controller/account_info.go
Normal file
93
src/modules/auth/controller/account_info.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
systemModelVO "be.ems/src/modules/system/model/vo"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Me 登录用户信息
|
||||
//
|
||||
// GET /me
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Login User Information
|
||||
// @Description Login User Information
|
||||
// @Router /me [get]
|
||||
func (s AccountController) Me(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
info, err := reqctx.LoginUser(c)
|
||||
if err != nil {
|
||||
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 角色权限集合,系统管理员拥有所有权限
|
||||
isSystemUser := config.IsSystemUser(info.UserId)
|
||||
roles, perms := s.accountService.RoleAndMenuPerms(info.UserId, isSystemUser)
|
||||
|
||||
info.User.NickName = i18n.TKey(language, info.User.NickName)
|
||||
info.User.Remark = i18n.TKey(language, info.User.Remark)
|
||||
if info.User.Dept != nil {
|
||||
info.User.Dept.DeptName = i18n.TKey(language, info.User.Dept.DeptName)
|
||||
}
|
||||
for ri := range info.User.Roles {
|
||||
info.User.Roles[ri].RoleName = i18n.TKey(language, info.User.Roles[ri].RoleName)
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"user": info.User,
|
||||
"roles": roles,
|
||||
"permissions": perms,
|
||||
}
|
||||
if !isSystemUser {
|
||||
// 强制改密码
|
||||
forcePasswdChange, _ := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime)
|
||||
if forcePasswdChange {
|
||||
data["forcePasswdChange"] = true
|
||||
}
|
||||
}
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// Router 登录用户路由信息
|
||||
//
|
||||
// GET /router
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Login User Routing Information
|
||||
// @Description Login User Routing Information
|
||||
// @Router /router [get]
|
||||
func (s AccountController) Router(c *gin.Context) {
|
||||
loginUserId := reqctx.LoginUserToUserID(c)
|
||||
|
||||
// 前端路由,系统管理员拥有所有
|
||||
isSystemUser := config.IsSystemUser(loginUserId)
|
||||
buildMenus := s.accountService.RouteMenus(loginUserId, isSystemUser)
|
||||
// 闭包函数处理多语言
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var converI18n func(language string, arr *[]systemModelVO.Router)
|
||||
converI18n = func(language string, arr *[]systemModelVO.Router) {
|
||||
for i := range *arr {
|
||||
(*arr)[i].Meta.Title = i18n.TKey(language, (*arr)[i].Meta.Title)
|
||||
if len((*arr)[i].Children) > 0 {
|
||||
converI18n(language, &(*arr)[i].Children)
|
||||
}
|
||||
}
|
||||
}
|
||||
converI18n(language, &buildMenus)
|
||||
|
||||
c.JSON(200, resp.OkData(buildMenus))
|
||||
}
|
||||
80
src/modules/auth/controller/account_ldap.go
Normal file
80
src/modules/auth/controller/account_ldap.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/auth/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// LDAP LDAP认证登录
|
||||
//
|
||||
// POST /auth/ldap
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/ldap [post]
|
||||
func (s AccountController) LDAP(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var body model.LoginSourceBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 当前请求信息
|
||||
ipaddr, location := reqctx.IPAddrLocation(c)
|
||||
os, browser := reqctx.UaOsBrowser(c)
|
||||
|
||||
// 登录用户信息
|
||||
info, err := s.accountService.ByLDAP(body)
|
||||
if err != nil {
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, err.Error(),
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId)
|
||||
|
||||
// 生成访问令牌
|
||||
accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access")
|
||||
if accessToken == "" || expiresIn == 0 {
|
||||
c.JSON(200, resp.ErrMsg("token generation failed"))
|
||||
return
|
||||
}
|
||||
// 生成刷新令牌
|
||||
refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh")
|
||||
|
||||
// 记录令牌,创建系统访问记录
|
||||
token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser})
|
||||
s.accountService.UpdateLoginDateAndIP(info)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_YES, "app.common.loginSuccess",
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
|
||||
data["tokenType"] = constants.HEADER_PREFIX
|
||||
data["accessToken"] = accessToken
|
||||
data["expiresIn"] = expiresIn
|
||||
data["refreshToken"] = refreshToken
|
||||
data["refreshExpiresIn"] = refreshExpiresIn
|
||||
data["userId"] = info.UserId
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
107
src/modules/auth/controller/account_oauth2.go
Normal file
107
src/modules/auth/controller/account_oauth2.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/auth/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// OAuth2CodeURL OAuth2认证跳转登录URL
|
||||
//
|
||||
// GET /auth/login/oauth2/authorize
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/login/oauth2/authorize [get]
|
||||
func (s AccountController) OAuth2CodeURL(c *gin.Context) {
|
||||
state := c.Query("state")
|
||||
if state == "" {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: state is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
redirectURL, err := s.accountService.ByOAuth2CodeURL(state)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.Redirect(302, redirectURL)
|
||||
}
|
||||
|
||||
// OAuth2 OAuth2认证登录
|
||||
//
|
||||
// POST /auth/login/oauth2/token
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/login/oauth2/token [post]
|
||||
func (s AccountController) OAuth2Token(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var body model.LoginSourceOauth2Body
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 当前请求信息
|
||||
ipaddr, location := reqctx.IPAddrLocation(c)
|
||||
os, browser := reqctx.UaOsBrowser(c)
|
||||
|
||||
// 登录用户信息
|
||||
info, err := s.accountService.ByOAuth2(body)
|
||||
if err != nil {
|
||||
s.sysLogLoginService.Insert(
|
||||
body.State, constants.STATUS_NO, err.Error(),
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId)
|
||||
|
||||
// 生成访问令牌
|
||||
accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access")
|
||||
if accessToken == "" || expiresIn == 0 {
|
||||
c.JSON(200, resp.ErrMsg("token generation failed"))
|
||||
return
|
||||
}
|
||||
// 生成刷新令牌
|
||||
refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh")
|
||||
|
||||
// 记录令牌,创建系统访问记录
|
||||
token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser})
|
||||
s.accountService.UpdateLoginDateAndIP(info)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.State, constants.STATUS_YES, "app.common.loginSuccess",
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
|
||||
data["tokenType"] = constants.HEADER_PREFIX
|
||||
data["accessToken"] = accessToken
|
||||
data["expiresIn"] = expiresIn
|
||||
data["refreshToken"] = refreshToken
|
||||
data["refreshExpiresIn"] = refreshExpiresIn
|
||||
data["userId"] = info.UserId
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
80
src/modules/auth/controller/account_smtp.go
Normal file
80
src/modules/auth/controller/account_smtp.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/auth/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SMTP SMTP认证登录
|
||||
//
|
||||
// POST /auth/smtp
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/smtp [post]
|
||||
func (s AccountController) SMTP(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var body model.LoginSourceBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 当前请求信息
|
||||
ipaddr, location := reqctx.IPAddrLocation(c)
|
||||
os, browser := reqctx.UaOsBrowser(c)
|
||||
|
||||
// 登录用户信息
|
||||
info, err := s.accountService.BySMTP(body)
|
||||
if err != nil {
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, err.Error(),
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId)
|
||||
|
||||
// 生成访问令牌
|
||||
accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access")
|
||||
if accessToken == "" || expiresIn == 0 {
|
||||
c.JSON(200, resp.ErrMsg("token generation failed"))
|
||||
return
|
||||
}
|
||||
// 生成刷新令牌
|
||||
refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh")
|
||||
|
||||
// 记录令牌,创建系统访问记录
|
||||
token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser})
|
||||
s.accountService.UpdateLoginDateAndIP(info)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_YES, "app.common.loginSuccess",
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
|
||||
data["tokenType"] = constants.HEADER_PREFIX
|
||||
data["accessToken"] = accessToken
|
||||
data["expiresIn"] = expiresIn
|
||||
data["refreshToken"] = refreshToken
|
||||
data["refreshExpiresIn"] = refreshExpiresIn
|
||||
data["userId"] = info.UserId
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
104
src/modules/auth/controller/account_system.go
Normal file
104
src/modules/auth/controller/account_system.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/auth/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Login 系统登录
|
||||
//
|
||||
// POST /auth/login
|
||||
//
|
||||
// @Tags common/authorization
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body object true "Request Param"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Summary System Login
|
||||
// @Description System Login
|
||||
// @Router /auth/login [post]
|
||||
func (s AccountController) Login(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var body model.LoginBody
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 当前请求信息
|
||||
ipaddr, location := reqctx.IPAddrLocation(c)
|
||||
os, browser := reqctx.UaOsBrowser(c)
|
||||
|
||||
// 校验验证码 根据错误信息,创建系统访问记录
|
||||
if err := s.accountService.ValidateCaptcha(body.Code, body.UUID); err != nil {
|
||||
msg := fmt.Sprintf("%s code %s", err.Error(), body.Code)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, msg,
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info, err := s.accountService.ByUsername(body.Username, body.Password)
|
||||
if err != nil {
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_NO, err.Error(),
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]any{}
|
||||
|
||||
if !config.IsSystemUser(info.UserId) {
|
||||
// 强制改密码
|
||||
forcePasswdChange, err := s.accountService.PasswordCountOrExpireTime(info.User.LoginCount, info.User.PasswordUpdateTime)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
if forcePasswdChange {
|
||||
data["forcePasswdChange"] = true
|
||||
}
|
||||
}
|
||||
|
||||
deviceFingerprint := reqctx.DeviceFingerprint(c, info.UserId)
|
||||
|
||||
// 生成访问令牌
|
||||
accessToken, expiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "access")
|
||||
if accessToken == "" || expiresIn == 0 {
|
||||
c.JSON(200, resp.ErrMsg("token generation failed"))
|
||||
return
|
||||
}
|
||||
// 生成刷新令牌
|
||||
refreshToken, refreshExpiresIn := token.UserTokenCreate(info.UserId, deviceFingerprint, "refresh")
|
||||
|
||||
// 记录令牌,创建系统访问记录
|
||||
token.UserInfoCreate(&info, deviceFingerprint, [4]string{ipaddr, location, os, browser})
|
||||
s.accountService.UpdateLoginDateAndIP(info)
|
||||
s.sysLogLoginService.Insert(
|
||||
body.Username, constants.STATUS_YES, "app.common.loginSuccess",
|
||||
[4]string{ipaddr, location, os, browser},
|
||||
)
|
||||
|
||||
data["tokenType"] = constants.HEADER_PREFIX
|
||||
data["accessToken"] = accessToken
|
||||
data["expiresIn"] = expiresIn
|
||||
data["refreshToken"] = refreshToken
|
||||
data["refreshExpiresIn"] = refreshExpiresIn
|
||||
data["userId"] = info.UserId
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/service"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/service"
|
||||
)
|
||||
|
||||
// NewOauth2 实例化控制层
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/service"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/service"
|
||||
)
|
||||
|
||||
// NewOauth2Client 实例化控制层
|
||||
@@ -2,15 +2,8 @@ package model
|
||||
|
||||
// LoginBody 用户登录对象
|
||||
type LoginBody struct {
|
||||
// Username 用户名
|
||||
Username string `json:"username" binding:"required"`
|
||||
|
||||
// Password 用户密码
|
||||
Password string `json:"password" binding:"required"`
|
||||
|
||||
// Code 验证码
|
||||
Code string `json:"code"`
|
||||
|
||||
// UUID 验证码唯一标识
|
||||
UUID string `json:"uuid"`
|
||||
Username string `json:"username" binding:"required"` // Username 用户名
|
||||
Password string `json:"password" binding:"required"` // Password 用户密码
|
||||
Code string `json:"code"` // Code 验证码
|
||||
UUID string `json:"uuid"` // UUID 验证码唯一标识
|
||||
}
|
||||
|
||||
22
src/modules/auth/model/login_source_body.go
Normal file
22
src/modules/auth/model/login_source_body.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
// LoginSourceVo 认证源登录对象
|
||||
type LoginSourceVo struct {
|
||||
UID string `json:"uid"` // UID 认证源UID
|
||||
Name string `json:"name"` // Name 认证源名称
|
||||
Type string `json:"type"` // Type 认证源类型
|
||||
Icon string `json:"icon"` // Icon 认证源图标
|
||||
}
|
||||
|
||||
// LoginSourceBody 认证源用户登录对象
|
||||
type LoginSourceBody struct {
|
||||
Username string `json:"username" binding:"required"` // Username 用户名
|
||||
Password string `json:"password" binding:"required"` // Password 用户密码
|
||||
UID string `json:"uid" binding:"required"` // UID 认证源唯一标识
|
||||
}
|
||||
|
||||
// LoginSourceOauth2Body 认证源OAuth2用户登录对象
|
||||
type LoginSourceOauth2Body struct {
|
||||
Code string `json:"code" binding:"required"` // Code 授权码
|
||||
State string `json:"state" binding:"required"` // State 状态-认证源唯一标识
|
||||
}
|
||||
@@ -8,3 +8,10 @@ type TokenBody struct {
|
||||
Code string `json:"code"` // 授权拿到的code值
|
||||
RefreshToken string `json:"refreshToken"` // 刷新令牌
|
||||
}
|
||||
|
||||
// CodeQuery 重定向授权码参数
|
||||
type CodeQuery struct {
|
||||
RedirectUrl string `form:"redirectUrl" binding:"required"` // 授权回调地址
|
||||
ClientId string `form:"clientId" binding:"required"` // 申请得到的客户端ID
|
||||
State string `form:"state" binding:"required"` // 随机字符串,认证服务器会原封不动地返回这个值
|
||||
}
|
||||
@@ -2,21 +2,10 @@ package model
|
||||
|
||||
// RegisterBody 用户注册对象
|
||||
type RegisterBody struct {
|
||||
// Username 用户名
|
||||
Username string `json:"username" binding:"required"`
|
||||
|
||||
// Password 用户密码
|
||||
Password string `json:"password" binding:"required"`
|
||||
|
||||
// ConfirmPassword 用户确认密码
|
||||
ConfirmPassword string `json:"confirmPassword" binding:"required"`
|
||||
|
||||
// Code 验证码
|
||||
Code string `json:"code"`
|
||||
|
||||
// UUID 验证码唯一标识
|
||||
UUID string `json:"uuid"`
|
||||
|
||||
// UserType 标记用户类型
|
||||
UserType string `json:"userType"`
|
||||
Username string `json:"username" binding:"required"` // Username 用户名
|
||||
Password string `json:"password" binding:"required"` // Password 用户密码
|
||||
ConfirmPassword string `json:"confirmPassword" binding:"required"` // ConfirmPassword 用户确认密码
|
||||
Code string `json:"code"` // Code 验证码
|
||||
UUID string `json:"uuid"` // UUID 验证码唯一标识
|
||||
UserType string `json:"userType"` // UserType 标记用户类型
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/auth/model"
|
||||
)
|
||||
|
||||
// NewOauth2Client 实例化数据层
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/auth/model"
|
||||
)
|
||||
|
||||
// NewOauth2LogLogin 实例化数据层
|
||||
@@ -69,9 +69,10 @@ func (r Oauth2LogLoginRepository) SelectByPage(query map[string]string) ([]model
|
||||
sortOrder := sortOrderArr[i]
|
||||
// 排序字段
|
||||
sort := "id"
|
||||
if sortBy == "loginIp" {
|
||||
switch sortBy {
|
||||
case "loginIp":
|
||||
sort = "login_ip"
|
||||
} else if sortBy == "createTime" {
|
||||
case "createTime":
|
||||
sort = "create_time"
|
||||
}
|
||||
// 排序方式
|
||||
@@ -2,102 +2,32 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/database/redis"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/crypto"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
systemModelVO "be.ems/src/modules/system/model/vo"
|
||||
"be.ems/src/modules/auth/model"
|
||||
systemModel "be.ems/src/modules/system/model"
|
||||
systemService "be.ems/src/modules/system/service"
|
||||
)
|
||||
|
||||
// 实例化服务层 Account 结构体
|
||||
var NewAccount = &Account{
|
||||
sysUserService: systemService.NewSysUser,
|
||||
sysConfigService: systemService.NewSysConfig,
|
||||
sysRoleService: systemService.NewSysRole,
|
||||
sysMenuService: systemService.NewSysMenu,
|
||||
sysUserService: systemService.NewSysUser,
|
||||
sysConfigService: systemService.NewSysConfig,
|
||||
sysRoleService: systemService.NewSysRole,
|
||||
sysMenuService: systemService.NewSysMenu,
|
||||
sysLogSourceService: systemService.NewSysLoginSource,
|
||||
}
|
||||
|
||||
// 账号身份操作服务 服务层处理
|
||||
type Account struct {
|
||||
sysUserService *systemService.SysUser // 用户信息服务
|
||||
sysConfigService *systemService.SysConfig // 参数配置服务
|
||||
sysRoleService *systemService.SysRole // 角色服务
|
||||
sysMenuService *systemService.SysMenu // 菜单服务
|
||||
}
|
||||
|
||||
// ValidateCaptcha 校验验证码
|
||||
func (s *Account) ValidateCaptcha(code, uuid string) error {
|
||||
// 验证码检查,从数据库配置获取验证码开关 true开启,false关闭
|
||||
captchaEnabledStr := s.sysConfigService.FindValueByKey("sys.account.captchaEnabled")
|
||||
if !parse.Boolean(captchaEnabledStr) {
|
||||
return nil
|
||||
}
|
||||
if code == "" || uuid == "" {
|
||||
// 验证码信息错误
|
||||
return fmt.Errorf("captcha.err")
|
||||
}
|
||||
verifyKey := constants.CACHE_CAPTCHA_CODE + ":" + uuid
|
||||
captcha, _ := redis.Get("", verifyKey)
|
||||
if captcha == "" {
|
||||
// 验证码已失效
|
||||
return fmt.Errorf("captcha.errValid")
|
||||
}
|
||||
_ = redis.Del("", verifyKey)
|
||||
if captcha != code {
|
||||
// 验证码错误
|
||||
return fmt.Errorf("captcha.err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ByUsername 登录创建用户信息
|
||||
func (s Account) ByUsername(username, password string) (token.UserInfo, error) {
|
||||
info := token.UserInfo{}
|
||||
|
||||
// 检查密码重试次数
|
||||
retryKey, retryCount, lockTime, err := s.passwordRetryCount(username)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 查询用户登录账号
|
||||
sysUser := s.sysUserService.FindByUserName(username)
|
||||
if sysUser.UserName != username {
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
if sysUser.DelFlag == constants.STATUS_YES {
|
||||
return info, fmt.Errorf("login.errDelFlag")
|
||||
}
|
||||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||||
return info, fmt.Errorf("login.errStatus")
|
||||
}
|
||||
|
||||
// 检验用户密码
|
||||
compareBool := crypto.BcryptCompare(password, sysUser.Password)
|
||||
if compareBool {
|
||||
s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数
|
||||
} else {
|
||||
_ = redis.Set("", retryKey, retryCount+1, lockTime)
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info.UserId = sysUser.UserId
|
||||
info.DeptId = sysUser.DeptId
|
||||
info.User = sysUser
|
||||
// 用户权限组标识
|
||||
if config.IsSystemUser(sysUser.UserId) {
|
||||
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
} else {
|
||||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||||
info.Permissions = parse.RemoveDuplicates(perms)
|
||||
}
|
||||
return info, nil
|
||||
sysUserService *systemService.SysUser // 用户信息服务
|
||||
sysConfigService *systemService.SysConfig // 参数配置服务
|
||||
sysRoleService *systemService.SysRole // 角色服务
|
||||
sysMenuService *systemService.SysMenu // 菜单服务
|
||||
sysLogSourceService *systemService.SysLoginSource // 认证源
|
||||
}
|
||||
|
||||
// ByUserId 用户ID刷新令牌创建用户信息
|
||||
@@ -140,86 +70,43 @@ func (s Account) UpdateLoginDateAndIP(info token.UserInfo) bool {
|
||||
return s.sysUserService.Update(user) > 0
|
||||
}
|
||||
|
||||
// CleanLoginRecordCache 清除错误记录次数
|
||||
func (s Account) CleanLoginRecordCache(userName string) bool {
|
||||
cacheKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||||
hasKey, err := redis.Has("", cacheKey)
|
||||
if hasKey > 0 && err == nil {
|
||||
return redis.Del("", cacheKey) == nil
|
||||
// LoginSource 登录认证源
|
||||
func (s Account) LoginSource() []model.LoginSourceVo {
|
||||
rows := s.sysLogSourceService.FindByActive("")
|
||||
data := make([]model.LoginSourceVo, 0)
|
||||
for _, v := range rows {
|
||||
data = append(data, model.LoginSourceVo{
|
||||
UID: v.UID,
|
||||
Name: v.Name,
|
||||
Type: v.Type,
|
||||
Icon: v.Icon,
|
||||
})
|
||||
}
|
||||
return false
|
||||
return data
|
||||
}
|
||||
|
||||
// passwordRetryCount 密码重试次数
|
||||
func (s Account) passwordRetryCount(userName string) (string, int64, time.Duration, error) {
|
||||
// 从数据库配置获取登录次数和错误锁定时间
|
||||
maxRetryCountStr := s.sysConfigService.FindValueByKey("sys.user.maxRetryCount")
|
||||
lockTimeStr := s.sysConfigService.FindValueByKey("sys.user.lockTime")
|
||||
// 验证登录次数和错误锁定时间
|
||||
maxRetryCount := parse.Number(maxRetryCountStr)
|
||||
lockTime := parse.Number(lockTimeStr)
|
||||
// initLoginSourceUser 初始化登录源用户
|
||||
func (s *Account) initLoginSourceUser(uid, sType, username, password string) systemModel.SysUser {
|
||||
sysUser := systemModel.SysUser{
|
||||
UserName: username,
|
||||
NickName: username, // 昵称使用名称账号
|
||||
Password: password, // 原始密码
|
||||
UserType: sType,
|
||||
UserSource: uid,
|
||||
Sex: "0", // 性别未选择
|
||||
StatusFlag: constants.STATUS_YES, // 账号状态激活
|
||||
DeptId: 101, // 归属部门为根节点
|
||||
CreateBy: sType, // 创建来源
|
||||
}
|
||||
|
||||
// 验证缓存记录次数
|
||||
retryKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||||
retryCount, err := redis.Get("", retryKey)
|
||||
if retryCount == "" || err != nil {
|
||||
retryCount = "0"
|
||||
// 新增用户的角色管理
|
||||
sysUser.RoleIds = []int64{5}
|
||||
// 新增用户的岗位管理
|
||||
sysUser.PostIds = []int64{}
|
||||
|
||||
insertId := s.sysUserService.Insert(sysUser)
|
||||
if insertId > 0 {
|
||||
sysUser.UserId = insertId
|
||||
}
|
||||
// 是否超过错误值
|
||||
retryCountInt64 := parse.Number(retryCount)
|
||||
if retryCountInt64 >= int64(maxRetryCount) {
|
||||
// msg := fmt.Sprintf("密码输入错误 %d 次,帐户锁定 %d 分钟", maxRetryCount, lockTime)
|
||||
msg := fmt.Errorf("login.errRetryPasswd") // 密码输入错误多次,帐户已被锁定
|
||||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, fmt.Errorf("%s", msg)
|
||||
}
|
||||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
|
||||
}
|
||||
|
||||
// PasswordCountOrExpireTime 首次登录或密码过期时间
|
||||
func (s Account) PasswordCountOrExpireTime(loginCount, passwordUpdateTime int64) (bool, error) {
|
||||
forcePasswdChange := false
|
||||
// 从数据库配置获取-首次登录密码修改
|
||||
fristPasswdChangeStr := s.sysConfigService.FindValueByKey("sys.user.fristPasswdChange")
|
||||
if parse.Boolean(fristPasswdChangeStr) {
|
||||
forcePasswdChange = loginCount < 1 || passwordUpdateTime == 0
|
||||
}
|
||||
|
||||
// 非首次登录,判断密码是否过期
|
||||
if !forcePasswdChange {
|
||||
alert, err := s.sysUserService.ValidatePasswordExpireTime(passwordUpdateTime)
|
||||
if err != nil {
|
||||
return alert, err
|
||||
}
|
||||
forcePasswdChange = alert
|
||||
}
|
||||
return forcePasswdChange, nil
|
||||
}
|
||||
|
||||
// RoleAndMenuPerms 角色和菜单数据权限
|
||||
func (s Account) RoleAndMenuPerms(userId int64, isSystemUser bool) ([]string, []string) {
|
||||
if isSystemUser {
|
||||
return []string{constants.SYS_ROLE_SYSTEM_KEY}, []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
}
|
||||
// 角色key
|
||||
var roleGroup []string
|
||||
roles := s.sysRoleService.FindByUserId(userId)
|
||||
for _, role := range roles {
|
||||
roleGroup = append(roleGroup, role.RoleKey)
|
||||
}
|
||||
// 菜单权限key
|
||||
perms := s.sysMenuService.FindPermsByUserId(userId)
|
||||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
||||
}
|
||||
|
||||
// RouteMenus 前端路由所需要的菜单
|
||||
func (s Account) RouteMenus(userId int64, isSystemUser bool) []systemModelVO.Router {
|
||||
var buildMenus []systemModelVO.Router
|
||||
if isSystemUser {
|
||||
menus := s.sysMenuService.BuildTreeMenusByUserId(0)
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
} else {
|
||||
menus := s.sysMenuService.BuildTreeMenusByUserId(userId)
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
}
|
||||
return buildMenus
|
||||
return s.sysUserService.FindByUserName(username, sType, uid)
|
||||
}
|
||||
|
||||
36
src/modules/auth/service/account_info.go
Normal file
36
src/modules/auth/service/account_info.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
systemModelVO "be.ems/src/modules/system/model/vo"
|
||||
)
|
||||
|
||||
// RoleAndMenuPerms 角色和菜单数据权限
|
||||
func (s Account) RoleAndMenuPerms(userId int64, isSystemUser bool) ([]string, []string) {
|
||||
if isSystemUser {
|
||||
return []string{constants.SYS_ROLE_SYSTEM_KEY}, []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
}
|
||||
// 角色key
|
||||
var roleGroup []string
|
||||
roles := s.sysRoleService.FindByUserId(userId)
|
||||
for _, role := range roles {
|
||||
roleGroup = append(roleGroup, role.RoleKey)
|
||||
}
|
||||
// 菜单权限key
|
||||
perms := s.sysMenuService.FindPermsByUserId(userId)
|
||||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
||||
}
|
||||
|
||||
// RouteMenus 前端路由所需要的菜单
|
||||
func (s Account) RouteMenus(userId int64, isSystemUser bool) []systemModelVO.Router {
|
||||
var buildMenus []systemModelVO.Router
|
||||
if isSystemUser {
|
||||
menus := s.sysMenuService.BuildTreeMenusByUserId(0)
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
} else {
|
||||
menus := s.sysMenuService.BuildTreeMenusByUserId(userId)
|
||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||
}
|
||||
return buildMenus
|
||||
}
|
||||
108
src/modules/auth/service/account_ldap.go
Normal file
108
src/modules/auth/service/account_ldap.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/auth/model"
|
||||
systemModelVo "be.ems/src/modules/system/model/vo"
|
||||
)
|
||||
|
||||
// ByLDAP 登录创建用户信息
|
||||
func (s *Account) ByLDAP(body model.LoginSourceBody) (token.UserInfo, error) {
|
||||
info := token.UserInfo{}
|
||||
rows := s.sysLogSourceService.FindByActive(body.UID)
|
||||
if len(rows) != 1 {
|
||||
return info, fmt.Errorf("ldap auth source not exist")
|
||||
}
|
||||
item := rows[0]
|
||||
if item.Config == "" {
|
||||
return info, fmt.Errorf("ldap auth source config is empty")
|
||||
}
|
||||
var source systemModelVo.SysLoginSourceLDAP
|
||||
if err := json.Unmarshal([]byte(item.Config), &source); err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 校验LDAP用户
|
||||
err := ldapAuth(source, body.Username, body.Password)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 查询用户登录账号
|
||||
sysUser := s.sysUserService.FindByUserName(body.Username, item.Type, item.UID)
|
||||
if sysUser.UserId == 0 || sysUser.UserName == "" {
|
||||
sysUser = s.initLoginSourceUser(item.UID, item.Type, body.Username, body.Password)
|
||||
}
|
||||
if sysUser.UserId == 0 || sysUser.UserName != body.Username {
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
if sysUser.DelFlag == constants.STATUS_YES {
|
||||
return info, fmt.Errorf("login.errDelFlag")
|
||||
}
|
||||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||||
return info, fmt.Errorf("login.errStatus")
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info.UserId = sysUser.UserId
|
||||
info.DeptId = sysUser.DeptId
|
||||
info.User = sysUser
|
||||
// 用户权限组标识
|
||||
if config.IsSystemUser(sysUser.UserId) {
|
||||
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
} else {
|
||||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||||
info.Permissions = parse.RemoveDuplicates(perms)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// ldapAuth 校验LDAP用户
|
||||
func ldapAuth(source systemModelVo.SysLoginSourceLDAP, username, password string) error {
|
||||
// 连接LDAP
|
||||
l, err := ldap.DialURL(source.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
// 绑定DN校验
|
||||
if source.BindDN != "" && source.BindPassword != "" {
|
||||
if err := l.Bind(source.BindDN, source.BindPassword); err != nil {
|
||||
return fmt.Errorf("ldap user bind %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索用户
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
source.BaseDN,
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
fmt.Sprintf(source.UserFilter, ldap.EscapeFilter(username)),
|
||||
[]string{"dn", "uid"},
|
||||
nil,
|
||||
)
|
||||
sr, err := l.Search(searchRequest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ldap user search %s", err)
|
||||
}
|
||||
// for _, entry := range sr.Entries {
|
||||
// fmt.Printf("%s ==== %v\n", entry.DN, entry.GetAttributeValue("uid"))
|
||||
// }
|
||||
if len(sr.Entries) != 1 {
|
||||
return fmt.Errorf("ldap user does not exist or too many entries returned")
|
||||
}
|
||||
|
||||
// 校验密码
|
||||
if err = l.Bind(sr.Entries[0].DN, password); err != nil {
|
||||
return fmt.Errorf("ldap user bind %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
168
src/modules/auth/service/account_oauth2.go
Normal file
168
src/modules/auth/service/account_oauth2.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/auth/model"
|
||||
systemModelVo "be.ems/src/modules/system/model/vo"
|
||||
)
|
||||
|
||||
// ByOAuth2CodeURL 获取OAuth2登录URL
|
||||
func (s *Account) ByOAuth2CodeURL(state string) (string, error) {
|
||||
rows := s.sysLogSourceService.FindByActive(state)
|
||||
if len(rows) != 1 {
|
||||
return "", fmt.Errorf("oauth2 auth source not exist")
|
||||
}
|
||||
item := rows[0]
|
||||
if item.Config == "" {
|
||||
return "", fmt.Errorf("oauth2 auth source config is empty")
|
||||
}
|
||||
var source systemModelVo.SysLoginSourceOAuth2
|
||||
json.Unmarshal([]byte(item.Config), &source)
|
||||
|
||||
conf := oauth2.Config{
|
||||
ClientID: source.ClientID,
|
||||
ClientSecret: source.ClientSecret,
|
||||
RedirectURL: source.RedirectURL,
|
||||
Scopes: source.Scopes,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: source.AuthURL,
|
||||
TokenURL: source.TokenURL,
|
||||
},
|
||||
}
|
||||
return conf.AuthCodeURL(state, oauth2.AccessTypeOffline), nil
|
||||
}
|
||||
|
||||
// ByOAuth2 登录创建用户信息
|
||||
func (s *Account) ByOAuth2(body model.LoginSourceOauth2Body) (token.UserInfo, error) {
|
||||
info := token.UserInfo{}
|
||||
rows := s.sysLogSourceService.FindByActive(body.State)
|
||||
if len(rows) != 1 {
|
||||
return info, fmt.Errorf("oauth2 auth source not exist")
|
||||
}
|
||||
item := rows[0]
|
||||
if item.Config == "" {
|
||||
return info, fmt.Errorf("oauth2 auth source config is empty")
|
||||
}
|
||||
var source systemModelVo.SysLoginSourceOAuth2
|
||||
if err := json.Unmarshal([]byte(item.Config), &source); err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 校验OAuth2用户
|
||||
account, err := oauth2Auth(source, body.Code)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 查询用户登录账号
|
||||
sysUser := s.sysUserService.FindByUserName(account, item.Type, item.UID)
|
||||
if sysUser.UserId == 0 || sysUser.UserName == "" {
|
||||
sysUser = s.initLoginSourceUser(item.UID, item.Type, account, account)
|
||||
}
|
||||
if sysUser.UserId == 0 || sysUser.UserName != account {
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
if sysUser.DelFlag == constants.STATUS_YES {
|
||||
return info, fmt.Errorf("login.errDelFlag")
|
||||
}
|
||||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||||
return info, fmt.Errorf("login.errStatus")
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info.UserId = sysUser.UserId
|
||||
info.DeptId = sysUser.DeptId
|
||||
info.User = sysUser
|
||||
// 用户权限组标识
|
||||
if config.IsSystemUser(sysUser.UserId) {
|
||||
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
} else {
|
||||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||||
info.Permissions = parse.RemoveDuplicates(perms)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// oauth2Auth 校验OAuth2用户
|
||||
func oauth2Auth(source systemModelVo.SysLoginSourceOAuth2, code string) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
conf := oauth2.Config{
|
||||
ClientID: source.ClientID,
|
||||
ClientSecret: source.ClientSecret,
|
||||
RedirectURL: source.RedirectURL,
|
||||
Scopes: source.Scopes,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: source.AuthURL,
|
||||
TokenURL: source.TokenURL,
|
||||
},
|
||||
}
|
||||
token, err := conf.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 使用token创建HTTP客户端 请求用户信息
|
||||
resp, err := conf.Client(ctx, token).Get(source.UserURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// 解析用户信息
|
||||
var userInfo map[string]any
|
||||
if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 读取嵌套数据
|
||||
value, found := getValueByPath(userInfo, source.AccountField)
|
||||
if !found {
|
||||
return "", fmt.Errorf("oauth2 auth source account field not exist")
|
||||
}
|
||||
return fmt.Sprintf("%v", value), nil
|
||||
}
|
||||
|
||||
// getValueByPath 从嵌套的 map[string]any 获取嵌套键对应的值
|
||||
func getValueByPath(data map[string]any, path string) (any, bool) {
|
||||
keys := strings.Split(path, ".") // 按照 "." 拆分路径
|
||||
return getValue(data, keys)
|
||||
}
|
||||
|
||||
// getValue 是递归查找嵌套 map 的函数
|
||||
func getValue(data map[string]any, keys []string) (any, bool) {
|
||||
if len(keys) == 0 {
|
||||
return data, false
|
||||
}
|
||||
|
||||
// 获取当前键
|
||||
key := keys[0]
|
||||
|
||||
// 获取当前键的值
|
||||
val, ok := data[key]
|
||||
if !ok {
|
||||
return nil, false // 找不到键,返回 false
|
||||
}
|
||||
|
||||
// 如果还有嵌套键,继续查找
|
||||
if len(keys) > 1 {
|
||||
// 递归查找嵌套 map
|
||||
if reflect.TypeOf(val).Kind() == reflect.Map {
|
||||
// 将 `any` 转换为 `map[string]any` 类型
|
||||
if nestedMap, ok := val.(map[string]any); ok {
|
||||
return getValue(nestedMap, keys[1:])
|
||||
}
|
||||
}
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
88
src/modules/auth/service/account_smtp.go
Normal file
88
src/modules/auth/service/account_smtp.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/wneessen/go-mail"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/auth/model"
|
||||
systemModelVo "be.ems/src/modules/system/model/vo"
|
||||
)
|
||||
|
||||
// BySMTP 登录创建用户信息
|
||||
func (s *Account) BySMTP(body model.LoginSourceBody) (token.UserInfo, error) {
|
||||
info := token.UserInfo{}
|
||||
rows := s.sysLogSourceService.FindByActive(body.UID)
|
||||
if len(rows) != 1 {
|
||||
return info, fmt.Errorf("smtp auth source not exist")
|
||||
}
|
||||
item := rows[0]
|
||||
if item.Config == "" {
|
||||
return info, fmt.Errorf("smtp auth source config is empty")
|
||||
}
|
||||
var source systemModelVo.SysLoginSourceSMTP
|
||||
if err := json.Unmarshal([]byte(item.Config), &source); err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 校验SMTP用户
|
||||
err := smtpAuth(source, body.Username, body.Password)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 查询用户登录账号
|
||||
sysUser := s.sysUserService.FindByUserName(body.Username, item.Type, item.UID)
|
||||
if sysUser.UserId == 0 || sysUser.UserName == "" {
|
||||
sysUser = s.initLoginSourceUser(item.UID, item.Type, body.Username, body.Password)
|
||||
}
|
||||
if sysUser.UserId == 0 || sysUser.UserName != body.Username {
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
if sysUser.DelFlag == constants.STATUS_YES {
|
||||
return info, fmt.Errorf("login.errDelFlag")
|
||||
}
|
||||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||||
return info, fmt.Errorf("login.errStatus")
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info.UserId = sysUser.UserId
|
||||
info.DeptId = sysUser.DeptId
|
||||
info.User = sysUser
|
||||
// 用户权限组标识
|
||||
if config.IsSystemUser(sysUser.UserId) {
|
||||
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
} else {
|
||||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||||
info.Permissions = parse.RemoveDuplicates(perms)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// smtpAuth 校验SMTP用户
|
||||
func smtpAuth(source systemModelVo.SysLoginSourceSMTP, username, password string) error {
|
||||
client, err := mail.NewClient(source.Host,
|
||||
mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover),
|
||||
mail.WithUsername(username),
|
||||
mail.WithPort(source.Port),
|
||||
mail.WithPassword(password),
|
||||
mail.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create mail client %s", err)
|
||||
}
|
||||
// 连接到邮件SMTP服务器
|
||||
if err = client.DialWithContext(context.Background()); err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
return nil
|
||||
}
|
||||
138
src/modules/auth/service/account_sysstem.go
Normal file
138
src/modules/auth/service/account_sysstem.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/database/redis"
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/crypto"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
)
|
||||
|
||||
// ValidateCaptcha 校验验证码
|
||||
func (s Account) ValidateCaptcha(code, uuid string) error {
|
||||
// 验证码检查,从数据库配置获取验证码开关 true开启,false关闭
|
||||
captchaEnabledStr := s.sysConfigService.FindValueByKey("sys.account.captchaEnabled")
|
||||
if !parse.Boolean(captchaEnabledStr) {
|
||||
return nil
|
||||
}
|
||||
if code == "" || uuid == "" {
|
||||
// 验证码信息错误
|
||||
return fmt.Errorf("captcha.err")
|
||||
}
|
||||
verifyKey := constants.CACHE_CAPTCHA_CODE + ":" + uuid
|
||||
captcha, _ := redis.Get("", verifyKey)
|
||||
if captcha == "" {
|
||||
// 验证码已失效
|
||||
return fmt.Errorf("captcha.errValid")
|
||||
}
|
||||
_ = redis.Del("", verifyKey)
|
||||
if captcha != code {
|
||||
// 验证码错误
|
||||
return fmt.Errorf("captcha.err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ByUsername 登录创建用户信息
|
||||
func (s Account) ByUsername(username, password string) (token.UserInfo, error) {
|
||||
info := token.UserInfo{}
|
||||
|
||||
// 检查密码重试次数
|
||||
retryKey, retryCount, lockTime, err := s.passwordRetryCount(username)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
// 查询用户登录账号
|
||||
sysUser := s.sysUserService.FindByUserName(username, "System", "#")
|
||||
if sysUser.UserName != username {
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
if sysUser.DelFlag == constants.STATUS_YES {
|
||||
return info, fmt.Errorf("login.errDelFlag")
|
||||
}
|
||||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||||
return info, fmt.Errorf("login.errStatus")
|
||||
}
|
||||
|
||||
// 检验用户密码
|
||||
compareBool := crypto.BcryptCompare(password, sysUser.Password)
|
||||
if compareBool {
|
||||
s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数
|
||||
} else {
|
||||
_ = redis.Set("", retryKey, retryCount+1, lockTime)
|
||||
return info, fmt.Errorf("login.errNameOrPasswd")
|
||||
}
|
||||
|
||||
// 登录用户信息
|
||||
info.UserId = sysUser.UserId
|
||||
info.DeptId = sysUser.DeptId
|
||||
info.User = sysUser
|
||||
// 用户权限组标识
|
||||
if config.IsSystemUser(sysUser.UserId) {
|
||||
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||||
} else {
|
||||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||||
info.Permissions = parse.RemoveDuplicates(perms)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// CleanLoginRecordCache 清除错误记录次数
|
||||
func (s Account) CleanLoginRecordCache(userName string) bool {
|
||||
cacheKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||||
hasKey, err := redis.Has("", cacheKey)
|
||||
if hasKey > 0 && err == nil {
|
||||
return redis.Del("", cacheKey) == nil
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// passwordRetryCount 密码重试次数
|
||||
func (s Account) passwordRetryCount(userName string) (string, int64, time.Duration, error) {
|
||||
// 从数据库配置获取登录次数和错误锁定时间
|
||||
maxRetryCountStr := s.sysConfigService.FindValueByKey("sys.user.maxRetryCount")
|
||||
lockTimeStr := s.sysConfigService.FindValueByKey("sys.user.lockTime")
|
||||
// 验证登录次数和错误锁定时间
|
||||
maxRetryCount := parse.Number(maxRetryCountStr)
|
||||
lockTime := parse.Number(lockTimeStr)
|
||||
|
||||
// 验证缓存记录次数
|
||||
retryKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||||
retryCount, err := redis.Get("", retryKey)
|
||||
if retryCount == "" || err != nil {
|
||||
retryCount = "0"
|
||||
}
|
||||
// 是否超过错误值
|
||||
retryCountInt64 := parse.Number(retryCount)
|
||||
if retryCountInt64 >= int64(maxRetryCount) {
|
||||
// msg := fmt.Sprintf("密码输入错误 %d 次,帐户锁定 %d 分钟", maxRetryCount, lockTime)
|
||||
msg := fmt.Errorf("login.errRetryPasswd") // 密码输入错误多次,帐户已被锁定
|
||||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, fmt.Errorf("%s", msg)
|
||||
}
|
||||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
|
||||
}
|
||||
|
||||
// PasswordCountOrExpireTime 首次登录或密码过期时间
|
||||
func (s Account) PasswordCountOrExpireTime(loginCount, passwordUpdateTime int64) (bool, error) {
|
||||
forcePasswdChange := false
|
||||
// 从数据库配置获取-首次登录密码修改
|
||||
fristPasswdChangeStr := s.sysConfigService.FindValueByKey("sys.user.fristPasswdChange")
|
||||
if parse.Boolean(fristPasswdChangeStr) {
|
||||
forcePasswdChange = loginCount < 1 || passwordUpdateTime == 0
|
||||
}
|
||||
|
||||
// 非首次登录,判断密码是否过期
|
||||
if !forcePasswdChange {
|
||||
alert, err := s.sysUserService.ValidatePasswordExpireTime(passwordUpdateTime)
|
||||
if err != nil {
|
||||
return alert, err
|
||||
}
|
||||
forcePasswdChange = alert
|
||||
}
|
||||
return forcePasswdChange, nil
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"be.ems/src/framework/token"
|
||||
"be.ems/src/framework/utils/crypto"
|
||||
"be.ems/src/framework/utils/generate"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2Service 实例化服务层
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/utils/generate"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2ClientService 实例化服务层
|
||||
@@ -55,11 +55,11 @@ func (s Oauth2ClientService) DeleteByIds(ids []int64) (int64, error) {
|
||||
arr := s.oauth2ClientRepository.SelectByIds(ids)
|
||||
if len(arr) <= 0 {
|
||||
// return 0, fmt.Errorf("没有权限访问用户授权第三方应用数据!")
|
||||
return 0, fmt.Errorf("No permission to access user-authorized third-party application data!")
|
||||
return 0, fmt.Errorf("no permission to access user-authorized third-party application data")
|
||||
}
|
||||
if len(arr) == len(ids) {
|
||||
return s.oauth2ClientRepository.DeleteByIds(ids), nil
|
||||
}
|
||||
// return 0, fmt.Errorf("删除用户授权第三方应用信息失败!")
|
||||
return 0, fmt.Errorf("Failed to delete user-authorized third-party application information!")
|
||||
return 0, fmt.Errorf("failed to delete user-authorized third-party application information")
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/modules/oauth2/model"
|
||||
"be.ems/src/modules/oauth2/repository"
|
||||
"be.ems/src/modules/auth/model"
|
||||
"be.ems/src/modules/auth/repository"
|
||||
)
|
||||
|
||||
// NewOauth2LogLogin 实例化服务层
|
||||
@@ -61,12 +61,14 @@ func (s Register) ByUserName(username, password string) (int64, error) {
|
||||
|
||||
sysUser := systemModel.SysUser{
|
||||
UserName: username,
|
||||
NickName: username, // 昵称使用名称账号
|
||||
Password: password, // 原始密码
|
||||
NickName: username, // 昵称使用名称账号
|
||||
Password: password, // 原始密码
|
||||
UserType: "System",
|
||||
UserSource: "#",
|
||||
Sex: "0", // 性别未选择
|
||||
StatusFlag: constants.STATUS_YES, // 账号状态激活
|
||||
DeptId: 100, // 归属部门为根节点
|
||||
CreateBy: "register", // 创建来源
|
||||
DeptId: 101, // 归属部门为根节点
|
||||
CreateBy: "System", // 创建来源
|
||||
}
|
||||
|
||||
// 新增用户的角色管理
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
neDataModel "be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neModel "be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
@@ -23,26 +22,20 @@ import (
|
||||
)
|
||||
|
||||
var NewProcessor = &BackupExportCDRProcessor{
|
||||
count: 0,
|
||||
backupService: neDataService.NewBackup,
|
||||
sysDictService: systemService.NewSysDictData,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
imsCDREventService: neDataService.NewCDREventIMS,
|
||||
smscCDREventService: neDataService.NewCDREventSMSC,
|
||||
smfCDREventService: neDataService.NewCDREventSMF,
|
||||
sgwcCDREventService: neDataService.NewCDREventSGWC,
|
||||
count: 0,
|
||||
backupService: neDataService.NewBackup,
|
||||
sysDictService: systemService.NewSysDictData,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
}
|
||||
|
||||
// BackupExportCDR 队列任务处理
|
||||
type BackupExportCDRProcessor struct {
|
||||
count int // 执行次数
|
||||
backupService *neDataService.Backup // 备份相关服务
|
||||
sysDictService *systemService.SysDictData // 字典类型数据服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
imsCDREventService *neDataService.CDREventIMS // IMS-CDR会话事件服务
|
||||
smscCDREventService *neDataService.CDREventSMSC // SMSC-CDR会话事件服务
|
||||
smfCDREventService *neDataService.CDREventSMF // SMF-CDR会话事件服务
|
||||
sgwcCDREventService *neDataService.CDREventSGWC // SGWC-CDR会话事件服务
|
||||
count int // 执行次数
|
||||
backupService *neDataService.Backup // 备份相关服务
|
||||
sysDictService *systemService.SysDictData // 字典类型数据服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
}
|
||||
|
||||
func (s *BackupExportCDRProcessor) Execute(data any) (any, error) {
|
||||
@@ -104,16 +97,16 @@ func (s BackupExportCDRProcessor) exportIMS(hour int, rmUID, fileType string) st
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
language := "en"
|
||||
query := neDataModel.CDREventIMSQuery{
|
||||
SortField: "timestamp",
|
||||
SortOrder: "asc",
|
||||
RmUID: rmUID,
|
||||
BeginTime: start.UnixMilli(),
|
||||
EndTime: end.UnixMilli(),
|
||||
PageNum: 1,
|
||||
PageSize: 30000,
|
||||
query := map[string]string{
|
||||
"sortField": "timestamp",
|
||||
"sortOrder": "asc",
|
||||
"rmUID": rmUID,
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
"pageNum": fmt.Sprint(1),
|
||||
"pageSize": fmt.Sprint(30000),
|
||||
}
|
||||
rows, total := s.imsCDREventService.FindByPage(query)
|
||||
rows, total := s.cdrEventService.FindByPage("IMS", query)
|
||||
if total == 0 {
|
||||
return "no data"
|
||||
}
|
||||
@@ -393,16 +386,16 @@ func (s BackupExportCDRProcessor) exportSMSC(hour int, rmUID, fileType string) s
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
language := "en"
|
||||
query := neDataModel.CDREventSMSCQuery{
|
||||
SortField: "timestamp",
|
||||
SortOrder: "asc",
|
||||
RmUID: rmUID,
|
||||
BeginTime: start.UnixMilli(),
|
||||
EndTime: end.UnixMilli(),
|
||||
PageNum: 1,
|
||||
PageSize: 30000,
|
||||
query := map[string]string{
|
||||
"sortField": "timestamp",
|
||||
"sortOrder": "asc",
|
||||
"rmUID": rmUID,
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
"pageNum": fmt.Sprint(1),
|
||||
"pageSize": fmt.Sprint(30000),
|
||||
}
|
||||
rows, total := s.smscCDREventService.FindByPage(query)
|
||||
rows, total := s.cdrEventService.FindByPage("SMSC", query)
|
||||
if total == 0 {
|
||||
return "no data"
|
||||
}
|
||||
@@ -609,16 +602,16 @@ func (s BackupExportCDRProcessor) exportSMF(hour int, rmUID, fileType string) st
|
||||
end := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
query := neDataModel.CDREventSMFQuery{
|
||||
SortField: "timestamp",
|
||||
SortOrder: "asc",
|
||||
RmUID: rmUID,
|
||||
BeginTime: start.UnixMilli(),
|
||||
EndTime: end.UnixMilli(),
|
||||
PageNum: 1,
|
||||
PageSize: 30000,
|
||||
query := map[string]string{
|
||||
"sortField": "timestamp",
|
||||
"sortOrder": "asc",
|
||||
"rmUID": rmUID,
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
"pageNum": fmt.Sprint(1),
|
||||
"pageSize": fmt.Sprint(30000),
|
||||
}
|
||||
rows, total := s.smfCDREventService.FindByPage(query)
|
||||
rows, total := s.cdrEventService.FindByPage("SMF", query)
|
||||
if total == 0 {
|
||||
return "no data"
|
||||
}
|
||||
@@ -1017,16 +1010,16 @@ func (s BackupExportCDRProcessor) exportSGWC(hour int, rmUID, fileType string) s
|
||||
end := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
query := neDataModel.CDREventSGWCQuery{
|
||||
SortField: "timestamp",
|
||||
SortOrder: "asc",
|
||||
RmUID: rmUID,
|
||||
BeginTime: start.UnixMilli(),
|
||||
EndTime: end.UnixMilli(),
|
||||
PageNum: 1,
|
||||
PageSize: 30000,
|
||||
query := map[string]string{
|
||||
"sortField": "timestamp",
|
||||
"sortOrder": "asc",
|
||||
"rmUID": rmUID,
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
"pageNum": fmt.Sprint(1),
|
||||
"pageSize": fmt.Sprint(30000),
|
||||
}
|
||||
rows, total := s.sgwcCDREventService.FindByPage(query)
|
||||
rows, total := s.cdrEventService.FindByPage("SGWC", query)
|
||||
if total == 0 {
|
||||
return "no data"
|
||||
}
|
||||
|
||||
@@ -15,21 +15,22 @@ import (
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
neDataModel "be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
systemModel "be.ems/src/modules/system/model"
|
||||
systemService "be.ems/src/modules/system/service"
|
||||
)
|
||||
|
||||
var NewProcessor = &BackupExportTableProcessor{
|
||||
backupService: neDataService.NewBackup,
|
||||
count: 0,
|
||||
backupService: neDataService.NewBackup,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
count: 0,
|
||||
}
|
||||
|
||||
// BackupExportTable 备份导出数据表
|
||||
type BackupExportTableProcessor struct {
|
||||
backupService *neDataService.Backup // 备份相关服务
|
||||
count int // 执行次数
|
||||
backupService *neDataService.Backup // 备份相关服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
count int // 执行次数
|
||||
}
|
||||
|
||||
func (s *BackupExportTableProcessor) Execute(data any) (any, error) {
|
||||
@@ -197,13 +198,13 @@ func (s BackupExportTableProcessor) exportSMF(hour int, columns []string, filePa
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
// 查询数据
|
||||
rows := []neDataModel.CDREventSMF{}
|
||||
tx := db.DB("").Model(&neDataModel.CDREventSMF{})
|
||||
tx = tx.Where("created_at >= ? and created_at <= ?", start.UnixMilli(), end.UnixMilli())
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(rows) <= 0 {
|
||||
rows, total := s.cdrEventService.FindByPage("SMF", map[string]string{
|
||||
"sortField": "created_at",
|
||||
"sortOrder": "asc",
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
})
|
||||
if total <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -417,7 +418,7 @@ func (s BackupExportTableProcessor) exportSMF(hour int, columns []string, filePa
|
||||
|
||||
err := file.WriterFileCSV(data, filePath)
|
||||
|
||||
return tx.RowsAffected, err
|
||||
return total, err
|
||||
}
|
||||
|
||||
// exportIMS 导出csv
|
||||
@@ -428,13 +429,13 @@ func (s BackupExportTableProcessor) exportIMS(hour int, columns []string, filePa
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
// 查询数据
|
||||
rows := []neDataModel.CDREventIMS{}
|
||||
tx := db.DB("").Model(&neDataModel.CDREventIMS{})
|
||||
tx = tx.Where("created_at >= ? and created_at <= ?", start.UnixMilli(), end.UnixMilli())
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(rows) <= 0 {
|
||||
rows, total := s.cdrEventService.FindByPage("IMS", map[string]string{
|
||||
"sortField": "created_at",
|
||||
"sortOrder": "asc",
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
})
|
||||
if total <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -561,7 +562,7 @@ func (s BackupExportTableProcessor) exportIMS(hour int, columns []string, filePa
|
||||
|
||||
err := file.WriterFileCSV(data, filePath)
|
||||
|
||||
return tx.RowsAffected, err
|
||||
return total, err
|
||||
}
|
||||
|
||||
// exportSMSC 导出csv
|
||||
@@ -572,13 +573,13 @@ func (s BackupExportTableProcessor) exportSMSC(hour int, columns []string, fileP
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
// 查询数据
|
||||
rows := []neDataModel.CDREventSMSC{}
|
||||
tx := db.DB("").Model(&neDataModel.CDREventSMSC{})
|
||||
tx = tx.Where("created_at >= ? and created_at <= ?", start.UnixMilli(), end.UnixMilli())
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(rows) <= 0 {
|
||||
rows, total := s.cdrEventService.FindByPage("SMS", map[string]string{
|
||||
"sortField": "created_at",
|
||||
"sortOrder": "asc",
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
})
|
||||
if total <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -686,7 +687,7 @@ func (s BackupExportTableProcessor) exportSMSC(hour int, columns []string, fileP
|
||||
|
||||
err := file.WriterFileCSV(data, filePath)
|
||||
|
||||
return tx.RowsAffected, err
|
||||
return total, err
|
||||
}
|
||||
|
||||
// exportSGWC 导出csv
|
||||
@@ -697,13 +698,13 @@ func (s BackupExportTableProcessor) exportSGWC(hour int, columns []string, fileP
|
||||
start := end.Add(-time.Duration(hour) * time.Hour)
|
||||
|
||||
// 查询数据
|
||||
rows := []neDataModel.CDREventSMSC{}
|
||||
tx := db.DB("").Model(&neDataModel.CDREventSMSC{})
|
||||
tx = tx.Where("created_at >= ? and created_at <= ?", start.UnixMilli(), end.UnixMilli())
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(rows) <= 0 {
|
||||
rows, total := s.cdrEventService.FindByPage("SGWC", map[string]string{
|
||||
"sortField": "created_at",
|
||||
"sortOrder": "asc",
|
||||
"beginTime": fmt.Sprint(start.UnixMilli()),
|
||||
"endTime": fmt.Sprint(end.UnixMilli()),
|
||||
})
|
||||
if total <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -923,5 +924,5 @@ func (s BackupExportTableProcessor) exportSGWC(hour int, columns []string, fileP
|
||||
|
||||
err := file.WriterFileCSV(data, filePath)
|
||||
|
||||
return tx.RowsAffected, err
|
||||
return total, err
|
||||
}
|
||||
|
||||
@@ -5,33 +5,26 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tsmask/go-oam"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/cron"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
|
||||
neDataModel "be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neModel "be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
oamService "be.ems/src/modules/oam/service"
|
||||
)
|
||||
|
||||
var NewProcessor = &NeAlarmStateCheckProcessor{
|
||||
neConfigBackupService: neService.NewNeConfigBackup,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
alarmService: neDataService.NewAlarm,
|
||||
wsSendService: wsService.NewWSSend,
|
||||
count: 0,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
count: 0,
|
||||
}
|
||||
|
||||
// NeAlarmStateCheckProcessor 网元告警状态检查
|
||||
type NeAlarmStateCheckProcessor struct {
|
||||
neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
alarmService *neDataService.Alarm // 告警信息服务
|
||||
wsSendService *wsService.WSSend // ws发送服务
|
||||
count int // 执行次数
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
count int // 执行次数
|
||||
}
|
||||
|
||||
// alarmParams 告警参数
|
||||
@@ -69,104 +62,37 @@ func (s *NeAlarmStateCheckProcessor) Execute(data any) (any, error) {
|
||||
if neInfo.CreateTime == 0 {
|
||||
continue
|
||||
}
|
||||
neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
|
||||
|
||||
// 网元在线状态
|
||||
isOnline := parse.Boolean(neInfo.ServerState["online"])
|
||||
// 告警ID
|
||||
params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_STATE_CHECK, neInfo.CreateTime)
|
||||
// 检查网元告警ID是否唯一
|
||||
alarmIdArr := s.alarmService.Find(neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
AlarmId: params.AlarmId,
|
||||
})
|
||||
// 告警状态
|
||||
alarmStatus := ""
|
||||
if len(alarmIdArr) > 0 {
|
||||
alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus)
|
||||
}
|
||||
// 在线且状态为活动告警
|
||||
if isOnline && alarmStatus == "1" {
|
||||
// 进行清除
|
||||
clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0])
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, clearAlarm)
|
||||
result[neTypeAndId] = "alarm clear"
|
||||
}
|
||||
|
||||
// 不在线
|
||||
if !isOnline && alarmStatus == "" {
|
||||
// 进行新增
|
||||
newAlarm, err := s.alarmNew(neInfo, params)
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, newAlarm)
|
||||
result[neTypeAndId] = "alarm new"
|
||||
// 告警状态
|
||||
alarmStatus := oam.ALARM_STATUS_ACTIVE
|
||||
if isOnline {
|
||||
alarmStatus = oam.ALARM_STATUS_CLEAR
|
||||
}
|
||||
// 创建告警
|
||||
alarm := oam.Alarm{
|
||||
NeUid: neInfo.RmUID, // 网元唯一标识
|
||||
AlarmTime: time.Now().UnixMilli(), // 事件产生时间
|
||||
AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应
|
||||
AlarmCode: constants.ALARM_STATE_CHECK, // 告警状态码
|
||||
AlarmType: params.AlarmType, // 告警类型
|
||||
AlarmTitle: params.AlarmTitle, // 告警标题
|
||||
PerceivedSeverity: params.OrigSeverity, // 告警级别
|
||||
AlarmStatus: alarmStatus, // 告警状态
|
||||
SpecificProblem: params.SpecificProblem, // 告警问题原因
|
||||
SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID
|
||||
AddInfo: params.AddInfo, // 告警辅助信息
|
||||
LocationInfo: "NE State: Heartbeat", // 告警定位信息
|
||||
}
|
||||
if err = oamService.NewAlarm.Resolve(alarm); err == nil {
|
||||
result[neInfo.RmUID] = "state alarm"
|
||||
}
|
||||
}
|
||||
|
||||
// 返回结果,用于记录执行结果
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// alarmClear 清除告警
|
||||
func (s NeAlarmStateCheckProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) {
|
||||
// 变更告警ID为告警清除ID
|
||||
v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime)
|
||||
v.AlarmStatus = "0"
|
||||
// 告警清除
|
||||
v.ClearType = 1
|
||||
v.ClearTime = neInfo.UpdateTime
|
||||
v.ClearUser = "system"
|
||||
rows := s.alarmService.Update(v)
|
||||
if rows > 0 {
|
||||
return v, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail")
|
||||
}
|
||||
|
||||
// alarmNew 新增告警
|
||||
func (s NeAlarmStateCheckProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) {
|
||||
// seq 告警序号
|
||||
lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId)
|
||||
lastTime := neInfo.UpdateTime // 网元最后更新时间
|
||||
if lastTime < neInfo.CreateTime {
|
||||
lastTime = time.Now().UnixMilli()
|
||||
}
|
||||
alarm := neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
NeName: neInfo.NeName,
|
||||
Province: neInfo.Province,
|
||||
PvFlag: neInfo.PvFlag,
|
||||
AlarmSeq: lastSeq + 1,
|
||||
AlarmId: v.AlarmId,
|
||||
AlarmTitle: v.AlarmTitle,
|
||||
AlarmCode: constants.ALARM_STATE_CHECK,
|
||||
EventTime: lastTime,
|
||||
AlarmType: v.AlarmType,
|
||||
OrigSeverity: v.OrigSeverity,
|
||||
PerceivedSeverity: v.OrigSeverity,
|
||||
ObjectUid: neInfo.RmUID,
|
||||
ObjectName: "NE State",
|
||||
ObjectType: "state",
|
||||
LocationInfo: "NE State: Heartbeat",
|
||||
AlarmStatus: "1", // 活动告警
|
||||
SpecificProblem: v.SpecificProblem,
|
||||
SpecificProblemId: v.SpecificProblemID,
|
||||
AddInfo: v.AddInfo,
|
||||
}
|
||||
insertId := s.alarmService.InsertAndForword(alarm)
|
||||
if insertId > 0 {
|
||||
alarm.ID = insertId
|
||||
return alarm, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("new alarm fail")
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tsmask/go-oam"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/cron"
|
||||
"be.ems/src/framework/logger"
|
||||
@@ -18,6 +20,7 @@ import (
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neModel "be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
oamService "be.ems/src/modules/oam/service"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
)
|
||||
|
||||
@@ -28,22 +31,18 @@ var (
|
||||
)
|
||||
|
||||
var NewProcessor = &NeAlarmStateCheckCMDProcessor{
|
||||
neConfigBackupService: neService.NewNeConfigBackup,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
neStateService: neDataService.NewNEState,
|
||||
alarmService: neDataService.NewAlarm,
|
||||
wsSendService: wsService.NewWSSend,
|
||||
count: 0,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
neStateService: neDataService.NewNEState,
|
||||
wsSendService: wsService.NewWSSend,
|
||||
count: 0,
|
||||
}
|
||||
|
||||
// NeAlarmStateCheckCMDProcessor 网元告警内存/CPU/磁盘检查
|
||||
type NeAlarmStateCheckCMDProcessor struct {
|
||||
neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
neStateService *neDataService.NEState // 网元状态信息服务
|
||||
alarmService *neDataService.Alarm // 告警信息服务
|
||||
wsSendService *wsService.WSSend // ws发送服务
|
||||
count int // 执行次数
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
neStateService *neDataService.NEState // 网元状态信息服务
|
||||
wsSendService *wsService.WSSend // ws发送服务
|
||||
count int // 执行次数
|
||||
}
|
||||
|
||||
// alarmParams 告警参数
|
||||
@@ -103,65 +102,84 @@ func (s *NeAlarmStateCheckCMDProcessor) Execute(data any) (any, error) {
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
err := s.serverState(neInfo.ServerState, params.CPUUseGt, params.MemUseGt, params.DiskUseGt)
|
||||
sysCpuUsage, sysMemUsage, sysDiskUsage := s.serverState(neInfo.ServerState)
|
||||
// 检查CPU/Menory/Disk使用率
|
||||
warnMsg := []string{}
|
||||
if int64(sysCpuUsage) >= params.CPUUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("cpu usage %.2f%%", sysCpuUsage))
|
||||
}
|
||||
if int64(sysMemUsage) >= params.MemUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("memory usage %.2f%%", sysMemUsage))
|
||||
}
|
||||
if int64(sysDiskUsage) >= params.DiskUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("disk usage %.2f%%", sysDiskUsage))
|
||||
}
|
||||
var err error
|
||||
if len(warnMsg) > 0 {
|
||||
currentTime := time.Now()
|
||||
validTimes := []time.Time{}
|
||||
if v, ok := triggerCount.Load(neInfo.RmUID); ok {
|
||||
times := v.([]time.Time)
|
||||
// 清理过期的记录:10秒前的触发记录不再计入
|
||||
for _, t := range times {
|
||||
if currentTime.Sub(t) <= triggerWindow {
|
||||
validTimes = append(validTimes, t)
|
||||
}
|
||||
}
|
||||
validTimes = append(validTimes, currentTime)
|
||||
triggerCount.Store(neInfo.RmUID, validTimes)
|
||||
} else {
|
||||
// 事件第一次触发,初始化记录
|
||||
validTimes = append(validTimes, currentTime)
|
||||
triggerCount.Store(neInfo.RmUID, validTimes)
|
||||
}
|
||||
if int64(len(validTimes)) >= triggerMax {
|
||||
err = fmt.Errorf("greater than %s", strings.Join(warnMsg, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
// 检查状态连续触发
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
addInfo := params.AddInfo
|
||||
if addInfo != "" {
|
||||
addInfo = addInfo + ", " + err.Error()
|
||||
} else {
|
||||
addInfo = err.Error()
|
||||
}
|
||||
|
||||
neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
|
||||
// 事件产生时间
|
||||
alarmTime := time.Now().UnixMilli()
|
||||
// 告警ID
|
||||
params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_CMD_CHECK, neInfo.CreateTime)
|
||||
// 检查网元告警ID是否唯一
|
||||
alarmIdArr := s.alarmService.Find(neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
AlarmId: params.AlarmId,
|
||||
})
|
||||
// 告警状态, 存在的需要手动清除
|
||||
alarmStatus := ""
|
||||
if len(alarmIdArr) > 0 {
|
||||
alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus)
|
||||
params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_CMD_CHECK, alarmTime)
|
||||
// 创建告警
|
||||
alarm := oam.Alarm{
|
||||
NeUid: neInfo.RmUID, // 网元唯一标识
|
||||
AlarmTime: alarmTime, // 事件产生时间
|
||||
AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应
|
||||
AlarmCode: constants.ALARM_CMD_CHECK, // 告警状态码
|
||||
AlarmType: params.AlarmType, // 告警类型
|
||||
AlarmTitle: params.AlarmTitle, // 告警标题
|
||||
PerceivedSeverity: params.OrigSeverity, // 告警级别
|
||||
AlarmStatus: oam.ALARM_STATUS_ACTIVE, // 告警状态
|
||||
SpecificProblem: params.SpecificProblem, // 告警问题原因
|
||||
SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID
|
||||
AddInfo: addInfo, // 告警辅助信息
|
||||
LocationInfo: "NE CPU/Menory/Disk: Heartbeat", // 告警定位信息
|
||||
}
|
||||
// 活动告警进行清除
|
||||
if alarmStatus == "1" {
|
||||
clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0])
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, clearAlarm)
|
||||
result[neTypeAndId] = "alarm clear"
|
||||
alarmStatus = "" // 标记为未记录再次发起新告警
|
||||
}
|
||||
// 未记录
|
||||
if alarmStatus == "" {
|
||||
addInfo := params.AddInfo
|
||||
if params.AddInfo != "" {
|
||||
params.AddInfo = params.AddInfo + ", " + err.Error()
|
||||
} else {
|
||||
params.AddInfo = err.Error()
|
||||
}
|
||||
// 进行新增
|
||||
newAlarm, err := s.alarmNew(neInfo, params)
|
||||
params.AddInfo = addInfo // 恢复附加信息
|
||||
triggerCount.Clear() // 重置连续触发次数
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, newAlarm)
|
||||
result[neTypeAndId] = "alarm new"
|
||||
if err = oamService.NewAlarm.Resolve(alarm); err == nil {
|
||||
result[neInfo.RmUID] = "cmd alarm"
|
||||
}
|
||||
triggerCount.Delete(neInfo.RmUID)
|
||||
}
|
||||
|
||||
// 返回结果,用于记录执行结果
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// serverState 网元状态
|
||||
func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any, cpuUseGt, memUseGt, diskUseGt int64) error {
|
||||
// serverState 网元状态记录
|
||||
func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any) (float64, float64, float64) {
|
||||
// 网元CPU使用率
|
||||
var nfCpuUsage float64 = 0
|
||||
// CPU使用率
|
||||
@@ -224,94 +242,5 @@ func (s NeAlarmStateCheckCMDProcessor) serverState(state map[string]any, cpuUseG
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_NE_STATE, neState.NeType, neState.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, neState)
|
||||
|
||||
// 检查CPU/Menory/Disk使用率
|
||||
warnMsg := []string{}
|
||||
if int64(sysCpuUsage) >= cpuUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("cpu usage %.2f%%", sysCpuUsage))
|
||||
}
|
||||
if int64(sysMemUsage) >= memUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("memory usage %.2f%%", sysMemUsage))
|
||||
}
|
||||
if int64(sysDiskUsage) >= diskUseGt {
|
||||
warnMsg = append(warnMsg, fmt.Sprintf("disk usage %.2f%%", sysDiskUsage))
|
||||
}
|
||||
if len(warnMsg) > 0 {
|
||||
currentTime := time.Now()
|
||||
neTypeAndId := fmt.Sprintf("%s_%s", neState.NeType, neState.NeId)
|
||||
validTimes := []time.Time{}
|
||||
if v, ok := triggerCount.Load(neTypeAndId); ok {
|
||||
times := v.([]time.Time)
|
||||
// 清理过期的记录:10秒前的触发记录不再计入
|
||||
for _, t := range times {
|
||||
if currentTime.Sub(t) <= triggerWindow {
|
||||
validTimes = append(validTimes, t)
|
||||
}
|
||||
}
|
||||
validTimes = append(validTimes, currentTime)
|
||||
triggerCount.Store(neTypeAndId, validTimes)
|
||||
} else {
|
||||
// 事件第一次触发,初始化记录
|
||||
validTimes = append(validTimes, currentTime)
|
||||
triggerCount.Store(neTypeAndId, validTimes)
|
||||
}
|
||||
if int64(len(validTimes)) >= triggerMax {
|
||||
return fmt.Errorf("greater than %s", strings.Join(warnMsg, ", "))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// alarmClear 清除告警
|
||||
func (s NeAlarmStateCheckCMDProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) {
|
||||
// 变更告警ID为告警清除ID
|
||||
v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime)
|
||||
v.AlarmStatus = "0"
|
||||
// 告警清除
|
||||
v.ClearType = 1
|
||||
v.ClearTime = neInfo.UpdateTime
|
||||
v.ClearUser = "system"
|
||||
rows := s.alarmService.Update(v)
|
||||
if rows > 0 {
|
||||
return v, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail")
|
||||
}
|
||||
|
||||
// alarmNew 新增告警
|
||||
func (s NeAlarmStateCheckCMDProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) {
|
||||
// seq 告警序号
|
||||
lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId)
|
||||
lastTime := neInfo.UpdateTime // 网元最后更新时间
|
||||
if lastTime < neInfo.CreateTime {
|
||||
lastTime = time.Now().UnixMilli()
|
||||
}
|
||||
alarm := neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
NeName: neInfo.NeName,
|
||||
Province: neInfo.Province,
|
||||
PvFlag: neInfo.PvFlag,
|
||||
AlarmSeq: lastSeq + 1,
|
||||
AlarmId: v.AlarmId,
|
||||
AlarmTitle: v.AlarmTitle,
|
||||
AlarmCode: constants.ALARM_CMD_CHECK,
|
||||
EventTime: lastTime,
|
||||
AlarmType: v.AlarmType,
|
||||
OrigSeverity: v.OrigSeverity,
|
||||
PerceivedSeverity: v.OrigSeverity,
|
||||
ObjectUid: neInfo.RmUID,
|
||||
ObjectName: "NE CPU/Menory/Disk",
|
||||
ObjectType: "cmd",
|
||||
LocationInfo: "NE CPU/Menory/Disk: Heartbeat",
|
||||
AlarmStatus: "1", // 活动告警
|
||||
SpecificProblem: v.SpecificProblem,
|
||||
SpecificProblemId: v.SpecificProblemID,
|
||||
AddInfo: v.AddInfo,
|
||||
}
|
||||
insertId := s.alarmService.InsertAndForword(alarm)
|
||||
if insertId > 0 {
|
||||
alarm.ID = insertId
|
||||
return alarm, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("new alarm fail")
|
||||
return sysCpuUsage, sysMemUsage, sysDiskUsage
|
||||
}
|
||||
|
||||
@@ -10,29 +10,22 @@ import (
|
||||
"be.ems/src/framework/cron"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"github.com/tsmask/go-oam"
|
||||
|
||||
neDataModel "be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neModel "be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
oamService "be.ems/src/modules/oam/service"
|
||||
)
|
||||
|
||||
var NewProcessor = &NeAlarmStateCheckLicenseProcessor{
|
||||
neConfigBackupService: neService.NewNeConfigBackup,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
alarmService: neDataService.NewAlarm,
|
||||
wsSendService: wsService.NewWSSend,
|
||||
count: 0,
|
||||
neInfoService: neService.NewNeInfo,
|
||||
count: 0,
|
||||
}
|
||||
|
||||
// NeAlarmStateCheckLicenseProcessor 网元告警License到期检查
|
||||
type NeAlarmStateCheckLicenseProcessor struct {
|
||||
neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
alarmService *neDataService.Alarm // 告警信息服务
|
||||
wsSendService *wsService.WSSend // ws发送服务
|
||||
count int // 执行次数
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
count int // 执行次数
|
||||
}
|
||||
|
||||
// alarmParams 告警参数
|
||||
@@ -83,60 +76,36 @@ func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) {
|
||||
}
|
||||
|
||||
// 检查状态
|
||||
err := s.serverState(neInfo.ServerState, params.DayLt)
|
||||
err := s.cheackState(neInfo.ServerState, params.DayLt)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
if params.AddInfo != "" {
|
||||
params.AddInfo = params.AddInfo + ", " + err.Error()
|
||||
addInfo := params.AddInfo
|
||||
if addInfo != "" {
|
||||
addInfo = addInfo + ", " + err.Error()
|
||||
} else {
|
||||
params.AddInfo = err.Error()
|
||||
addInfo = err.Error()
|
||||
}
|
||||
|
||||
neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
|
||||
// 告警ID
|
||||
params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_LICENSE_CHECK, neInfo.CreateTime)
|
||||
// 检查网元告警ID是否唯一
|
||||
alarmIdArr := s.alarmService.Find(neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
AlarmId: params.AlarmId,
|
||||
})
|
||||
// 告警状态, 存在的需要手动清除
|
||||
alarmStatus := ""
|
||||
if len(alarmIdArr) > 0 {
|
||||
alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus)
|
||||
// 创建告警
|
||||
alarm := oam.Alarm{
|
||||
NeUid: neInfo.RmUID, // 网元唯一标识
|
||||
AlarmTime: time.Now().UnixMilli(), // 事件产生时间
|
||||
AlarmId: params.AlarmId, // 告警ID 唯一,清除时对应
|
||||
AlarmCode: constants.ALARM_LICENSE_CHECK, // 告警状态码
|
||||
AlarmType: params.AlarmType, // 告警类型
|
||||
AlarmTitle: params.AlarmTitle, // 告警标题
|
||||
PerceivedSeverity: params.OrigSeverity, // 告警级别
|
||||
AlarmStatus: oam.ALARM_STATUS_ACTIVE, // 告警状态
|
||||
SpecificProblem: params.SpecificProblem, // 告警问题原因
|
||||
SpecificProblemID: params.SpecificProblemID, // 告警问题原因ID
|
||||
AddInfo: addInfo, // 告警辅助信息
|
||||
LocationInfo: "NE License: Heartbeat", // 告警定位信息
|
||||
}
|
||||
// 活动告警进行清除
|
||||
if alarmStatus == "1" {
|
||||
clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0])
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, clearAlarm)
|
||||
result[neTypeAndId] = "alarm clear"
|
||||
alarmStatus = "" // 标记为未记录再次发起新告警
|
||||
}
|
||||
// 未记录
|
||||
if alarmStatus == "" {
|
||||
addInfo := params.AddInfo
|
||||
if params.AddInfo != "" {
|
||||
params.AddInfo = params.AddInfo + ", " + err.Error()
|
||||
} else {
|
||||
params.AddInfo = err.Error()
|
||||
}
|
||||
// 进行新增
|
||||
newAlarm, err := s.alarmNew(neInfo, params)
|
||||
params.AddInfo = addInfo // 恢复附加信息
|
||||
if err != nil {
|
||||
result[neTypeAndId] = err.Error()
|
||||
continue
|
||||
}
|
||||
groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
|
||||
s.wsSendService.ByGroupID(groupID, newAlarm)
|
||||
result[neTypeAndId] = "alarm new"
|
||||
if err = oamService.NewAlarm.Resolve(alarm); err == nil {
|
||||
result[neInfo.RmUID] = "license alarm"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +113,8 @@ func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// serverState 网元状态
|
||||
func (s NeAlarmStateCheckLicenseProcessor) serverState(state map[string]any, dayLt int64) error {
|
||||
// cheackState 检查网元状态
|
||||
func (s NeAlarmStateCheckLicenseProcessor) cheackState(state map[string]any, dayLt int64) error {
|
||||
expire := fmt.Sprint(state["expire"])
|
||||
if expire == "" || expire == "<nil>" || expire == "-" || expire == "2099-12-31" {
|
||||
return nil
|
||||
@@ -168,58 +137,3 @@ func (s NeAlarmStateCheckLicenseProcessor) serverState(state map[string]any, day
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// alarmClear 清除告警
|
||||
func (s NeAlarmStateCheckLicenseProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) {
|
||||
// 变更告警ID为告警清除ID
|
||||
v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime)
|
||||
v.AlarmStatus = "0"
|
||||
// 告警清除
|
||||
v.ClearType = 1
|
||||
v.ClearTime = neInfo.UpdateTime
|
||||
v.ClearUser = "system"
|
||||
rows := s.alarmService.Update(v)
|
||||
if rows > 0 {
|
||||
return v, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail")
|
||||
}
|
||||
|
||||
// alarmNew 新增告警
|
||||
func (s NeAlarmStateCheckLicenseProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) {
|
||||
// seq 告警序号
|
||||
lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.NeId)
|
||||
lastTime := neInfo.UpdateTime // 网元最后更新时间
|
||||
if lastTime < neInfo.CreateTime {
|
||||
lastTime = time.Now().UnixMilli()
|
||||
}
|
||||
alarm := neDataModel.Alarm{
|
||||
NeType: neInfo.NeType,
|
||||
NeId: neInfo.NeId,
|
||||
NeName: neInfo.NeName,
|
||||
Province: neInfo.Province,
|
||||
PvFlag: neInfo.PvFlag,
|
||||
AlarmSeq: lastSeq + 1,
|
||||
AlarmId: v.AlarmId,
|
||||
AlarmTitle: v.AlarmTitle,
|
||||
AlarmCode: constants.ALARM_LICENSE_CHECK,
|
||||
EventTime: lastTime,
|
||||
AlarmType: v.AlarmType,
|
||||
OrigSeverity: v.OrigSeverity,
|
||||
PerceivedSeverity: v.OrigSeverity,
|
||||
ObjectUid: neInfo.RmUID,
|
||||
ObjectName: "NE License",
|
||||
ObjectType: "license",
|
||||
LocationInfo: "NE License: Heartbeat",
|
||||
AlarmStatus: "1", // 活动告警
|
||||
SpecificProblem: v.SpecificProblem,
|
||||
SpecificProblemId: v.SpecificProblemID,
|
||||
AddInfo: v.AddInfo,
|
||||
}
|
||||
insertId := s.alarmService.InsertAndForword(alarm)
|
||||
if insertId > 0 {
|
||||
alarm.ID = insertId
|
||||
return alarm, nil
|
||||
}
|
||||
return neDataModel.Alarm{}, fmt.Errorf("new alarm fail")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
s := MonitorInfo{}
|
||||
s.load(0.5) // 0.5 半分钟
|
||||
s.Load(5 * time.Second) // 0.5 半分钟
|
||||
|
||||
fmt.Println(s)
|
||||
select {}
|
||||
@@ -28,34 +29,22 @@ type MonitorInfo struct {
|
||||
}
|
||||
|
||||
// load 执行资源获取
|
||||
func (m *MonitorInfo) load(interval float64) {
|
||||
var itemBase MonitorBase
|
||||
itemBase.CreateTime = time.Now().UnixMilli()
|
||||
|
||||
loadInfo, _ := load.Avg()
|
||||
itemBase.CPULoad1 = loadInfo.Load1
|
||||
itemBase.CPULoad5 = loadInfo.Load5
|
||||
itemBase.CPULoad15 = loadInfo.Load15
|
||||
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
||||
if len(totalPercent) > 0 {
|
||||
itemBase.CPU = totalPercent[0]
|
||||
}
|
||||
cpuCount, _ := cpu.Counts(false)
|
||||
cpuAvg := (float64(cpuCount*2) * 0.75) * 100
|
||||
itemBase.LoadUsage = 0
|
||||
if cpuAvg > 0 {
|
||||
itemBase.LoadUsage = loadInfo.Load1 / cpuAvg
|
||||
}
|
||||
|
||||
memoryInfo, _ := mem.VirtualMemory()
|
||||
itemBase.Memory = memoryInfo.UsedPercent
|
||||
|
||||
m.MonitorBase = itemBase
|
||||
|
||||
// 求平均
|
||||
m.MonitorIO = loadDiskIO(interval)
|
||||
m.MonitorNetwork = loadNetIO(interval)
|
||||
func (m *MonitorInfo) Load(duration time.Duration) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
m.MonitorBase = loadCPUMem(duration)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
m.MonitorIO = loadDiskIO(duration)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
m.MonitorNetwork = loadNetIO(duration)
|
||||
}()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// MonitorBase 监控_基本信息 monitor_base
|
||||
@@ -73,25 +62,49 @@ type MonitorBase struct {
|
||||
type MonitorIO struct {
|
||||
CreateTime int64 `json:"createTime"` // 创建时间
|
||||
Name string `json:"name"` // 磁盘名
|
||||
Read int64 `json:"read"` // 读取K
|
||||
Write int64 `json:"write"` // 写入K
|
||||
Count int64 `json:"count"` // 次数
|
||||
Time int64 `json:"time"` // 耗时
|
||||
Read uint64 `json:"read"` // 读取 Bytes
|
||||
Write uint64 `json:"write"` // 写入 Bytes
|
||||
Count uint64 `json:"count"` // 次数
|
||||
Time uint64 `json:"time"` // 耗时
|
||||
}
|
||||
|
||||
// MonitorNetwork 监控_网络IO monitor_network
|
||||
type MonitorNetwork struct {
|
||||
CreateTime int64 `json:"createTime"` // 创建时间
|
||||
Name string `json:"name"` // 网卡名
|
||||
Up float64 `json:"up"` // 上行
|
||||
Down float64 `json:"down"` // 下行
|
||||
CreateTime int64 `json:"createTime"` // 创建时间
|
||||
Name string `json:"name"` // 网卡名
|
||||
Up uint64 `json:"up"` // 上行 bytes
|
||||
Down uint64 `json:"down"` // 下行 bytes
|
||||
}
|
||||
|
||||
// loadCPUMem CPU内存使用率,interval表示采集的平均值(分钟)
|
||||
func loadCPUMem(duration time.Duration) MonitorBase {
|
||||
var itemBase MonitorBase
|
||||
itemBase.CreateTime = time.Now().UnixMilli()
|
||||
|
||||
loadInfo, _ := load.Avg()
|
||||
itemBase.CPULoad1 = loadInfo.Load1
|
||||
itemBase.CPULoad5 = loadInfo.Load5
|
||||
itemBase.CPULoad15 = loadInfo.Load15
|
||||
totalPercent, _ := cpu.Percent(duration, false)
|
||||
if len(totalPercent) > 0 {
|
||||
itemBase.CPU = totalPercent[0]
|
||||
}
|
||||
if cpuCount, _ := cpu.Counts(false); cpuCount > 0 {
|
||||
itemBase.LoadUsage = loadInfo.Load1 / float64(cpuCount)
|
||||
} else {
|
||||
itemBase.LoadUsage = 0
|
||||
}
|
||||
|
||||
memoryInfo, _ := mem.VirtualMemory()
|
||||
itemBase.Memory = memoryInfo.UsedPercent
|
||||
return itemBase
|
||||
}
|
||||
|
||||
// loadDiskIO 磁盘读写,interval表示采集的平均值(分钟)
|
||||
func loadDiskIO(interval float64) []MonitorIO {
|
||||
func loadDiskIO(duration time.Duration) []MonitorIO {
|
||||
ioStat, _ := disk.IOCounters()
|
||||
|
||||
time.Sleep(time.Duration(interval) * time.Minute)
|
||||
time.Sleep(duration)
|
||||
|
||||
ioStat2, _ := disk.IOCounters()
|
||||
var ioList []MonitorIO
|
||||
@@ -104,32 +117,24 @@ func loadDiskIO(interval float64) []MonitorIO {
|
||||
itemIO.Name = io1.Name
|
||||
|
||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
||||
itemIO.Read = int64(float64(io2.ReadBytes-io1.ReadBytes) / interval / 60)
|
||||
itemIO.Read = io2.ReadBytes - io1.ReadBytes
|
||||
}
|
||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||
itemIO.Write = int64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
|
||||
itemIO.Write = io2.WriteBytes - io1.WriteBytes
|
||||
}
|
||||
|
||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||
itemIO.Count = int64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
|
||||
itemIO.Count = io2.ReadCount - io1.ReadCount
|
||||
}
|
||||
writeCount := int64(0)
|
||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
||||
writeCount = int64(float64(io2.WriteCount-io1.WriteCount) / interval * 60)
|
||||
}
|
||||
if writeCount > itemIO.Count {
|
||||
itemIO.Count = writeCount
|
||||
itemIO.Count += io2.WriteCount - io1.WriteCount
|
||||
}
|
||||
|
||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||
itemIO.Time = int64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
|
||||
itemIO.Time = io2.ReadTime - io1.ReadTime
|
||||
}
|
||||
writeTime := int64(0)
|
||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
||||
writeTime = int64(float64(io2.WriteTime-io1.WriteTime) / interval / 60)
|
||||
}
|
||||
if writeTime > itemIO.Time {
|
||||
itemIO.Time = writeTime
|
||||
itemIO.Time += io2.WriteTime - io1.WriteTime
|
||||
}
|
||||
ioList = append(ioList, itemIO)
|
||||
break
|
||||
@@ -140,7 +145,7 @@ func loadDiskIO(interval float64) []MonitorIO {
|
||||
}
|
||||
|
||||
// loadNetIO 网络接口(包括虚拟接口),interval表示采集的平均值(分钟)
|
||||
func loadNetIO(interval float64) []MonitorNetwork {
|
||||
func loadNetIO(duration time.Duration) []MonitorNetwork {
|
||||
// 获取当前时刻
|
||||
netStat, _ := net.IOCounters(true)
|
||||
netStatAll, _ := net.IOCounters(false)
|
||||
@@ -148,7 +153,7 @@ func loadNetIO(interval float64) []MonitorNetwork {
|
||||
netStatList = append(netStatList, netStat...)
|
||||
netStatList = append(netStatList, netStatAll...)
|
||||
|
||||
time.Sleep(time.Duration(interval) * time.Minute)
|
||||
time.Sleep(duration)
|
||||
|
||||
// 获取结束时刻
|
||||
netStat2, _ := net.IOCounters(true)
|
||||
@@ -168,10 +173,10 @@ func loadNetIO(interval float64) []MonitorNetwork {
|
||||
|
||||
// 如果结束时刻发送字节数和当前时刻发送字节数都不为零,并且结束时刻发送字节数大于当前时刻发送字节数
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
|
||||
itemNet.Up = net2.BytesSent - net1.BytesSent
|
||||
}
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
|
||||
itemNet.Down = net2.BytesRecv - net1.BytesRecv
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
|
||||
@@ -199,9 +199,10 @@ func (s SysJob) ExportData(rows []model.SysJob, fileName string) (string, error)
|
||||
}
|
||||
}
|
||||
misfirePolicy := "放弃执行"
|
||||
if row.MisfirePolicy == "1" {
|
||||
switch row.MisfirePolicy {
|
||||
case "1":
|
||||
misfirePolicy = "立即执行"
|
||||
} else if row.MisfirePolicy == "2" {
|
||||
case "2":
|
||||
misfirePolicy = "执行一次"
|
||||
}
|
||||
concurrent := "禁止"
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/constants"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
@@ -42,7 +43,7 @@ type AlarmController struct {
|
||||
// @Param pvFlag query string false "PV Flag" Enums(PNF,VNF)
|
||||
// @Param alarmCode query string false "alarm status code"
|
||||
// @Param alarmType query string false "Alarm type Communication alarms=1, Equipment alarms=2, Processing faults=3, Environmental alarms=4, Quality of service alarms=5" Enums(1,2,3,4,5)
|
||||
// @Param alarmStatus query string false "Alarm status 0:clear, 1:active" Enums(0,1)
|
||||
// @Param alarmStatus query string false "Alarm status Clear Active" Enums(0,1)
|
||||
// @Param origSeverity query string false "Alarm Type 1: Critical, 2: Major, 3: Minor, 4: Warning" Enums(1,2,3,4)
|
||||
// @Param sortField query string false "Sort fields, fill in result fields" default(event_time)
|
||||
// @Param sortOrder query string false "Sort by ascending or descending order, asc desc" default(asc)
|
||||
@@ -107,7 +108,7 @@ func (s AlarmController) Clear(c *gin.Context) {
|
||||
}
|
||||
|
||||
clearUser := reqctx.LoginUserToUserName(c)
|
||||
rows, err := s.alarmService.AlarmClearByIds(body.Ids, clearUser)
|
||||
rows, err := s.alarmService.ClearByIds(body.Ids, clearUser, constants.ALARM_CLEAR_TYPE_MANUAL_CLEAR)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -130,7 +131,7 @@ func (s AlarmController) Ack(c *gin.Context) {
|
||||
}
|
||||
|
||||
ackUser := reqctx.LoginUserToUserName(c)
|
||||
rows, err := s.alarmService.AlarmAckByIds(body.Ids, ackUser, body.AckState)
|
||||
rows, err := s.alarmService.AckByIds(body.Ids, ackUser, constants.ALARM_ACK_STATE_ACK)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -138,6 +139,58 @@ func (s AlarmController) Ack(c *gin.Context) {
|
||||
c.JSON(200, resp.OkData(rows))
|
||||
}
|
||||
|
||||
// 告警级别数量
|
||||
//
|
||||
// GET /count/severity
|
||||
func (s AlarmController) CountSeverity(c *gin.Context) {
|
||||
var query struct {
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"required,oneof=Clear Active"` // 告警状态
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.alarmService.CountSeverity(query.AlarmStatus)
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// 告警类别数量
|
||||
//
|
||||
// GET /count/type
|
||||
func (s AlarmController) CountType(c *gin.Context) {
|
||||
var query struct {
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"required,oneof=Clear Active"` // 告警状态
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.alarmService.CountType(query.AlarmStatus)
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// 告警状态前几排名
|
||||
//
|
||||
// GET /count/ne
|
||||
func (s AlarmController) CountNe(c *gin.Context) {
|
||||
var query struct {
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"required,oneof=Clear Active"` // 告警状态
|
||||
Top int `json:"top" form:"top" binding:"required"` // 前几
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.alarmService.CountNe(query.AlarmStatus, query.Top)
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// 告警列表导出
|
||||
//
|
||||
// GET /export
|
||||
|
||||
183
src/modules/network_data/controller/all_kpi_c.go
Normal file
183
src/modules/network_data/controller/all_kpi_c.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 实例化控制层 KPICController 结构体
|
||||
var NewKPIC = &KPICController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
kpicReportService: neDataService.NewKpiCReport,
|
||||
}
|
||||
|
||||
// 性能统计
|
||||
//
|
||||
// PATH /kpic
|
||||
type KPICController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
kpicReportService *neDataService.KpiCReport // 指标统计服务
|
||||
}
|
||||
|
||||
// 获取统计数据
|
||||
//
|
||||
// GET /data
|
||||
//
|
||||
// @Tags network_data/kpi
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC) default(AMF)
|
||||
// @Param neId query string true "NE ID" default(001)
|
||||
// @Param beginTime query number true "begin time (timestamped milliseconds)" default(1729162507596)
|
||||
// @Param endTime query number true "end time (timestamped milliseconds)" default(1729164187611)
|
||||
// @Param interval query number true "interval" Enums(5,10,15,30,60,300,600,900,1800,3600) default(60)
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Access to statistical data
|
||||
// @Description Access to statistical data
|
||||
// @Router /neData/kpic/data [get]
|
||||
func (s KPICController) KPIData(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.KPICQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
kpiData := s.kpicReportService.FindData(querys)
|
||||
c.JSON(200, resp.OkData(kpiData))
|
||||
}
|
||||
|
||||
// 自定义标题列表
|
||||
//
|
||||
// GET /titlelist
|
||||
func (s KPICController) ListTitle(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
if v, ok := query["status"]; ok && v == "" {
|
||||
query["status"] = "1"
|
||||
}
|
||||
rows, total := s.kpicReportService.TitleFindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
|
||||
}
|
||||
|
||||
// 自定义标题新增
|
||||
//
|
||||
// POST /title
|
||||
func (s KPICController) AddTitle(c *gin.Context) {
|
||||
var body model.KpiCTitle
|
||||
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 校验指标是否存在
|
||||
kpicTitles := s.kpicReportService.TitleFind(model.KpiCTitle{
|
||||
NeType: body.NeType,
|
||||
KpiId: body.KpiId,
|
||||
})
|
||||
if len(kpicTitles) > 0 {
|
||||
for _, v := range kpicTitles {
|
||||
if v.Status == "2" {
|
||||
c.JSON(200, resp.ErrMsg("custom indicator already exist"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 生成自定义指标ID
|
||||
if body.KpiId == "" {
|
||||
body.KpiId = fmt.Sprintf("%s.C.01", strings.ToUpper(body.NeType))
|
||||
} else {
|
||||
// 网元类型最后指标ID
|
||||
lastKpiId := s.kpicReportService.TitleLastKPIId(body.NeType)
|
||||
if lastKpiId != "" {
|
||||
// title like AMF.C.01 截断 .C. 并获取后面的数字部分
|
||||
parts := strings.Split(lastKpiId, ".C.")
|
||||
if len(parts) == 2 {
|
||||
numStr := parts[1]
|
||||
if num, err := strconv.Atoi(numStr); err == nil {
|
||||
num++ // 数字加 1
|
||||
// 转换为前面补零的 2 位字符串
|
||||
body.KpiId = fmt.Sprintf("%s.C.%02d", strings.ToUpper(body.NeType), num)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.CreatedBy = reqctx.LoginUserToUserName(c)
|
||||
insertId := s.kpicReportService.TitleInsert(body)
|
||||
if insertId > 0 {
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Err(nil))
|
||||
}
|
||||
|
||||
// 自定义标题修改
|
||||
//
|
||||
// PUT /title
|
||||
func (s KPICController) EditTitle(c *gin.Context) {
|
||||
var body model.KpiCTitle
|
||||
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
rows := s.kpicReportService.TitleUpdate(body)
|
||||
if rows > 0 {
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Err(nil))
|
||||
}
|
||||
|
||||
// 自定义标题删除
|
||||
//
|
||||
// DELETE /title/:id
|
||||
func (s KPICController) RemoveTitle(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
id := c.Query("id")
|
||||
if id == "" {
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理字符转id数组后去重
|
||||
uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
|
||||
// 转换成int64数组类型
|
||||
ids := make([]int64, 0)
|
||||
for _, v := range uniqueIDs {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.kpicReportService.TitleDeleteByIds(ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, resp.OkMsg(msg))
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (s NBStateController) List(c *gin.Context) {
|
||||
|
||||
// 历史记录列表导出
|
||||
//
|
||||
// POST /export
|
||||
// GET /export
|
||||
//
|
||||
// @Tags network_data/amf,network_data/mme
|
||||
// @Accept json
|
||||
@@ -82,7 +82,7 @@ func (s NBStateController) List(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary Base Station Status List Export
|
||||
// @Description Base Station Status List Export
|
||||
// @Router /nb-state/export [post]
|
||||
// @Router /nb-state/export [get]
|
||||
func (s NBStateController) Export(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
@@ -19,15 +18,15 @@ import (
|
||||
// 实例化控制层 AMFController 结构体
|
||||
var NewAMF = &AMFController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
ueEventService: neDataService.NewUEEventAMF,
|
||||
ueEventService: neDataService.NewUEEvent,
|
||||
}
|
||||
|
||||
// 网元AMF
|
||||
//
|
||||
// PATH /amf
|
||||
type AMFController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
ueEventService *neDataService.UEEventAMF // UE会话事件服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
ueEventService *neDataService.UEEvent // UE会话事件服务
|
||||
}
|
||||
|
||||
// UE会话列表
|
||||
@@ -49,23 +48,20 @@ type AMFController struct {
|
||||
// @Router /neData/amf/ue/list [get]
|
||||
func (s *AMFController) UEList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.UEEventAMFQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("AMF", querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.ueEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -98,7 +94,7 @@ func (s *AMFController) UERemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.ueEventService.DeleteByIds(ids)
|
||||
rows, err := s.ueEventService.DeleteByIds("AMF", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -109,7 +105,7 @@ func (s *AMFController) UERemove(c *gin.Context) {
|
||||
|
||||
// UE会话列表导出
|
||||
//
|
||||
// POST /ue/export
|
||||
// GET /ue/export
|
||||
//
|
||||
// @Tags network_data/amf
|
||||
// @Accept json
|
||||
@@ -119,28 +115,23 @@ func (s *AMFController) UERemove(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary UE Session List Export
|
||||
// @Description UE Session List Export
|
||||
// @Router /neData/amf/ue/export [post]
|
||||
// @Router /neData/amf/ue/export [get]
|
||||
func (s *AMFController) UEExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.UEEventAMFQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("AMF", querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -150,7 +141,7 @@ func (s *AMFController) UEExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("amf_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.ueEventService.ExportXlsx(rows, fileName, language)
|
||||
saveFilePath, err := s.ueEventService.ExportAMF(rows, fileName, language)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
|
||||
317
src/modules/network_data/controller/cbc.go
Normal file
317
src/modules/network_data/controller/cbc.go
Normal file
@@ -0,0 +1,317 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
neType = "CBC" // 网元类型
|
||||
)
|
||||
|
||||
// 实例化控制层 CBCController 结构体
|
||||
var NewCBC = &CBCController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
neCBCMessageService: neDataService.NewCBCMessage,
|
||||
}
|
||||
|
||||
// 网元CBC
|
||||
type CBCController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
neCBCMessageService *neDataService.CBCMessage // CBC消息服务
|
||||
}
|
||||
|
||||
func (m *CBCController) List(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
neId := c.Query("neId")
|
||||
if neId == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
var query model.CBCMessageQuery
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
query.NeType = neType
|
||||
query.NeId = neId
|
||||
|
||||
data, total, err := neDataService.NewCBCMessage.SelectByPage(query)
|
||||
if err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 转换数据格式,确保 MessageJson 正确序列化
|
||||
processedData := make([]map[string]interface{}, len(data))
|
||||
for i, msg := range data {
|
||||
var messageJson interface{}
|
||||
if len(msg.MessageJson) > 0 {
|
||||
// 尝试解析为 JSON 对象
|
||||
if err := json.Unmarshal(msg.MessageJson, &messageJson); err != nil {
|
||||
// 如果解析失败,就作为字符串
|
||||
messageJson = string(msg.MessageJson)
|
||||
}
|
||||
}
|
||||
|
||||
processedData[i] = map[string]interface{}{
|
||||
"id": msg.Id,
|
||||
"neType": msg.NeType,
|
||||
"neId": msg.NeId,
|
||||
"messageJson": messageJson, // 这里是解析后的 JSON 对象
|
||||
"status": msg.Status.Enum(),
|
||||
"detail": msg.Detail,
|
||||
"createdAt": msg.CreatedAt,
|
||||
"updatedAt": msg.UpdatedAt,
|
||||
}
|
||||
}
|
||||
c.JSON(200, resp.Ok(gin.H{
|
||||
"total": total,
|
||||
"data": processedData,
|
||||
}))
|
||||
}
|
||||
|
||||
// Update 更新CB消息
|
||||
func (m *CBCController) Insert(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 绑定请求体
|
||||
var msg model.CBCMessage
|
||||
msg.NeType = neType
|
||||
msg.NeId = c.Query("neId")
|
||||
msg.Status = model.CBCEventStatusInactive // 默认状态为 INACTIVE
|
||||
if msg.NeId == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
msg.CreatedAt = now
|
||||
msg.UpdatedAt = now
|
||||
|
||||
// 使用 ShouldBindBodyWithJSON 读取请求体
|
||||
var jsonData interface{}
|
||||
if err := c.ShouldBindBodyWithJSON(&jsonData); err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 将绑定的数据转换为 JSON
|
||||
jsonBytes, err := json.Marshal(jsonData)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
msg.MessageJson = json.RawMessage(jsonBytes)
|
||||
|
||||
if err := neDataService.NewCBCMessage.Insert(msg); err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
}
|
||||
|
||||
// Update 更新CB消息
|
||||
func (m *CBCController) Update(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
|
||||
// 获取路径参数
|
||||
messageId := c.Param("id")
|
||||
if messageId == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(messageId, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 直接读取body为json.RawMessage
|
||||
var jsonData interface{}
|
||||
if err := c.ShouldBindBodyWithJSON(&jsonData); err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 将绑定的数据转换为 JSON
|
||||
jsonBytes, err := json.Marshal(jsonData)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
messageJson := json.RawMessage(jsonBytes)
|
||||
|
||||
if err := neDataService.NewCBCMessage.Update(id, messageJson); err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
}
|
||||
|
||||
// UpdateStatus 更新CB消息状态
|
||||
// 这里的 neId 参数是为了兼容性,实际更新状态时不需要使用它
|
||||
// 但为了保持与原有接口一致,仍然保留该参数
|
||||
// 如果需要根据 neId 进行特定的逻辑处理,可以在服务层实现
|
||||
// 但在当前实现中,neId 仅用于验证请求的有效性
|
||||
// 实际的状态更新逻辑不依赖于 neId
|
||||
// 该接口用于更新 CB 消息的状态,状态值通过查询参数传递
|
||||
// 例如:PUT /:neId/message/status?status=ACTIVE
|
||||
func (m *CBCController) UpdateStatus(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
|
||||
neId := c.Query("neId")
|
||||
status := c.Param("status")
|
||||
if neId == "" || status == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
messageId := c.Param("id")
|
||||
if messageId != "" {
|
||||
id, err := strconv.ParseInt(messageId, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 如果提供了 messageId,则更新特定消息的状态
|
||||
if err := neDataService.NewCBCMessage.UpdateStatus(id, status); err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
return
|
||||
}
|
||||
// 如果没有提供 messageId,则更新所有消息的状态
|
||||
if err := neDataService.NewCBCMessage.UpdateStatusByNeId(neId, status); err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
}
|
||||
|
||||
// Delete 删除CB消息
|
||||
func (m *CBCController) Delete(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
|
||||
// 获取路径参数
|
||||
messageId := c.Param("id")
|
||||
if messageId == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(messageId, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
if err := neDataService.NewCBCMessage.Delete(id); err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.Ok(nil))
|
||||
}
|
||||
|
||||
// ListById 根据ID获取CB消息
|
||||
func (m *CBCController) ListById(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
|
||||
// 获取路径参数
|
||||
idStr := c.Param("id")
|
||||
if idStr == "" {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
data, err := neDataService.NewCBCMessage.SelectById(id)
|
||||
if err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
c.JSON(404, resp.CodeMsg(404, i18n.TKey(language, "app.common.err404")))
|
||||
return
|
||||
}
|
||||
// 转换数据格式,确保 MessageJson 正确序列化
|
||||
var messageJson interface{}
|
||||
if len(data.MessageJson) > 0 {
|
||||
// 尝试解析为 JSON 对象
|
||||
if err := json.Unmarshal(data.MessageJson, &messageJson); err != nil {
|
||||
// 如果解析失败,就作为字符串
|
||||
messageJson = string(data.MessageJson)
|
||||
}
|
||||
}
|
||||
|
||||
processedData := map[string]interface{}{
|
||||
"id": data.Id,
|
||||
"neType": data.NeType,
|
||||
"neId": data.NeId,
|
||||
"messageJson": messageJson, // 这里是解析后的 JSON 对象
|
||||
"status": data.Status.Enum(),
|
||||
"detail": data.Detail,
|
||||
"createdAt": data.CreatedAt,
|
||||
"updatedAt": data.UpdatedAt,
|
||||
}
|
||||
|
||||
c.JSON(200, resp.Ok(gin.H{
|
||||
"data": processedData,
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *CBCController) Export(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var query model.CBCMessageQuery
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
// 限制导出数据集
|
||||
if query.PageSize > 10000 {
|
||||
query.PageSize = 10000
|
||||
}
|
||||
// 查询数据
|
||||
rows, total, err := m.neCBCMessageService.SelectByPage(query)
|
||||
if err != nil {
|
||||
c.JSON(500, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("cbc_message_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := m.neCBCMessageService.ExportXlsx(rows, fileName, language)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.FileAttachment(saveFilePath, fileName)
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
@@ -19,15 +18,15 @@ import (
|
||||
// 实例化控制层 IMSController 结构体
|
||||
var NewIMS = &IMSController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
cdrEventService: neDataService.NewCDREventIMS,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
}
|
||||
|
||||
// 网元IMS
|
||||
//
|
||||
// PATH /ims
|
||||
type IMSController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREventIMS // CDR会话事件服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -50,23 +49,20 @@ type IMSController struct {
|
||||
// @Router /neData/ims/cdr/list [get]
|
||||
func (s *IMSController) CDRList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.CDREventIMSQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -99,7 +95,7 @@ func (s *IMSController) CDRRemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.cdrEventService.DeleteByIds(ids)
|
||||
rows, err := s.cdrEventService.DeleteByIds("IMS", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -110,7 +106,7 @@ func (s *IMSController) CDRRemove(c *gin.Context) {
|
||||
|
||||
// CDR会话列表导出
|
||||
//
|
||||
// POST /cdr/export
|
||||
// GET /cdr/export
|
||||
//
|
||||
// @Tags network_data/ims
|
||||
// @Accept json
|
||||
@@ -120,28 +116,23 @@ func (s *IMSController) CDRRemove(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary CDR Session List Export
|
||||
// @Description CDR Session List Export
|
||||
// @Router /neData/ims/cdr/export [post]
|
||||
// @Router /neData/ims/cdr/export [get]
|
||||
func (s *IMSController) CDRExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventIMSQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -151,7 +142,7 @@ func (s *IMSController) CDRExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("ims_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.cdrEventService.ExportXlsx(rows, fileName, language)
|
||||
saveFilePath, err := s.cdrEventService.ExportIMS(rows, fileName, language)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
@@ -19,15 +18,15 @@ import (
|
||||
// 实例化控制层 MMEController 结构体
|
||||
var NewMME = &MMEController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
ueEventService: neDataService.NewUEEventMME,
|
||||
ueEventService: neDataService.NewUEEvent,
|
||||
}
|
||||
|
||||
// 网元MME
|
||||
//
|
||||
// PATH /mme
|
||||
type MMEController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
ueEventService *neDataService.UEEventMME // UE会话事件服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
ueEventService *neDataService.UEEvent // UE会话事件服务
|
||||
}
|
||||
|
||||
// UE会话列表
|
||||
@@ -49,23 +48,20 @@ type MMEController struct {
|
||||
// @Router /neData/mme/ue/list [get]
|
||||
func (s *MMEController) UEList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.UEEventMMEQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("MME", querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.ueEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -98,7 +94,7 @@ func (s *MMEController) UERemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.ueEventService.DeleteByIds(ids)
|
||||
rows, err := s.ueEventService.DeleteByIds("MME", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -109,7 +105,7 @@ func (s *MMEController) UERemove(c *gin.Context) {
|
||||
|
||||
// UE会话列表导出
|
||||
//
|
||||
// POST /ue/export
|
||||
// GET /ue/export
|
||||
//
|
||||
// @Tags network_data/mme
|
||||
// @Accept json
|
||||
@@ -119,28 +115,23 @@ func (s *MMEController) UERemove(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary UE Session List Export
|
||||
// @Description UE Session List Export
|
||||
// @Router /neData/mme/ue/export [post]
|
||||
// @Router /neData/mme/ue/export [get]
|
||||
func (s *MMEController) UEExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.UEEventMMEQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("MME", querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.ueEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -150,7 +141,7 @@ func (s *MMEController) UEExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("mme_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.ueEventService.ExportXlsx(rows, fileName, language)
|
||||
saveFilePath, err := s.ueEventService.ExportMME(rows, fileName, language)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
|
||||
70
src/modules/network_data/controller/n3iwf.go
Normal file
70
src/modules/network_data/controller/n3iwf.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 实例化控制层 N3IWFController 结构体
|
||||
var NewN3IWF = &N3IWFController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
}
|
||||
|
||||
// 网元N3IWF
|
||||
//
|
||||
// PATH /n3iwf
|
||||
type N3IWFController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
}
|
||||
|
||||
// 在线订阅用户列表信息
|
||||
//
|
||||
// GET /sub/list
|
||||
//
|
||||
// @Tags network_data/n3iwf
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param neId query string true "NE ID" default(001)
|
||||
// @Param imsi query string false "imsi"
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Online session user list information
|
||||
// @Description Online session user list information
|
||||
// @Router /neData/n3iwf/sub/list [get]
|
||||
func (s N3IWFController) SubUserList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var query struct {
|
||||
NeId string `form:"neId" binding:"required"`
|
||||
IMSI string `form:"imsi"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元信息
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("N3IWF", query.NeId)
|
||||
if neInfo.NeId != query.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元直连
|
||||
data, err := neFetchlink.N3IWFSubInfoList(neInfo, map[string]string{
|
||||
"imsi": query.IMSI,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
107
src/modules/network_data/controller/nssf.go
Normal file
107
src/modules/network_data/controller/nssf.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 实例化控制层 NSSFController 结构体
|
||||
var NewNSSF = &NSSFController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
}
|
||||
|
||||
// 网元NSSF
|
||||
//
|
||||
// PATH /NSSF
|
||||
type NSSFController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
}
|
||||
|
||||
// 在线订阅用户列表信息
|
||||
//
|
||||
// GET /sub/list
|
||||
//
|
||||
// @Tags network_data/nssf
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param neId query string true "NE ID" default(001)
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Online session user list information
|
||||
// @Description Online session user list information
|
||||
// @Router /neData/nssf/sub/list [get]
|
||||
func (s NSSFController) SubUserList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var query struct {
|
||||
NeId string `form:"neId" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元信息
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("NSSF", query.NeId)
|
||||
if neInfo.NeId != query.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元直连
|
||||
data, err := neFetchlink.NSSFSubInfoList(neInfo)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
|
||||
// 可用AMF列表信息
|
||||
//
|
||||
// GET /amf/list
|
||||
//
|
||||
// @Tags network_data/nssf
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param neId query string true "NE ID" default(001)
|
||||
// @Success 200 {object} object "Response Results"
|
||||
// @Security TokenAuth
|
||||
// @Summary Online session user list information
|
||||
// @Description Online session user list information
|
||||
// @Router /neData/nssf/amf/list [get]
|
||||
func (s NSSFController) AvailableList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var query struct {
|
||||
NeId string `form:"neId" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元信息
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID("NSSF", query.NeId)
|
||||
if neInfo.NeId != query.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元直连
|
||||
data, err := neFetchlink.NSSFAvailableAMFList(neInfo)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp.OkData(data))
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -17,7 +16,7 @@ import (
|
||||
// 实例化控制层 SGWCController 结构体
|
||||
var NewSGWC = &SGWCController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
cdrEventService: neDataService.NewCDREventSGWC,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
UDMExtendService: neDataService.NewUDMExtend,
|
||||
}
|
||||
|
||||
@@ -25,9 +24,9 @@ var NewSGWC = &SGWCController{
|
||||
//
|
||||
// PATH /sgwc
|
||||
type SGWCController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREventSGWC // CDR会话事件服务
|
||||
UDMExtendService *neDataService.UDMExtend // UDM用户信息服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
UDMExtendService *neDataService.UDMExtend // UDM用户信息服务
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -50,23 +49,20 @@ type SGWCController struct {
|
||||
// @Router /neData/sgwc/cdr/list [get]
|
||||
func (s *SGWCController) CDRList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.CDREventSGWCQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -99,7 +95,7 @@ func (s *SGWCController) CDRRemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.cdrEventService.DeleteByIds(ids)
|
||||
rows, err := s.cdrEventService.DeleteByIds("SGWC", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -123,25 +119,20 @@ func (s *SGWCController) CDRRemove(c *gin.Context) {
|
||||
// @Router /neData/sgwc/cdr/export [post]
|
||||
func (s *SGWCController) CDRExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventSGWCQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -151,7 +142,7 @@ func (s *SGWCController) CDRExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("sgwc_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.cdrEventService.ExportXlsx(rows, fileName)
|
||||
saveFilePath, err := s.cdrEventService.ExportSGWC(rows, fileName)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
@@ -20,7 +19,7 @@ import (
|
||||
// 实例化控制层 SMFController 结构体
|
||||
var NewSMF = &SMFController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
cdrEventService: neDataService.NewCDREventSMF,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
UDMExtendService: neDataService.NewUDMExtend,
|
||||
}
|
||||
|
||||
@@ -28,9 +27,9 @@ var NewSMF = &SMFController{
|
||||
//
|
||||
// PATH /smf
|
||||
type SMFController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREventSMF // CDR会话事件服务
|
||||
UDMExtendService *neDataService.UDMExtend // UDM用户信息服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
UDMExtendService *neDataService.UDMExtend // UDM用户信息服务
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -52,23 +51,20 @@ type SMFController struct {
|
||||
// @Router /neData/smf/cdr/list [get]
|
||||
func (s *SMFController) CDRList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.CDREventSMFQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -101,7 +97,7 @@ func (s *SMFController) CDRRemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.cdrEventService.DeleteByIds(ids)
|
||||
rows, err := s.cdrEventService.DeleteByIds("SMF", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -112,7 +108,7 @@ func (s *SMFController) CDRRemove(c *gin.Context) {
|
||||
|
||||
// CDR会话列表导出
|
||||
//
|
||||
// POST /cdr/export
|
||||
// GET /cdr/export
|
||||
//
|
||||
// @Tags network_data/smf
|
||||
// @Accept json
|
||||
@@ -122,28 +118,23 @@ func (s *SMFController) CDRRemove(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary CDR Session List Export
|
||||
// @Description CDR Session List Export
|
||||
// @Router /neData/smf/cdr/export [post]
|
||||
// @Router /neData/smf/cdr/export [get]
|
||||
func (s *SMFController) CDRExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventSMFQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -153,7 +144,7 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("smf_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.cdrEventService.ExportXlsx(rows, fileName)
|
||||
saveFilePath, err := s.cdrEventService.ExportSMF(rows, fileName)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -219,7 +210,7 @@ func (s *SMFController) SubUserNum(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary Online session user list information
|
||||
// @Description Online session user list information
|
||||
// @Router /neData/smf/session/list [get]
|
||||
// @Router /neData/smf/sub/list [get]
|
||||
func (s *SMFController) SubUserList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var query struct {
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"be.ems/src/framework/reqctx"
|
||||
"be.ems/src/framework/resp"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
|
||||
@@ -18,15 +17,15 @@ import (
|
||||
// 实例化控制层 SMSCController 结构体
|
||||
var NewSMSC = &SMSCController{
|
||||
neInfoService: neService.NewNeInfo,
|
||||
cdrEventService: neDataService.NewCDREventSMSC,
|
||||
cdrEventService: neDataService.NewCDREvent,
|
||||
}
|
||||
|
||||
// 网元SMSC
|
||||
//
|
||||
// PATH /smsc
|
||||
type SMSCController struct {
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREventSMSC // CDR会话事件服务
|
||||
neInfoService *neService.NeInfo // 网元信息服务
|
||||
cdrEventService *neDataService.CDREvent // CDR会话事件服务
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -49,23 +48,20 @@ type SMSCController struct {
|
||||
// @Router /neData/smsc/cdr/list [get]
|
||||
func (s *SMSCController) CDRList(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
var querys model.CDREventSMSCQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
@@ -98,7 +94,7 @@ func (s *SMSCController) CDRRemove(c *gin.Context) {
|
||||
ids = append(ids, parse.Number(v))
|
||||
}
|
||||
|
||||
rows, err := s.cdrEventService.DeleteByIds(ids)
|
||||
rows, err := s.cdrEventService.DeleteByIds("SMSC", ids)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
@@ -109,7 +105,7 @@ func (s *SMSCController) CDRRemove(c *gin.Context) {
|
||||
|
||||
// CDR会话列表导出
|
||||
//
|
||||
// POST /cdr/export
|
||||
// GET /cdr/export
|
||||
//
|
||||
// @Tags network_data/smsc
|
||||
// @Accept json
|
||||
@@ -119,28 +115,23 @@ func (s *SMSCController) CDRRemove(c *gin.Context) {
|
||||
// @Security TokenAuth
|
||||
// @Summary CDR Session List Export
|
||||
// @Description CDR Session List Export
|
||||
// @Router /neData/smsc/cdr/export [post]
|
||||
// @Router /neData/smsc/cdr/export [get]
|
||||
func (s *SMSCController) CDRExport(c *gin.Context) {
|
||||
language := reqctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventSMSCQuery
|
||||
if err := c.ShouldBindBodyWithJSON(&querys); err != nil {
|
||||
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
|
||||
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
|
||||
return
|
||||
}
|
||||
query := reqctx.QueryMap(c)
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
pageSize := parse.Number(query["pageSize"])
|
||||
if pageSize > 10000 {
|
||||
query["pageSize"] = "10000"
|
||||
}
|
||||
// 查询网元信息 rmUID
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.FindByNeTypeAndNeID(query["neType"], query["neId"])
|
||||
if neInfo.NeType == "" {
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(querys)
|
||||
query["rmUID"] = neInfo.RmUID
|
||||
rows, total := s.cdrEventService.FindByPage(neInfo.NeType, query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
@@ -150,7 +141,7 @@ func (s *SMSCController) CDRExport(c *gin.Context) {
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("smsc_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 导出数据表格
|
||||
saveFilePath, err := s.cdrEventService.ExportXlsx(rows, fileName, language)
|
||||
saveFilePath, err := s.cdrEventService.ExportSMSC(rows, fileName, language)
|
||||
if err != nil {
|
||||
c.JSON(200, resp.ErrMsg(err.Error()))
|
||||
return
|
||||
|
||||
@@ -77,8 +77,8 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
|
||||
// @Router /neData/udm/auth/list [get]
|
||||
func (s *UDMAuthController) List(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmAuthService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
|
||||
rows, total := s.udmAuthService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
// UDM鉴权用户信息
|
||||
@@ -478,7 +478,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmAuthService.FindByPage(query)
|
||||
rows, total := s.udmAuthService.FindByPage(query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
|
||||
@@ -77,8 +77,8 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
|
||||
// @Router /neData/udm/sub/list [get]
|
||||
func (s *UDMSubController) List(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmSubService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
|
||||
rows, total := s.udmSubService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
// UDM签约用户信息
|
||||
@@ -484,7 +484,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmSubService.FindByPage(query)
|
||||
rows, total := s.udmSubService.FindByPage(query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
|
||||
@@ -76,8 +76,8 @@ func (s *UDMVOIPController) ResetData(c *gin.Context) {
|
||||
// @Router /neData/udm/voip/list [get]
|
||||
func (s *UDMVOIPController) List(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmVOIPService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
|
||||
rows, total := s.udmVOIPService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
// UDMVOIP用户信息
|
||||
@@ -416,7 +416,7 @@ func (s *UDMVOIPController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmVOIPService.FindByPage(query)
|
||||
rows, total := s.udmVOIPService.FindByPage(query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
|
||||
@@ -76,8 +76,8 @@ func (s *UDMVolteIMSController) ResetData(c *gin.Context) {
|
||||
// @Router /neData/udm/volte-ims/list [get]
|
||||
func (s *UDMVolteIMSController) List(c *gin.Context) {
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmVolteIMSService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"total": total, "rows": rows}))
|
||||
rows, total := s.udmVolteIMSService.FindByPage(query)
|
||||
c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
|
||||
}
|
||||
|
||||
// UDMVolteIMS用户信息
|
||||
@@ -462,7 +462,7 @@ func (s *UDMVolteIMSController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
query := reqctx.QueryMap(c)
|
||||
total, rows := s.udmVolteIMSService.FindByPage(query)
|
||||
rows, total := s.udmVolteIMSService.FindByPage(query)
|
||||
if total == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
|
||||
@@ -8,26 +8,26 @@ type Alarm struct {
|
||||
NeName string `json:"neName" gorm:"column:ne_name"` // 网元名称
|
||||
Province string `json:"province" gorm:"column:province"` // 网元省份地域
|
||||
PvFlag string `json:"pvFlag" gorm:"column:pv_flag"` // 网元标识虚拟化标识
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增
|
||||
AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID
|
||||
AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题
|
||||
AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
PerceivedSeverity string `json:"perceivedSeverity" gorm:"column:perceived_severity"` // 告警级别 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度
|
||||
PerceivedSeverity string `json:"perceivedSeverity" gorm:"column:perceived_severity"` // 告警级别
|
||||
ObjectUid string `json:"objectUid" gorm:"column:object_uid"` // 对象ID
|
||||
ObjectName string `json:"objectName" gorm:"column:object_name"` // 对象名称
|
||||
ObjectType string `json:"objectType" gorm:"column:object_type"` // 对象类型
|
||||
LocationInfo string `json:"locationInfo" gorm:"column:location_info"` // 告警定位信息
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态
|
||||
SpecificProblem string `json:"specificProblem" gorm:"column:specific_problem"` // 告警问题原因
|
||||
SpecificProblemId string `json:"specificProblemId" gorm:"column:specific_problem_id"` // 告警问题原因ID
|
||||
AddInfo string `json:"addInfo" gorm:"column:add_info"` // 告警辅助信息
|
||||
AckState int64 `json:"ackState" gorm:"column:ack_state"` // 确认状态 0: Unacked, 1: Acked
|
||||
AckTime int64 `json:"ackTime" gorm:"column:ack_time"` // 确认时间 秒级
|
||||
AckState string `json:"ackState" gorm:"column:ack_state"` // 确认状态
|
||||
AckTime int64 `json:"ackTime" gorm:"column:ack_time"` // 确认时间
|
||||
AckUser string `json:"ackUser" gorm:"column:ack_user"` // 确认用户
|
||||
ClearType int64 `json:"clearType" gorm:"column:clear_type"` // 清除状态 0: Unclear, 1: AutoClear, 2: ManualClear
|
||||
ClearType string `json:"clearType" gorm:"column:clear_type"` // 清除状态
|
||||
ClearTime int64 `json:"clearTime" gorm:"column:clear_time"` // 清除时间
|
||||
ClearUser string `json:"clearUser" gorm:"column:clear_user"` // 清除用户
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 创建时间
|
||||
@@ -46,9 +46,9 @@ type AlarmQuery struct {
|
||||
PvFlag string `json:"pvFlag" form:"pvFlag"`
|
||||
AlarmCode string `json:"alarmCode" form:"alarmCode"`
|
||||
AlarmType string `json:"alarmType" form:"alarmType"`
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active
|
||||
OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态
|
||||
OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
|
||||
@@ -9,16 +9,16 @@ type AlarmEvent struct {
|
||||
AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID
|
||||
AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题
|
||||
AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间
|
||||
ObjectUid string `json:"objectUid" gorm:"column:object_uid"` // 对象ID
|
||||
ObjectName string `json:"objectName" gorm:"column:object_name"` // 对象名称
|
||||
ObjectType string `json:"objectType" gorm:"column:object_type"` // 对象类型
|
||||
LocationInfo string `json:"locationInfo" gorm:"column:location_info"` // 告警定位信息
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态
|
||||
SpecificProblem string `json:"specificProblem" gorm:"column:specific_problem"` // 告警问题原因
|
||||
SpecificProblemId string `json:"specificProblemId" gorm:"column:specific_problem_id"` // 告警问题原因ID
|
||||
AddInfo string `json:"addInfo" gorm:"column:add_info"` // 告警辅助信息
|
||||
ClearType int64 `json:"clearType" gorm:"column:clear_type"` // 清除状态 0: Unclear, 1: AutoClear, 2: ManualClear
|
||||
ClearType string `json:"clearType" gorm:"column:clear_type"` // 清除状态
|
||||
ClearTime int64 `json:"clearTime" gorm:"column:clear_time"` // 清除时间
|
||||
ClearUser string `json:"clearUser" gorm:"column:clear_user"` // 清除用户
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 创建时间
|
||||
@@ -34,8 +34,8 @@ type AlarmEventQuery struct {
|
||||
NeType string `json:"neType" form:"neType"` // 网元类型
|
||||
NeID string `json:"neId" form:"neId"` // 网元ID
|
||||
AlarmCode string `json:"alarmCode" form:"alarmCode"`
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
|
||||
@@ -5,16 +5,16 @@ type AlarmForwardLog struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeId string `json:"neId" gorm:"column:ne_id"`
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增
|
||||
AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID
|
||||
AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码
|
||||
AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 创建时间
|
||||
Type string `json:"type" gorm:"column:type"` // 转发方式 SMS/EMAIL
|
||||
Type string `json:"type" gorm:"column:type"` // 转发方式 SMS/EMAIL/SMSC
|
||||
Target string `json:"target" gorm:"column:target"` // 发送目标用户
|
||||
Result string `json:"result" gorm:"column:result"` // 发送结果
|
||||
}
|
||||
@@ -28,7 +28,7 @@ func (*AlarmForwardLog) TableName() string {
|
||||
type AlarmForwardLogQuery struct {
|
||||
NeType string `json:"neType" form:"neType"` // 网元类型
|
||||
NeID string `json:"neId" form:"neId"` // 网元ID
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
|
||||
@@ -5,14 +5,14 @@ type AlarmLog struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeId string `json:"neId" gorm:"column:ne_id"`
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 同网元类型连续递增
|
||||
AlarmSeq int64 `json:"alarmSeq" gorm:"column:alarm_seq"` // 告警序号 连续递增
|
||||
AlarmId string `json:"alarmId" gorm:"column:alarm_id"` // 告警ID
|
||||
AlarmCode int64 `json:"alarmCode" gorm:"column:alarm_code"` // 告警状态码
|
||||
AlarmTitle string `json:"alarmTitle" gorm:"column:alarm_title"` // 告警标题
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态 0:clear, 1:active
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型 CommunicationAlarm=1,EquipmentAlarm=2,ProcessingFailure=3,EnvironmentalAlarm=4,QualityOfServiceAlarm=5
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间 秒级
|
||||
AlarmStatus string `json:"alarmStatus" gorm:"column:alarm_status"` // 告警状态
|
||||
AlarmType string `json:"alarmType" gorm:"column:alarm_type"` // 告警类型
|
||||
OrigSeverity string `json:"origSeverity" gorm:"column:orig_severity"` // 严重程度
|
||||
EventTime int64 `json:"eventTime" gorm:"column:event_time"` // 事件产生时间
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 创建时间
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ func (*AlarmLog) TableName() string {
|
||||
|
||||
// AlarmLogQuery 告警日志数据查询参数结构体
|
||||
type AlarmLogQuery struct {
|
||||
NeType string `json:"neType" form:"neType"` // 网元类型
|
||||
NeID string `json:"neId" form:"neId"` // 网元ID
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=0 1"` // 告警状态 0:clear, 1:active
|
||||
OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型 1: Critical, 2: Major, 3: Minor, 4: Warning, 5: Event(Only VNF)
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
NeType string `json:"neType" form:"neType"` // 网元类型
|
||||
NeID string `json:"neId" form:"neId"` // 网元ID
|
||||
AlarmStatus string `json:"alarmStatus" form:"alarmStatus" binding:"omitempty,oneof=Clear Active"` // 告警状态
|
||||
OrigSeverity string `json:"origSeverity" form:"origSeverity"` // 告警类型
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查event_time
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=event_time id"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
|
||||
112
src/modules/network_data/model/cbc_message.go
Normal file
112
src/modules/network_data/model/cbc_message.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CBCEventStatus int
|
||||
|
||||
// CBCEventStatus CB事件状态枚举
|
||||
const (
|
||||
CBCEventStatusNull CBCEventStatus = iota // 未知状态
|
||||
CBCEventStatusActive
|
||||
CBCEventStatusInactive
|
||||
)
|
||||
|
||||
func (status CBCEventStatus) Enum() string {
|
||||
switch status {
|
||||
case CBCEventStatusNull:
|
||||
return "NULL"
|
||||
case CBCEventStatusActive:
|
||||
return "ACTIVE"
|
||||
case CBCEventStatusInactive:
|
||||
return "INACTIVE"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
func (status CBCEventStatus) String() string {
|
||||
return fmt.Sprintf("%d", status)
|
||||
}
|
||||
|
||||
// ParseCBCEventStatus 将字符串转换为 枚举类型
|
||||
func ParseCBCEventStatus(s string) CBCEventStatus {
|
||||
if i, err := strconv.Atoi(s); err == nil {
|
||||
return CBCEventStatus(i)
|
||||
}
|
||||
// 如果转换失败,则按名称匹配(忽略大小写)
|
||||
switch strings.ToUpper(s) {
|
||||
case "NULL":
|
||||
return CBCEventStatusNull
|
||||
case "ACTIVE":
|
||||
return CBCEventStatusActive
|
||||
case "INACTIVE":
|
||||
return CBCEventStatusInactive
|
||||
case "":
|
||||
// 如果字符串为空,则返回未知状态
|
||||
return CBCEventStatusNull
|
||||
default:
|
||||
// 默认返回未知状态
|
||||
return CBCEventStatusNull
|
||||
}
|
||||
}
|
||||
|
||||
// CBCMessageQuery 查询条件结构体
|
||||
type CBCMessageQuery struct {
|
||||
NeType string `form:"neType"` // 网元类型
|
||||
NeId string `form:"neId"` // 网元ID
|
||||
EventName string `form:"eventName"` // 事件名称
|
||||
Status string `form:"status"` // 消息状态
|
||||
StartTime string `form:"startTime"` // 创建时间范围-起始
|
||||
EndTime string `form:"endTime"` // 创建时间范围-结束
|
||||
PageNum int `form:"pageNum" binding:"required"`
|
||||
PageSize int `form:"pageSize" binding:"required"`
|
||||
}
|
||||
|
||||
// @Description CBCMessage CB消息
|
||||
type CBCMessage struct {
|
||||
Id int64 `json:"id" gorm:"column:id"` // CB消息ID
|
||||
NeType string `json:"neType" gorm:"column:ne_type"` // 网元类型
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // 网元ID
|
||||
MessageJson json.RawMessage `json:"messageJson" gorm:"column:message_json"` // 消息内容JSON
|
||||
Status CBCEventStatus `json:"status" gorm:"column:status"` // 消息状态
|
||||
Detail string `json:"detail" gorm:"column:detail"` // 详情
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 创建时间
|
||||
UpdatedAt int64 `json:"updatedAt" gorm:"column:updated_at"` // 更新时间
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CBCMessage) TableName() string {
|
||||
return "cbc_message"
|
||||
}
|
||||
|
||||
// Scan 实现 sql.Scanner 接口,支持从数据库字符串转为 CBCEventStatus
|
||||
func (s *CBCEventStatus) Scan(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
*s = ParseCBCEventStatus(v)
|
||||
return nil
|
||||
case []byte:
|
||||
*s = ParseCBCEventStatus(string(v))
|
||||
return nil
|
||||
case int64:
|
||||
*s = CBCEventStatus(v)
|
||||
return nil
|
||||
case int:
|
||||
*s = CBCEventStatus(v)
|
||||
return nil
|
||||
default:
|
||||
return errors.New("unsupported Scan type for CBCEventStatus")
|
||||
}
|
||||
}
|
||||
|
||||
// Value 实现 driver.Valuer 接口,支持将 CBCEventStatus 存为字符串
|
||||
func (s CBCEventStatus) Value() (driver.Value, error) {
|
||||
return s.Enum(), nil
|
||||
}
|
||||
17
src/modules/network_data/model/cdr_event.go
Normal file
17
src/modules/network_data/model/cdr_event.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
// CDREvent CDR会话对象 cdr_event
|
||||
type CDREvent struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUid string `json:"rmUid" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CDREvent) TableName() string {
|
||||
return "cdr_event"
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package model
|
||||
|
||||
// CDREventIMS CDR会话对象IMS cdr_event_ims
|
||||
type CDREventIMS struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUid string `json:"rmUid" gorm:"column:rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CDREventIMS) TableName() string {
|
||||
return "cdr_event_ims"
|
||||
}
|
||||
|
||||
// CDREventIMSQuery CDR会话对象IMS查询参数结构体
|
||||
type CDREventIMSQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=IMS"` // 网元类型IMS
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC
|
||||
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
|
||||
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package model
|
||||
|
||||
// CDREventSGWC CDR会话对象SGWC cdr_event_sgwc
|
||||
type CDREventSGWC struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUid string `json:"rmUid" gorm:"column:rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CDREventSGWC) TableName() string {
|
||||
return "cdr_event_sgwc"
|
||||
}
|
||||
|
||||
// CDREventSGWCQuery CDR会话对象SGWC查询参数结构体
|
||||
type CDREventSGWCQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=SGWC"` // SGWC
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
IMSI string `json:"imsi" form:"imsi"`
|
||||
MSISDN string `json:"msisdn" form:"msisdn"`
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package model
|
||||
|
||||
// CDREventSMF CDR会话对象SMF cdr_event_smf
|
||||
type CDREventSMF struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUid string `json:"rmUid" gorm:"column:rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CDREventSMF) TableName() string {
|
||||
return "cdr_event_smf"
|
||||
}
|
||||
|
||||
// CDREventSMFQuery CDR会话对象SMF查询参数结构体
|
||||
type CDREventSMFQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=SMF"` // 网元类型, 暂时支持SMF
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
RecordType string `json:"recordType" form:"recordType"` // 暂时没用到
|
||||
SubscriberID string `json:"subscriberID" form:"subscriberID"`
|
||||
DNN string `json:"dnn" form:"dnn"`
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package model
|
||||
|
||||
// CDREventSMSC CDR会话对象SMSC cdr_event_smsc
|
||||
type CDREventSMSC struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUid string `json:"rmUid" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
CdrJson string `json:"cdrJSON" gorm:"column:cdr_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*CDREventSMSC) TableName() string {
|
||||
return "cdr_event_smsc"
|
||||
}
|
||||
|
||||
// CDREventSMSCQuery CDR会话对象SMSC查询参数结构体
|
||||
type CDREventSMSCQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=SMSC"` // 网元类型, 暂时支持SMSC
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOSM MTSM
|
||||
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
|
||||
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
18
src/modules/network_data/model/ue_event.go
Normal file
18
src/modules/network_data/model/ue_event.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package model
|
||||
|
||||
// UEEvent UE会话对象 ue_event
|
||||
type UEEvent struct {
|
||||
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到时间
|
||||
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型
|
||||
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*UEEvent) TableName() string {
|
||||
return "ue_event"
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package model
|
||||
|
||||
// UEEventAMF UE会话对象AMF ue_event_amf
|
||||
type UEEventAMF struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
|
||||
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*UEEventAMF) TableName() string {
|
||||
return "ue_event_amf"
|
||||
}
|
||||
|
||||
// UEEventAMFQuery UE会话对象AMF查询参数结构体
|
||||
type UEEventAMFQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=AMF"` // 网元类型, 暂时支持AMF
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
|
||||
IMSI string `json:"imsi" form:"imsi"` // imsi
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package model
|
||||
|
||||
// UEEventMME UE会话对象MME ue_event_mme
|
||||
type UEEventMME struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
|
||||
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
|
||||
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
|
||||
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (*UEEventMME) TableName() string {
|
||||
return "ue_event_mme"
|
||||
}
|
||||
|
||||
// UEEventMMEQuery UE会话对象MME查询参数结构体
|
||||
type UEEventMMEQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required,oneof=MME"` // 网元类型, 暂时支持MME
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
|
||||
IMSI string `json:"imsi" form:"imsi"` // imsi
|
||||
BeginTime int64 `json:"beginTime" form:"beginTime"` // 开始时间 查timestamp
|
||||
EndTime int64 `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -33,6 +33,31 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
}
|
||||
|
||||
// 性能自定义统计信息
|
||||
kpicGroup := neDataGroup.Group("/kpic")
|
||||
{
|
||||
kpicGroup.GET("/data",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewKPIC.KPIData,
|
||||
)
|
||||
kpicGroup.GET("/title/list",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewKPIC.ListTitle,
|
||||
)
|
||||
kpicGroup.POST("/title",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewKPIC.AddTitle,
|
||||
)
|
||||
kpicGroup.PUT("/title",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewKPIC.EditTitle,
|
||||
)
|
||||
kpicGroup.DELETE("/title",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewKPIC.RemoveTitle,
|
||||
)
|
||||
}
|
||||
|
||||
// 告警数据信息
|
||||
alarmGroup := neDataGroup.Group("/alarm")
|
||||
{
|
||||
@@ -59,6 +84,18 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.alarm", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewAlarm.Export,
|
||||
)
|
||||
alarmGroup.GET("/count/type",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewAlarm.CountType,
|
||||
)
|
||||
alarmGroup.GET("/count/severity",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewAlarm.CountSeverity,
|
||||
)
|
||||
alarmGroup.GET("/count/ne",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewAlarm.CountNe,
|
||||
)
|
||||
}
|
||||
|
||||
// 告警日志数据信息
|
||||
@@ -100,7 +137,7 @@ func Setup(router *gin.Engine) {
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewNBState.List,
|
||||
)
|
||||
nbStateGroup.POST("/export",
|
||||
nbStateGroup.GET("/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewNBState.Export,
|
||||
)
|
||||
@@ -118,7 +155,7 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewIMS.CDRRemove,
|
||||
)
|
||||
imsGroup.POST("/cdr/export",
|
||||
imsGroup.GET("/cdr/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewIMS.CDRExport,
|
||||
@@ -145,7 +182,7 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewSMSC.CDRRemove,
|
||||
)
|
||||
smscGroup.POST("/cdr/export",
|
||||
smscGroup.GET("/cdr/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewSMSC.CDRExport,
|
||||
@@ -164,7 +201,7 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewSMF.CDRRemove,
|
||||
)
|
||||
smfGroup.POST("/cdr/export",
|
||||
smfGroup.GET("/cdr/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewSMF.CDRExport,
|
||||
@@ -191,7 +228,7 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewAMF.UERemove,
|
||||
)
|
||||
amfGroup.POST("/ue/export",
|
||||
amfGroup.GET("/ue/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewAMF.UEExport,
|
||||
@@ -215,6 +252,29 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
}
|
||||
|
||||
// 网元N3IWF
|
||||
n3iwfGroup := neDataGroup.Group("/n3iwf")
|
||||
{
|
||||
n3iwfGroup.GET("/sub/list",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewN3IWF.SubUserList,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元N3IWF
|
||||
nssf := controller.NewNSSF
|
||||
nssfGroup := neDataGroup.Group("/nssf")
|
||||
{
|
||||
nssfGroup.GET("/sub/list",
|
||||
middleware.AuthorizeUser(nil),
|
||||
nssf.SubUserList,
|
||||
)
|
||||
nssfGroup.GET("/amf/list",
|
||||
middleware.AuthorizeUser(nil),
|
||||
nssf.AvailableList,
|
||||
)
|
||||
}
|
||||
|
||||
// 备份数据
|
||||
backupGroup := neDataGroup.Group("/backup")
|
||||
{
|
||||
@@ -452,7 +512,7 @@ func Setup(router *gin.Engine) {
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewMME.UERemove,
|
||||
)
|
||||
mmeGroup.POST("/ue/export",
|
||||
mmeGroup.GET("/ue/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewMME.UEExport,
|
||||
@@ -519,6 +579,44 @@ func Setup(router *gin.Engine) {
|
||||
controller.NewPCF.RuleInfoImport,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元CBC
|
||||
cbcGroup := neDataGroup.Group("/cbc")
|
||||
{
|
||||
cbcGroup.GET("/message/list",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewCBC.List,
|
||||
)
|
||||
cbcGroup.GET("/message/:id",
|
||||
middleware.AuthorizeUser(nil),
|
||||
controller.NewCBC.ListById,
|
||||
)
|
||||
cbcGroup.POST("/message",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.cbcMessage", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
controller.NewCBC.Insert,
|
||||
)
|
||||
cbcGroup.PUT("/message/:id",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.cbcMessage", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewCBC.Update,
|
||||
)
|
||||
cbcGroup.PUT("/message/:id/:status",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.cbcMessage", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewCBC.UpdateStatus,
|
||||
)
|
||||
cbcGroup.DELETE("/message/:id",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.cbcMessage", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewCBC.Delete,
|
||||
)
|
||||
cbcGroup.GET("/message/export",
|
||||
middleware.AuthorizeUser(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.cbcMessage", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewCBC.Export,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// InitLoad 初始参数
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -32,7 +33,7 @@ func (r Alarm) SelectByPage(query model.AlarmQuery) ([]model.Alarm, int64) {
|
||||
tx = tx.Where("pv_flag = ?", query.PvFlag)
|
||||
}
|
||||
if query.AlarmCode != "" {
|
||||
tx = tx.Where("alarm_code = ?", query.AlarmCode)
|
||||
tx = tx.Where("alarm_code like ?", fmt.Sprintf("%%%s%%", query.AlarmCode))
|
||||
}
|
||||
if query.AlarmType != "" {
|
||||
tx = tx.Where("alarm_type in (?)", strings.Split(query.AlarmType, ","))
|
||||
@@ -192,3 +193,21 @@ func (r Alarm) SelectAlarmSeqLast(neType, neId string) int64 {
|
||||
}
|
||||
return alarmSeq
|
||||
}
|
||||
|
||||
// GroupTotal 分组统计
|
||||
func (r Alarm) GroupTotal(alarmStatus string, group string, limit int) []map[string]any {
|
||||
tx := db.DB("").Model(&model.Alarm{})
|
||||
tx = tx.Select("count(*) as total", group)
|
||||
tx = tx.Where("alarm_status=?", alarmStatus)
|
||||
tx = tx.Group(group).Order("total DESC")
|
||||
// 查询数据
|
||||
var rows []map[string]any = make([]map[string]any, 0)
|
||||
if limit > 0 {
|
||||
tx = tx.Limit(limit)
|
||||
}
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ func (r AlarmLog) SelectByPage(query model.AlarmLogQuery) ([]model.AlarmLog, int
|
||||
if query.NeID != "" {
|
||||
tx = tx.Where("ne_id = ?", query.NeID)
|
||||
}
|
||||
if query.AlarmStatus != "" {
|
||||
tx = tx.Where("alarm_status = ?", query.AlarmStatus)
|
||||
}
|
||||
if query.BeginTime != 0 {
|
||||
tx = tx.Where("created_at >= ?", query.BeginTime)
|
||||
}
|
||||
|
||||
273
src/modules/network_data/repository/cbc_message.go
Normal file
273
src/modules/network_data/repository/cbc_message.go
Normal file
@@ -0,0 +1,273 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 实例化数据层 UEEvent 结构体
|
||||
var NewCBCMessage = &CBCMessage{}
|
||||
|
||||
// UEEvent UE会话事件 数据层处理
|
||||
type CBCMessage struct{}
|
||||
|
||||
// SelectCBCMessage 根据条件分页查询CB消息
|
||||
func (s *CBCMessage) SelectByPage(query model.CBCMessageQuery) ([]model.CBCMessage, int, error) {
|
||||
var msg []model.CBCMessage
|
||||
var total int64
|
||||
|
||||
tx := db.DB("").Table("cbc_message")
|
||||
|
||||
if query.NeType != "" {
|
||||
tx = tx.Where("ne_type = ?", query.NeType)
|
||||
}
|
||||
if query.NeId != "" {
|
||||
tx = tx.Where("ne_id = ?", query.NeId)
|
||||
}
|
||||
if query.EventName != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(message_json, '$.eventName') = ?", query.EventName)
|
||||
}
|
||||
if query.Status != "" {
|
||||
tx = tx.Where("status = ?", query.Status)
|
||||
}
|
||||
|
||||
var startMicro, endMicro int64
|
||||
var err error
|
||||
if query.StartTime != "" {
|
||||
startMicro, err = parseTimeToMilli(query.StartTime)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("invalid start time: %w", err)
|
||||
}
|
||||
}
|
||||
if query.EndTime != "" {
|
||||
endMicro, err = parseTimeToMilli(query.EndTime)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("invalid end time: %w", err)
|
||||
}
|
||||
}
|
||||
if startMicro > 0 && endMicro > 0 {
|
||||
tx = tx.Where("created_at BETWEEN ? AND ?", startMicro, endMicro)
|
||||
} else if startMicro > 0 {
|
||||
tx = tx.Where("created_at >= ?", startMicro)
|
||||
} else if endMicro > 0 {
|
||||
tx = tx.Where("created_at <= ?", endMicro)
|
||||
}
|
||||
|
||||
// 统计总数
|
||||
if err := tx.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count CBC message: %w", err)
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
offset := (query.PageNum - 1) * query.PageSize
|
||||
if err := tx.Limit(query.PageSize).Offset(offset).Order("created_at desc").Find(&msg).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to select CBC message: %w", err)
|
||||
}
|
||||
|
||||
return msg, int(total), nil
|
||||
}
|
||||
|
||||
// SelectCBCMessageByPage 分页查询CB消息
|
||||
// @Description 分页查询CB消息
|
||||
// @param page 页码
|
||||
// @param pageSize 每页大小
|
||||
// @return []model.CBCMessage CB消息列表
|
||||
// @return int 总记录数
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// SelectByPage(1, 10)
|
||||
// func (s *CBCMessage) SelectByPage(pageNum int, pageSize int) ([]model.CBCMessage, int, error) {
|
||||
// var tickets []model.CBCMessage
|
||||
// var total int64
|
||||
|
||||
// // 统计总数
|
||||
// if err := db.DB("").Table("cbc_message").Count(&total).Error; err != nil {
|
||||
// return nil, 0, fmt.Errorf("failed to count CBC message: %w", err)
|
||||
// }
|
||||
|
||||
// // 分页查询
|
||||
// offset := (pageNum - 1) * pageSize
|
||||
// if err := db.DB("").Table("cbc_message").
|
||||
// Limit(pageSize).
|
||||
// Offset(offset).
|
||||
// Find(&tickets).Error; err != nil {
|
||||
// return nil, 0, fmt.Errorf("failed to select CBC message: %w", err)
|
||||
// }
|
||||
|
||||
// return tickets, int(total), nil
|
||||
// }
|
||||
|
||||
// InsertCBCMessage 插入CB消息
|
||||
// @Description 插入CB消息
|
||||
// @param msg CB消息对象
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// CBCMessage.InsertCBCMessage(msg)
|
||||
func (s *CBCMessage) Insert(msg model.CBCMessage) error {
|
||||
msg.CreatedAt = time.Now().UnixMilli()
|
||||
// 这里可以使用ORM或其他方式将ticket插入到数据库中
|
||||
if err := db.DB("").Table("cbc_message").Create(&msg).Error; err != nil {
|
||||
return fmt.Errorf("failed to insert CBC message: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectCBCMessageById 根据工单ID查询CB消息
|
||||
// @Description 根据工单ID查询CB消息
|
||||
// @param id 工单ID
|
||||
// @return *model.CBCMessage CB消息对象
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// CBCMessage.SelectCBCMessageById(12345)
|
||||
func (s *CBCMessage) SelectById(id int64) (*model.CBCMessage, error) {
|
||||
var msg model.CBCMessage
|
||||
if err := db.DB("").Table("cbc_message").
|
||||
Where("id = ?", id).
|
||||
First(&msg).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to select CBC message: %w", err)
|
||||
}
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
// SelectByEventName 根据事件名称查询CB消息
|
||||
func (s *CBCMessage) SelectByEventName(eventName string) (*model.CBCMessage, error) {
|
||||
var msg model.CBCMessage
|
||||
if err := db.DB("").Table("cbc_message").
|
||||
Where("JSON_EXTRACT(message_json, '$.eventName') = ?", eventName).
|
||||
First(&msg).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
// UpdateCBCMessage 更新CB消息
|
||||
// @Description 更新CB消息
|
||||
// @param msg CB消息对象
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// mfCBCMessageService.UpdateCBCMessage(msg)
|
||||
func (s *CBCMessage) Update(id int64, messageJson json.RawMessage) (*model.CBCMessage, error) {
|
||||
var msg model.CBCMessage
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
err := db.DB("").Transaction(func(tx *gorm.DB) error {
|
||||
// 在事务中更新
|
||||
if err := tx.Table("cbc_message").
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]any{
|
||||
"message_json": messageJson,
|
||||
"updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("failed to update CBC message: %w", err)
|
||||
}
|
||||
|
||||
// 在事务中查询更新后的记录
|
||||
if err := tx.Table("cbc_message").
|
||||
Where("id = ?", id).
|
||||
First(&msg).Error; err != nil {
|
||||
return fmt.Errorf("failed to fetch updated CBC message: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
// UpdateCBCMessage 更新CB消息
|
||||
// @Description 更新CB消息
|
||||
// @param msg CB消息对象
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// UpdateCBCMessageDetail(msg)
|
||||
func (s *CBCMessage) UpdateDetail(eventName, detail string) error {
|
||||
now := time.Now().UnixMilli()
|
||||
if err := db.DB("").Table("cbc_message").
|
||||
Where("JSON_EXTRACT(message_json, '$.eventName') = ?", eventName).
|
||||
Updates(map[string]any{
|
||||
"detail": detail,
|
||||
"updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("failed to update CBC message: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteCBCMessage 删除CB消息
|
||||
// @Description 删除CB消息
|
||||
// @param id 工单ID
|
||||
// @return error 错误信息
|
||||
// @example
|
||||
// DeleteCBCMessage(12345)
|
||||
func (s *CBCMessage) Delete(id int64) error {
|
||||
// 执行删除操作
|
||||
if err := db.DB("").Table("cbc_message").
|
||||
Where("id = ?", id).
|
||||
Delete(&model.CBCMessage{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete CBC message: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateCBCMessageStatus 更新CB消息状态
|
||||
// @Description 更新CB消息状态,并根据状态变化发送相应的HTTP请求
|
||||
// @param status 新状态
|
||||
// @return error 错误信息
|
||||
func (s *CBCMessage) UpdateStatus(id int64, status model.CBCEventStatus) error {
|
||||
// 更新数据库状态
|
||||
now := time.Now().UnixMilli()
|
||||
if err := db.DB("").Table("cbc_message").
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("failed to update CBC message status: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Select 查询所有CB消息
|
||||
func (s *CBCMessage) Select(msgs *[]model.CBCMessage) error {
|
||||
if err := db.DB("").Table("cbc_message").Find(&msgs).Error; err != nil {
|
||||
return fmt.Errorf("failed to query CB messages: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectByNeId 根据网元ID查询CB消息
|
||||
func (s *CBCMessage) SelectByNeId(neId string, msgs *[]model.CBCMessage) error {
|
||||
if err := db.DB("").Table("cbc_message").Where("ne_id = ?", neId).Find(&msgs).Error; err != nil {
|
||||
return fmt.Errorf("failed to query CB messages: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 假设 query.StartTime 和 query.EndTime 是 "2006-01-02 15:04:05" 格式字符串
|
||||
func parseTimeToMilli(ts string) (int64, error) {
|
||||
if ts == "" {
|
||||
return 0, nil
|
||||
}
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05", ts, time.Local)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return t.UnixMilli(), nil
|
||||
}
|
||||
167
src/modules/network_data/repository/cdr_event.go
Normal file
167
src/modules/network_data/repository/cdr_event.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREvent 结构体
|
||||
var NewCDREvent = &CDREvent{}
|
||||
|
||||
// CDREvent CDR会话事件 数据层处理
|
||||
type CDREvent struct{}
|
||||
|
||||
// SelectByPage 分页查询集合
|
||||
func (r CDREvent) SelectByPage(neType string, query map[string]string) ([]model.CDREvent, int64) {
|
||||
// 表名
|
||||
tableName := fmt.Sprintf("cdr_event_%s", strings.ToLower(neType))
|
||||
tx := db.DB("").Table(tableName).Model(&model.CDREvent{})
|
||||
// 查询条件拼接
|
||||
if v, ok := query["rmUID"]; ok && v != "" {
|
||||
tx = tx.Where("rm_uid = ?", v)
|
||||
}
|
||||
if v, ok := query["beginTime"]; ok && v != "" {
|
||||
if len(v) == 10 {
|
||||
v = v + "000"
|
||||
}
|
||||
tx = tx.Where("created_at >= ?", v)
|
||||
}
|
||||
if v, ok := query["endTime"]; ok && v != "" {
|
||||
if len(v) == 10 {
|
||||
v = v + "000"
|
||||
}
|
||||
tx = tx.Where("created_at <= ?", v)
|
||||
}
|
||||
|
||||
// 各个网元特殊查询条件
|
||||
switch neType {
|
||||
case "SMSC":
|
||||
if v, ok := query["callerParty"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.callerParty') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
if v, ok := query["calledParty"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.calledParty') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
if v, ok := query["recordType"]; ok && v != "" {
|
||||
recordTypes := strings.Split(v, ",")
|
||||
var querytrArr []string
|
||||
for _, recordType := range recordTypes {
|
||||
querytrArr = append(querytrArr, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') = '%s'", recordType))
|
||||
}
|
||||
tx = tx.Where(fmt.Sprintf("( %s )", strings.Join(querytrArr, " OR ")))
|
||||
}
|
||||
case "SMF":
|
||||
if v, ok := query["recordType"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.recordType') = ?", v)
|
||||
}
|
||||
if v, ok := query["subscriberID"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
if v, ok := query["dnn"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.dNNID') = ?", v)
|
||||
}
|
||||
case "SGWC":
|
||||
if v, ok := query["imsi"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.servedIMSI') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
if v, ok := query["msisdn"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.servedMSISDN') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
case "IMS":
|
||||
if v, ok := query["callerParty"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.callerParty') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
if v, ok := query["calledParty"]; ok && v != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.calledParty') like ?", fmt.Sprintf("%%%s%%", v))
|
||||
}
|
||||
}
|
||||
|
||||
var total int64 = 0
|
||||
rows := []model.CDREvent{}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
tx = tx.Offset(int(pageNum * pageSize)).Limit(int(pageSize))
|
||||
|
||||
// 排序
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
sortSql := v
|
||||
if o, ok := query["sortOrder"]; ok && o != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
tx = tx.Order(sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r CDREvent) SelectByIds(neType string, ids []int64) []model.CDREvent {
|
||||
rows := []model.CDREvent{}
|
||||
if len(ids) <= 0 {
|
||||
return rows
|
||||
}
|
||||
// 表名
|
||||
tableName := fmt.Sprintf("cdr_event_%s", strings.ToLower(neType))
|
||||
tx := db.DB("").Table(tableName).Model(&model.CDREvent{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r CDREvent) DeleteByIds(neType string, ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
// 表名
|
||||
tableName := fmt.Sprintf("cdr_event_%s", strings.ToLower(neType))
|
||||
tx := db.DB("").Table(tableName).Where("id in ?", ids)
|
||||
if err := tx.Delete(&model.CDREvent{}).Error; err != nil {
|
||||
logger.Errorf("delete err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Insert 新增信息 返回新增数据ID
|
||||
func (r CDREvent) Insert(param model.CDREvent) int64 {
|
||||
if param.NeType == "" {
|
||||
return 0
|
||||
}
|
||||
if param.CreatedAt == 0 {
|
||||
param.CreatedAt = time.Now().UnixMilli()
|
||||
}
|
||||
// 表名
|
||||
tableName := fmt.Sprintf("cdr_event_%s", strings.ToLower(param.NeType))
|
||||
// 执行插入
|
||||
if err := db.DB("").Table(tableName).Create(¶m).Error; err != nil {
|
||||
logger.Errorf("insert err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return param.ID
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventIMS 结构体
|
||||
var NewCDREventIMS = &CDREventIMS{}
|
||||
|
||||
// CDREventIMS CDR会话事件 数据层处理
|
||||
type CDREventIMS struct{}
|
||||
|
||||
// SelectByPage 分页查询集合
|
||||
func (r CDREventIMS) SelectByPage(query model.CDREventIMSQuery) ([]model.CDREventIMS, int64) {
|
||||
tx := db.DB("").Model(&model.CDREventIMS{})
|
||||
// 查询条件拼接
|
||||
if query.NeType != "" {
|
||||
tx = tx.Where("ne_type = ?", query.NeType)
|
||||
}
|
||||
if query.RmUID != "" {
|
||||
tx = tx.Where("rm_uid = ?", query.RmUID)
|
||||
}
|
||||
if query.BeginTime != 0 {
|
||||
tx = tx.Where("created_at >= ?", query.BeginTime)
|
||||
}
|
||||
if query.EndTime != 0 {
|
||||
tx = tx.Where("created_at <= ?", query.EndTime)
|
||||
}
|
||||
if query.CallerParty != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.callerParty') = ?", query.CallerParty)
|
||||
}
|
||||
if query.CalledParty != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.calledParty') = ?", query.CalledParty)
|
||||
}
|
||||
|
||||
if query.RecordType != "" {
|
||||
recordTypes := strings.Split(query.RecordType, ",")
|
||||
var querytrArr []string
|
||||
for _, recordType := range recordTypes {
|
||||
querytrArr = append(querytrArr, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') = '%s'", recordType))
|
||||
}
|
||||
tx = tx.Where(fmt.Sprintf("( %s )", strings.Join(querytrArr, " OR ")))
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
var total int64 = 0
|
||||
rows := []model.CDREventIMS{}
|
||||
|
||||
// 查询数量为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 排序
|
||||
if query.SortField != "" {
|
||||
sortField := query.SortField
|
||||
if query.SortOrder == "desc" {
|
||||
sortField = sortField + " desc"
|
||||
}
|
||||
tx = tx.Order(sortField)
|
||||
}
|
||||
|
||||
// 查询数据分页
|
||||
pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize)
|
||||
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
|
||||
err := tx.Find(&rows).Error
|
||||
if err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows, total
|
||||
}
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventIMS) SelectByIds(ids []int64) []model.CDREventIMS {
|
||||
rows := []model.CDREventIMS{}
|
||||
if len(ids) <= 0 {
|
||||
return rows
|
||||
}
|
||||
tx := db.DB("").Model(&model.CDREventIMS{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventIMS) DeleteByIds(ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
tx := db.DB("").Where("id in ?", ids)
|
||||
if err := tx.Delete(&model.CDREventIMS{}).Error; err != nil {
|
||||
logger.Errorf("delete err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventSGWC 结构体
|
||||
var NewCDREventSGWC = &CDREventSGWC{}
|
||||
|
||||
// CDREventSGWC CDR会话事件 数据层处理
|
||||
type CDREventSGWC struct{}
|
||||
|
||||
// SelectByPage 分页查询集合
|
||||
func (r CDREventSGWC) SelectByPage(query model.CDREventSGWCQuery) ([]model.CDREventSGWC, int64) {
|
||||
tx := db.DB("").Model(&model.CDREventSGWC{})
|
||||
// 查询条件拼接
|
||||
if query.NeType != "" {
|
||||
tx = tx.Where("ne_type = ?", query.NeType)
|
||||
}
|
||||
if query.RmUID != "" {
|
||||
tx = tx.Where("rm_uid = ?", query.RmUID)
|
||||
}
|
||||
if query.BeginTime != 0 {
|
||||
tx = tx.Where("timestamp >= ?", query.BeginTime)
|
||||
}
|
||||
if query.EndTime != 0 {
|
||||
tx = tx.Where("timestamp <= ?", query.EndTime)
|
||||
}
|
||||
if query.IMSI != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.servedIMSI') = ?", query.IMSI)
|
||||
}
|
||||
if query.MSISDN != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.servedMSISDN') = ?", query.MSISDN)
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
var total int64 = 0
|
||||
rows := []model.CDREventSGWC{}
|
||||
|
||||
// 查询数量为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 排序
|
||||
if query.SortField != "" {
|
||||
sortField := query.SortField
|
||||
if query.SortOrder == "desc" {
|
||||
sortField = sortField + " desc"
|
||||
}
|
||||
tx = tx.Order(sortField)
|
||||
}
|
||||
|
||||
// 查询数据分页
|
||||
pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize)
|
||||
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
|
||||
err := tx.Find(&rows).Error
|
||||
if err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows, total
|
||||
}
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventSGWC) SelectByIds(ids []int64) []model.CDREventSGWC {
|
||||
rows := []model.CDREventSGWC{}
|
||||
if len(ids) <= 0 {
|
||||
return rows
|
||||
}
|
||||
tx := db.DB("").Model(&model.CDREventSGWC{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventSGWC) DeleteByIds(ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
tx := db.DB("").Where("id in ?", ids)
|
||||
if err := tx.Delete(&model.CDREventSGWC{}).Error; err != nil {
|
||||
logger.Errorf("delete err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventSMF 结构体
|
||||
var NewCDREventSMF = &CDREventSMF{}
|
||||
|
||||
// CDREventSMF CDR会话事件 数据层处理
|
||||
type CDREventSMF struct{}
|
||||
|
||||
// SelectByPage 分页查询集合
|
||||
func (r CDREventSMF) SelectByPage(query model.CDREventSMFQuery) ([]model.CDREventSMF, int64) {
|
||||
tx := db.DB("").Model(&model.CDREventSMF{})
|
||||
// 查询条件拼接
|
||||
if query.NeType != "" {
|
||||
tx = tx.Where("ne_type = ?", query.NeType)
|
||||
}
|
||||
if query.RmUID != "" {
|
||||
tx = tx.Where("rm_uid = ?", query.RmUID)
|
||||
}
|
||||
if query.BeginTime != 0 {
|
||||
tx = tx.Where("timestamp >= ?", query.BeginTime)
|
||||
}
|
||||
if query.EndTime != 0 {
|
||||
tx = tx.Where("timestamp <= ?", query.EndTime)
|
||||
}
|
||||
if query.RecordType != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.recordType') = ?", query.RecordType)
|
||||
}
|
||||
if query.SubscriberID != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?", query.SubscriberID)
|
||||
}
|
||||
if query.DNN != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.dNNID') = ?", query.DNN)
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
var total int64 = 0
|
||||
rows := []model.CDREventSMF{}
|
||||
|
||||
// 查询数量为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 排序
|
||||
if query.SortField != "" {
|
||||
sortField := query.SortField
|
||||
if query.SortOrder == "desc" {
|
||||
sortField = sortField + " desc"
|
||||
}
|
||||
tx = tx.Order(sortField)
|
||||
}
|
||||
|
||||
// 查询数据分页
|
||||
pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize)
|
||||
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
|
||||
err := tx.Find(&rows).Error
|
||||
if err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows, total
|
||||
}
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventSMF) SelectByIds(ids []int64) []model.CDREventSMF {
|
||||
rows := []model.CDREventSMF{}
|
||||
if len(ids) <= 0 {
|
||||
return rows
|
||||
}
|
||||
tx := db.DB("").Model(&model.CDREventSMF{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventSMF) DeleteByIds(ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
tx := db.DB("").Where("id in ?", ids)
|
||||
if err := tx.Delete(&model.CDREventSMF{}).Error; err != nil {
|
||||
logger.Errorf("delete err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventSMSC 结构体
|
||||
var NewCDREventSMSC = &CDREventSMSC{}
|
||||
|
||||
// CDREventSMSC CDR会话事件 数据层处理
|
||||
type CDREventSMSC struct{}
|
||||
|
||||
// SelectByPage 分页查询集合
|
||||
func (r CDREventSMSC) SelectByPage(query model.CDREventSMSCQuery) ([]model.CDREventSMSC, int64) {
|
||||
tx := db.DB("").Model(&model.CDREventSMSC{})
|
||||
// 查询条件拼接
|
||||
if query.NeType != "" {
|
||||
tx = tx.Where("ne_type = ?", query.NeType)
|
||||
}
|
||||
if query.RmUID != "" {
|
||||
tx = tx.Where("rm_uid = ?", query.RmUID)
|
||||
}
|
||||
if query.BeginTime != 0 {
|
||||
tx = tx.Where("timestamp >= ?", query.BeginTime)
|
||||
}
|
||||
if query.EndTime != 0 {
|
||||
tx = tx.Where("timestamp <= ?", query.EndTime)
|
||||
}
|
||||
if query.CallerParty != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.callerParty') = ?", query.CallerParty)
|
||||
}
|
||||
if query.CalledParty != "" {
|
||||
tx = tx.Where("JSON_EXTRACT(cdr_json, '$.calledParty') = ?", query.CalledParty)
|
||||
}
|
||||
|
||||
if query.RecordType != "" {
|
||||
recordTypes := strings.Split(query.RecordType, ",")
|
||||
var querytrArr []string
|
||||
for _, recordType := range recordTypes {
|
||||
querytrArr = append(querytrArr, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') = '%s'", recordType))
|
||||
}
|
||||
tx = tx.Where(fmt.Sprintf("( %s )", strings.Join(querytrArr, " OR ")))
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
var total int64 = 0
|
||||
rows := []model.CDREventSMSC{}
|
||||
|
||||
// 查询数量为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 排序
|
||||
if query.SortField != "" {
|
||||
sortField := query.SortField
|
||||
if query.SortOrder == "desc" {
|
||||
sortField = sortField + " desc"
|
||||
}
|
||||
tx = tx.Order(sortField)
|
||||
}
|
||||
|
||||
// 查询数据分页
|
||||
pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize)
|
||||
tx = tx.Limit(pageSize).Offset(pageSize * pageNum)
|
||||
err := tx.Find(&rows).Error
|
||||
if err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows, total
|
||||
}
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventSMSC) SelectByIds(ids []int64) []model.CDREventSMSC {
|
||||
rows := []model.CDREventSMSC{}
|
||||
if len(ids) <= 0 {
|
||||
return rows
|
||||
}
|
||||
tx := db.DB("").Model(&model.CDREventSMSC{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventSMSC) DeleteByIds(ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
tx := db.DB("").Where("id in ?", ids)
|
||||
if err := tx.Delete(&model.CDREventSMSC{}).Error; err != nil {
|
||||
logger.Errorf("delete err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
@@ -17,7 +17,7 @@ var NewKpiCReport = &KpiCReport{}
|
||||
type KpiCReport struct{}
|
||||
|
||||
// SelectGoldKPI 通过网元指标数据信息
|
||||
func (r KpiCReport) SelectKPI(query model.KPIQuery) []model.KpiCReport {
|
||||
func (r KpiCReport) SelectKPI(query model.KPICQuery) []model.KpiCReport {
|
||||
rows := []model.KpiCReport{}
|
||||
if query.NeType == "" {
|
||||
return rows
|
||||
@@ -87,3 +87,132 @@ func (r KpiCReport) SelectKPITitle(neType string) []model.KpiCTitle {
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// TitleLastKPIId 查询指标标题最后kpiid
|
||||
func (r KpiCReport) TitleLastKPIId(neType string) string {
|
||||
tx := db.DB("").Model(&model.KpiCTitle{})
|
||||
tx = tx.Where("ne_type=?", neType)
|
||||
tx = tx.Select("kpi_id").Order("kpi_id DESC")
|
||||
// 查询数据
|
||||
var kpiId string = ""
|
||||
if err := tx.Limit(1).Find(&kpiId).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return kpiId
|
||||
}
|
||||
return kpiId
|
||||
}
|
||||
|
||||
// SelectByPageTitle 分页查询集合
|
||||
func (r KpiCReport) TitleSelectByPage(query map[string]string) ([]model.KpiCTitle, int64) {
|
||||
tx := db.DB("").Model(&model.KpiCTitle{})
|
||||
// 查询条件拼接
|
||||
if v, ok := query["neType"]; ok && v != "" {
|
||||
tx = tx.Where("ne_type = ?", v)
|
||||
}
|
||||
if v, ok := query["status"]; ok && v != "" {
|
||||
tx = tx.Where("status = ?", v)
|
||||
} else {
|
||||
tx = tx.Where("status != ?", "2")
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
var total int64 = 0
|
||||
rows := []model.KpiCTitle{}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"])
|
||||
tx = tx.Offset(int(pageNum * pageSize)).Limit(int(pageSize))
|
||||
|
||||
// 排序
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
sortSql := v
|
||||
if o, ok := query["sortOrder"]; ok && o != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
tx = tx.Order(sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// TitleSelect 网元对应的指标名称
|
||||
func (r KpiCReport) TitleSelect(param model.KpiCTitle) []model.KpiCTitle {
|
||||
tx := db.DB("").Model(&model.KpiCTitle{})
|
||||
// 构建查询条件
|
||||
if param.NeType != "" {
|
||||
tx = tx.Where("ne_type =?", param.NeType)
|
||||
}
|
||||
if param.Title != "" {
|
||||
tx = tx.Where("title = ?", param.Title)
|
||||
}
|
||||
if param.Status != "" {
|
||||
tx = tx.Where("status = ?", param.Status)
|
||||
}
|
||||
// 查询数据
|
||||
rows := []model.KpiCTitle{}
|
||||
if err := tx.Find(&rows).Error; err != nil {
|
||||
logger.Errorf("query find err => %v", err.Error())
|
||||
return rows
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// TitleInsert 新增信息
|
||||
func (r KpiCReport) TitleInsert(param model.KpiCTitle) int64 {
|
||||
if param.CreatedBy != "" {
|
||||
param.UpdatedAt = time.Now().UnixMilli()
|
||||
}
|
||||
param.Status = "1"
|
||||
tx := db.DB("").Create(¶m)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
return param.ID
|
||||
}
|
||||
|
||||
// TitleUpdate 修改信息
|
||||
func (r KpiCReport) TitleUpdate(param model.KpiCTitle) int64 {
|
||||
if param.ID <= 0 {
|
||||
return 0
|
||||
}
|
||||
param.UpdatedAt = time.Now().UnixMilli()
|
||||
tx := db.DB("").Model(&model.KpiCTitle{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id = ?", param.ID)
|
||||
tx = tx.Omit("id", "created_by")
|
||||
// 执行更新
|
||||
if err := tx.Updates(param).Error; err != nil {
|
||||
logger.Errorf("update err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// TitleDeleteByIds 批量删除信息
|
||||
func (r KpiCReport) TitleDeleteByIds(ids []int64) int64 {
|
||||
if len(ids) <= 0 {
|
||||
return 0
|
||||
}
|
||||
tx := db.DB("").Model(&model.KpiCTitle{})
|
||||
// 构建查询条件
|
||||
tx = tx.Where("id in ?", ids)
|
||||
if err := tx.Update("status", 2).Error; err != nil {
|
||||
logger.Errorf("update err => %v", err.Error())
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"be.ems/src/framework/database/db"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
@@ -36,14 +35,14 @@ func (r NBState) SelectByPage(query model.NBStateQuery) ([]model.NBState, int64)
|
||||
if len(startTime) == 10 {
|
||||
startTime = startTime + "000"
|
||||
}
|
||||
tx = tx.Where("time >= ?", date.ParseDateToStr(startTime, date.YYYY_MM_DDTHH_MM_SSZ))
|
||||
tx = tx.Where("create_time >= ?", startTime)
|
||||
}
|
||||
if query.EndTime != "" {
|
||||
endTime := query.EndTime
|
||||
if len(endTime) == 10 {
|
||||
endTime = endTime + "999"
|
||||
}
|
||||
tx = tx.Where("time <= ?", date.ParseDateToStr(endTime, date.YYYY_MM_DDTHH_MM_SSZ))
|
||||
tx = tx.Where("create_time <= ?", endTime)
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
|
||||
@@ -27,7 +27,7 @@ func (r *UDMAuthUser) ClearAndInsert(neId string, uArr []model.UDMAuthUser) int6
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *UDMAuthUser) SelectPage(query map[string]string) (int64, []model.UDMAuthUser) {
|
||||
func (r *UDMAuthUser) SelectPage(query map[string]string) ([]model.UDMAuthUser, int64) {
|
||||
tx := db.DB("").Model(&model.UDMAuthUser{})
|
||||
// 查询条件拼接
|
||||
if v, ok := query["imsi"]; ok && v != "" {
|
||||
@@ -48,7 +48,7 @@ func (r *UDMAuthUser) SelectPage(query map[string]string) (int64, []model.UDMAut
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
if err := tx.Count(&total).Error; err != nil || total <= 0 {
|
||||
return total, rows
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// 分页
|
||||
@@ -73,7 +73,7 @@ func (r *UDMAuthUser) SelectPage(query map[string]string) (int64, []model.UDMAut
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
return total, rows
|
||||
return rows, total
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user