Selaa lähdekoodia

动态生成评分指标

317699326@qq.com 2 päivää sitten
vanhempi
commit
3a95eff3ba
5 muutettua tiedostoa jossa 1840 lisäystä ja 250 poistoa
  1. 151 0
      models/data_manage/manual_classify.go
  2. 22 5
      models/dk.go
  3. 1322 0
      models/target.go
  4. 333 245
      services/dk.go
  5. 12 0
      utils/common.go

+ 151 - 0
models/data_manage/manual_classify.go

@@ -0,0 +1,151 @@
+package data_manage
+
+import (
+	"eta/eta_task/global"
+	"eta/eta_task/utils"
+	"time"
+)
+
+type EdbdataClassify struct {
+	ClassifyId   int       `orm:"column(classify_id);pk" gorm:"primaryKey" description:"分类id"`
+	ClassifyName string    `description:"分类名称"`
+	ParentId     int       `description:"父级id"`
+	CreateTime   time.Time `description:"创建时间"`
+	Sort         int       `description:"排序"`
+	IsShow       int       `description:"是否显示"`
+}
+
+type EdbdataClassifyList struct {
+	ClassifyId   int       `description:"分类id"`
+	ClassifyName string    `description:"分类名称"`
+	ParentId     int       `description:"父级id"`
+	CreateTime   time.Time `description:"创建时间"`
+	Sort         int       `description:"排序"`
+	IsShow       int       `description:"是否显示"`
+	Total        int       `description:"指标总数"`
+}
+
+func AddEdbdataClassify(item *EdbdataClassify) (lastId int64, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Create(item).Error
+	if err != nil {
+		return
+	}
+	lastId = int64(item.ClassifyId)
+	return
+}
+
+type ManualClassifyList struct {
+	ClassifyId   int
+	ClassifyName string
+	ParentId     int
+	CheckList    []int                 `gorm:"-"`
+	Child        []*ManualClassifyList `gorm:"-"`
+}
+
+func GetManualClassifyAllV2() (items []*ManualClassifyList, err error) {
+	var newItems []*ManualClassifyList
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id=0 AND is_show=1 ORDER BY sort ASC ,classify_id ASC `
+	err = o.Raw(sql).Find(&newItems).Error
+	if err != nil {
+		return
+	}
+	classifyLen := len(newItems)
+	for i := 0; i < classifyLen; i++ {
+		var childItems []*ManualClassifyList
+		parentId := newItems[i].ClassifyId
+		childSql := ``
+		childSql = "SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id=? AND is_show=1 ORDER BY sort ASC ,classify_id ASC "
+		err = o.Raw(childSql, parentId).Find(&childItems).Error
+		if err != nil {
+			return
+		}
+		if childItems != nil && len(childItems) > 0 {
+			newItems[i].Child = childItems
+		}
+	}
+
+	for _, v := range newItems {
+		items = append(items, v)
+	}
+	return
+}
+
+type AddManualClassifyReq struct {
+	ClassifyName string `description:"分类名称"`
+	ParentId     int    `description:"父级id,第一级传0"`
+}
+
+func GetManualClassifyCount(classifyName string, parentId int) (count int, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT COUNT(1) AS count FROM edbdata_classify WHERE parent_id=? AND classify_name=? `
+	err = o.Raw(sql, parentId, classifyName).Scan(&count).Error
+	return
+}
+
+func GetManualClassifyByClassifyName(classifyName string) (item *EdbdataClassify, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT * FROM edbdata_classify WHERE classify_name=? `
+	err = o.Raw(sql, classifyName).Find(&item).Error
+	return
+}
+
+func ModifyManualClassifyIsShow(isShow, classifyId, parentId int) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `UPDATE edbdata_classify SET is_show=?,parent_id=? WHERE classify_id=? `
+	err = o.Exec(sql, isShow, parentId, classifyId).Error
+	return
+}
+
+type EditManualClassifyReq struct {
+	ClassifyName string `description:"分类名称"`
+	ClassifyId   int    `orm:"column(classify_id);pk" gorm:"primaryKey" description:"分类id"`
+	ParentId     int    `description:"上级id"`
+}
+
+// DelManualClassifyReq 删除手工指标分类请求
+type DelManualClassifyReq struct {
+	ClassifyId int `description:"分类id"`
+}
+
+func GetManualClassifyById(classifyId int) (item *EdbdataClassify, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT * FROM edbdata_classify WHERE classify_id=? `
+	err = o.Raw(sql, classifyId).Find(&item).Error
+	return
+}
+
+func ModifyManualClassifyName(classifyName string, classifyId, parentId int) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	updateStr := ` classify_name=? `
+	pars := []interface{}{classifyName}
+	if parentId > 0 {
+		updateStr += ` , parent_id=? `
+		pars = append(pars, parentId)
+	}
+	sql := `UPDATE edbdata_classify SET ` + updateStr + ` WHERE classify_id=? `
+
+	pars = append(pars, classifyId)
+	err = o.Exec(sql, pars...).Error
+	return
+}
+
+func GetManualClassifyAllByCondition(condition string) (items []*EdbdataClassifyList, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE is_show=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `  ORDER BY sort ASC `
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+// GetChildManualClassifyCount 根据分类id获取下面存在的子分类数量(展示的)
+func GetChildManualClassifyCount(parentId int) (count int, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT COUNT(1) AS count FROM edbdata_classify WHERE parent_id=? AND is_show = 1`
+	err = o.Raw(sql, parentId).Scan(&count).Error
+	return
+}

+ 22 - 5
models/dk.go

@@ -15,18 +15,19 @@ type WechatArticle struct {
 	TextContent string
 }
 
-func GetWechatArticleTags(startTime, endTime string) (list []*WechatArticleTag, err error) {
-	sql := `SELECT a.tag_name,GROUP_CONCAT(a.article_id) AS article_id
+func GetWechatArticleTags(classifyName, startTime, endTime string, startSize, pageSize int) (list []*WechatArticleTag, err error) {
+	sql := `SELECT a.tag_name,GROUP_CONCAT(DISTINCT a.article_id) AS article_id
 		FROM article_dfa_tag_mapping AS a
 		INNER JOIN wechat_article AS b ON a.article_id=b.wechat_article_id
+		INNER JOIN dfa_tag_sensitive_word_mapping AS c ON a.tag_name=c.tag_name
 		WHERE a.tag_name<>''
 		AND b.article_create_time >= ?
 		AND b.article_create_time <= ?
 		AND a.source='wechat'
-		AND a.tag_name IN('原油')
-		GROUP BY a.tag_name `
+		AND c.classify_name=?
+		GROUP BY a.tag_name LIMIT ?,?`
 
-	err = global.DbMap[utils.DbNameAI].Raw(sql, startTime, endTime).Find(&list).Error
+	err = global.DbMap[utils.DbNameAI].Raw(sql, startTime, endTime, classifyName, startSize, pageSize).Find(&list).Error
 	return list, err
 }
 
@@ -47,3 +48,19 @@ func ModifyWechatArticleSummary(articleId string, isSummary int) (err error) {
 	err = global.DbMap[utils.DbNameAI].Exec(sql, isSummary).Error
 	return err
 }
+
+func GetWechatArticleTagsTotal(classifyName, startTime, endTime string) (total int, err error) {
+	sql := `SELECT COUNT(1) AS total
+		FROM article_dfa_tag_mapping AS a
+		INNER JOIN wechat_article AS b ON a.article_id=b.wechat_article_id
+		INNER JOIN dfa_tag_sensitive_word_mapping AS c ON a.tag_name=c.tag_name
+		WHERE a.tag_name<>''
+		AND b.article_create_time >= ?
+		AND b.article_create_time <= ?
+		AND a.source='wechat'
+		AND c.classify_name=?
+		GROUP BY a.tag_name`
+
+	err = global.DbMap[utils.DbNameAI].Raw(sql, startTime, endTime, classifyName).Scan(&total).Error
+	return total, err
+}

+ 1322 - 0
models/target.go

@@ -0,0 +1,1322 @@
+package models
+
+import (
+	sql2 "database/sql"
+	"eta/eta_task/global"
+	"eta/eta_task/utils"
+	"gorm.io/gorm"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type DataList struct {
+	TradeCode    string  `gorm:"column:TRADE_CODE" description:"指标编码"`
+	SecName      string  `gorm:"column:SEC_NAME" description:"指标名称"`
+	Unit         string  `gorm:"column:UNIT" description:"单位"`
+	Remark       string  `gorm:"column(REMARK)" description:"备注"`
+	Frequency    string  `description:"频度"`
+	ClassifyId   int     `description:"分类id"`
+	ClassifyName string  `description:"分类名称"`
+	Dt           string  `gorm:"column:DT" description:"录入日期"`
+	Close        float64 `gorm:"column:CLOSE" description:"录入值"`
+	ModifyTime   string  `description:"修改时间"`
+}
+
+type DataListResp struct {
+	List   []*DataList
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+func GetDataList(condition string, pars []interface{}, startSize, pageSize int) (items []*DataList, err error) {
+	sql := `select a.TRADE_CODE,a.SEC_NAME,a.UNIT,a.frequency,a.classify_id,b.classify_name,c.DT,c.CLOSE,c.modify_time FROM edbdata AS c
+                inner join edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+                left join edbdata_classify AS b ON a.classify_id=b.classify_id
+                where a.classify_id>0`
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` order by c.DT desc limit ?,? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	pars = append(pars, startSize, pageSize)
+	err = o.Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetDataListCount(condition string, pars []interface{}) (count int, err error) {
+	sql := ` select count(1) as count FROM edbdata AS c
+                    inner join edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE    
+                    left join edbdata_classify AS b ON a.classify_id=b.classify_id
+                    where a.classify_id>0 `
+	if condition != "" {
+		sql += condition
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	var countNull sql2.NullInt64
+	err = o.Raw(sql, pars...).Scan(&countNull).Error
+	if err != nil {
+		return
+	}
+	if countNull.Valid {
+		count = int(countNull.Int64)
+	}
+	return
+}
+
+type DataAddReq struct {
+	TradeCode  string `description:"指标唯一编码"`
+	CreateDate string `description:"创建日期"`
+	Close      string `description:"录入值"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *Edbdata) AfterFind(db *gorm.DB) (err error) {
+	m.Dt = utils.GormDateStrToDateStr(m.Dt)
+
+	return
+}
+
+type EdbDataNextDateTime struct {
+	TradeCode  string    `gorm:"column:TRADE_CODE;pk" description:"指标编码"`
+	Dt         string    `gorm:"column:DT" description:"日期"`
+	Close      string    `gorm:"column:CLOSE" description:"值"`
+	ModifyTime time.Time `gorm:"column:modify_time" description:"修改时间"`
+
+	NextDateTime string `description:"下期日期"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *EdbDataNextDateTime) AfterFind(db *gorm.DB) (err error) {
+	m.Dt = utils.GormDateStrToDateStr(m.Dt)
+	m.NextDateTime = utils.GormDateStrToDateStr(m.NextDateTime)
+
+	return
+}
+
+func GetDataInfo(tradeCode, creteDate string) (item *Edbdata, err error) {
+	sql := " SELECT * FROM edbdata WHERE TRADE_CODE=? AND DT=? "
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, tradeCode, creteDate).First(&item).Error
+	return
+}
+
+func AddEdbdata(item *Edbdata) (lastId int64, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Create(item).Error
+	return
+}
+
+type DataEditReq struct {
+	TradeCode     string      `description:"指标唯一编码"`
+	CreateDate    string      `description:"创建日期"`
+	Close         interface{} `description:"录入值"`
+	OldCreateDate string      `description:"旧的录入日期"`
+}
+
+// BatchDataEditReq 批量修改指标
+type BatchDataEditReq struct {
+	OldCreateDate string        `description:"旧的录入日期"`
+	CreateDate    string        `description:"新的录入日期"`
+	List          []DataEditReq `description:"需要修改的数据"`
+}
+
+// EditEdbdata 编辑数据
+func EditEdbdata(item *Edbdata) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` UPDATE edbdata SET CLOSE = ?,modify_time=NOW() WHERE TRADE_CODE = ? AND DT = ? `
+	err = o.Exec(sql, item.Close, item.TradeCode, item.Dt).Error
+	return
+}
+
+type EdbdataDeleteRecord struct {
+	Id         int       `gorm:"column:id;primaryKey;autoIncrement"`
+	TradeCode  string    `gorm:"column:TRADE_CODE" description:"指标编码"`
+	Dt         string    `gorm:"column:DT" description:"日期"`
+	Close      string    `gorm:"column:CLOSE" description:"值"`
+	ModifyTime time.Time `gorm:"column:modify_time" description:"修改时间"`
+	CreateTime time.Time
+	SysUserId  int
+}
+
+func AddEdbdataDeleteRecord(item *EdbdataDeleteRecord) (lastId int64, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Create(item).Error
+	if err != nil {
+		return
+	}
+	lastId = int64(item.Id)
+	return
+}
+
+// DeleteEdbData 根据指标code和日期删除数据
+func DeleteEdbData(tradeCode, dt string) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` DELETE FROM edbdata WHERE TRADE_CODE = ? AND DT = ? `
+	err = o.Exec(sql, tradeCode, dt).Error
+	return
+}
+
+// DeleteAllEdbData 根据指标code删除数据
+func DeleteAllEdbData(tradeCode string) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` DELETE FROM edbdata WHERE TRADE_CODE = ? `
+	err = o.Exec(sql, tradeCode).Error
+	return
+}
+
+type Edbinfo struct {
+	TradeCode    string  `gorm:"column:TRADE_CODE;autoIncrement:false;primaryKey" description:"指标code"`
+	SecName      string  `gorm:"column:SEC_NAME;" description:"指标名称"`
+	Unit         string  `gorm:"column:UNIT;" description:"单位"`
+	Remark       string  `gorm:"column:REMARK;" description:"备注"`
+	Frequency    string  `gorm:"column:frequency" description:"频度"`
+	ClassifyId   int     `gorm:"column:classify_id" description:"分类id"`
+	ClassifyName string  `gorm:"-" description:"分类名称"`
+	CreateDate   string  `gorm:"column:create_date" description:"创建时间"`
+	UserId       int     `gorm:"column:user_id" description:"录入用户id"`
+	UserName     string  `gorm:"column:user_name" description:"录入用户名称"`
+	NoticeTime   string  `gorm:"column:notice_time" description:"通知时间"`
+	Mobile       string  `gorm:"column:mobile" description:"录入者手机号"`
+	Sort         int     `gorm:"column:sort" description:"排序"`
+	ModifyTime   string  `description:"最近一次更新时间"`
+	IsJoinEdb    int8    `description:"指标库是否已添加:0-否;1-是"`
+	StartDate    string  `description:"数据开始日期"`
+	EndDate      string  `description:"数据结束日期"`
+	LatestValue  float64 `description:"指标最新值"`
+}
+
+type EdbinfoItem struct {
+	TradeCode    string  `gorm:"column:TRADE_CODE;primaryKey;autoIncrement:false;" orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string  `gorm:"column:SEC_NAME" orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string  `gorm:"column:UNIT" orm:"column(UNIT);" description:"单位"`
+	Remark       string  `gorm:"column:REMARK" orm:"column(REMARK);" description:"备注"`
+	Frequency    string  `description:"频度"`
+	ClassifyId   int     `description:"分类id"`
+	ClassifyName string  `description:"分类名称"`
+	CreateDate   string  `description:"创建时间"`
+	UserId       int     `description:"录入用户id"`
+	UserName     string  `description:"录入用户名称"`
+	NoticeTime   string  `description:"通知时间"`
+	Mobile       string  `description:"录入者手机号"`
+	ModifyTime   string  `description:"最近一次更新时间"`
+	StartDate    string  `description:"数据开始日期"`
+	EndDate      string  `description:"数据结束日期"`
+	LatestValue  float64 `description:"指标最新值"`
+}
+
+// EdbParamsInfo 指标数据结构体
+type EdbParamsInfo struct {
+	Unit      string `description:"单位" gorm:"column:UNIT"`
+	Frequency string `gorm:"column:frequency;" description:"单位"`
+}
+
+// GetEdbUnitList 获取指标单位
+func GetEdbUnitList() (items []*EdbParamsInfo, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT UNIT,Frequency from edbinfo group by UNIT`
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+type TargetListResp struct {
+	List   []*EdbinfoItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+type EdbinfoAddReq struct {
+	SecName    string `description:"指标名称"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	ClassifyId int    `description:"分类id"`
+	NoticeTime string `description:"通知时间"`
+}
+
+// GetMaxTradeCode 获取指标最大trade_code
+func GetMaxTradeCode() (max_trade_code string, err error) {
+	sql := " SELECT MAX(TRADE_CODE) AS max_trade_code FROM edbinfo WHERE LEFT(TRADE_CODE,1)='W' "
+	o := global.DbMap[utils.DbNameManualIndex]
+	var codeNull sql2.NullString
+	err = o.Raw(sql).Scan(&codeNull).Error
+	max_trade_code = "W00"
+	if codeNull.Valid {
+		max_trade_code = codeNull.String
+	}
+	return
+}
+
+func GetEdbinfoBySecName(secName string) (item *Edbinfo, err error) {
+	sql := `SELECT * FROM edbinfo WHERE SEC_NAME=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, secName).First(&item).Error
+	return
+}
+
+func GetEdbinfoByTradeCode(tradeCode string) (item *Edbinfo, err error) {
+	sql := `SELECT * FROM edbinfo WHERE TRADE_CODE=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, tradeCode).First(&item).Error
+	return
+}
+
+func AddEdbinfo(tradeCode, secName, unit, remark, frequency, noticeTime string, classifyId int, userId int, userName string) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	currTime := time.Now().Format(utils.FormatDateTime)
+	edbInfo := &Edbinfo{
+		TradeCode:  tradeCode,
+		SecName:    secName,
+		Unit:       unit,
+		Remark:     remark,
+		Frequency:  frequency,
+		ClassifyId: classifyId,
+		CreateDate: currTime,
+		UserId:     userId,
+		UserName:   userName,
+		NoticeTime: noticeTime,
+		Mobile:     "",
+		ModifyTime: currTime,
+		IsJoinEdb:  0,
+	}
+	err = o.Create(edbInfo).Error
+	return
+}
+
+func AddEdbinfoUser(tradeCode, mobile string) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `INSERT INTO edbinfo_user(TRADE_CODE, mobile) VALUES (?,?)`
+	err = o.Exec(sql, tradeCode, mobile).Error
+	return
+}
+
+type EdbinfoEditReq struct {
+	TradeCode  string `description:"指标code"`
+	SecName    string `description:"指标名称"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	ClassifyId int    `description:"分类id"`
+	NoticeTime string `description:"通知时间"`
+}
+
+type SearchTargetListResp struct {
+	List []*Edbinfo
+}
+
+type EdbdataClassify struct {
+	ClassifyId   int
+	ClassifyName string
+	ParentId     int
+	EdbInfoTotal int
+	TradeCode    string
+	UniqueCode   string
+}
+
+type EdbdataClassifyList struct {
+	ClassifyId   int
+	ClassifyName string
+	ParentId     int
+	Child        []*EdbdataClassify `gorm:"-"`
+	TradeCode    string
+	UniqueCode   string
+}
+
+func GetEdbdataClassify(userId int64) (items []*EdbdataClassifyList, err error) {
+	var newItems []*EdbdataClassifyList
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id=0 `
+	err = o.Raw(sql).Find(&newItems).Error
+	if err != nil {
+		return
+	}
+	classifyLen := len(newItems)
+
+	// 获取子集分类
+	var allChildItems []*EdbdataClassify
+	if userId > 0 {
+		userClassifyList, _ := GetManualUserClassify(int(userId))
+		var userIdArr []int
+		for _, v := range userClassifyList {
+			userIdArr = append(userIdArr, v.ClassifyId)
+		}
+		num := len(userClassifyList)
+		if num > 0 {
+			childSql := "SELECT a.classify_id,a.classify_name,a.parent_id FROM edbdata_classify AS a WHERE a.is_show=1 and a.classify_id IN(" + utils.GetOrmInReplace(num) + ") ORDER BY a.create_time ASC "
+			err = o.Raw(childSql, userIdArr).Find(&allChildItems).Error
+		}
+	} else {
+		childSql := "SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE is_show=1 ORDER BY create_time ASC "
+		err = o.Raw(childSql).Find(&allChildItems).Error
+	}
+	if err != nil {
+		return
+	}
+
+	for i := 0; i < classifyLen; i++ {
+		var childItems []*EdbdataClassify
+		parentId := newItems[i].ClassifyId
+		for _, v := range allChildItems {
+			if v.ParentId == parentId {
+				childItems = append(childItems, v)
+			}
+		}
+		newItems[i].Child = childItems
+	}
+	for _, v := range newItems {
+		childLen := len(v.Child)
+		if childLen > 0 {
+			items = append(items, v)
+		}
+	}
+	return
+}
+
+type ManualUserClassify struct {
+	ManualUserClassifyId int `gorm:"column:manual_user_classify_id;primaryKey"`
+	AdminId              int
+	ClassifyId           int
+	CreateTime           time.Time
+}
+
+func GetManualUserClassify(sysUserId int) (list []*ManualUserClassify, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM manual_user_classify WHERE admin_id=? `
+	err = o.Raw(sql, sysUserId).Find(&list).Error
+	return
+}
+
+type EdbdataClassifyResp struct {
+	List []*EdbdataClassifyList
+}
+
+func GetTargetBySecName(secName string) (item *Edbinfo, err error) {
+	sql := `SELECT * FROM edbinfo WHERE SEC_NAME=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, secName).First(&item).Error
+	return
+}
+
+// 更新指标数据信息
+func (edbinfo *Edbinfo) Update(cols []string) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Select(cols).Updates(edbinfo).Error
+	return
+}
+
+//func ModifyTargetClassifyId(tradeCode string, classifyId int) (err error) {
+//	sql := `UPDATE edbinfo SET classify_id=? WHERE TRADE_CODE=? `
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	err = o.Exec(sql, classifyId, tradeCode).Error
+//	return
+//}
+
+//func GetTargetsDataCount(tradeCode, dt string) (count int, err error) {
+//	sql := `SELECT COUNT(1) AS count FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	err = o.Raw(sql, tradeCode, dt).QueryRow(&count)
+//	return
+//}
+
+// GetTargetsDataList 根据code获取指标数据列表
+func GetTargetsDataList(tradeCode string) (items []*Edbdata, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT * FROM edbdata WHERE TRADE_CODE=? ORDER BY DT ASC `
+	err = o.Raw(sql, tradeCode).Find(&items).Error
+	return
+}
+
+//func GetTargetsData(tradeCode, dt string) (item *Edbdata, err error) {
+//	sql := `SELECT * FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	err = o.Raw(sql, tradeCode, dt).First(&item).Error
+//	return
+//}
+
+func ModifyTargetsDataByImport(tradeCode, dt, close string) (err error) {
+	sql := `UPDATE  edbdata SET CLOSE=?,modify_time=NOW() WHERE  TRADE_CODE=? AND DT=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Exec(sql, close, tradeCode, dt).Error
+	return
+}
+
+func AddTargetsDataByImport(tradeCode, dt, close string) (err error) {
+	sql := `INSERT INTO edbdata(TRADE_CODE, DT,CLOSE, modify_time)VALUES(?,?,?,NOW()) `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Exec(sql, tradeCode, dt, close).Error
+	return
+}
+
+type EdbdataImportResp struct {
+	Status       int
+	Msg          string
+	SuccessCount int
+	FailCount    int
+	IndexCount   int `description:"指标数"`
+}
+
+type DataListForExport struct {
+	TradeCode    string `gorm:"column:TRADE_CODE" description:"指标code"`
+	SecName      string `gorm:"column:SEC_NAME" description:"指标名称"`
+	Unit         string `gorm:"column:UNIT" description:"单位"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	NoticeTime   string `description:"通知时间"`
+	ClassifyName string
+	Dt           string  `gorm:"column:DT" description:"日期"`
+	Close        float64 `gorm:"column:CLOSE" description:"值"`
+}
+
+type DataDeleteReq struct {
+	TradeCode  string `description:"指标唯一编码"`
+	CreateDate string `description:"数据录入日期"`
+}
+
+func DataDelete(tradeCode, createDate, close string, modifyTime time.Time, sysUserId int) (err error) {
+	to := global.DbMap[utils.DbNameManualIndex].Begin()
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	recordSql := ` INSERT INTO edbdata_delete_record(TRADE_CODE,DT,CLOSE,modify_time,create_time,sys_user_id) 
+                 VALUES(?,?,?,?,?,?)`
+	err = to.Exec(recordSql, tradeCode, createDate, close, modifyTime, time.Now(), sysUserId).Error
+	sql := ` DELETE FROM edbdata WHERE TRADE_CODE = ? AND DT = ? `
+	err = to.Exec(sql, tradeCode, createDate).Error
+	return
+}
+
+//func GetTargetInfoCount(tradeCode string) (count int, err error) {
+//	sql := ` SELECT COUNT(1) AS count FROM edbdata AS c
+//           INNER JOIN edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+//           WHERE a.TRADE_CODE=? `
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	err = o.Raw(sql, tradeCode).QueryRow(&count)
+//	return
+//}
+
+type TargetDeleteReq struct {
+	TradeCode string `description:"指标唯一编码"`
+}
+
+func TargetDelete(tradeCode string) (err error) {
+	to := global.DbMap[utils.DbNameManualIndex].Begin()
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := " DELETE FROM edbinfo WHERE TRADE_CODE = ? "
+	err = to.Exec(sql, tradeCode).Error
+
+	sql = " DELETE FROM edbdata WHERE TRADE_CODE = ? "
+	err = to.Exec(sql, tradeCode).Error
+	return
+}
+
+type Researcher struct {
+	AdminId     int    `description:"系统用户id"`
+	AdminName   string `description:"系统用户名称"`
+	RealName    string `description:"系统用户姓名"`
+	Role        string `description:"系统用户角色"`
+	Mobile      string `description:"手机号"`
+	TargetCount int    `description:"指标数量"`
+}
+
+type ResearcherListResp struct {
+	List []*Researcher
+}
+
+func GetResearcherEntry() (items []*Researcher, err error) {
+	sql := ` SELECT admin_id,admin_name,real_name,mobile,0 as target_count FROM admin WHERE role_type=1 `
+	o := global.DEFAULT_DB
+	sql = utils.ReplaceDriverKeywords("", sql)
+	err = o.Raw(sql).Find(&items).Error
+	researchLen := len(items)
+	edbO := global.DbMap[utils.DbNameManualIndex]
+	for i := 0; i < researchLen; i++ {
+		var count int
+		mobile := items[i].Mobile
+		sqlCount := ` SELECT COUNT(DISTINCT a.TRADE_CODE) AS count FROM  edbinfo_user AS a
+            INNER JOIN edbinfo AS b ON a.TRADE_CODE=b.TRADE_CODE
+            WHERE a.mobile=? AND b.classify_id>0 `
+		var countNull sql2.NullInt64
+		err = edbO.Raw(sqlCount, mobile).Scan(&countNull).Error
+		if err != nil {
+			return
+		}
+		if countNull.Valid {
+			count = int(countNull.Int64)
+		}
+
+		items[i].TargetCount = count
+	}
+	return
+}
+
+func GetResearcherEntryByMobile(mobile string) (items []*Researcher, err error) {
+	sql := ` SELECT admin_id,admin_name,real_name,mobile,0 as target_count FROM admin WHERE  role_type=1 `
+	if mobile != "" {
+		sql += ` AND mobile IN(` + mobile + `)`
+	}
+	sql = utils.ReplaceDriverKeywords("", sql)
+	o := global.DEFAULT_DB
+	err = o.Raw(sql).Find(&items).Error
+	researchLen := len(items)
+	edbO := global.DbMap[utils.DbNameManualIndex]
+	for i := 0; i < researchLen; i++ {
+		var count int
+		mobile := items[i].Mobile
+		sqlCount := ` SELECT COUNT(DISTINCT a.TRADE_CODE) AS count FROM  edbinfo_user AS a
+            INNER JOIN edbinfo AS b ON a.TRADE_CODE=b.TRADE_CODE
+            WHERE a.mobile=? AND b.classify_id>0 `
+		var countNull sql2.NullInt64
+		err = edbO.Raw(sqlCount, mobile).Scan(&countNull).Error
+		if err != nil {
+			return
+		}
+		if countNull.Valid {
+			count = int(countNull.Int64)
+		}
+
+		items[i].TargetCount = count
+	}
+	return
+}
+
+type EdbinfoItems struct {
+	TradeCode    string `gorm:"column:TRADE_CODE;autoIncrement:false;primaryKey" description:"指标编码"`
+	SecName      string `gorm:"column:SEC_NAME;" description:"指标名称"`
+	Unit         string `gorm:"column:UNIT;" description:"单位"`
+	Remark       string `gorm:"column:REMARK;" description:"备注"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	CreateDate   string `description:"创建时间"`
+	UserId       int    `description:"录入用户id"`
+	NoticeTime   string `description:"通知时间"`
+	Mobile       string `description:"录入者手机号"`
+	ModifyDate   string `description:"待更新日期"`
+	Status       string `description:"状态:未完成/完成"`
+}
+
+type TargetItemsResp struct {
+	List SortEdbInfo
+}
+
+type SortEdbInfo []EdbinfoItems
+
+// 获取此 slice 的长度
+func (p SortEdbInfo) Len() int { return len(p) }
+
+// 根据元素的状态降序排序
+func (p SortEdbInfo) Less(i, j int) bool {
+	return p[i].Status > p[j].Status
+}
+
+// 交换数据
+func (p SortEdbInfo) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// 嵌套结构体  将继承 SortEdbInfo 的所有属性和方法
+// 所以相当于SortByName 也实现了 Len() 和 Swap() 方法
+type SortByStatus struct{ SortEdbInfo }
+
+// 根据元素的姓名长度降序排序 (此处按照自己的业务逻辑写)
+func (p SortByStatus) Less(i, j int) bool {
+	return len(p.SortEdbInfo[i].Status) > len(p.SortEdbInfo[j].Status)
+}
+
+type SortByModifyDate struct{ SortEdbInfo }
+
+// 根据元素的年龄降序排序 (此处按照自己的业务逻辑写)
+func (p SortByModifyDate) Less(i, j int) bool {
+	return p.SortEdbInfo[i].ModifyDate > p.SortEdbInfo[j].ModifyDate
+}
+
+type DataCheckResp struct {
+	Status int    `description:"状态:1:该日期已存在数据,是否确认修改?,0:数据不存在"`
+	Close  string `description:"值"`
+}
+
+type TargetCheckResp struct {
+	Status int `description:"状态:1:该指标有关联数据,请先删除数据,0:指标不存在关联数据,可直接删除"`
+}
+
+type EdbdataExportList struct {
+	TradeCode    string `gorm:"column:TRADE_CODE;" description:"指标code"`
+	SecName      string `gorm:"column:SEC_NAME;" description:"指标名称"`
+	Unit         string `gorm:"column:UNIT;" description:"单位"`
+	Remark       string `gorm:"column:REMARK;" description:"备注"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	CreateDate   string `description:"创建时间"`
+	Dt           string `gorm:"column:DT;" description:"最新一次录入时间"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *EdbdataExportList) AfterFind(db *gorm.DB) (err error) {
+	m.Dt = utils.GormDateStrToDateStr(m.Dt)
+
+	return
+}
+
+func GetEdbdataSecName(condition string, pars []interface{}) (items []*EdbdataExportList, err error) {
+	//sql := `SELECT a.TRADE_CODE,a.SEC_NAME,a.frequency,a.UNIT,MAX(c.DT) AS Dt
+	//	        FROM edbdata AS c
+	//	        INNER JOIN edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+	//	        INNER JOIN edbinfo_user AS d ON a.TRADE_CODE=d.TRADE_CODE
+	//	        LEFT JOIN edbdata_classify AS b ON a.classify_id=b.classify_id
+	//	        WHERE a.classify_id>0`
+	sql := `SELECT a.TRADE_CODE,a.SEC_NAME,a.frequency,a.UNIT,MAX(c.DT) AS Dt,b.classify_name
+		        FROM edbdata AS c
+		        INNER JOIN edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+		        LEFT JOIN edbdata_classify AS b ON a.classify_id=b.classify_id
+		        WHERE a.classify_id>0`
+	if condition != "" {
+		sql += condition
+	}
+	sql += " GROUP BY a.TRADE_CODE ORDER BY a.TRADE_CODE ASC "
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetEdbDataFrequency(classifyId int) (items []*string, err error) {
+	sql := `SELECT DISTINCT frequency FROM edbinfo where classify_id=? AND frequency IS NOT NULL ORDER BY FIELD(frequency,'日度','周度','月度','季度','半年度','年度') `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, classifyId).Find(&items).Error
+	return
+}
+
+// GetEdbDataFrequencyByClassifyIdList
+// @Description: 根据分类列表获取所有的频度
+// @author: Roc
+// @datetime 2024-08-15 17:51:13
+// @param classifyIdList []int
+// @return items []*string
+// @return err error
+func GetEdbDataFrequencyByClassifyIdList(classifyIdList []int) (items []string, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	sql := `SELECT DISTINCT frequency FROM edbinfo where classify_id in (` + utils.GetOrmInReplace(num) + `) AND frequency IS NOT NULL ORDER BY FIELD(frequency,'日度','周度','月度','季度','半年度','年度') `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, classifyIdList).Find(&items).Error
+	return
+}
+
+func GetEdbDataFrequencyByKeyord(keyword string) (items []string, err error) {
+	sql := `SELECT DISTINCT frequency FROM edbinfo where SEC_NAME=? ORDER BY FIELD(frequency,'日度','周度','月度','季度','半年度','年度') `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, keyword).Find(&items).Error
+	return
+}
+
+type EdbdataList struct {
+	Dt string `gorm:"column:DT;" description:"录入时间"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *EdbdataList) AfterFind(db *gorm.DB) (err error) {
+	m.Dt = utils.GormDateStrToDateStr(m.Dt)
+
+	return
+}
+
+func GetEdbdataList(tradeCode string) (items []*EdbdataList, err error) {
+	sql := ` SELECT  DT FROM edbdata WHERE TRADE_CODE IN(` + tradeCode + `)  GROUP BY DT ORDER BY DT DESC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+type EdbdataItem struct {
+	TradeCode string  `gorm:"column:TRADE_CODE;" description:"指标code"`
+	Dt        string  `gorm:"column:DT;" description:"最新一次录入时间"`
+	Close     float64 `gorm:"column:CLOSE;" description:"值"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *EdbdataItem) AfterFind(db *gorm.DB) (err error) {
+	m.Dt = utils.GormDateStrToDateStr(m.Dt)
+
+	return
+}
+
+func GetEdbdataValueByTradeCode(tradeCode, dt string) (item *EdbdataItem, err error) {
+	sql := ` SELECT  TRADE_CODE,DT,CLOSE FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, tradeCode, dt).First(&item).Error
+	return
+}
+
+func GetEdbdataAllByTradeCode(tradeCode string) (items []*EdbdataItem, err error) {
+	sql := ` SELECT * FROM edbdata WHERE TRADE_CODE=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, tradeCode).Find(&items).Error
+	return
+}
+
+func GetEdbdataClassifyByParentId(parentId int) (items []*EdbdataClassify, err error) {
+	sql := ` SELECT * FROM edbdata_classify WHERE parent_id=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, parentId).Find(&items).Error
+	return
+}
+
+type LzPriceClassify struct {
+	ProductName string
+}
+
+func GetLzPriceClassify() (items []*LzPriceClassify, err error) {
+	sql := ` SELECT product_name  FROM longzhongpriceinfo GROUP BY product_name ORDER BY product_name DESC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+type Longzhongpriceinfo struct {
+	LongzhongpriceinfoId int `gorm:"column:longzhongpriceinfo_id;primaryKey"`
+	Standard             string
+	ModelName            string
+	Unit                 string
+	AreaName             string
+	PriceType            string
+	Memo                 string
+	PriceId              string
+	ProductName          string
+	InfoType             string
+	InfoTypeRemark       string
+	MarketName           string
+	ManufactureName      string
+}
+
+func GetLongzhongpriceinfoByClassifyName(productName string) (items []*Longzhongpriceinfo, err error) {
+	sql := `SELECT * FROM longzhongpriceinfo WHERE product_name=? ORDER BY longzhongpriceinfo_id ASC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, productName).Find(&items).Error
+	return
+}
+
+func GetLongzhongPriceDataMaxCount(productName string) (count int, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT MAX(t.num) AS count FROM (
+				SELECT COUNT(1) AS num  FROM longzhongpriceinfo AS a
+				INNER JOIN longzhongpricedata AS b ON a.longzhongpriceinfo_id=b.longzhongpriceinfo_id
+				WHERE a.product_name=?
+				GROUP BY a.product_name
+			)AS t `
+	//err = o.Raw(sql, productName).QueryRow(&count)
+	var countNull sql2.NullInt64
+	err = o.Raw(sql, productName).Scan(&countNull).Error
+	if err != nil {
+		return
+	}
+	if countNull.Valid {
+		count = int(countNull.Int64)
+	}
+	return
+}
+
+type LongzhongpricedataItems struct {
+	LongzhongpricedataId int `gorm:"column:longzhongpricedata_id;primaryKey"`
+	LongzhongpriceinfoId int
+	PriceDate            string
+	Memo                 string
+	Price                float64
+	CnyPrice             float64
+	ZsyPrice             float64
+	ZshPrice             float64
+	LowPrice             float64
+	HighPrice            float64
+	RisePrice            float64
+	TonPrice             float64
+	PriceType            string
+	UpdateDate           string
+}
+
+func GetLongzhongPriceDataById(lzPriceInfoId int) (items []*LongzhongpricedataItems, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT DISTINCT a.longzhongpriceinfo_id,a.price_date,a.memo,a.price,a.cny_price,a.zsy_price,a.zsh_price,a.low_price,a.high_price,a.rise_price,a.ton_price,a.price_type,a.update_date  
+			 FROM longzhongpricedata AS a
+			 WHERE longzhongpriceinfo_id=? ORDER BY price_date DESC `
+	err = o.Raw(sql, lzPriceInfoId).Find(&items).Error
+	return
+}
+
+func GetLzSurveyClassify() (items []*LzPriceClassify, err error) {
+	sql := ` SELECT breed_name AS product_name  FROM longzhong_survey_product GROUP BY breed_name ORDER BY breed_name DESC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+type LongzhongSurveyProduct struct {
+	SurveyProductId      int `gorm:"column:survey_product_id;primaryKey"`
+	ProjectQuotaId       int64
+	BreedId              string
+	BreedName            string
+	QuotaId              string
+	QuotaName            string
+	UnitId               string
+	UnitName             string
+	SampleType           int64
+	SampleId             string
+	SampleName           string
+	DeviceId             string
+	Device               string
+	ProductCraftId       string
+	ProductCraft         string
+	ProductLine          string
+	InputMode            int64
+	Frequency            int64
+	InputValue           string
+	TaskShouldFinishTime int
+	CustomId             string
+	CustomType           int64
+	Custom               string
+	QuotaSampleId        int64
+	StartDate            string
+	EndDate              string
+	LzCode               string
+}
+
+func (obj *LongzhongSurveyProduct) AfterFind(tx *gorm.DB) (err error) {
+	obj.StartDate = utils.GormDateStrToDateStr(obj.StartDate)
+	obj.EndDate = utils.GormDateStrToDateStr(obj.EndDate)
+	return
+}
+func GetLongzhongSurveyProductByClassifyName(productName string) (items []*LongzhongSurveyProduct, err error) {
+	sql := `SELECT * FROM longzhong_survey_product WHERE breed_name=? ORDER BY survey_product_id ASC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, productName).Find(&items).Error
+	return
+}
+
+func GetLzSurveyProductByNameAndFrequency(productName string, frequency int) (items []*LongzhongSurveyProduct, err error) {
+
+	sql := `SELECT * FROM longzhong_survey_product WHERE breed_name=? AND frequency=? ORDER BY survey_product_id ASC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, productName, frequency).Find(&items).Error
+	return
+}
+
+func GetExportLzSurveyProductByBreedIds(breedIds []string) (items []*LongzhongSurveyProduct, err error) {
+	if len(breedIds) == 0 {
+		return
+	}
+	field := ` survey_product_id, breed_id, breed_name, sample_name, custom, quota_name, lz_code, frequency, unit_name, end_date, input_value `
+	sql := `SELECT ` + field + ` FROM longzhong_survey_product WHERE breed_id IN (` + utils.GetOrmInReplace(len(breedIds)) + `) ORDER BY breed_id ASC, frequency ASC, survey_product_id ASC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, breedIds).Find(&items).Error
+	return
+}
+
+func GetLzFrequency(productName string) (items []*int, err error) {
+	sql := `SELECT DISTINCT frequency FROM longzhong_survey_product WHERE breed_name=? ORDER BY frequency`
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql, productName).Find(&items).Error
+	return
+}
+
+// EdbInfoItem
+type EdbInfoItem struct {
+	TradeCode        string                 `gorm:"column:TRADE_CODE;autoIncrement:false;primaryKey" description:"指标编码"`
+	SecName          string                 `gorm:"column:SEC_NAME;" description:"指标名称"`
+	Unit             string                 `gorm:"column:UNIT;" description:"单位"`
+	Remark           string                 `gorm:"column:REMARK;" description:"备注"`
+	Frequency        string                 `description:"频度"`
+	ClassifyId       int                    `description:"分类id"`
+	ClassifyName     string                 `description:"分类名称"`
+	CreateDate       string                 `description:"创建时间"`
+	UserId           int                    `description:"录入用户id"`
+	UserName         string                 `description:"录入用户名称"`
+	NoticeTime       string                 `description:"通知时间"`
+	Mobile           string                 `description:"录入者手机号"`
+	ModifyDate       string                 `description:"待更新日期"`
+	ModifyTime       string                 `description:"最近一次更新时间"`
+	Status           string                 `description:"状态:未完成/完成"`
+	IsJoinEdb        int8                   `description:"指标库是否已添加:0-否;1-是"`
+	StartDate        string                 `description:"数据开始日期"`
+	EndDate          string                 `description:"数据结束日期"`
+	LatestValue      float64                `description:"指标最新值"`
+	DataList         []*Edbdata             `gorm:"-" description:"指标数据列表"`
+	NextDataTimeList []*EdbDataNextDateTime `gorm:"-" description:"下期数据时间列表"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *EdbInfoItem) AfterFind(db *gorm.DB) (err error) {
+	m.CreateDate = utils.GormDateStrToDateTimeStr(m.CreateDate)
+	m.ModifyTime = utils.GormDateStrToDateTimeStr(m.ModifyTime)
+	m.StartDate = utils.GormDateStrToDateStr(m.StartDate)
+	m.EndDate = utils.GormDateStrToDateStr(m.EndDate)
+
+	return
+}
+
+// ConvDate
+func (m *EdbInfoItem) ConvDate() {
+	m.CreateDate = utils.GormDateStrToDateTimeStr(m.CreateDate)
+	m.ModifyTime = utils.GormDateStrToDateTimeStr(m.ModifyTime)
+	m.StartDate = utils.GormDateStrToDateStr(m.StartDate)
+	m.EndDate = utils.GormDateStrToDateStr(m.EndDate)
+
+	return
+}
+
+type lzSurveyData struct {
+	DataTime   string `gorm:"column:data_time" description:"日期"`
+	InputValue string `gorm:"column:input_value" description:"值"`
+}
+
+// GetLzItemListByCode 根据code查询隆众数据列表
+//func GetLzItemListByCode(lzCode string) (items []*lzSurveyData, err error) {
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	sql := "SELECT * FROM longzhong_survey_data WHERE survey_product_id=? GROUP BY data_time DESC"
+//	err = o.Raw(sql, lzCode).Find(&items).Error
+//	return
+//}
+
+// GetEdbDataListByCodes 通过指标ID获取所有数据
+func GetEdbDataListByCodes(tradeCode string) (items []*Edbdata, err error) {
+	sql := ` SELECT  TRADE_CODE,DT,round(CLOSE,4) CLOSE,modify_time  FROM edbdata WHERE TRADE_CODE IN(` + tradeCode + `)  GROUP BY TRADE_CODE,DT ORDER BY DT DESC `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+// TargetItemListResp 指标数据结构体
+type TargetItemListResp struct {
+	List          []*EdbInfoItem
+	FrequencyList []string
+}
+
+// BatchDataDeleteReq 批量删除某日的指标数据请求结构体
+type BatchDataDeleteReq struct {
+	CreateDate    string   `description:"创建日期"`
+	TradeCodeList []string `description:"指标唯一编码列表"`
+}
+
+// BatchDeleteEdbDataByDate 批量删除某日的指标数据
+func BatchDeleteEdbDataByDate(tradeCodes, dt string, opUserId int) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	var list []*Edbdata
+	sql := ` select * FROM edbdata WHERE TRADE_CODE in  (` + tradeCodes + `) AND DT = ? `
+	err = o.Raw(sql, dt).Find(&list).Error
+	if err != nil {
+		return
+	}
+	deleteRecordList := make([]*EdbdataDeleteRecord, 0)
+	for _, edbDataInfo := range list {
+		deleteRecord := &EdbdataDeleteRecord{
+			TradeCode:  edbDataInfo.TradeCode,
+			Dt:         edbDataInfo.Dt,
+			Close:      edbDataInfo.Close,
+			ModifyTime: time.Now(),
+			CreateTime: time.Now(),
+			SysUserId:  opUserId,
+		}
+		deleteRecordList = append(deleteRecordList, deleteRecord)
+	}
+	if len(deleteRecordList) > 0 {
+		tmpErr := o.CreateInBatches(deleteRecordList, utils.MultiAddNum).Error
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+	}
+	sql = ` DELETE FROM edbdata WHERE TRADE_CODE in  (` + tradeCodes + `) AND DT = ? `
+	err = o.Exec(sql, dt).Error
+	return
+}
+
+// BatchDeleteEdbData 批量删除指标数据
+func BatchDeleteEdbData(tradeCode string, opUserId int) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	var list []*Edbdata
+	sql := ` select * FROM edbdata WHERE TRADE_CODE =  ? `
+	err = o.Raw(sql, tradeCode).Find(&list).Error
+	if err != nil {
+		return
+	}
+	deleteRecordList := make([]*EdbdataDeleteRecord, 0)
+	for _, edbDataInfo := range list {
+		deleteRecord := &EdbdataDeleteRecord{
+			TradeCode:  edbDataInfo.TradeCode,
+			Dt:         edbDataInfo.Dt,
+			Close:      edbDataInfo.Close,
+			ModifyTime: time.Now(),
+			CreateTime: time.Now(),
+			SysUserId:  opUserId,
+		}
+		deleteRecordList = append(deleteRecordList, deleteRecord)
+	}
+	err = o.CreateInBatches(deleteRecordList, utils.MultiAddNum).Error
+	if err != nil {
+		return
+	}
+	sql = ` DELETE FROM edbdata WHERE TRADE_CODE  = ? `
+	err = o.Exec(sql, tradeCode).Error
+	return
+}
+
+// GetEdbInfoCountByClassifyId 根据指标分类id获取当前分类下的指标数量
+func GetEdbInfoCountByClassifyId(classifyId int) (count int, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT COUNT(1) AS count FROM ( SELECT a.*,b.CLOSE FROM edbinfo AS a 
+             INNER JOIN edbdata AS b ON a.TRADE_CODE=b.TRADE_CODE
+             WHERE a.classify_id=? group by a.TRADE_CODE) d `
+	var countNull sql2.NullInt64
+	err = o.Raw(sql, classifyId).Scan(&countNull).Error
+	if err != nil {
+		return
+	}
+	if countNull.Valid {
+		count = int(countNull.Int64)
+	}
+	return
+}
+
+// EdbInfoGroupCount 指标分类id获取当前分类下的指标数量
+type EdbInfoGroupCount struct {
+	Count      int
+	ClassifyId int
+}
+
+// GetEdbInfoGroupCountByClassifyIds 根据指标分类id获取当前分类下的指标数量
+//func GetEdbInfoGroupCountByClassifyIds(classifyIdList []int) (list []*EdbInfoGroupCount, err error) {
+//	num := len(classifyIdList)
+//	if num <= 0 {
+//		return
+//	}
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	sql := `SELECT COUNT(1) AS count,classify_id FROM ( SELECT a.*,b.CLOSE FROM edbinfo AS a
+//             INNER JOIN edbdata AS b ON a.TRADE_CODE=b.TRADE_CODE
+//             WHERE a.classify_id in (` + utils.GetOrmInReplace(num) + `) group by a.TRADE_CODE) d
+//						 GROUP BY classify_id `
+//	err = o.Raw(sql, classifyIdList).Find(&list).Error
+//	return
+//}
+
+// GetExcelData 获取excel样式数据
+//func GetExcelData() (list []*data_manage.ExcelStyle, err error) {
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	sql := `SELECT * FROM excel_style `
+//	err = o.Raw(sql).QueryRows(&list)
+//	return
+//}
+
+// AddExcelData 添加excel样式数据
+//func AddExcelData(item *data_manage.ExcelStyle) (id int64, err error) {
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	id, err = o.Insert(item)
+//	return
+//}
+
+type EdbdataFloat struct {
+	TradeCode  string    `gorm:"column:TRADE_CODE;autoIncrement:false;primaryKey" description:"指标编码"`
+	Dt         string    `gorm:"column:DT" description:"日期"`
+	Close      float64   `gorm:"column:CLOSE" description:"值"`
+	ModifyTime time.Time `gorm:"column:modify_time" description:"修改时间"`
+}
+
+//func GetTargetsDataFloat(tradeCode, dt string) (item *EdbdataFloat, err error) {
+//	sql := `SELECT * FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	err = o.Raw(sql, tradeCode, dt).First(&item).Error
+//	return
+//}
+
+func ModifyEdbinfo(tradeCode, unit, frequency string, classifyId int) (err error) {
+	sql := `UPDATE edbinfo SET UNIT = ?,frequency=?, classify_id=?, create_date=NOW() WHERE TRADE_CODE=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Exec(sql, unit, frequency, classifyId, tradeCode).Error
+	return
+}
+
+func DeleteTargetsDataByImport(tradeCode, dt string) (err error) {
+	sql := `DELETE FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Exec(sql, tradeCode, dt).Error
+	return
+}
+
+// GetEdbinfoListByCodeListGroupByUserId 根据指标code列表、用户分组获取指标信息
+//func GetEdbinfoListByCodeListGroupByUserId(edbCodeList []string) (items []*Edbinfo, err error) {
+//	num := len(edbCodeList)
+//	if num <= 0 {
+//		return
+//	}
+//	o := global.DbMap[utils.DbNameManualIndex]
+//	sql := `SELECT * FROM edbinfo WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) GROUP BY user_id `
+//	err = o.Raw(sql, edbCodeList).Find(&items).Error
+//	return
+//}
+
+// GetEdbinfoListByCodeListByCodeIdList
+// @Description: 根据指标code列表获取列表信息
+// @param edbCodeList
+// @return items
+// @return err
+func GetEdbinfoListByCodeListByCodeIdList(edbCodeList []string) (items []*Edbinfo, err error) {
+	num := len(edbCodeList)
+	if num <= 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT * FROM edbinfo WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) `
+	err = o.Raw(sql, edbCodeList).Find(&items).Error
+	return
+}
+
+// GetEdbinfoListByCodeListByUserId
+// @Description: 根据用户id列表获取指标列表信息
+// @param userIdList
+// @return items
+// @return err
+func GetEdbinfoListByCodeListByUserId(userIdList []int) (items []*Edbinfo, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `SELECT * FROM edbinfo WHERE user_id in (` + utils.GetOrmInReplace(num) + `) `
+	err = o.Raw(sql, userIdList).Find(&items).Error
+	return
+}
+
+// ModifyEdbinfoUserIdByCodeList 根据指标code列表修改创建人
+func ModifyEdbinfoUserIdByCodeList(edbCodeList []string, userId int, userName string) (err error) {
+	num := len(edbCodeList)
+	if num <= 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `UPDATE edbinfo SET user_id = ?,user_name = ? WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) `
+	err = o.Exec(sql, userId, userName, edbCodeList).Error
+	return
+}
+
+// ModifyEdbinfoUserIdByOldUserId
+// @Description:  根据旧用户id修改新用户id
+// @author: Roc
+// @datetime 2024-03-25 17:59:32
+// @param oldUserId int
+// @param userId int
+// @return err error
+func ModifyEdbinfoUserIdByOldUserId(oldUserIdList []int, userId int) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := `UPDATE edbinfo SET user_id=? WHERE user_id in (` + utils.GetOrmInReplace(num) + `) `
+	err = o.Exec(sql, userId, oldUserIdList).Error
+	return
+}
+
+func GetEdbInfoAdminList() (list []int, err error) {
+	sql := `SELECT user_id FROM edbinfo GROUP BY user_id `
+	o := global.DbMap[utils.DbNameManualIndex]
+	err = o.Raw(sql).Find(&list).Error
+	return
+}
+
+// GetAllChildManualEdbClassify
+// @Description: 获取手工数据中所有的子分类
+// @author: Roc
+// @datetime 2024-07-16 13:27:28
+// @return items []*EdbdataClassify
+// @return err error
+func GetAllChildManualEdbClassify() (items []*EdbdataClassify, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id > 0 `
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+// GetChildManualEdbClassifyByIdList
+// @Description: 获取手工数据中所有的子分类
+// @author: Roc
+// @datetime 2024-07-16 13:33:57
+// @param idList []int
+// @return items []*EdbdataClassify
+// @return err error
+func GetChildManualEdbClassifyByIdList(idList []int) (items []*EdbdataClassify, err error) {
+	num := len(idList)
+	if num <= 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	err = o.Raw(sql, idList).Find(&items).Error
+	return
+}
+
+// EdbinfoMaxMinDate
+// @Description: 手工指标的最小最大日期
+type EdbinfoMaxMinDate struct {
+	MinDate string
+	MaxDate string
+}
+
+func (mmDate *EdbinfoMaxMinDate) AfterFind(tx *gorm.DB) (err error) {
+	mmDate.MinDate = utils.GormDateStrToDateStr(mmDate.MinDate)
+	mmDate.MaxDate = utils.GormDateStrToDateStr(mmDate.MaxDate)
+	return
+}
+
+// GetEdbdataMaxMinDate
+// @Description: 获取手工指标的最小最大日期
+// @author: Roc
+// @datetime 2024-08-01 14:27:20
+// @param tradeCode string
+// @return item EdbinfoMaxMinDate
+// @return err error
+func GetEdbdataMaxMinDate(tradeCode string) (item EdbinfoMaxMinDate, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT MIN(DT) min_date,MAX(DT) max_date FROM edbdata WHERE TRADE_CODE = ? `
+	err = o.Raw(sql, tradeCode).First(&item).Error
+	return
+}
+
+// GetEdbdataLatestValue
+// @Description: 获取手工数据的最新值
+// @author: Roc
+// @datetime 2024-08-02 10:33:22
+// @param tradeCode string
+// @return latestValue float64
+// @return err error
+func GetEdbdataLatestValue(tradeCode string) (latestValue float64, err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` SELECT CLOSE FROM edbdata WHERE TRADE_CODE = ? ORDER BY DT DESC LIMIT 1`
+	//err = o.Raw(sql, tradeCode).QueryRow(&latestValue)
+	var valueNull sql2.NullFloat64
+	err = o.Raw(sql, tradeCode).Scan(&valueNull).Error
+	if err != nil {
+		return
+	}
+	if valueNull.Valid {
+		latestValue = valueNull.Float64
+	}
+	return
+}
+
+// ModifyEdbinfoMaxMinDate
+// @Description: 修改手工指标的最小最大日期
+// @author: Roc
+// @datetime 2024-08-01 15:33:45
+// @param startDate string
+// @param endDate string
+// @param tradeCode string
+// @return err error
+func ModifyEdbinfoMaxMinDate(tradeCode, startDate, endDate string, latestValue float64) (err error) {
+	o := global.DbMap[utils.DbNameManualIndex]
+	sql := ` UPDATE edbinfo SET start_date = ?, end_date = ?, latest_value = ? , modify_time = now() WHERE TRADE_CODE = ? `
+	err = o.Exec(sql, startDate, endDate, latestValue, tradeCode).Error
+	return
+}

+ 333 - 245
services/dk.go

@@ -3,13 +3,13 @@ package services
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"eta/eta_task/models"
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/utils"
 	"fmt"
-	"github.com/PuerkitoBio/goquery"
 	"html"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"strconv"
 	"strings"
@@ -19,37 +19,107 @@ import (
 // 使用deepseek api 处理报告
 func AutoCreateReportAssess(cont context.Context) (err error) {
 	//获取品种
-	startTime := "2025-03-03 00:00:00" //time.Now().AddDate(0, 0, -1).Format(utils.FormatDate) + " 00:00:00"
+	startTime := "2025-06-23 00:00:00" //time.Now().AddDate(0, 0, -1).Format(utils.FormatDate) + " 00:00:00"
 	weekStartTime, err := time.Parse(utils.FormatDateTime, startTime)
 	if err != nil {
 		fmt.Println("weekStartTime time.Parse Err:" + err.Error())
 		return
 	}
 	weekEndTime := weekStartTime.AddDate(0, 0, 6)
-	for {
-		startTime = weekStartTime.Format(utils.FormatDateTime)
-		endTime := weekEndTime.Format(utils.FormatDateTime)
-		startDate := weekStartTime.Format(utils.FormatDate)
-		endDate := weekEndTime.Format(utils.FormatDate)
-		AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate)
-		fmt.Println(startTime, endTime)
-		if weekEndTime.After(time.Now()) {
-			fmt.Println("before:", weekEndTime, time.Now())
-			break
-		}
-		weekStartTime = weekEndTime.AddDate(0, 0, 1)
-		weekEndTime = weekStartTime.AddDate(0, 0, 6)
-	}
+
+	startTime = weekStartTime.Format(utils.FormatDateTime)
+	endTime := weekEndTime.Format(utils.FormatDateTime)
+	startDate := weekStartTime.Format(utils.FormatDate)
+	endDate := weekEndTime.Format(utils.FormatDate)
+	AutoCreateReportAssessByKind(startTime, endTime, startDate, endDate)
+
+	//for {
+	//	startTime = weekStartTime.Format(utils.FormatDateTime)
+	//	endTime := weekEndTime.Format(utils.FormatDateTime)
+	//	startDate := weekStartTime.Format(utils.FormatDate)
+	//	endDate := weekEndTime.Format(utils.FormatDate)
+	//	AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate)
+	//	fmt.Println(startTime, endTime)
+	//	if weekEndTime.After(time.Now()) {
+	//		fmt.Println("before:", weekEndTime, time.Now())
+	//		break
+	//	}
+	//	weekStartTime = weekEndTime.AddDate(0, 0, 1)
+	//	weekEndTime = weekStartTime.AddDate(0, 0, 6)
+	//}
 	return nil
 }
 
-func AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate string) (err error) {
-
-	tagList, err := models.GetWechatArticleTags(startTime, endTime)
+func AutoCreateReportAssessByKind(startTime, endTime, startDate, endDate string) {
+	classifyName := "能化"
+	tagTotal, err := models.GetWechatArticleTagsTotal(classifyName, startTime, endTime)
 	if err != nil {
-		fmt.Println("GetWechatArticleTags Err:" + err.Error())
+		fmt.Println("GetWechatArticleTagsTotal Err:" + err.Error())
 		return
 	}
+	pageSize := 5
+	pageTotal := utils.PageCount(tagTotal, 5)
+
+	kindScoreList := make([]*DkKindItem, 0)
+	var messageContent string
+	kindMap := make(map[string]string)
+	for i := 0; i < pageTotal; i++ {
+		fmt.Println("pageIndex:", i)
+		startSize := utils.StartIndex(i, pageSize)
+		tagList, err := models.GetWechatArticleTags(classifyName, startTime, endTime, startSize, pageSize)
+		if err != nil {
+			fmt.Println("GetWechatArticleTags Err:" + err.Error())
+			return
+		}
+
+		pageMessageContent, err := AutoCreateReportAssessByWeek(tagList, startTime, endTime, startDate, endDate)
+		if err != nil {
+			fmt.Println("AutoCreateReportAssessByWeek Err:" + err.Error())
+			return
+		}
+
+		pageMessageContent = strings.ReplaceAll(pageMessageContent, "\n", "")
+		pageMessageContent = strings.ReplaceAll(pageMessageContent, "```json", "")
+		pageMessageContent = strings.ReplaceAll(pageMessageContent, "```", "")
+		resultItem := make(map[string]*DkKindItem)
+		err = json.Unmarshal([]byte(pageMessageContent), &resultItem)
+		if err != nil {
+			fmt.Println("json.Unmarshal Err:" + err.Error())
+		}
+		for _, v := range resultItem {
+			if _, ok := kindMap[v.Kind]; !ok {
+
+				str := `<article style="padding: 15px; margin-bottom: 20px;">
+    <h3 style="color: #2980b9;">` + v.Kind + `评分: <span style="color: #e74c3c;">` + strconv.Itoa(v.Score) + `/10</span></h3>
+    <p><strong>主要逻辑与观点:</strong></p>
+    <div>
+      ` + v.Point + `
+    </div>
+    <p><strong>总结:</strong> ` + v.Summarize + `</p>
+  </article>`
+				messageContent += str
+				if v.Kind != "" {
+					kindScoreList = append(kindScoreList, v)
+				}
+			}
+			kindMap[v.Kind] = v.Kind
+		}
+		break
+	}
+	if messageContent != "" {
+		messageContent = `<p style="font-size: 16px;color: #666;text-align: right;margin-bottom: 40px;"> ` + startDate + `~` + endDate + `</p >` + messageContent
+		SaveReport(classifyName, messageContent, endTime, endDate)
+	}
+	if len(kindScoreList) > 0 {
+		err = saveIndex(kindScoreList, classifyName, endDate)
+		if err != nil {
+			fmt.Println("saveIndex Err:" + err.Error())
+		}
+	}
+	utils.FileLog.Info("messageContent:" + messageContent)
+}
+
+func AutoCreateReportAssessByWeek(tagList []*models.WechatArticleTag, startTime, endTime, startDate, endDate string) (messageContent string, err error) {
 
 	req := new(DkCompletionsReq)
 	req.Model = "deepseek-chat"
@@ -70,7 +140,10 @@ func AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate string)
 	msgList := make([]*DkCompletionsMessagesReq, 0)
 	msg := new(DkCompletionsMessagesReq)
 	//msg.Content = "请阅读如下文章。首先根据文章内容,对#品种名称 进行打分,打分规则为10分最看多,0分最看空。其次,对#品种名称 提炼主要逻辑和观点,得出总结,品种和品种之间用横线拆分,输出格式限定为:1. 使用语义化的HTML5标签,2. 采用现代响应式设计(无固定宽度),3. 包含丰富的文本格式元素,4. 通过内联样式确保自适应渲染"
