添加定时清理相关
This commit is contained in:
parent
8540f76fcf
commit
9cfb302777
Binary file not shown.
|
Before Width: | Height: | Size: 647 KiB After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 90 KiB |
@ -30,7 +30,7 @@ func WireApp(bc *conf.Bootstrap, log *slog.Logger) (http.Handler, func(), error)
|
|||||||
vqdTaskCore := api.NewVqdTaskCore(db)
|
vqdTaskCore := api.NewVqdTaskCore(db)
|
||||||
hostCore := host.NewCore(bc)
|
hostCore := host.NewCore(bc)
|
||||||
mediaCore := media.NewCore(hostCore)
|
mediaCore := media.NewCore(hostCore)
|
||||||
vqdSdkCore := vqdsdk.NewCore(hostCore, vqdTaskCore)
|
vqdSdkCore := vqdsdk.NewCore(hostCore, vqdTaskCore, bc)
|
||||||
vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc)
|
vqdTaskAPI := api.NewVqdTaskAPI(vqdTaskCore, mediaCore,vqdSdkCore,hostCore, bc)
|
||||||
|
|
||||||
usecase := &api.Usecase{
|
usecase := &api.Usecase{
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"easyvqd/internal/core/vqd"
|
"easyvqd/internal/core/vqd"
|
||||||
"git.lnton.com/lnton/pkg/orm"
|
"git.lnton.com/lnton/pkg/orm"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ vqd.VqdAlarmStorer = VqdAlarm{}
|
var _ vqd.VqdAlarmStorer = VqdAlarm{}
|
||||||
@ -48,6 +49,15 @@ func (d VqdAlarm) Del(ctx context.Context, model *vqd.VqdAlarm, opts ...orm.Quer
|
|||||||
return orm.DeleteWithContext(ctx, d.db, model, opts...)
|
return orm.DeleteWithContext(ctx, d.db, model, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelAll implements vqd.VqdTaskTemplateStorer.
|
||||||
|
func (d VqdAlarm) DelAll(expireTime time.Time, batchSize int) (int, error) {
|
||||||
|
result := d.db.Where(`created_at < ?`, expireTime).Limit(batchSize).Delete(&vqd.VqdAlarm{})
|
||||||
|
if result.Error != nil {
|
||||||
|
return 0, result.Error
|
||||||
|
}
|
||||||
|
return int(result.RowsAffected), nil
|
||||||
|
}
|
||||||
|
|
||||||
// EditStatus implements vqd.VqdAlarmStorer.
|
// EditStatus implements vqd.VqdAlarmStorer.
|
||||||
func (d VqdAlarm) EditStatus(status int, id int) error {
|
func (d VqdAlarm) EditStatus(status int, id int) error {
|
||||||
if err := d.db.Model(&vqd.VqdAlarm{}).Where(`id = ?`, id).Update("task_status", status).Error; err != nil {
|
if err := d.db.Model(&vqd.VqdAlarm{}).Where(`id = ?`, id).Update("task_status", status).Error; err != nil {
|
||||||
|
|||||||
@ -55,3 +55,6 @@ func (d VqdTaskTemplate) EditStatus(status vqd.EncodeStatus, id int) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (d VqdTaskTemplate) FirstOrCreate(b any) error {
|
||||||
|
return d.db.FirstOrCreate(b).Error
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"git.lnton.com/lnton/pkg/reason"
|
"git.lnton.com/lnton/pkg/reason"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VqdAlarmStorer Instantiation interface
|
// VqdAlarmStorer Instantiation interface
|
||||||
@ -17,6 +18,7 @@ type VqdAlarmStorer interface {
|
|||||||
Add(context.Context, *VqdAlarm) error
|
Add(context.Context, *VqdAlarm) error
|
||||||
Edit(context.Context, *VqdAlarm, func(*VqdAlarm), ...orm.QueryOption) error
|
Edit(context.Context, *VqdAlarm, func(*VqdAlarm), ...orm.QueryOption) error
|
||||||
Del(context.Context, *VqdAlarm, ...orm.QueryOption) error
|
Del(context.Context, *VqdAlarm, ...orm.QueryOption) error
|
||||||
|
DelAll(expireTime time.Time, batchSize int) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindVqdAlarmAll Paginated search
|
// FindVqdAlarmAll Paginated search
|
||||||
@ -113,3 +115,8 @@ func (c Core) DelVqdAlarmAll(ctx context.Context, ids []int) (*VqdAlarm, error)
|
|||||||
}
|
}
|
||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelVqdTaskAlarmAll Delete object
|
||||||
|
func (c Core) DelVqdTaskAlarmAll(expireTime time.Time, batchSize int) (int, error) {
|
||||||
|
return c.store.VqdAlarm().DelAll(expireTime, batchSize)
|
||||||
|
}
|
||||||
|
|||||||
@ -52,6 +52,18 @@ func (c Core) FindVqdTask(ctx context.Context, in *FindVqdTaskInput) ([]*VqdTask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindVqdTaskTemplateID Query a single object
|
||||||
|
func (c Core) FindVqdTaskTemplateID(ctx context.Context, id int) (*VqdTask, error) {
|
||||||
|
var out VqdTask
|
||||||
|
if err := c.store.VqdTask().Get(ctx, &out, orm.Where("task_template_id=?", id)); err != nil {
|
||||||
|
if orm.IsErrRecordNotFound(err) {
|
||||||
|
return nil, reason.ErrNotFound.Withf(`Get err[%s]`, err.Error())
|
||||||
|
}
|
||||||
|
return nil, reason.ErrDB.Withf(`Get err[%s]`, err.Error())
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetVqdTask Query a single object
|
// GetVqdTask Query a single object
|
||||||
func (c Core) GetVqdTask(ctx context.Context, id int) (*VqdTask, error) {
|
func (c Core) GetVqdTask(ctx context.Context, id int) (*VqdTask, error) {
|
||||||
var out VqdTask
|
var out VqdTask
|
||||||
@ -63,6 +75,7 @@ func (c Core) GetVqdTask(ctx context.Context, id int) (*VqdTask, error) {
|
|||||||
}
|
}
|
||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Core) GetNameVqdTask(ctx context.Context, name string) (*VqdTask, error) {
|
func (c Core) GetNameVqdTask(ctx context.Context, name string) (*VqdTask, error) {
|
||||||
var out VqdTask
|
var out VqdTask
|
||||||
if err := c.store.VqdTask().Get(ctx, &out, orm.Where("name=?", name)); err != nil {
|
if err := c.store.VqdTask().Get(ctx, &out, orm.Where("name=?", name)); err != nil {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ type EditVqdTaskInput struct {
|
|||||||
Name string `json:"name"` // 名称
|
Name string `json:"name"` // 名称
|
||||||
ChannelID string `json:"channel_id"` // 关联通道
|
ChannelID string `json:"channel_id"` // 关联通道
|
||||||
ChannelName string `json:"channel_name"` // 通道名称
|
ChannelName string `json:"channel_name"` // 通道名称
|
||||||
TaskTemplateID string `json:"task_template_id"` // 关联模板
|
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
||||||
Enable bool `form:"enable"` // 启用
|
Enable bool `form:"enable"` // 启用
|
||||||
Des string `json:"des"` // 描述
|
Des string `json:"des"` // 描述
|
||||||
@ -24,7 +24,7 @@ type AddVqdTaskInput struct {
|
|||||||
Name string `json:"name"` // 名称
|
Name string `json:"name"` // 名称
|
||||||
ChannelID string `json:"channel_id"` // 关联通道
|
ChannelID string `json:"channel_id"` // 关联通道
|
||||||
ChannelName string `json:"channel_name"` // 通道名称
|
ChannelName string `json:"channel_name"` // 通道名称
|
||||||
TaskTemplateID string `json:"task_template_id"` // 关联模板
|
TaskTemplateID int `json:"task_template_id"` // 关联模板
|
||||||
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
TaskTemplateName string `json:"task_template_name"` // 模板名称
|
||||||
Enable bool `form:"enable"` // 启用
|
Enable bool `form:"enable"` // 启用
|
||||||
Des string `json:"des"` // 描述
|
Des string `json:"des"` // 描述
|
||||||
|
|||||||
@ -17,6 +17,8 @@ type VqdTaskTemplateStorer interface {
|
|||||||
Add(context.Context, *VqdTaskTemplate) error
|
Add(context.Context, *VqdTaskTemplate) error
|
||||||
Edit(context.Context, *VqdTaskTemplate, func(*VqdTaskTemplate), ...orm.QueryOption) error
|
Edit(context.Context, *VqdTaskTemplate, func(*VqdTaskTemplate), ...orm.QueryOption) error
|
||||||
Del(context.Context, *VqdTaskTemplate, ...orm.QueryOption) error
|
Del(context.Context, *VqdTaskTemplate, ...orm.QueryOption) error
|
||||||
|
|
||||||
|
FirstOrCreate(b any) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindVqdTaskTemplateAll Paginated search
|
// FindVqdTaskTemplateAll Paginated search
|
||||||
@ -33,16 +35,14 @@ func (c Core) FindVqdTaskTemplateAll() ([]*VqdTaskTemplate, int64, error) {
|
|||||||
func (c Core) FindVqdTaskTemplate(ctx context.Context, in *FindVqdTaskTemplateInput) ([]*VqdTaskTemplate, int64, error) {
|
func (c Core) FindVqdTaskTemplate(ctx context.Context, in *FindVqdTaskTemplateInput) ([]*VqdTaskTemplate, int64, error) {
|
||||||
items := make([]*VqdTaskTemplate, 0)
|
items := make([]*VqdTaskTemplate, 0)
|
||||||
if in.Name != "" {
|
if in.Name != "" {
|
||||||
query := orm.NewQuery(8).
|
query := orm.NewQuery(8).Where("name like ? ", "%"+in.Name+"%")
|
||||||
Where("name like ? ", "%"+in.Name+"%").OrderBy("created_at DESC")
|
|
||||||
total, err := c.store.VqdTaskTemplate().Find(ctx, &items, in, query.Encode()...)
|
total, err := c.store.VqdTaskTemplate().Find(ctx, &items, in, query.Encode()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error())
|
return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error())
|
||||||
}
|
}
|
||||||
return items, total, nil
|
return items, total, nil
|
||||||
} else {
|
} else {
|
||||||
query := orm.NewQuery(2).OrderBy("created_at DESC")
|
total, err := c.store.VqdTaskTemplate().Find(ctx, &items, in)
|
||||||
total, err := c.store.VqdTaskTemplate().Find(ctx, &items, in, query.Encode()...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error())
|
return nil, 0, reason.ErrDB.Withf(`Find err[%s]`, err.Error())
|
||||||
}
|
}
|
||||||
@ -61,6 +61,16 @@ func (c Core) GetVqdTaskTemplate(ctx context.Context, id int) (*VqdTaskTemplate,
|
|||||||
}
|
}
|
||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
func (c Core) GetIDVqdTaskTemplate(ctx context.Context, ID int64) (*VqdTaskTemplate, error) {
|
||||||
|
var out VqdTaskTemplate
|
||||||
|
if err := c.store.VqdTaskTemplate().Get(ctx, &out, orm.Where("id=?", ID)); err != nil {
|
||||||
|
if orm.IsErrRecordNotFound(err) {
|
||||||
|
return nil, reason.ErrNotFound.Withf(`Get err[%s]`, err.Error())
|
||||||
|
}
|
||||||
|
return nil, reason.ErrDB.Withf(`Get err[%s]`, err.Error())
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTaskTemplate, error) {
|
func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTaskTemplate, error) {
|
||||||
var out VqdTaskTemplate
|
var out VqdTaskTemplate
|
||||||
if err := c.store.VqdTaskTemplate().Get(ctx, &out, orm.Where("name=?", name)); err != nil {
|
if err := c.store.VqdTaskTemplate().Get(ctx, &out, orm.Where("name=?", name)); err != nil {
|
||||||
@ -72,6 +82,11 @@ func (c Core) GetNameVqdTaskTemplate(ctx context.Context, name string) (*VqdTask
|
|||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FirstOrCreateTemplate Insert into database
|
||||||
|
func (c Core) FirstOrCreateTemplate(b any) error {
|
||||||
|
return c.store.VqdTaskTemplate().FirstOrCreate(b)
|
||||||
|
}
|
||||||
|
|
||||||
// AddVqdTaskTemplate Insert into database
|
// AddVqdTaskTemplate Insert into database
|
||||||
func (c Core) AddVqdTaskTemplate(ctx context.Context, in *AddVqdTaskTemplateInput) (*VqdTaskTemplate, error) {
|
func (c Core) AddVqdTaskTemplate(ctx context.Context, in *AddVqdTaskTemplateInput) (*VqdTaskTemplate, error) {
|
||||||
var out VqdTaskTemplate
|
var out VqdTaskTemplate
|
||||||
|
|||||||
@ -14,18 +14,18 @@ type EditVqdTaskTemplateInput struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Plans string `json:"plans"`
|
Plans string `json:"plans"`
|
||||||
Enable bool `json:"enable"`
|
Enable bool `json:"enable"`
|
||||||
//VqdConfig VqdConfig `json:"vqd_config"` // 诊断基础配置
|
VqdConfig VqdConfig `json:"vqd_config"` // 诊断基础配置
|
||||||
//VqdLgtDark VqdLgtDark `json:"vqd_lgt_dark"` // 亮度检测
|
VqdLgtDark VqdLgtDark `json:"vqd_lgt_dark"` // 亮度检测
|
||||||
//VqdBlue VqdBlue `json:"vqd_blue"` // 蓝屏检查
|
VqdBlue VqdBlue `json:"vqd_blue"` // 蓝屏检查
|
||||||
//VqdClarity VqdClarity `json:"vqd_clarity"` // 清晰度检查
|
VqdClarity VqdClarity `json:"vqd_clarity"` // 清晰度检查
|
||||||
//VqdShark VqdShark `json:"vqd_shark"` // 抖动检查
|
VqdShark VqdShark `json:"vqd_shark"` // 抖动检查
|
||||||
//VqdFreeze VqdFreeze `json:"vqd_freeze"` // 冻结检测
|
VqdFreeze VqdFreeze `json:"vqd_freeze"` // 冻结检测
|
||||||
//VqdColor VqdColor `json:"vqd_color"` // 偏色检测
|
VqdColor VqdColor `json:"vqd_color"` // 偏色检测
|
||||||
//VqdOcclusion VqdOcclusion `json:"vqd_occlusion"` // 遮挡检测
|
VqdOcclusion VqdOcclusion `json:"vqd_occlusion"` // 遮挡检测
|
||||||
//VqdNoise VqdNoise `json:"vqd_noise"` // 噪声检测
|
VqdNoise VqdNoise `json:"vqd_noise"` // 噪声检测
|
||||||
//VqdContrast VqdContrast `json:"vqd_contrast"` // 对比度检测
|
VqdContrast VqdContrast `json:"vqd_contrast"` // 对比度检测
|
||||||
//VqdMosaic VqdMosaic `json:"vqd_mosaic"` // 马赛克检测
|
VqdMosaic VqdMosaic `json:"vqd_mosaic"` // 马赛克检测
|
||||||
//VqdFlower VqdFlower `json:"vqd_flower"` // 花屏检测
|
VqdFlower VqdFlower `json:"vqd_flower"` // 花屏检测
|
||||||
Des string ` json:"des"` // 描述
|
Des string ` json:"des"` // 描述
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,17 +33,17 @@ type AddVqdTaskTemplateInput struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Plans string `json:"plans"`
|
Plans string `json:"plans"`
|
||||||
Enable bool `json:"enable"`
|
Enable bool `json:"enable"`
|
||||||
//VqdConfig VqdConfig `json:"vqd_config"` // 诊断基础配置
|
VqdConfig VqdConfig `json:"vqd_config"` // 诊断基础配置
|
||||||
//VqdLgtDark VqdLgtDark `json:"vqd_lgt_dark"` // 亮度检测
|
VqdLgtDark VqdLgtDark `json:"vqd_lgt_dark"` // 亮度检测
|
||||||
//VqdBlue VqdBlue `json:"vqd_blue"` // 蓝屏检查
|
VqdBlue VqdBlue `json:"vqd_blue"` // 蓝屏检查
|
||||||
//VqdClarity VqdClarity `json:"vqd_clarity"` // 清晰度检查
|
VqdClarity VqdClarity `json:"vqd_clarity"` // 清晰度检查
|
||||||
//VqdShark VqdShark `json:"vqd_shark"` // 抖动检查
|
VqdShark VqdShark `json:"vqd_shark"` // 抖动检查
|
||||||
//VqdFreeze VqdFreeze `json:"vqd_freeze"` // 冻结检测
|
VqdFreeze VqdFreeze `json:"vqd_freeze"` // 冻结检测
|
||||||
//VqdColor VqdColor `json:"vqd_color"` // 偏色检测
|
VqdColor VqdColor `json:"vqd_color"` // 偏色检测
|
||||||
//VqdOcclusion VqdOcclusion `json:"vqd_occlusion"` // 遮挡检测
|
VqdOcclusion VqdOcclusion `json:"vqd_occlusion"` // 遮挡检测
|
||||||
//VqdNoise VqdNoise `json:"vqd_noise"` // 噪声检测
|
VqdNoise VqdNoise `json:"vqd_noise"` // 噪声检测
|
||||||
//VqdContrast VqdContrast `json:"vqd_contrast"` // 对比度检测
|
VqdContrast VqdContrast `json:"vqd_contrast"` // 对比度检测
|
||||||
//VqdMosaic VqdMosaic `json:"vqd_mosaic"` // 马赛克检测
|
VqdMosaic VqdMosaic `json:"vqd_mosaic"` // 马赛克检测
|
||||||
//VqdFlower VqdFlower `json:"vqd_flower"` // 花屏检测
|
VqdFlower VqdFlower `json:"vqd_flower"` // 花屏检测
|
||||||
Des string ` json:"des"` // 描述
|
Des string ` json:"des"` // 描述
|
||||||
}
|
}
|
||||||
|
|||||||
227
internal/core/vqdsdk/clean.go
Normal file
227
internal/core/vqdsdk/clean.go
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
package vqdsdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 配置参数
|
||||||
|
const (
|
||||||
|
// 要清理的目标目录(请替换为你实际的目录路径)
|
||||||
|
cleanDir = "/snap"
|
||||||
|
// 定时任务执行间隔(每天执行一次)
|
||||||
|
interval = 24 * time.Hour
|
||||||
|
// 批量删除大小(避免单次删除过多锁表)
|
||||||
|
batchSize = 1000
|
||||||
|
// 日期目录的格式(如 20260117)
|
||||||
|
dateDirLayout = "20060102"
|
||||||
|
// 定时任务首次执行时间(每天凌晨1点)
|
||||||
|
executeHour = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// scheduleCleanFile 定时执行清理任务
|
||||||
|
func (c Core) scheduleCleanTask() {
|
||||||
|
// 计算首次执行时间(今天/明天的凌晨1点)
|
||||||
|
now := time.Now()
|
||||||
|
nextExec := time.Date(now.Year(), now.Month(), now.Day(), executeHour, 0, 0, 0, now.Location())
|
||||||
|
if nextExec.Before(now) {
|
||||||
|
nextExec = nextExec.Add(24 * time.Hour)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算首次执行的等待时间
|
||||||
|
initialDelay := nextExec.Sub(now)
|
||||||
|
slog.Info(fmt.Sprintf("定时任务已启动,首次执行时间:%s(等待 %v)", nextExec.Format(time.RFC3339), initialDelay))
|
||||||
|
|
||||||
|
// 首次执行等待
|
||||||
|
time.Sleep(initialDelay)
|
||||||
|
|
||||||
|
// 执行首次清理
|
||||||
|
if err := c.cleanExpiredFiles(); err != nil {
|
||||||
|
slog.Error("首次清理任务执行失败 Files", "err", err)
|
||||||
|
}
|
||||||
|
time.Sleep(20 * time.Minute)
|
||||||
|
if err := c.cleanExpiredDbs(); err != nil {
|
||||||
|
slog.Error("首次清理任务执行失败 Dbs", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环执行定时任务
|
||||||
|
ticker := time.NewTicker(interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
if err := c.cleanExpiredFiles(); err != nil {
|
||||||
|
slog.Error("定时清理任务执行失败 Files", "err", err)
|
||||||
|
}
|
||||||
|
time.Sleep(20 * time.Minute)
|
||||||
|
if err := c.cleanExpiredDbs(); err != nil {
|
||||||
|
slog.Error("定时清理任务执行失败 Dbs", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanExpiredDbs 清理超过expireDays天的数据
|
||||||
|
func (c Core) cleanExpiredDbs() error {
|
||||||
|
// 计算过期时间阈值
|
||||||
|
expireDays := time.Duration(c.Cfg.VqdConfig.SaveDay)
|
||||||
|
if expireDays < 1 {
|
||||||
|
expireDays = 1
|
||||||
|
}
|
||||||
|
expireTime := time.Now().Add(-expireDays * 24 * time.Hour)
|
||||||
|
slog.Info(fmt.Sprintf("开始清理中超过 %d 天的数据,过期时间阈值:%s", expireDays, expireTime.Format(time.RFC3339)))
|
||||||
|
|
||||||
|
totalDeleted := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
deletedCount, err := c.VqdTaskCore.DelVqdTaskAlarmAll(expireTime, batchSize)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("数据清理失败", "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 获取本次删除的行数
|
||||||
|
totalDeleted += deletedCount
|
||||||
|
|
||||||
|
// 无更多数据则退出循环
|
||||||
|
if deletedCount < batchSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量删除间隔,降低数据库压力
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
slog.Info("本次数据清理任务执行完成")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteDirContents 删除目录下的所有文件(保留目录结构,仅删文件)
|
||||||
|
func deleteTaskDirContents(dir string, expireTime time.Time) error {
|
||||||
|
// 遍历目录
|
||||||
|
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
// 处理遍历过程中的错误(如权限问题)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("访问路径失败", "path", path, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 只处理目录(跳过文件)
|
||||||
|
if !d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 获取当前目录的名称(如 20260117)
|
||||||
|
dirName := filepath.Base(path)
|
||||||
|
dirDate, err := time.Parse(dateDirLayout, dirName)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("解析目录日期失败", "path", path, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 判断日期目录是否早于阈值(即过期)
|
||||||
|
isExpired := dirDate.Before(expireTime)
|
||||||
|
|
||||||
|
// 非日期目录,继续遍历子目录
|
||||||
|
if dirDate.IsZero() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期目录未过期,跳过
|
||||||
|
if !isExpired {
|
||||||
|
slog.Error("目录日期未过期跳过", "path", path, "dirDate", dirDate.Format(dateDirLayout))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过期日期目录:先删除目录内所有文件
|
||||||
|
slog.Error("目录已过期开始清理其中文件", "path", path, "dirDate", dirDate.Format(dateDirLayout))
|
||||||
|
if err := deleteDirContents(path, expireTime); err != nil {
|
||||||
|
slog.Error("清理目录内容失败", "path", path, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除空的日期目录
|
||||||
|
if err := os.Remove(path); err != nil {
|
||||||
|
slog.Error("删除空目录失败(可能非空)", "path", path, "err", err)
|
||||||
|
} else {
|
||||||
|
slog.Info("成功删除过期目录", "path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳过已删除目录的子目录遍历(避免无效操作)
|
||||||
|
return fs.SkipDir
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("遍历目录失败", "dir", dir, "err", err)
|
||||||
|
return fmt.Errorf("遍历目录 [%s] 失败:%w", dir, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func deleteDirContents(dir string, expireTime time.Time) error {
|
||||||
|
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("访问路径失败", "path", path, "err", err)
|
||||||
|
return nil // 跳过错误路径,继续处理
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只删除文件,跳过目录
|
||||||
|
if !d.IsDir() {
|
||||||
|
// 获取文件信息(包含修改时间)
|
||||||
|
fileInfo, err := d.Info()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("获取文件失败", "path", path, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 判断文件是否过期
|
||||||
|
if fileInfo.ModTime().Before(expireTime) {
|
||||||
|
// 删除过期文件
|
||||||
|
if errs := os.Remove(path); errs != nil {
|
||||||
|
slog.Error("删除文件失败", "path", path, "err", err)
|
||||||
|
} else {
|
||||||
|
slog.Info("成功删除文件", "path", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("遍历目录 [%s] 失败:%w", dir, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanExpiredFiles 清理指定目录下超过expireDays天未修改的文件
|
||||||
|
func (c Core) cleanExpiredFiles() error {
|
||||||
|
// 计算过期时间阈值
|
||||||
|
expireDays := time.Duration(c.Cfg.VqdConfig.SaveDay)
|
||||||
|
if expireDays < 1 {
|
||||||
|
expireDays = 1
|
||||||
|
}
|
||||||
|
expireTime := time.Now().Add(-expireDays * 24 * time.Hour)
|
||||||
|
slog.Info(fmt.Sprintf("开始清理目录 [%s] 中超过 %d 天的文件,过期时间阈值:%s", cleanDir, expireDays, expireTime.Format(time.RFC3339)))
|
||||||
|
|
||||||
|
dir, _ := os.Getwd()
|
||||||
|
rootDir := filepath.Join(dir, cleanDir)
|
||||||
|
dateDirs, err := os.ReadDir(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("访问根目录路径失败", "path", rootDir, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, d := range dateDirs {
|
||||||
|
// 只处理目录(跳过文件)
|
||||||
|
if !d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
path := filepath.Join(rootDir, d.Name())
|
||||||
|
if err := deleteTaskDirContents(path, expireTime); err != nil {
|
||||||
|
slog.Error("清理目录内容失败", "path", path, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 删除空的日期目录
|
||||||
|
if err := os.Remove(path); err != nil {
|
||||||
|
slog.Error("删除空目录失败(可能非空)", "path", path, "err", err)
|
||||||
|
} else {
|
||||||
|
slog.Info("成功删除过期目录", "path", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info("本次文件清理任务执行完成")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package vqdsdk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"easyvqd/internal/conf"
|
||||||
"easyvqd/internal/core/host"
|
"easyvqd/internal/core/host"
|
||||||
"easyvqd/internal/core/vqd"
|
"easyvqd/internal/core/vqd"
|
||||||
"time"
|
"time"
|
||||||
@ -10,14 +11,14 @@ import (
|
|||||||
type Core struct {
|
type Core struct {
|
||||||
HostCore *host.Core
|
HostCore *host.Core
|
||||||
VqdTaskCore *vqd.Core
|
VqdTaskCore *vqd.Core
|
||||||
//WorkflowCore *Workflow
|
Cfg *conf.Bootstrap
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCore(HostCore *host.Core, VqdTaskCore *vqd.Core) *Core {
|
func NewCore(HostCore *host.Core, VqdTaskCore *vqd.Core, Cfg *conf.Bootstrap) *Core {
|
||||||
core := &Core{
|
core := &Core{
|
||||||
HostCore: HostCore,
|
HostCore: HostCore,
|
||||||
VqdTaskCore: VqdTaskCore,
|
VqdTaskCore: VqdTaskCore,
|
||||||
//WorkflowCore: OpenVqdTask(VqdTaskCore),
|
Cfg: Cfg,
|
||||||
}
|
}
|
||||||
time.AfterFunc(time.Duration(5)*time.Second, func() {
|
time.AfterFunc(time.Duration(5)*time.Second, func() {
|
||||||
in := &vqd.AddVqdAlarmInput{
|
in := &vqd.AddVqdAlarmInput{
|
||||||
@ -31,10 +32,13 @@ func NewCore(HostCore *host.Core, VqdTaskCore *vqd.Core) *Core {
|
|||||||
TaskName: "",
|
TaskName: "",
|
||||||
FilePath: "",
|
FilePath: "",
|
||||||
}
|
}
|
||||||
|
for i := 0; i < 40; i++ {
|
||||||
core.VqdTaskCore.AddVqdAlarm(context.TODO(), in)
|
core.VqdTaskCore.AddVqdAlarm(context.TODO(), in)
|
||||||
core.VqdTaskCore.AddVqdAlarm(context.TODO(), in)
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
// 启用定时清理任务
|
||||||
|
core.scheduleCleanTask()
|
||||||
// 启用任务管理器
|
// 启用任务管理器
|
||||||
return core
|
return core
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"easyvqd/internal/core/vqd"
|
||||||
"easyvqd/internal/web/api/static"
|
"easyvqd/internal/web/api/static"
|
||||||
"expvar"
|
"expvar"
|
||||||
|
"git.lnton.com/lnton/pkg/orm"
|
||||||
statics "github.com/gin-contrib/static"
|
statics "github.com/gin-contrib/static"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -24,6 +26,12 @@ import (
|
|||||||
|
|
||||||
var startRuntime = time.Now()
|
var startRuntime = time.Now()
|
||||||
|
|
||||||
|
// recordErr 记录错误
|
||||||
|
func recordErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
func setupRouter(r *gin.Engine, uc *Usecase) {
|
func setupRouter(r *gin.Engine, uc *Usecase) {
|
||||||
r.Use(
|
r.Use(
|
||||||
// 格式化输出到控制台,然后记录到日志
|
// 格式化输出到控制台,然后记录到日志
|
||||||
@ -55,7 +63,9 @@ func setupRouter(r *gin.Engine, uc *Usecase) {
|
|||||||
registerConfig(r, ConfigAPI{uc: uc, cfg: uc.Conf})
|
registerConfig(r, ConfigAPI{uc: uc, cfg: uc.Conf})
|
||||||
RegisterHostAPI(r, uc)
|
RegisterHostAPI(r, uc)
|
||||||
RegisterVqdTask(r, uc.VqdTaskAPI)
|
RegisterVqdTask(r, uc.VqdTaskAPI)
|
||||||
|
if !orm.GetEnabledAutoMigrate() {
|
||||||
|
recordErr(InitTemplate(uc))
|
||||||
|
}
|
||||||
r.NoRoute(func(ctx *gin.Context) {
|
r.NoRoute(func(ctx *gin.Context) {
|
||||||
p := ctx.Request.URL.Path
|
p := ctx.Request.URL.Path
|
||||||
if strings.HasPrefix(p, "/web/") {
|
if strings.HasPrefix(p, "/web/") {
|
||||||
@ -151,6 +161,105 @@ type KV struct {
|
|||||||
Value int64
|
Value int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InitTemplate(uc *Usecase) error {
|
||||||
|
cfg := uc.Conf
|
||||||
|
in := vqd.VqdTaskTemplate{
|
||||||
|
Enable: true,
|
||||||
|
IsDefault: true,
|
||||||
|
VqdConfig: vqd.VqdConfig{
|
||||||
|
Enable: true,
|
||||||
|
FrmNum: cfg.VqdConfig.FrmNum,
|
||||||
|
IsDeepLearn: cfg.VqdConfig.IsDeepLearn,
|
||||||
|
},
|
||||||
|
VqdLgtDark: vqd.VqdLgtDark{
|
||||||
|
Enable: true,
|
||||||
|
DarkThr: cfg.VqdLgtDark.DarkThr,
|
||||||
|
LgtThr: cfg.VqdLgtDark.LgtThr,
|
||||||
|
LgtDarkAbnNumRatio: cfg.VqdLgtDark.LgtDarkAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdBlue: vqd.VqdBlue{
|
||||||
|
Enable: true,
|
||||||
|
BlueThr: cfg.VqdBlue.BlueThr,
|
||||||
|
BlueAbnNumRatio: cfg.VqdBlue.BlueAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdClarity: vqd.VqdClarity{
|
||||||
|
Enable: true,
|
||||||
|
ClarityThr: cfg.VqdClarity.ClarityThr,
|
||||||
|
ClarityAbnNumRatio: cfg.VqdClarity.ClarityAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdShark: vqd.VqdShark{
|
||||||
|
Enable: true,
|
||||||
|
SharkThr: cfg.VqdShark.SharkThr,
|
||||||
|
SharkAbnNumRatio: cfg.VqdShark.SharkAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdFreeze: vqd.VqdFreeze{
|
||||||
|
Enable: true,
|
||||||
|
FreezeThr: cfg.VqdFreeze.FreezeThr,
|
||||||
|
FreezeAbnNumRatio: cfg.VqdFreeze.FreezeAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdColor: vqd.VqdColor{
|
||||||
|
Enable: true,
|
||||||
|
ColorThr: cfg.VqdColor.ColorThr,
|
||||||
|
ColorAbnNumRatio: cfg.VqdColor.ColorAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdOcclusion: vqd.VqdOcclusion{
|
||||||
|
Enable: true,
|
||||||
|
OcclusionThr: cfg.VqdOcclusion.OcclusionThr,
|
||||||
|
OcclusionAbnNumRatio: cfg.VqdOcclusion.OcclusionAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdNoise: vqd.VqdNoise{
|
||||||
|
Enable: true,
|
||||||
|
NoiseThr: cfg.VqdNoise.NoiseThr,
|
||||||
|
NoiseAbnNumRatio: cfg.VqdNoise.NoiseAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdContrast: vqd.VqdContrast{
|
||||||
|
Enable: true,
|
||||||
|
CtraLowThr: cfg.VqdContrast.CtraLowThr,
|
||||||
|
CtraHighThr: cfg.VqdContrast.CtraHighThr,
|
||||||
|
CtraAbnNumRatio: cfg.VqdContrast.CtraAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdMosaic: vqd.VqdMosaic{
|
||||||
|
Enable: true,
|
||||||
|
MosaicThr: cfg.VqdMosaic.MosaicThr,
|
||||||
|
MosaicAbnNumRatio: cfg.VqdMosaic.MosaicAbnNumRatio,
|
||||||
|
},
|
||||||
|
VqdFlower: vqd.VqdFlower{
|
||||||
|
Enable: true,
|
||||||
|
FlowerThr: cfg.VqdFlower.FlowerThr,
|
||||||
|
FlowerAbnNumRatio: cfg.VqdFlower.FlowerAbnNumRatio,
|
||||||
|
MosaicThr: cfg.VqdFlower.MosaicThr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
in.Name = "每天"
|
||||||
|
in.Model.ID = 1
|
||||||
|
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
|
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
in.Des = "每天分析,启用全部分析模块。"
|
||||||
|
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||||
|
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
in.Name = "工作日"
|
||||||
|
in.Model.ID = 2
|
||||||
|
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
|
in.Plans = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000"
|
||||||
|
in.Des = "工作日分析,启用全部分析模块。"
|
||||||
|
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||||
|
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
in.Name = "双休日"
|
||||||
|
in.Model.ID = 3
|
||||||
|
in.Model.CreatedAt = orm.Time{Time: time.Now()}
|
||||||
|
in.Plans = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111"
|
||||||
|
in.Des = "休息日分析,启用全部分析模块。"
|
||||||
|
if err := uc.VqdTaskCore.FirstOrCreateTemplate(&in); err != nil {
|
||||||
|
slog.Error("FirstOrCreateTemplate", "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func sortExpvarMap(data *expvar.Map, top int) []KV {
|
func sortExpvarMap(data *expvar.Map, top int) []KV {
|
||||||
kvs := make([]KV, 0, 8)
|
kvs := make([]KV, 0, 8)
|
||||||
data.Do(func(kv expvar.KeyValue) {
|
data.Do(func(kv expvar.KeyValue) {
|
||||||
|
|||||||
@ -27,26 +27,59 @@ func registerConfig(g gin.IRouter, api ConfigAPI, handler ...gin.HandlerFunc) {
|
|||||||
|
|
||||||
group.GET("/base", web.WarpH(api.getBase))
|
group.GET("/base", web.WarpH(api.getBase))
|
||||||
group.PUT("/base", web.WarpH(api.editBase))
|
group.PUT("/base", web.WarpH(api.editBase))
|
||||||
|
group.GET("/default", web.WarpH(api.getDefaultConfig))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type getBaseOutput conf.VqdConfig
|
type getBaseOutput struct {
|
||||||
type editBaseInput conf.VqdConfig
|
SaveDay int32 `json:"save_day"`
|
||||||
|
}
|
||||||
|
type editBaseInput struct {
|
||||||
|
SaveDay int32 `json:"save_day"`
|
||||||
|
}
|
||||||
|
type getBaseConfigOutput struct {
|
||||||
|
FrmNum int32 `json:"frm_num"`
|
||||||
|
IsDeepLearn bool `json:"is_deep_learn"`
|
||||||
|
VqdLgtDark conf.VqdLgtDark `json:"vqd_lgt_dark"` // 亮度检测
|
||||||
|
VqdBlue conf.VqdBlue `json:"vqd_blue"` // 蓝屏检查
|
||||||
|
VqdClarity conf.VqdClarity `json:"vqd_clarity"` // 清晰度检查
|
||||||
|
VqdShark conf.VqdShark `json:"vqd_shark"` // 抖动检查
|
||||||
|
VqdFreeze conf.VqdFreeze `json:"vqd_freeze"` // 冻结检测
|
||||||
|
VqdColor conf.VqdColor `json:"vqd_color"` // 偏色检测
|
||||||
|
VqdOcclusion conf.VqdOcclusion `json:"vqd_occlusion"` // 遮挡检测
|
||||||
|
VqdNoise conf.VqdNoise `json:"vqd_noise"` // 噪声检测
|
||||||
|
VqdContrast conf.VqdContrast `json:"vqd_contrast"` // 对比度检测
|
||||||
|
VqdMosaic conf.VqdMosaic `json:"vqd_mosaic"` // 马赛克检测
|
||||||
|
VqdFlower conf.VqdFlower `json:"vqd_flower"` // 花屏检测
|
||||||
|
}
|
||||||
|
|
||||||
func (uc *ConfigAPI) editBase(c *gin.Context, in *editBaseInput) (any, error) {
|
func (uc *ConfigAPI) editBase(c *gin.Context, in *editBaseInput) (any, error) {
|
||||||
uc.cfg.VqdConfig.FrmNum = in.FrmNum
|
|
||||||
uc.cfg.VqdConfig.SaveDay = in.SaveDay
|
uc.cfg.VqdConfig.SaveDay = in.SaveDay
|
||||||
uc.cfg.VqdConfig.IsDeepLearn = in.IsDeepLearn
|
|
||||||
conf.WriteConfig(uc.cfg, uc.cfg.ConfigDirPath())
|
conf.WriteConfig(uc.cfg, uc.cfg.ConfigDirPath())
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
func (uc *ConfigAPI) getDefaultConfig(_ *gin.Context, _ *struct{}) (getBaseConfigOutput, error) {
|
||||||
|
return getBaseConfigOutput{
|
||||||
|
FrmNum: uc.cfg.VqdConfig.FrmNum,
|
||||||
|
IsDeepLearn: uc.cfg.VqdConfig.IsDeepLearn,
|
||||||
|
VqdLgtDark: uc.cfg.VqdLgtDark,
|
||||||
|
VqdBlue: uc.cfg.VqdBlue,
|
||||||
|
VqdClarity: uc.cfg.VqdClarity,
|
||||||
|
VqdShark: uc.cfg.VqdShark,
|
||||||
|
VqdFreeze: uc.cfg.VqdFreeze,
|
||||||
|
VqdColor: uc.cfg.VqdColor,
|
||||||
|
VqdOcclusion: uc.cfg.VqdOcclusion,
|
||||||
|
VqdNoise: uc.cfg.VqdNoise,
|
||||||
|
VqdContrast: uc.cfg.VqdContrast,
|
||||||
|
VqdMosaic: uc.cfg.VqdMosaic,
|
||||||
|
VqdFlower: uc.cfg.VqdFlower,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
func (uc *ConfigAPI) getBase(_ *gin.Context, _ *struct{}) (getBaseOutput, error) {
|
func (uc *ConfigAPI) getBase(_ *gin.Context, _ *struct{}) (getBaseOutput, error) {
|
||||||
confMutex.Lock()
|
confMutex.Lock()
|
||||||
defer confMutex.Unlock()
|
defer confMutex.Unlock()
|
||||||
|
|
||||||
return getBaseOutput{
|
return getBaseOutput{
|
||||||
FrmNum: uc.cfg.VqdConfig.FrmNum,
|
|
||||||
IsDeepLearn: uc.cfg.VqdConfig.IsDeepLearn,
|
|
||||||
SaveDay: uc.cfg.VqdConfig.SaveDay,
|
SaveDay: uc.cfg.VqdConfig.SaveDay,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,10 @@ func (a VqdTaskAPI) findVqdTask(c *gin.Context, in *vqd.FindVqdTaskInput) (any,
|
|||||||
row["channel_name"] = item.ChannelName
|
row["channel_name"] = item.ChannelName
|
||||||
row["task_template_id"] = item.TaskTemplateID
|
row["task_template_id"] = item.TaskTemplateID
|
||||||
row["task_template_name"] = item.TaskTemplateName
|
row["task_template_name"] = item.TaskTemplateName
|
||||||
|
template, errs := a.core.GetIDVqdTaskTemplate(c.Request.Context(), item.TaskTemplateID)
|
||||||
|
if errs == nil && template != nil {
|
||||||
|
row["task_template_name"] = template.Name
|
||||||
|
}
|
||||||
row["created_at"] = item.CreatedAt
|
row["created_at"] = item.CreatedAt
|
||||||
row["updated_at"] = item.UpdatedAt
|
row["updated_at"] = item.UpdatedAt
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,19 @@ func (a VqdTaskAPI) findVqdTaskTemplate(c *gin.Context, in *vqd.FindVqdTaskTempl
|
|||||||
row["des"] = item.Des
|
row["des"] = item.Des
|
||||||
row["plans"] = item.Plans
|
row["plans"] = item.Plans
|
||||||
row["enable"] = item.Enable
|
row["enable"] = item.Enable
|
||||||
|
row["is_default"] = item.IsDefault
|
||||||
|
row["vqd_config"] = item.VqdConfig
|
||||||
|
row["vqd_lgt_dark"] = item.VqdLgtDark
|
||||||
|
row["vqd_blue"] = item.VqdBlue
|
||||||
|
row["vqd_clarity"] = item.VqdClarity
|
||||||
|
row["vqd_shark"] = item.VqdShark
|
||||||
|
row["vqd_freeze"] = item.VqdFreeze
|
||||||
|
row["vqd_color"] = item.VqdColor
|
||||||
|
row["vqd_occlusion"] = item.VqdOcclusion
|
||||||
|
row["vqd_noise"] = item.VqdNoise
|
||||||
|
row["vqd_contrast"] = item.VqdContrast
|
||||||
|
row["vqd_mosaic"] = item.VqdMosaic
|
||||||
|
row["vqd_flower"] = item.VqdFlower
|
||||||
row["created_at"] = item.CreatedAt
|
row["created_at"] = item.CreatedAt
|
||||||
row["updated_at"] = item.UpdatedAt
|
row["updated_at"] = item.UpdatedAt
|
||||||
|
|
||||||
@ -38,6 +51,19 @@ func (a VqdTaskAPI) getVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error)
|
|||||||
|
|
||||||
row["id"] = item.ID
|
row["id"] = item.ID
|
||||||
row["name"] = item.Name
|
row["name"] = item.Name
|
||||||
|
row["is_default"] = item.IsDefault
|
||||||
|
row["vqd_config"] = item.VqdConfig
|
||||||
|
row["vqd_lgt_dark"] = item.VqdLgtDark
|
||||||
|
row["vqd_blue"] = item.VqdBlue
|
||||||
|
row["vqd_clarity"] = item.VqdClarity
|
||||||
|
row["vqd_shark"] = item.VqdShark
|
||||||
|
row["vqd_freeze"] = item.VqdFreeze
|
||||||
|
row["vqd_color"] = item.VqdColor
|
||||||
|
row["vqd_occlusion"] = item.VqdOcclusion
|
||||||
|
row["vqd_noise"] = item.VqdNoise
|
||||||
|
row["vqd_contrast"] = item.VqdContrast
|
||||||
|
row["vqd_mosaic"] = item.VqdMosaic
|
||||||
|
row["vqd_flower"] = item.VqdFlower
|
||||||
row["des"] = item.Des
|
row["des"] = item.Des
|
||||||
row["plans"] = item.Plans
|
row["plans"] = item.Plans
|
||||||
row["enable"] = item.Enable
|
row["enable"] = item.Enable
|
||||||
@ -71,7 +97,20 @@ func (a VqdTaskAPI) editVqdTaskTemplate(c *gin.Context, in *vqd.EditVqdTaskTempl
|
|||||||
|
|
||||||
func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) {
|
func (a VqdTaskAPI) delVqdTaskTemplate(c *gin.Context, _ *struct{}) (any, error) {
|
||||||
ID, _ := strconv.Atoi(c.Param("id"))
|
ID, _ := strconv.Atoi(c.Param("id"))
|
||||||
_, err := a.core.DelVqdTaskTemplate(c.Request.Context(), ID)
|
info, err := a.core.GetVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`find vqd [%d] err [%s]`, ID, err.Error()))
|
||||||
|
}
|
||||||
|
if info.IsDefault {
|
||||||
|
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`默认模板不支持删除 [%s] `, info.Name))
|
||||||
|
}
|
||||||
|
templateInfo, err := a.core.FindVqdTaskTemplateID(c.Request.Context(), ID)
|
||||||
|
if err == nil {
|
||||||
|
if templateInfo != nil {
|
||||||
|
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`模板关联【%s】任务,需先清理【%s】任务后才能删除模板!`, templateInfo.Name, templateInfo.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = a.core.DelVqdTaskTemplate(c.Request.Context(), ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error()))
|
return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`del vqd [%d] err [%s]`, ID, err.Error()))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { GET, PUT } from "./http";
|
import { GET, PUT } from "./http";
|
||||||
import type { UpdateConfigBaseReq, VqdConfigBaseDetailRes } from "../types/config";
|
import type { UpdateConfigBaseReq, VqdConfigBaseDetailRes, VqdConfigDefaultDetailRes } from "../types/config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取详情
|
* 获取详情
|
||||||
@ -7,6 +7,12 @@ import type { UpdateConfigBaseReq, VqdConfigBaseDetailRes } from "../types/confi
|
|||||||
export async function GetVqdConfigBase() {
|
export async function GetVqdConfigBase() {
|
||||||
return await GET<VqdConfigBaseDetailRes>(`/configs/base`);
|
return await GET<VqdConfigBaseDetailRes>(`/configs/base`);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取默认详情
|
||||||
|
*/
|
||||||
|
export async function GetVqdConfigDefault() {
|
||||||
|
return await GET<VqdConfigDefaultDetailRes>(`/configs/default`);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新
|
* 更新
|
||||||
|
|||||||
@ -31,6 +31,8 @@ export async function GetVqdTaskTemplateById(id: string) {
|
|||||||
*/
|
*/
|
||||||
export async function UpdateVqdTaskTemplate(data: UpdateVqdTaskTemplateReq) {
|
export async function UpdateVqdTaskTemplate(data: UpdateVqdTaskTemplateReq) {
|
||||||
const { id, ...payload } = data;
|
const { id, ...payload } = data;
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
return await PUT<VqdTaskTemplateBaseRes>(`/template/${id}`, payload);
|
return await PUT<VqdTaskTemplateBaseRes>(`/template/${id}`, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import { forwardRef, useImperativeHandle, useState, useRef } from "react";
|
import { forwardRef, useImperativeHandle, useState, useRef } from "react";
|
||||||
import { Modal, Form, Input, Radio, Button, message, Space } from "antd";
|
import { Modal, Form, Input, Select, Button, message, Space } from "antd";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
import { CreateVqdTask, UpdateVqdTask } from "../api/vqdtask";
|
||||||
|
import { GetVqdTaskTemplate } from "../api/vqdtasktemplate";
|
||||||
import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask";
|
import type { CreateVqdTaskReq, VqdTaskItem } from "../types/vqdtask";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
|
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
||||||
|
|
||||||
interface AddVqdTaskProps {
|
interface AddVqdTaskProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -19,12 +20,15 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
({ title, onSuccess }, ref) => {
|
({ title, onSuccess }, ref) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [editing, setEditing] = useState<boolean>(false);
|
const [editing, setEditing] = useState<boolean>(false);
|
||||||
|
const [channelId, setChannelId] = useState<string>("");
|
||||||
|
const channelRef = useRef<IChannelModelFunc>(null);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
open: (task?: VqdTaskItem) => {
|
open: (task?: VqdTaskItem) => {
|
||||||
if (task) {
|
if (task) {
|
||||||
setEditing(true);
|
setEditing(true);
|
||||||
|
setChannelId(task.channel_id)
|
||||||
const formValues = {
|
const formValues = {
|
||||||
name: task.name,
|
name: task.name,
|
||||||
id: task.id,
|
id: task.id,
|
||||||
@ -45,7 +49,29 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
setOpen(true);
|
setOpen(true);
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
page: 1,
|
||||||
|
size: 999,
|
||||||
|
name: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取任务列表
|
||||||
|
const {
|
||||||
|
data: storageResponse,
|
||||||
|
isLoading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["storage", pagination],
|
||||||
|
queryFn: () =>
|
||||||
|
GetVqdTaskTemplate({ ...pagination })
|
||||||
|
.then((res) => res.data)
|
||||||
|
.catch((err) => {
|
||||||
|
ErrorHandle(err);
|
||||||
|
throw err;
|
||||||
|
}),
|
||||||
|
// refetchInterval: 4000,
|
||||||
|
retry: 1,
|
||||||
|
});
|
||||||
const { mutate: createMutate, isPending: creating } = useMutation({
|
const { mutate: createMutate, isPending: creating } = useMutation({
|
||||||
mutationFn: CreateVqdTask,
|
mutationFn: CreateVqdTask,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@ -69,6 +95,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
|
setChannelId("");
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,7 +103,7 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
<Modal
|
<Modal
|
||||||
style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||||
title={title}
|
title={title}
|
||||||
|
destroyOnHidden={true}
|
||||||
open={open}
|
open={open}
|
||||||
onCancel={handleClose}
|
onCancel={handleClose}
|
||||||
centered
|
centered
|
||||||
@ -134,7 +161,34 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
>
|
>
|
||||||
<Input placeholder="请输入名称" />
|
<Input placeholder="请输入名称" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="channel_id"
|
||||||
|
label="关联通道"
|
||||||
|
rules={[{ required: true, message: "请选择通道" }]}
|
||||||
|
>
|
||||||
|
<Space.Compact style={{ width: '100%' }}>
|
||||||
|
<Input defaultValue="请输入通道" disabled value={channelId} />
|
||||||
|
|
||||||
|
<Button type="primary" onClick={() => {
|
||||||
|
channelRef.current?.openModal(channelId)
|
||||||
|
}}>选择通道</Button>
|
||||||
|
</Space.Compact>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="task_template_id" label="选择模板" rules={[{ required: true, message: "请选择模板" }]}>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择模板"
|
||||||
|
onChange={(res, item: any) => {
|
||||||
|
form.setFieldsValue({ task_template_name: item?.label });
|
||||||
|
}}
|
||||||
|
options={storageResponse?.items
|
||||||
|
.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value !== 0)}
|
||||||
|
></Select>
|
||||||
|
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="des"
|
name="des"
|
||||||
label="描述"
|
label="描述"
|
||||||
@ -146,7 +200,17 @@ const AddVqdTask = forwardRef<AddVqdTaskRef, AddVqdTaskProps>(
|
|||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
|
<Form.Item name="channel_name" hidden>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="task_template_name" hidden>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
<ChannelModel ref={channelRef} onCallback={(id: any, name: any) => {
|
||||||
|
form.setFieldsValue({ channel_id: id, channel_name: name });
|
||||||
|
setChannelId(id)
|
||||||
|
}} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,77 @@
|
|||||||
import { forwardRef, useImperativeHandle, useState, useRef } from "react";
|
import { forwardRef, useImperativeHandle, useState, useRef, createContext, useContext, useEffect } from "react";
|
||||||
import { Modal, Form, Input, Radio, Button, message, Space } from "antd";
|
import { Modal, Form, Input, InputNumber, Button, message, Row, Col, Card, Flex, Switch, Tabs, FormInstance } from "antd";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { CreateVqdTaskTemplate, UpdateVqdTaskTemplate } from "../api/vqdtasktemplate";
|
import { GetVqdConfigDefault } from "../api/config";
|
||||||
|
import { CreateVqdTaskTemplate, UpdateVqdTaskTemplate, } from "../api/vqdtasktemplate";
|
||||||
import type { CreateVqdTaskTemplateReq, VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
import type { CreateVqdTaskTemplateReq, VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
|
|
||||||
|
import type { TabsProps } from 'antd';
|
||||||
|
const week = [
|
||||||
|
'星期一',
|
||||||
|
'星期二',
|
||||||
|
'星期三',
|
||||||
|
'星期四',
|
||||||
|
'星期五',
|
||||||
|
'星期六',
|
||||||
|
'星期日',
|
||||||
|
];
|
||||||
|
|
||||||
|
const hour = [
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
|
22, 23,
|
||||||
|
];
|
||||||
|
|
||||||
|
const gridStyle: React.CSSProperties = {
|
||||||
|
border: '0.1px solid #ccc',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '40px',
|
||||||
|
userSelect: 'none',
|
||||||
|
};
|
||||||
|
const titleStyle: React.CSSProperties = {
|
||||||
|
border: '0.1px solid #ccc',
|
||||||
|
width: '90px',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '40px',
|
||||||
|
userSelect: 'none',
|
||||||
|
};
|
||||||
|
type PlansSpan = {
|
||||||
|
start: string;
|
||||||
|
end: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const emptyList = [
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
Array(24).fill(0),
|
||||||
|
];
|
||||||
interface AddVqdTaskTemplateProps {
|
interface AddVqdTaskTemplateProps {
|
||||||
title: string;
|
title: string;
|
||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
}
|
}
|
||||||
|
interface IAddTemplateContext {
|
||||||
|
editing: boolean;
|
||||||
|
checkList: number[][];
|
||||||
|
form: FormInstance<CreateVqdTaskTemplateReq>;
|
||||||
|
setCheckList: React.Dispatch<React.SetStateAction<number[][]>>;
|
||||||
|
onDelPullDeviceData: (index: number) => void;
|
||||||
|
}
|
||||||
|
const layout = {
|
||||||
|
labelCol: { span: 10 },
|
||||||
|
wrapperCol: { span: 14 },
|
||||||
|
};
|
||||||
|
const AddTemplateContext = createContext<IAddTemplateContext | null>(null);
|
||||||
|
const useAddTemplate = () => {
|
||||||
|
const context = useContext(AddTemplateContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useAddTemplate must be used within a AddTemplateProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
export interface AddVqdTaskTemplateRef {
|
export interface AddVqdTaskTemplateRef {
|
||||||
open: (task?: VqdTaskTemplateItem) => void;
|
open: (task?: VqdTaskTemplateItem) => void;
|
||||||
}
|
}
|
||||||
@ -19,8 +80,81 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
({ title, onSuccess }, ref) => {
|
({ title, onSuccess }, ref) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [editing, setEditing] = useState<boolean>(false);
|
const [editing, setEditing] = useState<boolean>(false);
|
||||||
|
const [checkList, setCheckList] = useState<number[][]>([...emptyList.map((list) => [...list])]);
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
|
|
||||||
|
const arrayToString = (arr: number[][]): string => {
|
||||||
|
return arr.map((subArr) => subArr.join('')).join('');
|
||||||
|
}
|
||||||
|
const parsePlans = (value: string | undefined): number[][] => {
|
||||||
|
const result: number[][] = [];
|
||||||
|
if (!value) return result;
|
||||||
|
const binaryArray: number[] = value.split('').map(Number);
|
||||||
|
while (binaryArray.length) {
|
||||||
|
result.push(binaryArray.splice(0, 24));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const onChange = (key: string) => {
|
||||||
|
console.log(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemsTabs: TabsProps['items'] = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
forceRender: true,
|
||||||
|
label: '诊断参数',
|
||||||
|
children: <TemplateConfig />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
forceRender: true,
|
||||||
|
label: '诊断时间',
|
||||||
|
children: <TemplatePlans />
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const { mutate: getVqdConfigDefault } = useMutation({
|
||||||
|
mutationFn: GetVqdConfigDefault,
|
||||||
|
onSuccess: (res) => {
|
||||||
|
const formValues = {
|
||||||
|
vqd_config: {
|
||||||
|
enable: false,
|
||||||
|
frm_num: res.data.frm_num,
|
||||||
|
is_deep_learn: res.data.is_deep_learn,
|
||||||
|
},
|
||||||
|
enable: true,
|
||||||
|
plans: '',
|
||||||
|
des: '',
|
||||||
|
name: '',
|
||||||
|
vqd_lgt_dark: res.data.vqd_lgt_dark,
|
||||||
|
vqd_blue: res.data.vqd_blue,
|
||||||
|
vqd_clarity: res.data.vqd_clarity,
|
||||||
|
vqd_shark: res.data.vqd_shark,
|
||||||
|
vqd_freeze: res.data.vqd_freeze,
|
||||||
|
vqd_color: res.data.vqd_color,
|
||||||
|
vqd_occlusion: res.data.vqd_occlusion,
|
||||||
|
vqd_noise: res.data.vqd_noise,
|
||||||
|
vqd_contrast: res.data.vqd_contrast,
|
||||||
|
vqd_mosaic: res.data.vqd_mosaic,
|
||||||
|
vqd_flower: res.data.vqd_flower,
|
||||||
|
};
|
||||||
|
formValues.vqd_lgt_dark.enable = false
|
||||||
|
formValues.vqd_blue.enable = false
|
||||||
|
formValues.vqd_clarity.enable = false
|
||||||
|
formValues.vqd_shark.enable = false
|
||||||
|
formValues.vqd_freeze.enable = false
|
||||||
|
formValues.vqd_color.enable = false
|
||||||
|
formValues.vqd_occlusion.enable = false
|
||||||
|
formValues.vqd_noise.enable = false
|
||||||
|
formValues.vqd_contrast.enable = false
|
||||||
|
formValues.vqd_mosaic.enable = false
|
||||||
|
formValues.vqd_flower.enable = false
|
||||||
|
form.setFieldsValue(formValues);
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
open: (task?: VqdTaskTemplateItem) => {
|
open: (task?: VqdTaskTemplateItem) => {
|
||||||
if (task) {
|
if (task) {
|
||||||
@ -30,14 +164,29 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
id: task.id,
|
id: task.id,
|
||||||
plans: task.plans,
|
plans: task.plans,
|
||||||
enable: task.enable,
|
enable: task.enable,
|
||||||
|
des: task.des,
|
||||||
|
vqd_config: task.vqd_config,
|
||||||
|
vqd_lgt_dark: task.vqd_lgt_dark,
|
||||||
|
vqd_blue: task.vqd_blue,
|
||||||
|
vqd_clarity: task.vqd_clarity,
|
||||||
|
vqd_shark: task.vqd_shark,
|
||||||
|
vqd_freeze: task.vqd_freeze,
|
||||||
|
vqd_color: task.vqd_color,
|
||||||
|
vqd_occlusion: task.vqd_occlusion,
|
||||||
|
vqd_noise: task.vqd_noise,
|
||||||
|
vqd_contrast: task.vqd_contrast,
|
||||||
|
vqd_mosaic: task.vqd_mosaic,
|
||||||
|
vqd_flower: task.vqd_flower,
|
||||||
};
|
};
|
||||||
|
setCheckList(parsePlans(task.plans))
|
||||||
form.setFieldsValue(formValues);
|
form.setFieldsValue(formValues);
|
||||||
} else {
|
} else {
|
||||||
|
getVqdConfigDefault()
|
||||||
setEditing(false);
|
setEditing(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
// form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
// bid: "2",
|
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
},
|
},
|
||||||
@ -68,44 +217,38 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
setEditing(false);
|
setEditing(false);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
};
|
};
|
||||||
|
const onDelPullDeviceData = (index: number) => {
|
||||||
|
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
|
<AddTemplateContext.Provider
|
||||||
|
value={{
|
||||||
|
form,
|
||||||
|
checkList,
|
||||||
|
editing,
|
||||||
|
setCheckList,
|
||||||
|
onDelPullDeviceData
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Modal
|
<Modal
|
||||||
style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
// style={{ top: '-180px' }} // 距离顶部 80px(可改为 10% 等百分比)
|
||||||
title={title}
|
title={title}
|
||||||
|
width={"64%"}
|
||||||
open={open}
|
open={open}
|
||||||
onCancel={handleClose}
|
onCancel={handleClose}
|
||||||
|
destroyOnHidden={true}
|
||||||
centered
|
centered
|
||||||
onOk={() => form.submit()}
|
onOk={() => form.submit()}
|
||||||
confirmLoading={creating || updating}
|
confirmLoading={creating || updating}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
{...layout}
|
||||||
onFinish={(values) => {
|
onFinish={(values: CreateVqdTaskTemplateReq) => {
|
||||||
if (creating || updating) return
|
if (creating || updating) return
|
||||||
console.log(values);
|
const payload = values as CreateVqdTaskTemplateReq;
|
||||||
|
payload.plans = arrayToString(checkList)
|
||||||
const {
|
console.log(payload);
|
||||||
name,
|
|
||||||
des,
|
|
||||||
plans,
|
|
||||||
enable } = values as {
|
|
||||||
name: string;
|
|
||||||
des: string;
|
|
||||||
id?: number;
|
|
||||||
plans: string;
|
|
||||||
|
|
||||||
enable: boolean;
|
|
||||||
};
|
|
||||||
const payload: CreateVqdTaskTemplateReq = {
|
|
||||||
name,
|
|
||||||
des,
|
|
||||||
plans,
|
|
||||||
enable,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (editing) {
|
if (editing) {
|
||||||
const id = (values as any).id;
|
const id = (values as any).id;
|
||||||
updateMutate({ id: String(id), ...payload });
|
updateMutate({ id: String(id), ...payload });
|
||||||
@ -114,22 +257,37 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<br />
|
||||||
|
<Flex gap="large" >
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
style={{ width: '30%' }}
|
||||||
name="name"
|
name="name"
|
||||||
label="名称"
|
label="模板名称"
|
||||||
rules={[{ required: true, message: "请输入名称" }]}
|
rules={[{ required: true, message: "请输入模板名称" }]}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入名称" />
|
<Input placeholder="请输入名称" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
style={{ width: '30%' }}
|
||||||
name="des"
|
name="des"
|
||||||
label="描述"
|
label="描述"
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入描述" />
|
<Input placeholder="请输入描述" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
style={{ width: '20%' }}
|
||||||
|
name="enable"
|
||||||
|
label="启用"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Tabs defaultActiveKey="1" items={itemsTabs} onChange={onChange} />
|
||||||
|
|
||||||
|
|
||||||
{editing && (
|
{editing && (
|
||||||
<Form.Item name="id" hidden>
|
<Form.Item name="id" hidden>
|
||||||
<Input />
|
<Input />
|
||||||
@ -137,8 +295,393 @@ const AddVqdTaskTemplate = forwardRef<AddVqdTaskTemplateRef, AddVqdTaskTemplateP
|
|||||||
)}
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
</AddTemplateContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default AddVqdTaskTemplate;
|
export default AddVqdTaskTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const TemplatePlans: React.FC = () => {
|
||||||
|
const {
|
||||||
|
checkList,
|
||||||
|
editing,
|
||||||
|
setCheckList,
|
||||||
|
form,
|
||||||
|
} = useAddTemplate();
|
||||||
|
// 开始滑动选择
|
||||||
|
const [config, setConfig] = useState<{
|
||||||
|
start: boolean;
|
||||||
|
}>({ start: false });
|
||||||
|
|
||||||
|
const selector = useRef<boolean>(true);
|
||||||
|
|
||||||
|
const [coping, setCoping] = useState<
|
||||||
|
{ index: number; value: number[] } | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
const handler = (list: number[]) => {
|
||||||
|
let out: PlansSpan[] = [];
|
||||||
|
let start = false;
|
||||||
|
let timeParam: PlansSpan = { start: '', end: '' };
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
const v = list[i];
|
||||||
|
|
||||||
|
let s = i.toString().padStart(2, '0');
|
||||||
|
if (i == 23 && v == 1) {
|
||||||
|
s = '24';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!start && v == 1) {
|
||||||
|
start = true;
|
||||||
|
timeParam = { start: `${i}:00`, end: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start && (v == 0 || i == list.length - 1)) {
|
||||||
|
start = false;
|
||||||
|
timeParam.end = `${s}:00`;
|
||||||
|
out.push(timeParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div style={{ border: '1px solid #999' }}>
|
||||||
|
<Row wrap={false}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...titleStyle,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Week/Time
|
||||||
|
</div>
|
||||||
|
<Row wrap={false} style={{ width: '86.5%' }}>
|
||||||
|
{[...hour].map((v, idx) => {
|
||||||
|
return (
|
||||||
|
<Col key={v} span={1} style={gridStyle}>
|
||||||
|
{v}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
{week.map((v, weekIdx) => {
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
key={v}
|
||||||
|
onMouseDown={() => setConfig({ ...config, start: true })}
|
||||||
|
onMouseUp={() => setConfig({ ...config, start: false })}
|
||||||
|
wrap={false}
|
||||||
|
>
|
||||||
|
<div style={titleStyle}>{v}</div>
|
||||||
|
<Row key={v + '1'} wrap={false} style={{ width: '86.5%' }}>
|
||||||
|
{[...hour].map((v, hourIdx) => {
|
||||||
|
// 时间选择
|
||||||
|
return (
|
||||||
|
<Col
|
||||||
|
onMouseOver={() => {
|
||||||
|
if (!config.start) return;
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onMouseDown={() => {
|
||||||
|
selector.current = checkList[weekIdx][hourIdx] == 0;
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx][hourIdx] = selector.current ? 1 : 0;
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
key={v}
|
||||||
|
span={1}
|
||||||
|
style={{
|
||||||
|
...gridStyle,
|
||||||
|
backgroundColor:
|
||||||
|
checkList[weekIdx][hourIdx] == 1
|
||||||
|
? '#658EE0'
|
||||||
|
: 'white',
|
||||||
|
}}
|
||||||
|
></Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
margin: 'auto',
|
||||||
|
marginLeft: '2px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type={coping?.index == weekIdx ? 'primary' : 'default'}
|
||||||
|
size="small"
|
||||||
|
style={{ padding: '1px 5px', fontSize: '12px' }}
|
||||||
|
onClick={() => {
|
||||||
|
if (!coping) {
|
||||||
|
setCoping({
|
||||||
|
index: weekIdx,
|
||||||
|
value: checkList[weekIdx],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCheckList((v) => {
|
||||||
|
let list = [...v];
|
||||||
|
list[weekIdx] = [...coping.value];
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
setCoping(undefined);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!coping || coping?.index == weekIdx ? "复制" : "粘贴"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ height: '20px' }}></div>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<div>
|
||||||
|
<span>时间段</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{week.map((v, weekIdx) => {
|
||||||
|
return (
|
||||||
|
// 周
|
||||||
|
<Row wrap={false} key={v}>
|
||||||
|
<div style={{ color: '#9A9A9A', paddingRight: '5px' }}>
|
||||||
|
<span>{v}</span> :
|
||||||
|
</div>
|
||||||
|
<Row wrap={false}>
|
||||||
|
{handler(checkList[weekIdx]).map((v, idx, arr) => {
|
||||||
|
// 已选时间段
|
||||||
|
return (
|
||||||
|
<Col key={`${v.start}~${v.end}_${idx}_${weekIdx}`}>
|
||||||
|
{`${v.start}~${v.end}` +
|
||||||
|
(idx < arr.length - 1 ? ',' : '')}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
const BoxInputNumber: React.FC<{
|
||||||
|
parent: string;
|
||||||
|
children: string;
|
||||||
|
defaultValue: number
|
||||||
|
labelName: string;
|
||||||
|
}> = ({ parent, children, defaultValue, labelName }) => {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
className="mb-1"
|
||||||
|
name={[parent, children]}
|
||||||
|
label={labelName}
|
||||||
|
normalize={(value) => {
|
||||||
|
return value ? parseFloat(value) : defaultValue;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
size="small"
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
step={0.1}
|
||||||
|
stringMode
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const TemplateConfig: React.FC = () => {
|
||||||
|
const {
|
||||||
|
editing,
|
||||||
|
form,
|
||||||
|
} = useAddTemplate();
|
||||||
|
|
||||||
|
const handleValuesChange = (value: string) => {
|
||||||
|
if (value) {
|
||||||
|
// form.setFieldsValue({ });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return <>
|
||||||
|
<Flex gap="large" wrap justify="space-between">
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade" >
|
||||||
|
<h4>基础配置</h4>
|
||||||
|
<Form.Item
|
||||||
|
className="mb-0"
|
||||||
|
name={['vqd_config', 'enable']}
|
||||||
|
>
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<Form.Item
|
||||||
|
className="mb-1"
|
||||||
|
name={['vqd_config', 'is_deep_learn']}
|
||||||
|
label="深度学习"
|
||||||
|
>
|
||||||
|
<Switch size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
className="mb-1"
|
||||||
|
name={['vqd_config', 'frm_num']}
|
||||||
|
label="连续分析帧数"
|
||||||
|
>
|
||||||
|
<InputNumber min={2} max={64} defaultValue={10} size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>蓝屏检查</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_blue', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_blue" children="blue_thr" defaultValue={0.6} labelName="判断阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_blue" children="blue_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>清晰度检查</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_clarity', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_clarity" children="clarity_thr" defaultValue={0.4} labelName="判断阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_clarity" children="clarity_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>抖动检查</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_shark', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_shark" children="shark_thr" defaultValue={0.2} labelName="阈值参数" />
|
||||||
|
<BoxInputNumber parent="vqd_shark" children="shark_abn_num_ratio" defaultValue={0.2} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>冻结检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_freeze', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_freeze" children="freeze_thr" defaultValue={0.4} labelName="阈值参数" />
|
||||||
|
<BoxInputNumber parent="vqd_freeze" children="freeze_abn_num_ratio" defaultValue={0.9} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>偏色检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_color', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_color" children="color_thr" defaultValue={0.2} labelName="偏色判断值" />
|
||||||
|
<BoxInputNumber parent="vqd_color" children="color_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>遮挡检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_occlusion', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_occlusion" children="occlusion_thr" defaultValue={0.1} labelName="判断阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_occlusion" children="occlusion_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>马赛克检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_mosaic', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_mosaic" children="mosaic_thr" defaultValue={0.1} labelName="阈值参数" />
|
||||||
|
<BoxInputNumber parent="vqd_mosaic" children="mosaic_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>噪声检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_noise', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_noise" children="noise_thr" defaultValue={0.3} labelName="过暗阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_noise" children="noise_abn_num_ratio" defaultValue={0.6} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>对比度检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_contrast', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_contrast" children="ctra_low_thr" defaultValue={0.2} labelName="低判断阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_contrast" children="ctra_high_thr" defaultValue={0.8} labelName="高判断阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_contrast" children="ctra_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>亮度检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_lgt_dark', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_lgt_dark" children="dark_thr" defaultValue={0.4} labelName="过暗阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_lgt_dark" children="lgt_thr" defaultValue={0.1} labelName="过亮阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_lgt_dark" children="lgt_dark_abn_num_ratio" defaultValue={0.5} labelName="次数比例" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex vertical className="config-box">
|
||||||
|
<Flex justify="space-between" align="center" className="config-box-hade">
|
||||||
|
<h4>花屏检测</h4>
|
||||||
|
<Form.Item className="mb-0" name={['vqd_flower', 'enable']} >
|
||||||
|
<Switch className="ml-1" size="small" />
|
||||||
|
</Form.Item>
|
||||||
|
</Flex>
|
||||||
|
<div className="config-box-item">
|
||||||
|
<BoxInputNumber parent="vqd_flower" children="flower_thr" defaultValue={0.3} labelName="阈值参数" />
|
||||||
|
<BoxInputNumber parent="vqd_flower" children="flower_abn_num_ratio" defaultValue={0.6} labelName="过亮阈值" />
|
||||||
|
<BoxInputNumber parent="vqd_flower" children="mosaic_thr" defaultValue={0.3} labelName="马赛克阈值参数" />
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
</>
|
||||||
|
}
|
||||||
34
web/src/components/Snap.tsx
Normal file
34
web/src/components/Snap.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// import {
|
||||||
|
// FindAlarmSnapshot,
|
||||||
|
// } from '@/service/http/aiserver';
|
||||||
|
import { Image } from 'antd';
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface ISnapshot {
|
||||||
|
filePath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Snapshot: React.FC<ISnapshot> = ({
|
||||||
|
filePath,
|
||||||
|
}) => {
|
||||||
|
// const [base64, setBase64] = useState("");
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (filePath != "") {
|
||||||
|
// FindAlarmSnapshot(filePath).then(data => {
|
||||||
|
// setBase64(data.data.data)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }, [filePath]);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Image
|
||||||
|
width="100%"
|
||||||
|
height="130px"
|
||||||
|
fallback={'./assets/img/noImg.png'}
|
||||||
|
src={filePath || './assets/img/noImg.png'}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Snapshot;
|
||||||
@ -1,15 +1,16 @@
|
|||||||
import { useRef, useState, useMemo } from "react";
|
import { useRef, useState, useMemo } from "react";
|
||||||
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip } from "antd";
|
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip, Select, Row, Col, Empty, Pagination, Tag } from "antd";
|
||||||
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||||
import { GetVqdAlarm, DeleteVqdAlarm, DeleteVqdAlarmAll } from "../api/vqdalarm";
|
import { GetVqdAlarm, DeleteVqdAlarm, DeleteVqdAlarmAll } from "../api/vqdalarm";
|
||||||
import type { VqdAlarmItem } from "../types/vqdalarm";
|
import type { VqdAlarmItem } from "../types/vqdalarm";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
import { FormatFileSizeToString } from "../utils/rate";
|
import { FormatFileSizeToString } from "../utils/rate";
|
||||||
import { formatSecondsToHMS } from "../utils/time";
|
import { formatSecondsToHMS } from "../utils/time";
|
||||||
import Filter from "./Filter";
|
import Filter from "./Filter";
|
||||||
|
import AlarmSnap from './snap';
|
||||||
|
const variants = ['filled'] as const;
|
||||||
export default function VqdAlarmPage() {
|
export default function VqdAlarmPage() {
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
const [pagination, setPagination] = useState({
|
const [pagination, setPagination] = useState({
|
||||||
@ -17,7 +18,8 @@ export default function VqdAlarmPage() {
|
|||||||
size: 10,
|
size: 10,
|
||||||
name: ""
|
name: ""
|
||||||
});
|
});
|
||||||
|
const [arrList, setArrList] = useState<any>([{ name: "全部类型", id: 0 }]);
|
||||||
|
const [templateData, setTemplateData] = useState<VqdAlarmItem[]>([]);
|
||||||
// 获取任务列表
|
// 获取任务列表
|
||||||
const {
|
const {
|
||||||
data: storageResponse,
|
data: storageResponse,
|
||||||
@ -55,6 +57,13 @@ export default function VqdAlarmPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 处理分页变化
|
// 处理分页变化
|
||||||
|
const onAlarmPageChange = (page: number, pageSize?: number) => {
|
||||||
|
setPagination((prev) => ({
|
||||||
|
...prev,
|
||||||
|
page: page,
|
||||||
|
size: pageSize || prev.size,
|
||||||
|
}));
|
||||||
|
}
|
||||||
const handleTableChange = (page: number, pageSize?: number) => {
|
const handleTableChange = (page: number, pageSize?: number) => {
|
||||||
setPagination((prev) => ({
|
setPagination((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@ -129,7 +138,7 @@ export default function VqdAlarmPage() {
|
|||||||
|
|
||||||
|
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="确定要删除这个文件吗?"
|
title="确定要删除这个告警吗?"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
if (record.id) {
|
if (record.id) {
|
||||||
deleteMutation(record.id);
|
deleteMutation(record.id);
|
||||||
@ -151,7 +160,7 @@ export default function VqdAlarmPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Flex justify="space-between" align="center" className="mb-4">
|
{/* <Flex justify="space-between" align="center" className="mb-4">
|
||||||
<Space>
|
<Space>
|
||||||
|
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
@ -176,9 +185,9 @@ export default function VqdAlarmPage() {
|
|||||||
setPagination({ ...pagination, name: value });
|
setPagination({ ...pagination, name: value });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex> */}
|
||||||
{/* 表格 */}
|
{/* 表格 */}
|
||||||
<Table
|
{/* <Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
dataSource={storageResponse?.items}
|
dataSource={storageResponse?.items}
|
||||||
@ -195,7 +204,109 @@ export default function VqdAlarmPage() {
|
|||||||
onChange: handleTableChange,
|
onChange: handleTableChange,
|
||||||
onShowSizeChange: handleTableChange,
|
onShowSizeChange: handleTableChange,
|
||||||
}}
|
}}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
<Flex justify="flex-end" className="mr-2" align="center">
|
||||||
|
{/* <Space className="pl-2">
|
||||||
|
|
||||||
|
<Popconfirm
|
||||||
|
title="确定要批量删除文件吗?"
|
||||||
|
|
||||||
|
onConfirm={() => {
|
||||||
|
deleteMutationAll({ ids: selectedRowKeys as number[] })
|
||||||
|
}}
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
>
|
||||||
|
<Button color="danger" variant="solid" loading={delAllLoadings} disabled={selectedRowKeys.length == 0} >
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
|
||||||
|
</Space> */}
|
||||||
|
{/* <DatePicker
|
||||||
|
defaultDate={moment().format('YYYY-MM-DD')}
|
||||||
|
moonData={moonReq}
|
||||||
|
onChangePanel={handleSelectMoon}
|
||||||
|
onSelectDate={handleSelectDate}
|
||||||
|
loading={moonLoading}
|
||||||
|
/> */}
|
||||||
|
<div className="w-[150px] ml-[20px]">
|
||||||
|
<Select
|
||||||
|
defaultValue={0}
|
||||||
|
className="w-[100%] mr-2"
|
||||||
|
placeholder="选择类型"
|
||||||
|
onChange={(v) => {
|
||||||
|
console.log("类型", v);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options={arrList.map((item: any) => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
optionRender={(option) => (
|
||||||
|
<Space>
|
||||||
|
<span>
|
||||||
|
{option.data.label}
|
||||||
|
</span>
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Filter
|
||||||
|
|
||||||
|
searchLoading={isLoading}
|
||||||
|
onSearchChange={(value: string) => {
|
||||||
|
setPagination({ ...pagination, name: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
<br />
|
||||||
|
<Row gutter={[16, 16]} className="pl-2 pr-2">
|
||||||
|
{storageResponse?.items.map((item) => {
|
||||||
|
return (
|
||||||
|
<Col xxl={6} xl={8} lg={12} md={12} sm={12} xs={24} key={item.id} >
|
||||||
|
<div className="overflow-hidden relative rounded-lg h-full w-full cursor-pointer shadow">
|
||||||
|
<AlarmSnap filePath={item.file_path} />
|
||||||
|
<div className="pl-3 pr-2 pb-1">
|
||||||
|
|
||||||
|
<Flex justify="space-between" align="center">
|
||||||
|
<Tag bordered={false} color="#87d068" className="m-0 mt-2">{item.alarm_name}</Tag>
|
||||||
|
<Space className="pr-2"> 通道:{item.channel_name||"2222"}</Space>
|
||||||
|
</Flex>
|
||||||
|
<Flex justify="space-between" align="center">
|
||||||
|
<p className="m-0"> {item.created_at}</p>
|
||||||
|
<Tooltip title="删除">
|
||||||
|
<Popconfirm
|
||||||
|
title="删除告警"
|
||||||
|
description="确定要删除此告警吗?"
|
||||||
|
onConfirm={() => {
|
||||||
|
// delAlarmSnapshot([item.id])
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* loading={isDelLoading} */}
|
||||||
|
<Button type="text" danger icon={<DeleteOutlined />}></Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{storageResponse?.items.length === 0 && (
|
||||||
|
<Col span={24}>
|
||||||
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
<Flex justify="flex-end" className="mr-[20px] mt-6 mb-3" align="center">
|
||||||
|
<Pagination onChange={onAlarmPageChange} defaultCurrent={pagination.page} defaultPageSize={pagination.size} total={storageResponse?.total} />
|
||||||
|
</Flex>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,10 +25,7 @@ export default function VqdTaskPage() {
|
|||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
GetVqdConfigBase()
|
GetVqdConfigBase()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res.data);
|
|
||||||
const formValues = {
|
const formValues = {
|
||||||
frm_num: res.data.frm_num,
|
|
||||||
is_deep_learn: res.data.is_deep_learn,
|
|
||||||
save_day: res.data.save_day,
|
save_day: res.data.save_day,
|
||||||
};
|
};
|
||||||
form.setFieldsValue(formValues);
|
form.setFieldsValue(formValues);
|
||||||
@ -51,17 +48,11 @@ export default function VqdTaskPage() {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
save_day,
|
save_day,
|
||||||
frm_num,
|
|
||||||
is_deep_learn
|
|
||||||
} = values as {
|
} = values as {
|
||||||
save_day: number;
|
save_day: number;
|
||||||
frm_num: number;
|
|
||||||
is_deep_learn: boolean;
|
|
||||||
};
|
};
|
||||||
const payload: UpdateConfigBaseReq = {
|
const payload: UpdateConfigBaseReq = {
|
||||||
save_day,
|
save_day,
|
||||||
frm_num,
|
|
||||||
is_deep_learn,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = (values as any).id;
|
const id = (values as any).id;
|
||||||
@ -71,12 +62,12 @@ export default function VqdTaskPage() {
|
|||||||
<Form.Item name="save_day" label="数据保存天数" rules={[{ required: true, message: "请输入数据保存天数" }]}>
|
<Form.Item name="save_day" label="数据保存天数" rules={[{ required: true, message: "请输入数据保存天数" }]}>
|
||||||
<InputNumber min={1} defaultValue={3} />
|
<InputNumber min={1} defaultValue={3} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="frm_num" label="连续分析帧数(2-64), 默认为10, 最大为 64" rules={[{ required: true, message: "请输入连续分析帧数" }]}>
|
{/* <Form.Item name="frm_num" label="连续分析帧数(2-64), 默认为10, 最大为 64" rules={[{ required: true, message: "请输入连续分析帧数" }]}>
|
||||||
<InputNumber max={64} min={2} defaultValue={10} />
|
<InputNumber max={64} min={2} defaultValue={10} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="是否使用深度学习版本" name="is_deep_learn">
|
<Form.Item label="是否使用深度学习版本" name="is_deep_learn">
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item> */}
|
||||||
<Button type="primary" onClick={handleSave}>
|
<Button type="primary" onClick={handleSave}>
|
||||||
保存
|
保存
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { GetVqdTask, DeleteVqdTask } from "../api/vqdtask";
|
|||||||
import type { VqdTaskItem } from "../types/vqdtask";
|
import type { VqdTaskItem } from "../types/vqdtask";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import AddVqdTask, { AddVqdTaskRef } from "./AddVqdTask";
|
import AddVqdTask, { AddVqdTaskRef } from "./AddVqdTask";
|
||||||
import ChannelModel, { IChannelModelFunc } from "./channel/Channel";
|
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
import { FormatFileSizeToString } from "../utils/rate";
|
import { FormatFileSizeToString } from "../utils/rate";
|
||||||
import { formatSecondsToHMS } from "../utils/time";
|
import { formatSecondsToHMS } from "../utils/time";
|
||||||
@ -100,8 +99,18 @@ export default function VqdTaskPage() {
|
|||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "文件名称",
|
title: "关联通道",
|
||||||
dataIndex: "file_name",
|
dataIndex: "channel_name",
|
||||||
|
align: "center",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Space>
|
||||||
|
{text}
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "模板",
|
||||||
|
dataIndex: "task_template_name",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Space>
|
<Space>
|
||||||
@ -132,7 +141,7 @@ export default function VqdTaskPage() {
|
|||||||
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="确定要删除这个文件吗?"
|
title="确定要删除这个任务吗?"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
if (record.id) {
|
if (record.id) {
|
||||||
deleteMutation(record.id);
|
deleteMutation(record.id);
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { useRef, useState, useMemo } from "react";
|
import { useRef, useState, useMemo } from "react";
|
||||||
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip } from "antd";
|
import { Table, Button, Space, Popconfirm, Flex, message, Tooltip, Switch, Tag } from "antd";
|
||||||
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
import { EditOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||||
import { GetVqdTaskTemplate, DeleteVqdTaskTemplate } from "../api/vqdtasktemplate";
|
import { GetVqdTaskTemplate, DeleteVqdTaskTemplate, UpdateVqdTaskTemplate } from "../api/vqdtasktemplate";
|
||||||
import type { VqdTaskTemplateItem } from "../types/vqdtasktemplate";
|
import type { VqdTaskTemplateItem, CreateVqdTaskTemplateReq } from "../types/vqdtasktemplate";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import AddVqdTaskTemplate, { AddVqdTaskTemplateRef } from "./AddVqdTaskTemplate";
|
import AddVqdTaskTemplate, { AddVqdTaskTemplateRef } from "./AddVqdTaskTemplate";
|
||||||
import { useGlobal } from "../Context";
|
import { useGlobal } from "../Context";
|
||||||
@ -64,6 +64,11 @@ export default function VqdTaskTemplatePage() {
|
|||||||
const handleEdit = (disk: VqdTaskTemplateItem) => {
|
const handleEdit = (disk: VqdTaskTemplateItem) => {
|
||||||
dialogRef.current?.open(disk);
|
dialogRef.current?.open(disk);
|
||||||
};
|
};
|
||||||
|
const saveTemplate = (disk: VqdTaskTemplateItem, t: boolean) => {
|
||||||
|
const payload = disk as CreateVqdTaskTemplateReq;
|
||||||
|
payload.enable = t
|
||||||
|
updateMutate({ id: String(disk.id), ...payload })
|
||||||
|
};
|
||||||
|
|
||||||
// 处理分页变化
|
// 处理分页变化
|
||||||
const handleTableChange = (page: number, pageSize?: number) => {
|
const handleTableChange = (page: number, pageSize?: number) => {
|
||||||
@ -91,6 +96,14 @@ export default function VqdTaskTemplatePage() {
|
|||||||
setSelectedRowKeys([...newSelectedRowKeys]);
|
setSelectedRowKeys([...newSelectedRowKeys]);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const { mutate: updateMutate } = useMutation({
|
||||||
|
mutationFn: UpdateVqdTaskTemplate,
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success("更新成功");
|
||||||
|
refetch()
|
||||||
|
},
|
||||||
|
onError: ErrorHandle,
|
||||||
|
});
|
||||||
// 表格列定义
|
// 表格列定义
|
||||||
const columns: ColumnsType<VqdTaskTemplateItem> = [
|
const columns: ColumnsType<VqdTaskTemplateItem> = [
|
||||||
{
|
{
|
||||||
@ -99,26 +112,54 @@ export default function VqdTaskTemplatePage() {
|
|||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "文件名称",
|
title: "启用",
|
||||||
dataIndex: "file_name",
|
dataIndex: "enable",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Space>
|
<Space>
|
||||||
{text}
|
<Switch value={text} defaultChecked onChange={(t) => {
|
||||||
|
saveTemplate(record, t)
|
||||||
|
}} />
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "诊断模块",
|
||||||
|
align: "center",
|
||||||
|
width: 550,
|
||||||
|
dataIndex: "vqd_lgt_dark",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Flex gap="small" align="center" wrap>
|
||||||
|
{record?.vqd_lgt_dark?.enable && <Tag bordered={false} color="green" >亮度检测</Tag>}
|
||||||
|
{record?.vqd_blue?.enable && <Tag bordered={false} color="green" >蓝屏检查</Tag>}
|
||||||
|
{record?.vqd_clarity?.enable && <Tag bordered={false} color="green" >清晰度检查</Tag>}
|
||||||
|
{record?.vqd_shark?.enable && <Tag bordered={false} color="green" >抖动检查</Tag>}
|
||||||
|
{record?.vqd_freeze?.enable && <Tag bordered={false} color="green" >冻结检测</Tag>}
|
||||||
|
{record?.vqd_color?.enable && <Tag bordered={false} color="green" >偏色检测</Tag>}
|
||||||
|
{record?.vqd_occlusion?.enable && <Tag bordered={false} color="green" >遮挡检测</Tag>}
|
||||||
|
{record?.vqd_noise?.enable && <Tag bordered={false} color="green" >噪声检测</Tag>}
|
||||||
|
{record?.vqd_contrast?.enable && <Tag bordered={false} color="green" >对比度检测</Tag>}
|
||||||
|
{record?.vqd_mosaic?.enable && <Tag bordered={false} color="green" >马赛克检测</Tag>}
|
||||||
|
{record?.vqd_flower?.enable && <Tag bordered={false} color="green" >花屏检测</Tag>}
|
||||||
|
</Flex>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "描述",
|
title: "描述",
|
||||||
dataIndex: "des",
|
dataIndex: "des",
|
||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: "创建日期",
|
// title: "日期",
|
||||||
dataIndex: "created_at",
|
// dataIndex: "created_at",
|
||||||
align: "center",
|
// align: "center",
|
||||||
render: (text: string) => (text ? new Date(text).toLocaleString() : "-"),
|
// render: (text: string, record) => (
|
||||||
},
|
// <>
|
||||||
|
// <div>创建:{(text ? new Date(text).toLocaleString() : "-")}</div>
|
||||||
|
// 更新:{(record?.updated_at ? new Date(record?.updated_at).toLocaleString() : "-")}
|
||||||
|
// </>
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
align: "center",
|
align: "center",
|
||||||
@ -130,8 +171,8 @@ export default function VqdTaskTemplatePage() {
|
|||||||
<Tooltip placement="top" title="编辑" color="#fff">
|
<Tooltip placement="top" title="编辑" color="#fff">
|
||||||
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
<Button icon={<EditOutlined />} onClick={() => handleEdit(record)} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Popconfirm
|
{!record.is_default&&<Popconfirm
|
||||||
title="确定要删除这个文件吗?"
|
title="确定要删除这个模板吗?"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
if (record.id) {
|
if (record.id) {
|
||||||
deleteMutation(record.id);
|
deleteMutation(record.id);
|
||||||
@ -145,7 +186,8 @@ export default function VqdTaskTemplatePage() {
|
|||||||
danger
|
danger
|
||||||
icon={<DeleteOutlined />}
|
icon={<DeleteOutlined />}
|
||||||
/>
|
/>
|
||||||
</Popconfirm>
|
</Popconfirm>}
|
||||||
|
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -203,7 +245,7 @@ export default function VqdTaskTemplatePage() {
|
|||||||
{/* 编辑模态框 */}
|
{/* 编辑模态框 */}
|
||||||
<AddVqdTaskTemplate
|
<AddVqdTaskTemplate
|
||||||
ref={dialogRef}
|
ref={dialogRef}
|
||||||
title="编辑"
|
title="添加/编辑模板"
|
||||||
onSuccess={() => refetch()}
|
onSuccess={() => refetch()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Space, ConfigProvider, Modal, Tag, Tooltip, Button } from "antd";
|
import { Alert, ConfigProvider, Modal, Tag, message } from "antd";
|
||||||
import { DeliveredProcedureOutlined } from "@ant-design/icons";
|
|
||||||
import Table, { ColumnsType } from "antd/es/table";
|
import Table, { ColumnsType } from "antd/es/table";
|
||||||
import React, {
|
import React, {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
@ -13,30 +12,28 @@ import { ChannelItem, ChannelReq } from "../../types/device";
|
|||||||
import Filter from "./Filter";
|
import Filter from "./Filter";
|
||||||
import { GetChannels } from "../../api/devices";
|
import { GetChannels } from "../../api/devices";
|
||||||
import { useGlobal } from "../../Context";
|
import { useGlobal } from "../../Context";
|
||||||
import type { AddTaskItem } from "../../types/audiotask";
|
|
||||||
export interface IChannelModelFunc {
|
export interface IChannelModelFunc {
|
||||||
openModal: (id: number, name: string) => void;
|
openModal: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChannelModel {
|
interface IChannelModel {
|
||||||
ref: any;
|
ref: any;
|
||||||
onCallback: (data: AddTaskItem[]) => void;
|
onCallback: (id: any, name:any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChannelModel: React.FC<IChannelModel> = forwardRef(({onCallback},ref) => {
|
const ChannelModel: React.FC<IChannelModel> = forwardRef(({onCallback},ref) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
openModal: (id: number, name: string) => {
|
openModal: (id: string) => {
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
// if (id != 0) {
|
if (id != "") {
|
||||||
// setSelectedRowKeys([id])
|
setSelectedRowKeys([id])
|
||||||
// }
|
}
|
||||||
audioName.current = name
|
|
||||||
pid.current = id;
|
pid.current = id;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const pid = useRef<number>(0);
|
const pid = useRef<string>(undefined);
|
||||||
const audioName = useRef<string>('');
|
|
||||||
const { ErrorHandle } = useGlobal();
|
const { ErrorHandle } = useGlobal();
|
||||||
|
|
||||||
const columns: ColumnsType<ChannelItem> = [
|
const columns: ColumnsType<ChannelItem> = [
|
||||||
@ -77,25 +74,6 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
dataIndex: "protocol",
|
dataIndex: "protocol",
|
||||||
render: (text: string) => text || "-",
|
render: (text: string) => text || "-",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "操作",
|
|
||||||
align: "center",
|
|
||||||
width: 120,
|
|
||||||
fixed: "right",
|
|
||||||
render: (_, record) => (
|
|
||||||
<Space>
|
|
||||||
<Tooltip placement="top" title="下发广播任务" color="#fff">
|
|
||||||
<Button icon={<DeliveredProcedureOutlined />} onClick={() => {
|
|
||||||
onCallback([{
|
|
||||||
audio_id: pid.current,
|
|
||||||
channel_id: record.id,
|
|
||||||
channel_name: record.name,
|
|
||||||
}])
|
|
||||||
}} />
|
|
||||||
</Tooltip>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 获取通道列表
|
// 获取通道列表
|
||||||
@ -104,10 +82,9 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
size: 10, // 通道一般 < 10 个,客户端不做分页,一次性全查
|
size: 10, // 通道一般 < 10 个,客户端不做分页,一次性全查
|
||||||
device_id: "",
|
device_id: "",
|
||||||
pid: "ROOT",
|
pid: "ROOT",
|
||||||
status: true,
|
status: "",
|
||||||
name: "",
|
name: "",
|
||||||
bid: "",
|
bid: "",
|
||||||
protocol: "GB28181"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data, isLoading } = useQuery({
|
const { data, isLoading } = useQuery({
|
||||||
@ -122,7 +99,7 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
enabled: open,
|
enabled: open,
|
||||||
});
|
});
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
const [selectedRowsAll, setSelectedRows] = useState<ChannelItem[]>([]);
|
const [selectedRows, setSelectedRows] = useState<ChannelItem[]>([]);
|
||||||
const rowSelection = {
|
const rowSelection = {
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
getCheckboxProps: (record: ChannelItem) => ({
|
getCheckboxProps: (record: ChannelItem) => ({
|
||||||
@ -132,34 +109,18 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
newSelectedRowKeys: React.Key[],
|
newSelectedRowKeys: React.Key[],
|
||||||
selectedRows: ChannelItem[]
|
selectedRows: ChannelItem[]
|
||||||
) => {
|
) => {
|
||||||
setSelectedRowKeys(newSelectedRowKeys);
|
if (newSelectedRowKeys.length > 0) {
|
||||||
setSelectedRows(selectedRows)
|
setSelectedRowKeys([newSelectedRowKeys[newSelectedRowKeys.length - 1]]);
|
||||||
// if (newSelectedRowKeys.length > 0) {
|
setSelectedRows([selectedRows[selectedRows.length - 1]]);
|
||||||
// setSelectedRowKeys([newSelectedRowKeys[newSelectedRowKeys.length - 1]]);
|
}
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const onAll = () => {
|
|
||||||
let dataItem: AddTaskItem[] = []
|
|
||||||
selectedRowsAll.forEach(record => {
|
|
||||||
let list: AddTaskItem = {
|
|
||||||
audio_id: pid.current,
|
|
||||||
channel_id: record.id,
|
|
||||||
channel_name: record.name,
|
|
||||||
}
|
|
||||||
dataItem.push(list)
|
|
||||||
});
|
|
||||||
onCallback(dataItem)
|
|
||||||
setOpen(false);
|
|
||||||
setSelectedRows([])
|
|
||||||
setSelectedRowKeys([])
|
|
||||||
}
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
// if (selectedRowKeys.length>0) {
|
if (selectedRowKeys.length>0) {
|
||||||
// onCallback(selectedRowKeys[0], pid.current)
|
onCallback(selectedRows[0].id, selectedRows[0].name||selectedRows[0].id)
|
||||||
// }
|
}
|
||||||
setSelectedRows([])
|
|
||||||
setSelectedRowKeys([])
|
setSelectedRowKeys([])
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -184,17 +145,11 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
>
|
>
|
||||||
<Modal
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
title={`选择通道广播【${audioName.current}】音频`}
|
title="绑定通道"
|
||||||
style={{ top: "5%" }}
|
style={{ top: "5%" }}
|
||||||
width={"1000px"}
|
width={"1000px"}
|
||||||
footer={
|
|
||||||
<>
|
|
||||||
<Button onClick={() => onCancel()} >关 闭</Button>
|
|
||||||
<Button disabled={selectedRowKeys.length == 0} type="primary" onClick={() => onAll()} className="mr-6">批量下发</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
// onOk={onCancel}
|
onOk={onCancel}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-2 flex justify-end">
|
<div className="mb-2 flex justify-end">
|
||||||
@ -204,7 +159,7 @@ const ChannelModel: React.FC<IChannelModel> = forwardRef(({ onCallback }, ref) =
|
|||||||
onSearchChange={(value: string) => {
|
onSearchChange={(value: string) => {
|
||||||
setPagination({ ...pagination, name: value, bid: value });
|
setPagination({ ...pagination, name: value, bid: value });
|
||||||
}}
|
}}
|
||||||
onSelectChange={(value: any) => {
|
onSelectChange={(value: string) => {
|
||||||
setPagination({ ...pagination, status: value });
|
setPagination({ ...pagination, status: value });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -145,6 +145,14 @@
|
|||||||
margin-right: 0.75rem;
|
margin-right: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.m-0 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.mb-1 {
|
.mb-1 {
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -169,10 +177,26 @@
|
|||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mr-2 {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-4 {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-4 {
|
.mt-4 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-6 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@ -438,6 +462,10 @@
|
|||||||
padding-bottom: 2rem;
|
padding-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pb-1 {
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pb-2 {
|
.pb-2 {
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
@ -446,6 +474,18 @@
|
|||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pl-2 {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-3 {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-2 {
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pr-4 {
|
.pr-4 {
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
@ -506,6 +546,12 @@
|
|||||||
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
|
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
@ -553,3 +599,22 @@ body {
|
|||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.config-box {
|
||||||
|
width: 260px;
|
||||||
|
border: 1px solid rgb(222,222,222,0.8);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
|
}
|
||||||
|
.config-box-hade {
|
||||||
|
padding: 0.2rem 0.6rem;
|
||||||
|
border-radius: 0.5rem 0.5rem 0 0;
|
||||||
|
background-color: rgb(222,222,222,0.8);
|
||||||
|
}
|
||||||
|
.config-box-hade h4 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.config-box-item {
|
||||||
|
padding: 0.3rem;
|
||||||
|
}
|
||||||
@ -1,4 +1,16 @@
|
|||||||
|
import type {
|
||||||
|
VqdLgtDark,
|
||||||
|
VqdBlue,
|
||||||
|
VqdClarity,
|
||||||
|
VqdShark,
|
||||||
|
VqdFreeze,
|
||||||
|
VqdColor,
|
||||||
|
VqdOcclusion,
|
||||||
|
VqdNoise,
|
||||||
|
VqdContrast,
|
||||||
|
VqdMosaic,
|
||||||
|
VqdFlower,
|
||||||
|
} from "./vqdtasktemplate"
|
||||||
/**
|
/**
|
||||||
* 基础
|
* 基础
|
||||||
*/
|
*/
|
||||||
@ -8,12 +20,24 @@ export type VqdConfigBaseRes = {
|
|||||||
|
|
||||||
export type UpdateConfigBaseReq = {
|
export type UpdateConfigBaseReq = {
|
||||||
save_day: number;
|
save_day: number;
|
||||||
frm_num: number;
|
|
||||||
is_deep_learn: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VqdConfigBaseDetailRes = {
|
export type VqdConfigBaseDetailRes = {
|
||||||
save_day: number;
|
save_day: number;
|
||||||
|
}
|
||||||
|
export type VqdConfigDefaultDetailRes = {
|
||||||
frm_num: number;
|
frm_num: number;
|
||||||
is_deep_learn: boolean;
|
is_deep_learn: boolean;
|
||||||
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
|
vqd_blue: VqdBlue;
|
||||||
|
vqd_clarity: VqdClarity;
|
||||||
|
vqd_shark: VqdShark;
|
||||||
|
vqd_freeze: VqdFreeze;
|
||||||
|
vqd_color: VqdColor;
|
||||||
|
vqd_occlusion: VqdOcclusion;
|
||||||
|
vqd_noise: VqdNoise;
|
||||||
|
vqd_contrast: VqdContrast;
|
||||||
|
vqd_mosaic: VqdMosaic;
|
||||||
|
vqd_flower: VqdFlower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
web/src/types/device.d.ts
vendored
2
web/src/types/device.d.ts
vendored
@ -189,7 +189,7 @@ type ChannelReq = {
|
|||||||
/**
|
/**
|
||||||
* true:在线; false:离线;
|
* true:在线; false:离线;
|
||||||
*/
|
*/
|
||||||
status?: boolean;
|
status?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChannelRes = {
|
export type ChannelRes = {
|
||||||
|
|||||||
@ -26,6 +26,19 @@ export type VqdTaskTemplateItem = {
|
|||||||
name: string;
|
name: string;
|
||||||
plans: string;
|
plans: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
is_default: boolean;
|
||||||
|
vqd_config: VqdConfig;
|
||||||
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
|
vqd_blue: VqdBlue;
|
||||||
|
vqd_clarity: VqdClarity;
|
||||||
|
vqd_shark: VqdShark;
|
||||||
|
vqd_freeze: VqdFreeze;
|
||||||
|
vqd_color: VqdColor;
|
||||||
|
vqd_occlusion: VqdOcclusion;
|
||||||
|
vqd_noise: VqdNoise;
|
||||||
|
vqd_contrast: VqdContrast;
|
||||||
|
vqd_mosaic: VqdMosaic;
|
||||||
|
vqd_flower: VqdFlower;
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
des: string;
|
des: string;
|
||||||
@ -49,6 +62,70 @@ export type VqdTaskTemplateReq = {
|
|||||||
size: number;
|
size: number;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
export type VqdConfig = {
|
||||||
|
enable: boolean;
|
||||||
|
frm_num: number;
|
||||||
|
is_deep_learn: boolean;
|
||||||
|
}
|
||||||
|
export type VqdLgtDark = {
|
||||||
|
enable: boolean;
|
||||||
|
dark_thr: number;
|
||||||
|
lgt_thr: number;
|
||||||
|
lgt_dark_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdBlue = {
|
||||||
|
enable: boolean;
|
||||||
|
blue_thr: number;
|
||||||
|
blue_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdClarity = {
|
||||||
|
enable: boolean;
|
||||||
|
clarity_thr: number;
|
||||||
|
clarity_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdShark = {
|
||||||
|
enable: boolean;
|
||||||
|
shark_thr: number;
|
||||||
|
shark_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdFreeze = {
|
||||||
|
enable: boolean;
|
||||||
|
freeze_thr: number;
|
||||||
|
freeze_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdColor = {
|
||||||
|
enable: boolean;
|
||||||
|
color_thr: number;
|
||||||
|
color_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdOcclusion = {
|
||||||
|
enable: boolean;
|
||||||
|
occlusion_thr: number;
|
||||||
|
occlusion_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdNoise = {
|
||||||
|
enable: boolean;
|
||||||
|
noise_thr: number;
|
||||||
|
noise_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdContrast = {
|
||||||
|
enable: boolean;
|
||||||
|
ctra_low_thr: number;
|
||||||
|
ctra_high_thr: number;
|
||||||
|
ctra_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdMosaic = {
|
||||||
|
enable: boolean;
|
||||||
|
mosaic_thr: number;
|
||||||
|
mosaic_abn_num_ratio: number;
|
||||||
|
}
|
||||||
|
export type VqdFlower = {
|
||||||
|
enable: boolean;
|
||||||
|
flower_thr: number;
|
||||||
|
flower_abn_num_ratio: number;
|
||||||
|
mosaic_thr: number;
|
||||||
|
}
|
||||||
|
|
||||||
export type CreateVqdTaskTemplateReq = {
|
export type CreateVqdTaskTemplateReq = {
|
||||||
/**
|
/**
|
||||||
* 名称
|
* 名称
|
||||||
@ -62,6 +139,18 @@ export type CreateVqdTaskTemplateReq = {
|
|||||||
* 启用
|
* 启用
|
||||||
*/
|
*/
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
vqd_config: VqdConfig;
|
||||||
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
|
vqd_blue: VqdBlue;
|
||||||
|
vqd_clarity: VqdClarity;
|
||||||
|
vqd_shark: VqdShark;
|
||||||
|
vqd_freeze: VqdFreeze;
|
||||||
|
vqd_color: VqdColor;
|
||||||
|
vqd_occlusion: VqdOcclusion;
|
||||||
|
vqd_noise: VqdNoise;
|
||||||
|
vqd_contrast: VqdContrast;
|
||||||
|
vqd_mosaic: VqdMosaic;
|
||||||
|
vqd_flower: VqdFlower;
|
||||||
/**
|
/**
|
||||||
* 描述
|
* 描述
|
||||||
*/
|
*/
|
||||||
@ -86,6 +175,19 @@ export type VqdTaskTemplateDetailRes = {
|
|||||||
name: string;
|
name: string;
|
||||||
plans: string;
|
plans: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
is_default: boolean;
|
||||||
|
vqd_config: VqdConfig;
|
||||||
|
vqd_lgt_dark: VqdLgtDark;
|
||||||
|
vqd_blue: VqdBlue;
|
||||||
|
vqd_clarity: VqdClarity;
|
||||||
|
vqd_shark: VqdShark;
|
||||||
|
vqd_freeze: VqdFreeze;
|
||||||
|
vqd_color: VqdColor;
|
||||||
|
vqd_occlusion: VqdOcclusion;
|
||||||
|
vqd_noise: VqdNoise;
|
||||||
|
vqd_contrast: VqdContrast;
|
||||||
|
vqd_mosaic: VqdMosaic;
|
||||||
|
vqd_flower: VqdFlower;
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
des: string;
|
des: string;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user