From a25ee90c656b39e652f24e3378ad2bf5698b162b Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期五, 20 十二月 2024 01:59:06 +0800
Subject: [PATCH] 添加疑似托管模型

---
 pkg/mysqlx/mysqlx.go    |   16 +
 service/task_results.go |    2 
 db/summay.go            |   29 +++
 models/gather_model.go  |    5 
 db/model.go             |   15 +
 db/persons.go           |   54 ++++++
 cron/cron.go            |    2 
 db/task_results.go      |   36 ++-
 models/disappear.go     |  270 ++++++++++++++++++++++++++++++
 db/db.go                |   63 ++++++
 10 files changed, 462 insertions(+), 30 deletions(-)

diff --git a/cron/cron.go b/cron/cron.go
index 551c6f2..f85d719 100644
--- a/cron/cron.go
+++ b/cron/cron.go
@@ -46,7 +46,7 @@
 }
 
 func Run() (err error) {
-	_, err = s.Every(1).Minute().StartImmediately().Do(Dispatch)
+	_, err = s.Every(10).Minute().StartImmediately().Do(Dispatch)
 	if err != nil {
 		return err
 	}
diff --git a/db/db.go b/db/db.go
index de59e6a..b23ab8c 100644
--- a/db/db.go
+++ b/db/db.go
@@ -6,13 +6,12 @@
 
 	"model-engine/config"
 	"model-engine/db/es"
-	"model-engine/pkg/logger"
 	"model-engine/pkg/mysqlx"
 )
 
 // Init 鍒濆鍖杕ysql鍜宔s
 func Init() error {
-	if err := mysqlx.Init(config.MysqlConf, logger.GetLogger()); err != nil {
+	if err := mysqlx.Init(config.MysqlConf, nil); err != nil {
 		return err
 	}
 	if err := es.InitClient([]string{"http://" + config.EsInfo.Ip + ":" + config.EsInfo.Port}); err != nil {
@@ -65,6 +64,15 @@
 			Name:        "鐤戜技鑱氶泦",
 			Description: "閫氱敤鑱氶泦妯″瀷",
 			Version:     "v1.0.1",
+			Enabled:     false,
+		},
+		{
+			BaseModel: BaseModel{
+				ID: ModelIdDisappear,
+			},
+			Name:        "鐤戜技鑴辩",
+			Description: "閫氱敤鑴辩妯″瀷",
+			Version:     "v1.0.0",
 			Enabled:     false,
 		},
 	}
@@ -143,6 +151,57 @@
 				Value:    "1",
 				ValType:  "int",
 				Operator: "==",
+				Sort:     3,
+			},
+		},
+		{
+			Id:      "7a1f0a3a-c207-4d94-bc28-cc9e017b3628",
+			ModelId: ModelIdDisappear,
+			Scope:   "",
+			RuleArg: RuleArg{
+				Alias:    "disappearTime",
+				Name:     "鎸佺画鏃堕棿",
+				Type:     "input",
+				Must:     true,
+				Unit:     "灏忔椂",
+				Range:    "1,2400",
+				Value:    "24",
+				ValType:  "int",
+				Operator: ">=",
+				Sort:     0,
+			},
+		},
+		{
+			Id:      "f1b99f28-1be0-4f78-b7c1-b01b1656b7fa",
+			ModelId: ModelIdDisappear,
+			Scope:   "",
+			RuleArg: RuleArg{
+				Alias:    "age",
+				Name:     "骞撮緞娈�",
+				Type:     "input",
+				Must:     true,
+				Unit:     "宀�",
+				Range:    "1,100",
+				Value:    "60, 90",
+				ValType:  "int",
+				Operator: "==",
+				Sort:     1,
+			},
+		},
+		{
+			Id:      "47366fa6-2f61-4fe0-957a-b1e0606bb1f0",
+			ModelId: ModelIdDisappear,
+			Scope:   "",
+			RuleArg: RuleArg{
+				Alias:    "age",
+				Name:     "杩涘嚭鏂瑰悜",
+				Type:     "input",
+				Must:     false,
+				Unit:     "",
+				Range:    "",
+				Value:    "",
+				ValType:  "string",
+				Operator: "==",
 				Sort:     2,
 			},
 		},