-	msg.Content = "请阅读如下文章。首先根据文章内容,对#品种名称 进行打分,打分规则为10分最看多,0分最看空。其次,对#品种名称 提炼主要逻辑和观点,主要逻辑和观点尽可能的详细,得出总结,品种和品种之间用横线拆分,输出格式限定为:1. 使用语义化的HTML5标签代码段,不包含html,body,head,2. 采用现代响应式设计(无固定宽度),3. 包含丰富的文本格式元素,4. 通过内联样式确保自适应渲染"
+	//msg.Content = "请阅读如下文章。首先根据文章内容,对#品种名称 进行打分,打分规则为10分最看多,0分最看空。其次,对#品种名称 提炼主要逻辑和观点,主要逻辑和观点尽可能的详细,得出总结,品种和品种之间用横线拆分,输出格式限定为:1. 使用语义化的HTML5标签代码段,不包含html,body,head,2. 采用现代响应式设计(无固定宽度),3. 包含丰富的文本格式元素,4. 通过内联样式确保自适应渲染"
+
+	msg.Content = "请阅读如下文章。首先根据文章内容,对#品种名称 进行打分,打分规则为10分最看多,0分最看空。其次,对#品种名称 提炼主要逻辑和观点,主要逻辑和观点尽可能的详细,得出总结,请严格以标准、统一固定的json格式输出内容,定义字段如下,品类:kind,类型字符串;评分:score,类型int;逻辑和观点:point,类型字符串;总结:summarize,类型字符串"
+
 	msg.Role = "system"
 	msgList = append(msgList, msg)
 	for k, v := range tagList {
@@ -81,22 +154,22 @@ func AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate string)
 		articleList, err := models.GetWechatArticle(v.ArticleId, startTime, endTime)
 		if err != nil {
 			fmt.Println("GetWechatArticle Err:" + err.Error())
-			return err
+			return messageContent, err
 		}
 		var context string
 		context += `品种 ` + v.TagName + ":"
 		for _, av := range articleList {
 			context += av.TextContent
 		}
