package project import ( "context" "fmt" "time" "github.com/gogf/gf/v2/frame/g" "github.com/jinzhu/copier" "github.com/tiger1103/gfast/v3/internal/app/system/dao" "github.com/tiger1103/gfast/v3/internal/app/system/model" ) // 项目首页信息列表 func (p Project) ProjectIndex(ctx context.Context, req *ProjectIndexModuleReq) (res *ProjectListRes, err error) { res = new(ProjectListRes) // 查询所有项目总数 count, err := g.Model("sys_project").Ctx(ctx).Count() if err != nil { return nil, err } res.ProjectTotal = count // 查询所有项目的总容量之和 var capacity struct{ ProjectCapacity int } err = g.Model("sys_project").Fields("SUM(actual) AS ProjectCapacity").Ctx(ctx).Scan(&capacity) if err != nil { return nil, err } res.ProjectCapacity = capacity.ProjectCapacity // 分页查询大项目基础信息,然后遍历信息去补全其他的数据 var projects []struct { ProjectID int `json:"projectId"` ProjectName string `json:"projectName"` ProjectLeader string `json:"projectLeader"` OnStreamTime string `json:"onStreamTime"` } // 构建查询模型 query := g.Model("sys_project").Ctx(ctx). Fields("id AS ProjectID, project_name AS ProjectName, on_stream_time AS OnStreamTime, principal AS ProjectLeader") if req.ProjectName != "" { query = query.Where("project_name LIKE ?", "%"+req.ProjectName+"%") } err = query.Scan(&projects) if err != nil { return nil, err } buildProjectCount := 0 // 初始化在建项目数量计数器 for _, project := range projects { // 初始化列表模型 projectModel := ProjectListModel{ ProjectID: project.ProjectID, ProjectName: project.ProjectName, ProjectLeader: project.ProjectLeader, OnStreamTime: project.OnStreamTime, } // 首先将字符串转换为 JSON onStreamTime, err := time.Parse("2006-01-02", project.OnStreamTime) if err != nil { return nil, err } // 检查该项目的所有子项目是否均有完成时间 subProjectCount, err := g.Model("sub_project").Ctx(ctx).Where("project_id = ? AND done_time IS NOT NULL", project.ProjectID).Count() totalSubProjects, err := g.Model("sub_project").Ctx(ctx).Where("project_id = ?", project.ProjectID).Count() if err != nil { return nil, err } // 如果所有子项目的完成时间都不为空则设置为竣工 if subProjectCount == totalSubProjects && totalSubProjects != 0 { var latestDoneTimeString string // 查询子项目最后完成的任务的时间 err = g.Model("sub_project").Ctx(ctx). Fields("MAX(done_time)"). Where("project_id = ?", project.ProjectID). Scan(&latestDoneTimeString) if err != nil { return nil, err } latestDoneTime, err := time.Parse("2006-01-02", latestDoneTimeString) if err != nil { return nil, err } // 安全生产天数等于最后任务的完成时间减去项目的开始时间 projectModel.ProductionDays = int(latestDoneTime.Unix()-onStreamTime.Unix()) / 86400 projectModel.Status = "竣工" } else { // 安全生产天数等于当前的时间减去项目的开始时间 projectModel.ProductionDays = int(time.Now().Unix()-onStreamTime.Unix()) / 86400 projectModel.Status = "在建" buildProjectCount++ // 累加在建项目数量 } // 查询相关工作计划的总量与完成量 var work struct { TotalQuantity int `json:"totalQuantity"` CompletedQuantity int `json:"completedQuantity"` } err = g.Model("work_schedule").Ctx(ctx). Fields("SUM(plan_num) AS totalQuantity, SUM(finished_num) AS completedQuantity"). Where("project_id = ?", project.ProjectID). Scan(&work) if err != nil { return nil, err } projectModel.TotalQuantity = work.TotalQuantity projectModel.CompletedQuantity = work.CompletedQuantity // 添加到结果列表中 res.ProjectListModels = append(res.ProjectListModels, projectModel) } // 设置在建项目数量 res.BuildProject = buildProjectCount return res, nil } // 根据项目ID查询详情【基础数据】 func (p Project) ProjectDetail(ctx context.Context, req *ProjectIndexModuleDetailReq) (res *ProjectDetailModelRes, err error) { res = new(ProjectDetailModelRes) // 初始化查询模型,用于获取项目的基础信息 var project struct { ProjectID int `db:"ProjectID"` ProjectName string `db:"ProjectName"` ProjectLeader string `db:"ProjectLeader"` OnStreamTime string `db:"OnStreamTime"` } err = g.Model("sys_project").Ctx(ctx). Fields("id AS ProjectID, project_name AS ProjectName, principal AS ProjectLeader, on_stream_time AS OnStreamTime"). Where("id = ?", req.ProjectId). Scan(&project) if err != nil { return nil, err } // 将基本信息设置到响应结构体中 res.ProjectID = project.ProjectID res.ProjectName = project.ProjectName res.ProjectLeader = project.ProjectLeader res.OnStreamTime = project.OnStreamTime // 计算安全生产天数 onStreamDate, err := time.Parse("2006-01-02", project.OnStreamTime) if err != nil { return nil, err } res.ProductionDays = int(time.Since(onStreamDate).Hours() / 24) // 将时间差转换为天数 // 获取总数量和已完成数量 var quantities struct { TotalQuantity int `db:"TotalQuantity"` CompletedQuantity int `db:"CompletedQuantity"` } err = g.Model("work_schedule").Ctx(ctx). Fields("SUM(plan_num) AS TotalQuantity, SUM(finished_num) AS CompletedQuantity"). Where("project_id = ?", project.ProjectID). Scan(&quantities) if err != nil { return nil, err } res.TotalQuantity = quantities.TotalQuantity res.CompletedQuantity = quantities.CompletedQuantity return res, nil } // 根据项目ID查询详情【项目计划】 func (p Project) ProjectPlanDetail(ctx context.Context, req *ProjectPlanDetailReq) (res *ProjectPlanDetailRes, err error) { res = new(ProjectPlanDetailRes) // 使用结构体来接收查询结果 var planCounts struct { PendingPlan int `db:"PendingPlan"` // 待开始 ProcessingPlan int `db:"ProcessingPlan"` // 进行中 CompletedPlan int `db:"CompletedPlan"` // 已完成 DeferredPlan int `db:"DeferredPlan"` // 滞后 } // 构建查询语句以聚合不同状态的计划数量 err = g.Model("work_schedule").Ctx(ctx). Fields( "SUM(case when status = 0 then 1 else 0 end) AS PendingPlan", "SUM(case when status = 1 then 1 else 0 end) AS ProcessingPlan", "SUM(case when status = 2 then 1 else 0 end) AS CompletedPlan", "SUM(case when status = 3 then 1 else 0 end) AS DeferredPlan", ). Where("project_id = ?", req.ProjectId). Scan(&planCounts) if err != nil { return nil, err } // 将查询结果映射到响应结构体中 res.ProjectPlan = ProjectPlan{ PendingPlan: planCounts.PendingPlan, ProcessingPlan: planCounts.ProcessingPlan, CompletedPlan: planCounts.CompletedPlan, DeferredPlan: planCounts.DeferredPlan, } return res, nil } // 根据项目ID查询详情【项目计划详情】 func (p Project) ProjectPlanDetailStatus(ctx context.Context, req *ProjectPlanDetailStatusReq) (res *ProjectPlanDetailStatusRes, err error) { res = new(ProjectPlanDetailStatusRes) list := []model.SchduleDetail{} m := dao.WorkSchedule.Ctx(ctx).As("wc"). LeftJoin("work_status as ws", "wc.work_id = ws.work_id"). LeftJoin("sys_project as sp", "wc.project_id = sp.id"). Where("wc.status = ? AND wc.project_id = ?", req.Status, req.ProjectID) res.Total, err = m.Count() if err != nil { return nil, fmt.Errorf("failed to count: %w", err) } res.CurrentPage = req.PageNum // 查询工作计划详情 m = m.Fields("ws.work_name,wc.plan_num,wc.finished_num,wc.start_at,wc.end_at,sp.principal") err = m.Page(req.PageNum, req.PageSize).Scan(&list) if err != nil { return nil, fmt.Errorf("failed to fetch page: %w", err) } res.List = make([]SchduleList, 0, len(list)) copier.Copy(&res.List, &list) return res, nil } // 根据项目ID查询详情【视频监控】 func (p Project) ProjectVideoDetail(ctx context.Context, req *ProjectVideoDetailReq) (res *ProjectVideoDetailRes, err error) { res = new(ProjectVideoDetailRes) err = g.Model("ys7devices").Ctx(ctx). Fields( "id AS ID, created_at AS CreatedAt, DeviceSerial, DeviceName, DeviceType, Status, Defence, DeviceVersion, ProjectId, Detail, Position, Remark, VideoEncrypted"). Where("ProjectId = ?", req.ProjectId). Order("CreatedAt DESC"). Scan(&res.YS7Devices) if err != nil { return nil, err } return res, nil } // 根据项目ID查询详情【施工日志】 func (p Project) GetConstructionLogs(ctx context.Context, req *ProjectLogReq) (res *ProjectLogRes, err error) { res = new(ProjectLogRes) err = g.Model("bus_construction_log").Ctx(ctx). Fields( "id, date_of_occurrence, condition, technology_quality, remark, path, created_by, updated_by, created_at, updated_at, deleted_at"). Where("project_id = ? AND deleted_at IS NULL", req.ProjectId). Order("date_of_occurrence DESC"). Scan(&res.Logs) if err != nil { return nil, err } return res, nil }