feat: 自动化控制日志模块

This commit is contained in:
qi.zhou 2025-06-12 14:39:27 +08:00
parent 17ff791383
commit 1cbedc72cb
22 changed files with 1517 additions and 8 deletions

View File

@ -0,0 +1,59 @@
- name: Device
comment: 设备管理
disable_pagination: false
fill_gorm_commit: true
fill_router_prefix: true
fields:
- name: DeviceNo
type: string
comment: 设备编号
gorm_tag: "size:32;uniqueIndex"
form:
binding_tag: "required,max=32"
- name: Name
type: string
comment: 设备名称
gorm_tag: "size:64"
form:
binding_tag: "required,max=64"
- name: Type
type: int
comment: 设备类型1增氧机、2投喂机、3水循环
form:
binding_tag: "required"
- name: Status
type: bool
comment: 设备状态true=在线false=离线)
form:
binding_tag: "required"
- name: Model
type: string
comment: 设备型号
gorm_tag: "size:64"
form:
binding_tag: "required,max=64"
- name: WorkshopID
type: int64
comment: 关联车间ID
gorm_tag: "index;foreignKey:ID;references:work_shop"
form:
binding_tag: "required"
- name: DeviceFishPond
comment: 设备-鱼池关联表
disable_pagination: false
fill_gorm_commit: true
fill_router_prefix: true
fields:
- name: DeviceID
type: int64
comment: 设备ID
gorm_tag: "index;foreignKey:ID;references:device"
form:
binding_tag: "required"
- name: FishPondID
type: int64
comment: 鱼池ID
gorm_tag: "index;foreignKey:ID;references:fish_pond"
form:
binding_tag: "required"

View File