diff --git a/db/model.go b/db/model.go
index 97dcef1..bc3ac05 100644
--- a/db/model.go
+++ b/db/model.go
@@ -2,16 +2,18 @@
 
 import (
 	"fmt"
+
 	"gorm.io/gorm"
+
 	"model-engine/pkg/mysqlx"
 )
 
 type Model struct {
 	BaseModel
-	Name        string `json:"name" gorm:"type:varchar(255)"`                   //妯″瀷鍚嶇О
-	Description string `json:"description,omitempty" gorm:"type:varchar(1000)"` //妯″瀷鎻忚堪
-	Version     string `json:"version" gorm:"type:varchar(255)"`                //鐗堟湰鍙�
-	Enabled     bool   `json:"enabled"`                                         //鏄惁寮�鍚�
+	Name        string `json:"name" gorm:"type:varchar(255)"`                   // 妯″瀷鍚嶇О
+	Description string `json:"description,omitempty" gorm:"type:varchar(1000)"` // 妯″瀷鎻忚堪
+	Version     string `json:"version" gorm:"type:varchar(255)"`                // 鐗堟湰鍙�
+	Enabled     bool   `json:"enabled"`                                         // 鏄惁寮�鍚�
 }
 
 func (m *Model) TableName() string {
@@ -181,6 +183,7 @@
 }
 
 const (
-	ModelIdDrug   = "drug"   //娑夋瘨
-	ModelIdGather = "gather" //鑱氶泦
+	ModelIdDrug      = "drug"      // 娑夋瘨
+	ModelIdGather    = "gather"    // 鑱氶泦
+	ModelIdDisappear = "disappear" // 澶辫釜
 )