-		utils.FileLog.Info(context)
-
+		context = strings.Join(strings.Fields(context), " ")
+		context = strings.Replace(context, "\r\n", "", -1)
+		context = strings.Replace(context, "\n", "", -1)
 		context = strings.ReplaceAll(context, "\n", "")
 		context = strings.ReplaceAll(context, `"`, "")
 		context = strings.ReplaceAll(context, `\`, "/")
 		context = strings.ReplaceAll(context, `	`, "")
 		context = strings.ReplaceAll(context, `  `, "")
 		context = strings.ReplaceAll(context, `⭐️`, "")
-
 		context = strings.ReplaceAll(context, `"`, "")
 		msgItem.Content = context
 		msgList = append(msgList, msgItem)
@@ -113,49 +186,44 @@ func AutoCreateReportAssessByWeek(startTime, endTime, startDate, endDate string)
 		return
 	}
 
-	isSummary := 0
-	isSuccess := dkCompletions(string(reqBody), startTime, endTime, startDate, endDate)
-	if isSuccess {
-		isSummary = 1
-		for _, v := range tagList {
-			models.ModifyWechatArticleSummary(v.ArticleId, isSummary)
-		}
-	}
-	return nil
-}
-
-// 使用deepseek api 处理报告
-func AutoCreateReportAssessV1() {
-	//获取品种
-	startTime := `2025-03-31 00:00:00`
-	endTime := `2025-05-18 00:00:00`
-	tagList, err := models.GetWechatArticleTags(startTime, endTime)
-	if err != nil {
-		fmt.Println("GetWechatArticleTags Err:" + err.Error())
-		return
-	}
-	var context string
-
-	for _, v := range tagList {
-		context += `品种 ` + v.TagName
-		textContent := strings.ReplaceAll(v.TextContent, "\n", "")
-		//fmt.Println("textContent:" + textContent)
-		context += textContent
-	}
-
-	contextDoc, err := goquery.NewDocumentFromReader(strings.NewReader(context))
-	context = contextDoc.Text()
-	context = strings.ReplaceAll(context, `"`, "")
-	context = strings.ReplaceAll(context, `\`, "/")
-	context = strings.ReplaceAll(context, `	`, "")
-	context = strings.ReplaceAll(context, `  `, "")
-
-	utils.FileLog.Info(context)
-	fmt.Println(len(context))
-	//dkCompletions(context)
+	//isSummary := 0
+	messageContent = dkCompletions(string(reqBody))
+	return messageContent, nil
 }
 
-func dkCompletions(payloadBody, startTime, endTime, startDate, endDate string) (success bool) {
+//
+//// 使用deepseek api 处理报告
+//func AutoCreateReportAssessV1() {
+//	//获取品种
+//	startTime := `2025-03-31 00:00:00`
+//	endTime := `2025-05-18 00:00:00`
+//	tagList, err := models.GetWechatArticleTags(startTime, endTime)
+//	if err != nil {
+//		fmt.Println("GetWechatArticleTags Err:" + err.Error())
+//		return
+//	}
+//	var context string
+//
+//	for _, v := range tagList {
+//		context += `品种 ` + v.TagName
+//		textContent := strings.ReplaceAll(v.TextContent, "\n", "")
+//		//fmt.Println("textContent:" + textContent)
+//		context += textContent
+//	}
+//
+//	contextDoc, err := goquery.NewDocumentFromReader(strings.NewReader(context))
+//	context = contextDoc.Text()
+//	context = strings.ReplaceAll(context, `"`, "")
+//	context = strings.ReplaceAll(context, `\`, "/")
+//	context = strings.ReplaceAll(context, `	`, "")
+//	context = strings.ReplaceAll(context, `  `, "")
+//
+//	utils.FileLog.Info(context)
+//	fmt.Println(len(context))
+//	//dkCompletions(context)
+//}
+
+func dkCompletions(payloadBody string) (messageContent string) {
 
 	utils.FileLog.Info(payloadBody)
 
@@ -177,6 +245,7 @@ func dkCompletions(payloadBody, startTime, endTime, startDate, endDate string) (
 	req.Header.Add("Accept", "application/json")
 	req.Header.Add("Authorization", "Bearer sk-e21afcf4380249869d06b92a4379ee23")
 
+	fmt.Println("开始请求deepseek")
 	res, err := client.Do(req)
 	if err != nil {
 		fmt.Println(err)
@@ -184,7 +253,8 @@ func dkCompletions(payloadBody, startTime, endTime, startDate, endDate string) (
 	}
 	defer res.Body.Close()
 
-	body, err := ioutil.ReadAll(res.Body)
+	fmt.Println("结束请求deepseek")
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		fmt.Println(err)
 		return
@@ -202,205 +272,216 @@ func dkCompletions(payloadBody, startTime, endTime, startDate, endDate string) (
 	}
 
 	if len(result.Choices) > 0 && result.Choices[0].Message.Content != "" {
-		resultContent := result.Choices[0].Message.Content
-		resultContent = strings.ReplaceAll(resultContent, `\n`, "<br/>")
-		resultContent = strings.ReplaceAll(resultContent, "```html", "")
-		resultContent = strings.ReplaceAll(resultContent, "```", "")
-		scoreContent := resultContent
-		utils.FileLog.Info(resultContent)
-
-		//判断报告是否存在
-		classifyName := "AI研报"
-		reportClassify, err := models.GetClassifyByName(classifyName)
+		messageContent = result.Choices[0].Message.Content
+		return messageContent
+	}
+	return messageContent
+}
+
+func SaveReport(kindName, resultContent, endTime, endDate string) {
+	resultContent = strings.ReplaceAll(resultContent, `\n`, "<br/>")
+	resultContent = strings.ReplaceAll(resultContent, "```html", "")
+	resultContent = strings.ReplaceAll(resultContent, "```", "")
+	utils.FileLog.Info(resultContent)
+
+	//判断报告是否存在
+	classifyName := "AI研报"
+	reportClassify, err := models.GetClassifyByName(classifyName)
+	if err != nil {
+		fmt.Println("GetClassifyByName Err:" + err.Error())
+		return
+	}
+	if reportClassify == nil {
+		fmt.Println("reportClassify is nil")
+		return
+	}
+	//classifyIdSecond := 245
+	var isAdd bool
+	//reportItem, err := models.GetReport(reportClassify.Id, classifyIdSecond, startTime, endTime)
+	//if err != nil {
+	//	if err.Error() == utils.ErrNoRow() {
+	//		isAdd = true
+	//	} else {
+	//		fmt.Println("GetReport Err:" + err.Error())
+	//		return
+	//	}
+	//}
+	//if reportItem == nil {
+	//	isAdd = true
+	//}
+	isAdd = true
+	fmt.Println("isAdd:", isAdd)
+	if isAdd {
+		//获取最大期数
+		//GetReportStage
+		maxStage, e := models.GetReportStage(reportClassify.Id, 0, 0)
+		if e != nil {
+			fmt.Println("GetReportStage Err:" + err.Error())
+			return
+		}
+
+		fmt.Println(resultContent)
+		context := html.EscapeString(resultContent)
+		item := new(models.Report)
+		item.AddType = 1
+		item.ClassifyIdFirst = reportClassify.Id
+		item.ClassifyNameFirst = reportClassify.ClassifyName
+		item.ClassifyIdSecond = 245
+		item.ClassifyNameSecond = "AI智慧周报"
+		item.Title = "智汇周报(" + kindName + ")" + endDate
+		item.Frequency = "周度"
+		item.State = 2
+		item.Content = context
+		item.Stage = maxStage + 1
+		item.CreateTime = endTime
+		item.ModifyTime = endTime
+		item.CollaborateType = 1
+		item.IsPublicPublish = 1
+		item.ReportLayout = 1
+		err = models.AddReport(item)
 		if err != nil {
-			fmt.Println("GetClassifyByName Err:" + err.Error())
+			fmt.Println("AddReport Err:" + err.Error())
 			return
 		}
-		if reportClassify == nil {
-			fmt.Println("reportClassify is nil")
+
+		reportCode := utils.MD5(strconv.Itoa(item.Id))
+		err = models.ModifyReportCode(item.Id, reportCode)
+		if err != nil {
+			fmt.Println("ModifyReportCode Err:" + err.Error())
 			return
 		}
-		//classifyIdSecond := 245
-		var isAdd bool
-		//reportItem, err := models.GetReport(reportClassify.Id, classifyIdSecond, startTime, endTime)
+	} else {
+		//reportContent := html.UnescapeString(reportItem.Content)
+		//resultContent = reportContent + resultContent
+		//resultContent = html.EscapeString(resultContent)
+		//err = models.ModifyReportContent(reportItem.Id, resultContent)
 		//if err != nil {
-		//	if err.Error() == utils.ErrNoRow() {
-		//		isAdd = true
-		//	} else {
-		//		fmt.Println("GetReport Err:" + err.Error())
-		//		return
-		//	}
-		//}
-		//if reportItem == nil {
-		//	isAdd = true
+		//	fmt.Println("ModifyReportContent Err:" + err.Error())
+		//	return
 		//}
-		isAdd = true
-		fmt.Println("isAdd:", isAdd)
-		if isAdd {
-			//获取最大期数
-			//GetReportStage
-			maxStage, e := models.GetReportStage(reportClassify.Id, 0, 0)
-			if e != nil {
-				fmt.Println("GetReportStage Err:" + err.Error())
-				return
-			}
+	}
+}
 
-			fmt.Println(resultContent)
-
-			resultContent = "<p>" + startDate + "~" + endDate + "</p>" + resultContent
-			context := html.EscapeString(resultContent)
-			item := new(models.Report)
-			item.AddType = 1
-			item.ClassifyIdFirst = reportClassify.Id
-			item.ClassifyNameFirst = reportClassify.ClassifyName
-			item.ClassifyIdSecond = 245
-			item.ClassifyNameSecond = "AI智慧周报"
-			item.Title = "智汇周报" + endDate
-			item.Frequency = "周度"
-			item.State = 2
-			item.Content = context
-			item.Stage = maxStage + 1
-			item.CreateTime = endTime
-			item.ModifyTime = endTime
-			item.CollaborateType = 1
-			item.IsPublicPublish = 1
-			item.ReportLayout = 1
-			err = models.AddReport(item)
-			if err != nil {
-				fmt.Println("AddReport Err:" + err.Error())
-				return
-			}
+// 保存指标
+func saveIndex(indexList []*DkKindItem, classifyName, endData string) (err error) {
+	tradeCode, err := models.GetMaxTradeCode()
+	if err != nil {
+		return
+	}
 
-			reportCode := utils.MD5(strconv.Itoa(item.Id))
-			err = models.ModifyReportCode(item.Id, reportCode)
-			if err != nil {
-				fmt.Println("ModifyReportCode Err:" + err.Error())
-				return
+	maxTradeCode, err := utils.GetMaxTradeCode(tradeCode)
+	if err != nil {
+		return
+	}
+
+	if maxTradeCode == "" {
+		err = errors.New("编码为空,请联系技术")
+		return
+	}
+
+	for _, v := range indexList {
+		if v.Kind == "" {
+			break
+		}
+		secName := v.Kind + "-DeepSeek多空指数"
+		var isIndexAdd bool
+		item, err := models.GetEdbinfoBySecName(secName)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				isIndexAdd = true
+			} else {
+				err = errors.New("获取指标信息失败,Err:" + err.Error())
+				return err
 			}
+		}
+
+		var tradeCode string
+		if item != nil && item.TradeCode != "" {
+			tradeCode = item.TradeCode
 		} else {
-			//reportContent := html.UnescapeString(reportItem.Content)
-			//resultContent = reportContent + resultContent
-			//resultContent = html.EscapeString(resultContent)
-			//err = models.ModifyReportContent(reportItem.Id, resultContent)
-			//if err != nil {
-			//	fmt.Println("ModifyReportContent Err:" + err.Error())
-			//	return
-			//}
+			isIndexAdd = true
 		}
-		success = true
 
-		//指标数据处理
-		{
-			fmt.Println("指标数据处理")
-			doc, err := goquery.NewDocumentFromReader(strings.NewReader(scoreContent))
+		if isIndexAdd {
+			tradeCode = maxTradeCode
+			frequency := "周度"
+			var isAddManualClassify bool
+			classifyItem, err := data_manage.GetManualClassifyByClassifyName(v.Kind)
 			if err != nil {
-				fmt.Println("NewDocumentFromReader Err:" + err.Error())
-				return
-			}
-			fmt.Println("new doc", doc)
-			doc.Find("h2").Each(func(i int, hs *goquery.Selection) {
-				h2Text := hs.Text()
-				fmt.Println("find h2:" + h2Text)
-				var score string
-				if strings.Contains(h2Text, "原油") {
-					fmt.Println(h2Text)
-					fmt.Println(hs.Next().Text())
-					pfText := hs.Next().Text()
-					pfArr := strings.Split(pfText, "/")
-					if len(pfArr) > 0 {
-						scoreStr := pfArr[0]
-						if scoreStr != "" {
-							scoreArr := strings.Split(scoreStr, ":")
-							if len(scoreArr) > 1 {
-								score = scoreArr[1]
-								fmt.Println("score:", strings.Trim(score, " "))
-							} else {
-								fmt.Println("scoreArr len is", len(scoreArr))
-							}
-						} else {
-							fmt.Println("scoreStr is empty")
-						}
-					} else {
-						fmt.Println("pfArr len is 0")
-					}
+				if err.Error() == utils.ErrNoRow() {
+					isAddManualClassify = true
 				} else {
-					fmt.Println("not find h2")
+					err = errors.New("获取分类信息失败,Err:" + err.Error())
+					return err
 				}
-				fmt.Println("score,", score)
-				if score != "" {
-					score = strings.TrimLeft(score, " ")
-					scoreInt, err := strconv.Atoi(score)
-					if err != nil {
-						fmt.Println(" strconv.Atoi(score) Err:" + err.Error())
-					}
-					if scoreInt > 0 {
-						params := make([]interface{}, 0)
-						params = append(params, "W9535748")
-						params = append(params, endDate)
-						params = append(params, scoreInt)
-						sql := `INSERT INTO edbdata(TRADE_CODE, DT, CLOSE, modify_time, create_time) VALUES (?, ?, ?, NOW(),NOW());`
-						err = data_manage.AddEdbDataManualBySql(sql, params)
-						if err != nil {
-							fmt.Println("AddEdbDataManualBySql Err:" + err.Error())
-						}
-					}
-					return
+			}
+			if classifyItem == nil {
+				isAddManualClassify = true
+			}
+			var classifyId int
+			if isAddManualClassify {
+				classify := new(data_manage.EdbdataClassify)
+				classify.IsShow = 1
+				classify.ClassifyName = v.Kind
+				if classifyName == "化工" {
+					classify.ParentId = 4
+				} else if classifyName == "宏观" {
+					classify.ParentId = 1
+				} else if classifyName == "有色" {
+					classify.ParentId = 2
+				} else if classifyName == "黑色" {
+					classify.ParentId = 3
 				}
-			})
-
-			doc.Find("h3").Each(func(i int, hs *goquery.Selection) {
-				h2Text := hs.Text()
-				fmt.Println("find h2:" + h2Text)
-				var score string
-				if strings.Contains(h2Text, "原油") {
-					fmt.Println(h2Text)
-					fmt.Println(hs.Next().Text())
-					pfText := hs.Next().Text()
-					pfArr := strings.Split(pfText, "/")
-					if len(pfArr) > 0 {
-						scoreStr := pfArr[0]
-						if scoreStr != "" {
-							scoreArr := strings.Split(scoreStr, ":")
-							if len(scoreArr) > 1 {
-								score = scoreArr[1]
-								fmt.Println("score:", strings.Trim(score, " "))
-							} else {
-								fmt.Println("scoreArr len is", len(scoreArr))
-							}
-						} else {
-							fmt.Println("scoreStr is empty")
-						}
-					} else {
-						fmt.Println("pfArr len is 0")
-					}
-				} else {
-					fmt.Println("not find h2")
+				classify.CreateTime = time.Now()
+				classify.Sort = 0
+				lastId, err := data_manage.AddEdbdataClassify(classify)
+				if err != nil {
+					err = errors.New("新增分类失败,Err:" + err.Error())
+					return err
 				}
-				fmt.Println("score,", score)
-				if score != "" {
-					score = strings.TrimLeft(score, " ")
-					scoreInt, err := strconv.Atoi(score)
-					if err != nil {
-						fmt.Println(" strconv.Atoi(score) Err:" + err.Error())
-					}
-					if scoreInt > 0 {
-						params := make([]interface{}, 0)
-						params = append(params, "W9535748")
-						params = append(params, endDate)
-						params = append(params, scoreInt)
-						sql := `INSERT INTO edbdata(TRADE_CODE, DT, CLOSE, modify_time, create_time) VALUES (?, ?, ?, NOW(),NOW());`
-						err = data_manage.AddEdbDataManualBySql(sql, params)
-						if err != nil {
-							fmt.Println("AddEdbDataManualBySql Err:" + err.Error())
-						}
-					}
-					return
+				if lastId == 0 {
+					err = errors.New("分类ID返回异常")
+					fmt.Println("分类ID返回异常:", lastId)
+					return err
 				}
-			})
+				classifyId = int(lastId)
+			} else {
+				classifyId = classifyItem.ClassifyId
+			}
+			err = models.AddEdbinfo(maxTradeCode, secName, "", "手动", frequency, "", classifyId, 9, "戚明之")
+			if err != nil {
+				err = errors.New("新增指标失败,Err:" + err.Error())
+				return err
+			}
+		}
+		var isDataAdd bool
+		dataItem, err := models.GetEdbdataValueByTradeCode(tradeCode, endData)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				isDataAdd = true
+			} else {
+				err = errors.New("GetEdbdataValueByTradeCode,Err:" + err.Error())
+				return err
+			}
+		}
+
+		if dataItem == nil {
+			isDataAdd = true
 		}
 
+		if isDataAdd {
+			params := make([]interface{}, 0)
+			params = append(params, tradeCode)
+			params = append(params, endData)
+			params = append(params, v.Score)
+			sql := `INSERT INTO edbdata(TRADE_CODE, DT, CLOSE, modify_time, create_time) VALUES (?, ?, ?, NOW(),NOW());`
+			err = data_manage.AddEdbDataManualBySql(sql, params)
+			if err != nil {
+				fmt.Println("AddEdbDataManualBySql Err:" + err.Error())
+			}
+		}
 	}
-	return success
+	return nil
 }
 
 type DkCompletionsReq struct {
@@ -460,3 +541,10 @@ type DkCompletionsResult struct {
 		Code    string      `json:"code"`
 	} `json:"error"`
 }
+
+type DkKindItem struct {
+	Kind      string `json:"kind"`
+	Score     int    `json:"score"`
+	Point     string `json:"point"`
+	Summarize string `json:"summarize"`
+}

+ 12 - 0
utils/common.go

@@ -1039,3 +1039,15 @@ func GormDateStrToDateTimeStr(originalString string) (formatStr string) {
 
 	return
 }
+
+func GetMaxTradeCode(tradeCode string) (maxTradeCode string, err error) {
+	tradeCode = strings.Replace(tradeCode, "W", "", -1)
+	tradeCode = strings.Trim(tradeCode, " ")
+	tradeCodeInt, err := strconv.Atoi(tradeCode)
+	if err != nil {
+		return
+	}
+	tradeCodeInt = tradeCodeInt + 1
+	maxTradeCode = fmt.Sprintf("W%06d", tradeCodeInt)
+	return
+}