marge: 合并11.2版本
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
|||||||
networkelement "be.ems/src/modules/network_element"
|
networkelement "be.ems/src/modules/network_element"
|
||||||
practicalTraining "be.ems/src/modules/practical_training"
|
practicalTraining "be.ems/src/modules/practical_training"
|
||||||
"be.ems/src/modules/system"
|
"be.ems/src/modules/system"
|
||||||
|
"be.ems/src/modules/tool"
|
||||||
"be.ems/src/modules/trace"
|
"be.ems/src/modules/trace"
|
||||||
"be.ems/src/modules/ws"
|
"be.ems/src/modules/ws"
|
||||||
|
|
||||||
@@ -98,7 +99,10 @@ func initAppEngine() *gin.Engine {
|
|||||||
// 初始全局默认
|
// 初始全局默认
|
||||||
func initDefeat(app *gin.Engine) {
|
func initDefeat(app *gin.Engine) {
|
||||||
// 全局中间件
|
// 全局中间件
|
||||||
app.Use(errorcatch.ErrorCatch(), middleware.Report(), middleware.Cors(), security.Security())
|
if config.Env() == "local" {
|
||||||
|
app.Use(middleware.Report())
|
||||||
|
}
|
||||||
|
app.Use(errorcatch.ErrorCatch(), middleware.Cors(), security.Security())
|
||||||
|
|
||||||
// 静态目录-静态资源
|
// 静态目录-静态资源
|
||||||
if v := config.Get("staticFile.default"); v != nil {
|
if v := config.Get("staticFile.default"); v != nil {
|
||||||
@@ -143,6 +147,8 @@ func initModulesRoute(app *gin.Engine) {
|
|||||||
trace.Setup(app)
|
trace.Setup(app)
|
||||||
// 图表模块
|
// 图表模块
|
||||||
chart.Setup(app)
|
chart.Setup(app)
|
||||||
|
// 工具模块
|
||||||
|
tool.Setup(app)
|
||||||
// ws 模块
|
// ws 模块
|
||||||
ws.Setup(app)
|
ws.Setup(app)
|
||||||
// 调度任务模块--暂无接口
|
// 调度任务模块--暂无接口
|
||||||
|
|||||||
Binary file not shown.
BIN
src/assets/dependency/iperf/rpm/iperf-2.1.6-2.el8.aarch64.rpm
Normal file
BIN
src/assets/dependency/iperf/rpm/iperf-2.1.6-2.el8.aarch64.rpm
Normal file
Binary file not shown.
BIN
src/assets/dependency/iperf/rpm/iperf3-3.6-6.ky10.aarch64.rpm
Normal file
BIN
src/assets/dependency/iperf/rpm/iperf3-3.6-6.ky10.aarch64.rpm
Normal file
Binary file not shown.
BIN
src/assets/dependency/iperf3/deb/iperf3_3.1.3-1_amd64.deb
Normal file
BIN
src/assets/dependency/iperf3/deb/iperf3_3.1.3-1_amd64.deb
Normal file
Binary file not shown.
BIN
src/assets/dependency/iperf3/deb/libiperf0_3.1.3-1_amd64.deb
Normal file
BIN
src/assets/dependency/iperf3/deb/libiperf0_3.1.3-1_amd64.deb
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/dependency/iperf3/rpm/iperf3-3.6-6.ky10.aarch64.rpm
Normal file
BIN
src/assets/dependency/iperf3/rpm/iperf3-3.6-6.ky10.aarch64.rpm
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
# 项目信息
|
# 项目信息
|
||||||
framework:
|
framework:
|
||||||
name: "CN EMS"
|
name: "OMC"
|
||||||
version: "2.2408.1"
|
version: "2.2411.2"
|
||||||
|
|
||||||
# 应用服务配置
|
# 应用服务配置
|
||||||
server:
|
server:
|
||||||
@@ -172,6 +172,13 @@ redis:
|
|||||||
# 多个数据源时可以用这个指定默认的数据源
|
# 多个数据源时可以用这个指定默认的数据源
|
||||||
defaultDataSourceName: "default"
|
defaultDataSourceName: "default"
|
||||||
|
|
||||||
|
# AES 加密
|
||||||
|
aes:
|
||||||
|
# 接口密钥
|
||||||
|
apiKey: "T9ox2DCzpLfJIPzkH9pKhsOTMOEMJcFv"
|
||||||
|
# 网元主机密钥
|
||||||
|
hostKey: "AGT66VfY4SMaiT97a7df0aef1704d5c5"
|
||||||
|
|
||||||
# 用户配置
|
# 用户配置
|
||||||
user:
|
user:
|
||||||
# 密码
|
# 密码
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# 应用服务配置
|
# 应用服务配置
|
||||||
server:
|
server:
|
||||||
port: 3040
|
port: 33040
|
||||||
proxy: true
|
proxy: true
|
||||||
|
|
||||||
# 日志
|
# 日志
|
||||||
logger:
|
logger:
|
||||||
fileDir: "C:/usr/local/omc/log"
|
fileDir: "C:/var/log"
|
||||||
level: 0 # 输出最低等级
|
level: 0 # 输出最低等级
|
||||||
|
|
||||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||||
@@ -28,11 +28,11 @@ gorm:
|
|||||||
dataSource:
|
dataSource:
|
||||||
default:
|
default:
|
||||||
type: "mysql"
|
type: "mysql"
|
||||||
host: "192.168.0.229"
|
host: "127.0.0.1"
|
||||||
port: 33066
|
port: 33066
|
||||||
username: "root"
|
username: "root"
|
||||||
password: "1000omc@kp!"
|
password: "1000omc@kp!"
|
||||||
database: "omc_db_dev"
|
database: "omc_db"
|
||||||
logging: true
|
logging: true
|
||||||
|
|
||||||
# Redis 缓存数据,数据源声明全小写
|
# Redis 缓存数据,数据源声明全小写
|
||||||
@@ -41,14 +41,14 @@ redis:
|
|||||||
# OMC系统使用库
|
# OMC系统使用库
|
||||||
default:
|
default:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "192.168.0.229" # Redis host
|
host: "127.0.0.1" # Redis host
|
||||||
password: ""
|
password: "helloearth"
|
||||||
db: 10 # Redis db_num
|
db: 10 # Redis db_num
|
||||||
# UDM网元用户库
|
# UDM网元用户库
|
||||||
udmuser:
|
udmuser:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "192.168.0.229"
|
host: "127.0.0.1"
|
||||||
password: ""
|
password: "helloearth"
|
||||||
db: 0 # Redis db_num
|
db: 0 # Redis db_num
|
||||||
# 多个数据源时可以用这个指定默认的数据源
|
# 多个数据源时可以用这个指定默认的数据源
|
||||||
defaultDataSourceName: "default"
|
defaultDataSourceName: "default"
|
||||||
|
|||||||
@@ -8,8 +8,13 @@ const (
|
|||||||
// 响应-msg错误失败
|
// 响应-msg错误失败
|
||||||
MSG_ERROR = "error"
|
MSG_ERROR = "error"
|
||||||
|
|
||||||
// 响应-msg正常成功
|
|
||||||
CODE_SUCCESS = 1
|
|
||||||
// 响应-code正常成功
|
// 响应-code正常成功
|
||||||
|
CODE_SUCCESS = 1
|
||||||
|
// 响应-msg正常成功
|
||||||
MSG_SUCCESS = "success"
|
MSG_SUCCESS = "success"
|
||||||
|
|
||||||
|
// 响应-code加密数据
|
||||||
|
CODE_ENCRYPT = 2
|
||||||
|
// 响应-msg加密数据
|
||||||
|
MSG_ENCRYPT = "encrypt"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ func DefaultDB() *gorm.DB {
|
|||||||
|
|
||||||
// 获取数据源
|
// 获取数据源
|
||||||
func DB(source string) *gorm.DB {
|
func DB(source string) *gorm.DB {
|
||||||
|
if source == "" {
|
||||||
|
source = config.Get("gorm.defaultDataSourceName").(string)
|
||||||
|
}
|
||||||
return dbMap[source]
|
return dbMap[source]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ func ErrorCatch() gin.HandlerFunc {
|
|||||||
|
|
||||||
// 返回错误响应给客户端
|
// 返回错误响应给客户端
|
||||||
if config.Env() == "prod" {
|
if config.Env() == "prod" {
|
||||||
c.JSON(500, result.ErrMsg("Internal Server Errors"))
|
c.JSON(500, result.CodeMsg(500, "Internal Server Errors"))
|
||||||
} else {
|
} else {
|
||||||
// 通过实现 error 接口的 Error() 方法自定义错误类型进行捕获
|
// 通过实现 error 接口的 Error() 方法自定义错误类型进行捕获
|
||||||
switch v := err.(type) {
|
switch v := err.(type) {
|
||||||
case error:
|
case error:
|
||||||
c.JSON(500, result.ErrMsg(v.Error()))
|
c.JSON(500, result.CodeMsg(500, v.Error()))
|
||||||
default:
|
default:
|
||||||
c.JSON(500, result.ErrMsg(fmt.Sprint(err)))
|
c.JSON(500, result.CodeMsg(500, fmt.Sprint(err)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func ClearLocaleData() {
|
|||||||
// LoadLocaleData 加载国际化数据
|
// LoadLocaleData 加载国际化数据
|
||||||
func LoadLocaleData(language string) []localeItem {
|
func LoadLocaleData(language string) []localeItem {
|
||||||
dictType := fmt.Sprintf("i18n_%s", language)
|
dictType := fmt.Sprintf("i18n_%s", language)
|
||||||
dictTypeList := systemService.NewSysDictTypeImpl.DictDataCache(dictType)
|
dictTypeList := systemService.NewSysDictType.DictDataCache(dictType)
|
||||||
localeData := []localeItem{}
|
localeData := []localeItem{}
|
||||||
for _, v := range dictTypeList {
|
for _, v := range dictTypeList {
|
||||||
localeData = append(localeData, localeItem{
|
localeData = append(localeData, localeItem{
|
||||||
@@ -58,7 +58,7 @@ func UpdateKeyValue(language, key, value string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新字典数据
|
// 更新字典数据
|
||||||
sysDictDataService := systemService.NewSysDictDataImpl
|
sysDictDataService := systemService.NewSysDictData
|
||||||
item := sysDictDataService.SelectDictDataByCode(code)
|
item := sysDictDataService.SelectDictDataByCode(code)
|
||||||
if item.DictCode == code && item.DictLabel == key {
|
if item.DictCode == code && item.DictLabel == key {
|
||||||
item.DictValue = value
|
item.DictValue = value
|
||||||
|
|||||||
151
src/framework/middleware/crypto_api.go
Normal file
151
src/framework/middleware/crypto_api.go
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/config"
|
||||||
|
constResult "be.ems/src/framework/constants/result"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/crypto"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CryptoApi 接口加解密
|
||||||
|
//
|
||||||
|
// 示例参数:middleware.CryptoApi(true, true)
|
||||||
|
//
|
||||||
|
// 参数表示:对请求解密,对响应加密
|
||||||
|
//
|
||||||
|
// 请将中间件放在最前置,对请求优先处理
|
||||||
|
func CryptoApi(requestDecrypt, responseEncrypt bool) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// 请求解密时对请求data注入
|
||||||
|
if requestDecrypt {
|
||||||
|
method := c.Request.Method
|
||||||
|
contentType := c.ContentType()
|
||||||
|
contentDe := ""
|
||||||
|
// 请求参数解析
|
||||||
|
if method == "GET" {
|
||||||
|
contentDe = c.Query("data")
|
||||||
|
} else if contentType == gin.MIMEJSON {
|
||||||
|
var body struct {
|
||||||
|
Data string `json:"data" binding:"required"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&body); err == nil {
|
||||||
|
contentDe = body.Data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否存在data字段数据
|
||||||
|
if contentDe == "" {
|
||||||
|
c.JSON(400, map[string]any{
|
||||||
|
"code": constResult.CODE_ERROR,
|
||||||
|
"msg": "decrypt not found field data",
|
||||||
|
})
|
||||||
|
c.Abort() // 停止执行后续的处理函数
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密-原数据加密前含16位长度iv
|
||||||
|
apiKey := config.Get("aes.apiKey").(string)
|
||||||
|
dataBodyStr, err := crypto.AESDecryptBase64(contentDe, apiKey)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CryptoApi decrypt err => %v", err)
|
||||||
|
c.JSON(400, map[string]any{
|
||||||
|
"code": constResult.CODE_ERROR,
|
||||||
|
"msg": "decrypted data could not be parsed",
|
||||||
|
})
|
||||||
|
c.Abort() // 停止执行后续的处理函数
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分配回请求体
|
||||||
|
if method == "GET" {
|
||||||
|
var urlParams map[string]any
|
||||||
|
json.Unmarshal([]byte(dataBodyStr), &urlParams)
|
||||||
|
rawQuery := []string{}
|
||||||
|
for k, v := range urlParams {
|
||||||
|
rawQuery = append(rawQuery, fmt.Sprintf("%s=%v", k, v))
|
||||||
|
}
|
||||||
|
c.Request.URL.RawQuery = strings.Join(rawQuery, "&")
|
||||||
|
} else if contentType == gin.MIMEJSON {
|
||||||
|
c.Request.Body = io.NopCloser(bytes.NewBuffer([]byte(dataBodyStr)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应加密时替换原有的响应体
|
||||||
|
var rbw *replaceBodyWriter
|
||||||
|
if responseEncrypt {
|
||||||
|
rbw = &replaceBodyWriter{
|
||||||
|
body: &bytes.Buffer{},
|
||||||
|
ResponseWriter: c.Writer,
|
||||||
|
}
|
||||||
|
c.Writer = rbw
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用下一个处理程序
|
||||||
|
c.Next()
|
||||||
|
|
||||||
|
// 响应加密时对响应data数据进行加密
|
||||||
|
if responseEncrypt {
|
||||||
|
// 满足成功并带数据的响应进行加密
|
||||||
|
if c.Writer.Status() == 200 {
|
||||||
|
var resBody map[string]any
|
||||||
|
json.Unmarshal(rbw.body.Bytes(), &resBody)
|
||||||
|
codeV, codeOk := resBody["code"]
|
||||||
|
dataV, dataOk := resBody["data"]
|
||||||
|
if codeOk && dataOk {
|
||||||
|
if parse.Number(codeV) == constResult.CODE_SUCCESS {
|
||||||
|
byteBodyData, _ := json.Marshal(dataV)
|
||||||
|
// 加密-原数据头加入标记16位长度iv终止符
|
||||||
|
apiKey := config.Get("aes.apiKey").(string)
|
||||||
|
contentEn, err := crypto.AESEncryptBase64("=:)"+string(byteBodyData), apiKey)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CryptoApi encrypt err => %v", err)
|
||||||
|
rbw.ReplaceWrite([]byte(fmt.Sprintf(`{"code":"%d","msg":"encrypt err"}`, constResult.CODE_ERROR)))
|
||||||
|
} else {
|
||||||
|
// 响应加密
|
||||||
|
byteBody, _ := json.Marshal(map[string]any{
|
||||||
|
"code": constResult.CODE_ENCRYPT,
|
||||||
|
"msg": constResult.MSG_ENCRYPT,
|
||||||
|
"data": contentEn,
|
||||||
|
})
|
||||||
|
rbw.ReplaceWrite(byteBody)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rbw.ReplaceWrite(nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rbw.ReplaceWrite(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaceBodyWriter 替换默认的响应体
|
||||||
|
type replaceBodyWriter struct {
|
||||||
|
gin.ResponseWriter
|
||||||
|
body *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 写入响应体
|
||||||
|
func (r replaceBodyWriter) Write(b []byte) (int, error) {
|
||||||
|
return r.body.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWrite 替换响应体
|
||||||
|
func (r *replaceBodyWriter) ReplaceWrite(b []byte) (int, error) {
|
||||||
|
if b == nil {
|
||||||
|
return r.ResponseWriter.Write(r.body.Bytes())
|
||||||
|
}
|
||||||
|
r.body = &bytes.Buffer{}
|
||||||
|
r.body.Write(b)
|
||||||
|
return r.ResponseWriter.Write(r.body.Bytes())
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
@@ -18,6 +19,10 @@ func Report() gin.HandlerFunc {
|
|||||||
|
|
||||||
// 计算请求处理时间,并打印日志
|
// 计算请求处理时间,并打印日志
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
logger.Infof("%s %s report end=> %v", c.Request.Method, c.Request.RequestURI, duration)
|
// logger.Infof("%s %s report end=> %v", c.Request.Method, c.Request.RequestURI, duration)
|
||||||
|
// 获取当前活跃的goroutine数量
|
||||||
|
num := runtime.NumGoroutine()
|
||||||
|
// logger.Infof("当前活跃的goroutine数量 %d\n", num)
|
||||||
|
logger.Infof("\n访问接口 %s %s\n总耗时 %v\n当前活跃的goroutine数量 %d\n", c.Request.Method, c.Request.RequestURI, duration, num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/framework/redis/conn.go
Normal file
79
src/framework/redis/conn.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConnRedis 连接redis对象
|
||||||
|
type ConnRedis struct {
|
||||||
|
Addr string `json:"addr"` // 地址
|
||||||
|
Port int64 `json:"port"` // 端口
|
||||||
|
User string `json:"user"` // 用户名
|
||||||
|
Password string `json:"password"` // 认证密码
|
||||||
|
Database int `json:"database"` // 数据库名称
|
||||||
|
|
||||||
|
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
||||||
|
|
||||||
|
Client *redis.Client `json:"client"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient 创建Redis客户端
|
||||||
|
func (c *ConnRedis) NewClient() (*ConnRedis, error) {
|
||||||
|
// IPV6地址协议
|
||||||
|
if strings.Contains(c.Addr, ":") {
|
||||||
|
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||||
|
}
|
||||||
|
addr := fmt.Sprintf("%s:%d", c.Addr, c.Port)
|
||||||
|
|
||||||
|
// 默认等待5s
|
||||||
|
if c.DialTimeOut == 0 {
|
||||||
|
c.DialTimeOut = 5 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接
|
||||||
|
rdb := redis.NewClient(&redis.Options{
|
||||||
|
Addr: addr,
|
||||||
|
// Username: c.User,
|
||||||
|
Password: c.Password,
|
||||||
|
DB: c.Database,
|
||||||
|
DialTimeout: c.DialTimeOut,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试数据库连接
|
||||||
|
if _, err := rdb.Ping(context.Background()).Result(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Client = rdb
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭当前Redis客户端
|
||||||
|
func (c *ConnRedis) Close() {
|
||||||
|
if c.Client != nil {
|
||||||
|
c.Client.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCMD 执行单次命令 "GET key"
|
||||||
|
func (c *ConnRedis) RunCMD(cmd string) (any, error) {
|
||||||
|
if c.Client == nil {
|
||||||
|
return "", fmt.Errorf("redis client not connected")
|
||||||
|
}
|
||||||
|
// 写入命令
|
||||||
|
cmdArr := strings.Fields(cmd)
|
||||||
|
if len(cmdArr) == 0 {
|
||||||
|
return "", fmt.Errorf("redis command is empty")
|
||||||
|
}
|
||||||
|
conn := *c.Client
|
||||||
|
args := make([]any, 0)
|
||||||
|
for _, v := range cmdArr {
|
||||||
|
args = append(args, v)
|
||||||
|
}
|
||||||
|
return conn.Do(context.Background(), args...).Result()
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/config"
|
"be.ems/src/framework/config"
|
||||||
@@ -30,6 +31,15 @@ if tonumber(current) == 1 then
|
|||||||
end
|
end
|
||||||
return tonumber(current);`)
|
return tonumber(current);`)
|
||||||
|
|
||||||
|
// 连接Redis实例
|
||||||
|
func ConnectPush(source string, rdb *redis.Client) {
|
||||||
|
if rdb == nil {
|
||||||
|
delete(rdbMap, source)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rdbMap[source] = rdb
|
||||||
|
}
|
||||||
|
|
||||||
// 连接Redis实例
|
// 连接Redis实例
|
||||||
func Connect() {
|
func Connect() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -170,31 +180,22 @@ func GetExpire(source string, key string) (float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获得缓存数据的key列表
|
// 获得缓存数据的key列表
|
||||||
func GetKeys(source string, pattern string) ([]string, error) {
|
func GetKeys(source string, match string) ([]string, error) {
|
||||||
// 数据源
|
// 数据源
|
||||||
rdb := DefaultRDB()
|
rdb := DefaultRDB()
|
||||||
if source != "" {
|
if source != "" {
|
||||||
rdb = RDB(source)
|
rdb = RDB(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化变量
|
keys := make([]string, 0)
|
||||||
var keys []string
|
|
||||||
var cursor uint64 = 0
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// 循环遍历获取匹配的键
|
iter := rdb.Scan(ctx, 0, match, 1000).Iterator()
|
||||||
for {
|
if err := iter.Err(); err != nil {
|
||||||
// 使用 SCAN 命令获取匹配的键
|
|
||||||
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 100).Result()
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Failed to scan keys: %v", err)
|
logger.Errorf("Failed to scan keys: %v", err)
|
||||||
return keys, err
|
return keys, err
|
||||||
}
|
}
|
||||||
cursor = nextCursor
|
for iter.Next(ctx) {
|
||||||
keys = append(keys, batchKeys...)
|
keys = append(keys, iter.Val())
|
||||||
// 当 cursor 为 0,表示遍历完成
|
|
||||||
if cursor == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return keys, nil
|
return keys, nil
|
||||||
}
|
}
|
||||||
@@ -252,6 +253,84 @@ func GetHash(source, key string) (map[string]string, error) {
|
|||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量获得缓存数据 [key]result
|
||||||
|
func GetHashBatch(source string, keys []string) (map[string]map[string]string, error) {
|
||||||
|
result := make(map[string]map[string]string, 0)
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return result, fmt.Errorf("not keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据源
|
||||||
|
rdb := DefaultRDB()
|
||||||
|
if source != "" {
|
||||||
|
rdb = RDB(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个有限的并发控制信号通道
|
||||||
|
sem := make(chan struct{}, 10)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var mt sync.Mutex
|
||||||
|
batchSize := 1000
|
||||||
|
total := len(keys)
|
||||||
|
if total < batchSize {
|
||||||
|
batchSize = total
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < total; i += batchSize {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(start int) {
|
||||||
|
ctx := context.Background()
|
||||||
|
// 并发控制,限制同时执行的 Goroutine 数量
|
||||||
|
sem <- struct{}{}
|
||||||
|
defer func() {
|
||||||
|
<-sem
|
||||||
|
ctx.Done()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
pipe := rdb.Pipeline()
|
||||||
|
for _, key := range keys[start : start+batchSize] {
|
||||||
|
pipe.HGetAll(ctx, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds, err := pipe.Exec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Failed to get hash batch exec err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将结果添加到 result map 并发访问
|
||||||
|
mt.Lock()
|
||||||
|
defer mt.Unlock()
|
||||||
|
|
||||||
|
// 处理命令结果
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
if cmd.Err() != nil {
|
||||||
|
logger.Errorf("Failed to get hash batch cmds err: %v", cmd.Err())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 将结果转换为 *redis.StringStringMapCmd 类型
|
||||||
|
rcmd, ok := cmd.(*redis.MapStringStringCmd)
|
||||||
|
if !ok {
|
||||||
|
logger.Errorf("Failed to get hash batch type err: %v", cmd.Err())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key := "-"
|
||||||
|
args := rcmd.Args()
|
||||||
|
if len(args) > 0 {
|
||||||
|
key = fmt.Sprint(args[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
result[key] = rcmd.Val()
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 判断是否存在
|
// 判断是否存在
|
||||||
func Has(source string, keys ...string) (bool, error) {
|
func Has(source string, keys ...string) (bool, error) {
|
||||||
// 数据源
|
// 数据源
|
||||||
|
|||||||
96
src/framework/socket/tcp_client.go
Normal file
96
src/framework/socket/tcp_client.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
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 := fmt.Sprintf("%s:%d", c.Addr, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/framework/socket/tcp_server.go
Normal file
77
src/framework/socket/tcp_server.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/framework/socket/udp_client.go
Normal file
96
src/framework/socket/udp_client.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
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 := fmt.Sprintf("%s:%d", c.Addr, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/framework/socket/udp_server.go
Normal file
67
src/framework/socket/udp_server.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.StopChan:
|
||||||
|
callback(nil, fmt.Errorf("udp service not created"))
|
||||||
|
default:
|
||||||
|
callback(s.Conn, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,9 +52,6 @@ func (c *ConnTelnet) NewClient() (*ConnTelnet, error) {
|
|||||||
|
|
||||||
c.Client = &client
|
c.Client = &client
|
||||||
|
|
||||||
// 调整窗口大小 (120 列 x 128 行)
|
|
||||||
requestPty(c.Client, 120, 128)
|
|
||||||
|
|
||||||
// 排空连接登录的信息
|
// 排空连接登录的信息
|
||||||
c.RunCMD("")
|
c.RunCMD("")
|
||||||
return c, nil
|
return c, nil
|
||||||
@@ -111,20 +108,9 @@ func (c *ConnTelnet) NewClientSession(cols, rows int) (*TelnetClientSession, err
|
|||||||
if c.Client == nil {
|
if c.Client == nil {
|
||||||
return nil, fmt.Errorf("telnet client not connected")
|
return nil, fmt.Errorf("telnet client not connected")
|
||||||
}
|
}
|
||||||
requestPty(c.Client, cols, rows)
|
s := &TelnetClientSession{
|
||||||
return &TelnetClientSession{
|
|
||||||
Client: *c.Client,
|
Client: *c.Client,
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
// s.WindowChange(cols, rows)
|
||||||
// requestPty 调整终端窗口大小
|
return s, nil
|
||||||
func requestPty(client *net.Conn, cols, rows int) error {
|
|
||||||
if client == nil {
|
|
||||||
return fmt.Errorf("telnet client not connected")
|
|
||||||
}
|
|
||||||
conn := *client
|
|
||||||
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
|
||||||
conn.Write([]byte{255, 251, 31})
|
|
||||||
conn.Write([]byte{255, 250, 31, byte(cols >> 8), byte(cols & 0xFF), byte(rows >> 8), byte(rows & 0xFF), 255, 240})
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,17 @@ func (s *TelnetClientSession) Close() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
|
||||||
|
func (s *TelnetClientSession) WindowChange(h, w int) error {
|
||||||
|
if s.Client == nil {
|
||||||
|
return fmt.Errorf("client is nil to content write failed")
|
||||||
|
}
|
||||||
|
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||||
|
s.Client.Write([]byte{255, 251, 31})
|
||||||
|
s.Client.Write([]byte{255, 250, 31, byte(w >> 8), byte(w & 0xFF), byte(h >> 8), byte(h & 0xFF), 255, 240})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Write 写入命令 不带回车(\n)也会执行根据客户端情况
|
// Write 写入命令 不带回车(\n)也会执行根据客户端情况
|
||||||
func (s *TelnetClientSession) Write(cmd string) (int, error) {
|
func (s *TelnetClientSession) Write(cmd string) (int, error) {
|
||||||
if s.Client == nil {
|
if s.Client == nil {
|
||||||
@@ -36,11 +47,11 @@ func (s *TelnetClientSession) Read() []byte {
|
|||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
// 设置读取超时时间为100毫秒
|
// 设置读取超时时间为100毫秒
|
||||||
s.Client.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
s.Client.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||||
_, err := s.Client.Read(buf)
|
n, err := s.Client.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
return buf
|
return buf[:n]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CombinedOutput 发送命令带结果返回
|
// CombinedOutput 发送命令带结果返回
|
||||||
@@ -10,12 +10,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StringEncryptByAES 字符串AES加密
|
// AESEncryptBase64 AES加密转Base64字符串
|
||||||
func StringEncryptByAES(text string) (string, error) {
|
func AESEncryptBase64(text, key string) (string, error) {
|
||||||
if len(text) == 0 {
|
if len(text) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
xpass, err := aesEncryptWithSalt([]byte(text))
|
xpass, err := AESEncrypt([]byte(text), []byte(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -23,8 +23,8 @@ func StringEncryptByAES(text string) (string, error) {
|
|||||||
return pass64, nil
|
return pass64, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringDecryptByAES 字符串AES解密
|
// AESDecryptBase64 AES解密解Base64字符串
|
||||||
func StringDecryptByAES(text string) (string, error) {
|
func AESDecryptBase64(text, key string) (string, error) {
|
||||||
if len(text) == 0 {
|
if len(text) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@@ -32,21 +32,16 @@ func StringDecryptByAES(text string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
tpass, err := AESDecrypt(bytesPass, []byte(key))
|
||||||
tpass, err := aesDecryptWithSalt(bytesPass)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return string(tpass), nil
|
return string(tpass), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// aesKey 字符串AES加解密密钥
|
// AESEncrypt AES加密
|
||||||
const aesKey = "AGT66VfY4SMaiT97a7df0aef1704d5c5"
|
func AESEncrypt(plaintext, aeskey []byte) ([]byte, error) {
|
||||||
|
block, err := aes.NewCipher(aeskey)
|
||||||
// const aesKey = "AGT66VfY4SMaiT97"
|
|
||||||
// aesEncryptWithSalt AES加密
|
|
||||||
func aesEncryptWithSalt(plaintext []byte) ([]byte, error) {
|
|
||||||
block, err := aes.NewCipher([]byte(aesKey))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -68,8 +63,8 @@ func aesEncryptWithSalt(plaintext []byte) ([]byte, error) {
|
|||||||
return ciphertext, nil
|
return ciphertext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// aesDecryptWithSalt AES解密
|
// AESDecrypt AES解密
|
||||||
func aesDecryptWithSalt(ciphertext []byte) ([]byte, error) {
|
func AESDecrypt(ciphertext, aeskey []byte) ([]byte, error) {
|
||||||
blockSize := aes.BlockSize
|
blockSize := aes.BlockSize
|
||||||
if len(ciphertext) < blockSize {
|
if len(ciphertext) < blockSize {
|
||||||
return nil, fmt.Errorf("ciphertext too short")
|
return nil, fmt.Errorf("ciphertext too short")
|
||||||
@@ -77,12 +72,14 @@ func aesDecryptWithSalt(ciphertext []byte) ([]byte, error) {
|
|||||||
|
|
||||||
iv := ciphertext[:blockSize]
|
iv := ciphertext[:blockSize]
|
||||||
ciphertext = ciphertext[blockSize:]
|
ciphertext = ciphertext[blockSize:]
|
||||||
|
block, err := aes.NewCipher([]byte(aeskey))
|
||||||
|
|
||||||
block, err := aes.NewCipher([]byte(aesKey))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(ciphertext) == 0 {
|
||||||
|
return nil, fmt.Errorf("ciphertext is invalid")
|
||||||
|
}
|
||||||
if len(ciphertext)%blockSize != 0 {
|
if len(ciphertext)%blockSize != 0 {
|
||||||
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
|
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// QueryMap 查询参数转换Map
|
// QueryMap 查询参数转换Map
|
||||||
@@ -30,7 +29,7 @@ func QueryMap(c *gin.Context) map[string]any {
|
|||||||
// BodyJSONMap JSON参数转换Map
|
// BodyJSONMap JSON参数转换Map
|
||||||
func BodyJSONMap(c *gin.Context) map[string]any {
|
func BodyJSONMap(c *gin.Context) map[string]any {
|
||||||
params := make(map[string]any)
|
params := make(map[string]any)
|
||||||
c.ShouldBindBodyWith(¶ms, binding.JSON)
|
c.ShouldBindBodyWithJSON(¶ms)
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ func RequestParamsMap(c *gin.Context) map[string]any {
|
|||||||
params := make(map[string]any)
|
params := make(map[string]any)
|
||||||
// json
|
// json
|
||||||
if strings.HasPrefix(c.ContentType(), "application/json") {
|
if strings.HasPrefix(c.ContentType(), "application/json") {
|
||||||
c.ShouldBindBodyWith(¶ms, binding.JSON)
|
c.ShouldBindBodyWithJSON(¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单
|
// 表单
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func Post(url string, data url.Values, headers map[string]string) ([]byte, error
|
|||||||
// PostJSON 发送 POST 请求,并将请求体序列化为 JSON 格式
|
// PostJSON 发送 POST 请求,并将请求体序列化为 JSON 格式
|
||||||
func PostJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
func PostJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: 3 * time.Second, // 超时时间
|
Timeout: 10 * time.Second, // 超时时间
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonData, err := json.Marshal(data)
|
jsonData, err := json.Marshal(data)
|
||||||
@@ -180,7 +180,7 @@ func PostUploadFile(url string, params map[string]string, file *os.File) ([]byte
|
|||||||
// PutJSON 发送 PUT 请求,并将请求体序列化为 JSON 格式
|
// PutJSON 发送 PUT 请求,并将请求体序列化为 JSON 格式
|
||||||
func PutJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
func PutJSON(url string, data any, headers map[string]string) ([]byte, error) {
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: 3 * time.Second, // 超时时间
|
Timeout: 10 * time.Second, // 超时时间
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonData, err := json.Marshal(data)
|
jsonData, err := json.Marshal(data)
|
||||||
|
|||||||
@@ -351,5 +351,6 @@ func ParseUploadFileDir(subPath string) string {
|
|||||||
// filePath 上传文件路径
|
// filePath 上传文件路径
|
||||||
func ParseUploadFilePath(filePath string) string {
|
func ParseUploadFilePath(filePath string) string {
|
||||||
prefix, dir := resourceUpload()
|
prefix, dir := resourceUpload()
|
||||||
return strings.Replace(filePath, prefix, dir, 1)
|
absPath := strings.Replace(filePath, prefix, dir, 1)
|
||||||
|
return filepath.ToSlash(absPath)
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/framework/utils/file/tar.go
Normal file
76
src/framework/utils/file/tar.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompressTarGZByDir 将目录下文件添加到 tar.gz 压缩文件
|
||||||
|
func CompressTarGZByDir(zipFilePath, dirPath string) error {
|
||||||
|
// 创建本地输出目录
|
||||||
|
if err := os.MkdirAll(filepath.Dir(zipFilePath), 0775); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建输出文件
|
||||||
|
tarFile, err := os.Create(zipFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tarFile.Close()
|
||||||
|
|
||||||
|
gw := gzip.NewWriter(tarFile)
|
||||||
|
defer gw.Close()
|
||||||
|
|
||||||
|
tw := tar.NewWriter(gw)
|
||||||
|
defer tw.Close()
|
||||||
|
|
||||||
|
// 遍历目录下的所有文件和子目录
|
||||||
|
err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 忽略目录
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建文件条目
|
||||||
|
header, err := tar.FileInfoHeader(info, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
relPath, err := filepath.Rel(dirPath, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
header.Name = relPath
|
||||||
|
if err := tw.WriteHeader(header); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !info.Mode().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开文件
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 写入文件内容
|
||||||
|
_, err = io.Copy(tw, file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/config"
|
||||||
"be.ems/src/framework/constants/common"
|
"be.ems/src/framework/constants/common"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
"be.ems/src/framework/utils/cmd"
|
"be.ems/src/framework/utils/cmd"
|
||||||
@@ -68,7 +69,8 @@ func codeFileRead() (map[string]any, error) {
|
|||||||
}
|
}
|
||||||
content := string(bytes)
|
content := string(bytes)
|
||||||
// 解密
|
// 解密
|
||||||
contentDe, err := crypto.StringDecryptByAES(content)
|
hostKey := config.Get("aes.hostKey").(string)
|
||||||
|
contentDe, err := crypto.AESDecryptBase64(content, hostKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("CodeFileRead decrypt: %v", err.Error())
|
logger.Errorf("CodeFileRead decrypt: %v", err.Error())
|
||||||
return mapData, fmt.Errorf("decrypt fail")
|
return mapData, fmt.Errorf("decrypt fail")
|
||||||
@@ -86,7 +88,8 @@ func codeFileRead() (map[string]any, error) {
|
|||||||
func codeFileWrite(data map[string]any) error {
|
func codeFileWrite(data map[string]any) error {
|
||||||
jsonByte, _ := json.Marshal(data)
|
jsonByte, _ := json.Marshal(data)
|
||||||
// 加密
|
// 加密
|
||||||
contentEn, err := crypto.StringEncryptByAES(string(jsonByte))
|
hostKey := config.Get("aes.hostKey").(string)
|
||||||
|
contentEn, err := crypto.AESEncryptBase64(string(jsonByte), hostKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("insert encrypt: %v", err.Error())
|
logger.Errorf("insert encrypt: %v", err.Error())
|
||||||
return fmt.Errorf("encrypt fail")
|
return fmt.Errorf("encrypt fail")
|
||||||
|
|||||||
@@ -17,46 +17,53 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Number 解析数值型
|
// Number 解析数值型
|
||||||
func Number(str any) int64 {
|
func Number(value any) int64 {
|
||||||
switch str := str.(type) {
|
switch v := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if str == "" {
|
if v == "" {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
num, err := strconv.ParseInt(str, 10, 64)
|
num, err := strconv.ParseInt(v, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return num
|
return num
|
||||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
case int, int8, int16, int32, int64:
|
||||||
return reflect.ValueOf(str).Int()
|
return reflect.ValueOf(v).Int()
|
||||||
|
case uint, uint8, uint16, uint32, uint64:
|
||||||
|
return int64(reflect.ValueOf(v).Uint())
|
||||||
case float32, float64:
|
case float32, float64:
|
||||||
return int64(reflect.ValueOf(str).Float())
|
return int64(reflect.ValueOf(v).Float())
|
||||||
|
case bool:
|
||||||
|
if v {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
default:
|
default:
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boolean 解析布尔型
|
// Boolean 解析布尔型
|
||||||
func Boolean(str any) bool {
|
func Boolean(value any) bool {
|
||||||
switch str := str.(type) {
|
switch v := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
if str == "" || str == "false" || str == "0" {
|
b, err := strconv.ParseBool(v)
|
||||||
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 尝试将字符串解析为数字
|
return b
|
||||||
if num, err := strconv.ParseFloat(str, 64); err == nil {
|
case int, int8, int16, int32, int64:
|
||||||
|
num := reflect.ValueOf(v).Int()
|
||||||
return num != 0
|
return num != 0
|
||||||
}
|
case uint, uint8, uint16, uint32, uint64:
|
||||||
return true
|
num := int64(reflect.ValueOf(v).Uint())
|
||||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
|
||||||
num := reflect.ValueOf(str).Int()
|
|
||||||
return num != 0
|
return num != 0
|
||||||
case float32, float64:
|
case float32, float64:
|
||||||
num := reflect.ValueOf(str).Float()
|
num := reflect.ValueOf(v).Float()
|
||||||
return num != 0
|
return num != 0
|
||||||
case bool:
|
case bool:
|
||||||
return str
|
return v
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,8 @@ type FileListRow struct {
|
|||||||
// 文件列表
|
// 文件列表
|
||||||
// search 文件名后模糊*
|
// search 文件名后模糊*
|
||||||
//
|
//
|
||||||
// return 目录大小,行记录,异常
|
// return 行记录,异常
|
||||||
func FileList(sshClient *ConnSSH, path, search string) (string, []FileListRow, error) {
|
func FileList(sshClient *ConnSSH, path, search string) ([]FileListRow, error) {
|
||||||
totalSize := ""
|
|
||||||
var rows []FileListRow
|
var rows []FileListRow
|
||||||
rowStr := ""
|
rowStr := ""
|
||||||
|
|
||||||
@@ -35,40 +34,37 @@ func FileList(sshClient *ConnSSH, path, search string) (string, []FileListRow, e
|
|||||||
if search != "" {
|
if search != "" {
|
||||||
searchStr = search + searchStr
|
searchStr = search + searchStr
|
||||||
}
|
}
|
||||||
cmdStr := fmt.Sprintf("cd %s && ls -lthd --time-style=+%%s %s", path, searchStr)
|
// cd /var/log && find. -maxdepth 1 -name'mme*' -exec ls -lthd --time-style=+%s {} +
|
||||||
|
cmdStr := fmt.Sprintf("cd %s && find . -maxdepth 1 -name '%s' -exec ls -lthd --time-style=+%%s {} +", path, searchStr)
|
||||||
|
// cd /var/log && ls -lthd --time-style=+%s mme*
|
||||||
|
// cmdStr := fmt.Sprintf("cd %s && ls -lthd --time-style=+%%s %s", path, searchStr)
|
||||||
|
|
||||||
// 是否远程客户端读取
|
// 是否远程客户端读取
|
||||||
if sshClient == nil {
|
if sshClient == nil {
|
||||||
resultStr, err := cmd.Execf(cmdStr)
|
resultStr, err := cmd.Execf(cmdStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
||||||
return totalSize, rows, err
|
return rows, err
|
||||||
}
|
}
|
||||||
rowStr = resultStr
|
rowStr = resultStr
|
||||||
} else {
|
} else {
|
||||||
resultStr, err := sshClient.RunCMD(cmdStr)
|
resultStr, err := sshClient.RunCMD(cmdStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
||||||
return totalSize, rows, err
|
return rows, err
|
||||||
}
|
}
|
||||||
rowStr = resultStr
|
rowStr = resultStr
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历组装
|
// 遍历组装
|
||||||
rowStrList := strings.Split(rowStr, "\n")
|
rowStrList := strings.Split(rowStr, "\n")
|
||||||
for i, rowStr := range rowStrList {
|
for _, rowStr := range rowStrList {
|
||||||
if rowStr == "" {
|
if rowStr == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 使用空格对字符串进行切割
|
// 使用空格对字符串进行切割
|
||||||
fields := strings.Fields(rowStr)
|
fields := strings.Fields(rowStr)
|
||||||
|
|
||||||
// 无查询过滤会有total总计
|
|
||||||
if i == 0 && searchStr == "" {
|
|
||||||
totalSize = fields[1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拆分不足7位跳过
|
// 拆分不足7位跳过
|
||||||
if len(fields) != 7 {
|
if len(fields) != 7 {
|
||||||
continue
|
continue
|
||||||
@@ -83,6 +79,14 @@ func FileList(sshClient *ConnSSH, path, search string) (string, []FileListRow, e
|
|||||||
fileType = "symlink"
|
fileType = "symlink"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 文件名
|
||||||
|
fileName := fields[6]
|
||||||
|
if fileName == "." {
|
||||||
|
continue
|
||||||
|
} else if strings.HasPrefix(fileName, "./") {
|
||||||
|
fileName = strings.TrimPrefix(fileName, "./")
|
||||||
|
}
|
||||||
|
|
||||||
// 提取各个字段的值
|
// 提取各个字段的值
|
||||||
rows = append(rows, FileListRow{
|
rows = append(rows, FileListRow{
|
||||||
FileMode: fileMode,
|
FileMode: fileMode,
|
||||||
@@ -92,8 +96,8 @@ func FileList(sshClient *ConnSSH, path, search string) (string, []FileListRow, e
|
|||||||
Group: fields[3],
|
Group: fields[3],
|
||||||
Size: fields[4],
|
Size: fields[4],
|
||||||
ModifiedTime: parse.Number(fields[5]),
|
ModifiedTime: parse.Number(fields[5]),
|
||||||
FileName: fields[6],
|
FileName: fileName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return totalSize, rows, nil
|
return rows, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyDirRemoteToLocal 复制目录-本地到远程
|
// CopyDirLocalToRemote 复制目录-本地到远程
|
||||||
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
||||||
// 遍历本地目录中的文件和子目录并复制到远程
|
// 遍历本地目录中的文件和子目录并复制到远程
|
||||||
err := filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
err := filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
||||||
@@ -94,7 +94,7 @@ func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyDirRemoteToLocal 复制文件-远程到本地
|
// CopyFileRemoteToLocal 复制文件-远程到本地
|
||||||
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
||||||
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -124,7 +124,7 @@ func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyDirRemoteToLocal 复制文件-本地到远程
|
// CopyFileLocalToRemote 复制文件-本地到远程
|
||||||
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
||||||
// 打开本地文件
|
// 打开本地文件
|
||||||
localFile, err := os.Open(localPath)
|
localFile, err := os.Open(localPath)
|
||||||
|
|||||||
@@ -212,11 +212,14 @@ func (c *ConnSSH) SendToAuthorizedKeys() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// "sudo mkdir -p ~/.ssh && sudo chown omcuser:omcuser ~/.ssh && sudo chmod 700 ~/.ssh"
|
||||||
|
// "sudo touch ~/.ssh/authorized_keys && sudo chown omcuser:omcuser ~/.ssh/authorized_keys && sudo chmod 600 ~/.ssh/authorized_keys"
|
||||||
|
// "echo 'ssh-rsa AAAAB3= pc-host\n' | sudo tee -a ~/.ssh/authorized_keys"
|
||||||
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
||||||
cmdStrArr := []string{
|
cmdStrArr := []string{
|
||||||
fmt.Sprintf("sudo mkdir -p /home/%s/.ssh && sudo chown %s:%s /home/%s/.ssh && sudo chmod 700 /home/%s/.ssh", c.User, c.User, c.User, c.User, c.User),
|
fmt.Sprintf("sudo mkdir -p ~/.ssh && sudo chown %s:%s ~/.ssh && sudo chmod 700 ~/.ssh", c.User, c.User),
|
||||||
fmt.Sprintf("sudo touch /home/%s/.ssh/authorized_keys && sudo chown %s:%s /home/%s/.ssh/authorized_keys && sudo chmod 600 /home/%s/.ssh/authorized_keys", c.User, c.User, c.User, c.User, c.User),
|
fmt.Sprintf("sudo touch ~/.ssh/authorized_keys && sudo chown %s:%s ~/.ssh/authorized_keys && sudo chmod 600 ~/.ssh/authorized_keys", c.User, c.User),
|
||||||
fmt.Sprintf("echo '%s' | sudo tee -a /home/%s/.ssh/authorized_keys", authorizedKeysEntry, c.User),
|
fmt.Sprintf("echo '%s' | sudo tee -a ~/.ssh/authorized_keys", authorizedKeysEntry),
|
||||||
}
|
}
|
||||||
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package ua
|
package ua
|
||||||
|
|
||||||
import "github.com/mssola/user_agent"
|
import "github.com/mssola/useragent"
|
||||||
|
|
||||||
// 获取user-agent信息
|
// 获取user-agent信息
|
||||||
func Info(userAgent string) *user_agent.UserAgent {
|
func Info(userAgent string) *useragent.UserAgent {
|
||||||
return user_agent.New(userAgent)
|
return useragent.New(userAgent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"be.ems/src/framework/constants/result"
|
constResult "be.ems/src/framework/constants/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CodeMsg 响应结果
|
// CodeMsg 响应结果
|
||||||
@@ -15,8 +15,8 @@ func CodeMsg(code int, msg string) map[string]any {
|
|||||||
// 响应成功结果 map[string]any{}
|
// 响应成功结果 map[string]any{}
|
||||||
func Ok(v map[string]any) map[string]any {
|
func Ok(v map[string]any) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_SUCCESS
|
args["code"] = constResult.CODE_SUCCESS
|
||||||
args["msg"] = result.MSG_SUCCESS
|
args["msg"] = constResult.MSG_SUCCESS
|
||||||
// v合并到args
|
// v合并到args
|
||||||
for key, value := range v {
|
for key, value := range v {
|
||||||
args[key] = value
|
args[key] = value
|
||||||
@@ -27,7 +27,7 @@ func Ok(v map[string]any) map[string]any {
|
|||||||
// 响应成功结果信息
|
// 响应成功结果信息
|
||||||
func OkMsg(msg string) map[string]any {
|
func OkMsg(msg string) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_SUCCESS
|
args["code"] = constResult.CODE_SUCCESS
|
||||||
args["msg"] = msg
|
args["msg"] = msg
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
@@ -35,8 +35,8 @@ func OkMsg(msg string) map[string]any {
|
|||||||
// 响应成功结果数据
|
// 响应成功结果数据
|
||||||
func OkData(data any) map[string]any {
|
func OkData(data any) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_SUCCESS
|
args["code"] = constResult.CODE_SUCCESS
|
||||||
args["msg"] = result.MSG_SUCCESS
|
args["msg"] = constResult.MSG_SUCCESS
|
||||||
args["data"] = data
|
args["data"] = data
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
@@ -44,8 +44,8 @@ func OkData(data any) map[string]any {
|
|||||||
// 响应失败结果 map[string]any{}
|
// 响应失败结果 map[string]any{}
|
||||||
func Err(v map[string]any) map[string]any {
|
func Err(v map[string]any) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_ERROR
|
args["code"] = constResult.CODE_ERROR
|
||||||
args["msg"] = result.MSG_ERROR
|
args["msg"] = constResult.MSG_ERROR
|
||||||
// v合并到args
|
// v合并到args
|
||||||
for key, value := range v {
|
for key, value := range v {
|
||||||
args[key] = value
|
args[key] = value
|
||||||
@@ -56,7 +56,7 @@ func Err(v map[string]any) map[string]any {
|
|||||||
// 响应失败结果信息
|
// 响应失败结果信息
|
||||||
func ErrMsg(msg string) map[string]any {
|
func ErrMsg(msg string) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_ERROR
|
args["code"] = constResult.CODE_ERROR
|
||||||
args["msg"] = msg
|
args["msg"] = msg
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
@@ -64,8 +64,8 @@ func ErrMsg(msg string) map[string]any {
|
|||||||
// 响应失败结果数据
|
// 响应失败结果数据
|
||||||
func ErrData(data any) map[string]any {
|
func ErrData(data any) map[string]any {
|
||||||
args := make(map[string]any)
|
args := make(map[string]any)
|
||||||
args["code"] = result.CODE_ERROR
|
args["code"] = constResult.CODE_ERROR
|
||||||
args["msg"] = result.MSG_ERROR
|
args["msg"] = constResult.MSG_ERROR
|
||||||
args["data"] = data
|
args["data"] = data
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ import (
|
|||||||
func Setup(router *gin.Engine) {
|
func Setup(router *gin.Engine) {
|
||||||
logger.Infof("开始加载 ====> chart 模块路由")
|
logger.Infof("开始加载 ====> chart 模块路由")
|
||||||
|
|
||||||
chartGroup := router.Group("/chart")
|
// G6关系图
|
||||||
|
chartGraphGroup := router.Group("/chart/graph")
|
||||||
// 关系图
|
|
||||||
chartGraphGroup := chartGroup.Group("/graph")
|
|
||||||
{
|
{
|
||||||
chartGraphGroup.GET("",
|
chartGraphGroup.GET("",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import (
|
|||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
chartService "be.ems/src/modules/chart/service"
|
"be.ems/src/modules/chart/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 ChartGraphController 结构体
|
// 实例化控制层 ChartGraphController 结构体
|
||||||
var NewChartGraph = &ChartGraphController{
|
var NewChartGraph = &ChartGraphController{
|
||||||
chartGraphService: chartService.NewChartGraphImpl,
|
chartGraphService: service.NewChartGraph,
|
||||||
}
|
}
|
||||||
|
|
||||||
// G6关系图
|
// G6关系图
|
||||||
@@ -19,7 +19,7 @@ var NewChartGraph = &ChartGraphController{
|
|||||||
// PATH /graph
|
// PATH /graph
|
||||||
type ChartGraphController struct {
|
type ChartGraphController struct {
|
||||||
// G6关系图数据表服务
|
// G6关系图数据表服务
|
||||||
chartGraphService chartService.IChartGraph
|
chartGraphService *service.ChartGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取关系图组名
|
// 获取关系图组名
|
||||||
|
|||||||
@@ -1,31 +1,32 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
// ChartGraph G6关系图数据对象 chart_graph
|
// ChartGraph 图表-G6关系图数据对象 chart_graph
|
||||||
type ChartGraph struct {
|
type ChartGraph struct {
|
||||||
RowID int64 `json:"rowId,omitempty" gorm:"column:row_id;primaryKey;autoIncrement"` // 记录ID
|
RowID int64 `json:"rowId,omitempty" gorm:"column:row_id;primaryKey;autoIncrement"` // 记录ID
|
||||||
RowType string `json:"rowType,omitempty" gorm:"column:row_type"` // 记录类型(node/edge/combo)
|
RowType string `json:"rowType" gorm:"row_type"` // 记录类型
|
||||||
RowGroup string `json:"rowGroup,omitempty" gorm:"column:row_group"` // 记录组名
|
RowGroup string `json:"rowGroup" gorm:"row_group"` // 记录组名
|
||||||
ID string `json:"id,omitempty" gorm:"column:id"` // 元素ID
|
ID string `json:"id" gorm:"id"` // 元素ID
|
||||||
Type string `json:"type,omitempty" gorm:"column:type"` // node/combo 类型
|
Type string `json:"type" gorm:"type"` // node/combo 类型
|
||||||
Depth int `json:"depth,omitempty" gorm:"column:depth"` // node/combo 深度
|
Depth int64 `json:"depth" gorm:"depth"` // node/combo 深度
|
||||||
X float64 `json:"x,omitempty" gorm:"column:x"` // node/combo 横向坐标
|
X float64 `json:"x" gorm:"x"` // node/combo 横向坐标
|
||||||
Y float64 `json:"y,omitempty" gorm:"column:y"` // node/combo 纵向坐标
|
Y float64 `json:"y" gorm:"y"` // node/combo 纵向坐标
|
||||||
Size string `json:"size,omitempty" gorm:"column:size"` // node/combo 大小-JSON数组
|
Size string `json:"size" gorm:"size"` // node/combo 大小-JSON数组
|
||||||
Icon string `json:"icon,omitempty" gorm:"column:icon"` // node-部分类型支持图标JSON配置
|
Icon string `json:"icon" gorm:"icon"` // node-部分类型支持图标JSON配置
|
||||||
Img string `json:"img,omitempty" gorm:"column:img"` // node-img 图片
|
Img string `json:"img" gorm:"img"` // node-img 图片
|
||||||
ClipCfg string `json:"clipCfg,omitempty" gorm:"column:clip_cfg"` // node-img 图片裁剪JSON配置
|
ClipCfg string `json:"clipCfg" gorm:"clip_cfg"` // node-img 图片裁剪JSON配置
|
||||||
Direction string `json:"direction,omitempty" gorm:"column:direction"` // node-triangle 三角形的方向(up/down/left/right)
|
Direction string `json:"direction" gorm:"direction"` // node-triangle 三角形的方向
|
||||||
Source string `json:"source,omitempty" gorm:"column:source"` // edge-边起始
|
Source string `json:"source" gorm:"source"` // edge-边起始
|
||||||
Target string `json:"target,omitempty" gorm:"column:target"` // edge-边目标
|
Target string `json:"target" gorm:"target"` // edge-边目标
|
||||||
ComboID string `json:"combo_id,omitempty" gorm:"column:combo_id"` // combo-分组
|
ComboId string `json:"comboId" gorm:"combo_id"` // combo-分组
|
||||||
Padding string `json:"padding,omitempty" gorm:"column:padding"` // combo-JSON分组内边距
|
Padding string `json:"padding" gorm:"padding"` // combo-JSON分组内边距
|
||||||
ParentID string `json:"parentId,omitempty" gorm:"column:parent_id"` // combo-父级分组
|
ParentId string `json:"parentId" gorm:"parent_id"` // combo-父级分组
|
||||||
Children string `json:"children,omitempty" gorm:"column:children"` // combo-JSON分组内含元素
|
Children string `json:"children" gorm:"children"` // combo-JSON分组内含元素
|
||||||
Style string `json:"style,omitempty" gorm:"column:style"` // 元素样式-JONS配置
|
Style string `json:"style" gorm:"style"` // 元素样式-JONS配置
|
||||||
Label string `json:"label,omitempty" gorm:"column:label"` // 标签文本
|
Label string `json:"label" gorm:"label"` // 标签文本
|
||||||
LabelCfg string `json:"labelCfg,omitempty" gorm:"column:label_cfg"` // 标签文本-JSON配置
|
LabelCfg string `json:"labelCfg" gorm:"label_cfg"` // 标签文本-JSON配置
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ChartGraph) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*ChartGraph) TableName() string {
|
||||||
return "chart_graph"
|
return "chart_graph"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,194 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import "be.ems/src/modules/chart/model"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/datasource"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/utils/repo"
|
||||||
|
"be.ems/src/modules/chart/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 ChartGraph 结构体
|
||||||
|
var NewChartGraph = &ChartGraph{
|
||||||
|
selectSql: `select
|
||||||
|
row_id, row_type, row_group,
|
||||||
|
id, type, depth, x, y, size, icon, img,
|
||||||
|
clip_cfg, direction,
|
||||||
|
source, target, combo_id,
|
||||||
|
padding, parent_id, children,
|
||||||
|
style, label, label_cfg
|
||||||
|
from chart_graph`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"row_id": "RowID",
|
||||||
|
"row_type": "RowType",
|
||||||
|
"row_group": "RowGroup",
|
||||||
|
"id": "ID",
|
||||||
|
"type": "Type",
|
||||||
|
"depth": "Depth",
|
||||||
|
"x": "X",
|
||||||
|
"y": "Y",
|
||||||
|
"size": "Size",
|
||||||
|
"icon": "Icon",
|
||||||
|
"img": "Img",
|
||||||
|
"clip_cfg": "ClipCfg",
|
||||||
|
"direction": "Direction",
|
||||||
|
"source": "Source",
|
||||||
|
"target": "Target",
|
||||||
|
"combo_id": "ComboID",
|
||||||
|
"padding": "Padding",
|
||||||
|
"parent_id": "ParentID",
|
||||||
|
"children": "Children",
|
||||||
|
"style": "Style",
|
||||||
|
"label": "Label",
|
||||||
|
"label_cfg": "LabelCfg",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChartGraph G6关系图数据表 数据层处理
|
||||||
|
type ChartGraph struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *ChartGraph) convertResultRows(rows []map[string]any) []model.ChartGraph {
|
||||||
|
arr := make([]model.ChartGraph, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
item := model.ChartGraph{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
repo.SetFieldValue(&item, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
// G6关系图数据 数据层接口
|
|
||||||
type IChartGraph interface {
|
|
||||||
// SelectPage 根据条件分页查询字典类型
|
// SelectPage 根据条件分页查询字典类型
|
||||||
SelectPage(query map[string]any) map[string]any
|
func (r *ChartGraph) SelectPage(query map[string]any) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if v, ok := query["rowType"]; ok && v != "" {
|
||||||
|
conditions = append(conditions, "row_type = ?")
|
||||||
|
params = append(params, strings.Trim(v.(string), " "))
|
||||||
|
}
|
||||||
|
if v, ok := query["rowGroup"]; ok && v != "" {
|
||||||
|
conditions = append(conditions, "row_group = ?")
|
||||||
|
params = append(params, strings.Trim(v.(string), " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]any{
|
||||||
|
"total": 0,
|
||||||
|
"rows": []model.ChartGraph{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from chart_graph"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("total err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
result["total"] = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
result["rows"] = r.convertResultRows(results)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SelectList 根据实体查询
|
// SelectList 根据实体查询
|
||||||
SelectList(graph model.ChartGraph) []model.ChartGraph
|
func (r *ChartGraph) SelectList(graph model.ChartGraph) []model.ChartGraph {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if graph.RowType != "" {
|
||||||
|
conditions = append(conditions, "row_type = ?")
|
||||||
|
params = append(params, graph.RowType)
|
||||||
|
}
|
||||||
|
if graph.RowGroup != "" {
|
||||||
|
conditions = append(conditions, "row_group = ?")
|
||||||
|
params = append(params, graph.RowGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + " order by depth asc "
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
// SelectGroup 查询组名
|
// SelectGroup 查询组名
|
||||||
SelectGroup() []string
|
func (r *ChartGraph) SelectGroup() []string {
|
||||||
|
rows := []string{}
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
querySql := "select row_group as 'str' from chart_graph GROUP BY row_group"
|
||||||
|
strRows, err := datasource.RawDB("", querySql, nil)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Query err => %v", err)
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
for _, v := range strRows {
|
||||||
|
rows = append(rows, v["str"].(string))
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
// Insert 批量添加
|
// Insert 批量添加
|
||||||
Inserts(graphs []model.ChartGraph) int64
|
func (r *ChartGraph) Inserts(graphs []model.ChartGraph) int64 {
|
||||||
|
tx := datasource.DefaultDB().CreateInBatches(graphs, 2000)
|
||||||
|
if err := tx.Error; err != nil {
|
||||||
|
logger.Errorf("CreateInBatches err => %v", err)
|
||||||
|
}
|
||||||
|
return tx.RowsAffected
|
||||||
|
}
|
||||||
|
|
||||||
// Delete 删除组数据
|
// Delete 删除组数据
|
||||||
DeleteGroup(rowGroup string) int64
|
func (r *ChartGraph) DeleteGroup(rowGroup string) int64 {
|
||||||
|
tx := datasource.DefaultDB().Where("row_group = ?", rowGroup).Delete(&model.ChartGraph{})
|
||||||
|
if err := tx.Error; err != nil {
|
||||||
|
logger.Errorf("Delete err => %v", err)
|
||||||
|
}
|
||||||
|
return tx.RowsAffected
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/src/framework/datasource"
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
"be.ems/src/framework/utils/repo"
|
|
||||||
"be.ems/src/modules/chart/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 NewChartGraphImpl 结构体
|
|
||||||
var NewChartGraphImpl = &ChartGraphImpl{
|
|
||||||
selectSql: `select
|
|
||||||
row_id, row_type, row_group,
|
|
||||||
id, type, depth, x, y, size, icon, img,
|
|
||||||
clip_cfg, direction,
|
|
||||||
source, target, combo_id,
|
|
||||||
padding, parent_id, children,
|
|
||||||
style, label, label_cfg
|
|
||||||
from chart_graph`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"row_id": "RowID",
|
|
||||||
"row_type": "RowType",
|
|
||||||
"row_group": "RowGroup",
|
|
||||||
"id": "ID",
|
|
||||||
"type": "Type",
|
|
||||||
"depth": "Depth",
|
|
||||||
"x": "X",
|
|
||||||
"y": "Y",
|
|
||||||
"size": "Size",
|
|
||||||
"icon": "Icon",
|
|
||||||
"img": "Img",
|
|
||||||
"clip_cfg": "ClipCfg",
|
|
||||||
"direction": "Direction",
|
|
||||||
"source": "Source",
|
|
||||||
"target": "Target",
|
|
||||||
"combo_id": "ComboID",
|
|
||||||
"padding": "Padding",
|
|
||||||
"parent_id": "ParentID",
|
|
||||||
"children": "Children",
|
|
||||||
"style": "Style",
|
|
||||||
"label": "Label",
|
|
||||||
"label_cfg": "LabelCfg",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChartGraphImpl G6关系图数据表 数据层处理
|
|
||||||
type ChartGraphImpl struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *ChartGraphImpl) convertResultRows(rows []map[string]any) []model.ChartGraph {
|
|
||||||
arr := make([]model.ChartGraph, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
item := model.ChartGraph{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
repo.SetFieldValue(&item, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, item)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectPage 根据条件分页查询字典类型
|
|
||||||
func (r *ChartGraphImpl) SelectPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["rowType"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "row_type = ?")
|
|
||||||
params = append(params, strings.Trim(v.(string), " "))
|
|
||||||
}
|
|
||||||
if v, ok := query["rowGroup"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "row_group = ?")
|
|
||||||
params = append(params, strings.Trim(v.(string), " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := map[string]any{
|
|
||||||
"total": 0,
|
|
||||||
"rows": []model.ChartGraph{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from chart_graph"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("total err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result["total"] = total
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("query err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
result["rows"] = r.convertResultRows(results)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectList 根据实体查询
|
|
||||||
func (r *ChartGraphImpl) SelectList(graph model.ChartGraph) []model.ChartGraph {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if graph.RowType != "" {
|
|
||||||
conditions = append(conditions, "row_type = ?")
|
|
||||||
params = append(params, graph.RowType)
|
|
||||||
}
|
|
||||||
if graph.RowGroup != "" {
|
|
||||||
conditions = append(conditions, "row_group = ?")
|
|
||||||
params = append(params, graph.RowGroup)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + " order by depth asc "
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectGroup 查询组名
|
|
||||||
func (r *ChartGraphImpl) SelectGroup() []string {
|
|
||||||
rows := []string{}
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
querySql := "select row_group as 'str' from chart_graph GROUP BY row_group"
|
|
||||||
strRows, err := datasource.RawDB("", querySql, nil)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Query err => %v", err)
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
for _, v := range strRows {
|
|
||||||
rows = append(rows, v["str"].(string))
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 批量添加
|
|
||||||
func (r *ChartGraphImpl) Inserts(graphs []model.ChartGraph) int64 {
|
|
||||||
tx := datasource.DefaultDB().CreateInBatches(graphs, 2000)
|
|
||||||
if err := tx.Error; err != nil {
|
|
||||||
logger.Errorf("CreateInBatches err => %v", err)
|
|
||||||
}
|
|
||||||
return tx.RowsAffected
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除组数据
|
|
||||||
func (r *ChartGraphImpl) DeleteGroup(rowGroup string) int64 {
|
|
||||||
tx := datasource.DefaultDB().Where("row_group = ?", rowGroup).Delete(&model.ChartGraph{})
|
|
||||||
if err := tx.Error; err != nil {
|
|
||||||
logger.Errorf("Delete err => %v", err)
|
|
||||||
}
|
|
||||||
return tx.RowsAffected
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,359 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
// G6关系图数据 服务层接口
|
import (
|
||||||
type IChartGraph interface {
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/modules/chart/model"
|
||||||
|
"be.ems/src/modules/chart/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 ChartGraph 结构体
|
||||||
|
var NewChartGraph = &ChartGraph{
|
||||||
|
graphRepository: repository.NewChartGraph,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChartGraph G6关系图数据表 服务层处理
|
||||||
|
type ChartGraph struct {
|
||||||
|
// G6关系图数据服务
|
||||||
|
graphRepository *repository.ChartGraph
|
||||||
|
}
|
||||||
|
|
||||||
// SelectGroup 查询组名
|
// SelectGroup 查询组名
|
||||||
SelectGroup() []string
|
func (s *ChartGraph) SelectGroup() []string {
|
||||||
|
return s.graphRepository.SelectGroup()
|
||||||
|
}
|
||||||
|
|
||||||
// LoadData 查询所组图数据
|
// LoadData 查询所组图数据
|
||||||
LoadData(rowGroup, rowType string) map[string]any
|
func (s *ChartGraph) LoadData(rowGroup, rowType string) map[string]any {
|
||||||
|
// 查询数据
|
||||||
|
graph := model.ChartGraph{
|
||||||
|
RowGroup: rowGroup,
|
||||||
|
}
|
||||||
|
if rowType != "" {
|
||||||
|
graph.RowType = rowType
|
||||||
|
}
|
||||||
|
data := s.graphRepository.SelectList(graph)
|
||||||
|
|
||||||
|
// 数据项
|
||||||
|
nodes := []map[string]any{}
|
||||||
|
edges := []map[string]any{}
|
||||||
|
combos := []map[string]any{}
|
||||||
|
|
||||||
|
for _, v := range data {
|
||||||
|
if v.RowType == "node" {
|
||||||
|
nodes = append(nodes, s.loadNode(v))
|
||||||
|
}
|
||||||
|
if v.RowType == "edge" {
|
||||||
|
edges = append(edges, s.loadEdge(v))
|
||||||
|
}
|
||||||
|
if v.RowType == "combo" {
|
||||||
|
combos = append(combos, s.loadCombo(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]any{
|
||||||
|
"nodes": nodes,
|
||||||
|
"edges": edges,
|
||||||
|
"combos": combos,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadNode 图数据Node
|
||||||
|
func (s *ChartGraph) loadNode(v model.ChartGraph) map[string]any {
|
||||||
|
node := map[string]any{
|
||||||
|
"id": v.ID,
|
||||||
|
"comboId": v.ComboId,
|
||||||
|
"x": v.X,
|
||||||
|
"y": v.Y,
|
||||||
|
"type": v.Type,
|
||||||
|
"depth": v.Depth,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素样式
|
||||||
|
style := map[string]any{}
|
||||||
|
if len(v.Style) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.Style), &style)
|
||||||
|
}
|
||||||
|
node["style"] = style
|
||||||
|
|
||||||
|
// 元素大小
|
||||||
|
if strings.Contains(v.Size, "[") {
|
||||||
|
sizeArr := []int64{}
|
||||||
|
json.Unmarshal([]byte(v.Size), &sizeArr)
|
||||||
|
node["size"] = sizeArr
|
||||||
|
} else {
|
||||||
|
node["size"] = parse.Number(v.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
node["label"] = v.Label
|
||||||
|
labelCfg := map[string]any{}
|
||||||
|
if len(v.LabelCfg) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
||||||
|
}
|
||||||
|
node["labelCfg"] = labelCfg
|
||||||
|
|
||||||
|
// 三角形属性
|
||||||
|
if v.Type == "triangle" {
|
||||||
|
node["direction"] = v.Direction
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片属性
|
||||||
|
if strings.Index(v.Type, "image") == 0 {
|
||||||
|
node["img"] = v.Img
|
||||||
|
clipCfg := map[string]any{}
|
||||||
|
if len(v.ClipCfg) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.ClipCfg), &clipCfg)
|
||||||
|
}
|
||||||
|
node["clipCfg"] = clipCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图标属性
|
||||||
|
if v.Icon != "" {
|
||||||
|
icon := map[string]any{}
|
||||||
|
if len(v.Icon) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.Icon), &icon)
|
||||||
|
}
|
||||||
|
node["icon"] = icon
|
||||||
|
}
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadEdge 图数据Edge
|
||||||
|
func (s *ChartGraph) loadEdge(v model.ChartGraph) map[string]any {
|
||||||
|
edge := map[string]any{
|
||||||
|
"id": v.ID,
|
||||||
|
"source": v.Source,
|
||||||
|
"target": v.Target,
|
||||||
|
"type": v.Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素样式
|
||||||
|
style := map[string]any{}
|
||||||
|
if len(v.Style) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.Style), &style)
|
||||||
|
}
|
||||||
|
edge["style"] = style
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
edge["label"] = v.Label
|
||||||
|
labelCfg := map[string]any{}
|
||||||
|
if len(v.LabelCfg) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
||||||
|
}
|
||||||
|
edge["labelCfg"] = labelCfg
|
||||||
|
|
||||||
|
return edge
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadCombo 图数据Combo
|
||||||
|
func (s *ChartGraph) loadCombo(v model.ChartGraph) map[string]any {
|
||||||
|
combo := map[string]any{
|
||||||
|
"id": v.ID,
|
||||||
|
"x": v.X,
|
||||||
|
"y": v.Y,
|
||||||
|
"type": v.Type,
|
||||||
|
"depth": v.Depth,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素样式
|
||||||
|
style := map[string]any{}
|
||||||
|
if len(v.Style) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.Style), &style)
|
||||||
|
}
|
||||||
|
combo["style"] = style
|
||||||
|
|
||||||
|
// 元素大小
|
||||||
|
if strings.Contains(v.Size, "[") {
|
||||||
|
sizeArr := []int64{}
|
||||||
|
json.Unmarshal([]byte(v.Size), &sizeArr)
|
||||||
|
combo["size"] = sizeArr
|
||||||
|
} else {
|
||||||
|
combo["size"] = parse.Number(v.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素内边距
|
||||||
|
if strings.Contains(v.Padding, "[") {
|
||||||
|
paddingArr := []int64{}
|
||||||
|
json.Unmarshal([]byte(v.Padding), &paddingArr)
|
||||||
|
combo["padding"] = paddingArr
|
||||||
|
} else {
|
||||||
|
combo["padding"] = parse.Number(v.Padding)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
combo["label"] = v.Label
|
||||||
|
labelCfg := map[string]any{}
|
||||||
|
if len(v.LabelCfg) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
||||||
|
}
|
||||||
|
combo["labelCfg"] = labelCfg
|
||||||
|
|
||||||
|
// 分组内元素
|
||||||
|
if v.Children != "" {
|
||||||
|
children := []map[string]any{}
|
||||||
|
if len(v.Children) > 7 {
|
||||||
|
json.Unmarshal([]byte(v.Children), &children)
|
||||||
|
}
|
||||||
|
combo["children"] = children
|
||||||
|
}
|
||||||
|
|
||||||
|
return combo
|
||||||
|
}
|
||||||
|
|
||||||
// SaveData 添加组图数据
|
// SaveData 添加组图数据
|
||||||
SaveData(rowGroup string, data map[string]any) int64
|
func (s *ChartGraph) SaveData(rowGroup string, data map[string]any) int64 {
|
||||||
|
graphs := []model.ChartGraph{}
|
||||||
// DeleteGroup 删除所组图数据
|
nodes := data["nodes"].([]map[string]any)
|
||||||
DeleteGroup(rowGroup string) int64
|
graphNodes := s.saveNode(rowGroup, nodes)
|
||||||
|
graphs = append(graphs, graphNodes...)
|
||||||
|
edges := data["edges"].([]map[string]any)
|
||||||
|
graphEdges := s.saveEdge(rowGroup, edges)
|
||||||
|
graphs = append(graphs, graphEdges...)
|
||||||
|
combos := data["combos"].([]map[string]any)
|
||||||
|
graphCombos := s.saveCombo(rowGroup, combos)
|
||||||
|
graphs = append(graphs, graphCombos...)
|
||||||
|
// 删除组数据后插入
|
||||||
|
if len(graphs) > 0 {
|
||||||
|
s.graphRepository.DeleteGroup(rowGroup)
|
||||||
|
}
|
||||||
|
return s.graphRepository.Inserts(graphs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveNode 图数据Node
|
||||||
|
func (s *ChartGraph) saveNode(rowGroup string, nodes []map[string]any) []model.ChartGraph {
|
||||||
|
var graphs []model.ChartGraph
|
||||||
|
for _, v := range nodes {
|
||||||
|
node := model.ChartGraph{
|
||||||
|
RowType: "node",
|
||||||
|
RowGroup: rowGroup,
|
||||||
|
ID: v["id"].(string),
|
||||||
|
X: v["x"].(float64),
|
||||||
|
Y: v["y"].(float64),
|
||||||
|
Type: v["type"].(string),
|
||||||
|
}
|
||||||
|
if comboId, ok := v["comboId"]; ok && comboId != nil {
|
||||||
|
node.ComboId = comboId.(string)
|
||||||
|
}
|
||||||
|
if depth, ok := v["depth"]; ok && depth != nil {
|
||||||
|
node.Depth = int64(depth.(float64))
|
||||||
|
}
|
||||||
|
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
||||||
|
node.Style = string(styleByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素大小
|
||||||
|
if sizeByte, err := json.Marshal(v["size"]); err == nil {
|
||||||
|
node.Size = string(sizeByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
if label, ok := v["label"]; ok && label != nil {
|
||||||
|
node.Label = label.(string)
|
||||||
|
}
|
||||||
|
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
||||||
|
node.LabelCfg = string(labelCfgByte)
|
||||||
|
}
|
||||||
|
// 三角形属性
|
||||||
|
if direction, ok := v["direction"]; ok && direction != nil && node.Type == "triangle" {
|
||||||
|
node.Direction = direction.(string)
|
||||||
|
}
|
||||||
|
// 图片属性
|
||||||
|
if img, ok := v["img"]; ok && img != nil {
|
||||||
|
node.Img = img.(string)
|
||||||
|
if clipCfgByte, err := json.Marshal(v["clipCfg"]); err == nil {
|
||||||
|
node.ClipCfg = string(clipCfgByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 图标属性
|
||||||
|
if icon, ok := v["icon"]; ok && icon != nil {
|
||||||
|
if iconByte, err := json.Marshal(icon); err == nil {
|
||||||
|
node.Icon = string(iconByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graphs = append(graphs, node)
|
||||||
|
}
|
||||||
|
return graphs
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveEdge 图数据Edge
|
||||||
|
func (s *ChartGraph) saveEdge(rowGroup string, edges []map[string]any) []model.ChartGraph {
|
||||||
|
var graphs []model.ChartGraph
|
||||||
|
for _, v := range edges {
|
||||||
|
edge := model.ChartGraph{
|
||||||
|
RowType: "edge",
|
||||||
|
RowGroup: rowGroup,
|
||||||
|
ID: v["id"].(string),
|
||||||
|
Source: v["source"].(string),
|
||||||
|
Target: v["target"].(string),
|
||||||
|
Type: v["type"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
||||||
|
edge.Style = string(styleByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
if label, ok := v["label"]; ok && label != nil {
|
||||||
|
edge.Label = label.(string)
|
||||||
|
}
|
||||||
|
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
||||||
|
edge.LabelCfg = string(labelCfgByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
graphs = append(graphs, edge)
|
||||||
|
}
|
||||||
|
return graphs
|
||||||
|
}
|
||||||
|
|
||||||
|
// saveCombo 图数据Combo
|
||||||
|
func (s *ChartGraph) saveCombo(rowGroup string, combos []map[string]any) []model.ChartGraph {
|
||||||
|
var graphs []model.ChartGraph
|
||||||
|
for _, v := range combos {
|
||||||
|
combo := model.ChartGraph{
|
||||||
|
RowType: "combo",
|
||||||
|
RowGroup: rowGroup,
|
||||||
|
ID: v["id"].(string),
|
||||||
|
X: v["x"].(float64),
|
||||||
|
Y: v["y"].(float64),
|
||||||
|
Type: v["type"].(string),
|
||||||
|
}
|
||||||
|
if depth, ok := v["depth"]; ok && depth != nil {
|
||||||
|
combo.Depth = int64(depth.(float64))
|
||||||
|
}
|
||||||
|
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
||||||
|
combo.Style = string(styleByte)
|
||||||
|
}
|
||||||
|
if paddingByte, err := json.Marshal(v["padding"]); err == nil {
|
||||||
|
combo.Padding = string(paddingByte)
|
||||||
|
}
|
||||||
|
if childrenByte, err := json.Marshal(v["children"]); err == nil {
|
||||||
|
combo.Children = string(childrenByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 元素大小
|
||||||
|
if sizeByte, err := json.Marshal(v["size"]); err == nil {
|
||||||
|
combo.Size = string(sizeByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签文本
|
||||||
|
if label, ok := v["label"]; ok && label != nil {
|
||||||
|
combo.Label = label.(string)
|
||||||
|
}
|
||||||
|
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
||||||
|
combo.LabelCfg = string(labelCfgByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
graphs = append(graphs, combo)
|
||||||
|
}
|
||||||
|
return graphs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 删除所组图数据
|
||||||
|
func (s *ChartGraph) DeleteGroup(rowGroup string) int64 {
|
||||||
|
return s.graphRepository.DeleteGroup(rowGroup)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,359 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
"be.ems/src/modules/chart/model"
|
|
||||||
chartRepository "be.ems/src/modules/chart/repository"
|
|
||||||
"github.com/goccy/go-json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ChartGraphImpl 结构体
|
|
||||||
var NewChartGraphImpl = &ChartGraphImpl{
|
|
||||||
graphRepository: chartRepository.NewChartGraphImpl,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChartGraphImpl G6关系图数据表 服务层处理
|
|
||||||
type ChartGraphImpl struct {
|
|
||||||
// G6关系图数据服务
|
|
||||||
graphRepository chartRepository.IChartGraph
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectGroup 查询组名
|
|
||||||
func (s *ChartGraphImpl) SelectGroup() []string {
|
|
||||||
return s.graphRepository.SelectGroup()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadData 查询所组图数据
|
|
||||||
func (s *ChartGraphImpl) LoadData(rowGroup, rowType string) map[string]any {
|
|
||||||
// 查询数据
|
|
||||||
graph := model.ChartGraph{
|
|
||||||
RowGroup: rowGroup,
|
|
||||||
}
|
|
||||||
if rowType != "" {
|
|
||||||
graph.RowType = rowType
|
|
||||||
}
|
|
||||||
data := s.graphRepository.SelectList(graph)
|
|
||||||
|
|
||||||
// 数据项
|
|
||||||
nodes := []map[string]any{}
|
|
||||||
edges := []map[string]any{}
|
|
||||||
combos := []map[string]any{}
|
|
||||||
|
|
||||||
for _, v := range data {
|
|
||||||
if v.RowType == "node" {
|
|
||||||
nodes = append(nodes, s.loadNode(v))
|
|
||||||
}
|
|
||||||
if v.RowType == "edge" {
|
|
||||||
edges = append(edges, s.loadEdge(v))
|
|
||||||
}
|
|
||||||
if v.RowType == "combo" {
|
|
||||||
combos = append(combos, s.loadCombo(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]any{
|
|
||||||
"nodes": nodes,
|
|
||||||
"edges": edges,
|
|
||||||
"combos": combos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadNode 图数据Node
|
|
||||||
func (s *ChartGraphImpl) loadNode(v model.ChartGraph) map[string]any {
|
|
||||||
node := map[string]any{
|
|
||||||
"id": v.ID,
|
|
||||||
"comboId": v.ComboID,
|
|
||||||
"x": v.X,
|
|
||||||
"y": v.Y,
|
|
||||||
"type": v.Type,
|
|
||||||
"depth": v.Depth,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素样式
|
|
||||||
style := map[string]any{}
|
|
||||||
if len(v.Style) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.Style), &style)
|
|
||||||
}
|
|
||||||
node["style"] = style
|
|
||||||
|
|
||||||
// 元素大小
|
|
||||||
if strings.Contains(v.Size, "[") {
|
|
||||||
sizeArr := []int64{}
|
|
||||||
json.Unmarshal([]byte(v.Size), &sizeArr)
|
|
||||||
node["size"] = sizeArr
|
|
||||||
} else {
|
|
||||||
node["size"] = parse.Number(v.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
node["label"] = v.Label
|
|
||||||
labelCfg := map[string]any{}
|
|
||||||
if len(v.LabelCfg) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
|
||||||
}
|
|
||||||
node["labelCfg"] = labelCfg
|
|
||||||
|
|
||||||
// 三角形属性
|
|
||||||
if v.Type == "triangle" {
|
|
||||||
node["direction"] = v.Direction
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图片属性
|
|
||||||
if strings.Index(v.Type, "image") == 0 {
|
|
||||||
node["img"] = v.Img
|
|
||||||
clipCfg := map[string]any{}
|
|
||||||
if len(v.ClipCfg) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.ClipCfg), &clipCfg)
|
|
||||||
}
|
|
||||||
node["clipCfg"] = clipCfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图标属性
|
|
||||||
if v.Icon != "" {
|
|
||||||
icon := map[string]any{}
|
|
||||||
if len(v.Icon) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.Icon), &icon)
|
|
||||||
}
|
|
||||||
node["icon"] = icon
|
|
||||||
}
|
|
||||||
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadEdge 图数据Edge
|
|
||||||
func (s *ChartGraphImpl) loadEdge(v model.ChartGraph) map[string]any {
|
|
||||||
edge := map[string]any{
|
|
||||||
"id": v.ID,
|
|
||||||
"source": v.Source,
|
|
||||||
"target": v.Target,
|
|
||||||
"type": v.Type,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素样式
|
|
||||||
style := map[string]any{}
|
|
||||||
if len(v.Style) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.Style), &style)
|
|
||||||
}
|
|
||||||
edge["style"] = style
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
edge["label"] = v.Label
|
|
||||||
labelCfg := map[string]any{}
|
|
||||||
if len(v.LabelCfg) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
|
||||||
}
|
|
||||||
edge["labelCfg"] = labelCfg
|
|
||||||
|
|
||||||
return edge
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadCombo 图数据Combo
|
|
||||||
func (s *ChartGraphImpl) loadCombo(v model.ChartGraph) map[string]any {
|
|
||||||
combo := map[string]any{
|
|
||||||
"id": v.ID,
|
|
||||||
"x": v.X,
|
|
||||||
"y": v.Y,
|
|
||||||
"type": v.Type,
|
|
||||||
"depth": v.Depth,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素样式
|
|
||||||
style := map[string]any{}
|
|
||||||
if len(v.Style) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.Style), &style)
|
|
||||||
}
|
|
||||||
combo["style"] = style
|
|
||||||
|
|
||||||
// 元素大小
|
|
||||||
if strings.Contains(v.Size, "[") {
|
|
||||||
sizeArr := []int64{}
|
|
||||||
json.Unmarshal([]byte(v.Size), &sizeArr)
|
|
||||||
combo["size"] = sizeArr
|
|
||||||
} else {
|
|
||||||
combo["size"] = parse.Number(v.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素内边距
|
|
||||||
if strings.Contains(v.Padding, "[") {
|
|
||||||
paddingArr := []int64{}
|
|
||||||
json.Unmarshal([]byte(v.Padding), &paddingArr)
|
|
||||||
combo["padding"] = paddingArr
|
|
||||||
} else {
|
|
||||||
combo["padding"] = parse.Number(v.Padding)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
combo["label"] = v.Label
|
|
||||||
labelCfg := map[string]any{}
|
|
||||||
if len(v.LabelCfg) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
|
|
||||||
}
|
|
||||||
combo["labelCfg"] = labelCfg
|
|
||||||
|
|
||||||
// 分组内元素
|
|
||||||
if v.Children != "" {
|
|
||||||
children := []map[string]any{}
|
|
||||||
if len(v.Children) > 7 {
|
|
||||||
json.Unmarshal([]byte(v.Children), &children)
|
|
||||||
}
|
|
||||||
combo["children"] = children
|
|
||||||
}
|
|
||||||
|
|
||||||
return combo
|
|
||||||
}
|
|
||||||
|
|
||||||
// SaveData 添加组图数据
|
|
||||||
func (s *ChartGraphImpl) SaveData(rowGroup string, data map[string]any) int64 {
|
|
||||||
graphs := []model.ChartGraph{}
|
|
||||||
nodes := data["nodes"].([]map[string]any)
|
|
||||||
graphNodes := s.saveNode(rowGroup, nodes)
|
|
||||||
graphs = append(graphs, graphNodes...)
|
|
||||||
edges := data["edges"].([]map[string]any)
|
|
||||||
graphEdges := s.saveEdge(rowGroup, edges)
|
|
||||||
graphs = append(graphs, graphEdges...)
|
|
||||||
combos := data["combos"].([]map[string]any)
|
|
||||||
graphCombos := s.saveCombo(rowGroup, combos)
|
|
||||||
graphs = append(graphs, graphCombos...)
|
|
||||||
// 删除组数据后插入
|
|
||||||
if len(graphs) > 0 {
|
|
||||||
s.graphRepository.DeleteGroup(rowGroup)
|
|
||||||
}
|
|
||||||
return s.graphRepository.Inserts(graphs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// saveNode 图数据Node
|
|
||||||
func (s *ChartGraphImpl) saveNode(rowGroup string, nodes []map[string]any) []model.ChartGraph {
|
|
||||||
var graphs []model.ChartGraph
|
|
||||||
for _, v := range nodes {
|
|
||||||
node := model.ChartGraph{
|
|
||||||
RowType: "node",
|
|
||||||
RowGroup: rowGroup,
|
|
||||||
ID: v["id"].(string),
|
|
||||||
X: v["x"].(float64),
|
|
||||||
Y: v["y"].(float64),
|
|
||||||
Type: v["type"].(string),
|
|
||||||
}
|
|
||||||
if comboId, ok := v["comboId"]; ok && comboId != nil {
|
|
||||||
node.ComboID = comboId.(string)
|
|
||||||
}
|
|
||||||
if depth, ok := v["depth"]; ok && depth != nil {
|
|
||||||
node.Depth = int(depth.(float64))
|
|
||||||
}
|
|
||||||
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
|
||||||
node.Style = string(styleByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素大小
|
|
||||||
if sizeByte, err := json.Marshal(v["size"]); err == nil {
|
|
||||||
node.Size = string(sizeByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
if label, ok := v["label"]; ok && label != nil {
|
|
||||||
node.Label = label.(string)
|
|
||||||
}
|
|
||||||
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
|
||||||
node.LabelCfg = string(labelCfgByte)
|
|
||||||
}
|
|
||||||
// 三角形属性
|
|
||||||
if direction, ok := v["direction"]; ok && direction != nil && node.Type == "triangle" {
|
|
||||||
node.Direction = direction.(string)
|
|
||||||
}
|
|
||||||
// 图片属性
|
|
||||||
if img, ok := v["img"]; ok && img != nil {
|
|
||||||
node.Img = img.(string)
|
|
||||||
if clipCfgByte, err := json.Marshal(v["clipCfg"]); err == nil {
|
|
||||||
node.ClipCfg = string(clipCfgByte)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 图标属性
|
|
||||||
if icon, ok := v["icon"]; ok && icon != nil {
|
|
||||||
if iconByte, err := json.Marshal(icon); err == nil {
|
|
||||||
node.Icon = string(iconByte)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graphs = append(graphs, node)
|
|
||||||
}
|
|
||||||
return graphs
|
|
||||||
}
|
|
||||||
|
|
||||||
// saveEdge 图数据Edge
|
|
||||||
func (s *ChartGraphImpl) saveEdge(rowGroup string, edges []map[string]any) []model.ChartGraph {
|
|
||||||
var graphs []model.ChartGraph
|
|
||||||
for _, v := range edges {
|
|
||||||
edge := model.ChartGraph{
|
|
||||||
RowType: "edge",
|
|
||||||
RowGroup: rowGroup,
|
|
||||||
ID: v["id"].(string),
|
|
||||||
Source: v["source"].(string),
|
|
||||||
Target: v["target"].(string),
|
|
||||||
Type: v["type"].(string),
|
|
||||||
}
|
|
||||||
|
|
||||||
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
|
||||||
edge.Style = string(styleByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
if label, ok := v["label"]; ok && label != nil {
|
|
||||||
edge.Label = label.(string)
|
|
||||||
}
|
|
||||||
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
|
||||||
edge.LabelCfg = string(labelCfgByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
graphs = append(graphs, edge)
|
|
||||||
}
|
|
||||||
return graphs
|
|
||||||
}
|
|
||||||
|
|
||||||
// saveCombo 图数据Combo
|
|
||||||
func (s *ChartGraphImpl) saveCombo(rowGroup string, combos []map[string]any) []model.ChartGraph {
|
|
||||||
var graphs []model.ChartGraph
|
|
||||||
for _, v := range combos {
|
|
||||||
combo := model.ChartGraph{
|
|
||||||
RowType: "combo",
|
|
||||||
RowGroup: rowGroup,
|
|
||||||
ID: v["id"].(string),
|
|
||||||
X: v["x"].(float64),
|
|
||||||
Y: v["y"].(float64),
|
|
||||||
Type: v["type"].(string),
|
|
||||||
}
|
|
||||||
if depth, ok := v["depth"]; ok && depth != nil {
|
|
||||||
combo.Depth = int(depth.(float64))
|
|
||||||
}
|
|
||||||
if styleByte, err := json.Marshal(v["style"]); err == nil {
|
|
||||||
combo.Style = string(styleByte)
|
|
||||||
}
|
|
||||||
if paddingByte, err := json.Marshal(v["padding"]); err == nil {
|
|
||||||
combo.Padding = string(paddingByte)
|
|
||||||
}
|
|
||||||
if childrenByte, err := json.Marshal(v["children"]); err == nil {
|
|
||||||
combo.Children = string(childrenByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 元素大小
|
|
||||||
if sizeByte, err := json.Marshal(v["size"]); err == nil {
|
|
||||||
combo.Size = string(sizeByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签文本
|
|
||||||
if label, ok := v["label"]; ok && label != nil {
|
|
||||||
combo.Label = label.(string)
|
|
||||||
}
|
|
||||||
if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
|
|
||||||
combo.LabelCfg = string(labelCfgByte)
|
|
||||||
}
|
|
||||||
|
|
||||||
graphs = append(graphs, combo)
|
|
||||||
}
|
|
||||||
return graphs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除所组图数据
|
|
||||||
func (s *ChartGraphImpl) DeleteGroup(rowGroup string) int64 {
|
|
||||||
return s.graphRepository.DeleteGroup(rowGroup)
|
|
||||||
}
|
|
||||||
@@ -52,6 +52,7 @@ func Setup(router *gin.Engine) {
|
|||||||
// Count: 10,
|
// Count: 10,
|
||||||
// Type: middleware.LIMIT_IP,
|
// Type: middleware.LIMIT_IP,
|
||||||
// }),
|
// }),
|
||||||
|
middleware.CryptoApi(true, true),
|
||||||
controller.NewAccount.Login,
|
controller.NewAccount.Login,
|
||||||
)
|
)
|
||||||
indexGroup.GET("/getInfo", middleware.PreAuthorize(nil), controller.NewAccount.Info)
|
indexGroup.GET("/getInfo", middleware.PreAuthorize(nil), controller.NewAccount.Info)
|
||||||
@@ -74,6 +75,7 @@ func Setup(router *gin.Engine) {
|
|||||||
// Count: 10,
|
// Count: 10,
|
||||||
// Type: middleware.LIMIT_IP,
|
// Type: middleware.LIMIT_IP,
|
||||||
// }),
|
// }),
|
||||||
|
middleware.CryptoApi(true, true),
|
||||||
controller.NewRegister.Register,
|
controller.NewRegister.Register,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 AccountController 结构体
|
// 实例化控制层 AccountController 结构体
|
||||||
var NewAccount = &AccountController{
|
var NewAccount = &AccountController{
|
||||||
accountService: commonService.NewAccountImpl,
|
accountService: commonService.NewAccount,
|
||||||
sysLogLoginService: systemService.NewSysLogLoginImpl,
|
sysLogLoginService: systemService.NewSysLogLoginImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +25,7 @@ var NewAccount = &AccountController{
|
|||||||
//
|
//
|
||||||
// PATH /
|
// PATH /
|
||||||
type AccountController struct {
|
type AccountController struct {
|
||||||
// 账号身份操作服务
|
accountService *commonService.Account // 账号身份操作服务
|
||||||
accountService commonService.IAccount
|
|
||||||
// 系统登录访问
|
// 系统登录访问
|
||||||
sysLogLoginService systemService.ISysLogLogin
|
sysLogLoginService systemService.ISysLogLogin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 BootloaderController 结构体
|
// 实例化控制层 BootloaderController 结构体
|
||||||
var NewBootloader = &BootloaderController{
|
var NewBootloader = &BootloaderController{
|
||||||
accountService: commonService.NewAccountImpl,
|
accountService: commonService.NewAccount,
|
||||||
sysUserService: systemService.NewSysUserImpl,
|
sysUserService: systemService.NewSysUserImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,8 +26,7 @@ var NewBootloader = &BootloaderController{
|
|||||||
//
|
//
|
||||||
// PATH /bootloader
|
// PATH /bootloader
|
||||||
type BootloaderController struct {
|
type BootloaderController struct {
|
||||||
// 账号身份操作服务
|
accountService *commonService.Account // 账号身份操作服务
|
||||||
accountService commonService.IAccount
|
|
||||||
// 用户信息服务
|
// 用户信息服务
|
||||||
sysUserService systemService.ISysUser
|
sysUserService systemService.ISysUser
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,194 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import "be.ems/src/framework/vo"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/config"
|
||||||
|
adminConstants "be.ems/src/framework/constants/admin"
|
||||||
|
"be.ems/src/framework/constants/cachekey"
|
||||||
|
"be.ems/src/framework/constants/common"
|
||||||
|
"be.ems/src/framework/redis"
|
||||||
|
"be.ems/src/framework/utils/crypto"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/vo"
|
||||||
|
"be.ems/src/modules/system/model"
|
||||||
|
systemService "be.ems/src/modules/system/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 Account 结构体
|
||||||
|
var NewAccount = &Account{
|
||||||
|
sysUserService: systemService.NewSysUserImpl,
|
||||||
|
sysConfigService: systemService.NewSysConfigImpl,
|
||||||
|
sysRoleService: systemService.NewSysRoleImpl,
|
||||||
|
sysMenuService: systemService.NewSysMenuImpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账号身份操作服务 服务层处理
|
||||||
|
type Account struct {
|
||||||
|
// 用户信息服务
|
||||||
|
sysUserService systemService.ISysUser
|
||||||
|
// 参数配置服务
|
||||||
|
sysConfigService systemService.ISysConfig
|
||||||
|
// 角色服务
|
||||||
|
sysRoleService systemService.ISysRole
|
||||||
|
// 菜单服务
|
||||||
|
sysMenuService systemService.ISysMenu
|
||||||
|
}
|
||||||
|
|
||||||
// 账号身份操作服务 服务层接口
|
|
||||||
type IAccount interface {
|
|
||||||
// ValidateCaptcha 校验验证码
|
// ValidateCaptcha 校验验证码
|
||||||
ValidateCaptcha(code, uuid string) error
|
func (s *Account) ValidateCaptcha(code, uuid string) error {
|
||||||
|
// 验证码检查,从数据库配置获取验证码开关 true开启,false关闭
|
||||||
|
captchaEnabledStr := s.sysConfigService.SelectConfigValueByKey("sys.account.captchaEnabled")
|
||||||
|
if !parse.Boolean(captchaEnabledStr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if code == "" || uuid == "" {
|
||||||
|
// 验证码信息错误
|
||||||
|
return fmt.Errorf("captcha.err")
|
||||||
|
}
|
||||||
|
verifyKey := cachekey.CAPTCHA_CODE_KEY + 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
|
||||||
|
}
|
||||||
|
|
||||||
// LoginByUsername 登录生成token
|
// LoginByUsername 登录创建用户信息
|
||||||
LoginByUsername(username, password string) (vo.LoginUser, error)
|
func (s *Account) LoginByUsername(username, password string) (vo.LoginUser, error) {
|
||||||
|
loginUser := vo.LoginUser{}
|
||||||
|
|
||||||
|
// 检查密码重试次数
|
||||||
|
retrykey, retryCount, lockTime, err := s.passwordRetryCount(username)
|
||||||
|
if err != nil {
|
||||||
|
return loginUser, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询用户登录账号
|
||||||
|
sysUser := s.sysUserService.SelectUserByUserName(username)
|
||||||
|
if sysUser.UserName != username {
|
||||||
|
return loginUser, fmt.Errorf("login.errNameOrPasswd")
|
||||||
|
}
|
||||||
|
if sysUser.DelFlag == common.STATUS_YES {
|
||||||
|
// 对不起,您的账号已被删除
|
||||||
|
return loginUser, fmt.Errorf("login.errDelFlag")
|
||||||
|
}
|
||||||
|
if sysUser.Status == common.STATUS_NO {
|
||||||
|
return loginUser, fmt.Errorf("login.errStatus")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检验用户密码
|
||||||
|
compareBool := crypto.BcryptCompare(password, sysUser.Password)
|
||||||
|
if !compareBool {
|
||||||
|
redis.SetByExpire("", retrykey, retryCount+1, lockTime)
|
||||||
|
// 用户不存在或密码错误
|
||||||
|
return loginUser, fmt.Errorf("login.errNameOrPasswd")
|
||||||
|
} else {
|
||||||
|
// 清除错误记录次数
|
||||||
|
s.ClearLoginRecordCache(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录用户信息
|
||||||
|
loginUser.UserID = sysUser.UserID
|
||||||
|
loginUser.DeptID = sysUser.DeptID
|
||||||
|
loginUser.User = sysUser
|
||||||
|
// 用户权限组标识
|
||||||
|
isAdmin := config.IsAdmin(sysUser.UserID)
|
||||||
|
if isAdmin {
|
||||||
|
loginUser.Permissions = []string{adminConstants.PERMISSION}
|
||||||
|
} else {
|
||||||
|
perms := s.sysMenuService.SelectMenuPermsByUserId(sysUser.UserID)
|
||||||
|
loginUser.Permissions = parse.RemoveDuplicates(perms)
|
||||||
|
}
|
||||||
|
return loginUser, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateLoginDateAndIP 更新登录时间和IP
|
// UpdateLoginDateAndIP 更新登录时间和IP
|
||||||
UpdateLoginDateAndIP(loginUser *vo.LoginUser) bool
|
func (s *Account) UpdateLoginDateAndIP(loginUser *vo.LoginUser) bool {
|
||||||
|
sysUser := loginUser.User
|
||||||
|
userInfo := model.SysUser{
|
||||||
|
UserID: sysUser.UserID,
|
||||||
|
LoginIP: sysUser.LoginIP,
|
||||||
|
LoginDate: sysUser.LoginDate,
|
||||||
|
UpdateBy: sysUser.UserName,
|
||||||
|
Sex: sysUser.Sex,
|
||||||
|
PhoneNumber: sysUser.PhoneNumber,
|
||||||
|
Email: sysUser.Email,
|
||||||
|
Remark: sysUser.Remark,
|
||||||
|
}
|
||||||
|
rows := s.sysUserService.UpdateUser(userInfo)
|
||||||
|
return rows > 0
|
||||||
|
}
|
||||||
|
|
||||||
// ClearLoginRecordCache 清除错误记录次数
|
// ClearLoginRecordCache 清除错误记录次数
|
||||||
ClearLoginRecordCache(username string) bool
|
func (s *Account) ClearLoginRecordCache(username string) bool {
|
||||||
|
cacheKey := cachekey.PWD_ERR_CNT_KEY + username
|
||||||
|
hasKey, _ := redis.Has("", cacheKey)
|
||||||
|
if hasKey {
|
||||||
|
delOk, _ := redis.Del("", cacheKey)
|
||||||
|
return delOk
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// passwordRetryCount 密码重试次数
|
||||||
|
func (s *Account) passwordRetryCount(username string) (string, int64, time.Duration, error) {
|
||||||
|
// 从数据库配置获取登录次数和错误锁定时间
|
||||||
|
maxRetryCountStr := s.sysConfigService.SelectConfigValueByKey("sys.user.maxRetryCount")
|
||||||
|
lockTimeStr := s.sysConfigService.SelectConfigValueByKey("sys.user.lockTime")
|
||||||
|
|
||||||
|
// 验证登录次数和错误锁定时间
|
||||||
|
maxRetryCount := parse.Number(maxRetryCountStr)
|
||||||
|
lockTime := parse.Number(lockTimeStr)
|
||||||
|
// 验证缓存记录次数
|
||||||
|
retrykey := cachekey.PWD_ERR_CNT_KEY + username
|
||||||
|
retryCount, err := redis.Get("", retrykey)
|
||||||
|
if retryCount == "" || err != nil {
|
||||||
|
retryCount = "0"
|
||||||
|
}
|
||||||
|
// 是否超过错误值
|
||||||
|
retryCountInt64 := parse.Number(retryCount)
|
||||||
|
if retryCountInt64 >= maxRetryCount {
|
||||||
|
// 密码输入错误多次,帐户已被锁定
|
||||||
|
errorMsg := fmt.Errorf("login.errRetryPasswd")
|
||||||
|
return retrykey, retryCountInt64, time.Duration(lockTime) * time.Minute, errorMsg
|
||||||
|
}
|
||||||
|
return retrykey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RoleAndMenuPerms 角色和菜单数据权限
|
// RoleAndMenuPerms 角色和菜单数据权限
|
||||||
RoleAndMenuPerms(userId string, isAdmin bool) ([]string, []string)
|
func (s *Account) RoleAndMenuPerms(userId string, isAdmin bool) ([]string, []string) {
|
||||||
|
if isAdmin {
|
||||||
|
return []string{adminConstants.ROLE_KEY}, []string{adminConstants.PERMISSION}
|
||||||
|
} else {
|
||||||
|
// 角色key
|
||||||
|
roleGroup := []string{}
|
||||||
|
roles := s.sysRoleService.SelectRoleListByUserId(userId)
|
||||||
|
for _, role := range roles {
|
||||||
|
roleGroup = append(roleGroup, role.RoleKey)
|
||||||
|
}
|
||||||
|
// 菜单权限key
|
||||||
|
perms := s.sysMenuService.SelectMenuPermsByUserId(userId)
|
||||||
|
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RouteMenus 前端路由所需要的菜单
|
// RouteMenus 前端路由所需要的菜单
|
||||||
RouteMenus(userId string, isAdmin bool) []vo.Router
|
func (s *Account) RouteMenus(userId string, isAdmin bool) []vo.Router {
|
||||||
|
var buildMenus []vo.Router
|
||||||
|
if isAdmin {
|
||||||
|
menus := s.sysMenuService.SelectMenuTreeByUserId("*")
|
||||||
|
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||||
|
} else {
|
||||||
|
menus := s.sysMenuService.SelectMenuTreeByUserId(userId)
|
||||||
|
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||||||
|
}
|
||||||
|
return buildMenus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/src/framework/config"
|
|
||||||
adminConstants "be.ems/src/framework/constants/admin"
|
|
||||||
"be.ems/src/framework/constants/cachekey"
|
|
||||||
"be.ems/src/framework/constants/common"
|
|
||||||
"be.ems/src/framework/redis"
|
|
||||||
"be.ems/src/framework/utils/crypto"
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
"be.ems/src/framework/vo"
|
|
||||||
"be.ems/src/modules/system/model"
|
|
||||||
systemService "be.ems/src/modules/system/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 AccountImpl 结构体
|
|
||||||
var NewAccountImpl = &AccountImpl{
|
|
||||||
sysUserService: systemService.NewSysUserImpl,
|
|
||||||
sysConfigService: systemService.NewSysConfigImpl,
|
|
||||||
sysRoleService: systemService.NewSysRoleImpl,
|
|
||||||
sysMenuService: systemService.NewSysMenuImpl,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 账号身份操作服务 服务层处理
|
|
||||||
type AccountImpl struct {
|
|
||||||
// 用户信息服务
|
|
||||||
sysUserService systemService.ISysUser
|
|
||||||
// 参数配置服务
|
|
||||||
sysConfigService systemService.ISysConfig
|
|
||||||
// 角色服务
|
|
||||||
sysRoleService systemService.ISysRole
|
|
||||||
// 菜单服务
|
|
||||||
sysMenuService systemService.ISysMenu
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateCaptcha 校验验证码
|
|
||||||
func (s *AccountImpl) ValidateCaptcha(code, uuid string) error {
|
|
||||||
// 验证码检查,从数据库配置获取验证码开关 true开启,false关闭
|
|
||||||
captchaEnabledStr := s.sysConfigService.SelectConfigValueByKey("sys.account.captchaEnabled")
|
|
||||||
if !parse.Boolean(captchaEnabledStr) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if code == "" || uuid == "" {
|
|
||||||
// 验证码信息错误
|
|
||||||
return fmt.Errorf("captcha.err")
|
|
||||||
}
|
|
||||||
verifyKey := cachekey.CAPTCHA_CODE_KEY + 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoginByUsername 登录创建用户信息
|
|
||||||
func (s *AccountImpl) LoginByUsername(username, password string) (vo.LoginUser, error) {
|
|
||||||
loginUser := vo.LoginUser{}
|
|
||||||
|
|
||||||
// 检查密码重试次数
|
|
||||||
retrykey, retryCount, lockTime, err := s.passwordRetryCount(username)
|
|
||||||
if err != nil {
|
|
||||||
return loginUser, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询用户登录账号
|
|
||||||
sysUser := s.sysUserService.SelectUserByUserName(username)
|
|
||||||
if sysUser.UserName != username {
|
|
||||||
return loginUser, fmt.Errorf("login.errNameOrPasswd")
|
|
||||||
}
|
|
||||||
if sysUser.DelFlag == common.STATUS_YES {
|
|
||||||
// 对不起,您的账号已被删除
|
|
||||||
return loginUser, fmt.Errorf("login.errDelFlag")
|
|
||||||
}
|
|
||||||
if sysUser.Status == common.STATUS_NO {
|
|
||||||
return loginUser, fmt.Errorf("login.errStatus")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检验用户密码
|
|
||||||
compareBool := crypto.BcryptCompare(password, sysUser.Password)
|
|
||||||
if !compareBool {
|
|
||||||
redis.SetByExpire("", retrykey, retryCount+1, lockTime)
|
|
||||||
// 用户不存在或密码错误
|
|
||||||
return loginUser, fmt.Errorf("login.errNameOrPasswd")
|
|
||||||
} else {
|
|
||||||
// 清除错误记录次数
|
|
||||||
s.ClearLoginRecordCache(username)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录用户信息
|
|
||||||
loginUser.UserID = sysUser.UserID
|
|
||||||
loginUser.DeptID = sysUser.DeptID
|
|
||||||
loginUser.User = sysUser
|
|
||||||
// 用户权限组标识
|
|
||||||
isAdmin := config.IsAdmin(sysUser.UserID)
|
|
||||||
if isAdmin {
|
|
||||||
loginUser.Permissions = []string{adminConstants.PERMISSION}
|
|
||||||
} else {
|
|
||||||
perms := s.sysMenuService.SelectMenuPermsByUserId(sysUser.UserID)
|
|
||||||
loginUser.Permissions = parse.RemoveDuplicates(perms)
|
|
||||||
}
|
|
||||||
return loginUser, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateLoginDateAndIP 更新登录时间和IP
|
|
||||||
func (s *AccountImpl) UpdateLoginDateAndIP(loginUser *vo.LoginUser) bool {
|
|
||||||
sysUser := loginUser.User
|
|
||||||
userInfo := model.SysUser{
|
|
||||||
UserID: sysUser.UserID,
|
|
||||||
LoginIP: sysUser.LoginIP,
|
|
||||||
LoginDate: sysUser.LoginDate,
|
|
||||||
UpdateBy: sysUser.UserName,
|
|
||||||
}
|
|
||||||
rows := s.sysUserService.UpdateUser(userInfo)
|
|
||||||
return rows > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearLoginRecordCache 清除错误记录次数
|
|
||||||
func (s *AccountImpl) ClearLoginRecordCache(username string) bool {
|
|
||||||
cacheKey := cachekey.PWD_ERR_CNT_KEY + username
|
|
||||||
hasKey, _ := redis.Has("", cacheKey)
|
|
||||||
if hasKey {
|
|
||||||
delOk, _ := redis.Del("", cacheKey)
|
|
||||||
return delOk
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// passwordRetryCount 密码重试次数
|
|
||||||
func (s *AccountImpl) passwordRetryCount(username string) (string, int64, time.Duration, error) {
|
|
||||||
// 从数据库配置获取登录次数和错误锁定时间
|
|
||||||
maxRetryCountStr := s.sysConfigService.SelectConfigValueByKey("sys.user.maxRetryCount")
|
|
||||||
lockTimeStr := s.sysConfigService.SelectConfigValueByKey("sys.user.lockTime")
|
|
||||||
|
|
||||||
// 验证登录次数和错误锁定时间
|
|
||||||
maxRetryCount := parse.Number(maxRetryCountStr)
|
|
||||||
lockTime := parse.Number(lockTimeStr)
|
|
||||||
// 验证缓存记录次数
|
|
||||||
retrykey := cachekey.PWD_ERR_CNT_KEY + username
|
|
||||||
retryCount, err := redis.Get("", retrykey)
|
|
||||||
if retryCount == "" || err != nil {
|
|
||||||
retryCount = "0"
|
|
||||||
}
|
|
||||||
// 是否超过错误值
|
|
||||||
retryCountInt64 := parse.Number(retryCount)
|
|
||||||
if retryCountInt64 >= maxRetryCount {
|
|
||||||
// 密码输入错误多次,帐户已被锁定
|
|
||||||
errorMsg := fmt.Errorf("login.errRetryPasswd")
|
|
||||||
return retrykey, retryCountInt64, time.Duration(lockTime) * time.Minute, errorMsg
|
|
||||||
}
|
|
||||||
return retrykey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoleAndMenuPerms 角色和菜单数据权限
|
|
||||||
func (s *AccountImpl) RoleAndMenuPerms(userId string, isAdmin bool) ([]string, []string) {
|
|
||||||
if isAdmin {
|
|
||||||
return []string{adminConstants.ROLE_KEY}, []string{adminConstants.PERMISSION}
|
|
||||||
} else {
|
|
||||||
// 角色key
|
|
||||||
roleGroup := []string{}
|
|
||||||
roles := s.sysRoleService.SelectRoleListByUserId(userId)
|
|
||||||
for _, role := range roles {
|
|
||||||
roleGroup = append(roleGroup, role.RoleKey)
|
|
||||||
}
|
|
||||||
// 菜单权限key
|
|
||||||
perms := s.sysMenuService.SelectMenuPermsByUserId(userId)
|
|
||||||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RouteMenus 前端路由所需要的菜单
|
|
||||||
func (s *AccountImpl) RouteMenus(userId string, isAdmin bool) []vo.Router {
|
|
||||||
var buildMenus []vo.Router
|
|
||||||
if isAdmin {
|
|
||||||
menus := s.sysMenuService.SelectMenuTreeByUserId("*")
|
|
||||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
|
||||||
} else {
|
|
||||||
menus := s.sysMenuService.SelectMenuTreeByUserId(userId)
|
|
||||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
|
||||||
}
|
|
||||||
return buildMenus
|
|
||||||
}
|
|
||||||
160
src/modules/crontask/processor/exportTable/exportTable.go
Normal file
160
src/modules/crontask/processor/exportTable/exportTable.go
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
package exportTable
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/lib/dborm"
|
||||||
|
"be.ems/lib/log"
|
||||||
|
"be.ems/src/framework/cron"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NewProcessor = &BarProcessor{
|
||||||
|
progress: 0,
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// bar 队列任务处理
|
||||||
|
type BarProcessor struct {
|
||||||
|
// 任务进度
|
||||||
|
progress int
|
||||||
|
// 执行次数
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
type BarParams struct {
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
TableName string `json:"tableName"`
|
||||||
|
Columns string `json:"columns"` // exported column name of time string
|
||||||
|
TimeCol string `json:"timeCol"` // time stamp of column name
|
||||||
|
TimeUnit string `json:"timeUnit"` // timestamp unit: second/micro/milli
|
||||||
|
Extras string `json:"extras"` // extras condition for where
|
||||||
|
FilePath string `json:"filePath"` // file path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BarProcessor) Execute(data any) (any, error) {
|
||||||
|
s.count++
|
||||||
|
|
||||||
|
options := data.(cron.JobData)
|
||||||
|
sysJob := options.SysJob
|
||||||
|
var params BarParams
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(sysJob.TargetParams), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// mkdir if not exist
|
||||||
|
if _, err = os.Stat(params.FilePath); os.IsNotExist(err) {
|
||||||
|
err = os.MkdirAll(params.FilePath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to Mkdir:", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//duration = params.Duration
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
end := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
|
||||||
|
start := end.Add(-time.Duration(params.Duration) * time.Hour)
|
||||||
|
|
||||||
|
var startTime, endTime int64
|
||||||
|
switch params.TimeUnit {
|
||||||
|
case "second":
|
||||||
|
// 格式化时间戳为秒级
|
||||||
|
startTime = start.Unix()
|
||||||
|
endTime = end.Unix()
|
||||||
|
case "milli":
|
||||||
|
// 格式化时间戳为毫秒级
|
||||||
|
startTime = start.UnixMilli()
|
||||||
|
endTime = end.UnixMilli()
|
||||||
|
case "micro":
|
||||||
|
// 格式化时间戳为微妙级
|
||||||
|
startTime = start.UnixMicro()
|
||||||
|
endTime = end.UnixMicro()
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("error input parameter")
|
||||||
|
}
|
||||||
|
var query string
|
||||||
|
if params.Extras != "" {
|
||||||
|
query = fmt.Sprintf("SELECT %s FROM `%s` WHERE `%s` >= %d AND `%s` < %d AND %s",
|
||||||
|
params.Columns, params.TableName, params.TimeCol, startTime, params.TimeCol, endTime, params.Extras)
|
||||||
|
} else {
|
||||||
|
query = fmt.Sprintf("SELECT %s FROM `%s` WHERE `%s` >= %d AND `%s` < %d",
|
||||||
|
params.Columns, params.TableName, params.TimeCol, startTime, params.TimeCol, endTime)
|
||||||
|
}
|
||||||
|
log.Trace("query:", query)
|
||||||
|
filePath := fmt.Sprintf("%s/%s_export_%s.csv", params.FilePath, params.TableName, time.Now().Format("20060102150405"))
|
||||||
|
affected, err := s.exportData(query, filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回结果,用于记录执行结果
|
||||||
|
return map[string]any{
|
||||||
|
"msg": "sucess",
|
||||||
|
"filePath": filePath,
|
||||||
|
"affected": affected,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BarProcessor) exportData(query, filePath string) (int64, error) {
|
||||||
|
rows, err := dborm.XCoreDB().Query(query)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
// 创建 CSV 文件
|
||||||
|
file, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
writer := csv.NewWriter(file)
|
||||||
|
defer writer.Flush()
|
||||||
|
|
||||||
|
// 写入表头
|
||||||
|
columns, _ := rows.ColumnTypes()
|
||||||
|
header := make([]string, len(columns))
|
||||||
|
for i, col := range columns {
|
||||||
|
header[i] = col.Name()
|
||||||
|
}
|
||||||
|
if err := writer.Write(header); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入数据
|
||||||
|
var affected int64 = 0
|
||||||
|
for rows.Next() {
|
||||||
|
values := make([]sql.RawBytes, len(columns))
|
||||||
|
scanArgs := make([]interface{}, len(columns))
|
||||||
|
for i := range values {
|
||||||
|
scanArgs[i] = &values[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Scan(scanArgs...); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
record := make([]string, len(columns))
|
||||||
|
for i, val := range values {
|
||||||
|
if val == nil {
|
||||||
|
record[i] = ""
|
||||||
|
} else {
|
||||||
|
record[i] = string(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
affected++
|
||||||
|
if err := writer.Write(record); err != nil {
|
||||||
|
return affected, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected, nil
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var NewProcessor = &MonitorSysResourceProcessor{
|
var NewProcessor = &MonitorSysResourceProcessor{
|
||||||
monitorService: monitorService.NewMonitorImpl,
|
monitorService: monitorService.NewMonitor,
|
||||||
count: 0,
|
count: 0,
|
||||||
openDataCancel: false,
|
openDataCancel: false,
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ var NewProcessor = &MonitorSysResourceProcessor{
|
|||||||
// MonitorSysResourceProcessor 系统资源CPU/IO/Netword收集
|
// MonitorSysResourceProcessor 系统资源CPU/IO/Netword收集
|
||||||
type MonitorSysResourceProcessor struct {
|
type MonitorSysResourceProcessor struct {
|
||||||
// 服务器系统相关信息服务
|
// 服务器系统相关信息服务
|
||||||
monitorService monitorService.IMonitor
|
monitorService *monitorService.Monitor
|
||||||
// 执行次数
|
// 执行次数
|
||||||
count int
|
count int
|
||||||
// 是否已经开启数据通道
|
// 是否已经开启数据通道
|
||||||
|
|||||||
@@ -11,19 +11,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var NewProcessor = &NeConfigBackupProcessor{
|
var NewProcessor = &NeConfigBackupProcessor{
|
||||||
neConfigBackupService: neService.NewNeConfigBackupImpl,
|
neConfigBackupService: neService.NewNeConfigBackup,
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
count: 0,
|
count: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeConfigBackupProcessor 网元配置文件定期备份
|
// NeConfigBackupProcessor 网元配置文件定期备份
|
||||||
type NeConfigBackupProcessor struct {
|
type NeConfigBackupProcessor struct {
|
||||||
// 网元配置文件备份记录服务
|
neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
|
||||||
neConfigBackupService neService.INeConfigBackup
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
// 网元信息服务
|
count int // 执行次数
|
||||||
neInfoService neService.INeInfo
|
|
||||||
// 执行次数
|
|
||||||
count int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NeConfigBackupProcessor) Execute(data any) (any, error) {
|
func (s *NeConfigBackupProcessor) Execute(data any) (any, error) {
|
||||||
|
|||||||
45
src/modules/crontask/processor/ne_data_udm/ne_data_udm.go
Normal file
45
src/modules/crontask/processor/ne_data_udm/ne_data_udm.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package ne_data_udm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"be.ems/src/framework/cron"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
neDataService "be.ems/src/modules/network_data/service"
|
||||||
|
neModel "be.ems/src/modules/network_element/model"
|
||||||
|
neService "be.ems/src/modules/network_element/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NewProcessor = &NeDataUDM{
|
||||||
|
udmAuthService: neDataService.NewUDMAuthUser,
|
||||||
|
udmSubService: neDataService.NewUDMSubUser,
|
||||||
|
neInfoService: neService.NewNeInfo,
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NeDataUDM 网元配置文件定期备份
|
||||||
|
type NeDataUDM struct {
|
||||||
|
udmAuthService *neDataService.UDMAuthUser // UDM鉴权信息
|
||||||
|
udmSubService *neDataService.UDMSubUser // UDM签约信息
|
||||||
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
|
count int // 执行次数
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NeDataUDM) Execute(data any) (any, error) {
|
||||||
|
s.count++ // 执行次数加一
|
||||||
|
options := data.(cron.JobData)
|
||||||
|
sysJob := options.SysJob
|
||||||
|
logger.Infof("重复 %v 任务ID %s", options.Repeat, sysJob.JobID)
|
||||||
|
// 返回结果,用于记录执行结果
|
||||||
|
result := map[string]any{
|
||||||
|
"count": s.count,
|
||||||
|
}
|
||||||
|
|
||||||
|
neList := s.neInfoService.SelectList(neModel.NeInfo{NeType: "UDM"}, false, false)
|
||||||
|
for _, neInfo := range neList {
|
||||||
|
result[fmt.Sprintf("AuthNumber_%s", neInfo.NeId)] = s.udmAuthService.ResetData(neInfo.NeId)
|
||||||
|
result[fmt.Sprintf("SubNumber_%s", neInfo.NeId)] = s.udmSubService.ResetData(neInfo.NeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -5,10 +5,13 @@ import (
|
|||||||
"be.ems/src/modules/crontask/processor/backupEtcFromNE"
|
"be.ems/src/modules/crontask/processor/backupEtcFromNE"
|
||||||
"be.ems/src/modules/crontask/processor/delExpiredNeBackup"
|
"be.ems/src/modules/crontask/processor/delExpiredNeBackup"
|
||||||
"be.ems/src/modules/crontask/processor/deleteExpiredRecord"
|
"be.ems/src/modules/crontask/processor/deleteExpiredRecord"
|
||||||
|
"be.ems/src/modules/crontask/processor/exportTable"
|
||||||
"be.ems/src/modules/crontask/processor/genNeStateAlarm"
|
"be.ems/src/modules/crontask/processor/genNeStateAlarm"
|
||||||
"be.ems/src/modules/crontask/processor/getStateFromNE"
|
"be.ems/src/modules/crontask/processor/getStateFromNE"
|
||||||
processorMonitorSysResource "be.ems/src/modules/crontask/processor/monitor_sys_resource"
|
processorMonitorSysResource "be.ems/src/modules/crontask/processor/monitor_sys_resource"
|
||||||
processorNeConfigBackup "be.ems/src/modules/crontask/processor/ne_config_backup"
|
processorNeConfigBackup "be.ems/src/modules/crontask/processor/ne_config_backup"
|
||||||
|
processorNeDataUDM "be.ems/src/modules/crontask/processor/ne_data_udm"
|
||||||
|
"be.ems/src/modules/crontask/processor/removeFile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitCronQueue 初始定时任务队列
|
// InitCronQueue 初始定时任务队列
|
||||||
@@ -17,10 +20,14 @@ func InitCronQueue() {
|
|||||||
cron.CreateQueue("monitor_sys_resource", processorMonitorSysResource.NewProcessor)
|
cron.CreateQueue("monitor_sys_resource", processorMonitorSysResource.NewProcessor)
|
||||||
// 网元-网元配置文件定期备份
|
// 网元-网元配置文件定期备份
|
||||||
cron.CreateQueue("ne_config_backup", processorNeConfigBackup.NewProcessor)
|
cron.CreateQueue("ne_config_backup", processorNeConfigBackup.NewProcessor)
|
||||||
|
// 网元数据-UDM数据刷新同步
|
||||||
|
cron.CreateQueue("ne_data_udm", processorNeDataUDM.NewProcessor)
|
||||||
// delete expired NE backup file
|
// delete expired NE backup file
|
||||||
cron.CreateQueue("delExpiredNeBackup", delExpiredNeBackup.NewProcessor)
|
cron.CreateQueue("delExpiredNeBackup", delExpiredNeBackup.NewProcessor)
|
||||||
cron.CreateQueue("deleteExpiredRecord", deleteExpiredRecord.NewProcessor)
|
cron.CreateQueue("deleteExpiredRecord", deleteExpiredRecord.NewProcessor)
|
||||||
cron.CreateQueue("backupEtcFromNE", backupEtcFromNE.NewProcessor)
|
cron.CreateQueue("backupEtcFromNE", backupEtcFromNE.NewProcessor)
|
||||||
cron.CreateQueue("getStateFromNE", getStateFromNE.NewProcessor)
|
cron.CreateQueue("getStateFromNE", getStateFromNE.NewProcessor)
|
||||||
cron.CreateQueue("genNeStateAlarm", genNeStateAlarm.NewProcessor)
|
cron.CreateQueue("genNeStateAlarm", genNeStateAlarm.NewProcessor)
|
||||||
|
cron.CreateQueue("exportTable", exportTable.NewProcessor)
|
||||||
|
cron.CreateQueue("removeFile", removeFile.NewProcessor)
|
||||||
}
|
}
|
||||||
|
|||||||
159
src/modules/crontask/processor/removeFile/removeFile.go
Normal file
159
src/modules/crontask/processor/removeFile/removeFile.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package removeFile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/lib/log"
|
||||||
|
"be.ems/src/framework/cron"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NewProcessor = &BarProcessor{
|
||||||
|
progress: 0,
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// bar 队列任务处理
|
||||||
|
type BarProcessor struct {
|
||||||
|
// 任务进度
|
||||||
|
progress int
|
||||||
|
// 执行次数
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
type BarParams struct {
|
||||||
|
FilePath string `json:"filePath"` // file path
|
||||||
|
MaxDays int `json:"maxDays"`
|
||||||
|
MaxFiles *int `json:"maxFiles"` // keep max files
|
||||||
|
MaxSize *int64 `json:"maxSize"`
|
||||||
|
Extras string `json:"extras"` // extras condition for where
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
Path string
|
||||||
|
Info os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BarProcessor) Execute(data any) (any, error) {
|
||||||
|
s.count++
|
||||||
|
|
||||||
|
options := data.(cron.JobData)
|
||||||
|
sysJob := options.SysJob
|
||||||
|
var params []BarParams
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(sysJob.TargetParams), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []map[string]any{}
|
||||||
|
for _, param := range params {
|
||||||
|
res, _ := s.ExecuteOne(param)
|
||||||
|
result = append(result, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回结果,用于记录执行结果
|
||||||
|
return map[string]any{
|
||||||
|
"result": result,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BarProcessor) ExecuteOne(params BarParams) (map[string]any, error) {
|
||||||
|
var maxFiles int = 0
|
||||||
|
var maxSize int64 = 0
|
||||||
|
if params.MaxFiles != nil {
|
||||||
|
maxFiles = *params.MaxFiles
|
||||||
|
}
|
||||||
|
if params.MaxSize != nil {
|
||||||
|
maxSize = int64(*params.MaxSize * 1024 * 1024)
|
||||||
|
}
|
||||||
|
files, err := getFiles(params.FilePath)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]any{
|
||||||
|
"msg": "failed",
|
||||||
|
"err": err.Error(),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取本地时区
|
||||||
|
loc, err := time.LoadLocation("Local")
|
||||||
|
if err != nil {
|
||||||
|
return map[string]any{
|
||||||
|
"msg": "failed",
|
||||||
|
"err": err.Error(),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
cutoff := time.Now().In(loc).AddDate(0, 0, -params.MaxDays)
|
||||||
|
|
||||||
|
var oldFiles []FileInfo
|
||||||
|
for _, file := range files {
|
||||||
|
if file.Info.ModTime().Before(cutoff) {
|
||||||
|
oldFiles = append(oldFiles, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按修改时间排序文件(最旧的在前)
|
||||||
|
sort.Slice(oldFiles, func(i, j int) bool {
|
||||||
|
return oldFiles[i].Info.ModTime().Before(oldFiles[j].Info.ModTime())
|
||||||
|
})
|
||||||
|
|
||||||
|
deleted, errorDel := 0, 0
|
||||||
|
|
||||||
|
// 删除文件,直到满足文件总数不超过maxFiles个且总大小不超过maxSize的条件
|
||||||
|
var totalSize int64
|
||||||
|
for i, file := range oldFiles {
|
||||||
|
if (maxFiles > 0 && i >= maxFiles) || (maxSize > 0 && totalSize+file.Info.Size() > maxSize) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
err := os.Remove(file.Path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error deleting file:", file.Path, err)
|
||||||
|
errorDel++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalSize += file.Info.Size()
|
||||||
|
deleted++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果仍然有超过maxFiles个文件或总大小超过maxSize,继续删除最旧的文件
|
||||||
|
remainingFiles := files
|
||||||
|
sort.Slice(remainingFiles, func(i, j int) bool {
|
||||||
|
return remainingFiles[i].Info.ModTime().Before(remainingFiles[j].Info.ModTime())
|
||||||
|
})
|
||||||
|
|
||||||
|
for (maxFiles > 0 && len(remainingFiles) > maxFiles) || (maxSize > 0 && totalSize > maxSize) {
|
||||||
|
file := remainingFiles[0]
|
||||||
|
err := os.Remove(file.Path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error deleting file:", file.Path, err)
|
||||||
|
remainingFiles = remainingFiles[1:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalSize -= file.Info.Size()
|
||||||
|
remainingFiles = remainingFiles[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回结果,用于记录执行结果
|
||||||
|
return map[string]any{
|
||||||
|
"msg": "successed",
|
||||||
|
"filePath": params.FilePath,
|
||||||
|
"deleted": deleted,
|
||||||
|
"errorDel": errorDel,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFiles(dir string) ([]FileInfo, error) {
|
||||||
|
var files []FileInfo
|
||||||
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !info.IsDir() {
|
||||||
|
files = append(files, FileInfo{Path: path, Info: info})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return files, err
|
||||||
|
}
|
||||||
@@ -11,15 +11,14 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 MonitorInfoController 结构体
|
// 实例化控制层 MonitorInfoController 结构体
|
||||||
var NewMonitor = &MonitorController{
|
var NewMonitor = &MonitorController{
|
||||||
monitorService: service.NewMonitorImpl,
|
monitorService: service.NewMonitor,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务器资源监控信息
|
// 服务器资源监控信息
|
||||||
//
|
//
|
||||||
// PATH /monitor
|
// PATH /monitor
|
||||||
type MonitorController struct {
|
type MonitorController struct {
|
||||||
// 服务器系统相关信息服务
|
monitorService *service.Monitor // 服务器系统相关信息服务
|
||||||
monitorService service.IMonitor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 资源监控信息加载
|
// 资源监控信息加载
|
||||||
@@ -28,21 +27,14 @@ type MonitorController struct {
|
|||||||
func (s *MonitorController) Load(c *gin.Context) {
|
func (s *MonitorController) Load(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
var querys struct {
|
var querys struct {
|
||||||
// 数据类型all/load/cpu/memory/io/network
|
Type string `form:"type" binding:"required,oneof=all load cpu memory io network"` // 数据类型all/load/cpu/memory/io/network
|
||||||
Type string `form:"type" binding:"required,oneof=all load cpu memory io network"`
|
StartTime int64 `form:"startTime" binding:"required"` // 开始时间
|
||||||
// 开始时间
|
EndTime int64 `form:"endTime" binding:"required"` // 结束时间
|
||||||
StartTime int64 `form:"startTime" binding:"required"`
|
NeType string `form:"neType"` // 网元类型
|
||||||
// 结束时间
|
NeID string `form:"neId"` // 网元ID
|
||||||
EndTime int64 `form:"endTime" binding:"required"`
|
Name string `form:"name"` // 名称,networ和io时有效
|
||||||
// 网元类型
|
|
||||||
NeType string `form:"neType"`
|
|
||||||
// 网元ID
|
|
||||||
NeID string `form:"neId"`
|
|
||||||
// 名称,networ和iok时有效
|
|
||||||
Name string `form:"name"`
|
|
||||||
}
|
}
|
||||||
err := c.ShouldBindQuery(&querys)
|
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||||
if err != nil {
|
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,10 +141,8 @@ func (s *SysCacheController) ClearCacheKey(c *gin.Context) {
|
|||||||
func (s *SysCacheController) ClearCacheSafe(c *gin.Context) {
|
func (s *SysCacheController) ClearCacheSafe(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
caches := []model.SysCache{
|
caches := []model.SysCache{
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.user"), cachekey.LOGIN_TOKEN_KEY),
|
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.sys_config"), cachekey.SYS_CONFIG_KEY),
|
model.NewSysCacheNames(i18n.TKey(language, "cache.name.sys_config"), cachekey.SYS_CONFIG_KEY),
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.sys_dict"), cachekey.SYS_DICT_KEY),
|
model.NewSysCacheNames(i18n.TKey(language, "cache.name.sys_dict"), cachekey.SYS_DICT_KEY),
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.captcha_codes"), cachekey.CAPTCHA_CODE_KEY),
|
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.repeat_submit"), cachekey.REPEAT_SUBMIT_KEY),
|
model.NewSysCacheNames(i18n.TKey(language, "cache.name.repeat_submit"), cachekey.REPEAT_SUBMIT_KEY),
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.rate_limit"), cachekey.RATE_LIMIT_KEY),
|
model.NewSysCacheNames(i18n.TKey(language, "cache.name.rate_limit"), cachekey.RATE_LIMIT_KEY),
|
||||||
model.NewSysCacheNames(i18n.TKey(language, "cache.name.pwd_err_cnt"), cachekey.PWD_ERR_CNT_KEY),
|
model.NewSysCacheNames(i18n.TKey(language, "cache.name.pwd_err_cnt"), cachekey.PWD_ERR_CNT_KEY),
|
||||||
|
|||||||
@@ -22,18 +22,16 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 SysJobLogController 结构体
|
// 实例化控制层 SysJobLogController 结构体
|
||||||
var NewSysJob = &SysJobController{
|
var NewSysJob = &SysJobController{
|
||||||
sysJobService: service.NewSysJobImpl,
|
sysJobService: service.NewSysJob,
|
||||||
sysDictDataService: systemService.NewSysDictDataImpl,
|
sysDictDataService: systemService.NewSysDictData,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调度任务信息
|
// 调度任务信息
|
||||||
//
|
//
|
||||||
// PATH /monitor/job
|
// PATH /monitor/job
|
||||||
type SysJobController struct {
|
type SysJobController struct {
|
||||||
// 调度任务服务
|
sysJobService *service.SysJob // 调度任务服务
|
||||||
sysJobService service.ISysJob
|
sysDictDataService *systemService.SysDictData // 字典数据服务
|
||||||
// 字典数据服务
|
|
||||||
sysDictDataService systemService.ISysDictData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调度任务列表
|
// 调度任务列表
|
||||||
|
|||||||
@@ -21,18 +21,16 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 SysJobLogController 结构体
|
// 实例化控制层 SysJobLogController 结构体
|
||||||
var NewSysJobLog = &SysJobLogController{
|
var NewSysJobLog = &SysJobLogController{
|
||||||
sysJobLogService: service.NewSysJobLogImpl,
|
sysJobLogService: service.NewSysJobLog,
|
||||||
sysDictDataService: systemService.NewSysDictDataImpl,
|
sysDictDataService: systemService.NewSysDictData,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调度任务日志信息
|
// 调度任务日志信息
|
||||||
//
|
//
|
||||||
// PATH /monitor/jobLog
|
// PATH /monitor/jobLog
|
||||||
type SysJobLogController struct {
|
type SysJobLogController struct {
|
||||||
// 调度任务日志服务
|
sysJobLogService *service.SysJobLog // 调度任务日志服务
|
||||||
sysJobLogService service.ISysJobLog
|
sysDictDataService *systemService.SysDictData // 字典数据服务
|
||||||
// 字典数据服务
|
|
||||||
sysDictDataService systemService.ISysDictData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调度任务日志列表
|
// 调度任务日志列表
|
||||||
@@ -44,7 +42,7 @@ func (s *SysJobLogController) List(c *gin.Context) {
|
|||||||
querys := ctx.QueryMap(c)
|
querys := ctx.QueryMap(c)
|
||||||
// 任务ID优先级更高
|
// 任务ID优先级更高
|
||||||
if v, ok := querys["jobId"]; ok && v != nil {
|
if v, ok := querys["jobId"]; ok && v != nil {
|
||||||
jobInfo := service.NewSysJobImpl.SelectJobById(v.(string))
|
jobInfo := service.NewSysJob.SelectJobById(v.(string))
|
||||||
querys["jobName"] = jobInfo.JobName
|
querys["jobName"] = jobInfo.JobName
|
||||||
querys["jobGroup"] = jobInfo.JobGroup
|
querys["jobGroup"] = jobInfo.JobGroup
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"be.ems/src/framework/constants/cachekey"
|
"be.ems/src/framework/constants/cachekey"
|
||||||
"be.ems/src/framework/constants/roledatascope"
|
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
"be.ems/src/framework/redis"
|
"be.ems/src/framework/redis"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
@@ -20,15 +19,14 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 SysUserOnlineController 结构体
|
// 实例化控制层 SysUserOnlineController 结构体
|
||||||
var NewSysUserOnline = &SysUserOnlineController{
|
var NewSysUserOnline = &SysUserOnlineController{
|
||||||
sysUserOnlineService: service.NewSysUserOnlineImpl,
|
sysUserOnlineService: service.NewSysUserOnline,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在线用户监控
|
// 在线用户监控
|
||||||
//
|
//
|
||||||
// PATH /monitor/online
|
// PATH /monitor/online
|
||||||
type SysUserOnlineController struct {
|
type SysUserOnlineController struct {
|
||||||
// 在线用户服务
|
sysUserOnlineService *service.SysUserOnline // 在线用户服务
|
||||||
sysUserOnlineService service.ISysUserOnline
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在线用户列表
|
// 在线用户列表
|
||||||
@@ -38,43 +36,6 @@ func (s *SysUserOnlineController) List(c *gin.Context) {
|
|||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
ipaddr := c.Query("ipaddr")
|
ipaddr := c.Query("ipaddr")
|
||||||
userName := c.Query("userName")
|
userName := c.Query("userName")
|
||||||
data := map[string]any{
|
|
||||||
"total": 0,
|
|
||||||
"rows": []model.SysUserOnline{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当前登录用户
|
|
||||||
currentUser, _ := ctx.LoginUser(c)
|
|
||||||
currentRoleKey := ""
|
|
||||||
currentRoleDataScope := ""
|
|
||||||
if len(currentUser.User.Roles) > 0 {
|
|
||||||
role := currentUser.User.Roles[0]
|
|
||||||
currentRoleKey = role.RoleKey
|
|
||||||
currentRoleDataScope = role.DataScope
|
|
||||||
}
|
|
||||||
|
|
||||||
if currentRoleKey == "" {
|
|
||||||
c.JSON(200, result.Ok(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hasRoleDataScope := func(loginUser vo.LoginUser) bool {
|
|
||||||
if currentRoleDataScope == roledatascope.ALL {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if currentRoleDataScope == roledatascope.CUSTOM {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if currentRoleDataScope == roledatascope.DEPT && loginUser.DeptID == currentUser.DeptID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if currentRoleDataScope == roledatascope.DEPT_AND_CHILD && (strings.Contains(loginUser.User.Dept.Ancestors, currentUser.DeptID) || currentUser.DeptID == loginUser.DeptID) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if currentRoleDataScope == roledatascope.SELF && loginUser.UserID == currentUser.UserID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取所有在线用户key
|
// 获取所有在线用户key
|
||||||
keys, _ := redis.GetKeys("", cachekey.LOGIN_TOKEN_KEY+"*")
|
keys, _ := redis.GetKeys("", cachekey.LOGIN_TOKEN_KEY+"*")
|
||||||
@@ -106,10 +67,6 @@ func (s *SysUserOnlineController) List(c *gin.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasRoleDataScope(loginUser) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
onlineUser := s.sysUserOnlineService.LoginUserToUserOnline(loginUser)
|
onlineUser := s.sysUserOnlineService.LoginUserToUserOnline(loginUser)
|
||||||
if onlineUser.TokenID != "" {
|
if onlineUser.TokenID != "" {
|
||||||
onlineUser.LoginLocation = i18n.TKey(language, onlineUser.LoginLocation)
|
onlineUser.LoginLocation = i18n.TKey(language, onlineUser.LoginLocation)
|
||||||
@@ -146,9 +103,10 @@ func (s *SysUserOnlineController) List(c *gin.Context) {
|
|||||||
return filteredUserOnlines[j].LoginTime > filteredUserOnlines[i].LoginTime
|
return filteredUserOnlines[j].LoginTime > filteredUserOnlines[i].LoginTime
|
||||||
})
|
})
|
||||||
|
|
||||||
data["total"] = len(filteredUserOnlines)
|
c.JSON(200, result.Ok(map[string]any{
|
||||||
data["rows"] = filteredUserOnlines
|
"total": len(filteredUserOnlines),
|
||||||
c.JSON(200, result.Ok(data))
|
"rows": filteredUserOnlines,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在线用户强制退出
|
// 在线用户强制退出
|
||||||
|
|||||||
@@ -9,27 +9,27 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 SystemInfoController 结构体
|
// 实例化控制层 SystemInfoController 结构体
|
||||||
var NewSystemInfo = &SystemInfoController{
|
var NewSystemInfo = &SystemInfoController{
|
||||||
systemInfogService: service.NewSystemInfoImpl,
|
systemInfogService: service.NewSystemInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务器监控信息
|
// 服务器监控信息
|
||||||
//
|
//
|
||||||
// PATH /monitor/system-info
|
// PATH /monitor/system-info
|
||||||
type SystemInfoController struct {
|
type SystemInfoController struct {
|
||||||
// 服务器系统相关信息服务
|
systemInfogService *service.SystemInfo // 服务器系统相关信息服务
|
||||||
systemInfogService service.ISystemInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务器信息
|
// 服务器信息
|
||||||
//
|
//
|
||||||
// GET /
|
// GET /
|
||||||
func (s *SystemInfoController) Info(c *gin.Context) {
|
func (s *SystemInfoController) Info(c *gin.Context) {
|
||||||
c.JSON(200, result.OkData(map[string]any{
|
data := map[string]any{
|
||||||
"cpu": s.systemInfogService.CPUInfo(),
|
"cpu": s.systemInfogService.CPUInfo(),
|
||||||
"memory": s.systemInfogService.MemoryInfo(),
|
"memory": s.systemInfogService.MemoryInfo(),
|
||||||
"network": s.systemInfogService.NetworkInfo(),
|
"network": s.systemInfogService.NetworkInfo(),
|
||||||
"time": s.systemInfogService.TimeInfo(),
|
"time": s.systemInfogService.TimeInfo(),
|
||||||
"system": s.systemInfogService.SystemInfo(),
|
"system": s.systemInfogService.SystemInfo(),
|
||||||
"disk": s.systemInfogService.DiskInfo(),
|
"disk": s.systemInfogService.DiskInfo(),
|
||||||
}))
|
}
|
||||||
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,19 @@ package model
|
|||||||
|
|
||||||
// MonitorBase 监控_基本信息 monitor_base
|
// MonitorBase 监控_基本信息 monitor_base
|
||||||
type MonitorBase struct {
|
type MonitorBase struct {
|
||||||
// id
|
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
ID int64 `json:"id" gorm:"primaryKey"`
|
CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间
|
||||||
// 创建时间
|
CPU float64 `json:"cpu" gorm:"cpu"` // cpu使用率
|
||||||
CreateTime int64 `json:"createTime"`
|
LoadUsage float64 `json:"loadUsage" gorm:"load_usage"` // cpu平均使用率
|
||||||
// cpu使用率
|
CPULoad1 float64 `json:"cpuLoad1" gorm:"cpu_load1"` // cpu使用1分钟
|
||||||
CPU float64 `json:"cpu"`
|
CPULoad5 float64 `json:"cpuLoad5" gorm:"cpu_load5"` // cpu使用5分钟
|
||||||
// cpu平均使用率
|
CPULoad15 float64 `json:"cpuLoad15" gorm:"cpu_load15"` // cpu使用15分钟
|
||||||
LoadUsage float64 `json:"loadUsage"`
|
Memory float64 `json:"memory" gorm:"memory"` // 内存使用率
|
||||||
// cpu使用1分钟
|
NeType string `json:"neType" gorm:"ne_type"` // 网元类型
|
||||||
CPULoad1 float64 `json:"cpuLoad1"`
|
NeID string `json:"neId" gorm:"ne_id"` // 网元ID
|
||||||
// cpu使用5分钟
|
|
||||||
CPULoad5 float64 `json:"cpuLoad5"`
|
|
||||||
// cpu使用15分钟
|
|
||||||
CPULoad15 float64 `json:"cpuLoad15"`
|
|
||||||
// 内存使用率
|
|
||||||
Memory float64 `json:"memory"`
|
|
||||||
// 网元ID
|
|
||||||
NeType string `json:"neType"`
|
|
||||||
// 网元类型
|
|
||||||
NeID string `json:"neId"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MonitorBase) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*MonitorBase) TableName() string {
|
||||||
return "monitor_base"
|
return "monitor_base"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,18 @@ package model
|
|||||||
|
|
||||||
// MonitorIO 监控_磁盘IO monitor_io
|
// MonitorIO 监控_磁盘IO monitor_io
|
||||||
type MonitorIO struct {
|
type MonitorIO struct {
|
||||||
// id
|
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
ID int64 `json:"id" gorm:"primaryKey"`
|
CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间
|
||||||
// 创建时间
|
Name string `json:"name" gorm:"name"` // 磁盘名
|
||||||
CreateTime int64 `json:"createTime"`
|
Read int64 `json:"read" gorm:"read"` // 读取K
|
||||||
// 磁盘名
|
Write int64 `json:"write" gorm:"write"` // 写入K
|
||||||
Name string `json:"name"`
|
Count int64 `json:"count" gorm:"count"` // 读写次数
|
||||||
// 读取K
|
Time int64 `json:"time" gorm:"time"` // 读写延迟
|
||||||
Read int64 `json:"read"`
|
NeType string `json:"neType" gorm:"ne_type"` // 网元类型
|
||||||
// 写入K
|
NeID string `json:"neId" gorm:"ne_id"` // 网元ID
|
||||||
Write int64 `json:"write"`
|
|
||||||
// 次数
|
|
||||||
Count int64 `json:"count"`
|
|
||||||
// 耗时
|
|
||||||
Time int64 `json:"time"`
|
|
||||||
// 网元ID
|
|
||||||
NeType string `json:"neType"`
|
|
||||||
// 网元类型
|
|
||||||
NeID string `json:"neId"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MonitorIO) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*MonitorIO) TableName() string {
|
||||||
return "monitor_io"
|
return "monitor_io"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,22 +2,16 @@ package model
|
|||||||
|
|
||||||
// MonitorNetwork 监控_网络IO monitor_network
|
// MonitorNetwork 监控_网络IO monitor_network
|
||||||
type MonitorNetwork struct {
|
type MonitorNetwork struct {
|
||||||
// id
|
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
ID int64 `json:"id" gorm:"primaryKey"`
|
CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间
|
||||||
// 创建时间
|
Name string `json:"name" gorm:"name"` // 网卡名
|
||||||
CreateTime int64 `json:"createTime"`
|
Up float64 `json:"up" gorm:"up"` // 上行
|
||||||
// 网卡名
|
Down float64 `json:"down" gorm:"down"` // 下行
|
||||||
Name string `json:"name"`
|
NeType string `json:"neType" gorm:"ne_type"` // 网元类型
|
||||||
// 上行
|
NeID string `json:"neId" gorm:"ne_id"` // 网元ID
|
||||||
Up float64 `json:"up"`
|
|
||||||
// 下行
|
|
||||||
Down float64 `json:"down"`
|
|
||||||
// 网元ID 本机#号
|
|
||||||
NeType string `json:"neType"`
|
|
||||||
// 网元类型 本机#号
|
|
||||||
NeID string `json:"neId"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MonitorNetwork) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*MonitorNetwork) TableName() string {
|
||||||
return "monitor_network"
|
return "monitor_network"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,5 +165,5 @@ func InitLoad() {
|
|||||||
// 初始化定时任务处理
|
// 初始化定时任务处理
|
||||||
processor.InitCronQueue()
|
processor.InitCronQueue()
|
||||||
// 启动时,初始化调度任务
|
// 启动时,初始化调度任务
|
||||||
service.NewSysJobImpl.ResetQueueJob()
|
service.NewSysJob.ResetQueueJob()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,274 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
// IMonitor 服务器系统相关信息 服务层接口
|
import (
|
||||||
type IMonitor interface {
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/modules/monitor/model"
|
||||||
|
"be.ems/src/modules/monitor/repository"
|
||||||
|
systemService "be.ems/src/modules/system/service"
|
||||||
|
"github.com/shirou/gopsutil/v4/cpu"
|
||||||
|
"github.com/shirou/gopsutil/v4/disk"
|
||||||
|
"github.com/shirou/gopsutil/v4/load"
|
||||||
|
"github.com/shirou/gopsutil/v4/mem"
|
||||||
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 Monitor 结构体
|
||||||
|
var NewMonitor = &Monitor{
|
||||||
|
sysConfigService: systemService.NewSysConfigImpl,
|
||||||
|
monitorRepository: repository.NewMonitorImpl,
|
||||||
|
diskIO: make(chan []disk.IOCountersStat, 2),
|
||||||
|
netIO: make(chan []net.IOCountersStat, 2),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor 服务器系统相关信息 服务层处理
|
||||||
|
type Monitor struct {
|
||||||
|
// 参数配置服务
|
||||||
|
sysConfigService systemService.ISysConfig
|
||||||
|
// 监控服务资源数据信息
|
||||||
|
monitorRepository repository.IMonitor
|
||||||
|
// 磁盘网络IO 数据通道
|
||||||
|
diskIO chan ([]disk.IOCountersStat)
|
||||||
|
netIO chan ([]net.IOCountersStat)
|
||||||
|
}
|
||||||
|
|
||||||
// RunMonitor 执行资源监控
|
// RunMonitor 执行资源监控
|
||||||
RunMonitor()
|
func (s *Monitor) RunMonitor() {
|
||||||
|
var itemBase model.MonitorBase
|
||||||
|
itemBase.CreateTime = time.Now().UnixMilli()
|
||||||
|
itemBase.NeType = "#"
|
||||||
|
itemBase.NeID = "#"
|
||||||
|
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
|
||||||
|
|
||||||
|
if err := s.monitorRepository.CreateMonitorBase(itemBase); err != nil {
|
||||||
|
logger.Errorf("CreateMonitorBase err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将当前资源发送到chan中处理保存
|
||||||
|
s.loadDiskIO()
|
||||||
|
s.loadNetIO()
|
||||||
|
|
||||||
|
// 监控系统资源-保留天数
|
||||||
|
storeDays := s.sysConfigService.SelectConfigValueByKey("monitor.sysResource.storeDays")
|
||||||
|
if storeDays != "" {
|
||||||
|
storeDays, _ := strconv.Atoi(storeDays)
|
||||||
|
ltTime := time.Now().AddDate(0, 0, -storeDays).UnixMilli()
|
||||||
|
_ = s.monitorRepository.DelMonitorBase(ltTime)
|
||||||
|
_ = s.monitorRepository.DelMonitorIO(ltTime)
|
||||||
|
_ = s.monitorRepository.DelMonitorNet(ltTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Monitor) loadDiskIO() {
|
||||||
|
ioStat, _ := disk.IOCounters()
|
||||||
|
var diskIOList []disk.IOCountersStat
|
||||||
|
for _, io := range ioStat {
|
||||||
|
diskIOList = append(diskIOList, io)
|
||||||
|
}
|
||||||
|
s.diskIO <- diskIOList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Monitor) loadNetIO() {
|
||||||
|
netStat, _ := net.IOCounters(true)
|
||||||
|
netStatAll, _ := net.IOCounters(false)
|
||||||
|
var netList []net.IOCountersStat
|
||||||
|
netList = append(netList, netStat...)
|
||||||
|
netList = append(netList, netStatAll...)
|
||||||
|
s.netIO <- netList
|
||||||
|
}
|
||||||
|
|
||||||
|
// monitorCancel 监控搜集IO/Network上下文
|
||||||
|
var monitorCancel context.CancelFunc
|
||||||
|
|
||||||
// RunMonitorDataCancel 启动资源监控数据存储io/network通道 移除之前的chan上下文后在设置新的均值
|
// RunMonitorDataCancel 启动资源监控数据存储io/network通道 移除之前的chan上下文后在设置新的均值
|
||||||
// interval 采集的平均值(分钟)
|
// interval 采集的平均值(分钟)
|
||||||
RunMonitorDataCancel(removeBefore bool, interval float64)
|
func (s *Monitor) RunMonitorDataCancel(removeBefore bool, interval float64) {
|
||||||
|
// 是否取消之前的
|
||||||
|
if removeBefore {
|
||||||
|
monitorCancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上下文控制
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
monitorCancel = cancel
|
||||||
|
|
||||||
|
// chanl 通道进行存储数据
|
||||||
|
go s.saveIODataToDB(ctx, interval)
|
||||||
|
go s.saveNetDataToDB(ctx, interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Monitor) saveIODataToDB(ctx context.Context, interval float64) {
|
||||||
|
defer close(s.diskIO)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case ioStat := <-s.diskIO:
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case ioStat2 := <-s.diskIO:
|
||||||
|
var ioList []model.MonitorIO
|
||||||
|
timeMilli := time.Now().UnixMilli()
|
||||||
|
for _, io2 := range ioStat2 {
|
||||||
|
for _, io1 := range ioStat {
|
||||||
|
if io2.Name == io1.Name {
|
||||||
|
var itemIO model.MonitorIO
|
||||||
|
itemIO.CreateTime = timeMilli
|
||||||
|
itemIO.NeType = "#"
|
||||||
|
itemIO.NeID = "#"
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||||
|
itemIO.Write = int64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||||
|
itemIO.Count = int64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||||
|
itemIO.Time = int64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
ioList = append(ioList, itemIO)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.monitorRepository.BatchCreateMonitorIO(ioList); err != nil {
|
||||||
|
logger.Errorf("BatchCreateMonitorIO err: %v", err)
|
||||||
|
}
|
||||||
|
s.diskIO <- ioStat2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Monitor) saveNetDataToDB(ctx context.Context, interval float64) {
|
||||||
|
defer close(s.netIO)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case netStat := <-s.netIO:
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case netStat2 := <-s.netIO:
|
||||||
|
var netList []model.MonitorNetwork
|
||||||
|
timeMilli := time.Now().UnixMilli()
|
||||||
|
for _, net2 := range netStat2 {
|
||||||
|
for _, net1 := range netStat {
|
||||||
|
if net2.Name == net1.Name {
|
||||||
|
var itemNet model.MonitorNetwork
|
||||||
|
itemNet.CreateTime = timeMilli
|
||||||
|
itemNet.NeType = "#"
|
||||||
|
itemNet.NeID = "#"
|
||||||
|
itemNet.Name = net1.Name
|
||||||
|
|
||||||
|
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||||
|
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
|
||||||
|
}
|
||||||
|
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||||
|
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
|
||||||
|
}
|
||||||
|
netList = append(netList, itemNet)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.monitorRepository.BatchCreateMonitorNet(netList); err != nil {
|
||||||
|
logger.Errorf("BatchCreateMonitorNet err: %v", err)
|
||||||
|
}
|
||||||
|
s.netIO <- netStat2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SelectMonitorInfo 查询监控资源信息
|
// SelectMonitorInfo 查询监控资源信息
|
||||||
SelectMonitorInfo(query map[string]any) map[string]any
|
func (s *Monitor) SelectMonitorInfo(query map[string]any) map[string]any {
|
||||||
|
infoType := query["type"]
|
||||||
|
startTimeMilli := query["startTime"]
|
||||||
|
endTimeMilli := query["endTime"]
|
||||||
|
neType := query["neType"]
|
||||||
|
neId := query["neId"]
|
||||||
|
name := query["name"]
|
||||||
|
|
||||||
|
// 返回数据
|
||||||
|
backDatas := map[string]any{}
|
||||||
|
|
||||||
|
// 基本信息
|
||||||
|
if infoType == "all" || infoType == "load" || infoType == "cpu" || infoType == "memory" {
|
||||||
|
rows := s.monitorRepository.SelectMonitorBase(map[string]any{
|
||||||
|
"startTime": startTimeMilli,
|
||||||
|
"endTime": endTimeMilli,
|
||||||
|
"neType": neType,
|
||||||
|
"neId": neId,
|
||||||
|
})
|
||||||
|
backDatas["base"] = rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// 磁盘IO
|
||||||
|
if infoType == "all" || infoType == "io" {
|
||||||
|
rows := s.monitorRepository.SelectMonitorIO(map[string]any{
|
||||||
|
"startTime": startTimeMilli,
|
||||||
|
"endTime": endTimeMilli,
|
||||||
|
"neType": neType,
|
||||||
|
"neId": neId,
|
||||||
|
"name": name,
|
||||||
|
})
|
||||||
|
backDatas["io"] = rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网络
|
||||||
|
if infoType == "all" || infoType == "network" {
|
||||||
|
rows := s.monitorRepository.SelectMonitorNetwork(map[string]any{
|
||||||
|
"startTime": startTimeMilli,
|
||||||
|
"endTime": endTimeMilli,
|
||||||
|
"neType": neType,
|
||||||
|
"neId": neId,
|
||||||
|
"name": name,
|
||||||
|
})
|
||||||
|
backDatas["network"] = rows
|
||||||
|
}
|
||||||
|
|
||||||
|
return backDatas
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,271 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
"be.ems/src/modules/monitor/model"
|
|
||||||
"be.ems/src/modules/monitor/repository"
|
|
||||||
systemService "be.ems/src/modules/system/service"
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/shirou/gopsutil/v3/load"
|
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 MonitorImpl 结构体
|
|
||||||
var NewMonitorImpl = &MonitorImpl{
|
|
||||||
sysConfigService: systemService.NewSysConfigImpl,
|
|
||||||
monitorRepository: repository.NewMonitorImpl,
|
|
||||||
diskIO: make(chan []disk.IOCountersStat, 2),
|
|
||||||
netIO: make(chan []net.IOCountersStat, 2),
|
|
||||||
}
|
|
||||||
|
|
||||||
// MonitorImpl 服务器系统相关信息 服务层处理
|
|
||||||
type MonitorImpl struct {
|
|
||||||
// 参数配置服务
|
|
||||||
sysConfigService systemService.ISysConfig
|
|
||||||
// 监控服务资源数据信息
|
|
||||||
monitorRepository repository.IMonitor
|
|
||||||
// 磁盘网络IO 数据通道
|
|
||||||
diskIO chan ([]disk.IOCountersStat)
|
|
||||||
netIO chan ([]net.IOCountersStat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunMonitor 执行资源监控
|
|
||||||
func (s *MonitorImpl) RunMonitor() {
|
|
||||||
var itemBase model.MonitorBase
|
|
||||||
itemBase.CreateTime = time.Now().UnixMilli()
|
|
||||||
itemBase.NeType = "#"
|
|
||||||
itemBase.NeID = "#"
|
|
||||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
|
||||||
if len(totalPercent) == 1 {
|
|
||||||
itemBase.CPU = totalPercent[0]
|
|
||||||
}
|
|
||||||
cpuCount, _ := cpu.Counts(false)
|
|
||||||
|
|
||||||
loadInfo, _ := load.Avg()
|
|
||||||
itemBase.CPULoad1 = loadInfo.Load1
|
|
||||||
itemBase.CPULoad5 = loadInfo.Load5
|
|
||||||
itemBase.CPULoad15 = loadInfo.Load15
|
|
||||||
itemBase.LoadUsage = loadInfo.Load1 / (float64(cpuCount*2) * 0.75) * 100
|
|
||||||
|
|
||||||
memoryInfo, _ := mem.VirtualMemory()
|
|
||||||
itemBase.Memory = memoryInfo.UsedPercent
|
|
||||||
|
|
||||||
if err := s.monitorRepository.CreateMonitorBase(itemBase); err != nil {
|
|
||||||
logger.Errorf("CreateMonitorBase err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将当前资源发送到chan中处理保存
|
|
||||||
s.loadDiskIO()
|
|
||||||
s.loadNetIO()
|
|
||||||
|
|
||||||
// 监控系统资源-保留天数
|
|
||||||
storeDays := s.sysConfigService.SelectConfigValueByKey("monitor.sysResource.storeDays")
|
|
||||||
if storeDays != "" {
|
|
||||||
storeDays, _ := strconv.Atoi(storeDays)
|
|
||||||
ltTime := time.Now().AddDate(0, 0, -storeDays).UnixMilli()
|
|
||||||
_ = s.monitorRepository.DelMonitorBase(ltTime)
|
|
||||||
_ = s.monitorRepository.DelMonitorIO(ltTime)
|
|
||||||
_ = s.monitorRepository.DelMonitorNet(ltTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MonitorImpl) loadDiskIO() {
|
|
||||||
ioStat, _ := disk.IOCounters()
|
|
||||||
var diskIOList []disk.IOCountersStat
|
|
||||||
for _, io := range ioStat {
|
|
||||||
diskIOList = append(diskIOList, io)
|
|
||||||
}
|
|
||||||
s.diskIO <- diskIOList
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MonitorImpl) loadNetIO() {
|
|
||||||
netStat, _ := net.IOCounters(true)
|
|
||||||
netStatAll, _ := net.IOCounters(false)
|
|
||||||
var netList []net.IOCountersStat
|
|
||||||
netList = append(netList, netStat...)
|
|
||||||
netList = append(netList, netStatAll...)
|
|
||||||
s.netIO <- netList
|
|
||||||
}
|
|
||||||
|
|
||||||
// monitorCancel 监控搜集IO/Network上下文
|
|
||||||
var monitorCancel context.CancelFunc
|
|
||||||
|
|
||||||
// RunMonitorDataCancel 启动资源监控数据存储io/network通道 移除之前的chan上下文后在设置新的均值
|
|
||||||
// interval 采集的平均值(分钟)
|
|
||||||
func (s *MonitorImpl) RunMonitorDataCancel(removeBefore bool, interval float64) {
|
|
||||||
// 是否取消之前的
|
|
||||||
if removeBefore {
|
|
||||||
monitorCancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上下文控制
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
monitorCancel = cancel
|
|
||||||
|
|
||||||
// chanl 通道进行存储数据
|
|
||||||
go s.saveIODataToDB(ctx, interval)
|
|
||||||
go s.saveNetDataToDB(ctx, interval)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MonitorImpl) saveIODataToDB(ctx context.Context, interval float64) {
|
|
||||||
defer close(s.diskIO)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case ioStat := <-s.diskIO:
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case ioStat2 := <-s.diskIO:
|
|
||||||
var ioList []model.MonitorIO
|
|
||||||
timeMilli := time.Now().UnixMilli()
|
|
||||||
for _, io2 := range ioStat2 {
|
|
||||||
for _, io1 := range ioStat {
|
|
||||||
if io2.Name == io1.Name {
|
|
||||||
var itemIO model.MonitorIO
|
|
||||||
itemIO.CreateTime = timeMilli
|
|
||||||
itemIO.NeType = "#"
|
|
||||||
itemIO.NeID = "#"
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
|
||||||
itemIO.Write = int64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
|
|
||||||
}
|
|
||||||
|
|
||||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
|
||||||
itemIO.Count = int64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
|
||||||
itemIO.Time = int64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
ioList = append(ioList, itemIO)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := s.monitorRepository.BatchCreateMonitorIO(ioList); err != nil {
|
|
||||||
logger.Errorf("BatchCreateMonitorIO err: %v", err)
|
|
||||||
}
|
|
||||||
s.diskIO <- ioStat2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MonitorImpl) saveNetDataToDB(ctx context.Context, interval float64) {
|
|
||||||
defer close(s.netIO)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case netStat := <-s.netIO:
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case netStat2 := <-s.netIO:
|
|
||||||
var netList []model.MonitorNetwork
|
|
||||||
timeMilli := time.Now().UnixMilli()
|
|
||||||
for _, net2 := range netStat2 {
|
|
||||||
for _, net1 := range netStat {
|
|
||||||
if net2.Name == net1.Name {
|
|
||||||
var itemNet model.MonitorNetwork
|
|
||||||
itemNet.CreateTime = timeMilli
|
|
||||||
itemNet.NeType = "#"
|
|
||||||
itemNet.NeID = "#"
|
|
||||||
itemNet.Name = net1.Name
|
|
||||||
|
|
||||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
|
||||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
|
|
||||||
}
|
|
||||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
|
||||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
|
|
||||||
}
|
|
||||||
netList = append(netList, itemNet)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.monitorRepository.BatchCreateMonitorNet(netList); err != nil {
|
|
||||||
logger.Errorf("BatchCreateMonitorNet err: %v", err)
|
|
||||||
}
|
|
||||||
s.netIO <- netStat2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMonitorInfo 查询监控资源信息
|
|
||||||
func (s *MonitorImpl) SelectMonitorInfo(query map[string]any) map[string]any {
|
|
||||||
infoType := query["type"]
|
|
||||||
startTimeMilli := query["startTime"]
|
|
||||||
endTimeMilli := query["endTime"]
|
|
||||||
neType := query["neType"]
|
|
||||||
neId := query["neId"]
|
|
||||||
name := query["name"]
|
|
||||||
|
|
||||||
// 返回数据
|
|
||||||
backDatas := map[string]any{}
|
|
||||||
|
|
||||||
// 基本信息
|
|
||||||
if infoType == "all" || infoType == "load" || infoType == "cpu" || infoType == "memory" {
|
|
||||||
rows := s.monitorRepository.SelectMonitorBase(map[string]any{
|
|
||||||
"startTime": startTimeMilli,
|
|
||||||
"endTime": endTimeMilli,
|
|
||||||
"neType": neType,
|
|
||||||
"neId": neId,
|
|
||||||
})
|
|
||||||
backDatas["base"] = rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// 磁盘IO
|
|
||||||
if infoType == "all" || infoType == "io" {
|
|
||||||
rows := s.monitorRepository.SelectMonitorIO(map[string]any{
|
|
||||||
"startTime": startTimeMilli,
|
|
||||||
"endTime": endTimeMilli,
|
|
||||||
"neType": neType,
|
|
||||||
"neId": neId,
|
|
||||||
"name": name,
|
|
||||||
})
|
|
||||||
backDatas["io"] = rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// 网络
|
|
||||||
if infoType == "all" || infoType == "network" {
|
|
||||||
rows := s.monitorRepository.SelectMonitorNetwork(map[string]any{
|
|
||||||
"startTime": startTimeMilli,
|
|
||||||
"endTime": endTimeMilli,
|
|
||||||
"neType": neType,
|
|
||||||
"neId": neId,
|
|
||||||
"name": name,
|
|
||||||
})
|
|
||||||
backDatas["network"] = rows
|
|
||||||
}
|
|
||||||
|
|
||||||
return backDatas
|
|
||||||
}
|
|
||||||
@@ -5,17 +5,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v4/cpu"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v4/disk"
|
||||||
"github.com/shirou/gopsutil/v3/load"
|
"github.com/shirou/gopsutil/v4/load"
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
"github.com/shirou/gopsutil/v4/mem"
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInfo(t *testing.T) {
|
func TestInfo(t *testing.T) {
|
||||||
s := MonitorInfo{}
|
s := MonitorInfo{}
|
||||||
s.load(0.5) // 0.5 半分钟
|
s.load(0.5) // 0.5 半分钟
|
||||||
@@ -36,17 +32,21 @@ func (m *MonitorInfo) load(interval float64) {
|
|||||||
var itemBase MonitorBase
|
var itemBase MonitorBase
|
||||||
itemBase.CreateTime = time.Now().UnixMilli()
|
itemBase.CreateTime = time.Now().UnixMilli()
|
||||||
|
|
||||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
|
||||||
if len(totalPercent) == 1 {
|
|
||||||
itemBase.CPU = totalPercent[0]
|
|
||||||
}
|
|
||||||
cpuCount, _ := cpu.Counts(false)
|
|
||||||
|
|
||||||
loadInfo, _ := load.Avg()
|
loadInfo, _ := load.Avg()
|
||||||
itemBase.CPULoad1 = loadInfo.Load1
|
itemBase.CPULoad1 = loadInfo.Load1
|
||||||
itemBase.CPULoad5 = loadInfo.Load5
|
itemBase.CPULoad5 = loadInfo.Load5
|
||||||
itemBase.CPULoad15 = loadInfo.Load15
|
itemBase.CPULoad15 = loadInfo.Load15
|
||||||
itemBase.LoadUsage = loadInfo.Load1 / (float64(cpuCount*2) * 0.75) * 100
|
|
||||||
|
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()
|
memoryInfo, _ := mem.VirtualMemory()
|
||||||
itemBase.Memory = memoryInfo.UsedPercent
|
itemBase.Memory = memoryInfo.UsedPercent
|
||||||
|
|||||||
@@ -1,35 +1,169 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"be.ems/src/framework/constants/common"
|
||||||
|
"be.ems/src/framework/cron"
|
||||||
"be.ems/src/modules/monitor/model"
|
"be.ems/src/modules/monitor/model"
|
||||||
|
"be.ems/src/modules/monitor/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ISysJob 调度任务信息 服务层接口
|
// 实例化服务层 SysJob 结构体
|
||||||
type ISysJob interface {
|
var NewSysJob = &SysJob{
|
||||||
|
sysJobRepository: repository.NewSysJobImpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
// SysJob 调度任务 服务层处理
|
||||||
|
type SysJob struct {
|
||||||
|
// 调度任务数据信息
|
||||||
|
sysJobRepository repository.ISysJob
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobPage 分页查询调度任务集合
|
// SelectJobPage 分页查询调度任务集合
|
||||||
SelectJobPage(query map[string]any) map[string]any
|
func (r *SysJob) SelectJobPage(query map[string]any) map[string]any {
|
||||||
|
return r.sysJobRepository.SelectJobPage(query)
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobList 查询调度任务集合
|
// SelectJobList 查询调度任务集合
|
||||||
SelectJobList(sysJob model.SysJob) []model.SysJob
|
func (r *SysJob) SelectJobList(sysJob model.SysJob) []model.SysJob {
|
||||||
|
return r.sysJobRepository.SelectJobList(sysJob)
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobById 通过调度ID查询调度任务信息
|
// SelectJobById 通过调度ID查询调度任务信息
|
||||||
SelectJobById(jobId string) model.SysJob
|
func (r *SysJob) SelectJobById(jobId string) model.SysJob {
|
||||||
|
if jobId == "" {
|
||||||
|
return model.SysJob{}
|
||||||
|
}
|
||||||
|
jobs := r.sysJobRepository.SelectJobByIds([]string{jobId})
|
||||||
|
if len(jobs) > 0 {
|
||||||
|
return jobs[0]
|
||||||
|
}
|
||||||
|
return model.SysJob{}
|
||||||
|
}
|
||||||
|
|
||||||
// CheckUniqueJobName 校验调度任务名称和组是否唯一
|
// CheckUniqueJobName 校验调度任务名称和组是否唯一
|
||||||
CheckUniqueJobName(jobName, jobGroup, jobId string) bool
|
func (r *SysJob) CheckUniqueJobName(jobName, jobGroup, jobId string) bool {
|
||||||
|
uniqueId := r.sysJobRepository.CheckUniqueJob(model.SysJob{
|
||||||
|
JobName: jobName,
|
||||||
|
JobGroup: jobGroup,
|
||||||
|
})
|
||||||
|
if uniqueId == jobId {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return uniqueId == ""
|
||||||
|
}
|
||||||
|
|
||||||
// InsertJob 新增调度任务信息
|
// InsertJob 新增调度任务信息
|
||||||
InsertJob(sysJob model.SysJob) string
|
func (r *SysJob) InsertJob(sysJob model.SysJob) string {
|
||||||
|
insertId := r.sysJobRepository.InsertJob(sysJob)
|
||||||
|
if insertId == "" && sysJob.Status == common.STATUS_YES {
|
||||||
|
sysJob.JobID = insertId
|
||||||
|
r.insertQueueJob(sysJob, true)
|
||||||
|
}
|
||||||
|
return insertId
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateJob 修改调度任务信息
|
// UpdateJob 修改调度任务信息
|
||||||
UpdateJob(sysJob model.SysJob) int64
|
func (r *SysJob) UpdateJob(sysJob model.SysJob) int64 {
|
||||||
|
rows := r.sysJobRepository.UpdateJob(sysJob)
|
||||||
|
if rows > 0 {
|
||||||
|
//状态正常添加队列任务
|
||||||
|
if sysJob.Status == common.STATUS_YES {
|
||||||
|
r.insertQueueJob(sysJob, true)
|
||||||
|
}
|
||||||
|
// 状态禁用删除队列任务
|
||||||
|
if sysJob.Status == common.STATUS_NO {
|
||||||
|
r.deleteQueueJob(sysJob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteJobByIds 批量删除调度任务信息
|
// DeleteJobByIds 批量删除调度任务信息
|
||||||
DeleteJobByIds(jobIds []string) (int64, error)
|
func (r *SysJob) DeleteJobByIds(jobIds []string) (int64, error) {
|
||||||
|
// 检查是否存在
|
||||||
// RunQueueJob 立即运行一次调度任务
|
jobs := r.sysJobRepository.SelectJobByIds(jobIds)
|
||||||
RunQueueJob(sysJob model.SysJob) bool
|
if len(jobs) <= 0 {
|
||||||
|
// 没有可访问调度任务数据!
|
||||||
|
return 0, fmt.Errorf("there is no accessible scheduling task data")
|
||||||
|
}
|
||||||
|
if len(jobs) == len(jobIds) {
|
||||||
|
// 清除任务
|
||||||
|
for _, job := range jobs {
|
||||||
|
r.deleteQueueJob(job)
|
||||||
|
}
|
||||||
|
rows := r.sysJobRepository.DeleteJobByIds(jobIds)
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
// 删除调度任务信息失败!
|
||||||
|
return 0, fmt.Errorf("failed to delete scheduling task information")
|
||||||
|
}
|
||||||
|
|
||||||
// ResetQueueJob 重置初始调度任务
|
// ResetQueueJob 重置初始调度任务
|
||||||
ResetQueueJob()
|
func (r *SysJob) ResetQueueJob() {
|
||||||
|
// 获取注册的队列名称
|
||||||
|
queueNames := cron.QueueNames()
|
||||||
|
if len(queueNames) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 查询系统中定义状态为正常启用的任务
|
||||||
|
sysJobs := r.sysJobRepository.SelectJobList(model.SysJob{
|
||||||
|
Status: common.STATUS_YES,
|
||||||
|
})
|
||||||
|
for _, sysJob := range sysJobs {
|
||||||
|
for _, name := range queueNames {
|
||||||
|
if name == sysJob.InvokeTarget {
|
||||||
|
r.insertQueueJob(sysJob, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunQueueJob 立即运行一次调度任务
|
||||||
|
func (r *SysJob) RunQueueJob(sysJob model.SysJob) bool {
|
||||||
|
return r.insertQueueJob(sysJob, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// insertQueueJob 添加调度任务
|
||||||
|
func (r *SysJob) insertQueueJob(sysJob model.SysJob, repeat bool) bool {
|
||||||
|
// 获取队列 Processor
|
||||||
|
queue := cron.GetQueue(sysJob.InvokeTarget)
|
||||||
|
if queue.Name != sysJob.InvokeTarget {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 给执行任务数据参数
|
||||||
|
options := cron.JobData{
|
||||||
|
Repeat: repeat,
|
||||||
|
SysJob: sysJob,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不是重复任务的情况,立即执行一次
|
||||||
|
if !repeat {
|
||||||
|
// 执行单次任务
|
||||||
|
status := queue.RunJob(options, cron.JobOptions{
|
||||||
|
JobId: sysJob.JobID,
|
||||||
|
})
|
||||||
|
// 执行中或等待中的都返回正常
|
||||||
|
return status == cron.Active || status == cron.Waiting
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行重复任务
|
||||||
|
queue.RunJob(options, cron.JobOptions{
|
||||||
|
JobId: sysJob.JobID,
|
||||||
|
Cron: sysJob.CronExpression,
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteQueueJob 删除调度任务
|
||||||
|
func (r *SysJob) deleteQueueJob(sysJob model.SysJob) bool {
|
||||||
|
// 获取队列 Processor
|
||||||
|
queue := cron.GetQueue(sysJob.InvokeTarget)
|
||||||
|
if queue.Name != sysJob.InvokeTarget {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return queue.RemoveJob(sysJob.JobID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"be.ems/src/framework/constants/common"
|
|
||||||
"be.ems/src/framework/cron"
|
|
||||||
"be.ems/src/modules/monitor/model"
|
|
||||||
"be.ems/src/modules/monitor/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 SysJobImpl 结构体
|
|
||||||
var NewSysJobImpl = &SysJobImpl{
|
|
||||||
sysJobRepository: repository.NewSysJobImpl,
|
|
||||||
}
|
|
||||||
|
|
||||||
// SysJobImpl 调度任务 服务层处理
|
|
||||||
type SysJobImpl struct {
|
|
||||||
// 调度任务数据信息
|
|
||||||
sysJobRepository repository.ISysJob
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobPage 分页查询调度任务集合
|
|
||||||
func (r *SysJobImpl) SelectJobPage(query map[string]any) map[string]any {
|
|
||||||
return r.sysJobRepository.SelectJobPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobList 查询调度任务集合
|
|
||||||
func (r *SysJobImpl) SelectJobList(sysJob model.SysJob) []model.SysJob {
|
|
||||||
return r.sysJobRepository.SelectJobList(sysJob)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobById 通过调度ID查询调度任务信息
|
|
||||||
func (r *SysJobImpl) SelectJobById(jobId string) model.SysJob {
|
|
||||||
if jobId == "" {
|
|
||||||
return model.SysJob{}
|
|
||||||
}
|
|
||||||
jobs := r.sysJobRepository.SelectJobByIds([]string{jobId})
|
|
||||||
if len(jobs) > 0 {
|
|
||||||
return jobs[0]
|
|
||||||
}
|
|
||||||
return model.SysJob{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueJobName 校验调度任务名称和组是否唯一
|
|
||||||
func (r *SysJobImpl) CheckUniqueJobName(jobName, jobGroup, jobId string) bool {
|
|
||||||
uniqueId := r.sysJobRepository.CheckUniqueJob(model.SysJob{
|
|
||||||
JobName: jobName,
|
|
||||||
JobGroup: jobGroup,
|
|
||||||
})
|
|
||||||
if uniqueId == jobId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertJob 新增调度任务信息
|
|
||||||
func (r *SysJobImpl) InsertJob(sysJob model.SysJob) string {
|
|
||||||
insertId := r.sysJobRepository.InsertJob(sysJob)
|
|
||||||
if insertId == "" && sysJob.Status == common.STATUS_YES {
|
|
||||||
sysJob.JobID = insertId
|
|
||||||
r.insertQueueJob(sysJob, true)
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateJob 修改调度任务信息
|
|
||||||
func (r *SysJobImpl) UpdateJob(sysJob model.SysJob) int64 {
|
|
||||||
rows := r.sysJobRepository.UpdateJob(sysJob)
|
|
||||||
if rows > 0 {
|
|
||||||
//状态正常添加队列任务
|
|
||||||
if sysJob.Status == common.STATUS_YES {
|
|
||||||
r.insertQueueJob(sysJob, true)
|
|
||||||
}
|
|
||||||
// 状态禁用删除队列任务
|
|
||||||
if sysJob.Status == common.STATUS_NO {
|
|
||||||
r.deleteQueueJob(sysJob)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteJobByIds 批量删除调度任务信息
|
|
||||||
func (r *SysJobImpl) DeleteJobByIds(jobIds []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
jobs := r.sysJobRepository.SelectJobByIds(jobIds)
|
|
||||||
if len(jobs) <= 0 {
|
|
||||||
// 没有可访问调度任务数据!
|
|
||||||
return 0, fmt.Errorf("there is no accessible scheduling task data")
|
|
||||||
}
|
|
||||||
if len(jobs) == len(jobIds) {
|
|
||||||
// 清除任务
|
|
||||||
for _, job := range jobs {
|
|
||||||
r.deleteQueueJob(job)
|
|
||||||
}
|
|
||||||
rows := r.sysJobRepository.DeleteJobByIds(jobIds)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
// 删除调度任务信息失败!
|
|
||||||
return 0, fmt.Errorf("failed to delete scheduling task information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetQueueJob 重置初始调度任务
|
|
||||||
func (r *SysJobImpl) ResetQueueJob() {
|
|
||||||
// 获取注册的队列名称
|
|
||||||
queueNames := cron.QueueNames()
|
|
||||||
if len(queueNames) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 查询系统中定义状态为正常启用的任务
|
|
||||||
sysJobs := r.sysJobRepository.SelectJobList(model.SysJob{
|
|
||||||
Status: common.STATUS_YES,
|
|
||||||
})
|
|
||||||
for _, sysJob := range sysJobs {
|
|
||||||
for _, name := range queueNames {
|
|
||||||
if name == sysJob.InvokeTarget {
|
|
||||||
r.insertQueueJob(sysJob, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunQueueJob 立即运行一次调度任务
|
|
||||||
func (r *SysJobImpl) RunQueueJob(sysJob model.SysJob) bool {
|
|
||||||
return r.insertQueueJob(sysJob, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertQueueJob 添加调度任务
|
|
||||||
func (r *SysJobImpl) insertQueueJob(sysJob model.SysJob, repeat bool) bool {
|
|
||||||
// 获取队列 Processor
|
|
||||||
queue := cron.GetQueue(sysJob.InvokeTarget)
|
|
||||||
if queue.Name != sysJob.InvokeTarget {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 给执行任务数据参数
|
|
||||||
options := cron.JobData{
|
|
||||||
Repeat: repeat,
|
|
||||||
SysJob: sysJob,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不是重复任务的情况,立即执行一次
|
|
||||||
if !repeat {
|
|
||||||
// 执行单次任务
|
|
||||||
status := queue.RunJob(options, cron.JobOptions{
|
|
||||||
JobId: sysJob.JobID,
|
|
||||||
})
|
|
||||||
// 执行中或等待中的都返回正常
|
|
||||||
return status == cron.Active || status == cron.Waiting
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行重复任务
|
|
||||||
queue.RunJob(options, cron.JobOptions{
|
|
||||||
JobId: sysJob.JobID,
|
|
||||||
Cron: sysJob.CronExpression,
|
|
||||||
})
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteQueueJob 删除调度任务
|
|
||||||
func (r *SysJobImpl) deleteQueueJob(sysJob model.SysJob) bool {
|
|
||||||
// 获取队列 Processor
|
|
||||||
queue := cron.GetQueue(sysJob.InvokeTarget)
|
|
||||||
if queue.Name != sysJob.InvokeTarget {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return queue.RemoveJob(sysJob.JobID)
|
|
||||||
}
|
|
||||||
@@ -2,22 +2,41 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"be.ems/src/modules/monitor/model"
|
"be.ems/src/modules/monitor/model"
|
||||||
|
"be.ems/src/modules/monitor/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ISysJobLog 调度任务日志 服务层接口
|
// 实例化服务层 SysJobLog 结构体
|
||||||
type ISysJobLog interface {
|
var NewSysJobLog = &SysJobLog{
|
||||||
|
sysJobLogRepository: repository.NewSysJobLogImpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
// SysJobLog 调度任务日志 服务层处理
|
||||||
|
type SysJobLog struct {
|
||||||
|
// 调度任务日志数据信息
|
||||||
|
sysJobLogRepository repository.ISysJobLog
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobLogPage 分页查询调度任务日志集合
|
// SelectJobLogPage 分页查询调度任务日志集合
|
||||||
SelectJobLogPage(query map[string]any) map[string]any
|
func (s *SysJobLog) SelectJobLogPage(query map[string]any) map[string]any {
|
||||||
|
return s.sysJobLogRepository.SelectJobLogPage(query)
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobLogList 查询调度任务日志集合
|
// SelectJobLogList 查询调度任务日志集合
|
||||||
SelectJobLogList(sysJobLog model.SysJobLog) []model.SysJobLog
|
func (s *SysJobLog) SelectJobLogList(sysJobLog model.SysJobLog) []model.SysJobLog {
|
||||||
|
return s.sysJobLogRepository.SelectJobLogList(sysJobLog)
|
||||||
|
}
|
||||||
|
|
||||||
// SelectJobLogById 通过调度ID查询调度任务日志信息
|
// SelectJobLogById 通过调度ID查询调度任务日志信息
|
||||||
SelectJobLogById(jobLogId string) model.SysJobLog
|
func (s *SysJobLog) SelectJobLogById(jobLogId string) model.SysJobLog {
|
||||||
|
return s.sysJobLogRepository.SelectJobLogById(jobLogId)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteJobLogByIds 批量删除调度任务日志信息
|
// DeleteJobLogByIds 批量删除调度任务日志信息
|
||||||
DeleteJobLogByIds(jobLogIds []string) int64
|
func (s *SysJobLog) DeleteJobLogByIds(jobLogIds []string) int64 {
|
||||||
|
return s.sysJobLogRepository.DeleteJobLogByIds(jobLogIds)
|
||||||
|
}
|
||||||
|
|
||||||
// CleanJobLog 清空调度任务日志
|
// CleanJobLog 清空调度任务日志
|
||||||
CleanJobLog() error
|
func (s *SysJobLog) CleanJobLog() error {
|
||||||
|
return s.sysJobLogRepository.CleanJobLog()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"be.ems/src/modules/monitor/model"
|
|
||||||
"be.ems/src/modules/monitor/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 SysJobLogImpl 结构体
|
|
||||||
var NewSysJobLogImpl = &SysJobLogImpl{
|
|
||||||
sysJobLogRepository: repository.NewSysJobLogImpl,
|
|
||||||
}
|
|
||||||
|
|
||||||
// SysJobLogImpl 调度任务日志 服务层处理
|
|
||||||
type SysJobLogImpl struct {
|
|
||||||
// 调度任务日志数据信息
|
|
||||||
sysJobLogRepository repository.ISysJobLog
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobLogPage 分页查询调度任务日志集合
|
|
||||||
func (s *SysJobLogImpl) SelectJobLogPage(query map[string]any) map[string]any {
|
|
||||||
return s.sysJobLogRepository.SelectJobLogPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobLogList 查询调度任务日志集合
|
|
||||||
func (s *SysJobLogImpl) SelectJobLogList(sysJobLog model.SysJobLog) []model.SysJobLog {
|
|
||||||
return s.sysJobLogRepository.SelectJobLogList(sysJobLog)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectJobLogById 通过调度ID查询调度任务日志信息
|
|
||||||
func (s *SysJobLogImpl) SelectJobLogById(jobLogId string) model.SysJobLog {
|
|
||||||
return s.sysJobLogRepository.SelectJobLogById(jobLogId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteJobLogByIds 批量删除调度任务日志信息
|
|
||||||
func (s *SysJobLogImpl) DeleteJobLogByIds(jobLogIds []string) int64 {
|
|
||||||
return s.sysJobLogRepository.DeleteJobLogByIds(jobLogIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CleanJobLog 清空调度任务日志
|
|
||||||
func (s *SysJobLogImpl) CleanJobLog() error {
|
|
||||||
return s.sysJobLogRepository.CleanJobLog()
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,29 @@ import (
|
|||||||
"be.ems/src/modules/monitor/model"
|
"be.ems/src/modules/monitor/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ISysUserOnline 在线用户 服务层接口
|
// 实例化服务层 SysUserOnline 结构体
|
||||||
type ISysUserOnline interface {
|
var NewSysUserOnline = &SysUserOnline{}
|
||||||
|
|
||||||
|
// SysUserOnline 在线用户 服务层处理
|
||||||
|
type SysUserOnline struct{}
|
||||||
|
|
||||||
// LoginUserToUserOnline 设置在线用户信息
|
// LoginUserToUserOnline 设置在线用户信息
|
||||||
LoginUserToUserOnline(loginUser vo.LoginUser) model.SysUserOnline
|
func (r *SysUserOnline) LoginUserToUserOnline(loginUser vo.LoginUser) model.SysUserOnline {
|
||||||
|
if loginUser.UserID == "" {
|
||||||
|
return model.SysUserOnline{}
|
||||||
|
}
|
||||||
|
|
||||||
|
sysUserOnline := model.SysUserOnline{
|
||||||
|
TokenID: loginUser.UUID,
|
||||||
|
UserName: loginUser.User.UserName,
|
||||||
|
IPAddr: loginUser.IPAddr,
|
||||||
|
LoginLocation: loginUser.LoginLocation,
|
||||||
|
Browser: loginUser.Browser,
|
||||||
|
OS: loginUser.OS,
|
||||||
|
LoginTime: loginUser.LoginTime,
|
||||||
|
}
|
||||||
|
if loginUser.User.DeptID != "" {
|
||||||
|
sysUserOnline.DeptName = loginUser.User.Dept.DeptName
|
||||||
|
}
|
||||||
|
return sysUserOnline
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"be.ems/src/framework/vo"
|
|
||||||
"be.ems/src/modules/monitor/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 SysUserOnlineImpl 结构体
|
|
||||||
var NewSysUserOnlineImpl = &SysUserOnlineImpl{}
|
|
||||||
|
|
||||||
// SysUserOnlineImpl 在线用户 服务层处理
|
|
||||||
type SysUserOnlineImpl struct{}
|
|
||||||
|
|
||||||
// LoginUserToUserOnline 设置在线用户信息
|
|
||||||
func (r *SysUserOnlineImpl) LoginUserToUserOnline(loginUser vo.LoginUser) model.SysUserOnline {
|
|
||||||
if loginUser.UserID == "" {
|
|
||||||
return model.SysUserOnline{}
|
|
||||||
}
|
|
||||||
|
|
||||||
sysUserOnline := model.SysUserOnline{
|
|
||||||
TokenID: loginUser.UUID,
|
|
||||||
UserName: loginUser.User.UserName,
|
|
||||||
IPAddr: loginUser.IPAddr,
|
|
||||||
LoginLocation: loginUser.LoginLocation,
|
|
||||||
Browser: loginUser.Browser,
|
|
||||||
OS: loginUser.OS,
|
|
||||||
LoginTime: loginUser.LoginTime,
|
|
||||||
}
|
|
||||||
if loginUser.User.DeptID != "" {
|
|
||||||
sysUserOnline.DeptName = loginUser.User.Dept.DeptName
|
|
||||||
}
|
|
||||||
return sysUserOnline
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,177 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
// ISystemInfo 服务器系统相关信息 服务层接口
|
import (
|
||||||
type ISystemInfo interface {
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/config"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/v4/cpu"
|
||||||
|
"github.com/shirou/gopsutil/v4/disk"
|
||||||
|
"github.com/shirou/gopsutil/v4/host"
|
||||||
|
"github.com/shirou/gopsutil/v4/mem"
|
||||||
|
"github.com/shirou/gopsutil/v4/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 SystemInfo 结构体
|
||||||
|
var NewSystemInfo = &SystemInfo{}
|
||||||
|
|
||||||
|
// SystemInfo 服务器系统相关信息 服务层处理
|
||||||
|
type SystemInfo struct{}
|
||||||
|
|
||||||
// SystemInfo 系统信息
|
// SystemInfo 系统信息
|
||||||
SystemInfo() map[string]any
|
func (s *SystemInfo) SystemInfo() map[string]any {
|
||||||
|
info, err := host.Info()
|
||||||
|
if err != nil {
|
||||||
|
info.Platform = err.Error()
|
||||||
|
}
|
||||||
|
// 获取主机运行时间
|
||||||
|
bootTime := time.Since(time.Unix(int64(info.BootTime), 0)).Seconds()
|
||||||
|
// 获取程序运行时间
|
||||||
|
runTime := time.Since(config.RunTime()).Abs().Seconds()
|
||||||
|
return map[string]any{
|
||||||
|
"platform": info.Platform,
|
||||||
|
"platformVersion": info.PlatformVersion,
|
||||||
|
"arch": info.KernelArch,
|
||||||
|
"archVersion": info.KernelVersion,
|
||||||
|
"os": info.OS,
|
||||||
|
"hostname": info.Hostname,
|
||||||
|
"bootTime": int64(bootTime),
|
||||||
|
"processId": os.Getpid(),
|
||||||
|
"runArch": runtime.GOARCH,
|
||||||
|
"runVersion": runtime.Version(),
|
||||||
|
"runTime": int64(runTime),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TimeInfo 系统时间信息
|
// TimeInfo 系统时间信息
|
||||||
TimeInfo() map[string]string
|
func (s *SystemInfo) TimeInfo() map[string]string {
|
||||||
|
now := time.Now()
|
||||||
|
// 获取当前时间
|
||||||
|
current := now.Format("2006-01-02 15:04:05")
|
||||||
|
// 获取时区
|
||||||
|
timezone := now.Format("-0700 MST")
|
||||||
|
// 获取时区名称
|
||||||
|
timezoneName := now.Format("MST")
|
||||||
|
|
||||||
|
return map[string]string{
|
||||||
|
"current": current,
|
||||||
|
"timezone": timezone,
|
||||||
|
"timezoneName": timezoneName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MemoryInfo 内存信息
|
// MemoryInfo 内存信息
|
||||||
MemoryInfo() map[string]any
|
func (s *SystemInfo) MemoryInfo() map[string]any {
|
||||||
|
memInfo, err := mem.VirtualMemory()
|
||||||
|
if err != nil {
|
||||||
|
memInfo.UsedPercent = 0
|
||||||
|
memInfo.Available = 0
|
||||||
|
memInfo.Total = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var memStats runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&memStats)
|
||||||
|
|
||||||
|
return map[string]any{
|
||||||
|
"usage": fmt.Sprintf("%.2f", memInfo.UsedPercent), // 内存利用率
|
||||||
|
"freemem": parse.Bit(float64(memInfo.Available)), // 可用内存大小(GB)
|
||||||
|
"totalmem": parse.Bit(float64(memInfo.Total)), // 总内存大小(GB)
|
||||||
|
"rss": parse.Bit(float64(memStats.Sys)), // 常驻内存大小(RSS)
|
||||||
|
"heapTotal": parse.Bit(float64(memStats.HeapSys)), // 堆总大小
|
||||||
|
"heapUsed": parse.Bit(float64(memStats.HeapAlloc)), // 堆已使用大小
|
||||||
|
"external": parse.Bit(float64(memStats.Sys - memStats.HeapSys)), // 外部内存大小(非堆)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CPUInfo CPU信息
|
// CPUInfo CPU信息
|
||||||
CPUInfo() map[string]any
|
func (s *SystemInfo) CPUInfo() map[string]any {
|
||||||
|
var core int = 0
|
||||||
|
var speed string = "未知"
|
||||||
|
var model string = "未知"
|
||||||
|
cpuInfo, err := cpu.Info()
|
||||||
|
if err == nil {
|
||||||
|
core = runtime.NumCPU()
|
||||||
|
speed = fmt.Sprintf("%.0fMHz", cpuInfo[0].Mhz)
|
||||||
|
model = strings.TrimSpace(cpuInfo[0].ModelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
useds := []string{}
|
||||||
|
cpuPercent, err := cpu.Percent(0, true)
|
||||||
|
if err == nil {
|
||||||
|
for _, v := range cpuPercent {
|
||||||
|
useds = append(useds, fmt.Sprintf("%.2f", v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]any{
|
||||||
|
"model": model,
|
||||||
|
"speed": speed,
|
||||||
|
"core": core,
|
||||||
|
"coreUsed": useds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkInfo 网络信息
|
// NetworkInfo 网络信息
|
||||||
NetworkInfo() map[string]string
|
func (s *SystemInfo) NetworkInfo() map[string]string {
|
||||||
|
ipAddrs := make(map[string]string)
|
||||||
|
interfaces, err := net.Interfaces()
|
||||||
|
if err == nil {
|
||||||
|
for _, iface := range interfaces {
|
||||||
|
name := iface.Name
|
||||||
|
if name[len(name)-1] == '0' {
|
||||||
|
name = name[0 : len(name)-1]
|
||||||
|
name = strings.Trim(name, "")
|
||||||
|
}
|
||||||
|
// ignore localhost
|
||||||
|
if name == "lo" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var addrs []string
|
||||||
|
for _, v := range iface.Addrs {
|
||||||
|
prefix := strings.Split(v.Addr, "/")[0]
|
||||||
|
if strings.Contains(prefix, "::") {
|
||||||
|
addrs = append(addrs, fmt.Sprintf("IPv6 %s", prefix))
|
||||||
|
}
|
||||||
|
if strings.Contains(prefix, ".") {
|
||||||
|
addrs = append(addrs, fmt.Sprintf("IPv4 %s", prefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipAddrs[name] = strings.Join(addrs, " / ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ipAddrs
|
||||||
|
}
|
||||||
|
|
||||||
// DiskInfo 磁盘信息
|
// DiskInfo 磁盘信息
|
||||||
DiskInfo() []map[string]string
|
func (s *SystemInfo) DiskInfo() []map[string]string {
|
||||||
|
disks := make([]map[string]string, 0)
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
partitions, err := disk.PartitionsWithContext(ctx, false)
|
||||||
|
if err != nil && err != context.DeadlineExceeded {
|
||||||
|
return disks
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, partition := range partitions {
|
||||||
|
usage, err := disk.Usage(partition.Mountpoint)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
disks = append(disks, map[string]string{
|
||||||
|
"size": parse.Bit(float64(usage.Total)),
|
||||||
|
"used": parse.Bit(float64(usage.Used)),
|
||||||
|
"avail": parse.Bit(float64(usage.Free)),
|
||||||
|
"pcent": fmt.Sprintf("%.1f%%", usage.UsedPercent),
|
||||||
|
"target": partition.Device,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return disks
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/src/framework/config"
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/shirou/gopsutil/v3/host"
|
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 SystemInfoImpl 结构体
|
|
||||||
var NewSystemInfoImpl = &SystemInfoImpl{}
|
|
||||||
|
|
||||||
// SystemInfoImpl 服务器系统相关信息 服务层处理
|
|
||||||
type SystemInfoImpl struct{}
|
|
||||||
|
|
||||||
// SystemInfo 系统信息
|
|
||||||
func (s *SystemInfoImpl) SystemInfo() map[string]any {
|
|
||||||
info, err := host.Info()
|
|
||||||
if err != nil {
|
|
||||||
info.Platform = err.Error()
|
|
||||||
}
|
|
||||||
// 获取主机运行时间
|
|
||||||
bootTime := time.Since(time.Unix(int64(info.BootTime), 0)).Seconds()
|
|
||||||
// 获取程序运行时间
|
|
||||||
runTime := time.Since(config.RunTime()).Abs().Seconds()
|
|
||||||
return map[string]any{
|
|
||||||
"platform": info.Platform,
|
|
||||||
"platformVersion": info.PlatformVersion,
|
|
||||||
"arch": info.KernelArch,
|
|
||||||
"archVersion": info.KernelVersion,
|
|
||||||
"os": info.OS,
|
|
||||||
"hostname": info.Hostname,
|
|
||||||
"bootTime": int64(bootTime),
|
|
||||||
"processId": os.Getpid(),
|
|
||||||
"runArch": runtime.GOARCH,
|
|
||||||
"runVersion": runtime.Version(),
|
|
||||||
"runTime": int64(runTime),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeInfo 系统时间信息
|
|
||||||
func (s *SystemInfoImpl) TimeInfo() map[string]string {
|
|
||||||
now := time.Now()
|
|
||||||
// 获取当前时间
|
|
||||||
current := now.Format("2006-01-02 15:04:05")
|
|
||||||
// 获取时区
|
|
||||||
timezone := now.Format("-0700 MST")
|
|
||||||
// 获取时区名称
|
|
||||||
timezoneName := now.Format("MST")
|
|
||||||
|
|
||||||
return map[string]string{
|
|
||||||
"current": current,
|
|
||||||
"timezone": timezone,
|
|
||||||
"timezoneName": timezoneName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemoryInfo 内存信息
|
|
||||||
func (s *SystemInfoImpl) MemoryInfo() map[string]any {
|
|
||||||
memInfo, err := mem.VirtualMemory()
|
|
||||||
if err != nil {
|
|
||||||
memInfo.UsedPercent = 0
|
|
||||||
memInfo.Available = 0
|
|
||||||
memInfo.Total = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var memStats runtime.MemStats
|
|
||||||
runtime.ReadMemStats(&memStats)
|
|
||||||
|
|
||||||
return map[string]any{
|
|
||||||
"usage": fmt.Sprintf("%.2f", memInfo.UsedPercent), // 内存利用率
|
|
||||||
"freemem": parse.Bit(float64(memInfo.Available)), // 可用内存大小(GB)
|
|
||||||
"totalmem": parse.Bit(float64(memInfo.Total)), // 总内存大小(GB)
|
|
||||||
"rss": parse.Bit(float64(memStats.Sys)), // 常驻内存大小(RSS)
|
|
||||||
"heapTotal": parse.Bit(float64(memStats.HeapSys)), // 堆总大小
|
|
||||||
"heapUsed": parse.Bit(float64(memStats.HeapAlloc)), // 堆已使用大小
|
|
||||||
"external": parse.Bit(float64(memStats.Sys - memStats.HeapSys)), // 外部内存大小(非堆)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CPUInfo CPU信息
|
|
||||||
func (s *SystemInfoImpl) CPUInfo() map[string]any {
|
|
||||||
var core int = 0
|
|
||||||
var speed string = "未知"
|
|
||||||
var model string = "未知"
|
|
||||||
cpuInfo, err := cpu.Info()
|
|
||||||
if err == nil {
|
|
||||||
core = runtime.NumCPU()
|
|
||||||
speed = fmt.Sprintf("%.0fMHz", cpuInfo[0].Mhz)
|
|
||||||
model = strings.TrimSpace(cpuInfo[0].ModelName)
|
|
||||||
}
|
|
||||||
|
|
||||||
useds := []string{}
|
|
||||||
cpuPercent, err := cpu.Percent(0, true)
|
|
||||||
if err == nil {
|
|
||||||
for _, v := range cpuPercent {
|
|
||||||
useds = append(useds, fmt.Sprintf("%.2f", v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]any{
|
|
||||||
"model": model,
|
|
||||||
"speed": speed,
|
|
||||||
"core": core,
|
|
||||||
"coreUsed": useds,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkInfo 网络信息
|
|
||||||
func (s *SystemInfoImpl) NetworkInfo() map[string]string {
|
|
||||||
ipAddrs := make(map[string]string)
|
|
||||||
interfaces, err := net.Interfaces()
|
|
||||||
if err == nil {
|
|
||||||
for _, iface := range interfaces {
|
|
||||||
name := iface.Name
|
|
||||||
if name[len(name)-1] == '0' {
|
|
||||||
name = name[0 : len(name)-1]
|
|
||||||
name = strings.Trim(name, "")
|
|
||||||
}
|
|
||||||
// ignore localhost
|
|
||||||
if name == "lo" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var addrs []string
|
|
||||||
for _, v := range iface.Addrs {
|
|
||||||
prefix := strings.Split(v.Addr, "/")[0]
|
|
||||||
if strings.Contains(prefix, "::") {
|
|
||||||
addrs = append(addrs, fmt.Sprintf("IPv6 %s", prefix))
|
|
||||||
}
|
|
||||||
if strings.Contains(prefix, ".") {
|
|
||||||
addrs = append(addrs, fmt.Sprintf("IPv4 %s", prefix))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ipAddrs[name] = strings.Join(addrs, " / ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ipAddrs
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiskInfo 磁盘信息
|
|
||||||
func (s *SystemInfoImpl) DiskInfo() []map[string]string {
|
|
||||||
disks := make([]map[string]string, 0)
|
|
||||||
|
|
||||||
partitions, err := disk.Partitions(false)
|
|
||||||
if err != nil {
|
|
||||||
return disks
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, partition := range partitions {
|
|
||||||
usage, err := disk.Usage(partition.Mountpoint)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
disks = append(disks, map[string]string{
|
|
||||||
"size": parse.Bit(float64(usage.Total)),
|
|
||||||
"used": parse.Bit(float64(usage.Used)),
|
|
||||||
"avail": parse.Bit(float64(usage.Free)),
|
|
||||||
"pcent": fmt.Sprintf("%.1f%%", usage.UsedPercent),
|
|
||||||
"target": partition.Device,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return disks
|
|
||||||
}
|
|
||||||
@@ -15,19 +15,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 AlarmController 结构体
|
// 实例化控制层 AlarmController 结构体
|
||||||
var NewAlarmController = &AlarmController{
|
var NewAlarm = &AlarmController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
alarmService: neDataService.NewAlarmImpl,
|
alarmService: neDataService.NewAlarm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 告警数据
|
// 告警数据
|
||||||
//
|
//
|
||||||
// PATH /alarm
|
// PATH /alarm
|
||||||
type AlarmController struct {
|
type AlarmController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
alarmService *neDataService.Alarm // 告警信息服务
|
||||||
// 告警信息服务
|
|
||||||
alarmService neDataService.IAlarm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 告警列表
|
// 告警列表
|
||||||
|
|||||||
@@ -11,19 +11,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 PerfKPIController 结构体
|
// 实例化控制层 PerfKPIController 结构体
|
||||||
var NewPerfKPIController = &PerfKPIController{
|
var NewPerfKPI = &PerfKPIController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
perfKPIService: neDataService.NewPerfKPIImpl,
|
perfKPIService: neDataService.NewPerfKPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 性能统计
|
// 性能统计
|
||||||
//
|
//
|
||||||
// PATH /kpi
|
// PATH /kpi
|
||||||
type PerfKPIController struct {
|
type PerfKPIController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
perfKPIService *neDataService.PerfKPI // 统计信息服务
|
||||||
// 统计信息服务
|
|
||||||
perfKPIService neDataService.IPerfKPI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取统计数据
|
// 获取统计数据
|
||||||
|
|||||||
@@ -22,19 +22,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 AMFController 结构体
|
// 实例化控制层 AMFController 结构体
|
||||||
var NewAMFController = &AMFController{
|
var NewAMF = &AMFController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
ueEventService: neDataService.NewUEEventAMFImpl,
|
ueEventService: neDataService.NewUEEventAMF,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元AMF
|
// 网元AMF
|
||||||
//
|
//
|
||||||
// PATH /amf
|
// PATH /amf
|
||||||
type AMFController struct {
|
type AMFController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
ueEventService *neDataService.UEEventAMF // UE会话事件服务
|
||||||
// UE会话事件服务
|
|
||||||
ueEventService neDataService.IUEEventAMF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UE会话列表
|
// UE会话列表
|
||||||
@@ -121,11 +119,11 @@ func (s *AMFController) UEExport(c *gin.Context) {
|
|||||||
"E1": "Time",
|
"E1": "Time",
|
||||||
}
|
}
|
||||||
// 读取字典数据 UE 事件类型
|
// 读取字典数据 UE 事件类型
|
||||||
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
|
dictUEEventType := sysService.NewSysDictData.SelectDictDataByType("ue_event_type")
|
||||||
// 读取字典数据 UE 事件认证代码类型
|
// 读取字典数据 UE 事件认证代码类型
|
||||||
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
|
dictUEAauthCode := sysService.NewSysDictData.SelectDictDataByType("ue_auth_code")
|
||||||
// 读取字典数据 UE 事件CM状态
|
// 读取字典数据 UE 事件CM状态
|
||||||
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
|
dictUEEventCmState := sysService.NewSysDictData.SelectDictDataByType("ue_event_cm_state")
|
||||||
// 从第二行开始的数据
|
// 从第二行开始的数据
|
||||||
dataCells := make([]map[string]any, 0)
|
dataCells := make([]map[string]any, 0)
|
||||||
for i, row := range rows {
|
for i, row := range rows {
|
||||||
@@ -180,7 +178,7 @@ func (s *AMFController) UEExport(c *gin.Context) {
|
|||||||
timeStr = v.(string)
|
timeStr = v.(string)
|
||||||
}
|
}
|
||||||
if v, ok := eventJSON["status"]; ok && v != nil {
|
if v, ok := eventJSON["status"]; ok && v != nil {
|
||||||
eventResult = v.(string)
|
eventResult = fmt.Sprint(v)
|
||||||
for _, v := range dictUEEventCmState {
|
for _, v := range dictUEEventCmState {
|
||||||
if eventResult == v.DictValue {
|
if eventResult == v.DictValue {
|
||||||
eventResult = i18n.TKey(language, v.DictLabel)
|
eventResult = i18n.TKey(language, v.DictLabel)
|
||||||
|
|||||||
@@ -23,19 +23,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 IMSController 结构体
|
// 实例化控制层 IMSController 结构体
|
||||||
var NewIMSController = &IMSController{
|
var NewIMS = &IMSController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
cdrEventService: neDataService.NewCDREventIMSImpl,
|
cdrEventService: neDataService.NewCDREventIMS,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元IMS
|
// 网元IMS
|
||||||
//
|
//
|
||||||
// PATH /ims
|
// PATH /ims
|
||||||
type IMSController struct {
|
type IMSController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
cdrEventService *neDataService.CDREventIMS // CDR会话事件服务
|
||||||
// CDR会话事件服务
|
|
||||||
cdrEventService neDataService.ICDREventIMS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CDR会话列表
|
// CDR会话列表
|
||||||
@@ -49,13 +47,13 @@ func (s *IMSController) CDRList(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询网元获取IP
|
// 查询网元信息 rmUID
|
||||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// querys.RmUID = neInfo.RmUID
|
querys.RmUID = neInfo.RmUID
|
||||||
|
|
||||||
// 查询数据
|
// 查询数据
|
||||||
data := s.cdrEventService.SelectPage(querys)
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
@@ -103,6 +101,13 @@ func (s *IMSController) CDRExport(c *gin.Context) {
|
|||||||
if querys.PageSize > 10000 {
|
if querys.PageSize > 10000 {
|
||||||
querys.PageSize = 10000
|
querys.PageSize = 10000
|
||||||
}
|
}
|
||||||
|
// 查询网元信息 rmUID
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
querys.RmUID = neInfo.RmUID
|
||||||
data := s.cdrEventService.SelectPage(querys)
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
if parse.Number(data["total"]) == 0 {
|
if parse.Number(data["total"]) == 0 {
|
||||||
// 导出数据记录为空
|
// 导出数据记录为空
|
||||||
@@ -118,16 +123,16 @@ func (s *IMSController) CDRExport(c *gin.Context) {
|
|||||||
"A1": "ID",
|
"A1": "ID",
|
||||||
"B1": "Record Behavior",
|
"B1": "Record Behavior",
|
||||||
"C1": "Type",
|
"C1": "Type",
|
||||||
"D1": "Called",
|
"D1": "Caller",
|
||||||
"E1": "Caller",
|
"E1": "Called",
|
||||||
"F1": "Duration",
|
"F1": "Duration",
|
||||||
"G1": "Result",
|
"G1": "Result",
|
||||||
"H1": "Time",
|
"H1": "Time",
|
||||||
}
|
}
|
||||||
// 读取字典数据 CDR SIP响应代码类别类型
|
// 读取字典数据 CDR SIP响应代码类别类型
|
||||||
dictCDRSipCode := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_sip_code")
|
dictCDRSipCode := sysService.NewSysDictData.SelectDictDataByType("cdr_sip_code")
|
||||||
// 读取字典数据 CDR 呼叫类型
|
// 读取字典数据 CDR 呼叫类型
|
||||||
dictCDRCallType := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_call_type")
|
dictCDRCallType := sysService.NewSysDictData.SelectDictDataByType("cdr_call_type")
|
||||||
// 从第二行开始的数据
|
// 从第二行开始的数据
|
||||||
dataCells := make([]map[string]any, 0)
|
dataCells := make([]map[string]any, 0)
|
||||||
for i, row := range rows {
|
for i, row := range rows {
|
||||||
@@ -193,8 +198,8 @@ func (s *IMSController) CDRExport(c *gin.Context) {
|
|||||||
"A" + idx: row.ID,
|
"A" + idx: row.ID,
|
||||||
"B" + idx: recordType,
|
"B" + idx: recordType,
|
||||||
"C" + idx: callTypeLable,
|
"C" + idx: callTypeLable,
|
||||||
"D" + idx: called,
|
"D" + idx: caller,
|
||||||
"E" + idx: caller,
|
"E" + idx: called,
|
||||||
"F" + idx: duration,
|
"F" + idx: duration,
|
||||||
"G" + idx: callResult,
|
"G" + idx: callResult,
|
||||||
"H" + idx: timeStr,
|
"H" + idx: timeStr,
|
||||||
|
|||||||
@@ -23,19 +23,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 MMEController 结构体
|
// 实例化控制层 MMEController 结构体
|
||||||
var NewMMEController = &MMEController{
|
var NewMME = &MMEController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
ueEventService: neDataService.NewUEEventMMEImpl,
|
ueEventService: neDataService.NewUEEventMME,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元MME
|
// 网元MME
|
||||||
//
|
//
|
||||||
// PATH /mme
|
// PATH /mme
|
||||||
type MMEController struct {
|
type MMEController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
ueEventService *neDataService.UEEventMME // UE会话事件服务
|
||||||
// UE会话事件服务
|
|
||||||
ueEventService neDataService.IUEEventMME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UE会话列表
|
// UE会话列表
|
||||||
@@ -122,11 +120,11 @@ func (s *MMEController) UEExport(c *gin.Context) {
|
|||||||
"E1": "Time",
|
"E1": "Time",
|
||||||
}
|
}
|
||||||
// 读取字典数据 UE 事件类型
|
// 读取字典数据 UE 事件类型
|
||||||
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
|
dictUEEventType := sysService.NewSysDictData.SelectDictDataByType("ue_event_type")
|
||||||
// 读取字典数据 UE 事件认证代码类型
|
// 读取字典数据 UE 事件认证代码类型
|
||||||
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
|
dictUEAauthCode := sysService.NewSysDictData.SelectDictDataByType("ue_auth_code")
|
||||||
// 读取字典数据 UE 事件CM状态
|
// 读取字典数据 UE 事件CM状态
|
||||||
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
|
dictUEEventCmState := sysService.NewSysDictData.SelectDictDataByType("ue_event_cm_state")
|
||||||
// 从第二行开始的数据
|
// 从第二行开始的数据
|
||||||
dataCells := make([]map[string]any, 0)
|
dataCells := make([]map[string]any, 0)
|
||||||
for i, row := range rows {
|
for i, row := range rows {
|
||||||
|
|||||||
@@ -15,25 +15,26 @@ import (
|
|||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
"be.ems/src/modules/network_data/model"
|
"be.ems/src/modules/network_data/model"
|
||||||
neDataService "be.ems/src/modules/network_data/service"
|
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"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 SMFController 结构体
|
// 实例化控制层 SMFController 结构体
|
||||||
var NewSMFController = &SMFController{
|
var NewSMF = &SMFController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
cdrEventService: neDataService.NewCDREventSMFImpl,
|
cdrEventService: neDataService.NewCDREventSMF,
|
||||||
|
udmUserInfoService: neDataService.NewUDMUserInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元SMF
|
// 网元SMF
|
||||||
//
|
//
|
||||||
// PATH /smf
|
// PATH /smf
|
||||||
type SMFController struct {
|
type SMFController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
cdrEventService *neDataService.CDREventSMF // CDR会话事件服务
|
||||||
// CDR会话事件服务
|
udmUserInfoService *neDataService.UDMUserInfo // UDM用户信息服务
|
||||||
cdrEventService neDataService.ICDREventSMF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CDR会话列表
|
// CDR会话列表
|
||||||
@@ -47,13 +48,13 @@ func (s *SMFController) CDRList(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询网元获取IP
|
// 查询网元信息 rmUID
|
||||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// querys.RmUID = neInfo.RmUID
|
querys.RmUID = neInfo.RmUID
|
||||||
|
|
||||||
// 查询数据
|
// 查询数据
|
||||||
data := s.cdrEventService.SelectPage(querys)
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
@@ -101,6 +102,13 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
|||||||
if querys.PageSize > 10000 {
|
if querys.PageSize > 10000 {
|
||||||
querys.PageSize = 10000
|
querys.PageSize = 10000
|
||||||
}
|
}
|
||||||
|
// 查询网元信息 rmUID
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
querys.RmUID = neInfo.RmUID
|
||||||
data := s.cdrEventService.SelectPage(querys)
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
if parse.Number(data["total"]) == 0 {
|
if parse.Number(data["total"]) == 0 {
|
||||||
// 导出数据记录为空
|
// 导出数据记录为空
|
||||||
@@ -115,17 +123,30 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
|||||||
headerCells := map[string]string{
|
headerCells := map[string]string{
|
||||||
"A1": "ID",
|
"A1": "ID",
|
||||||
"B1": "Charging ID",
|
"B1": "Charging ID",
|
||||||
"C1": "Subscriber ID Data",
|
"C1": "NE Name",
|
||||||
"D1": "Subscriber ID Type",
|
"D1": "Resource Unique ID",
|
||||||
"E1": "Data Volume Uplink",
|
"E1": "Subscriber ID Data",
|
||||||
"F1": "Data Volume Downlink",
|
"F1": "Subscriber ID Type",
|
||||||
"G1": "Data Total Volume",
|
"G1": "Data Volume Uplink",
|
||||||
"H1": "Duration",
|
"H1": "Data Volume Downlink",
|
||||||
"I1": "Invocation Time",
|
"I1": "Data Total Volume",
|
||||||
"J1": "PDU Session Charging Information",
|
"J1": "Duration",
|
||||||
|
"K1": "Invocation Time",
|
||||||
|
"L1": "User Identifier",
|
||||||
|
"M1": "SSC Mode",
|
||||||
|
"N1": "DNN ID",
|
||||||
|
"O1": "PDU Type",
|
||||||
|
"P1": "RAT Type",
|
||||||
|
"Q1": "PDU IPv4 Address",
|
||||||
|
"R1": "Network Function IPv4",
|
||||||
|
"S1": "PDU IPv6 Address Swith Prefix",
|
||||||
|
"T1": "Record Network Function ID",
|
||||||
|
"U1": "Record Type",
|
||||||
|
"V1": "Record Opening Time",
|
||||||
}
|
}
|
||||||
// 从第二行开始的数据
|
// 从第二行开始的数据
|
||||||
dataCells := make([]map[string]any, 0)
|
dataCells := make([]map[string]any, 0)
|
||||||
|
|
||||||
for i, row := range rows {
|
for i, row := range rows {
|
||||||
idx := strconv.Itoa(i + 2)
|
idx := strconv.Itoa(i + 2)
|
||||||
// 解析 JSON 字符串为 map
|
// 解析 JSON 字符串为 map
|
||||||
@@ -150,12 +171,22 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
|||||||
subscriptionIDData = sub["subscriptionIDData"].(string)
|
subscriptionIDData = sub["subscriptionIDData"].(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 网络功能 IPv4 地址
|
||||||
|
networkFunctionIPv4Address := ""
|
||||||
|
if v, ok := cdrJSON["nFunctionConsumerInformation"]; ok && v != nil {
|
||||||
|
if conInfo, conInfoOk := v.(map[string]any); conInfoOk && conInfo != nil {
|
||||||
|
networkFunctionIPv4Address = conInfo["networkFunctionIPv4Address"].(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 数据量上行链路
|
// 数据量上行链路
|
||||||
dataVolumeUplink := []string{}
|
dataVolumeUplink := []string{}
|
||||||
// 数据量下行链路
|
// 数据量下行链路
|
||||||
dataVolumeDownlink := []string{}
|
dataVolumeDownlink := []string{}
|
||||||
// 数据总量
|
// 数据总量
|
||||||
dataTotalVolume := []string{}
|
dataTotalVolume := []string{}
|
||||||
|
|
||||||
if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
|
if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
|
||||||
usageList := v.([]any)
|
usageList := v.([]any)
|
||||||
if len(usageList) > 0 {
|
if len(usageList) > 0 {
|
||||||
@@ -190,32 +221,31 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
|||||||
invocationTimestamp = v.(string)
|
invocationTimestamp = v.(string)
|
||||||
}
|
}
|
||||||
// 记录打开时间
|
// 记录打开时间
|
||||||
pduSessionChargingInformation := ""
|
User_Identifier := ""
|
||||||
|
SSC_Mode := ""
|
||||||
|
RAT_Type := ""
|
||||||
|
DNN_ID := ""
|
||||||
|
PDU_Type := ""
|
||||||
|
PDU_IPv4 := ""
|
||||||
|
PDU_IPv6 := ""
|
||||||
if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
|
if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
|
||||||
pduInfo := v.(map[string]any)
|
pduInfo := v.(map[string]any)
|
||||||
|
|
||||||
User_Identifier := ""
|
|
||||||
if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
|
if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
|
||||||
User_Identifier = v.(string)
|
User_Identifier = v.(string)
|
||||||
}
|
}
|
||||||
SSC_Mode := ""
|
|
||||||
if v, ok := pduInfo["sSCMode"]; ok && v != nil {
|
if v, ok := pduInfo["sSCMode"]; ok && v != nil {
|
||||||
SSC_Mode = v.(string)
|
SSC_Mode = v.(string)
|
||||||
}
|
}
|
||||||
RAT_Type := ""
|
|
||||||
if v, ok := pduInfo["rATType"]; ok && v != nil {
|
if v, ok := pduInfo["rATType"]; ok && v != nil {
|
||||||
RAT_Type = v.(string)
|
RAT_Type = v.(string)
|
||||||
}
|
}
|
||||||
DNN_ID := ""
|
|
||||||
if v, ok := pduInfo["dNNID"]; ok && v != nil {
|
if v, ok := pduInfo["dNNID"]; ok && v != nil {
|
||||||
DNN_ID = v.(string)
|
DNN_ID = v.(string)
|
||||||
}
|
}
|
||||||
PDU_Type := ""
|
|
||||||
if v, ok := pduInfo["pDUType"]; ok && v != nil {
|
if v, ok := pduInfo["pDUType"]; ok && v != nil {
|
||||||
PDU_Type = v.(string)
|
PDU_Type = v.(string)
|
||||||
}
|
}
|
||||||
PDU_IPv4 := ""
|
|
||||||
PDU_IPv6 := ""
|
|
||||||
if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
|
if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
|
||||||
pDUAddress := v.(map[string]any)
|
pDUAddress := v.(map[string]any)
|
||||||
if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
|
if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
|
||||||
@@ -226,24 +256,54 @@ func (s *SMFController) CDRExport(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pduSessionChargingInformation = fmt.Sprintf(`User Identifier: %s
|
// pduSessionChargingInformation = fmt.Sprintf(`User Identifier: %s
|
||||||
SSC Mode: %s RAT Type: %s DNN ID: %s
|
// SSC Mode: %s RAT Type: %s DNN ID: %s
|
||||||
PDU Type: %s
|
// PDU Type: %s
|
||||||
PDU IPv4 Address: %s
|
// PDU IPv4 Address: %s
|
||||||
PDU IPv6 Addres Swith Prefix: %s`, User_Identifier, SSC_Mode, RAT_Type, DNN_ID, PDU_Type, PDU_IPv4, PDU_IPv6)
|
// PDU IPv6 Addres Swith Prefix: %s`, User_Identifier, SSC_Mode, RAT_Type, DNN_ID, PDU_Type, PDU_IPv4, PDU_IPv6)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录网络参数ID
|
||||||
|
recordNFID := ""
|
||||||
|
if v, ok := cdrJSON["recordingNetworkFunctionID"]; ok && v != nil {
|
||||||
|
recordNFID = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录开始时间
|
||||||
|
recordOpeningTime := ""
|
||||||
|
if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil {
|
||||||
|
recordOpeningTime = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
//记录类型
|
||||||
|
recordType := ""
|
||||||
|
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
||||||
|
recordType = v.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataCells = append(dataCells, map[string]any{
|
dataCells = append(dataCells, map[string]any{
|
||||||
"A" + idx: row.ID,
|
"A" + idx: row.ID,
|
||||||
"B" + idx: chargingID,
|
"B" + idx: chargingID,
|
||||||
"C" + idx: subscriptionIDData,
|
"C" + idx: row.NeName,
|
||||||
"D" + idx: subscriptionIDType,
|
"D" + idx: row.RmUID,
|
||||||
"E" + idx: strings.Join(dataVolumeUplink, ","),
|
"E" + idx: subscriptionIDData,
|
||||||
"F" + idx: strings.Join(dataVolumeDownlink, ","),
|
"F" + idx: subscriptionIDType,
|
||||||
"G" + idx: strings.Join(dataTotalVolume, ","),
|
"G" + idx: strings.Join(dataVolumeUplink, ","),
|
||||||
"H" + idx: duration,
|
"H" + idx: strings.Join(dataVolumeDownlink, ","),
|
||||||
"I" + idx: invocationTimestamp,
|
"I" + idx: strings.Join(dataTotalVolume, ","),
|
||||||
"J" + idx: pduSessionChargingInformation,
|
"J" + idx: duration,
|
||||||
|
"K" + idx: invocationTimestamp,
|
||||||
|
"L" + idx: User_Identifier,
|
||||||
|
"M" + idx: SSC_Mode,
|
||||||
|
"N" + idx: DNN_ID,
|
||||||
|
"O" + idx: PDU_Type,
|
||||||
|
"P" + idx: RAT_Type,
|
||||||
|
"Q" + idx: PDU_IPv4,
|
||||||
|
"R" + idx: networkFunctionIPv4Address,
|
||||||
|
"S" + idx: PDU_IPv6,
|
||||||
|
"T" + idx: recordNFID,
|
||||||
|
"U" + idx: recordType,
|
||||||
|
"V" + idx: recordOpeningTime,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,3 +316,62 @@ PDU IPv6 Addres Swith Prefix: %s`, User_Identifier, SSC_Mode, RAT_Type, DNN_ID,
|
|||||||
|
|
||||||
c.FileAttachment(saveFilePath, fileName)
|
c.FileAttachment(saveFilePath, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在线订阅用户列表信息
|
||||||
|
//
|
||||||
|
// GET /subscribers
|
||||||
|
func (s *SMFController) SubUserList(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
var query struct {
|
||||||
|
NeId string `form:"neId" binding:"required"`
|
||||||
|
IMSI string `form:"imsi"`
|
||||||
|
MSISDN string `form:"msisdn"`
|
||||||
|
Upstate string `form:"upstate"`
|
||||||
|
PageNum string `form:"pageNum"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindQuery(&query); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询网元信息 rmUID
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("SMF", query.NeId)
|
||||||
|
if neInfo.NeId != query.NeId || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网元直连
|
||||||
|
data, err := neFetchlink.SMFSubInfoList(neInfo, map[string]string{
|
||||||
|
"imsi": query.IMSI,
|
||||||
|
"msisdn": query.MSISDN,
|
||||||
|
"upstate": query.Upstate,
|
||||||
|
"pageNum": query.PageNum,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对数据进行处理,去掉前缀,并加入imsi拓展信息
|
||||||
|
rows := data["rows"].([]any)
|
||||||
|
if len(rows) > 0 {
|
||||||
|
arr := &rows
|
||||||
|
for i := range *arr {
|
||||||
|
item := (*arr)[i].(map[string]any)
|
||||||
|
if v, ok := item["imsi"]; ok && v != nil {
|
||||||
|
imsiStr := v.(string)
|
||||||
|
imsiStr = strings.TrimPrefix(imsiStr, "imsi-")
|
||||||
|
item["imsi"] = imsiStr
|
||||||
|
// 查UDM拓展信息
|
||||||
|
info := s.udmUserInfoService.SelectByIMSIAndNeID(imsiStr, "")
|
||||||
|
item["remark"] = info.Remark
|
||||||
|
}
|
||||||
|
if v, ok := item["msisdn"]; ok && v != nil {
|
||||||
|
item["msisdn"] = strings.TrimPrefix(v.(string), "msisdn-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, result.Ok(data))
|
||||||
|
}
|
||||||
|
|||||||
195
src/modules/network_data/controller/smsc.go
Normal file
195
src/modules/network_data/controller/smsc.go
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/ctx"
|
||||||
|
"be.ems/src/framework/utils/date"
|
||||||
|
"be.ems/src/framework/utils/file"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/vo/result"
|
||||||
|
"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"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化控制层 SMSCController 结构体
|
||||||
|
var NewSMSC = &SMSCController{
|
||||||
|
neInfoService: neService.NewNeInfo,
|
||||||
|
cdrEventService: neDataService.NewCDREventSMSC,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网元SMSC
|
||||||
|
//
|
||||||
|
// PATH /smsc
|
||||||
|
type SMSCController struct {
|
||||||
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
|
cdrEventService *neDataService.CDREventSMSC // CDR会话事件服务
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDR会话列表
|
||||||
|
//
|
||||||
|
// GET /cdr/list
|
||||||
|
func (s *SMSCController) CDRList(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
var querys model.CDREventSMSCQuery
|
||||||
|
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询网元信息 rmUID
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
querys.RmUID = neInfo.RmUID
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
|
c.JSON(200, result.Ok(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDR会话删除
|
||||||
|
//
|
||||||
|
// DELETE /cdr/:cdrIds
|
||||||
|
func (s *SMSCController) CDRRemove(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
cdrIds := c.Param("cdrIds")
|
||||||
|
if cdrIds == "" {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 处理字符转id数组后去重
|
||||||
|
ids := strings.Split(cdrIds, ",")
|
||||||
|
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||||
|
if len(uniqueIDs) <= 0 {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rows, err := s.cdrEventService.DeleteByIds(uniqueIDs)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||||
|
c.JSON(200, result.OkMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDR会话列表导出
|
||||||
|
//
|
||||||
|
// POST /cdr/export
|
||||||
|
func (s *SMSCController) CDRExport(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
// 查询结果,根据查询条件结果,单页最大值限制
|
||||||
|
var querys model.CDREventSMSCQuery
|
||||||
|
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 限制导出数据集
|
||||||
|
if querys.PageSize > 10000 {
|
||||||
|
querys.PageSize = 10000
|
||||||
|
}
|
||||||
|
// 查询网元信息 rmUID
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
querys.RmUID = neInfo.RmUID
|
||||||
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
|
if parse.Number(data["total"]) == 0 {
|
||||||
|
// 导出数据记录为空
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rows := data["rows"].([]model.CDREventSMSC)
|
||||||
|
|
||||||
|
// 导出文件名称
|
||||||
|
fileName := fmt.Sprintf("smsc_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||||
|
// 第一行表头标题
|
||||||
|
headerCells := map[string]string{
|
||||||
|
"A1": "ID",
|
||||||
|
"B1": "Record Behavior",
|
||||||
|
"C1": "Service Type",
|
||||||
|
"D1": "Caller",
|
||||||
|
"E1": "Called",
|
||||||
|
"F1": "Result",
|
||||||
|
"G1": "Time",
|
||||||
|
}
|
||||||
|
// 从第二行开始的数据
|
||||||
|
dataCells := make([]map[string]any, 0)
|
||||||
|
for i, row := range rows {
|
||||||
|
idx := strconv.Itoa(i + 2)
|
||||||
|
// 解析 JSON 字符串为 map
|
||||||
|
var cdrJSON map[string]interface{}
|
||||||
|
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 记录类型
|
||||||
|
recordType := ""
|
||||||
|
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
||||||
|
recordType = v.(string)
|
||||||
|
}
|
||||||
|
// 服务类型
|
||||||
|
serviceType := ""
|
||||||
|
if v, ok := cdrJSON["serviceType"]; ok && v != nil {
|
||||||
|
serviceType = v.(string)
|
||||||
|
}
|
||||||
|
// 被叫
|
||||||
|
called := ""
|
||||||
|
if v, ok := cdrJSON["calledParty"]; ok && v != nil {
|
||||||
|
called = v.(string)
|
||||||
|
}
|
||||||
|
// 主叫
|
||||||
|
caller := ""
|
||||||
|
if v, ok := cdrJSON["callerParty"]; ok && v != nil {
|
||||||
|
caller = v.(string)
|
||||||
|
}
|
||||||
|
// 呼叫结果 0失败,1成功
|
||||||
|
callResult := "Fail"
|
||||||
|
if v, ok := cdrJSON["result"]; ok && v != nil {
|
||||||
|
resultVal := parse.Number(v)
|
||||||
|
if resultVal == 1 {
|
||||||
|
callResult = "Success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 取时间
|
||||||
|
timeStr := ""
|
||||||
|
if v, ok := cdrJSON["updateTime"]; ok && v != nil {
|
||||||
|
releaseTime := parse.Number(v)
|
||||||
|
timeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCells = append(dataCells, map[string]any{
|
||||||
|
"A" + idx: row.ID,
|
||||||
|
"B" + idx: recordType,
|
||||||
|
"C" + idx: serviceType,
|
||||||
|
"D" + idx: caller,
|
||||||
|
"E" + idx: called,
|
||||||
|
"F" + idx: callResult,
|
||||||
|
"G" + idx: timeStr,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出数据表格
|
||||||
|
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.FileAttachment(saveFilePath, fileName)
|
||||||
|
}
|
||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
|
|
||||||
"be.ems/src/framework/constants/uploadsubpath"
|
"be.ems/src/framework/constants/uploadsubpath"
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/telnet"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/utils/file"
|
"be.ems/src/framework/utils/file"
|
||||||
"be.ems/src/framework/utils/parse"
|
"be.ems/src/framework/utils/parse"
|
||||||
"be.ems/src/framework/utils/telnet"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
"be.ems/src/modules/network_data/model"
|
"be.ems/src/modules/network_data/model"
|
||||||
neDataService "be.ems/src/modules/network_data/service"
|
neDataService "be.ems/src/modules/network_data/service"
|
||||||
@@ -23,18 +23,16 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 UDMAuthController 结构体
|
// 实例化控制层 UDMAuthController 结构体
|
||||||
var NewUDMAuth = &UDMAuthController{
|
var NewUDMAuth = &UDMAuthController{
|
||||||
udmAuthService: neDataService.NewUDMAuthImpl,
|
udmAuthService: neDataService.NewUDMAuthUser,
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM鉴权用户
|
// UDM鉴权用户
|
||||||
//
|
//
|
||||||
// PATH /udm/auth
|
// PATH /udm/auth
|
||||||
type UDMAuthController struct {
|
type UDMAuthController struct {
|
||||||
// UDM鉴权信息服务
|
udmAuthService *neDataService.UDMAuthUser // UDM鉴权信息服务
|
||||||
udmAuthService neDataService.IUDMAuth
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
// 网元信息服务
|
|
||||||
neInfoService neService.INeInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM鉴权用户重载数据
|
// UDM鉴权用户重载数据
|
||||||
@@ -48,7 +46,6 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
neId = ""
|
|
||||||
data := s.udmAuthService.ResetData(neId)
|
data := s.udmAuthService.ResetData(neId)
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -58,9 +55,8 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
|
|||||||
// GET /list
|
// GET /list
|
||||||
func (s *UDMAuthController) List(c *gin.Context) {
|
func (s *UDMAuthController) List(c *gin.Context) {
|
||||||
querys := ctx.QueryMap(c)
|
querys := ctx.QueryMap(c)
|
||||||
querys["neId"] = ""
|
total, rows := s.udmAuthService.SelectPage(querys)
|
||||||
data := s.udmAuthService.SelectPage(querys)
|
c.JSON(200, result.Ok(map[string]any{"total": total, "rows": rows}))
|
||||||
c.JSON(200, result.Ok(data))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM鉴权用户信息
|
// UDM鉴权用户信息
|
||||||
@@ -81,7 +77,7 @@ func (s *UDMAuthController) Info(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -102,27 +98,9 @@ func (s *UDMAuthController) Info(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
neId = ""
|
// 解析返回的数据
|
||||||
u := model.UDMAuth{
|
u := s.udmAuthService.ParseInfo(imsi, neId, data)
|
||||||
IMSI: imsi,
|
s.udmAuthService.Insert(neId, u)
|
||||||
Amf: data["amf"],
|
|
||||||
Status: "1",
|
|
||||||
Ki: data["ki"],
|
|
||||||
AlgoIndex: data["algo"],
|
|
||||||
Opc: data["opc"],
|
|
||||||
NeId: neId,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询imsi存在赋予id用于更新
|
|
||||||
list := s.udmAuthService.SelectList(u)
|
|
||||||
if len(list) > 0 {
|
|
||||||
item := list[0]
|
|
||||||
if item.ID != "" {
|
|
||||||
u.ID = item.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go s.udmAuthService.Insert(neId, u)
|
|
||||||
|
|
||||||
c.JSON(200, result.OkData(u))
|
c.JSON(200, result.OkData(u))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +115,7 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMAuth
|
var body model.UDMAuthUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || body.IMSI == "" {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
@@ -150,7 +128,7 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -159,7 +137,8 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
cmd := fmt.Sprintf("add authdat:imsi=%s,", body.IMSI)
|
||||||
|
cmd += s.udmAuthService.ParseCommandParams(body)
|
||||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -168,8 +147,7 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmAuthService.Insert(neId, body)
|
||||||
go s.udmAuthService.Insert(neId, body)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -186,7 +164,7 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMAuth
|
var body model.UDMAuthUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || body.IMSI == "" {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
@@ -199,7 +177,7 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -208,7 +186,8 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
cmd := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,", body.IMSI, num)
|
||||||
|
cmd += s.udmAuthService.ParseCommandParams(body)
|
||||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -217,8 +196,7 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmAuthService.LoadData(neId, body.IMSI, num)
|
||||||
go s.udmAuthService.LoadData(neId, body.IMSI, num)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -234,7 +212,7 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMAuth
|
var body model.UDMAuthUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || body.IMSI == "" {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
@@ -247,7 +225,7 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -256,20 +234,8 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("mod authdata:imsi=%s", body.IMSI)
|
cmd := fmt.Sprintf("mod authdata:imsi=%s,", body.IMSI)
|
||||||
// 修改的参数名称
|
cmd += s.udmAuthService.ParseCommandParams(body)
|
||||||
if body.Ki != "" {
|
|
||||||
cmd += fmt.Sprintf(",ki=%s", body.Ki)
|
|
||||||
}
|
|
||||||
if body.Amf != "" {
|
|
||||||
cmd += fmt.Sprintf(",amf=%s", body.Amf)
|
|
||||||
}
|
|
||||||
if body.AlgoIndex != "" {
|
|
||||||
cmd += fmt.Sprintf(",algo=%s", body.AlgoIndex)
|
|
||||||
}
|
|
||||||
if body.Opc != "" {
|
|
||||||
cmd += fmt.Sprintf(",opc=%s", body.Opc)
|
|
||||||
}
|
|
||||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -278,8 +244,7 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmAuthService.Insert(neId, body)
|
||||||
go s.udmAuthService.Insert(neId, body)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -310,7 +275,7 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -329,8 +294,7 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmAuthService.Delete(imsi, neId)
|
||||||
go s.udmAuthService.Delete(neId, imsi)
|
|
||||||
}
|
}
|
||||||
resultData[imsi] = data
|
resultData[imsi] = data
|
||||||
}
|
}
|
||||||
@@ -357,7 +321,7 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -375,8 +339,7 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmAuthService.LoadData(neId, imsi, num)
|
||||||
go s.udmAuthService.LoadData(neId, imsi, num)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -386,32 +349,44 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
|
|||||||
// POST /export
|
// POST /export
|
||||||
func (s *UDMAuthController) Export(c *gin.Context) {
|
func (s *UDMAuthController) Export(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
var body struct {
|
// 查询结果,根据查询条件结果,单页最大值限制
|
||||||
NeId string `json:"neId" binding:"required"`
|
querys := ctx.BodyJSONMap(c)
|
||||||
Type string `json:"type" binding:"required"`
|
neId := querys["neId"].(string)
|
||||||
}
|
fileType := querys["type"].(string)
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
if neId == "" || fileType == "" {
|
||||||
if err != nil {
|
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !(fileType == "csv" || fileType == "txt") {
|
||||||
if !(body.Type == "csv" || body.Type == "txt") {
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errExportType")))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
neId := ""
|
querys["pageNum"] = 1
|
||||||
list := s.udmAuthService.SelectList(model.UDMAuth{NeId: neId})
|
querys["pageSize"] = 10000
|
||||||
// 文件名
|
total, rows := s.udmAuthService.SelectPage(querys)
|
||||||
fileName := fmt.Sprintf("udm_auth_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
if total == 0 {
|
||||||
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
// 导出数据记录为空
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if body.Type == "csv" {
|
// rows := s.udmAuthService.SelectList(model.UDMAuthUser{NeId: neId})
|
||||||
|
if len(rows) <= 0 {
|
||||||
|
// 导出数据记录为空
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件名
|
||||||
|
fileName := fmt.Sprintf("udm_auth_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
|
||||||
|
filePath := filepath.Join(file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||||
|
|
||||||
|
if fileType == "csv" {
|
||||||
// 转换数据
|
// 转换数据
|
||||||
data := [][]string{}
|
data := [][]string{}
|
||||||
data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
|
data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
|
||||||
for _, v := range list {
|
for _, v := range rows {
|
||||||
opc := v.Opc
|
opc := v.Opc
|
||||||
if opc == "-" {
|
if opc == "-" {
|
||||||
opc = ""
|
opc = ""
|
||||||
@@ -426,10 +401,10 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if body.Type == "txt" {
|
if fileType == "txt" {
|
||||||
// 转换数据
|
// 转换数据
|
||||||
data := [][]string{}
|
data := [][]string{}
|
||||||
for _, v := range list {
|
for _, v := range rows {
|
||||||
opc := v.Opc
|
opc := v.Opc
|
||||||
if opc == "-" {
|
if opc == "-" {
|
||||||
opc = ""
|
opc = ""
|
||||||
@@ -437,8 +412,8 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
|||||||
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, opc})
|
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, opc})
|
||||||
}
|
}
|
||||||
// 输出到文件
|
// 输出到文件
|
||||||
err = file.WriterFileTXT(data, ",", filePath)
|
|
||||||
if err != nil {
|
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -534,13 +509,11 @@ func (s *UDMAuthController) Import(c *gin.Context) {
|
|||||||
if strings.Contains(resultMsg, "ok") {
|
if strings.Contains(resultMsg, "ok") {
|
||||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||||
data := file.ReadFileCSV(localFilePath)
|
data := file.ReadFileCSV(localFilePath)
|
||||||
neId := ""
|
go s.udmAuthService.InsertData(neInfo.NeId, "csv", data)
|
||||||
go s.udmAuthService.InsertData(neId, "csv", data)
|
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||||
data := file.ReadFileTXT(",", localFilePath)
|
data := file.ReadFileTXT(",", localFilePath)
|
||||||
neId := ""
|
go s.udmAuthService.InsertData(neInfo.NeId, "txt", data)
|
||||||
go s.udmAuthService.InsertData(neId, "txt", data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkMsg(resultMsg))
|
c.JSON(200, result.OkMsg(resultMsg))
|
||||||
|
|||||||
@@ -3,16 +3,15 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/constants/uploadsubpath"
|
"be.ems/src/framework/constants/uploadsubpath"
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/telnet"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/utils/file"
|
"be.ems/src/framework/utils/file"
|
||||||
"be.ems/src/framework/utils/parse"
|
"be.ems/src/framework/utils/parse"
|
||||||
"be.ems/src/framework/utils/telnet"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
"be.ems/src/modules/network_data/model"
|
"be.ems/src/modules/network_data/model"
|
||||||
neDataService "be.ems/src/modules/network_data/service"
|
neDataService "be.ems/src/modules/network_data/service"
|
||||||
@@ -23,18 +22,16 @@ import (
|
|||||||
|
|
||||||
// 实例化控制层 UDMSubController 结构体
|
// 实例化控制层 UDMSubController 结构体
|
||||||
var NewUDMSub = &UDMSubController{
|
var NewUDMSub = &UDMSubController{
|
||||||
udmSubService: neDataService.NewUDMSubImpl,
|
udmSubService: neDataService.NewUDMSubUser,
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM签约用户
|
// UDM签约用户
|
||||||
//
|
//
|
||||||
// PATH /udm/sub
|
// PATH /udm/sub
|
||||||
type UDMSubController struct {
|
type UDMSubController struct {
|
||||||
// UDM签约信息服务
|
udmSubService *neDataService.UDMSubUser // UDM签约信息服务
|
||||||
udmSubService neDataService.IUDMSub
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
// 网元信息服务
|
|
||||||
neInfoService neService.INeInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM签约用户重载数据
|
// UDM签约用户重载数据
|
||||||
@@ -48,7 +45,6 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
neId = ""
|
|
||||||
data := s.udmSubService.ResetData(neId)
|
data := s.udmSubService.ResetData(neId)
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -58,9 +54,8 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
|
|||||||
// GET /list
|
// GET /list
|
||||||
func (s *UDMSubController) List(c *gin.Context) {
|
func (s *UDMSubController) List(c *gin.Context) {
|
||||||
querys := ctx.QueryMap(c)
|
querys := ctx.QueryMap(c)
|
||||||
querys["neId"] = ""
|
total, rows := s.udmSubService.SelectPage(querys)
|
||||||
data := s.udmSubService.SelectPage(querys)
|
c.JSON(200, result.Ok(map[string]any{"total": total, "rows": rows}))
|
||||||
c.JSON(200, result.Ok(data))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDM签约用户信息
|
// UDM签约用户信息
|
||||||
@@ -81,7 +76,7 @@ func (s *UDMSubController) Info(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -103,52 +98,8 @@ func (s *UDMSubController) Info(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 解析返回的数据
|
// 解析返回的数据
|
||||||
cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64)
|
u := s.udmSubService.ParseInfo(imsi, neId, data)
|
||||||
rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64)
|
s.udmSubService.Insert(neId, u)
|
||||||
msisdn := data["MSISDN"]
|
|
||||||
imsMsisdnLen := strings.Index(msisdn, ",")
|
|
||||||
if imsMsisdnLen != -1 {
|
|
||||||
msisdn = msisdn[:imsMsisdnLen]
|
|
||||||
}
|
|
||||||
neId = ""
|
|
||||||
u := model.UDMSub{
|
|
||||||
IMSI: imsi,
|
|
||||||
Msisdn: msisdn,
|
|
||||||
Ambr: data["AMBR"],
|
|
||||||
Arfb: data["AreaForbidden"],
|
|
||||||
Cn: fmt.Sprint(cnType),
|
|
||||||
SmData: data["SM-Data(snssai+dnn[1..n])"],
|
|
||||||
Sar: data["ServiceAreaRestriction"],
|
|
||||||
Nssai: data["NSSAI"],
|
|
||||||
SmfSel: data["Smf-Selection"],
|
|
||||||
Rat: fmt.Sprint(rat),
|
|
||||||
NeId: neId,
|
|
||||||
}
|
|
||||||
// 1,64,24,65,def_eps,1,2,010200000000,-
|
|
||||||
if v, ok := data["EPS-Data"]; ok {
|
|
||||||
u.EpsDat = v
|
|
||||||
arr := strings.Split(v, ",")
|
|
||||||
u.EpsFlag = arr[0]
|
|
||||||
u.EpsOdb = arr[1]
|
|
||||||
u.HplmnOdb = arr[2]
|
|
||||||
u.Ard = arr[3]
|
|
||||||
u.Epstpl = arr[4]
|
|
||||||
u.ContextId = arr[5]
|
|
||||||
u.ApnContext = arr[7]
|
|
||||||
// [6] 是不要的,导入和导出不用
|
|
||||||
u.StaticIp = arr[8]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询imsi存在赋予id用于更新
|
|
||||||
list := s.udmSubService.SelectList(u)
|
|
||||||
if len(list) > 0 {
|
|
||||||
item := list[0]
|
|
||||||
if item.ID != "" {
|
|
||||||
u.ID = item.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go s.udmSubService.Insert(neId, u)
|
|
||||||
|
|
||||||
c.JSON(200, result.OkData(u))
|
c.JSON(200, result.OkData(u))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,9 +114,9 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMSub
|
var body model.UDMSubUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || len(body.IMSI) < 15 {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -176,7 +127,7 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -185,12 +136,8 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
cmd := fmt.Sprintf("add udmuser:imsi=%s,", body.IMSI)
|
||||||
body.IMSI, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
cmd += s.udmSubService.ParseCommandParams(body)
|
||||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
|
||||||
if body.StaticIp != "" {
|
|
||||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
|
||||||
}
|
|
||||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -199,8 +146,8 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
body.NeId = neId
|
||||||
go s.udmSubService.Insert(neId, body)
|
s.udmSubService.Insert(neId, body)
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -217,9 +164,9 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMSub
|
var body model.UDMSubUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || len(body.IMSI) < 15 {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -230,7 +177,7 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -239,8 +186,8 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
cmd := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,", body.IMSI, body.MSISDN, num)
|
||||||
body.IMSI, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
cmd += s.udmSubService.ParseCommandParams(body)
|
||||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
||||||
if body.StaticIp != "" {
|
if body.StaticIp != "" {
|
||||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||||
@@ -253,8 +200,7 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmSubService.LoadData(neId, body.IMSI, num, body.Remark)
|
||||||
go s.udmSubService.LoadData(neId, body.IMSI, num)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -270,9 +216,9 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var body model.UDMSub
|
var body model.UDMSubUser
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||||
if err != nil || body.IMSI == "" {
|
if err != nil || len(body.IMSI) < 15 {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -283,7 +229,7 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -292,62 +238,8 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
|||||||
defer telnetClient.Close()
|
defer telnetClient.Close()
|
||||||
|
|
||||||
// 发送MML
|
// 发送MML
|
||||||
cmd := fmt.Sprintf("mod udmuser:imsi=%s", body.IMSI)
|
cmd := fmt.Sprintf("mod udmuser:imsi=%s,", body.IMSI)
|
||||||
// 修改的参数名称
|
cmd += s.udmSubService.ParseCommandParams(body)
|
||||||
if body.Msisdn != "" {
|
|
||||||
cmd += fmt.Sprintf(",msisdn=%s", body.Msisdn)
|
|
||||||
}
|
|
||||||
if body.Ambr != "" {
|
|
||||||
cmd += fmt.Sprintf(",ambr=%s", body.Ambr)
|
|
||||||
}
|
|
||||||
if body.Nssai != "" {
|
|
||||||
cmd += fmt.Sprintf(",nssai=%s", body.Nssai)
|
|
||||||
}
|
|
||||||
if body.Arfb != "" {
|
|
||||||
cmd += fmt.Sprintf(",arfb=%s", body.Arfb)
|
|
||||||
}
|
|
||||||
if body.Sar != "" {
|
|
||||||
cmd += fmt.Sprintf(",sar=%s", body.Sar)
|
|
||||||
}
|
|
||||||
if body.Rat != "" {
|
|
||||||
cmd += fmt.Sprintf(",rat=%s", body.Rat)
|
|
||||||
}
|
|
||||||
if body.Cn != "" {
|
|
||||||
cmd += fmt.Sprintf(",cn=%s", body.Cn)
|
|
||||||
}
|
|
||||||
if body.SmfSel != "" {
|
|
||||||
cmd += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
|
|
||||||
}
|
|
||||||
if body.SmData != "" {
|
|
||||||
cmd += fmt.Sprintf(",sm_data=%s", body.SmData)
|
|
||||||
}
|
|
||||||
if body.EpsDat != "" {
|
|
||||||
cmd += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
|
|
||||||
}
|
|
||||||
if body.EpsFlag != "" {
|
|
||||||
cmd += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
|
|
||||||
}
|
|
||||||
if body.EpsOdb != "" {
|
|
||||||
cmd += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
|
|
||||||
}
|
|
||||||
if body.HplmnOdb != "" {
|
|
||||||
cmd += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
|
|
||||||
}
|
|
||||||
if body.Epstpl != "" {
|
|
||||||
cmd += fmt.Sprintf(",epstpl=%s", body.Epstpl)
|
|
||||||
}
|
|
||||||
if body.Ard != "" {
|
|
||||||
cmd += fmt.Sprintf(",ard=%s", body.Ard)
|
|
||||||
}
|
|
||||||
if body.ContextId != "" {
|
|
||||||
cmd += fmt.Sprintf(",context_id=%s", body.ContextId)
|
|
||||||
}
|
|
||||||
if body.ApnContext != "" {
|
|
||||||
cmd += fmt.Sprintf(",apn_context=%s", body.ApnContext)
|
|
||||||
}
|
|
||||||
if body.StaticIp != "" {
|
|
||||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
|
||||||
}
|
|
||||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -356,8 +248,8 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
body.NeId = neId
|
||||||
go s.udmSubService.Insert(neId, body)
|
s.udmSubService.Insert(neId, body)
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -369,7 +261,7 @@ func (s *UDMSubController) Remove(c *gin.Context) {
|
|||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
neId := c.Param("neId")
|
neId := c.Param("neId")
|
||||||
imsi := c.Param("imsi")
|
imsi := c.Param("imsi")
|
||||||
if neId == "" || imsi == "" {
|
if neId == "" || len(imsi) < 15 {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -388,7 +280,7 @@ func (s *UDMSubController) Remove(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -407,8 +299,7 @@ func (s *UDMSubController) Remove(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmSubService.Delete(neId, imsi)
|
||||||
go s.udmSubService.Delete(neId, imsi)
|
|
||||||
}
|
}
|
||||||
resultData[imsi] = data
|
resultData[imsi] = data
|
||||||
}
|
}
|
||||||
@@ -424,7 +315,7 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
|||||||
neId := c.Param("neId")
|
neId := c.Param("neId")
|
||||||
imsi := c.Param("imsi")
|
imsi := c.Param("imsi")
|
||||||
num := c.Param("num")
|
num := c.Param("num")
|
||||||
if neId == "" || imsi == "" || num == "" {
|
if neId == "" || len(imsi) < 15 || num == "" {
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -435,7 +326,7 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 网元主机的Telnet客户端
|
||||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
@@ -453,8 +344,7 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
|||||||
|
|
||||||
// 命令ok时
|
// 命令ok时
|
||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
neId = ""
|
s.udmSubService.LoadData(neId, imsi, num, "-(Deleted)-")
|
||||||
go s.udmSubService.LoadData(neId, imsi, num)
|
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkData(data))
|
c.JSON(200, result.OkData(data))
|
||||||
}
|
}
|
||||||
@@ -464,53 +354,63 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
|||||||
// POST /export
|
// POST /export
|
||||||
func (s *UDMSubController) Export(c *gin.Context) {
|
func (s *UDMSubController) Export(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
var body struct {
|
// 查询结果,根据查询条件结果,单页最大值限制
|
||||||
NeId string `json:"neId" binding:"required"`
|
querys := ctx.BodyJSONMap(c)
|
||||||
Type string `json:"type" binding:"required"`
|
neId := querys["neId"].(string)
|
||||||
}
|
fileType := querys["type"].(string)
|
||||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
if neId == "" || fileType == "" {
|
||||||
if err != nil {
|
|
||||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !(fileType == "csv" || fileType == "txt") {
|
||||||
if !(body.Type == "csv" || body.Type == "txt") {
|
|
||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
neId := ""
|
querys["pageNum"] = 1
|
||||||
list := s.udmSubService.SelectList(model.UDMSub{NeId: neId})
|
querys["pageSize"] = 10000
|
||||||
// 文件名
|
total, rows := s.udmSubService.SelectPage(querys)
|
||||||
fileName := fmt.Sprintf("udm_sub_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
if total == 0 {
|
||||||
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
// 导出数据记录为空
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if body.Type == "csv" {
|
// rows := s.udmSubService.SelectList(model.UDMSubUser{NeId: neId})
|
||||||
|
if len(rows) <= 0 {
|
||||||
|
// 导出数据记录为空
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件名
|
||||||
|
fileName := fmt.Sprintf("udm_sub_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), fileType)
|
||||||
|
filePath := filepath.Join(file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||||
|
|
||||||
|
if fileType == "csv" {
|
||||||
// 转换数据
|
// 转换数据
|
||||||
data := [][]string{}
|
data := [][]string{}
|
||||||
data = append(data, []string{"imsi", "msisdn", "ambr", "nssai", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"})
|
data = append(data, []string{"IMSI", "MSISDN", "UeAmbrTpl", "NssaiTpl", "AreaForbiddenTpl", "ServiceAreaRestrictionTpl", "RatRestrictions", "CnTypeRestrictions", "SmfSel", "SmData", "EPSDat"})
|
||||||
for _, v := range list {
|
for _, v := range rows {
|
||||||
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
||||||
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
data = append(data, []string{v.IMSI, v.MSISDN, v.UeAmbrTpl, v.NssaiTpl, v.AreaForbiddenTpl, v.ServiceAreaRestrictionTpl, v.RatRestrictions, v.CnTypeRestrictions, v.SmfSel, v.SmData, epsDat})
|
||||||
}
|
}
|
||||||
// 输出到文件
|
// 输出到文件
|
||||||
err = file.WriterFileCSV(data, filePath)
|
if err := file.WriterFileCSV(data, filePath); err != nil {
|
||||||
if err != nil {
|
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if body.Type == "txt" {
|
if fileType == "txt" {
|
||||||
// 转换数据
|
// 转换数据
|
||||||
data := [][]string{}
|
data := [][]string{}
|
||||||
for _, v := range list {
|
for _, v := range rows {
|
||||||
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
||||||
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
data = append(data, []string{v.IMSI, v.MSISDN, v.UeAmbrTpl, v.NssaiTpl, v.AreaForbiddenTpl, v.ServiceAreaRestrictionTpl, v.RatRestrictions, v.CnTypeRestrictions, v.SmfSel, v.SmData, epsDat})
|
||||||
}
|
}
|
||||||
// 输出到文件
|
// 输出到文件
|
||||||
err = file.WriterFileTXT(data, ",", filePath)
|
if err := file.WriterFileTXT(data, ",", filePath); err != nil {
|
||||||
if err != nil {
|
|
||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -590,13 +490,11 @@ func (s *UDMSubController) Import(c *gin.Context) {
|
|||||||
if strings.Contains(data, "ok") {
|
if strings.Contains(data, "ok") {
|
||||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||||
data := file.ReadFileCSV(localFilePath)
|
data := file.ReadFileCSV(localFilePath)
|
||||||
neId := ""
|
go s.udmSubService.InsertData(neInfo.NeId, "csv", data)
|
||||||
go s.udmSubService.InsertData(neId, "csv", data)
|
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||||
data := file.ReadFileTXT(",", localFilePath)
|
data := file.ReadFileTXT(",", localFilePath)
|
||||||
neId := ""
|
go s.udmSubService.InsertData(neInfo.NeId, "txt", data)
|
||||||
go s.udmSubService.InsertData(neId, "txt", data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.JSON(200, result.OkMsg(data))
|
c.JSON(200, result.OkMsg(data))
|
||||||
|
|||||||
@@ -10,19 +10,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 实例化控制层 UPFController 结构体
|
// 实例化控制层 UPFController 结构体
|
||||||
var NewUPFController = &UPFController{
|
var NewUPF = &UPFController{
|
||||||
neInfoService: neService.NewNeInfoImpl,
|
neInfoService: neService.NewNeInfo,
|
||||||
perfKPIService: neDataService.NewPerfKPIImpl,
|
perfKPIService: neDataService.NewPerfKPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元UPF
|
// 网元UPF
|
||||||
//
|
//
|
||||||
// PATH /upf
|
// PATH /upf
|
||||||
type UPFController struct {
|
type UPFController struct {
|
||||||
// 网元信息服务
|
neInfoService *neService.NeInfo // 网元信息服务
|
||||||
neInfoService neService.INeInfo
|
perfKPIService *neDataService.PerfKPI // 统计信息服务
|
||||||
// 统计信息服务
|
|
||||||
perfKPIService neDataService.IPerfKPI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 总流量数 N3上行 N6下行
|
// 总流量数 N3上行 N6下行
|
||||||
@@ -32,7 +30,6 @@ type UPFController struct {
|
|||||||
func (s *UPFController) TotalFlow(c *gin.Context) {
|
func (s *UPFController) TotalFlow(c *gin.Context) {
|
||||||
language := ctx.AcceptLanguage(c)
|
language := ctx.AcceptLanguage(c)
|
||||||
var querys struct {
|
var querys struct {
|
||||||
NeType string `json:"neType" form:"neType" binding:"required"`
|
|
||||||
NeID string `form:"neId" binding:"required"`
|
NeID string `form:"neId" binding:"required"`
|
||||||
Day int `form:"day" binding:"required"`
|
Day int `form:"day" binding:"required"`
|
||||||
}
|
}
|
||||||
@@ -42,7 +39,7 @@ func (s *UPFController) TotalFlow(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询网元获取IP
|
// 查询网元获取IP
|
||||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UPF", querys.NeID)
|
||||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import "time"
|
|||||||
|
|
||||||
// Alarm 告警数据对象 alarm
|
// Alarm 告警数据对象 alarm
|
||||||
type Alarm struct {
|
type Alarm struct {
|
||||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
ID string `json:"id" gorm:"id"`
|
||||||
AlarmSeq string `json:"alarmSeq" gorm:"alarm_seq"`
|
AlarmSeq string `json:"alarmSeq" gorm:"alarm_seq"`
|
||||||
AlarmId string `json:"alarmId" gorm:"alarm_id"`
|
AlarmId string `json:"alarmId" gorm:"alarm_id"`
|
||||||
AlarmTitle string `json:"alarmTitle" gorm:"alarm_title"`
|
AlarmTitle string `json:"alarmTitle" gorm:"alarm_title"`
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type CDREventIMSQuery struct {
|
|||||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型IMS
|
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型IMS
|
||||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||||
RmUID string `json:"rmUID" form:"rmUID"`
|
RmUID string `json:"rmUID" form:"rmUID"`
|
||||||
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
|
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC
|
||||||
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
|
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
|
||||||
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
|
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
|
||||||
StartTime string `json:"startTime" form:"startTime"`
|
StartTime string `json:"startTime" form:"startTime"`
|
||||||
|
|||||||
30
src/modules/network_data/model/cdr_event_smsc.go
Normal file
30
src/modules/network_data/model/cdr_event_smsc.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// CDREventSMSC CDR会话对象SMSC cdr_event_smsc
|
||||||
|
type CDREventSMSC 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"`
|
||||||
|
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
|
||||||
|
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDREventSMSCQuery CDR会话对象SMSC查询参数结构体
|
||||||
|
type CDREventSMSCQuery struct {
|
||||||
|
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型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"` // 被叫号码
|
||||||
|
StartTime string `json:"startTime" form:"startTime"`
|
||||||
|
EndTime string `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,17 +1,18 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
// UDMAuth UDM鉴权用户对象 u_auth_user
|
// UDMAuthUser UDM鉴权用户 u_auth_user
|
||||||
type UDMAuth struct {
|
type UDMAuthUser struct {
|
||||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 默认ID
|
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 默认ID
|
||||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
|
||||||
Amf string `json:"amf" gorm:"column:amf"` // ANF
|
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
|
||||||
Status string `json:"status" gorm:"column:status"` // 状态 默认给1
|
Amf string `json:"amf" gorm:"column:amf"` // AMF
|
||||||
|
Status string `json:"status" gorm:"column:status"` // 状态
|
||||||
Ki string `json:"ki" gorm:"column:ki"` // ki
|
Ki string `json:"ki" gorm:"column:ki"` // ki
|
||||||
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // AlgoIndex
|
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // algoIndex
|
||||||
Opc string `json:"opc" gorm:"column:opc"` // opc
|
Opc string `json:"opc" gorm:"column:opc"` // OPC
|
||||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UDMAuth) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*UDMAuthUser) TableName() string {
|
||||||
return "u_auth_user"
|
return "u_auth_user"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,48 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
// UDMSub UDM签约用户对象 u_sub_user
|
// UDMSubUser UDM签约用户 u_sub_user
|
||||||
type UDMSub struct {
|
type UDMSubUser struct {
|
||||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 主键
|
||||||
Msisdn string `json:"msisdn" gorm:"column:msisdn"` // 相当手机号
|
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
|
||||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
|
||||||
Ambr string `json:"ambr" gorm:"column:ambr"`
|
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识
|
||||||
Nssai string `json:"nssai" gorm:"column:nssai"`
|
|
||||||
Rat string `json:"rat" gorm:"column:rat"`
|
|
||||||
Arfb string `json:"arfb" gorm:"column:arfb"`
|
|
||||||
Sar string `json:"sar" gorm:"column:sar"`
|
|
||||||
Cn string `json:"cn" gorm:"column:cn"`
|
|
||||||
SmData string `json:"smData" gorm:"column:sm_data"`
|
|
||||||
SmfSel string `json:"smfSel" gorm:"column:smf_sel"`
|
|
||||||
EpsDat string `json:"epsDat" gorm:"column:eps_dat"`
|
|
||||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
|
||||||
|
|
||||||
EpsFlag string `json:"epsFlag" gorm:"column:eps_flag"`
|
AmDat string `json:"amDat" gorm:"column:am_dat"` // AmData
|
||||||
EpsOdb string `json:"epsOdb" gorm:"column:eps_odb"`
|
UeAmbrTpl string `json:"ambr" gorm:"column:ambr"` // AmData SubUeAMBRTemp
|
||||||
HplmnOdb string `json:"hplmnOdb" gorm:"column:hplmn_odb"`
|
NssaiTpl string `json:"nssai" gorm:"column:nssai"` // AmData SubSNSSAITemp
|
||||||
Ard string `json:"ard" gorm:"column:ard"`
|
RatRestrictions string `json:"rat" gorm:"column:rat"` // AmData RAT 0x00:VIRTUAL 0x01:WLAN 0x02:EUTRA 0x03:NR
|
||||||
Epstpl string `json:"epstpl" gorm:"column:epstpl"`
|
AreaForbiddenTpl string `json:"arfb" gorm:"column:arfb"` // AmData AreaForbidden
|
||||||
ContextId string `json:"contextId" gorm:"column:context_id"`
|
ServiceAreaRestrictionTpl string `json:"sar" gorm:"column:sar"` // AmData serviceAreaRestrictTemp
|
||||||
ApnContext string `json:"apnContext" gorm:"column:apn_context"`
|
CnTypeRestrictions string `json:"cnType" gorm:"column:cn_type"` // AmData CNType 0x00:EPC和5GC 0x01:5GC 0x02:EPC 0x03:EPC+5GC
|
||||||
StaticIp string `json:"staticIp" gorm:"column:static_ip"`
|
RfspIndex string `json:"rfspIndex" gorm:"column:rfsp_index"` // AmData RfspIndex
|
||||||
|
SubsRegTime string `json:"regTimer" gorm:"column:reg_timer"` // AmData RegTimer
|
||||||
|
UeUsageType string `json:"ueUsageType" gorm:"column:ue_usage_type"` // AmData UEUsageType
|
||||||
|
ActiveTime string `json:"activeTime" gorm:"column:active_time"` // AmData ActiveTime
|
||||||
|
MicoAllowed string `json:"mico" gorm:"column:mico"` // AmData MICO
|
||||||
|
OdbPs string `json:"odbPs" gorm:"column:odb_ps"` // AmData ODB_PS 0-all,1-hplmn,2-vplmn
|
||||||
|
GroupId string `json:"groupId" gorm:"column:group_id"` // AmData GroupId
|
||||||
|
|
||||||
|
EpsDat string `json:"epsDat" gorm:"column:eps_dat"` // EpsDat
|
||||||
|
EpsFlag string `json:"epsFlag" gorm:"column:eps_flag"` // EpsDat epsFlag
|
||||||
|
EpsOdb string `json:"epsOdb" gorm:"column:eps_odb"` // EpsDat epsOdb
|
||||||
|
HplmnOdb string `json:"hplmnOdb" gorm:"column:hplmn_odb"` // EpsDat hplmnOdb
|
||||||
|
Ard string `json:"ard" gorm:"column:ard"` // EpsDat Ard
|
||||||
|
Epstpl string `json:"epstpl" gorm:"column:epstpl"` // EpsDat Epstpl
|
||||||
|
ContextId string `json:"contextId" gorm:"column:context_id"` // EpsDat ContextId
|
||||||
|
ApnNum string `json:"apnNum" gorm:"column:apn_mum"` // EpsDat apnNum
|
||||||
|
ApnContext string `json:"apnContext" gorm:"column:apn_context"` // EpsDat apnContext
|
||||||
|
StaticIp string `json:"staticIp" gorm:"column:static_ip"` // EpsDat staticIp 指给4G UE分配的静态IP,没有可不带此字段名
|
||||||
|
|
||||||
|
SmData string `json:"smData" gorm:"column:sm_data"` // smData
|
||||||
|
SmfSel string `json:"smfSel" gorm:"column:smf_sel"` // smfSel
|
||||||
|
Cag string `json:"cag" gorm:"column:cag"` // CAG
|
||||||
|
|
||||||
// ====== 非数据库字段属性 ======
|
// ====== 非数据库字段属性 ======
|
||||||
|
|
||||||
|
Remark string `json:"remark,omitempty" gorm:"-"` // 备注
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UDMSub) TableName() string {
|
// TableName 表名称
|
||||||
|
func (*UDMSubUser) TableName() string {
|
||||||
return "u_sub_user"
|
return "u_sub_user"
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/modules/network_data/model/udm_user_info.go
Normal file
15
src/modules/network_data/model/udm_user_info.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// UDMUserInfo UDM用户IMSI扩展信息 u_user_info
|
||||||
|
type UDMUserInfo struct {
|
||||||
|
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 默认ID
|
||||||
|
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡/USIM卡ID
|
||||||
|
MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户电话号码
|
||||||
|
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
||||||
|
Remark string `json:"remark" gorm:"remark"` // 备注
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 表名称
|
||||||
|
func (*UDMUserInfo) TableName() string {
|
||||||
|
return "u_user_info"
|
||||||
|
}
|
||||||
@@ -21,11 +21,11 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
kpiGroup.GET("/title",
|
kpiGroup.GET("/title",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewPerfKPIController.Title,
|
controller.NewPerfKPI.Title,
|
||||||
)
|
)
|
||||||
kpiGroup.GET("/data",
|
kpiGroup.GET("/data",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewPerfKPIController.GoldKPI,
|
controller.NewPerfKPI.GoldKPI,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,11 +34,11 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
alarmGroup.GET("/list",
|
alarmGroup.GET("/list",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewAlarmController.List,
|
controller.NewAlarm.List,
|
||||||
)
|
)
|
||||||
alarmGroup.DELETE("/:alarmIds",
|
alarmGroup.DELETE("/:alarmIds",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewAlarmController.Remove,
|
controller.NewAlarm.Remove,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,17 +47,36 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
imsGroup.GET("/cdr/list",
|
imsGroup.GET("/cdr/list",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewIMSController.CDRList,
|
controller.NewIMS.CDRList,
|
||||||
)
|
)
|
||||||
imsGroup.DELETE("/cdr/:cdrIds",
|
imsGroup.DELETE("/cdr/:cdrIds",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
controller.NewIMSController.CDRRemove,
|
controller.NewIMS.CDRRemove,
|
||||||
)
|
)
|
||||||
imsGroup.POST("/cdr/export",
|
imsGroup.POST("/cdr/export",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||||
controller.NewIMSController.CDRExport,
|
controller.NewIMS.CDRExport,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网元SMSC
|
||||||
|
smscGroup := neDataGroup.Group("/smsc")
|
||||||
|
{
|
||||||
|
smscGroup.GET("/cdr/list",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
controller.NewSMSC.CDRList,
|
||||||
|
)
|
||||||
|
smscGroup.DELETE("/cdr/:cdrIds",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
|
controller.NewSMSC.CDRRemove,
|
||||||
|
)
|
||||||
|
smscGroup.POST("/cdr/export",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smscCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||||
|
controller.NewSMSC.CDRExport,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,17 +85,21 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
smfGroup.GET("/cdr/list",
|
smfGroup.GET("/cdr/list",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewSMFController.CDRList,
|
controller.NewSMF.CDRList,
|
||||||
)
|
)
|
||||||
smfGroup.DELETE("/cdr/:cdrIds",
|
smfGroup.DELETE("/cdr/:cdrIds",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
controller.NewSMFController.CDRRemove,
|
controller.NewSMF.CDRRemove,
|
||||||
)
|
)
|
||||||
smfGroup.POST("/cdr/export",
|
smfGroup.POST("/cdr/export",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||||
controller.NewSMFController.CDRExport,
|
controller.NewSMF.CDRExport,
|
||||||
|
)
|
||||||
|
smfGroup.GET("/subscribers",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
controller.NewSMF.SubUserList,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,17 +108,17 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
amfGroup.GET("/ue/list",
|
amfGroup.GET("/ue/list",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewAMFController.UEList,
|
controller.NewAMF.UEList,
|
||||||
)
|
)
|
||||||
amfGroup.DELETE("/ue/:ueIds",
|
amfGroup.DELETE("/ue/:ueIds",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
controller.NewAMFController.UERemove,
|
controller.NewAMF.UERemove,
|
||||||
)
|
)
|
||||||
amfGroup.POST("/ue/export",
|
amfGroup.POST("/ue/export",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||||
controller.NewAMFController.UEExport,
|
controller.NewAMF.UEExport,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +127,7 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
upfGroup.GET("/totalFlow",
|
upfGroup.GET("/totalFlow",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewUPFController.TotalFlow,
|
controller.NewUPF.TotalFlow,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,17 +244,17 @@ func Setup(router *gin.Engine) {
|
|||||||
{
|
{
|
||||||
mmeGroup.GET("/ue/list",
|
mmeGroup.GET("/ue/list",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
controller.NewMMEController.UEList,
|
controller.NewMME.UEList,
|
||||||
)
|
)
|
||||||
mmeGroup.DELETE("/ue/:ueIds",
|
mmeGroup.DELETE("/ue/:ueIds",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
controller.NewMMEController.UERemove,
|
controller.NewMME.UERemove,
|
||||||
)
|
)
|
||||||
mmeGroup.POST("/ue/export",
|
mmeGroup.POST("/ue/export",
|
||||||
middleware.PreAuthorize(nil),
|
middleware.PreAuthorize(nil),
|
||||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||||
controller.NewMMEController.UEExport,
|
controller.NewMME.UEExport,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,194 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import "be.ems/src/modules/network_data/model"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/datasource"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/utils/repo"
|
||||||
|
"be.ems/src/modules/network_data/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 Alarm 结构体
|
||||||
|
var NewAlarm = &Alarm{
|
||||||
|
selectSql: `select
|
||||||
|
id, alarm_seq, alarm_id, alarm_title, ne_type, ne_id, alarm_code, event_time,
|
||||||
|
alarm_type, orig_severity, perceived_severity, pv_flag, ne_name, object_uid, object_name,
|
||||||
|
object_type, location_info, province, alarm_status, specific_problem, specific_problem_id,
|
||||||
|
add_info, counter, latest_event_time, ack_state, ack_time, ack_user, clear_type,
|
||||||
|
clear_time, clear_user, timestamp
|
||||||
|
from alarm`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"id": "ID",
|
||||||
|
"alarm_seq": "AlarmSeq",
|
||||||
|
"alarm_id": "AlarmId",
|
||||||
|
"alarm_title": "AlarmTitle",
|
||||||
|
"ne_type": "NeType",
|
||||||
|
"ne_id": "NeId",
|
||||||
|
"alarm_code": "AlarmCode",
|
||||||
|
"event_time": "EventTime",
|
||||||
|
"alarm_type": "AlarmType",
|
||||||
|
"orig_severity": "OrigSeverity",
|
||||||
|
"perceived_severity": "PerceivedSeverity",
|
||||||
|
"pv_flag": "PvFlag",
|
||||||
|
"ne_name": "NeName",
|
||||||
|
"object_uid": "ObjectUid",
|
||||||
|
"object_name": "ObjectName",
|
||||||
|
"object_type": "ObjectType",
|
||||||
|
"location_info": "LocationInfo",
|
||||||
|
"province": "Province",
|
||||||
|
"alarm_status": "AlarmStatus",
|
||||||
|
"specific_problem": "SpecificProblem",
|
||||||
|
"specific_problem_id": "SpecificProblemId",
|
||||||
|
"add_info": "AddInfo",
|
||||||
|
"counter": "Counter",
|
||||||
|
"latest_event_time": "LatestEventTime",
|
||||||
|
"ack_state": "AckState",
|
||||||
|
"ack_time": "AckTime",
|
||||||
|
"ack_user": "AckUser",
|
||||||
|
"clear_type": "ClearType",
|
||||||
|
"clear_time": "ClearTime",
|
||||||
|
"clear_user": "ClearUser",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alarm 告警 数据层处理
|
||||||
|
type Alarm struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *Alarm) convertResultRows(rows []map[string]any) []model.Alarm {
|
||||||
|
arr := make([]model.Alarm, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
item := model.Alarm{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
repo.SetFieldValue(&item, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
// 告警 数据层接口
|
|
||||||
type IAlarm interface {
|
|
||||||
// SelectPage 根据条件分页查询
|
// SelectPage 根据条件分页查询
|
||||||
SelectPage(querys model.AlarmQuery) map[string]any
|
func (r *Alarm) SelectPage(querys model.AlarmQuery) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if querys.NeType != "" {
|
||||||
|
conditions = append(conditions, "ne_type = ?")
|
||||||
|
params = append(params, querys.NeType)
|
||||||
|
}
|
||||||
|
if querys.RmUID != "" {
|
||||||
|
conditions = append(conditions, "object_uid = ?")
|
||||||
|
params = append(params, querys.RmUID)
|
||||||
|
}
|
||||||
|
if querys.StartTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp >= ?")
|
||||||
|
params = append(params, querys.StartTime)
|
||||||
|
}
|
||||||
|
if querys.EndTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp <= ?")
|
||||||
|
params = append(params, querys.EndTime)
|
||||||
|
}
|
||||||
|
if querys.OrigSeverity != "" {
|
||||||
|
eventTypes := strings.Split(querys.OrigSeverity, ",")
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
|
||||||
|
conditions = append(conditions, fmt.Sprintf("orig_severity in (%s)", placeholder))
|
||||||
|
for _, eventType := range eventTypes {
|
||||||
|
params = append(params, eventType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]any{
|
||||||
|
"total": 0,
|
||||||
|
"rows": []model.Alarm{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from alarm"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("total err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
result["total"] = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
orderSql := ""
|
||||||
|
if querys.SortField != "" {
|
||||||
|
sortSql := querys.SortField
|
||||||
|
if querys.SortOrder != "" {
|
||||||
|
if querys.SortOrder == "desc" {
|
||||||
|
sortSql += " desc "
|
||||||
|
} else {
|
||||||
|
sortSql += " asc "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
result["rows"] = r.convertResultRows(results)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SelectByIds 通过ID查询
|
// SelectByIds 通过ID查询
|
||||||
SelectByIds(ids []string) []model.Alarm
|
func (r *Alarm) SelectByIds(ids []string) []model.Alarm {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(ids))
|
||||||
|
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(ids)
|
||||||
|
results, err := datasource.RawDB("", querySql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.Alarm{}
|
||||||
|
}
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
DeleteByIds(ids []string) int64
|
func (r *Alarm) DeleteByIds(ids []string) int64 {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(ids))
|
||||||
|
sql := "delete from alarm where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(ids)
|
||||||
|
results, err := datasource.ExecDB("", sql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("delete err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return results
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/src/framework/datasource"
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
"be.ems/src/framework/utils/repo"
|
|
||||||
"be.ems/src/modules/network_data/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 AlarmImpl 结构体
|
|
||||||
var NewAlarmImpl = &AlarmImpl{
|
|
||||||
selectSql: `select
|
|
||||||
id, alarm_seq, alarm_id, alarm_title, ne_type, ne_id, alarm_code, event_time,
|
|
||||||
alarm_type, orig_severity, perceived_severity, pv_flag, ne_name, object_uid, object_name,
|
|
||||||
object_type, location_info, province, alarm_status, specific_problem, specific_problem_id,
|
|
||||||
add_info, counter, latest_event_time, ack_state, ack_time, ack_user, clear_type,
|
|
||||||
clear_time, clear_user, timestamp
|
|
||||||
from alarm`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"id": "ID",
|
|
||||||
"alarm_seq": "AlarmSeq",
|
|
||||||
"alarm_id": "AlarmId",
|
|
||||||
"alarm_title": "AlarmTitle",
|
|
||||||
"ne_type": "NeType",
|
|
||||||
"ne_id": "NeId",
|
|
||||||
"alarm_code": "AlarmCode",
|
|
||||||
"event_time": "EventTime",
|
|
||||||
"alarm_type": "AlarmType",
|
|
||||||
"orig_severity": "OrigSeverity",
|
|
||||||
"perceived_severity": "PerceivedSeverity",
|
|
||||||
"pv_flag": "PvFlag",
|
|
||||||
"ne_name": "NeName",
|
|
||||||
"object_uid": "ObjectUid",
|
|
||||||
"object_name": "ObjectName",
|
|
||||||
"object_type": "ObjectType",
|
|
||||||
"location_info": "LocationInfo",
|
|
||||||
"province": "Province",
|
|
||||||
"alarm_status": "AlarmStatus",
|
|
||||||
"specific_problem": "SpecificProblem",
|
|
||||||
"specific_problem_id": "SpecificProblemId",
|
|
||||||
"add_info": "AddInfo",
|
|
||||||
"counter": "Counter",
|
|
||||||
"latest_event_time": "LatestEventTime",
|
|
||||||
"ack_state": "AckState",
|
|
||||||
"ack_time": "AckTime",
|
|
||||||
"ack_user": "AckUser",
|
|
||||||
"clear_type": "ClearType",
|
|
||||||
"clear_time": "ClearTime",
|
|
||||||
"clear_user": "ClearUser",
|
|
||||||
"timestamp": "Timestamp",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlarmImpl 告警 数据层处理
|
|
||||||
type AlarmImpl struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *AlarmImpl) convertResultRows(rows []map[string]any) []model.Alarm {
|
|
||||||
arr := make([]model.Alarm, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
item := model.Alarm{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
repo.SetFieldValue(&item, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, item)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectPage 根据条件分页查询
|
|
||||||
func (r *AlarmImpl) SelectPage(querys model.AlarmQuery) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if querys.NeType != "" {
|
|
||||||
conditions = append(conditions, "ne_type = ?")
|
|
||||||
params = append(params, querys.NeType)
|
|
||||||
}
|
|
||||||
if querys.RmUID != "" {
|
|
||||||
conditions = append(conditions, "object_uid = ?")
|
|
||||||
params = append(params, querys.RmUID)
|
|
||||||
}
|
|
||||||
if querys.StartTime != "" {
|
|
||||||
conditions = append(conditions, "timestamp >= ?")
|
|
||||||
params = append(params, querys.StartTime)
|
|
||||||
}
|
|
||||||
if querys.EndTime != "" {
|
|
||||||
conditions = append(conditions, "timestamp <= ?")
|
|
||||||
params = append(params, querys.EndTime)
|
|
||||||
}
|
|
||||||
if querys.OrigSeverity != "" {
|
|
||||||
eventTypes := strings.Split(querys.OrigSeverity, ",")
|
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
|
|
||||||
conditions = append(conditions, fmt.Sprintf("orig_severity in (%s)", placeholder))
|
|
||||||
for _, eventType := range eventTypes {
|
|
||||||
params = append(params, eventType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := map[string]any{
|
|
||||||
"total": 0,
|
|
||||||
"rows": []model.Alarm{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from alarm"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("total err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result["total"] = total
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 排序
|
|
||||||
orderSql := ""
|
|
||||||
if querys.SortField != "" {
|
|
||||||
sortSql := querys.SortField
|
|
||||||
if querys.SortOrder != "" {
|
|
||||||
if querys.SortOrder == "desc" {
|
|
||||||
sortSql += " desc "
|
|
||||||
} else {
|
|
||||||
sortSql += " asc "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
result["rows"] = r.convertResultRows(results)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectByIds 通过ID查询
|
|
||||||
func (r *AlarmImpl) SelectByIds(ids []string) []model.Alarm {
|
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(ids))
|
|
||||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
|
||||||
parameters := repo.ConvertIdsSlice(ids)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("query err => %v", err)
|
|
||||||
return []model.Alarm{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteByIds 批量删除信息
|
|
||||||
func (r *AlarmImpl) DeleteByIds(ids []string) int64 {
|
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(ids))
|
|
||||||
sql := "delete from alarm where id in (" + placeholder + ")"
|
|
||||||
parameters := repo.ConvertIdsSlice(ids)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,189 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import "be.ems/src/modules/network_data/model"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/datasource"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/utils/repo"
|
||||||
|
"be.ems/src/modules/network_data/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 CDREventIMS 结构体
|
||||||
|
var NewCDREventIMS = &CDREventIMS{
|
||||||
|
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_ims`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"id": "ID",
|
||||||
|
"ne_type": "NeType",
|
||||||
|
"ne_name": "NeName",
|
||||||
|
"rm_uid": "RmUID",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
|
"cdr_json": "CDRJSONStr",
|
||||||
|
"created_at": "CreatedAt",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDREventIMS CDR会话事件IMS 数据层处理
|
||||||
|
type CDREventIMS struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *CDREventIMS) convertResultRows(rows []map[string]any) []model.CDREventIMS {
|
||||||
|
arr := make([]model.CDREventIMS, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
item := model.CDREventIMS{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
repo.SetFieldValue(&item, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
// CDR会话事件IMS 数据层接口
|
|
||||||
type ICDREventIMS interface {
|
|
||||||
// SelectPage 根据条件分页查询
|
// SelectPage 根据条件分页查询
|
||||||
SelectPage(querys model.CDREventIMSQuery) map[string]any
|
func (r *CDREventIMS) SelectPage(querys model.CDREventIMSQuery) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if querys.NeType != "" {
|
||||||
|
conditions = append(conditions, "ne_type = ?")
|
||||||
|
params = append(params, querys.NeType)
|
||||||
|
}
|
||||||
|
if querys.RmUID != "" {
|
||||||
|
conditions = append(conditions, "rm_uid = ?")
|
||||||
|
params = append(params, querys.RmUID)
|
||||||
|
}
|
||||||
|
if querys.StartTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp >= ?")
|
||||||
|
if len(querys.StartTime) == 13 {
|
||||||
|
querys.StartTime = querys.StartTime[:10]
|
||||||
|
}
|
||||||
|
params = append(params, querys.StartTime)
|
||||||
|
}
|
||||||
|
if querys.EndTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp <= ?")
|
||||||
|
if len(querys.EndTime) == 13 {
|
||||||
|
querys.EndTime = querys.EndTime[:10]
|
||||||
|
}
|
||||||
|
params = append(params, querys.EndTime)
|
||||||
|
}
|
||||||
|
if querys.CallerParty != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.callerParty') = ?")
|
||||||
|
params = append(params, querys.CallerParty)
|
||||||
|
}
|
||||||
|
if querys.CalledParty != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.calledParty') = ?")
|
||||||
|
params = append(params, querys.CalledParty)
|
||||||
|
}
|
||||||
|
// MySQL8支持的
|
||||||
|
// if querys.RecordType != "" {
|
||||||
|
// recordTypes := strings.Split(querys.RecordType, ",")
|
||||||
|
// placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||||
|
// conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
|
||||||
|
// for _, recordType := range recordTypes {
|
||||||
|
// params = append(params, recordType)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Mariadb不支持json in查询改or
|
||||||
|
if querys.RecordType != "" {
|
||||||
|
recordTypes := strings.Split(querys.RecordType, ",")
|
||||||
|
var queryStrArr []string
|
||||||
|
for _, recordType := range recordTypes {
|
||||||
|
queryStrArr = append(queryStrArr, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
|
||||||
|
params = append(params, recordType)
|
||||||
|
}
|
||||||
|
conditions = append(conditions, fmt.Sprintf("( %s )", strings.Join(queryStrArr, " OR ")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]any{
|
||||||
|
"total": 0,
|
||||||
|
"rows": []model.CDREventIMS{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from cdr_event_ims"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("total err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
result["total"] = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
orderSql := ""
|
||||||
|
if querys.SortField != "" {
|
||||||
|
sortSql := querys.SortField
|
||||||
|
if querys.SortOrder != "" {
|
||||||
|
if querys.SortOrder == "desc" {
|
||||||
|
sortSql += " desc "
|
||||||
|
} else {
|
||||||
|
sortSql += " asc "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
result["rows"] = r.convertResultRows(results)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SelectByIds 通过ID查询
|
// SelectByIds 通过ID查询
|
||||||
SelectByIds(cdrIds []string) []model.CDREventIMS
|
func (r *CDREventIMS) SelectByIds(cdrIds []string) []model.CDREventIMS {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.RawDB("", querySql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.CDREventIMS{}
|
||||||
|
}
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
DeleteByIds(cdrIds []string) int64
|
func (r *CDREventIMS) DeleteByIds(cdrIds []string) int64 {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
sql := "delete from cdr_event_ims where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.ExecDB("", sql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("delete err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return results
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,170 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import "be.ems/src/modules/network_data/model"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/datasource"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/utils/repo"
|
||||||
|
"be.ems/src/modules/network_data/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 CDREventSMF 结构体
|
||||||
|
var NewCDREventSMF = &CDREventSMF{
|
||||||
|
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_smf`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"id": "ID",
|
||||||
|
"ne_type": "NeType",
|
||||||
|
"ne_name": "NeName",
|
||||||
|
"rm_uid": "RmUID",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
|
"cdr_json": "CDRJSONStr",
|
||||||
|
"created_at": "CreatedAt",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDREventSMF CDR会话事件 数据层处理
|
||||||
|
type CDREventSMF struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *CDREventSMF) convertResultRows(rows []map[string]any) []model.CDREventSMF {
|
||||||
|
arr := make([]model.CDREventSMF, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
item := model.CDREventSMF{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
repo.SetFieldValue(&item, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
// CDR会话事件SMF 数据层接口
|
|
||||||
type ICDREventSMF interface {
|
|
||||||
// SelectPage 根据条件分页查询
|
// SelectPage 根据条件分页查询
|
||||||
SelectPage(querys model.CDREventSMFQuery) map[string]any
|
func (r *CDREventSMF) SelectPage(querys model.CDREventSMFQuery) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if querys.NeType != "" {
|
||||||
|
conditions = append(conditions, "ne_type = ?")
|
||||||
|
params = append(params, querys.NeType)
|
||||||
|
}
|
||||||
|
if querys.RmUID != "" {
|
||||||
|
conditions = append(conditions, "rm_uid = ?")
|
||||||
|
params = append(params, querys.RmUID)
|
||||||
|
}
|
||||||
|
if querys.StartTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp >= ?")
|
||||||
|
if len(querys.StartTime) == 13 {
|
||||||
|
querys.StartTime = querys.StartTime[:10]
|
||||||
|
}
|
||||||
|
params = append(params, querys.StartTime)
|
||||||
|
}
|
||||||
|
if querys.EndTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp <= ?")
|
||||||
|
if len(querys.EndTime) == 13 {
|
||||||
|
querys.EndTime = querys.EndTime[:10]
|
||||||
|
}
|
||||||
|
params = append(params, querys.EndTime)
|
||||||
|
}
|
||||||
|
if querys.RecordType != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
|
||||||
|
params = append(params, querys.RecordType)
|
||||||
|
}
|
||||||
|
if querys.SubscriberID != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?")
|
||||||
|
params = append(params, querys.SubscriberID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]any{
|
||||||
|
"total": 0,
|
||||||
|
"rows": []model.CDREventSMF{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from cdr_event_smf"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("total err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
result["total"] = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
orderSql := ""
|
||||||
|
if querys.SortField != "" {
|
||||||
|
sortSql := querys.SortField
|
||||||
|
if querys.SortOrder != "" {
|
||||||
|
if querys.SortOrder == "desc" {
|
||||||
|
sortSql += " desc "
|
||||||
|
} else {
|
||||||
|
sortSql += " asc "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
result["rows"] = r.convertResultRows(results)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SelectByIds 通过ID查询
|
// SelectByIds 通过ID查询
|
||||||
SelectByIds(cdrIds []string) []model.CDREventSMF
|
func (r *CDREventSMF) SelectByIds(cdrIds []string) []model.CDREventSMF {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.RawDB("", querySql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.CDREventSMF{}
|
||||||
|
}
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
DeleteByIds(cdrIds []string) int64
|
func (r *CDREventSMF) DeleteByIds(cdrIds []string) int64 {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
sql := "delete from cdr_event_smf where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.ExecDB("", sql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("delete err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return results
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user