diff --git a/db/persons.go b/db/persons.go
new file mode 100644
index 0000000..4a01e3d
--- /dev/null
+++ b/db/persons.go
@@ -0,0 +1,54 @@
+package db
+
+import (
+	"time"
+
+	"gorm.io/gorm"
+)
+
+type BaseEntity struct {
+	ID        string `gorm:"primary_key;column:id;type:varchar(255);" json:"id"`
+	CreatedAt time.Time
+	UpdatedAt time.Time
+	DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
+}
+
+type DbPersons struct {
+	BaseEntity
+	TableId            string  `gorm:"column:table_id"`
+	FaceFeature        string  `gorm:"column:face_feature"`
+	PersonPicUrl       string  `gorm:"column:person_pic_url"`
+	PersonName         string  `gorm:"column:person_name"`
+	Age                string  `gorm:"column:age"`
+	Sex                string  `gorm:"column:sex"`
+	IdCard             string  `gorm:"column:id_card"`
+	PhoneNum           string  `gorm:"column:phone_num"`
+	MonitorLevel       string  `gorm:"column:monitor_level"`
+	PicDesc            string  `gorm:"column:pic_desc"`
+	Reserved           string  `gorm:"column:reserved"`
+	FromServerId       string  `gorm:"column:from_server_id"`
+	LastAppearanceTime int64   `gorm:"column:last_appearance_time"`
+	SnapshotCount      int     `gorm:"column:snapshot_count"`
+	DaysAppeared       int     `gorm:"column:days_appeared"`
+	Location           string  `gorm:"column:location"`
+	LastLocation       string  `gorm:"column:last_location"`
+	FaceAngleYaw       int32   `gorm:"column:face_angle_yaw"`
+	FaceAngleRoll      int32   `gorm:"column:face_angle_roll"`
+	FaceAnglePitch     int32   `gorm:"column:face_angle_pitch"`
+	CommunityID        string  `gorm:"column:community_id"` // 甯镐綇灏忓尯 domain unit ID
+	CommunityName      string  `gorm:"column:community_name"`
+	OrgID              string  `gorm:"column:org_id"` // 甯镐綇娲惧嚭鎵� domain unit ID
+	OrgName            string  `gorm:"column:community"`
+	FrontFaceScore     float64 `gorm:"column:front_face_score"`
+	ImageQuality       float64 `gorm:"column:image_quality"`
+	SimilarPersonId    string  `gorm:"column:similar_person_id"`
+	PersonalStatus     string  `gorm:"column:personal_status"`
+	NonHuman           bool    `gorm:"column:non_human"` // 闈炴椿浣擄紙1闈炲浣� 0娲讳綋锛�
+	IdPicUrl           string  `gorm:"column:id_pic_url"`
+	IsDelete           int     `gorm:"column:is_delete"` // 0 鏈垹闄� 1宸插垹闄�
+	FaceUpdateTime     int64   `gorm:"column:face_update_time"`
+}
+
+func (dp *DbPersons) TableName() string {
+	return "person"
+}
diff --git a/db/summay.go b/db/summay.go
new file mode 100644
index 0000000..49a3d7f
--- /dev/null
+++ b/db/summay.go
@@ -0,0 +1,29 @@
+package db
+
+type SnapshotCountSummary struct {
+	OrgId                    string  `gorm:"column:org_id"`                      // 娲惧嚭鎵�id
+	CommunityID              string  `gorm:"column:community_id"`                // 灏忓尯id
+	DocumentNumber           string  `gorm:"column:document_number"`             // 妗f缂栧彿
+	DaysAppeared             int     `gorm:"column:days_appeared"`               // 鍑虹幇澶╂暟
+	Count                    int     `gorm:"column:count"`                       // 鎶撴媿娆℃暟
+	Status                   string  `gorm:"column:status"`                      // 鏍囩
+	LastAppearanceTime       int64   `gorm:"column:last_appearance_time"`        // 鏈�鍚庡嚭鐜版椂闂�
+	LastAppearanceStatusTime int64   `gorm:"column:last_appearance_status_time"` // 鏈�鍚庡嚭鐜版椂闂�
+	LastLocation             string  `gorm:"column:last_location"`               // 鏈�鍚庡嚭鐜板湴鐐�
+	Building                 string  `gorm:"column:building"`                    // 妤兼爧鍙�
+	Floor                    string  `gorm:"column:floor"`                       // 妤煎眰
+	FrequentAddress          string  `gorm:"column:frequent_address"`            // 甯镐綇鍦板潃
+	IDStatus                 int     `gorm:"type:tinyint;not null;default:2"`    // 1宸插疄鍚� 2鏈疄鍚�
+	KeyStatus                int     `gorm:"type:tinyint;not null;default:2"`    // 1閲嶇偣浜哄憳 2 闈為噸鐐逛汉鍛�
+	StatusScore              float64 `gorm:"column:status_score"`                // 灞呬綇灞炴�ц瘎鍒�
+	StatusInitTime           int64   `gorm:"column:status_init_time"`
+	LastDirection            string  `gorm:"column:last_direction;type:varchar(255);"` // 鏈�鍚庡嚭鐜版柟鍚�
+}
+
+func (sc *SnapshotCountSummary) TableName() string {
+	return "snapshot_count_summary"
+}
+
+func (sc *SnapshotCountSummary) FindByPersonId(commId, docId string) error {
+	return GetDB().Table(sc.TableName()).Where("community_id = ? and document_number = ?", commId, docId).First(sc).Error
+}
diff --git a/db/task_results.go b/db/task_results.go
index ae4367d..8409cf2 100644
--- a/db/task_results.go
+++ b/db/task_results.go
@@ -2,24 +2,25 @@
 
 import (
 	"fmt"
-	"gorm.io/gorm"
 	"time"
+
+	"gorm.io/gorm"
 )
 
 type ModelTaskResults struct {
 	BaseModel
-	Title         string `json:"name" gorm:"type:varchar(255)"`                                                //棰勮鍚嶇О,鏆傛椂鐢ㄤ换鍔″悕绉�
-	Event         string `json:"event" gorm:"type:varchar(255)"`                                               //棰勮浜嬩欢
-	ModelID       string `json:"modelID" gorm:"type:varchar(255)"`                                             //妯″瀷ID
-	ModelTaskID   string `json:"modelTaskID" gorm:"type:varchar(255)"`                                         //妯″瀷浠诲姟ID
-	OrgID         string `json:"orgID" gorm:"index;column:org_id;type:varchar(299);not null;"`                 //娲惧嚭鎵� domain unit ID
-	CommunityId   string `json:"communityID" gorm:"index;column:community_id;type:varchar(299);not null;"`     //灏忓尯ID
-	PicDate       string `json:"picDate"       gorm:"uniqueIndex:pic_date_first_person_id;type:varchar(255);"` //鎶撴媿鏃堕棿
-	FirstPersonID string `json:"-" gorm:"uniqueIndex:pic_date_first_person_id;type:varchar(255);"`             //绗竴涓汉鐨処D
-	ObjectIds     string `json:"objectIds" gorm:"type:text"`                                                   //浜嬩欢瀵硅薄锛屽彲浠ユ槸浜猴紝澶氫釜鐢ㄩ�楀彿鍒嗛殧
-	Location      string `json:"location" gorm:"type:varchar(255)"`                                            //鍙戠敓鍦扮偣
-	Building      string `json:"building" gorm:"type:varchar(255);"`                                           //妤兼爧
-	Floor         string `json:"floor"       gorm:"type:varchar(255);"`                                        //妤煎眰
+	Title         string `json:"name" gorm:"type:varchar(255)"`                                                // 棰勮鍚嶇О,鏆傛椂鐢ㄤ换鍔″悕绉�
+	Event         string `json:"event" gorm:"type:varchar(255)"`                                               // 棰勮浜嬩欢
+	ModelID       string `json:"modelID" gorm:"type:varchar(255)"`                                             // 妯″瀷ID
+	ModelTaskID   string `json:"modelTaskID" gorm:"type:varchar(255)"`                                         // 妯″瀷浠诲姟ID
+	OrgID         string `json:"orgID" gorm:"index;column:org_id;type:varchar(299);not null;"`                 // 娲惧嚭鎵� domain unit ID
+	CommunityId   string `json:"communityID" gorm:"index;column:community_id;type:varchar(299);not null;"`     // 灏忓尯ID
+	PicDate       string `json:"picDate"       gorm:"uniqueIndex:pic_date_first_person_id;type:varchar(255);"` // 鎶撴媿鏃堕棿
+	FirstPersonID string `json:"-" gorm:"uniqueIndex:pic_date_first_person_id;type:varchar(255);"`             // 绗竴涓汉鐨処D
+	ObjectIds     string `json:"objectIds" gorm:"type:text"`                                                   // 浜嬩欢瀵硅薄锛屽彲浠ユ槸浜猴紝澶氫釜鐢ㄩ�楀彿鍒嗛殧
+	Location      string `json:"location" gorm:"type:varchar(255)"`                                            // 鍙戠敓鍦扮偣
+	Building      string `json:"building" gorm:"type:varchar(255);"`                                           // 妤兼爧
+	Floor         string `json:"floor"       gorm:"type:varchar(255);"`                                        // 妤煎眰
 
 }
 