@ -0,0 +1,229 @@
package api
import (
"ifms/internal/mods/autocontrol/biz"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/util"
"github.com/gin-gonic/gin"
)
// 设备管理
type Device struct {
DeviceBIZ *biz.Device
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Query device list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Device}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices [get]
func (a *Device) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.DeviceQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.DeviceBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Get device record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Device}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices/{id} [get]
func (a *Device) Get(c *gin.Context) {
ctx := c.Request.Context()
item, err := a.DeviceBIZ.Get(ctx, c.Param("id"))
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Create device record
// @Param body body schema.DeviceForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Device}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices [post]
func (a *Device) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
result, err := a.DeviceBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Update device record by ID
// @Param id path string true "unique id"
// @Param body body schema.DeviceForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices/{id} [put]
func (a *Device) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
err := a.DeviceBIZ.Update(ctx, c.Param("id"), item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Delete device record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices/{id} [delete]
func (a *Device) Delete(c *gin.Context) {
ctx := c.Request.Context()
err := a.DeviceBIZ.Delete(ctx, c.Param("id"))
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Get device statistics
// @Success 200 {object} util.ResponseResult{data=[]schema.DeviceStatistics}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices/statistics [get]
func (a *Device) Statistics(c *gin.Context) {
ctx := c.Request.Context()
statistics, err := a.DeviceBIZ.Statistics(ctx)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, statistics)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Device aeration config
// @Param body body schema.DeviceConfigAeration true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.DeviceConfigAeration}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices [post]
func (a *Device) AerationConfig(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceConfigAeration)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
err := a.DeviceBIZ.AerationConfig(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, nil)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Device feeding config
// @Param body body schema.DeviceConfigFeeding true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.DeviceConfigFeeding}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices [post]
func (a *Device) FeedingConfig(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceConfigFeeding)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
err := a.DeviceBIZ.FeedingConfig(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, nil)
}
// @Tags DeviceAPI
// @Security ApiKeyAuth
// @Summary Device water circulation config
// @Param body body schema.DeviceConfigWaterCirculation true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.DeviceConfigWaterCirculation}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/devices [post]
func (a *Device) WaterCirculationConfig(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceConfigWaterCirculation)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
err := a.DeviceBIZ.WaterCirculationConfig(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, nil)
}

View File

@ -75,7 +75,8 @@ func (a *DeviceControlLog) Create(c *gin.Context) {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
result, err := a.DeviceControlLogBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)

View File

@ -0,0 +1,133 @@
package api
import (
"ifms/internal/mods/autocontrol/biz"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/util"
"github.com/gin-gonic/gin"
)
// 设备-鱼池关联表
type DeviceFishPond struct {
DeviceFishPondBIZ *biz.DeviceFishPond
}
// @Tags DeviceFishPondAPI
// @Security ApiKeyAuth
// @Summary Query device fish pond list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.DeviceFishPond}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/device-fish-ponds [get]
func (a *DeviceFishPond) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.DeviceFishPondQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.DeviceFishPondBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags DeviceFishPondAPI
// @Security ApiKeyAuth
// @Summary Get device fish pond record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.DeviceFishPond}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/device-fish-ponds/{id} [get]
func (a *DeviceFishPond) Get(c *gin.Context) {
ctx := c.Request.Context()
item, err := a.DeviceFishPondBIZ.Get(ctx, c.Param("id"))
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags DeviceFishPondAPI
// @Security ApiKeyAuth
// @Summary Create device fish pond record
// @Param body body schema.DeviceFishPondForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.DeviceFishPond}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/device-fish-ponds [post]
func (a *DeviceFishPond) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceFishPondForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
result, err := a.DeviceFishPondBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags DeviceFishPondAPI
// @Security ApiKeyAuth
// @Summary Update device fish pond record by ID
// @Param id path string true "unique id"
// @Param body body schema.DeviceFishPondForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/device-fish-ponds/{id} [put]
func (a *DeviceFishPond) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.DeviceFishPondForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
err := a.DeviceFishPondBIZ.Update(ctx, c.Param("id"), item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags DeviceFishPondAPI
// @Security ApiKeyAuth
// @Summary Delete device fish pond record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/autocontrol/device-fish-ponds/{id} [delete]
func (a *DeviceFishPond) Delete(c *gin.Context) {
ctx := c.Request.Context()
err := a.DeviceFishPondBIZ.Delete(ctx, c.Param("id"))
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -75,7 +75,8 @@ func (a *DeviceRunLog) Create(c *gin.Context) {
util.ResError(c, err)
return
}
user := util.FromLoginUser(ctx)
item.TenantID = user.TenantID
result, err := a.DeviceRunLogBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)

View File

@ -0,0 +1,344 @@
package biz
import (
"context"
"strconv"
"strings"
"time"
"ifms/internal/consts"
"ifms/internal/mods/autocontrol/dal"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/gormx"
"ifms/pkg/util"
)
// 设备管理
type Device struct {
Trans *util.Trans
DeviceDAL *dal.Device
DeviceFishPondDAL *dal.DeviceFishPond
}
// Query devices from the data access object based on the provided parameters and options.
func (a *Device) Query(ctx context.Context, params schema.DeviceQueryParam) (*schema.DeviceQueryResult, error) {
params.Pagination = true
result, err := a.DeviceDAL.Query(ctx, params, schema.DeviceQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
// 预加载鱼池
return result, nil
}
// Get the specified device from the data access object.
func (a *Device) Get(ctx context.Context, id string) (*schema.Device, error) {
device, err := a.DeviceDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if device == nil {
return nil, errors.NotFound("", "Device not found")
}
return device, nil
}
// Create a new device in the data access object.
func (a *Device) Create(ctx context.Context, formItem *schema.DeviceForm) (*schema.Device, error) {
device := &schema.Device{
CreatedAt: time.Now(),
}
if err := formItem.FillTo(device); err != nil {
return nil, err
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
// 判断设备编号是否存在
exists, err := a.DeviceDAL.GetByDeviceNo(ctx, device.DeviceNo)
if err != nil {
return nil, err
} else if exists != nil {
return nil, errors.BadRequest("", "设备编号已存在")
}
err = a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceDAL.Create(ctx, device); err != nil {
return err
}
if len(formItem.DeviceFishPonds) > 0 {
for _, fishPond := range formItem.DeviceFishPonds {
deviceFishPond := &schema.DeviceFishPond{
DeviceID: device.ID,
FishPondID: fishPond.FishPondID,
FishPondName: fishPond.FishPondName,
TenantID: device.TenantID,
}
if err := a.DeviceFishPondDAL.Create(ctx, deviceFishPond); err != nil {
return err
}
}
}
return nil
})
if err != nil {
return nil, err
}
return device, nil
}
// Update the specified device in the data access object.
func (a *Device) Update(ctx context.Context, id string, formItem *schema.DeviceForm) error {
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
device, err := a.DeviceDAL.Get(ctx, id)
if err != nil {
return err
} else if device == nil {
return errors.NotFound("", "Device not found")
}
if err := formItem.FillTo(device); err != nil {
return err
}
// 判断设备编号是否存在
exists, err := a.DeviceDAL.GetByDeviceNo(ctx, device.DeviceNo)
if err != nil {
return err
} else if exists != nil && exists.ID != device.ID {
return errors.BadRequest("", "设备编号已存在")
}
device.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceDAL.Update(ctx, device); err != nil {
return err
}
if err := a.DeviceFishPondDAL.DeleteByDeviceID(ctx, device.ID); err != nil {
return err
}
if len(formItem.DeviceFishPonds) > 0 {
for _, fishPond := range formItem.DeviceFishPonds {
deviceFishPond := &schema.DeviceFishPond{
DeviceID: device.ID,
FishPondID: fishPond.FishPondID,
FishPondName: fishPond.FishPondName,
TenantID: device.TenantID,
}
if err := a.DeviceFishPondDAL.Create(ctx, deviceFishPond); err != nil {
return err
}
}
}
return nil
})
}
// Delete the specified device from the data access object.
func (a *Device) Delete(ctx context.Context, id string) error {
exists, err := a.DeviceDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Device not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}
func (a *Device) Statistics(ctx context.Context) ([]schema.DeviceStatistics, error) {
statistics, err := a.DeviceDAL.Statistics(ctx)
if err != nil {
return nil, err
}
return statistics, nil
}
func (a *Device) AerationConfig(ctx context.Context, item *schema.DeviceConfigAeration) error {
// 查询设备
device, err := a.DeviceDAL.Get(ctx, strconv.FormatInt(item.DeviceID, 10))
if err != nil {
return err
}
if device == nil {
return errors.NotFound("", "设备不存在")
}
if device.Type != schema.DeviceTypeAeration {
return errors.BadRequest("", "设备类型错误")
}
deviceAeration := &schema.DeviceConfigAeration{
DeviceID: item.DeviceID,
TenantID: device.TenantID,
Level: item.Level,
Aeration: item.Aeration,
}
operation, err := a.DeviceDAL.SaveAerationConfig(ctx, deviceAeration)
if err != nil {
return err
}
// 记录操作日志
RelatedPondIds := strconv.FormatInt(device.WorkshopID, 10)
RelatedPond := device.WorkshopName
for _, fishPond := range device.DeviceFishPonds {
RelatedPondIds += strconv.FormatInt(fishPond.FishPondID, 10) + ","
RelatedPond += fishPond.FishPondName + ","
}
// 移除逗号
RelatedPondIds = strings.TrimSuffix(RelatedPondIds, ",")
RelatedPond = strings.TrimSuffix(RelatedPond, ",")
user := util.FromLoginUser(ctx)
deviceControlLog := &schema.DeviceControlLog{
TenantID: user.TenantID,
DeviceID: item.DeviceID,
DeviceModel: device.Model,
DeviceName: device.Name,
RelatedPondIds: RelatedPondIds,
RelatedPond: RelatedPond,
OperatorUserID: int(user.ID),
Operator: user.Username,
Command: operation,
CommandStatus: true,
Type: device.Type,
}
deviceControlLogDAL := dal.DeviceControlLog{
DB: a.DeviceDAL.DB,
}
if err := deviceControlLogDAL.Create(ctx, deviceControlLog); err != nil {
return err
}
return nil
}
func (a *Device) FeedingConfig(ctx context.Context, item *schema.DeviceConfigFeeding) error {
// 查询设备
device, err := a.DeviceDAL.Get(ctx, strconv.FormatInt(item.DeviceID, 10))
if err != nil {
return err
}
if device == nil {
return errors.NotFound("", "设备不存在")
}
if device.Type != schema.DeviceTypeFeeding {
return errors.BadRequest("", "设备类型错误")
}
deviceFeeding := &schema.DeviceConfigFeeding{
TenantID: device.TenantID,
DeviceID: item.DeviceID,
FeedLevel: item.FeedLevel,
FeedTime: item.FeedTime,
IntervalTime: item.IntervalTime,
}
operation, err := a.DeviceDAL.SaveFeedingConfig(ctx, deviceFeeding)
if err != nil {
return err
}
// 记录操作日志
RelatedPondIds := strconv.FormatInt(device.WorkshopID, 10)
RelatedPond := device.WorkshopName
for _, fishPond := range device.DeviceFishPonds {
RelatedPondIds += strconv.FormatInt(fishPond.FishPondID, 10) + ","
RelatedPond += fishPond.FishPondName + ","
}
// 移除逗号
RelatedPondIds = strings.TrimSuffix(RelatedPondIds, ",")
RelatedPond = strings.TrimSuffix(RelatedPond, ",")
user := util.FromLoginUser(ctx)
deviceControlLog := &schema.DeviceControlLog{
TenantID: user.TenantID,
DeviceID: item.DeviceID,
DeviceModel: device.Model,
DeviceName: device.Name,
RelatedPondIds: RelatedPondIds,
RelatedPond: RelatedPond,
OperatorUserID: int(user.ID),
Operator: user.Username,
Command: operation,
CommandStatus: true,
Type: device.Type,
}
deviceControlLogDAL := dal.DeviceControlLog{
DB: a.DeviceDAL.DB,
}
if err := deviceControlLogDAL.Create(ctx, deviceControlLog); err != nil {
return err
}
return nil
}
func (a *Device) WaterCirculationConfig(ctx context.Context, item *schema.DeviceConfigWaterCirculation) error {
// 查询设备
device, err := a.DeviceDAL.Get(ctx, strconv.FormatInt(item.DeviceID, 10))
if err != nil {
return err
}
if device == nil {
return errors.NotFound("", "设备不存在")
}
if device.Type != schema.DeviceTypeWaterCirculation {
return errors.BadRequest("", "设备类型错误")
}
deviceWaterCirculation := &schema.DeviceConfigWaterCirculation{
TenantID: device.TenantID,
DeviceID: item.DeviceID,
WaterTemp: item.WaterTemp,
WaterCirculation: item.WaterCirculation,
Aeration: item.Aeration,
Filter: item.Filter,
Disinfection: item.Disinfection,
}
operation, err := a.DeviceDAL.SaveWaterCirculationConfig(ctx, deviceWaterCirculation)
if err != nil {
return err
}
// 记录操作日志
RelatedPondIds := strconv.FormatInt(device.WorkshopID, 10)
RelatedPond := device.WorkshopName
for _, fishPond := range device.DeviceFishPonds {
RelatedPondIds += strconv.FormatInt(fishPond.FishPondID, 10) + ","
RelatedPond += fishPond.FishPondName + ","
}
// 移除逗号
RelatedPondIds = strings.TrimSuffix(RelatedPondIds, ",")
RelatedPond = strings.TrimSuffix(RelatedPond, ",")
user := util.FromLoginUser(ctx)
deviceControlLog := &schema.DeviceControlLog{
TenantID: user.TenantID,
DeviceID: item.DeviceID,
DeviceModel: device.Model,
DeviceName: device.Name,
RelatedPondIds: RelatedPondIds,
RelatedPond: RelatedPond,
OperatorUserID: int(user.ID),
Operator: user.Username,
Command: operation,
CommandStatus: true,
Type: device.Type,
}
deviceControlLogDAL := dal.DeviceControlLog{
DB: a.DeviceDAL.DB,
}
if err := deviceControlLogDAL.Create(ctx, deviceControlLog); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,106 @@
package biz
import (
"context"
"time"
"ifms/internal/mods/autocontrol/dal"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/util"
)
// 设备-鱼池关联表
type DeviceFishPond struct {
Trans *util.Trans
DeviceFishPondDAL *dal.DeviceFishPond
}
// Query device fish ponds from the data access object based on the provided parameters and options.
func (a *DeviceFishPond) Query(ctx context.Context, params schema.DeviceFishPondQueryParam) (*schema.DeviceFishPondQueryResult, error) {
params.Pagination = true
result, err := a.DeviceFishPondDAL.Query(ctx, params, schema.DeviceFishPondQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified device fish pond from the data access object.
func (a *DeviceFishPond) Get(ctx context.Context, id string) (*schema.DeviceFishPond, error) {
deviceFishPond, err := a.DeviceFishPondDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if deviceFishPond == nil {
return nil, errors.NotFound("", "Device fish pond not found")
}
return deviceFishPond, nil
}
// Create a new device fish pond in the data access object.
func (a *DeviceFishPond) Create(ctx context.Context, formItem *schema.DeviceFishPondForm) (*schema.DeviceFishPond, error) {
deviceFishPond := &schema.DeviceFishPond{
CreatedAt: time.Now(),
}
if err := formItem.FillTo(deviceFishPond); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceFishPondDAL.Create(ctx, deviceFishPond); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return deviceFishPond, nil
}
// Update the specified device fish pond in the data access object.
func (a *DeviceFishPond) Update(ctx context.Context, id string, formItem *schema.DeviceFishPondForm) error {
deviceFishPond, err := a.DeviceFishPondDAL.Get(ctx, id)
if err != nil {
return err
} else if deviceFishPond == nil {
return errors.NotFound("", "Device fish pond not found")
}
if err := formItem.FillTo(deviceFishPond); err != nil {
return err
}
deviceFishPond.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceFishPondDAL.Update(ctx, deviceFishPond); err != nil {
return err
}
return nil
})
}
// Delete the specified device fish pond from the data access object.
func (a *DeviceFishPond) Delete(ctx context.Context, id string) error {
exists, err := a.DeviceFishPondDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Device fish pond not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.DeviceFishPondDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,279 @@
package dal
import (
"context"
"fmt"
"ifms/internal/consts"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/gormx"
"ifms/pkg/util"
"github.com/spf13/cast"
"gorm.io/gorm"
)
// Get device storage instance
func GetDeviceDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Device))
}
// 设备管理
type Device struct {
DB *gorm.DB
}
// Query devices from the database based on the provided parameters and options.
func (a *Device) Query(ctx context.Context, params schema.DeviceQueryParam, opts ...schema.DeviceQueryOptions) (*schema.DeviceQueryResult, error) {
var opt schema.DeviceQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
db := GetDeviceDB(ctx, a.DB)
db = db.Preload("DeviceFishPonds").Preload("DeviceConfigAeration").Preload("DeviceConfigFeeding").Preload("DeviceConfigWaterCirculation")
if params.Name != "" {
db = db.Where("name like ?", "%"+params.Name+"%")
}
if params.Type != nil {
db = db.Where("type=?", *params.Type)
}
var list schema.Devices
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
// 上面预加载了DeviceConfigAerationDeviceConfigFeedingDeviceConfigWaterCirculation则设置参数默认值不为null
for k, v := range list {
if v.DeviceConfigAeration == nil {
v.DeviceConfigAeration = &schema.DeviceConfigAeration{}
}
if v.DeviceConfigFeeding == nil {
v.DeviceConfigFeeding = &schema.DeviceConfigFeeding{}
}
if v.DeviceConfigWaterCirculation == nil {
v.DeviceConfigWaterCirculation = &schema.DeviceConfigWaterCirculation{}
}
list[k] = v
}
queryResult := &schema.DeviceQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified device from the database.
func (a *Device) Get(ctx context.Context, id string, opts ...schema.DeviceQueryOptions) (*schema.Device, error) {
var opt schema.DeviceQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
db := GetDeviceDB(ctx, a.DB)
db = db.Preload("DeviceFishPonds").Preload("DeviceConfigAeration").Preload("DeviceConfigFeeding").Preload("DeviceConfigWaterCirculation")
item := new(schema.Device)
ok, err := util.FindOne(ctx, db.Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *Device) GetByDeviceNo(ctx context.Context, deviceNo string, opts ...schema.DeviceQueryOptions) (*schema.Device, error) {
var opt schema.DeviceQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Device)
ok, err := util.FindOne(ctx, GetDeviceDB(ctx, a.DB).Where("device_no=?", deviceNo), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified device exists in the database.
func (a *Device) Exists(ctx context.Context, id string) (bool, error) {
ok, err := util.Exists(ctx, GetDeviceDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new device.
func (a *Device) Create(ctx context.Context, item *schema.Device) error {
result := GetDeviceDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified device in the database.
func (a *Device) Update(ctx context.Context, item *schema.Device) error {
result := GetDeviceDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified device from the database.
func (a *Device) Delete(ctx context.Context, id string) error {
result := GetDeviceDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Device))
return errors.WithStack(result.Error)
}
func (a *Device) Statistics(ctx context.Context) ([]schema.DeviceStatistics, error) {
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
// 统计不同的设备类型数量以及在线数量(status=true)
var statistics []schema.DeviceStatistics
// 类型为1,2,3
types := []int{schema.DeviceTypeAeration, schema.DeviceTypeFeeding, schema.DeviceTypeWaterCirculation}
for _, v := range types {
// 统计不同设备类型总数
total := int64(0)
GetDeviceDB(ctx, a.DB).Where("type=?", v).Count(&total)
// 统计不同设备类型在线数量
online := int64(0)
GetDeviceDB(ctx, a.DB).Where("type=?", v).Where("status=?", true).Count(&online)
statistics = append(statistics, schema.DeviceStatistics{
Type: v,
Total: int(total),
Online: int(online),
Offline: int(total - online),
})
if total > 0 {
statistics[len(statistics)-1].Rate = int(online * 100 / total)
}
}
return statistics, nil
}
func (a *Device) SaveAerationConfig(ctx context.Context, item *schema.DeviceConfigAeration) (string, error) {
operation := ""
// 查询数据是否存在 存在对比差异,不存在直接记录操作值
record := new(schema.DeviceConfigAeration)
GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigAeration)).Where("device_id=?", item.DeviceID).First(record)
level := ""
aeration := ""
if record.ID > 0 {
if record.Level == 1 {
level = "高"
} else if record.Level == 2 {
level = "中"
} else if record.Level == 3 {
level = "低"
}
aeration = cast.ToString(record.Aeration)
}
newLevel := ""
if item.Level == 1 {
newLevel = "高"
} else if item.Level == 2 {
newLevel = "中"
} else if item.Level == 3 {
newLevel = "低"
}
operation += fmt.Sprintf("档位: %v -> %v, ", level, newLevel)
operation += fmt.Sprintf("溶氧: %v -> %v, ", aeration, item.Aeration)
// 先删除后新增
result2 := GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigAeration)).Where("device_id=?", item.DeviceID).Delete(new(schema.DeviceConfigAeration))
if result2.Error != nil {
return operation, errors.WithStack(result2.Error)
}
result := GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigAeration)).Create(item)
return operation, errors.WithStack(result.Error)
}
func (a *Device) SaveFeedingConfig(ctx context.Context, item *schema.DeviceConfigFeeding) (string, error) {
operation := ""
// 查询数据是否存在 存在对比差异,不存在直接记录操作值
record := new(schema.DeviceConfigFeeding)
GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigFeeding)).Where("device_id=?", item.DeviceID).First(record)
feedLevel := ""
feedTime := ""
intervalTime := ""
if record.ID > 0 {
feedLevel = cast.ToString(record.FeedLevel)
feedTime = cast.ToString(record.FeedTime)
intervalTime = cast.ToString(record.IntervalTime)
}
// 投料量档位 投料时间(秒) 间隔时间(秒)
operation += fmt.Sprintf("投料量档位: %v -> %v, ", feedLevel, item.FeedLevel)
operation += fmt.Sprintf("投料时间: %v -> %v, ", feedTime, item.FeedTime)
operation += fmt.Sprintf("间隔时间: %v -> %v, ", intervalTime, item.IntervalTime)
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
// 先删除后新增
result2 := GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigFeeding)).Where("device_id=?", item.DeviceID).Delete(new(schema.DeviceConfigFeeding))
if result2.Error != nil {
return operation, errors.WithStack(result2.Error)
}
result := GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigFeeding)).Create(item)
return operation, errors.WithStack(result.Error)
}
func (a *Device) SaveWaterCirculationConfig(ctx context.Context, item *schema.DeviceConfigWaterCirculation) (string, error) {
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
operation := ""
// 查询数据是否存在 存在对比差异,不存在直接记录操作值
record := new(schema.DeviceConfigWaterCirculation)
GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigWaterCirculation)).Where("device_id=?", item.DeviceID).First(record)
waterTemp := ""
waterCirculation := ""
aeration := ""
filter := ""
disinfection := ""
if record.ID > 0 {
waterTemp = cast.ToString(record.WaterTemp)
waterCirculation = cast.ToString(record.WaterCirculation)
aeration = cast.ToString(record.Aeration)
if record.Filter {
filter = "开"
} else {
filter = "关"
}
if record.Disinfection {
disinfection = "开"
} else {
disinfection = "关"
}
}
newFilter := ""
newDisinfection := ""
if item.Filter {
newFilter = "开"
} else {
newFilter = "关"
}
if item.Disinfection {
newDisinfection = "开"
} else {
newDisinfection = "关"
}
operation += fmt.Sprintf("水温: %v -> %v, ", waterTemp, item.WaterTemp)
operation += fmt.Sprintf("水流: %v -> %v, ", waterCirculation, item.WaterCirculation)
operation += fmt.Sprintf("曝气: %v -> %v, ", aeration, item.Aeration)
operation += fmt.Sprintf("过滤: %v -> %v, ", filter, newFilter)
operation += fmt.Sprintf("消毒: %v -> %v, ", disinfection, newDisinfection)
// 先删除后新增
result := GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigWaterCirculation)).Where("device_id=?", item.DeviceID).Delete(new(schema.DeviceConfigWaterCirculation))
if result.Error != nil {
return operation, errors.WithStack(result.Error)
}
result = GetDeviceDB(ctx, a.DB).Model(new(schema.DeviceConfigWaterCirculation)).Create(item)
return operation, errors.WithStack(result.Error)
}

