Files
windows_lock_go/app/admin/service/mm_machine.go
2025-08-28 14:10:05 +08:00

752 lines
20 KiB
Go

package service
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
cDto "go-admin/common/dto"
"go-admin/common/enums"
"go-admin/common/helper"
)
type MmMachine struct {
service.Service
}
// GetPage 获取MmMachine列表
func (e *MmMachine) GetPage(c *dto.MmMachineGetPageReq, p *actions.DataPermission, list *[]models.MmMachine, count *int64) error {
var err error
var data models.MmMachine
var role models.SysRole
query := e.Orm.Model(&data)
e.Orm.Model(role).Where("role_id =?", p.RoleId).Find(&role)
if role.RoleKey != "admin" {
groups := ""
e.Orm.Model(models.MmUserGroup{}).Where("user_id = ?", p.UserId).Pluck("group_ids", &groups)
ids := strings.Split(groups, ",")
groupIds := make([]string, 0)
for _, item := range ids {
if item != "" {
groupIds = append(groupIds, item)
}
}
if len(groupIds) > 0 {
query.Where("group_id in ?", groupIds)
} else {
query.Where("1=0")
}
}
query.
Order(" LENGTH(machine_id) asc, machine_id asc").
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p),
)
if c.GroupId > 0 {
query = query.Where("group_id =?", c.GroupId)
} else if c.GroupId == -1 {
query = query.Where("group_id = 0")
}
switch c.ShowBind {
case 1:
query = query.Where("bios_id <> ''")
case 2:
query = query.Where("bios_id = '' or bios_id is null")
}
err = query.
Find(list).Limit(-1).Offset(-1).
Count(count).Error
if err != nil {
e.Log.Errorf("MmMachineService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取MmMachine对象
func (e *MmMachine) Get(d *dto.MmMachineGetReq, p *actions.DataPermission, model *models.MmMachine) error {
var data models.MmMachine
err := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).
First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetMmMachine error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建MmMachine对象
func (e *MmMachine) Insert(c *dto.MmMachineInsertReq) error {
var err error
var data models.MmMachine
result := getDistictApp(c.Content)
c.Content = strings.Join(result, "\n")
groupItems := getDistictApp(c.GroupItems)
c.GroupItems = strings.Join(groupItems, "\n")
c.Generate(&data)
err = e.Orm.Transaction(func(tx *gorm.DB) error {
var count int64
if err := tx.Model(data).Where("machine_id =?", c.MachineId).Count(&count).Error; err != nil {
return err
}
if count > 0 {
return errors.New("设备id已存在")
}
if err = tx.Create(&data).Error; err != nil {
return err
}
return nil
})
if err != nil {
e.Log.Errorf("MmMachineService Insert error:%s \r\n", err)
return err
}
//保存更新缓存
if data.MachineId != "" {
content := c.Content
groupItems := c.GroupItems
key := fmt.Sprintf(enums.MachineContentKey, data.MachineId)
key2 := fmt.Sprintf(enums.MachineGroupKey, data.MachineId)
var templates []models.MmWhiteTemplate
e.Orm.Model(models.MmWhiteTemplate{}).Find(&templates)
for _, item := range templates {
if item.Type == 0 {
content = item.Content
} else if item.Type == 1 {
groupItems = item.Content
}
}
helper.DefaultRedis.SetStringExpire(key, content, time.Hour*24*3)
helper.DefaultRedis.SetStringExpire(key2, groupItems, time.Hour*24*3)
}
return nil
}
// Update 修改MmMachine对象
func (e *MmMachine) Update(c *dto.MmMachineUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.MmMachine{}
result := getDistictApp(c.Content)
c.Content = strings.Join(result, "\n")
groupItems := getDistictApp(c.GroupItems)
c.GroupItems = strings.Join(groupItems, "\n")
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
err = e.Orm.Transaction(func(tx *gorm.DB) error {
var count int64
if err := tx.Model(data).Where("machine_id =? and id<>?", c.MachineId, c.GetId()).Find(&count).Error; err != nil {
return err
}
if count > 0 {
return errors.New("设备id已存在")
}
db := tx.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("MmMachineService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
})
//保存更新缓存
if data.MachineId != "" {
content := c.Content
groupItems := c.GroupItems
key := fmt.Sprintf(enums.MachineContentKey, data.MachineId)
key2 := fmt.Sprintf(enums.MachineGroupKey, data.MachineId)
if data.Content == "" || data.GroupItems == "" {
var templates []models.MmWhiteTemplate
e.Orm.Model(models.MmWhiteTemplate{}).Find(&templates)
for _, item := range templates {
if item.Type == 0 && content == "" {
content = item.Content
} else if item.Type == 1 && groupItems == "" {
groupItems = item.Content
}
}
}
helper.DefaultRedis.SetStringExpire(key, content, time.Hour*24*3)
helper.DefaultRedis.SetStringExpire(key2, groupItems, time.Hour*24*3)
}
return err
}
func (e *MmMachine) UpdateLimitBatch(req *dto.MmMachineUpdateLimitBatchReq, p *actions.DataPermission) error {
mapData := map[string]interface{}{}
if req.Type == 0 && req.Limit > 0 {
mapData["task_limit"] = req.Limit
}
if req.Type == 1 && req.Limit > 0 {
mapData["app_limit"] = req.Limit
}
if len(mapData) == 0 {
return errors.New("无更新内容")
}
if len(req.Ids) > 0 {
if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Updates(mapData).Error; err != nil {
e.Log.Errorf("Service UpdateLimitBatch error:%s \r\n", err)
return err
}
}
return nil
}
// 批量修改白名单
func (e *MmMachine) UpdateBatch(req *dto.MmMachineUpdateBatchReq, p *actions.DataPermission) error {
machineIds := make([]string, 0)
result := getDistictApp(req.Content)
req.Content = strings.Join(result, "\n")
mapData := map[string]interface{}{
"update_by": req.UpdateBy,
"updated_at": time.Now(),
}
switch req.Type {
case 0:
mapData["content"] = req.Content
case 1:
mapData["group_items"] = req.Content
default:
return errors.New("类型不存在")
}
if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Updates(mapData).Error; err != nil {
e.Log.Errorf("Service UpdateBatch error:%s \r\n", err)
return err
}
if err := e.Orm.Model(&models.MmMachine{}).Where("id in ?", req.Ids).Select("machine_id").Find(&machineIds).Error; err != nil {
e.Log.Errorf("Service UpdateBatch error:%s \r\n", err.Error())
}
switch {
case req.Type == 0:
var content string
if req.Content == "" {
var template models.MmWhiteTemplate
e.Orm.Model(template).Where("type = 0").First(&template)
content = template.Content
}
for _, item := range machineIds {
key := fmt.Sprintf(enums.MachineContentKey, item)
if content != "" {
helper.DefaultRedis.SetStringExpire(key, content, time.Hour*24*3)
} else {
helper.DefaultRedis.SetStringExpire(key, req.Content, time.Hour*24*3)
}
}
case req.Type == 1:
var content string
if req.Content == "" {
var template models.MmWhiteTemplate
e.Orm.Model(template).Where("type = 1").First(&template)
content = template.Content
}
for _, item := range machineIds {
key := fmt.Sprintf(enums.MachineContentKey, item)
if content != "" {
helper.DefaultRedis.SetStringExpire(key, content, time.Hour*24*3)
} else {
helper.DefaultRedis.SetStringExpire(key, req.Content, time.Hour*24*3)
}
}
}
return nil
}
// Remove 删除MmMachine
func (e *MmMachine) Remove(d *dto.MmMachineDeleteReq, p *actions.DataPermission) error {
var data models.MmMachine
db := e.Orm.Model(&data).
Scopes(
actions.Permission(data.TableName(), p),
).Delete(&data, d.GetId())
if err := db.Error; err != nil {
e.Log.Errorf("Service RemoveMmMachine error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}
// GetPassword 获取MmMachine密码
func (e *MmMachine) GetPassword() (string, error) {
var config models.SysConfig
if err := e.Orm.Model(config).Where("config_key = ?", "machine_password").First(&config).Error; err != nil {
e.Log.Errorf("Service GetPassword error:%s \r\n", err)
return "", err
}
return config.ConfigValue, nil
}
// GetWhiteProcess 获取白名单进程列表
func (e *MmMachine) GetWhiteProcess(req *dto.MmMachineQueryWhiteListReq, useCache bool) (dto.MmMachineHeartResp, error) {
result := e.GetHeartResp(req.MachineId, useCache)
return result, nil
}
// GetWhiteApp 获取白名单应用列表
// machineId 机器id
// cache 是否获取变更缓存
func (e *MmMachine) GetHeartResp(machineId string, cache bool) dto.MmMachineHeartResp {
var machine models.MmMachine
var config models.SysConfig
var keywordIntevalConfig models.SysConfig
var keywordLimitConfig models.SysConfig
var taskLimitConfig models.SysConfig
var appLimitConfig models.SysConfig
var interceptConfig models.SysConfig
configService := SysConfig{Service: e.Service}
result := dto.MmMachineHeartResp{}
heartInterval := 0
keywordHeartInterval := 0
e.Orm.Model(machine).Where("machine_id = ?", machineId).First(&machine)
config, _ = configService.GetByKey("machine_heart_interval")
keywordIntevalConfig, _ = configService.GetByKey("mm_keyword_interval")
keywordLimitConfig, _ = configService.GetByKey("mm_keyword_enable")
taskLimitConfig, _ = configService.GetByKey("mm_task_limit")
appLimitConfig, _ = configService.GetByKey("mm_app_limit")
interceptConfig, _ = configService.GetByKey("mm_intecept_inteval")
if config.ConfigValue != "" {
heartInterval, _ = strconv.Atoi(config.ConfigValue)
}
if keywordIntevalConfig.ConfigValue != "" {
keywordHeartInterval, _ = strconv.Atoi(keywordIntevalConfig.ConfigValue)
}
intercept, _ := strconv.ParseFloat(interceptConfig.ConfigValue, 64)
//默认一小时
if intercept > 0 {
result.InterceptInterval = intercept
} else {
result.InterceptInterval = 1
}
//从缓存获取变更
if cache {
contentKey := fmt.Sprintf(enums.MachineContentKey, machineId)
contentVal, _ := helper.DefaultRedis.GetString(contentKey)
groupKey := fmt.Sprintf(enums.MachineGroupKey, machineId)
groupItemVal, _ := helper.DefaultRedis.GetString(groupKey)
result.Content = contentVal
result.GroupItems = groupItemVal
if contentVal != "" {
helper.DefaultRedis.DeleteString(contentKey)
}
if groupItemVal != "" {
helper.DefaultRedis.DeleteString(groupKey)
}
} else {
//没有就返回模板配置
if machine.Content == "" {
var whiteTemplate models.MmWhiteTemplate
e.Orm.Model(whiteTemplate).Where("type = 0").First(&whiteTemplate)
result.Content = whiteTemplate.Content
} else {
result.Content = machine.Content
}
if machine.GroupItems == "" {
var temp models.MmWhiteTemplate
e.Orm.Model(temp).Where("type = 1").First(&temp)
result.GroupItems = temp.Content
} else {
result.GroupItems = machine.GroupItems
}
}
result.TaskLimit, _ = strconv.Atoi(taskLimitConfig.ConfigValue)
if result.TaskLimit < 1 || result.TaskLimit > 3 {
result.TaskLimit = 1
}
if appLimitConfig.ConfigValue != "2" {
result.AppLimit = 1
} else {
result.AppLimit = 2
}
result.HeartInterval = heartInterval
result.KeywordsInterval = keywordHeartInterval
if keywordLimitConfig.ConfigValue != "" {
result.KeywordLimit, _ = strconv.Atoi(keywordLimitConfig.ConfigValue)
} else {
result.KeywordLimit = 2
}
reboot, _ := helper.DefaultRedis.GetString(fmt.Sprintf(enums.RebootMachine, machineId))
if reboot == "1" {
result.Reboot = true
helper.DefaultRedis.DeleteString(fmt.Sprintf(enums.RebootMachine, machineId))
}
return result
}
// UpdateMachineWhite 更新机器白名单
func (e *MmMachine) UpdateMachineWhite(req *dto.MmMachineUpdateWhiteReq) error {
var machine models.MmMachine
result := getDistictApp(req.Content)
req.Content = strings.Join(result, "\n")
e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).Find(&machine)
if machine.Id > 0 && machine.BiosId == req.BiosId {
if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"content": req.Content, "last_time": time.Now()}).Error; err != nil {
e.Log.Errorf("Service UpdateMachineWhite error:%s \r\n", err)
return err
}
} else if machine.Id > 0 && machine.BiosId != req.BiosId {
if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"content": req.Content, "last_time": time.Now(), "bios_id": req.BiosId}).Error; err != nil {
e.Log.Errorf("Service UpdateMachineWhite error:%s \r\n", err)
return err
}
} else {
now := time.Now()
machine.MachineId = req.MachineId
machine.BiosId = req.BiosId
machine.Content = req.Content
machine.LastTime = &now
if err := e.Orm.Create(&machine).Error; err != nil {
e.Log.Errorf("Service UpdateMachineWhite error:%s \r\n", err)
return err
}
}
return nil
}
func getDistictApp(content string) []string {
apps := strings.Split(content, "\n")
seen := make(map[string]bool)
result := []string{}
for _, app := range apps {
app = strings.TrimSpace(app) // 去除首尾空格
if app == "" {
continue // 跳过空行
}
if !seen[app] {
seen[app] = true
result = append(result, app)
}
}
return result
}
func (e *MmMachine) CheckMachine(req *dto.MmMachineCheckMachineReq) dto.MmMachineHeartResp {
var machine models.MmMachine
now := time.Now()
resp := dto.MmMachineHeartResp{}
resp.Code = 1
if req.MachineId == "" {
err := errors.New("设备编号不能为空")
resp.Msg = "设备编号不能为空"
e.Log.Errorf("Service CheckMachine error:%s \r\n", err)
return resp
}
e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).First(&machine)
if machine.Id > 0 && machine.BiosId == "" {
machine.BiosId = req.BiosId
machine.Status = 1
machine.LastTime = &now
if err := e.Orm.Save(&machine).Error; err != nil {
e.Log.Errorf("Service CheckMachine error:%s \r\n", err)
resp.Msg = "保存失败"
return resp
}
} else if machine.Id > 0 && machine.BiosId != req.BiosId {
resp.Msg = "设备编号已被占用"
return resp
} else if machine.Id == 0 && req.MachineId != "" {
machine.MachineId = req.MachineId
machine.BiosId = req.BiosId
machine.Content = ""
machine.Status = 0
machine.TaskLimit = 1
machine.AppLimit = 1
if err := e.Orm.Create(&machine).Error; err != nil {
e.Log.Errorf("Service CheckMachine error:%s \r\n", err)
resp.Msg = "保存失败"
return resp
}
}
// e.Orm.Model(&models.MmMachine{}).Where("machine_id != ? and bios_id = ?", req.MachineId, req.BiosId).Updates(map[string]interface{}{"status": 0, "bios_id": ""})
e.Orm.Exec("update mm_machine set status = 0, bios_id = '' where machine_id != ? and bios_id = ?", req.MachineId, req.BiosId)
resp = e.GetHeartResp(req.MachineId, false)
if resp.Content != "" {
resp.Code = 0
}
return resp
}
// ChangeStatus 改变机器状态
func (e *MmMachine) ChangeStatus() error {
var machines []models.MmMachine
var data models.MmMachine
var config models.SysConfig
timeInterval := 5 * time.Minute
configService := SysConfig{Service: e.Service}
config, _ = configService.GetByKey("machine_status_change_time")
// e.Orm.Model(config).Where("config_key = ?", "machine_status_change_time").First(&config)
if config.ConfigValue != "" {
interval, _ := strconv.Atoi(config.ConfigValue)
if interval > 0 {
timeInterval = time.Duration(interval) * time.Minute
}
}
if err := e.Orm.Model(data).Find(&machines).Error; err != nil {
e.Log.Errorf("Service ChangeStatus error:%s \r\n", err)
return err
}
for _, machine := range machines {
if machine.LastTime != nil && time.Since(*machine.LastTime) >= timeInterval {
if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"status": 0}).Error; err != nil {
e.Log.Errorf("Service ChangeStatus error:%s \r\n", err)
}
} else if machine.LastTime == nil && machine.Status == 1 {
if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"status": 0}).Error; err != nil {
e.Log.Errorf("Service ChangeStatus error:%s \r\n", err)
}
} else if machine.LastTime != nil && machine.Status == 0 && time.Since(*machine.LastTime) <= timeInterval {
if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"status": 1}).Error; err != nil {
e.Log.Errorf("Service ChangeStatus error:%s \r\n", err)
}
}
}
return nil
}
// 获取设备列表
func (e *MmMachine) GetMachineList(p *actions.DataPermission) ([]dto.Option, error) {
var machines []models.MmMachine
result := make([]dto.Option, 0)
var role models.SysRole
query := e.Orm.Model(&models.MmMachine{})
e.Orm.Model(role).Where("role_id =?", p.RoleId).Find(&role)
if role.RoleKey != "admin" {
groups := ""
e.Orm.Model(models.MmUserGroup{}).Where("user_id = ?", p.UserId).Pluck("group_ids", &groups)
ids := strings.Split(groups, ",")
groupIds := make([]string, 0)
for _, item := range ids {
if item != "" {
groupIds = append(groupIds, item)
}
}
if len(groupIds) > 0 {
query.Where("group_id in ?", groupIds)
} else {
query.Where("1=0")
}
}
if err := query.Order("LENGTH(machine_id) asc, machine_id asc").Find(&machines).Error; err != nil {
e.Log.Errorf("Service GetMachineList error:%s \r\n", err)
return result, err
}
for _, machine := range machines {
statusName := "离线"
if machine.Status == 1 {
statusName = "在线"
}
label := fmt.Sprintf("%s(%s)", machine.MachineId, statusName)
result = append(result, dto.Option{Label: label, Value: machine.MachineId})
}
return result, nil
}
// 更新机器分组
func (e *MmMachine) UpdateGroupBatch(req *dto.MmMachineUpdateGroupBatchReq, p *actions.DataPermission) error {
if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Update("group_id", req.GroupId).Error; err != nil {
e.Log.Errorf("Service UpdateGroupBatch error:%s \r\n", err)
return err
}
return nil
}
// 清空所有机器数据
func (e *MmMachine) ClearAll() error {
if err := e.Orm.Exec("truncate table mm_machine").Error; err != nil {
e.Log.Errorf("Service ClearAll error:%s \r\n", err)
return err
}
return nil
}
// 清空所有绑定
func (e *MmMachine) Uninstall() error {
if err := e.Orm.Exec("update mm_machine set bios_id = '' where bios_id != ''").Error; err != nil {
e.Log.Errorf("Service Uninstall error:%s \r\n", err)
return err
}
return nil
}
// 批量修改备注
func (e *MmMachine) UpdateDescriptionBatch(req *dto.MmMachineUpdateDescriptionBatchReq, p *actions.DataPermission) error {
if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Update("description", req.Description).Error; err != nil {
e.Log.Errorf("Service UpdateDescriptionBatch error:%s \r\n", err)
return err
}
return nil
}
// 查询设备间隔账号
func (e *MmMachine) QueryIntervalAccount(c *gin.Context) error {
machineIds := make([]string, 0)
lastMachineId := 0
errMachineIds := make([]dto.MmMachineExportResp, 0)
if err := e.Orm.Model(models.MmMachine{}).
Order(" LENGTH(machine_id) asc, machine_id asc").
Pluck("machine_id", &machineIds).Error; err != nil {
e.Log.Errorf("Service QueryIntervalAccount error:%s \r\n", err)
return err
}
for _, machineId := range machineIds {
newId, _ := strconv.Atoi(machineId)
if newId == 0 {
continue
}
for i := lastMachineId + 1; i < newId; i++ {
errMachineIds = append(errMachineIds, dto.MmMachineExportResp{
MachineId: strconv.Itoa(i),
})
}
lastMachineId = newId
}
helper.ExportExcel(c, "导出设备号", errMachineIds, []string{})
return nil
}
// 重启机器
func (e *MmMachine) RebootMachine(req *dto.MmMachineRebootReq) error {
//重启所有设备
if len(req.MachineIds) == 0 {
var machineIds []string
if err := e.Orm.Model(models.MmMachine{}).Pluck("machine_id", &machineIds).Error; err != nil {
e.Log.Errorf("Service RebootMachine error:%s \r\n", err)
return err
}
for _, machineId := range machineIds {
key := fmt.Sprintf(enums.RebootMachine, machineId)
if err := helper.DefaultRedis.SetStringExpire(key, "1", time.Hour*24*3); err != nil {
e.Log.Errorf("Service RebootMachine error:%s \r\n", err)
}
}
} else {
for _, machineId := range req.MachineIds {
key := fmt.Sprintf(enums.RebootMachine, machineId)
if err := helper.DefaultRedis.SetStringExpire(key, "1", time.Hour*24*3); err != nil {
e.Log.Errorf("Service RebootMachine error:%s \r\n", err)
}
}
}
return nil
}