@@ -69,6 +70,11 @@
 	return slf
 }
 
+func (slf *ModelTaskResultsSearch) SetTaskId(id string) *ModelTaskResultsSearch {
+	slf.ModelTaskID = id
+	return slf
+}
+
 func (slf *ModelTaskResultsSearch) SetFirstPersonId(firstId string) *ModelTaskResultsSearch {
 	slf.FirstPersonID = firstId
 	return slf
@@ -97,6 +103,10 @@
 		db = db.Where("first_person_id = ?", slf.FirstPersonID)
 	}
 
+	if slf.ModelTaskID != "" {
+		db = db.Where("model_task_id = ?", slf.ModelTaskID)
+	}
+
 	if slf.Keyword != "" {
 		kw := "%" + slf.Keyword + "%"
 		db = db.Where("name like ?", kw)
diff --git a/models/disappear.go b/models/disappear.go
new file mode 100644
index 0000000..e65907f
--- /dev/null
+++ b/models/disappear.go
@@ -0,0 +1,270 @@
+package models
+
+import (
+	"errors"
+	"fmt"
+	"strings"
+	"time"
+
+	"model-engine/db"
+	"model-engine/pkg/logger"
+	"model-engine/service"
+)
+
+type DisappearModel struct {
+	AreaIds       map[string]struct{}
+	Building      string       // 妤兼爧
+	Floor         string       // 妤煎眰
+	AlarmType     db.AlarmType // 棰勮鏂瑰紡
+	KeyPersonType string       // 浜哄憳绫诲瀷
+	PersonLabel   string
+	DisappearTime int    // 娑堝け鏃堕棿, 鍗曚綅灏忔椂
+	AlarmInterval int    // 鎶ヨ鏃堕棿闂撮殧, 鍗曚綅澶�
+	LastDirection string // 鏈�鍚庝竴娆℃姄鎷�
+	PersonAge     int    // 骞撮緞
+	Task          *db.ModelTask
+}
+
+func (m *DisappearModel) Init(task *db.ModelTask) error {
+	m.AreaIds = make(map[string]struct{})
+	for _, a := range task.DomainUnitIds {
+		m.AreaIds[a] = struct{}{}
+	}
+
+	m.Task = task
+	m.Building = task.Building
+	m.Floor = task.Floor
+	m.AlarmType = task.AlarmType
+	m.KeyPersonType = task.PersonType
+	m.PersonLabel = task.PersonLabel
+
+	for _, v := range task.Rules {
+		if v.Alias == "disappearTime" {
+			if val, ok := v.Value.(float64); ok {
+				m.DisappearTime = int(val)
+			}
+		}
+
+		if v.Alias == "alarmInterval" {
+			if val, ok := v.Value.(float64); ok {
+				m.AlarmInterval = int(val)
+			}
+		}
+
+		if v.Alias == "age" {
+			if val, ok := v.Value.(float64); ok {
+				m.PersonAge = int(val)
+			}
+		}
+
+		if v.Alias == "lastDirection" {
+			if val, ok := v.Value.(string); ok {
+				m.LastDirection = val
+			}
+		}
+
+	}
+
+	logger.Debugf("DisappearModel init finish ...task id:%s, name:%s, rule:%+v\n", task.ID, task.Name, m)
+
+	if m.DisappearTime == 0 {
+		logger.Warnf("invalid parameters. task id:%s, name:%s\n", task.ID, task.Name)
+		return errors.New("invalid parameters")
+	}
+
+	return nil
+}
+
+type PersonInfo struct {
+	DocumentNumber     string `json:"document_number"`
+	CommunityId        string `json:"community_id"`
+	OrgId              string `json:"org_id"`
+	PersonName         string `json:"person_name"`
+	IdCard             string `json:"id_card"`
+	LastAppearanceTime int64  `json:"last_appearance_time"`
+	LastDirection      string `json:"last_direction"`
+	LastLocation       string `json:"last_location"`
+}
+
+func (m *DisappearModel) Run() error {
+	results := make([]*db.ModelTaskResults, 0)
+	var ageFilter, labelFilter, keyFilter, lastFilter []PersonInfo
+
+	if m.PersonAge > 0 {
+		err := db.GetDB().Raw(`
+		SELECT
+			s.document_number,
+			s.community_id,
+			s.org_id,
+			p.person_name,
+			p.id_card ,
+			s.last_appearance_time,
+			s.last_direction,
+			s.last_location
+		FROM
+			snapshot_count_summary AS s
+			JOIN person AS p ON p.id = s.document_number 
+		WHERE
+			s.STATUS = 'resident' 
+			AND p.id_card != "" 
+			AND TIMESTAMPDIFF(
+				YEAR,
+				STR_TO_DATE( CASE WHEN LENGTH( id_card ) = 18 THEN SUBSTRING( id_card, 7, 8 ) ELSE NULL END, '%Y%m%d' ),
+			CURDATE( ) > ?
+		`, m.PersonAge).Scan(&ageFilter).Error
+		if err != nil {
+			logger.Warnf(err.Error())
+		}
+
+		if len(ageFilter) == 0 {
+			return fmt.Errorf("no results found that match the age condition %d", m.PersonAge)
+		}
+	}
+
+	if m.PersonLabel != "" {
+		labels := strings.Split(m.PersonLabel, ",")
+		err := db.GetDB().Raw(`
+		SELECT
+			s.document_number,
+			s.community_id,
+			s.org_id,
+			p.person_name,
+			p.id_card,
+			s.last_appearance_time,
+			s.last_direction,
+			s.last_location 
+		FROM
+			snapshot_count_summary AS s
+			JOIN person AS p ON p.id = s.document_number
+			JOIN person_label AS l ON p.id = l.person_id 
+		WHERE
+			l.label_id IN ?
+		`, labels).Scan(&labelFilter).Error
+		if err != nil {
+			logger.Warnf(err.Error())
+		}
+
+		if len(labelFilter) == 0 {
+			return fmt.Errorf("no results found that match the label condition %s", m.PersonLabel)
+		}
+	}
+
+	// 鍚堝苟涓�涓嬫潯浠�
+	if m.PersonAge > 0 && m.PersonLabel != "" {
+		lastFilter = intersectPersonInfo(ageFilter, labelFilter)
+	} else if m.PersonAge > 0 {
+		lastFilter = ageFilter
+	} else if m.PersonLabel != "" {
+		lastFilter = labelFilter
+	}
+
+	if m.KeyPersonType != "" {
+		keyTypes := strings.Split(m.KeyPersonType, ",")
+		err := db.GetDB().Raw(`
+		SELECT
+			s.document_number,
+			s.community_id,
+			s.org_id,
+			p.person_name,
+			p.id_card,
+			s.last_appearance_time,
+			s.last_direction,
+			s.last_location 
+		FROM
+			snapshot_count_summary AS s
+			JOIN person AS p ON p.id = s.document_number
+			JOIN key_person AS k ON k.id_card = p.id_card 
+		WHERE
+			s.key_status = 1 
+			AND p.id_card != "" 
+			AND k.person_type IN ?
+		`, keyTypes).Scan(&keyFilter).Error
+		if err != nil {
+			logger.Warnf(err.Error())
+		}
+	}
+
+	if len(lastFilter) > 0 {
+		lastFilter = intersectPersonInfo(lastFilter, keyFilter)
+	} else {
+		lastFilter = keyFilter
+	}
+
+	for _, p := range lastFilter {
+		if len(m.AreaIds) > 0 {
+			_, o1 := m.AreaIds[p.CommunityId]
+			_, o2 := m.AreaIds[p.OrgId]
+			if !o1 && !o2 {
+				continue
+			}
+		}
+
+		if m.LastDirection != "" {
+			if p.LastDirection != m.LastDirection {
+				continue
+			}
+		}
+
+		if isOlderThanGivenHours(p.LastAppearanceTime, m.DisappearTime) {
+			result := &db.ModelTaskResults{
+				Title:         m.Task.Name,
+				Event:         m.Task.Name,
+				ModelID:       m.Task.ModelID,
+				ModelTaskID:   m.Task.ID,
+				CommunityId:   p.CommunityId,
+				OrgID:         p.OrgId,
+				ObjectIds:     p.DocumentNumber,
+				Location:      p.LastLocation,
+				PicDate:       time.Unix(p.LastAppearanceTime, 0).Format("2006-01-02 15:04:05"),
+				FirstPersonID: p.DocumentNumber,
+			}
+
+			results = append(results, result)
+		}
+	}
+
+	return service.SaveTaskResults(results)
+}
+
+func (m *DisappearModel) Shutdown() error {
+	// 娓呯悊璧勬簮
+	fmt.Println("Shutting down Disappear Model")
+	return nil
+}
+
+func intersectPersonInfo(arr1, arr2 []PersonInfo) []PersonInfo {
+	// 浣跨敤 map 鏉ュ瓨鍌� arr1 涓殑 DocumentNumber
+	resultMap := make(map[string]PersonInfo)
+	var result []PersonInfo
+
+	// 灏嗙涓�涓暟缁勭殑 DocumentNumber 娣诲姞鍒� map 涓�
+	for _, person := range arr1 {
+		resultMap[person.DocumentNumber] = person
+	}
+
+	// 閬嶅巻绗簩涓暟缁勶紝妫�鏌� DocumentNumber 鏄惁鍦� map 涓�
+	for _, person := range arr2 {
+		if _, exists := resultMap[person.DocumentNumber]; exists {
+			// 濡傛灉瀛樺湪浜ら泦锛屽皢璇ュ厓绱犲姞鍏ョ粨鏋滄暟缁�
+			result = append(result, person)
+			// 鍙�夛細濡傛灉甯屾湜姣忎釜浜ら泦鍏冪礌鍙嚭鐜颁竴娆★紝鍙互鍒犻櫎 map 涓殑鍏冪礌
+			delete(resultMap, person.DocumentNumber)
+		}
+	}
+
+	return result
+}
+
+func isOlderThanGivenHours(timestamp int64, hours int) bool {
+	// 灏嗘椂闂存埑杞崲涓烘椂闂村璞�
+	timestampTime := time.Unix(timestamp, 0)
+
+	// 鑾峰彇褰撳墠鏃堕棿
+	currentTime := time.Now()
+
+	// 璁$畻褰撳墠鏃堕棿鍑忓幓鎸囧畾灏忔椂鏁扮殑鏃堕棿
+	timeThreshold := currentTime.Add(-time.Duration(hours) * time.Hour)
+
+	// 鍒ゆ柇鏃堕棿鎴虫槸鍚︽棭浜庤鏃堕棿
+	return timestampTime.Before(timeThreshold)
+}
diff --git a/models/gather_model.go b/models/gather_model.go
index 3724c0d..64aa815 100644
--- a/models/gather_model.go
+++ b/models/gather_model.go
@@ -15,6 +15,7 @@
 
 	"model-engine/config"
 	"model-engine/db"
+	"model-engine/pkg/logger"
 	"model-engine/pkg/set"
 	"model-engine/service"
 )
