浏览代码

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	services/task_gn.go
Roc 4 月之前
父节点
当前提交
3818fbdf23

+ 3 - 1
global/dm.go

@@ -38,13 +38,15 @@ func InitDm() {
 	// 手工数据库
 	connectDm(utils.MYSQL_URL_EDB, "edb", newLogger, dmSqlMap, false)
 	// eta主库
-	connectDm(utils.MYSQL_URL, "master", newLogger, dmSqlMap, true)
+	//connectDm(utils.MYSQL_URL, "master", newLogger, dmSqlMap, true)
 	// 指标库
 	connectDm(utils.MYSQL_URL_DATA, "data", newLogger, dmSqlMap, false)
 	// 钢联库
 	connectDm(utils.MYSQL_URL_GL, "gl", newLogger, dmSqlMap, false)
 	// rddp库
 	connectDm(utils.MYSQL_URL_RDDP, "rddp", newLogger, dmSqlMap, false)
+	// eta主库
+	connectDm(utils.MYSQL_URL_ETA, "eta", newLogger, dmSqlMap, false)
 
 	/*initDm(utils.MYSQL_URL, "default", newLogger, dmSqlMap, true)
 	initDm(utils.MYSQL_URL_EDB, "edb", newLogger, dmSqlMap, true)

+ 17 - 22
models/admin.go

@@ -2,10 +2,12 @@ package models
 
 import (
 	"eta_gn/eta_task/global"
+	"fmt"
+	"strings"
 )
 
 type Admin struct {
-	AdminId      int
+	AdminId      int    `gorm:"primaryKey;autoIncrement;column:admin_id"`
 	AdminName    string `description:"系统用户名称"`
 	RealName     string `description:"系统用户姓名"`
 	Password     string `description:"密码"`
@@ -18,35 +20,28 @@ type Admin struct {
 	Authority    int    `description:"管理权限,0:无,1:部门负责人,2:小组负责人"`
 	Position     string `description:"职位"`
 	OpenId       string `description:"弘则部门公众号的openid"`
+	OutId        string `description:"外部ID"`
 }
 
 func GetAdminByAdminId(adminId int) (item *Admin, err error) {
 	//sql := `SELECT * FROM admin WHERE admin_id=? `
 	//err = orm.NewOrm().Raw(sql, adminId).QueryRow(&item)
 
-	sql := `SELECT * FROM admin WHERE admin_id=? `
+	sql := `SELECT * FROM "admin" WHERE admin_id=? `
 	err = global.DmSQL["eta"].Raw(sql, adminId).Find(&item).Error
 	return
 }
 
-type AdminView struct {
-	AdminId      int
-	AdminName    string `description:"系统用户名称"`
-	RealName     string `description:"系统用户姓名"`
-	Password     string `description:"密码"`
-	Mobile       string `description:"手机号"`
-	RoleId       int    `description:"角色id"`
-	RoleName     string `description:"角色名称"`
-	RoleTypeCode string `description:"角色编码"`
-	DepartmentId int    `description:"部门id"`
-	GroupId      int    `description:"分组id"`
-	GroupName    string `description:"分组名称"`
-	Authority    int    `description:"管理权限,0:无,1:部门负责人,2:小组负责人"`
-	Position     string `description:"职位"`
+func (m *Admin) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*Admin, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY created_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM "admin" WHERE 1=1 %s %s`, fields, condition, order)
+	err = global.DmSQL["eta"].Raw(sql, pars...).Find(&items).Error
+	return
 }
-
-//func GetAdminList() (list []*AdminView, err error) {
-//	sql := `SELECT * FROM admin `
-//	_, err = orm.NewOrm().Raw(sql).QueryRows(&list)
-//	return
-//}

+ 8 - 0
models/business_conf.go

@@ -16,6 +16,8 @@ const (
 	BusinessConfXfApiSecret    = "XfApiSecret"
 	BusinessConfXfVcn          = "XfVcn"
 	BusinessConfEnPptCoverImgs = "EnPptCoverImgs"
+	BusinessOpenOaMsg          = "OpenOaMsg"    // 是否开启OA消息推送
+	BusinessOaReportHost       = "OaReportHost" // OA推送跳转报告Host
 )
 
 // BusinessConf 商户配置表
@@ -227,3 +229,9 @@ type EdbStopRefreshRule struct {
 	BaseIndexStopDays int `description:"数据源间隔天数未加入指标库则停用"`
 	EdbStopDays       int `description:"指标库间隔天数未引用则停用"`
 }
+
+func GetBusinessConfByKey(key string) (item *BusinessConf, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM business_conf WHERE conf_key = ? LIMIT 1`)
+	err = global.DmSQL["eta"].Raw(sql, key).First(&item).Error
+	return
+}

+ 25 - 0
models/classify.go

@@ -2,7 +2,9 @@ package models
 
 import (
 	"eta_gn/eta_task/global"
+	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"strings"
 	"time"
 )
 
@@ -24,6 +26,11 @@ type Classify struct {
 	HomeImgUrl     string    `description:"首页配图"`
 	ClassifyLabel  string    `description:"分类标签"`
 	IsMassSend     int       `description:"1:群发,0:非群发"`
+	ClassifyType   int       `gorm:"column:classify_type"` //`description:"分类类型:1-研报;
+	IsRemind       int       `gorm:"column:is_remind"`     //`description:"是否开启提醒:0-关闭;1-开启"`
+	RemindTime     string    `gorm:"column:remind_time"`   //`description:"提醒时间:可选00:00-23:59"`
+	ReportNum      int       `gorm:"column:report_num"`    //`description:"分类下的报告数"`
+	LevelPath      string    `gorm:"column:level_path"`    //`description:"分类的层级路径,英文逗号分隔"`
 }
 
 type ClassifyAddReq struct {
@@ -248,3 +255,21 @@ type FindByIdClassifyReq struct {
 //	_, err = o.Raw(sql, parentId).QueryRows(&items)
 //	return
 //}
+
+func (m *Classify) TableName() string {
+	return "classify"
+}
+
+func (m *Classify) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*Classify, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}

+ 158 - 0
models/oa_report_message.go

@@ -0,0 +1,158 @@
+package models
+
+import (
+	"eta_gn/eta_task/global"
+	"eta_gn/eta_task/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+const (
+	OaReportMessageSourceRemind = 1
+
+	OaReportMessageStatusSuccess = 1
+	OaReportMessageStatusFail    = 2
+)
+
+// OaReportMessage OA报告消息
+type OaReportMessage struct {
+	Id            int       `gorm:"primaryKey;autoIncrement;column:id"`
+	ReceiveUserId int       `gorm:"column:receive_user_id" description:"接收人ID"`
+	ReportType    int       `gorm:"column:report_type" description:"报告类型:1-研报;2-PPT"`
+	ReportId      int       `gorm:"column:report_id" description:"报告/PPT-ID"`
+	MessageParams string    `gorm:"column:message_params" description:"消息请求"`
+	MessageResult string    `gorm:"column:message_result" description:"响应结果"`
+	TaskId        string    `gorm:"column:task_id" description:"待办任务ID"`
+	Source        int       `gorm:"column:source" description:"来源:1-报告提醒"`
+	SendStatus    int       `gorm:"column:send_status" description:"发送状态:1-发送成功;2-发送失败"`
+	CreateTime    time.Time `gorm:"column:create_time" description:"创建时间"`
+	ModifyTime    time.Time `gorm:"column:modify_time" description:"更新时间"`
+}
+
+func (m *OaReportMessage) TableName() string {
+	return "oa_report_message"
+}
+
+type OaReportMessageCols struct {
+	PrimaryId     string
+	ReceiveUserId string
+	ReportType    string
+	ReportId      string
+	MessageParams string
+	MessageResult string
+	TaskId        string
+	Source        string
+	SendStatus    string
+	CreateTime    string
+	ModifyTime    string
+}
+
+func (m *OaReportMessage) Cols() OaReportMessageCols {
+	return OaReportMessageCols{
+		PrimaryId:     "id",
+		ReceiveUserId: "receive_user_id",
+		ReportType:    "report_type",
+		ReportId:      "report_id",
+		MessageParams: "message_params",
+		MessageResult: "message_result",
+		TaskId:        "task_id",
+		Source:        "source",
+		SendStatus:    "send_status",
+		CreateTime:    "create_time",
+		ModifyTime:    "modify_time",
+	}
+}
+
+func (m *OaReportMessage) Create() (err error) {
+	err = global.DmSQL["eta"].Create(m).Error
+	return
+}
+
+func (m *OaReportMessage) CreateMulti(items []*OaReportMessage) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	err = global.DmSQL["eta"].CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (m *OaReportMessage) Update(cols []string) (err error) {
+	err = global.DmSQL["eta"].Select(cols).Updates(m).Error
+	return
+}
+
+func (m *OaReportMessage) Remove() (err error) {
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = global.DmSQL["eta"].Exec(sql, m.Id).Error
+	return
+}
+
+func (m *OaReportMessage) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	err = global.DmSQL["eta"].Exec(sql, ids).Error
+	return
+}
+
+func (m *OaReportMessage) RemoveByCondition(condition string, pars []interface{}) (err error) {
+	if condition == "" {
+		return
+	}
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
+	err = global.DmSQL["eta"].Exec(sql, pars...).Error
+	return
+}
+
+func (m *OaReportMessage) GetItemById(id int) (item *OaReportMessage, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = global.DmSQL["eta"].Raw(sql, id).First(&item).Error
+	return
+}
+
+func (m *OaReportMessage) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *OaReportMessage, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = global.DmSQL["eta"].Raw(sql, pars...).First(&item).Error
+	return
+}
+
+func (m *OaReportMessage) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = global.DmSQL["eta"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func (m *OaReportMessage) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*OaReportMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["eta"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *OaReportMessage) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*OaReportMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["eta"].Raw(sql, pars...).Find(&items).Error
+	return
+}

+ 68 - 0
models/ppt_v2.go

@@ -0,0 +1,68 @@
+package models
+
+import (
+	"eta_gn/eta_task/global"
+	"fmt"
+	"strings"
+	"time"
+)
+
+// PptV2 表
+type PptV2 struct {
+	PptId            int       `gorm:"column:ppt_id;primaryKey;autoIncrement:true" description:"ppt的Id"`
+	TemplateType     int       `gorm:"column:template_type" description:"模版类型"`
+	BackgroundImg    string    `gorm:"column:background_img" description:"背景图片"`
+	Title            string    `gorm:"column:title" description:"标题"`
+	ReportType       string    `gorm:"column:report_type" description:"报告类型"`
+	PptDate          string    `gorm:"column:ppt_date" description:"选择日期"`
+	Content          string    `gorm:"column:content" description:"ppt内容"`
+	PptUrl           string    `gorm:"column:ppt_url" description:"ppt下载地址"`
+	PptxUrl          string    `gorm:"column:pptx_url" description:"pptx下载地址"`
+	CreateTime       time.Time `gorm:"column:create_time" description:"创建时间"`
+	ModifyTime       time.Time `gorm:"column:modify_time" description:"修改时间"`
+	AdminId          int       `gorm:"column:admin_id" description:"系统用户id"`
+	AdminRealName    string    `gorm:"column:admin_real_name" description:"系统用户名称"`
+	PptVersion       int8      `gorm:"column:ppt_version" description:"是否ppt的旧版本;1:旧的,2:新的"`
+	ReportId         int       `gorm:"column:report_id" description:"关联的报告ID"`
+	ReportCode       string    `gorm:"column:report_code" description:"关联的报告code"`
+	IsShare          int8      `gorm:"column:is_share" description:"是否分享,0:不分享,1:分享"`
+	PublishTime      time.Time `gorm:"column:publish_time" description:"发布时间"`
+	CoverContent     string    `gorm:"column:cover_content" description:"PPT内容-JSON"`
+	PptPage          int       `gorm:"column:ppt_page" description:"PPT页数"`
+	TitleSetting     string    `gorm:"column:title_setting" description:"PPT标题设置"`
+	ClassifyId       int       `gorm:"column:classify_id" description:"报告分类ID"`
+	AddType          int       `gorm:"column:add_type" description:"新增方式:1-新增报告;2-继承报告"`
+	InheritReportId  int       `gorm:"column:inherit_report_id" description:"继承的报告ID"`
+	CollaborateType  int       `gorm:"column:collaborate_type" description:"协作方式:1-个人;2-多人协作"`
+	CollaborateUsers string    `gorm:"column:collaborate_users" description:"协作人IDs, 英文逗号分隔"`
+	IsPublicPublish  int       `gorm:"column:is_public_publish" description:"是否公开发布:1-是;2-否"`
+	SubmitTime       time.Time `gorm:"column:submit_time" description:"提交时间"`
+	ApproveTime      time.Time `gorm:"column:approve_time" description:"审批时间"`
+	ReportSource     int       `gorm:"column:report_source" description:"报告来源:1-系统内;2-智力共享"`
+	OutReportId      string    `gorm:"column:out_report_id" description:"外部报告ID(或编码)"`
+	State            int       `gorm:"column:state" description:"报告状态:1-未发布;2-已发布;3-待提交;4-待审批;5-已驳回;6-已通过"`
+	TopicEndTime     time.Time `gorm:"column:topic_end_time" description:"课题结束时间"`
+}
+
+// PptReportQueryFields 除富文本的常用查询字段
+var PptReportQueryFields = []string{
+	"ppt_id", "title", "classify_id", "ppt_version", "pptx_url", "ppt_page", "title_setting", "state", "report_source", "publish_time", "submit_time", "approve_time", "create_time", "modify_time", "admin_id", "admin_real_name", "collaborate_type", "collaborate_users", "topic_end_time",
+}
+
+func (m *PptV2) TableName() string {
+	return "ppt_v2"
+}
+
+func (m *PptV2) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*PptV2, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}

+ 32 - 3
models/report.go

@@ -2,9 +2,21 @@ package models
 
 import (
 	"eta_gn/eta_task/global"
+	"fmt"
+	"strings"
 	"time"
 )
 
+// 报告状态
+const (
+	ReportStateUnpublished = 1 // 未发布
+	ReportStatePublished   = 2 // 已发布
+	ReportStateWaitSubmit  = 3 // 待提交
+	ReportStateWaitApprove = 4 // 审批中
+	ReportStateRefused     = 5 // 已驳回
+	ReportStatePass        = 6 // 已通过
+)
+
 type Report struct {
 	Id                 int       `orm:"column(id)" description:"报告Id"`
 	AddType            int       `description:"新增方式:1:新增报告,2:继承报告"`
@@ -32,9 +44,12 @@ type Report struct {
 	OldReportId        int       `description:"research_report表ID(后续一两个版本过渡需要,之后可移除)"`
 	PreMsgSend         int       `description:"定时发布成功后是否立即推送模版消息:0否,1是"`
 	AdminId            int
-	AdminName          string `description:"系统用户名称"`
-	ClassifyIdThird    int    `description:"三级分类id"`
-	ClassifyNameThird  string `description:"三级分类名称"`
+	AdminName          string    `description:"系统用户名称"`
+	ClassifyIdThird    int       `description:"三级分类id"`
+	ClassifyNameThird  string    `description:"三级分类名称"`
+	ReportSource       int       `gorm:"column:report_source" description:"报告来源:1-系统内;2-智力共享"`
+	OutReportId        string    `gorm:"column:out_report_id" description:"外部报告ID(或编码)"`
+	TopicEndTime       time.Time `gorm:"column:topic_end_time" description:"课题结束时间"`
 }
 
 //
@@ -319,3 +334,17 @@ func PublishReportAndChapter(reportInfo *Report, isPublishReport bool, cols []st
 
 	return
 }
+
+func (m *Report) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*Report, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM report WHERE 1=1 %s %s`, fields, condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}

+ 115 - 0
models/report_grant.go

@@ -0,0 +1,115 @@
+package models
+
+import (
+	"eta_gn/eta_task/global"
+	"eta_gn/eta_task/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+// ReportGrant 报告授权表
+type ReportGrant struct {
+	GrantId    int       `gorm:"primaryKey;column:grant_id;type:int(9) unsigned;not null"`    // 授权id
+	ReportId   int       `gorm:"column:report_id;type:int(9) unsigned;not null;default:0"`    // 报告id
+	AdminId    int       `gorm:"column:admin_id;type:int(9) unsigned;default:0"`              // 授权的用户id
+	CreateTime time.Time `gorm:"column:create_time;type:timestamp;default:CURRENT_TIMESTAMP"` // 授权时间
+}
+
+func (m *ReportGrant) TableName() string {
+	return "report_grant"
+}
+
+type ReportGrantCols struct {
+	PrimaryId  string
+	ReportId   string
+	AdminId    string
+	CreateTime string
+}
+
+func (m *ReportGrant) Cols() ReportGrantCols {
+	return ReportGrantCols{
+		PrimaryId:  "grant_id",
+		ReportId:   "report_id",
+		AdminId:    "admin_id",
+		CreateTime: "create_time",
+	}
+}
+
+func (m *ReportGrant) Create() (err error) {
+	err = global.DmSQL["rddp"].Create(m).Error
+	return
+}
+
+func (m *ReportGrant) CreateMulti(items []*ReportGrant) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	err = global.DmSQL["rddp"].CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (m *ReportGrant) Update(cols []string) (err error) {
+	err = global.DmSQL["rddp"].Select(cols).Updates(m).Error
+	return
+}
+
+func (m *ReportGrant) Remove() (err error) {
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = global.DmSQL["rddp"].Exec(sql, m.GrantId).Error
+	return
+}
+
+func (m *ReportGrant) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	err = global.DmSQL["rddp"].Exec(sql, ids).Error
+	return
+}
+
+func (m *ReportGrant) RemoveByCondition(condition string, pars []interface{}) (err error) {
+	if condition == "" {
+		return
+	}
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
+	err = global.DmSQL["rddp"].Exec(sql, pars...).Error
+	return
+}
+
+func (m *ReportGrant) GetItemById(id int) (item *ReportGrant, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = global.DmSQL["rddp"].Raw(sql, id).First(&item).Error
+	return
+}
+
+func (m *ReportGrant) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *ReportGrant, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).First(&item).Error
+	return
+}
+
+func (m *ReportGrant) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func (m *ReportGrant) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*ReportGrant, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}

+ 213 - 0
models/report_message.go

@@ -0,0 +1,213 @@
+package models
+
+import (
+	"eta_gn/eta_task/global"
+	"eta_gn/eta_task/utils"
+	"fmt"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+const (
+	ReportMessageTypeWriteNotice   = 1 // 撰写通知
+	ReportMessageTypeApprovePass   = 2 // 审批通过
+	ReportMessageTypeApproveRefuse = 3 // 审批驳回
+)
+
+type ReportMessage struct {
+	Id            int       `gorm:"primaryKey;column:id;type:int(10) unsigned;not null"`
+	SendUserId    int       `gorm:"column:send_user_id" description:"发送人ID"`
+	ReceiveUserId int       `gorm:"column:receive_user_id" description:"接受者ID"`
+	Content       string    `gorm:"column:content" description:"消息内容"`
+	Remark        string    `gorm:"column:remark" description:"备注信息"`
+	ExtraContent  string    `gorm:"column:extra_content" description:"额外信息-JSON"`
+	ReportType    int       `gorm:"column:report_type" description:"报告类型:1-研报;2-PPT"`
+	ReportId      int       `gorm:"column:report_id" description:"报告/PPT-ID"`
+	MessageType   int       `gorm:"column:message_type" description:"消息类型:1-撰写通知;2-审批通过;3-审批驳回"`
+	IsRead        int       `gorm:"column:is_read" description:"是否已读:0-未读;1-已读"`
+	CreateTime    time.Time `gorm:"column:create_time" description:"消息时间"`
+	ModifyTime    time.Time `gorm:"column:modify_time" description:"更新时间"`
+}
+
+var ReportMessageCols = struct {
+	Id            string
+	SendUserId    string
+	ReceiveUserId string
+	Content       string
+	Remark        string
+	ExtraContent  string
+	ReportType    string
+	ReportId      string
+	MessageType   string
+	IsRead        string
+	CreateTime    string
+}{
+	Id:            "id",
+	SendUserId:    "send_user_id",
+	ReceiveUserId: "receive_user_id",
+	Content:       "content",
+	Remark:        "remark",
+	ExtraContent:  "extra_content",
+	ReportType:    "report_type",
+	ReportId:      "report_id",
+	MessageType:   "message_type",
+	IsRead:        "is_read",
+	CreateTime:    "create_time",
+}
+
+func (m *ReportMessage) TableName() string {
+	return "report_message"
+}
+
+func (m *ReportMessage) PrimaryId() string {
+	return ReportMessageCols.Id
+}
+
+func (m *ReportMessage) Create() (err error) {
+	err = global.DmSQL["rddp"].Create(m).Error
+	return
+}
+
+func (m *ReportMessage) CreateMulti(items []*ReportMessage) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	err = global.DmSQL["rddp"].CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (m *ReportMessage) Update(cols []string) (err error) {
+	err = global.DmSQL["rddp"].Select(cols).Updates(m).Error
+	return
+}
+
+func (m *ReportMessage) Del() (err error) {
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = global.DmSQL["rddp"].Exec(sql, m.Id).Error
+	return
+}
+
+func (m *ReportMessage) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	err = global.DmSQL["rddp"].Exec(sql, menuIds).Error
+	return
+}
+
+func (m *ReportMessage) GetItemById(id int) (item *ReportMessage, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = global.DmSQL["rddp"].Raw(sql, id).First(&item).Error
+	return
+}
+
+func (m *ReportMessage) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *ReportMessage, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).First(&item).Error
+	return
+}
+
+func (m *ReportMessage) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func (m *ReportMessage) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*ReportMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *ReportMessage) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*ReportMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	pars = append(pars, startSize)
+	pars = append(pars, pageSize)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// ReportMessageItem 报告消息
+type ReportMessageItem struct {
+	Id            int
+	SendUserId    int                       `description:"发送人ID"`
+	ReceiveUserId int                       `description:"接收者ID"`
+	Content       string                    `description:"消息内容"`
+	Remark        string                    `description:"备注信息"`
+	ReportType    int                       `description:"报告类型:1-研报;2-PPT"`
+	ReportId      int                       `description:"报告/PPT-ID"`
+	ReportState   int                       `description:"报告当前状态"`
+	MessageType   int                       `description:"消息类型:1-撰写通知;2-审批通过;3-审批驳回"`
+	IsRead        int                       `description:"是否已读:0-未读;1-已读"`
+	CreateTime    string                    `description:"消息时间"`
+	ApproveMsg    *ReportMessageApproveItem `description:"审批信息"`
+}
+
+// ReportMessageApproveItem 报告消息审批内容
+type ReportMessageApproveItem struct {
+	Title           string `description:"报告标题"`
+	ApproveType     int    `description:"审批类型:1-通过;2-驳回"`
+	ApproveUserId   int    `description:"审批人ID"`
+	ApproveUserName string `description:"审批人"`
+	ApproveRemark   string `description:"审批备注(驳回意见)"`
+}
+
+// FormatReportMessage2Item 格式化报告消息
+func FormatReportMessage2Item(origin *ReportMessage) (item *ReportMessageItem) {
+	item = new(ReportMessageItem)
+	if origin == nil {
+		return
+	}
+	item.Id = origin.Id
+	item.SendUserId = origin.SendUserId
+	item.ReceiveUserId = origin.ReceiveUserId
+	item.Content = origin.Content
+	item.Remark = origin.Remark
+	item.ReportType = origin.ReportType
+	item.ReportId = origin.ReportId
+	item.MessageType = origin.MessageType
+	item.IsRead = origin.IsRead
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	return
+}
+
+// ReportMessageListReq 消息列表请求参数
+type ReportMessageListReq struct {
+	PageSize     int `form:"PageSize"`
+	CurrentIndex int `form:"CurrentIndex"`
+}
+
+// ReportMessageListResp 消息列表响应体
+type ReportMessageListResp struct {
+	List        []*ReportMessageItem
+	Paging      *paging.PagingItem `description:"分页数据"`
+	UnreadTotal int                `description:"消息未读数"`
+}
+
+// ReportMessageReadReq 消息已读请求体
+type ReportMessageReadReq struct {
+	MessageId int `description:"消息ID"`
+}

+ 3 - 2
services/eta_bridge/eta_bridge.go

@@ -13,8 +13,9 @@ import (
 
 // BaseEtaBridgeDataResp 基础返回参数
 type BaseEtaBridgeDataResp struct {
-	Code int    `json:"code" description:"状态码"`
-	Msg  string `json:"msg" description:"提示信息"`
+	Code int         `json:"code" description:"状态码"`
+	Msg  string      `json:"msg" description:"提示信息"`
+	Data interface{} `json:"data" description:"返回数据"`
 	//Data GetCrmTokenData `json:"data" description:"返回数据"`
 }
 

+ 19 - 0
services/eta_bridge/gn.go

@@ -818,3 +818,22 @@ func InitRefreshEdb(cont context.Context) (err error) {
 	}
 	return
 }
+
+// PostOAReq
+// @Description: 请求oa待办参数
+type PostOAReq struct {
+	AppPersonId   string `json:"appPersonId" form:"appPersonId" description:"⽤户⼯号"`
+	AppPersonName string `json:"appPersonName" form:"appPersonName" description:"⽤户名"`
+	AppTaskUrl    string `json:"appTaskUrl" form:"appTaskUrl" description:"待办地址,跳转地址"`
+	TaskName      string `json:"taskName" form:"taskName" description:"待办标题"`
+	StatusName    string `json:"statusName" form:"statusName" description:"待办节点名称"`
+	Status        int    `json:"status" form:"status" description:"待办状态:1-插⼊,2-更新,3-删除"`
+	AppTaskId     string `json:"appTaskId" form:"appTaskId" description:"待办任务ID:插⼊时不需要传参,由接⼝⽣成唯⼀ID并返回,需要业务系统保存此ID,⽤于后续的更新和删除操作"`
+}
+
+// PostOAResp 请求OA响应
+type PostOAResp struct {
+	Code int    `json:"code" description:"状态码"`
+	Msg  string `json:"msg" description:"提示信息"`
+	Data string `json:"data" description:"待办任务ID"`
+}

+ 324 - 0
services/report.go

@@ -1,10 +1,12 @@
 package services
 
 import (
+	"encoding/json"
 	"errors"
 	"eta_gn/eta_task/models"
 	"eta_gn/eta_task/models/report"
 	"eta_gn/eta_task/services/alarm_msg"
+	"eta_gn/eta_task/services/eta_bridge"
 	"eta_gn/eta_task/utils"
 	"fmt"
 	"golang.org/x/net/context"
@@ -507,3 +509,325 @@ func getMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyNa
 
 	return
 }
+
+// ReportWriteRemind 报告撰写提醒
+func ReportWriteRemind(cont context.Context) (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("ReportWriteRemind-报告撰写提醒失败, ErrMsg: %v", err)
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	timeNow := time.Now()
+	timeClock := timeNow.Format("15:04")
+
+	// 查询需要提醒的分类
+	classifies := make([]*models.Classify, 0)
+	{
+		ob := new(models.Classify)
+		cond := ` AND is_remind = ? AND remind_time = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, 1, timeClock)
+		list, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+		if e != nil {
+			err = fmt.Errorf("获取分类失败, %v", e)
+			return
+		}
+		classifies = list
+	}
+	if len(classifies) == 0 {
+		return
+	}
+	var reportClassifyIds, pptClassifyIds []int
+	classifyMatch := make(map[string]bool)
+	for _, v := range classifies {
+		if v.ClassifyType == utils.ReportTypeDefault {
+			// levelPath作为下面报告的匹配
+			var levelIds []int
+			var firstId, secondId, thirdId int
+			levelArr := strings.Split(v.LevelPath, ",")
+			for _, l := range levelArr {
+				id, _ := strconv.Atoi(l)
+				levelIds = append(levelIds, id)
+			}
+			if len(levelIds) > 2 {
+				firstId = levelIds[0]
+				secondId = levelIds[1]
+				thirdId = levelIds[2]
+			}
+			if len(levelIds) > 1 {
+				firstId = levelIds[0]
+				secondId = levelIds[1]
+			}
+			if len(levelIds) > 0 {
+				firstId = levelIds[0]
+			}
+			classifyMatch[fmt.Sprintf("%d-%d-%d", firstId, secondId, thirdId)] = true
+			reportClassifyIds = append(reportClassifyIds, v.Id)
+			continue
+		}
+		if v.ClassifyType == utils.ReportTypePPT {
+			pptClassifyIds = append(pptClassifyIds, v.Id)
+			continue
+		}
+	}
+
+	// 查询需要提醒的报告
+	remindReports := make([]*models.Report, 0)
+	if len(reportClassifyIds) > 0 {
+		ob := new(models.Report)
+		cond := ` AND report_source = ? AND state = ? AND topic_end_time >= ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, utils.ReportSourceOuter, models.ReportStateWaitSubmit, timeNow)
+		list, e := ob.GetItemsByCondition(cond, pars, []string{"id", "title", "admin_id", "classify_id_first", "classify_id_second", "classify_id_third"}, "")
+		if e != nil {
+			err = fmt.Errorf("获取待提醒报告失败, %v", e)
+			return
+		}
+		for _, v := range list {
+			k := fmt.Sprintf("%d-%d-%d", v.ClassifyIdFirst, v.ClassifyIdSecond, v.ClassifyIdThird)
+			if !classifyMatch[k] {
+				continue
+			}
+			remindReports = append(remindReports, v)
+		}
+	}
+
+	// 查询需要提醒的PPT
+	remindPpts := make([]*models.PptV2, 0)
+	if len(pptClassifyIds) > 0 {
+		ob := new(models.PptV2)
+		cond := ` AND report_source = ? AND state = ? AND topic_end_time >= ? AND classify_id IN (?)`
+		pars := make([]interface{}, 0)
+		pars = append(pars, utils.ReportSourceOuter, models.ReportStateWaitSubmit, timeNow, pptClassifyIds)
+		list, e := ob.GetItemsByCondition(cond, pars, models.PptReportQueryFields, "")
+		if e != nil {
+			err = fmt.Errorf("获取待提醒报告失败, %v", e)
+			return
+		}
+		remindPpts = list
+	}
+	if len(remindReports) == 0 && len(remindPpts) == 0 {
+		return
+	}
+
+	reportMessages := make([]*models.ReportMessage, 0)
+	// 报告提醒
+	if len(remindReports) > 0 {
+		var remindReportIds []int
+		for _, v := range remindReports {
+			remindReportIds = append(remindReportIds, v.Id)
+		}
+
+		// 获取协作人
+		grantOb := new(models.ReportGrant)
+		grantCond := ` AND report_id IN (?)`
+		grantPars := make([]interface{}, 0)
+		grantPars = append(grantPars, remindReportIds)
+		grants, e := grantOb.GetItemsByCondition(grantCond, grantPars, []string{}, "")
+		if e != nil {
+			err = fmt.Errorf("获取报告协作人失败, %v", e)
+			return
+		}
+		reportGrants := make(map[int][]int)
+		for _, v := range grants {
+			reportGrants[v.ReportId] = append(reportGrants[v.ReportId], v.GrantId)
+		}
+
+		// 推送消息
+		for _, v := range remindReports {
+			var userIds []int
+			userIds = append(userIds, v.AdminId)
+			for _, p := range reportGrants[v.Id] {
+				if !utils.InArrayByInt(userIds, p) {
+					userIds = append(userIds, p)
+				}
+			}
+
+			for _, u := range userIds {
+				m := new(models.ReportMessage)
+				m.SendUserId = 0
+				m.ReceiveUserId = u
+				m.Content = fmt.Sprintf("您有一篇【%s】待编辑,请点击查看", v.Title)
+				m.ReportType = utils.ReportTypeDefault
+				m.ReportId = v.Id
+				m.MessageType = models.ReportMessageTypeWriteNotice
+				m.CreateTime = time.Now()
+				m.ModifyTime = time.Now()
+				reportMessages = append(reportMessages, m)
+			}
+		}
+	}
+
+	// PPT提醒
+	if len(remindPpts) > 0 {
+		for _, v := range remindPpts {
+			// 收信人
+			var userIds []int
+			userIds = append(userIds, v.AdminId)
+			partnerArr := strings.Split(v.CollaborateUsers, ",")
+			for _, p := range partnerArr {
+				id, _ := strconv.Atoi(p)
+				if id <= 0 {
+					continue
+				}
+				if !utils.InArrayByInt(userIds, id) {
+					userIds = append(userIds, id)
+				}
+			}
+
+			for _, u := range userIds {
+				m := new(models.ReportMessage)
+				m.SendUserId = 0
+				m.ReceiveUserId = u
+				m.Content = fmt.Sprintf("您有一篇【%s】待编辑,请点击查看", v.Title)
+				m.ReportType = utils.ReportTypePPT
+				m.ReportId = v.PptId
+				m.MessageType = models.ReportMessageTypeWriteNotice
+				m.CreateTime = time.Now()
+				m.ModifyTime = time.Now()
+				reportMessages = append(reportMessages, m)
+			}
+		}
+	}
+
+	if len(reportMessages) == 0 {
+		return
+	}
+	messageOb := new(models.ReportMessage)
+	if e := messageOb.CreateMulti(reportMessages); e != nil {
+		err = fmt.Errorf("新增报告提醒失败, %v", e)
+		return
+	}
+
+	// OA消息
+	go func() {
+		_ = SendOaReportMessage(reportMessages)
+	}()
+	return
+}
+
+// SendOaReportMessage 推送OA报告消息
+func SendOaReportMessage(reportMessages []*models.ReportMessage) (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("SendOaReportMessage-报告OA消息推送失败, ErrMsg: %v", err)
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+
+	// 未开启则不管
+	conf, e := models.GetBusinessConfByKey(models.BusinessOpenOaMsg)
+	if e != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取OA消息开关失败, %v", e))
+		return
+	}
+	var sendOa bool
+	if conf != nil && conf.ConfVal == "true" {
+		sendOa = true
+	}
+	if !sendOa {
+		return
+	}
+	hostConf, e := models.GetBusinessConfByKey(models.BusinessOaReportHost)
+	if e != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取OA消息跳转Host失败, %v", e))
+		return
+	}
+	var hostUrl string
+	if hostConf != nil {
+		hostUrl = hostConf.ConfVal
+	}
+	if hostUrl == "" {
+		utils.FileLog.Info("OA消息跳转Host未配置")
+		return
+	}
+	reportUrl := fmt.Sprintf("%s/reportNew", hostUrl)
+	pptUrl := fmt.Sprintf("%s/pptlist", hostUrl)
+
+	// 查询用户,匹配工号
+	adminIdOut := make(map[int]*models.Admin)
+	{
+		adminOb := new(models.Admin)
+		admins, e := adminOb.GetItemsByCondition(``, make([]interface{}, 0), []string{"admin_id", "real_name", "out_id"}, "")
+		if e != nil {
+			err = fmt.Errorf("获取员工列表失败, %v", e)
+			return
+		}
+		for _, v := range admins {
+			adminIdOut[v.AdminId] = v
+		}
+	}
+
+	// 推送OA
+	oaMessages := make([]*models.OaReportMessage, 0)
+	for _, v := range reportMessages {
+		// 接收用户
+		receiver := adminIdOut[v.ReceiveUserId]
+		if receiver == nil || (receiver != nil && receiver.AdminId <= 0) {
+			utils.FileLog.Info(fmt.Sprintf("SendOaReportMessage-OA推送用户异常, UserId: %d", v.ReceiveUserId))
+			continue
+		}
+
+		oaMessage := new(models.OaReportMessage)
+		oaMessage.ReceiveUserId = receiver.AdminId
+		oaMessage.ReportType = v.ReportType
+		oaMessage.ReportId = v.ReportId
+		oaMessage.Source = models.OaReportMessageSourceRemind
+		oaMessage.SendStatus = models.OaReportMessageStatusFail
+		oaMessage.CreateTime = time.Now()
+		oaMessage.ModifyTime = time.Now()
+
+		// OA请求参数
+		var params eta_bridge.PostOAReq
+		params.AppPersonId = receiver.OutId
+		params.AppPersonName = receiver.RealName
+		if v.ReportType == utils.ReportTypeDefault {
+			params.AppTaskUrl = reportUrl
+		}
+		if v.ReportType == utils.ReportTypePPT {
+			params.AppTaskUrl = pptUrl
+		}
+		params.TaskName = v.Content
+		params.StatusName = v.Content
+		params.Status = 1
+		b, e := json.Marshal(params)
+		if e != nil {
+			oaMessage.MessageResult = fmt.Sprintf("OA推送JSON格式化失败, %v", e)
+			oaMessages = append(oaMessages, oaMessage)
+			continue
+		}
+		oaMessage.MessageParams = string(b)
+
+		// OA请求
+		resByte, e, _ := eta_bridge.HttpEtaBridgePost(utils.SyncOaTodoPath, params)
+		if e != nil {
+			oaMessage.MessageResult = fmt.Sprintf("OA推送POST请求失败, %v", e)
+			oaMessages = append(oaMessages, oaMessage)
+			continue
+		}
+		oaMessage.MessageResult = string(resByte)
+		var sendRes eta_bridge.PostOAResp
+		if e = json.Unmarshal(resByte, &sendRes); e != nil {
+			oaMessages = append(oaMessages, oaMessage)
+			continue
+		}
+		if sendRes.Code != 200 {
+			oaMessages = append(oaMessages, oaMessage)
+			continue
+		}
+		oaMessage.TaskId = sendRes.Data
+		oaMessage.SendStatus = models.OaReportMessageStatusSuccess
+		oaMessages = append(oaMessages, oaMessage)
+	}
+	if len(oaMessages) == 0 {
+		return
+	}
+	oaMessageOb := new(models.OaReportMessage)
+	if e := oaMessageOb.CreateMulti(oaMessages); e != nil {
+		err = fmt.Errorf("新增OA待办记录失败, %v", e)
+	}
+	return
+}

+ 5 - 3
services/task.go

@@ -19,9 +19,11 @@ func Task() {
 		releaseTask()
 	}
 
-	// 定时发布研报
-	publishReport := task.NewTask("publishReport", "0 */1 * * * *", PublishReport)
-	task.AddTask("定时发布研报", publishReport)
+	//var ctx context.Context
+	//_ = ReportWriteRemind(ctx)
+	// 定时发布研报(国能没定时发布了)
+	//publishReport := task.NewTask("publishReport", "0 */1 * * * *", PublishReport)
+	//task.AddTask("定时发布研报", publishReport)
 
 	// 定时汇总数据源终端指标更新情况
 	setEdbSourceStatTask := task.NewTask("setEdbSourceStatTask", "0 20 19,23 * * *", data_stat.SetEdbSourceStatTask)

+ 3 - 0
services/task_gn.go

@@ -31,4 +31,7 @@ func GnTask() {
 	//syncOaUser := task.NewTask("syncGnUser", syncOaUserTime, eta_bridge.SyncGnUser)
 	//task.AddTask("定时同步OA用户信息", syncOaUser)
 
+	// 每分钟检查一下是否需要发送报告撰写提醒
+	sendReportWriteRemind := task.NewTask("sendReportWriteRemind", "0 */1 * * * *", ReportWriteRemind)
+	task.AddTask("定时发送报告撰写提醒", sendReportWriteRemind)
 }

+ 8 - 0
utils/common.go

@@ -914,3 +914,11 @@ func MinusInt(a []int, b []int) []int {
 	}
 	return diff
 }
