|
|
@@ -3,6 +3,7 @@ package opsdev
|
|
|
import (
|
|
|
"context"
|
|
|
"fmt"
|
|
|
+ "math"
|
|
|
"strings"
|
|
|
|
|
|
"dashoo.cn/opms_libary/myerrors"
|
|
|
@@ -49,11 +50,16 @@ func NewOpsEventTaskService(ctx context.Context) (svc *OpsEventTaskService, err
|
|
|
func (s *OpsEventTaskService) GetList(req *opsdevmodel.OpsEventTaskSearchReq) (total int, list []*opsdevmodel.OpsEventTaskRsp, err error) {
|
|
|
db := s.TaskDao.FieldsEx(s.TaskDao.Columns.DeletedTime)
|
|
|
|
|
|
- // 项目ID筛选
|
|
|
+ // 项目ID筛选(单选)
|
|
|
if req.ProjectId > 0 {
|
|
|
db = db.Where(s.TaskDao.Columns.ProjectId, req.ProjectId)
|
|
|
}
|
|
|
|
|
|
+ // 项目ID列表筛选(多选,优先于单选)
|
|
|
+ if len(req.ProjectIds) > 0 {
|
|
|
+ db = db.Where(s.TaskDao.Columns.ProjectId+" in (?)", req.ProjectIds)
|
|
|
+ }
|
|
|
+
|
|
|
// 关联事件ID筛选
|
|
|
if req.EventId > 0 {
|
|
|
db = db.Where(s.TaskDao.Columns.EventId, req.EventId)
|
|
|
@@ -89,6 +95,13 @@ func (s *OpsEventTaskService) GetList(req *opsdevmodel.OpsEventTaskSearchReq) (t
|
|
|
db = db.Where(s.TaskDao.Columns.ReleaseVersion + " is null")
|
|
|
}
|
|
|
|
|
|
+ // 排期状态筛选(plan_start_time/plan_end_time 为 datetime 类型,需用 IS NULL)
|
|
|
+ if req.ScheduleStatus == "scheduled" {
|
|
|
+ db = db.Where(s.TaskDao.Columns.PlanStartTime + " is not null").Where(s.TaskDao.Columns.PlanEndTime + " is not null")
|
|
|
+ } else if req.ScheduleStatus == "unscheduled" {
|
|
|
+ db = db.Where(s.TaskDao.Columns.PlanStartTime + " is null or " + s.TaskDao.Columns.PlanEndTime + " is null")
|
|
|
+ }
|
|
|
+
|
|
|
// 计划结束日期范围筛选
|
|
|
if req.PlanEndDateStart != "" {
|
|
|
db = db.Where(s.TaskDao.Columns.PlanEndTime+" >= ?", req.PlanEndDateStart+" 00:00:00")
|
|
|
@@ -595,10 +608,18 @@ func (s *OpsEventTaskService) Complete(req *opsdevmodel.OpsEventTaskCompleteReq)
|
|
|
|
|
|
// doComplete 执行完成任务(可在下游任务编号冲突时重试)
|
|
|
func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteReq, entity *opsdevmodel.OpsEventTask) error {
|
|
|
+ // 解析完成日期
|
|
|
+ completeTime := gtime.Now()
|
|
|
+ if req.CompleteDate != "" {
|
|
|
+ if parsed := gtime.NewFromStrFormat(req.CompleteDate, "Y-m-d"); parsed != nil {
|
|
|
+ completeTime = parsed
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 构造更新数据
|
|
|
data := g.Map{
|
|
|
s.TaskDao.Columns.TaskStatus: opsdevmodel.TaskStatusCompleted, // 已完成
|
|
|
- s.TaskDao.Columns.CompleteTime: gtime.Now(),
|
|
|
+ s.TaskDao.Columns.CompleteTime: completeTime,
|
|
|
s.TaskDao.Columns.ActualWorkHour: req.ActualWorkHour,
|
|
|
s.TaskDao.Columns.Remark: req.Remark,
|
|
|
}
|
|
|
@@ -624,7 +645,26 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
return myerrors.DbError("完成任务失败")
|
|
|
}
|
|
|
|
|
|
- // 2. 创建过程记录
|
|
|
+ // 2. 检查实际工时差异,自动登记工时差额
|
|
|
+ delta := req.ActualWorkHour - entity.ActualWorkHour
|
|
|
+ if delta != 0 {
|
|
|
+ workHourData := g.Map{
|
|
|
+ s.WorkHourDao.Columns.TaskId: req.Id,
|
|
|
+ s.WorkHourDao.Columns.OpsUserId: s.GetCxtUserId(),
|
|
|
+ s.WorkHourDao.Columns.OpsUserName: s.GetCxtUserName(),
|
|
|
+ s.WorkHourDao.Columns.ActualWorkDate: completeTime.Format("Y-m-d"),
|
|
|
+ s.WorkHourDao.Columns.ActualWorkHour: delta,
|
|
|
+ s.WorkHourDao.Columns.Remark: "完成任务自动登记工时差额",
|
|
|
+ }
|
|
|
+ service.SetCreatedInfo(workHourData, s.GetCxtUserId(), s.GetCxtUserName())
|
|
|
+ _, err = s.WorkHourDao.TX(tx).Data(workHourData).Insert()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error(err)
|
|
|
+ return myerrors.DbError("登记工时差额失败")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 创建过程记录
|
|
|
var handleContent string
|
|
|
if entity.TaskType == opsdevmodel.TaskTypeFeatureTest && req.TestResult != "" {
|
|
|
testResultText := "通过"
|
|
|
@@ -662,7 +702,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
|
|
|
recordId, _ := result.LastInsertId()
|
|
|
|
|
|
- // 3. 保存附件
|
|
|
+ // 4. 保存附件
|
|
|
if len(req.Attachments) > 0 {
|
|
|
for _, att := range req.Attachments {
|
|
|
attData := g.Map{
|
|
|
@@ -682,8 +722,8 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 4. 根据任务类型自动创建下游任务
|
|
|
- // 4.1 功能开发完成时,自动创建功能测试任务(原4.2)
|
|
|
+ // 5. 根据任务类型自动创建下游任务
|
|
|
+ // 5.1 功能开发完成时,自动创建功能测试任务(原4.2)
|
|
|
if entity.TaskType == opsdevmodel.TaskTypeFeatureDev {
|
|
|
testTaskData := g.Map{
|
|
|
s.TaskDao.Columns.TaskNo: testTaskNo,
|
|
|
@@ -728,7 +768,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 4.2b BUG任务完成时,自动创建功能测试任务
|
|
|
+ // 5.2b BUG任务完成时,自动创建功能测试任务
|
|
|
if entity.TaskType == opsdevmodel.TaskTypeBug {
|
|
|
testTaskData := g.Map{
|
|
|
s.TaskDao.Columns.TaskNo: testTaskNo,
|
|
|
@@ -785,7 +825,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 4.3 系统发版完成时,保存关联的研发任务到ops_event_task_release表
|
|
|
+ // 5.3 系统发版完成时,保存关联的研发任务到ops_event_task_release表
|
|
|
if entity.TaskType == opsdevmodel.TaskTypeSystemReleaseEvt && req.IsReleaseComplete && len(req.DevTaskIds) > 0 {
|
|
|
for _, devTaskId := range req.DevTaskIds {
|
|
|
releaseData := g.Map{
|
|
|
@@ -803,7 +843,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 5. 任务完成时自动更新关联的交付事件状态为完成并生成过程记录
|
|
|
+ // 6. 任务完成时自动更新关联的交付事件状态为完成并生成过程记录
|
|
|
if entity.EventId > 0 && entity.EventType == opsdevmodel.EventTypeDelivery {
|
|
|
// 触发事件自动完成的任务类型:10(需求评审)、30(功能测试-通过)、38(系统发版)、40(系统发版/硬件发货)、41(硬件安装)
|
|
|
if s.shouldAutoCompleteEvent(entity.TaskType, req.TestResult) {
|
|
|
@@ -1340,89 +1380,85 @@ func (s *OpsEventTaskService) GetWorkHourList(req *opsdevmodel.OpsEventTaskWorkH
|
|
|
|
|
|
// GetDashboardData 获取工作台看板数据(周视图)
|
|
|
func (s *OpsEventTaskService) GetDashboardData(startDate, endDate string) (*opsdevmodel.OpsEventTaskWorkHourDashboardRsp, error) {
|
|
|
- type workHourRow struct {
|
|
|
- TaskId int `json:"taskId"`
|
|
|
- ActualWorkDate string `json:"actualWorkDate"`
|
|
|
- ActualWorkHour float64 `json:"actualWorkHour"`
|
|
|
- OpsUserId int `json:"opsUserId"`
|
|
|
- TaskNo string `json:"taskNo"`
|
|
|
- TaskTitle string `json:"taskTitle"`
|
|
|
- TaskType string `json:"taskType"`
|
|
|
- TaskStatus string `json:"taskStatus"`
|
|
|
- Priority string `json:"priority"`
|
|
|
- ProjectName string `json:"projectName"`
|
|
|
- TaskActualHour float64 `json:"taskActualHour"`
|
|
|
- EstimateHour float64 `json:"estimateHour"`
|
|
|
- PlanEndTime string `json:"planEndTime"`
|
|
|
- }
|
|
|
-
|
|
|
userId := s.GetCxtUserId()
|
|
|
db := g.DB(s.Tenant)
|
|
|
- sql := `
|
|
|
- SELECT
|
|
|
- wh.task_id, DATE(wh.actual_work_date) AS actual_work_date, wh.actual_work_hour, wh.ops_user_id,
|
|
|
- t.id, t.task_no, t.task_title, t.task_type, t.task_status,
|
|
|
- t.priority, t.project_name, t.actual_work_hour AS task_actual_hour,
|
|
|
- t.estimate_work_hour, IFNULL(t.plan_end_time, '') AS plan_end_time
|
|
|
- FROM ops_event_task_work_hour wh
|
|
|
- LEFT JOIN ops_event_task t ON wh.task_id = t.id AND t.deleted_time IS NULL
|
|
|
- WHERE wh.actual_work_date >= ? AND wh.actual_work_date <= ?
|
|
|
- AND wh.ops_user_id = ?
|
|
|
- AND wh.deleted_time IS NULL
|
|
|
- ORDER BY wh.task_id, wh.actual_work_date
|
|
|
- `
|
|
|
|
|
|
- var rows []workHourRow
|
|
|
- err := db.GetScan(&rows, sql, startDate, endDate+" 23:59:59", userId)
|
|
|
+ type taskRow struct {
|
|
|
+ Id int `json:"id"`
|
|
|
+ TaskNo string `json:"taskNo"`
|
|
|
+ TaskTitle string `json:"taskTitle"`
|
|
|
+ TaskType string `json:"taskType"`
|
|
|
+ TaskStatus string `json:"taskStatus"`
|
|
|
+ Priority string `json:"priority"`
|
|
|
+ ProjectName string `json:"projectName"`
|
|
|
+ ActualWorkHour float64 `json:"actualWorkHour"`
|
|
|
+ EstimateWorkHour float64 `json:"estimateWorkHour"`
|
|
|
+ PlanStartDate string `json:"planStartDate"`
|
|
|
+ PlanEndTime string `json:"planEndTime"`
|
|
|
+ }
|
|
|
+ taskSQL := `
|
|
|
+ SELECT id, task_no, task_title, task_type, task_status,
|
|
|
+ priority, project_name, actual_work_hour, estimate_work_hour,
|
|
|
+ DATE(plan_start_time) AS plan_start_date,
|
|
|
+ IFNULL(DATE(plan_end_time), '') AS plan_end_time
|
|
|
+ FROM ops_event_task
|
|
|
+ WHERE ops_user_id = ?
|
|
|
+ AND plan_start_time >= ? AND plan_start_time <= ?
|
|
|
+ AND deleted_time IS NULL
|
|
|
+ ORDER BY plan_start_time, priority
|
|
|
+ `
|
|
|
+ var taskRows []taskRow
|
|
|
+ err := db.GetScan(&taskRows, taskSQL, userId, startDate, endDate+" 23:59:59")
|
|
|
if err != nil {
|
|
|
g.Log().Error(err)
|
|
|
- return nil, myerrors.DbError("查询工时数据失败")
|
|
|
+ return nil, myerrors.DbError("查询任务数据失败")
|
|
|
}
|
|
|
|
|
|
- type dayAcc struct {
|
|
|
- totalHours float64
|
|
|
- taskMap map[int]*opsdevmodel.DashboardTaskRsp
|
|
|
+ type hourRow struct {
|
|
|
+ WorkDate string `json:"workDate"`
|
|
|
+ TotalHour float64 `json:"totalHour"`
|
|
|
}
|
|
|
-
|
|
|
- dayMap := make(map[string]*dayAcc, 7)
|
|
|
- seenTasks := make(map[int]bool)
|
|
|
-
|
|
|
- for i := range rows {
|
|
|
- row := &rows[i]
|
|
|
- date := row.ActualWorkDate
|
|
|
- if _, ok := dayMap[date]; !ok {
|
|
|
- dayMap[date] = &dayAcc{taskMap: make(map[int]*opsdevmodel.DashboardTaskRsp)}
|
|
|
- }
|
|
|
- acc := dayMap[date]
|
|
|
- acc.totalHours += row.ActualWorkHour
|
|
|
-
|
|
|
- if _, ok := seenTasks[row.TaskId]; !ok {
|
|
|
- seenTasks[row.TaskId] = true
|
|
|
- }
|
|
|
- if _, ok := acc.taskMap[row.TaskId]; !ok {
|
|
|
- planEndTime := ""
|
|
|
- if len(row.PlanEndTime) >= 10 {
|
|
|
- planEndTime = row.PlanEndTime[:10]
|
|
|
- }
|
|
|
- acc.taskMap[row.TaskId] = &opsdevmodel.DashboardTaskRsp{
|
|
|
- Id: row.TaskId,
|
|
|
- TaskNo: row.TaskNo,
|
|
|
- TaskTitle: row.TaskTitle,
|
|
|
- TaskType: row.TaskType,
|
|
|
- TaskStatus: row.TaskStatus,
|
|
|
- Priority: row.Priority,
|
|
|
- ProjectName: row.ProjectName,
|
|
|
- ActualWorkHour: row.TaskActualHour,
|
|
|
- EstimateWorkHour: row.EstimateHour,
|
|
|
- PlanEndTime: planEndTime,
|
|
|
- }
|
|
|
- }
|
|
|
+ hourSQL := `
|
|
|
+ SELECT DATE(actual_work_date) AS work_date, SUM(actual_work_hour) AS total_hour
|
|
|
+ FROM ops_event_task_work_hour
|
|
|
+ WHERE ops_user_id = ?
|
|
|
+ AND actual_work_date >= ? AND actual_work_date <= ?
|
|
|
+ AND deleted_time IS NULL
|
|
|
+ GROUP BY DATE(actual_work_date)
|
|
|
+ `
|
|
|
+ var hourRows []hourRow
|
|
|
+ err = db.GetScan(&hourRows, hourSQL, userId, startDate, endDate+" 23:59:59")
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error(err)
|
|
|
+ return nil, myerrors.DbError("查询每日工时失败")
|
|
|
+ }
|
|
|
+
|
|
|
+ hourMap := make(map[string]float64, 7)
|
|
|
+ for i := range hourRows {
|
|
|
+ hourMap[hourRows[i].WorkDate] = hourRows[i].TotalHour
|
|
|
+ }
|
|
|
+
|
|
|
+ taskMap := make(map[string][]*opsdevmodel.DashboardTaskRsp, 7)
|
|
|
+ for i := range taskRows {
|
|
|
+ row := &taskRows[i]
|
|
|
+ date := row.PlanStartDate
|
|
|
+ taskMap[date] = append(taskMap[date], &opsdevmodel.DashboardTaskRsp{
|
|
|
+ Id: row.Id,
|
|
|
+ TaskNo: row.TaskNo,
|
|
|
+ TaskTitle: row.TaskTitle,
|
|
|
+ TaskType: row.TaskType,
|
|
|
+ TaskStatus: row.TaskStatus,
|
|
|
+ Priority: row.Priority,
|
|
|
+ ProjectName: row.ProjectName,
|
|
|
+ ActualWorkHour: row.ActualWorkHour,
|
|
|
+ EstimateWorkHour: row.EstimateWorkHour,
|
|
|
+ PlanEndTime: row.PlanEndTime,
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
- userName := s.GetCxtUserName()
|
|
|
overdueCount, err := db.GetValue(
|
|
|
- "SELECT COUNT(1) FROM ops_event_task WHERE plan_end_time < NOW() AND ops_user_name = ? AND task_status NOT IN (?,?) AND deleted_time IS NULL",
|
|
|
- userName,
|
|
|
+ "SELECT COUNT(1) FROM ops_event_task WHERE plan_end_time < NOW() AND ops_user_id = ? AND task_status NOT IN (?,?) AND deleted_time IS NULL",
|
|
|
+ userId,
|
|
|
opsdevmodel.TaskStatusCompleted, opsdevmodel.TaskStatusCancelled,
|
|
|
)
|
|
|
if err != nil {
|
|
|
@@ -1442,20 +1478,17 @@ func (s *OpsEventTaskService) GetDashboardData(startDate, endDate string) (*opsd
|
|
|
if i >= 5 {
|
|
|
targetHours = 0
|
|
|
}
|
|
|
- totalHours := 0.0
|
|
|
- var tasks []*opsdevmodel.DashboardTaskRsp
|
|
|
- if acc, ok := dayMap[date]; ok {
|
|
|
- totalHours = acc.totalHours
|
|
|
- for _, t := range acc.taskMap {
|
|
|
- tasks = append(tasks, t)
|
|
|
- }
|
|
|
- }
|
|
|
+ totalHours := hourMap[date]
|
|
|
weekTotal += totalHours
|
|
|
+ dayTasks := taskMap[date]
|
|
|
+ if dayTasks == nil {
|
|
|
+ dayTasks = []*opsdevmodel.DashboardTaskRsp{}
|
|
|
+ }
|
|
|
days = append(days, &opsdevmodel.DashboardDayRsp{
|
|
|
Date: date,
|
|
|
TotalHours: totalHours,
|
|
|
TargetHours: targetHours,
|
|
|
- Tasks: tasks,
|
|
|
+ Tasks: dayTasks,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -1473,4 +1506,96 @@ func (s *OpsEventTaskService) canAddWorkHour(status string) bool {
|
|
|
return status == opsdevmodel.TaskStatusProcessing
|
|
|
}
|
|
|
|
|
|
+// GetScheduleStats 获取人员排期统计(按周、按天、按人汇总任务数和预估工时)
|
|
|
+func (s *OpsEventTaskService) GetScheduleStats(req *opsdevmodel.OpsEventTaskScheduleStatReq) (*opsdevmodel.OpsEventTaskScheduleStatRsp, error) {
|
|
|
+ type dayRow struct {
|
|
|
+ OpsUserId int `json:"opsUserId"`
|
|
|
+ OpsUserName string `json:"opsUserName"`
|
|
|
+ PlanDate string `json:"planDate"`
|
|
|
+ TaskCount int `json:"taskCount"`
|
|
|
+ EstimateWorkHour float64 `json:"estimateWorkHour"`
|
|
|
+ }
|
|
|
+
|
|
|
+ sql := `
|
|
|
+ SELECT
|
|
|
+ ops_user_id,
|
|
|
+ ops_user_name,
|
|
|
+ DATE(plan_start_time) AS plan_date,
|
|
|
+ COUNT(*) AS task_count,
|
|
|
+ SUM(COALESCE(estimate_work_hour, 0)) AS estimate_work_hour
|
|
|
+ FROM ops_event_task
|
|
|
+ WHERE deleted_time IS NULL
|
|
|
+ AND task_status != ?
|
|
|
+ AND plan_start_time >= ?
|
|
|
+ AND plan_start_time < ?
|
|
|
+ `
|
|
|
+
|
|
|
+ args := []interface{}{opsdevmodel.TaskStatusCancelled, req.WeekStart, req.WeekEnd + " 23:59:59"}
|
|
|
+
|
|
|
+ if req.ProjectId > 0 {
|
|
|
+ sql += " AND project_id = ?"
|
|
|
+ args = append(args, req.ProjectId)
|
|
|
+ }
|
|
|
+
|
|
|
+ sql += `
|
|
|
+ GROUP BY ops_user_id, ops_user_name, DATE(plan_start_time)
|
|
|
+ ORDER BY ops_user_name, plan_date
|
|
|
+ `
|
|
|
+
|
|
|
+ var rows []dayRow
|
|
|
+ err := g.DB(s.Tenant).GetScan(&rows, sql, args...)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error(err)
|
|
|
+ return nil, myerrors.DbError("查询排期统计数据失败")
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按用户聚合,补全 7 天数据
|
|
|
+ userMap := make(map[int]*opsdevmodel.OpsEventTaskUserScheduleStat)
|
|
|
+ for _, row := range rows {
|
|
|
+ user, ok := userMap[row.OpsUserId]
|
|
|
+ if !ok {
|
|
|
+ user = &opsdevmodel.OpsEventTaskUserScheduleStat{
|
|
|
+ OpsUserId: row.OpsUserId,
|
|
|
+ OpsUserName: row.OpsUserName,
|
|
|
+ DayStats: make([]*opsdevmodel.OpsEventTaskUserDayStat, 7),
|
|
|
+ }
|
|
|
+ // 初始化 7 天空数据
|
|
|
+ weekStart := gtime.New(req.WeekStart)
|
|
|
+ for i := 0; i < 7; i++ {
|
|
|
+ day := weekStart.AddDate(0, 0, i)
|
|
|
+ user.DayStats[i] = &opsdevmodel.OpsEventTaskUserDayStat{
|
|
|
+ Date: day.Format("Y-m-d"),
|
|
|
+ TaskCount: 0,
|
|
|
+ EstimateWorkHour: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ userMap[row.OpsUserId] = user
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找对应 day index
|
|
|
+ for _, ds := range user.DayStats {
|
|
|
+ if ds.Date == row.PlanDate {
|
|
|
+ ds.TaskCount = row.TaskCount
|
|
|
+ ds.EstimateWorkHour = row.EstimateWorkHour
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算周合计
|
|
|
+ list := make([]*opsdevmodel.OpsEventTaskUserScheduleStat, 0, len(userMap))
|
|
|
+ for _, user := range userMap {
|
|
|
+ weekTotal := &opsdevmodel.OpsEventTaskUserDayStat{Date: "合计"}
|
|
|
+ for _, ds := range user.DayStats {
|
|
|
+ weekTotal.TaskCount += ds.TaskCount
|
|
|
+ weekTotal.EstimateWorkHour += ds.EstimateWorkHour
|
|
|
+ }
|
|
|
+ weekTotal.EstimateWorkHour = math.Round(weekTotal.EstimateWorkHour*10) / 10
|
|
|
+ user.WeekTotal = weekTotal
|
|
|
+ list = append(list, user)
|
|
|
+ }
|
|
|
+
|
|
|
+ return &opsdevmodel.OpsEventTaskScheduleStatRsp{List: list}, nil
|
|
|
+}
|
|
|
+
|
|
|
|