@@ -81,10 +82,10 @@
 		}
 	}
 
-	fmt.Printf("GatherModel init finish ...task id:%s, name:%s, rule:%+v\n", task.ID, task.Name, m)
+	logger.Debugf("GatherModel init finish ...task id:%s, name:%s, rule:%+v\n", task.ID, task.Name, m)
 
 	if m.GatherPersons == 0 || m.AppearInterval == 0 || m.DaysWindow == 0 || m.Threshold == 0 {
-		fmt.Printf("invalid parameters. task id:%s, name:%s\n", task.ID, task.Name)
+		logger.Warnf("invalid parameters. task id:%s, name:%s\n", task.ID, task.Name)
 		return errors.New("invalid parameters")
 	}
 
diff --git a/pkg/mysqlx/mysqlx.go b/pkg/mysqlx/mysqlx.go
index fc5c043..326b2c5 100644
--- a/pkg/mysqlx/mysqlx.go
+++ b/pkg/mysqlx/mysqlx.go
@@ -1,12 +1,13 @@
 package mysqlx
 
 import (
+	"time"
+
 	"go.uber.org/zap"
 	"gorm.io/driver/mysql"
 	"gorm.io/gorm"
 	"gorm.io/gorm/logger"
 	"gorm.io/gorm/schema"
-	"time"
 )
 
 type Conf struct {
@@ -29,16 +30,21 @@
 		},
 		DisableForeignKeyConstraintWhenMigrating: true,
 	}