+
+func TimeTransferString(format string, t time.Time) string {
+	str := t.Format(format)
+	if t.IsZero() {
+		return ""
+	}
+	return str
+}

+ 2 - 0
utils/config.go

@@ -123,6 +123,7 @@ var (
 	SyncCrmDataSourceType string // 桥接服务-crm内部来源系统参数配置
 	SyncCrmIndexNum       int    // 桥接服务-每次同步crm数据的数量
 	SyncOaUserTime        string // 桥接服务-OA用户同步时间
+	SyncOaTodoPath        string // 桥接服务-OA待办接口
 )
 
 var (
@@ -273,6 +274,7 @@ func init() {
 		SyncCrmAssetPkgCd = config["sync_crm_asset_pkg_cd"]         // 桥接服务-crm资产包配置
 		SyncCrmDataSourceType = config["sync_crm_data_source_type"] // 桥接服务-crm内部来源系统参数配置
 		SyncOaUserTime = config["sync_oa_user_time"]                // 桥接服务-OA用户同步时间
+		SyncOaTodoPath = config["sync_oa_todo_path"]                // 桥接服务-OA待办接口
 
 		syncCrmIndexNumStr := config["sync_crm_index_num"] // 桥接服务-每次同步crm数据的数量
 		if syncCrmIndexNumStr != `` {

+ 7 - 0
utils/constants.go

@@ -217,3 +217,10 @@ const (
 
 // BaseEdbRefreshStartDate 指标的基础刷新开始日期
 const BaseEdbRefreshStartDate = `1899-01-01`
+
+const (
+	ReportTypeDefault = 1 // 报告类型-默认研报
+	ReportTypePPT     = 2 // 报告类型-PPT
+	ReportSourceLocal = 1 // 报告来源-本地
+	ReportSourceOuter = 2 // 报告来源-外部
+)