View File

@ -3,8 +3,10 @@ package dal
import (
"context"
"ifms/internal/consts"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/gormx"
"ifms/pkg/util"
"gorm.io/gorm"
@ -26,7 +28,7 @@ func (a *DeviceControlLog) Query(ctx context.Context, params schema.DeviceContro
if len(opts) > 0 {
opt = opts[0]
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
db := GetDeviceControlLogDB(ctx, a.DB)
if v := params.Type; v != nil {

View File

@ -0,0 +1,91 @@
package dal
import (
"context"
"ifms/internal/consts"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/gormx"
"ifms/pkg/util"
"gorm.io/gorm"
)
// Get device fish pond storage instance
func GetDeviceFishPondDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.DeviceFishPond))
}
// 设备-鱼池关联表
type DeviceFishPond struct {
DB *gorm.DB
}
// Query device fish ponds from the database based on the provided parameters and options.
func (a *DeviceFishPond) Query(ctx context.Context, params schema.DeviceFishPondQueryParam, opts ...schema.DeviceFishPondQueryOptions) (*schema.DeviceFishPondQueryResult, error) {
var opt schema.DeviceFishPondQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
db := GetDeviceFishPondDB(ctx, a.DB)
var list schema.DeviceFishPonds
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.DeviceFishPondQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified device fish pond from the database.
func (a *DeviceFishPond) Get(ctx context.Context, id string, opts ...schema.DeviceFishPondQueryOptions) (*schema.DeviceFishPond, error) {
var opt schema.DeviceFishPondQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.DeviceFishPond)
ok, err := util.FindOne(ctx, GetDeviceFishPondDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified device fish pond exists in the database.
func (a *DeviceFishPond) Exists(ctx context.Context, id string) (bool, error) {
ok, err := util.Exists(ctx, GetDeviceFishPondDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new device fish pond.
func (a *DeviceFishPond) Create(ctx context.Context, item *schema.DeviceFishPond) error {
result := GetDeviceFishPondDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified device fish pond in the database.
func (a *DeviceFishPond) Update(ctx context.Context, item *schema.DeviceFishPond) error {
result := GetDeviceFishPondDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified device fish pond from the database.
func (a *DeviceFishPond) Delete(ctx context.Context, id string) error {
result := GetDeviceFishPondDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.DeviceFishPond))
return errors.WithStack(result.Error)
}
func (a *DeviceFishPond) DeleteByDeviceID(ctx context.Context, deviceID int64) error {
result := GetDeviceFishPondDB(ctx, a.DB).Where("device_id=?", deviceID).Delete(new(schema.DeviceFishPond))
return errors.WithStack(result.Error)
}

View File

@ -3,8 +3,10 @@ package dal
import (
"context"
"ifms/internal/consts"
"ifms/internal/mods/autocontrol/schema"
"ifms/pkg/errors"
"ifms/pkg/gormx"
"ifms/pkg/util"
"gorm.io/gorm"
@ -26,7 +28,7 @@ func (a *DeviceRunLog) Query(ctx context.Context, params schema.DeviceRunLogQuer
if len(opts) > 0 {
opt = opts[0]
}
ctx = gormx.WithTenantID(ctx, consts.DefaultTenantID)
db := GetDeviceRunLogDB(ctx, a.DB)
if v := params.Type; v != nil {

View File

@ -15,10 +15,12 @@ type AutoControl struct {
DB *gorm.DB
DeviceRunLogAPI *api.DeviceRunLog
DeviceControlLogAPI *api.DeviceControlLog
DeviceAPI *api.Device
DeviceFishPondAPI *api.DeviceFishPond
}
func (a *AutoControl) AutoMigrate(ctx context.Context) error {
return a.DB.AutoMigrate(new(schema.DeviceRunLog), new(schema.DeviceControlLog))
return a.DB.AutoMigrate(new(schema.DeviceRunLog), new(schema.DeviceControlLog), new(schema.Device), new(schema.DeviceFishPond))
}
func (a *AutoControl) Init(ctx context.Context) error {
@ -48,6 +50,31 @@ func (a *AutoControl) RegisterV1Routers(ctx context.Context, v1 *gin.RouterGroup
// deviceControlLog.PUT(":id", a.DeviceControlLogAPI.Update)
// deviceControlLog.DELETE(":id", a.DeviceControlLogAPI.Delete)
}
device := v1.Group("devices")
{
device.GET("", a.DeviceAPI.Query)
device.GET(":id", a.DeviceAPI.Get)
device.POST("", a.DeviceAPI.Create)
device.PUT(":id", a.DeviceAPI.Update)
// device.DELETE(":id", a.DeviceAPI.Delete)
// 统计设备数量以及状态
device.GET("statistics", a.DeviceAPI.Statistics)
// 增氧机配置
device.POST("aeration", a.DeviceAPI.AerationConfig)
// 投喂机配置
device.POST("feeding", a.DeviceAPI.FeedingConfig)
// 水循环配置
device.POST("water-circulation", a.DeviceAPI.WaterCirculationConfig)
}
// deviceFishPond := v1.Group("device-fish-ponds")
// {
// deviceFishPond.GET("", a.DeviceFishPondAPI.Query)
// deviceFishPond.GET(":id", a.DeviceFishPondAPI.Get)
// deviceFishPond.POST("", a.DeviceFishPondAPI.Create)
// deviceFishPond.PUT(":id", a.DeviceFishPondAPI.Update)
// deviceFishPond.DELETE(":id", a.DeviceFishPondAPI.Delete)
// }
return nil
}

View File

@ -0,0 +1,94 @@
package schema
import (
"time"
"ifms/pkg/util"
)
// 设备类型1增氧机、2投喂机、3水循环
const (
DeviceTypeAeration = 1
DeviceTypeFeeding = 2
DeviceTypeWaterCirculation = 3
)
// 设备管理
type Device struct {
ID int64 `json:"id" gorm:"primaryKey;comment:Unique ID;"` // Unique ID
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceNo string `json:"device_no" gorm:"size:32;uniqueIndex;comment:设备编号;"` // 设备编号
Name string `json:"name" gorm:"size:64;comment:设备名称;"` // 设备名称
Type int `json:"type" gorm:"comment:设备类型1增氧机、2投喂机、3水循环;"` // 设备类型1增氧机、2投喂机、3水循环
Status bool `json:"status" gorm:"comment:设备状态true=在线false=离线);"` // 设备状态true=在线false=离线)
Model string `json:"model" gorm:"size:64;comment:设备型号;"` // 设备型号
WorkshopID int64 `json:"workshop_id" gorm:"index;foreignKey:ID;references:work_shop;comment:关联车间ID;"` // 关联车间ID
WorkshopName string `json:"workshop_name" gorm:"comment:关联车间名称;"` // 关联车间名称
CreatedAt time.Time `json:"created_at" gorm:"index;comment:Create time;"` // Create time
UpdatedAt time.Time `json:"updated_at" gorm:"index;comment:Update time;"` // Update time
// 预加载信息
DeviceFishPonds []*DeviceFishPond `json:"device_fish_ponds" gorm:"index;foreignKey:DeviceID;references:ID;comment:关联鱼池ID;"`
DeviceConfigAeration *DeviceConfigAeration `json:"device_config_aeration" gorm:"index;foreignKey:DeviceID;references:ID;comment:增氧机配置;"`
DeviceConfigFeeding *DeviceConfigFeeding `json:"device_config_feeding" gorm:"index;foreignKey:DeviceID;references:ID;comment:投喂机配置;"`
DeviceConfigWaterCirculation *DeviceConfigWaterCirculation `json:"device_config_water_circulation" gorm:"index;foreignKey:DeviceID;references:ID;comment:水循环配置;"`
}
// Defining the query parameters for the `Device` struct.
type DeviceQueryParam struct {
util.PaginationParam
Name string `form:"name"`
Type *int `form:"type"`
}
// Defining the query options for the `Device` struct.
type DeviceQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Device` struct.
type DeviceQueryResult struct {
Data Devices
PageResult *util.PaginationResult
}
// Defining the slice of `Device` struct.
type Devices []*Device
// Defining the data structure for creating a `Device` struct.
type DeviceForm struct {
TenantID string `json:"tenant_id"` // 租户ID
DeviceNo string `json:"device_no" binding:"required,max=32"` // 设备编号
Name string `json:"name" binding:"required,max=64"` // 设备名称
Type int `json:"type" binding:"required"` // 设备类型1增氧机、2投喂机、3水循环
Status bool `json:"status"` // 设备状态true=在线false=离线)
Model string `json:"model" binding:"required,max=64"` // 设备型号
WorkshopID int64 `json:"workshop_id" binding:"required"` // 关联车间ID
WorkshopName string `json:"workshop_name" binding:"required"` // 关联车间名称
DeviceFishPonds []*DeviceFishPond `json:"device_fish_ponds" gorm:"index;foreignKey:DeviceID;references:ID;comment:关联鱼池ID;"`
}
// A validation function for the `DeviceForm` struct.
func (a *DeviceForm) Validate() error {
return nil
}
// Convert `DeviceForm` to `Device` object.
func (a *DeviceForm) FillTo(device *Device) error {
device.TenantID = a.TenantID
device.DeviceNo = a.DeviceNo
device.Name = a.Name
device.Type = a.Type
device.Status = a.Status
device.Model = a.Model
device.WorkshopID = a.WorkshopID
device.WorkshopName = a.WorkshopName
return nil
}
type DeviceStatistics struct {
Type int `json:"type"`
Total int `json:"total"`
Online int `json:"online"`
Offline int `json:"offline"`
Rate int `json:"rate"`
}

View File

@ -0,0 +1,14 @@
package schema
import "time"
// 增氧机配置表
type DeviceConfigAeration struct {
ID int64 `json:"id" gorm:"primaryKey;comment:Unique ID;"`
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID int64 `json:"device_id" gorm:"uniqueIndex;not null;comment:设备ID;"`
Level int `json:"level" gorm:"not null;comment:投料量档位;"`
Aeration float64 `json:"aeration" gorm:"type:decimal(5,2);not null;comment:溶氧(mg/l);"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;comment:创建时间;"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime;comment:更新时间;"`
}

View File

@ -0,0 +1,15 @@
package schema
import "time"
// 投喂机配置表
type DeviceConfigFeeding struct {
ID int64 `json:"id" gorm:"primaryKey;comment:Unique ID;"`
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID int64 `json:"device_id" gorm:"uniqueIndex;not null;comment:设备ID;"`
FeedLevel int `json:"feed_level" gorm:"not null;comment:投料量档位;"`
FeedTime int `json:"feed_time" gorm:"not null;comment:投料时间(秒);"`
IntervalTime int `json:"interval_time" gorm:"not null;comment:间隔时间(秒);"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;comment:创建时间;"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime;comment:更新时间;"`
}

View File

@ -0,0 +1,17 @@
package schema
import "time"
// 水循环配置表
type DeviceConfigWaterCirculation struct {
ID int64 `json:"id" gorm:"primaryKey;comment:Unique ID;"`
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID int64 `json:"device_id" gorm:"uniqueIndex;not null;comment:设备ID;"`
WaterTemp float64 `json:"water_temp" gorm:"type:decimal(4,1);not null;comment:水温设置(℃);"`
WaterCirculation int `json:"water_circulation" gorm:"not null;comment:水循环量(次);"`
Aeration float64 `json:"aeration" gorm:"type:decimal(5,2);not null;comment:增氧量(mg/l);"`
Filter bool `json:"filter" gorm:"not null;comment:是否过滤;"`
Disinfection bool `json:"disinfection" gorm:"not null;comment:是否消毒;"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;comment:创建时间;"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime;comment:更新时间;"`
}

View File

@ -9,7 +9,8 @@ import (
// 设备操作日志表
type DeviceControlLog struct {
ID int64 `json:"id" gorm:"primaryKey;autoIncrement;comment:Unique ID;"` // Unique ID
DeviceID string `json:"device_id" gorm:"size:32;index;comment:设备ID;"` // 设备ID
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID int64 `json:"device_id" gorm:"size:32;index;comment:设备ID;"` // 设备ID
DeviceModel string `json:"device_model" gorm:"size:64;comment:设备型号;"` // 设备型号
DeviceName string `json:"device_name" gorm:"size:64;comment:设备名称;"` // 设备名称
RelatedPondIds string `json:"related_pond_ids" gorm:"type:text;comment:关联鱼池/车间ID;"` // 关联鱼池/车间ID
@ -46,7 +47,8 @@ type DeviceControlLogs []*DeviceControlLog
// Defining the data structure for creating a `DeviceControlLog` struct.
type DeviceControlLogForm struct {
DeviceID string `json:"device_id" binding:"required,max=32"` // 设备ID
TenantID string `json:"tenant_id"` // 租户ID
DeviceID int64 `json:"device_id" binding:"required,max=32"` // 设备ID
DeviceModel string `json:"device_model" binding:"required,max=64"` // 设备型号
DeviceName string `json:"device_name" binding:"required,max=64"` // 设备名称
RelatedPondIds string `json:"related_pond_ids" binding:"required"` // 关联鱼池/车间ID
@ -65,6 +67,7 @@ func (a *DeviceControlLogForm) Validate() error {
// Convert `DeviceControlLogForm` to `DeviceControlLog` object.
func (a *DeviceControlLogForm) FillTo(deviceControlLog *DeviceControlLog) error {
deviceControlLog.TenantID = a.TenantID
deviceControlLog.DeviceID = a.DeviceID
deviceControlLog.DeviceModel = a.DeviceModel
deviceControlLog.DeviceName = a.DeviceName

View File

@ -0,0 +1,59 @@
package schema
import (
"time"
"ifms/pkg/util"
)
// 设备-鱼池关联表
type DeviceFishPond struct {
ID int64 `json:"id" gorm:"size:20;primaryKey;comment:Unique ID;"` // Unique ID
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID int64 `json:"device_id" gorm:"index;foreignKey:ID;references:device;comment:设备ID;"` // 设备ID
FishPondID int64 `json:"fish_pond_id" gorm:"index;foreignKey:ID;references:fish_pond;comment:鱼池ID;"` // 鱼池ID
FishPondName string `json:"fish_pond_name" gorm:"comment:鱼池名称;"` // 鱼池名称
CreatedAt time.Time `json:"created_at" gorm:"index;comment:Create time;"` // Create time
UpdatedAt time.Time `json:"updated_at" gorm:"index;comment:Update time;"` // Update time
}
// Defining the query parameters for the `DeviceFishPond` struct.
type DeviceFishPondQueryParam struct {
util.PaginationParam
}
// Defining the query options for the `DeviceFishPond` struct.
type DeviceFishPondQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `DeviceFishPond` struct.
type DeviceFishPondQueryResult struct {
Data DeviceFishPonds
PageResult *util.PaginationResult
}
// Defining the slice of `DeviceFishPond` struct.
type DeviceFishPonds []*DeviceFishPond
// Defining the data structure for creating a `DeviceFishPond` struct.
type DeviceFishPondForm struct {
TenantID string `json:"tenant_id"` // 租户ID
DeviceID int64 `json:"device_id" binding:"required"` // 设备ID
FishPondID int64 `json:"fish_pond_id" binding:"required"` // 鱼池ID
FishPondName string `json:"fish_pond_name" binding:"required"` // 鱼池名称
}
// A validation function for the `DeviceFishPondForm` struct.
func (a *DeviceFishPondForm) Validate() error {
return nil
}
// Convert `DeviceFishPondForm` to `DeviceFishPond` object.
func (a *DeviceFishPondForm) FillTo(deviceFishPond *DeviceFishPond) error {
deviceFishPond.TenantID = a.TenantID
deviceFishPond.DeviceID = a.DeviceID
deviceFishPond.FishPondID = a.FishPondID
deviceFishPond.FishPondName = a.FishPondName
return nil
}

View File

@ -9,6 +9,7 @@ import (
// 设备运行日志表
type DeviceRunLog struct {
ID int64 `json:"id" gorm:"primaryKey;autoIncrement;comment:Unique ID;"` // Unique ID
TenantID string `json:"tenant_id" gorm:"size:32;"` // Tenant ID
DeviceID string `json:"device_id" gorm:"size:32;index;comment:设备ID;"` // 设备ID
DeviceModel string `json:"device_model" gorm:"size:64;comment:设备型号;"` // 设备型号
DeviceName string `json:"device_name" gorm:"size:64;comment:设备名称;"` // 设备名称
@ -48,6 +49,7 @@ type DeviceRunLogs []*DeviceRunLog
// Defining the data structure for creating a `DeviceRunLog` struct.
type DeviceRunLogForm struct {
TenantID string `json:"tenant_id"` // 租户ID
DeviceID string `json:"device_id" binding:"required,max=32"` // 设备ID
DeviceModel string `json:"device_model" binding:"required,max=64"` // 设备型号
DeviceName string `json:"device_name" binding:"required,max=64"` // 设备名称
@ -69,6 +71,7 @@ func (a *DeviceRunLogForm) Validate() error {
// Convert `DeviceRunLogForm` to `DeviceRunLog` object.
func (a *DeviceRunLogForm) FillTo(deviceRunLog *DeviceRunLog) error {
deviceRunLog.TenantID = a.TenantID
deviceRunLog.DeviceID = a.DeviceID
deviceRunLog.DeviceModel = a.DeviceModel
deviceRunLog.DeviceName = a.DeviceName

View File

@ -16,4 +16,10 @@ var Set = wire.NewSet(
wire.Struct(new(dal.DeviceControlLog), "*"),
wire.Struct(new(biz.DeviceControlLog), "*"),
wire.Struct(new(api.DeviceControlLog), "*"),
wire.Struct(new(dal.Device), "*"),
wire.Struct(new(biz.Device), "*"),
wire.Struct(new(api.Device), "*"),
wire.Struct(new(dal.DeviceFishPond), "*"),
wire.Struct(new(biz.DeviceFishPond), "*"),
wire.Struct(new(api.DeviceFishPond), "*"),
)

View File

@ -1,10 +1,11 @@
package api
import (
"github.com/gin-gonic/gin"
"ifms/internal/mods/rbac/biz"
"ifms/internal/mods/rbac/schema"
"ifms/pkg/util"
"github.com/gin-gonic/gin"
)
// User management for RBAC

View File

@ -161,10 +161,33 @@ func BuildInjector(ctx context.Context) (*Injector, func(), error) {
apiDeviceControlLog := &api3.DeviceControlLog{
DeviceControlLogBIZ: bizDeviceControlLog,
}
device := &dal3.Device{
DB: db,
}
deviceFishPond := &dal3.DeviceFishPond{
DB: db,
}
bizDevice := &biz3.Device{
Trans: trans,
DeviceDAL: device,
DeviceFishPondDAL: deviceFishPond,
}
apiDevice := &api3.Device{
DeviceBIZ: bizDevice,
}
bizDeviceFishPond := &biz3.DeviceFishPond{
Trans: trans,
DeviceFishPondDAL: deviceFishPond,
}
apiDeviceFishPond := &api3.DeviceFishPond{
DeviceFishPondBIZ: bizDeviceFishPond,
}
autoControl := &autocontrol.AutoControl{
DB: db,
DeviceRunLogAPI: apiDeviceRunLog,
DeviceControlLogAPI: apiDeviceControlLog,
DeviceAPI: apiDevice,
DeviceFishPondAPI: apiDeviceFishPond,
}
modsMods := &mods.Mods{
RBAC: rbacRBAC,