-	dbLogger := New(log).LogMode(logger.Info)
-	if !conf.LogMode {
-		dbLogger = dbLogger.LogMode(logger.Silent)
+
+	if log != nil {
+		dbLogger := New(log).LogMode(logger.Info)
+		if !conf.LogMode {
+			dbLogger = dbLogger.LogMode(logger.Silent)
+		}
+
+		gConfig.Logger = dbLogger
 	}
 
-	gConfig.Logger = dbLogger
 	db, err := gorm.Open(mysql.Open(conf.Dsn), gConfig)
 	if err != nil {
 		return err
 	}
+
 	sqlDb, err := db.DB()
 	if err != nil {
 		return err
diff --git a/service/task_results.go b/service/task_results.go
index 56e3ce8..2c72759 100644
--- a/service/task_results.go
+++ b/service/task_results.go
@@ -7,7 +7,7 @@
 
 func SaveTaskResults(results []*db.ModelTaskResults) error {
 	for _, v := range results {
-		err := db.NewModelTaskResultsSearch().SetPicDate(v.PicDate).SetFirstPersonId(v.FirstPersonID).FirstOrCreate(v)
+		err := db.NewModelTaskResultsSearch().SetTaskId(v.ModelTaskID).SetPicDate(v.PicDate).SetFirstPersonId(v.FirstPersonID).FirstOrCreate(v)
 		if err != nil {
 			logger.Errorf("save task result err:%v", err)
 			return err

--
Gitblit v1.8.0