| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331 |
- package opsdev
- import (
- "context"
- "fmt"
- "regexp"
- "strings"
- "dashoo.cn/common_definition/comm_def"
- "dashoo.cn/opms_libary/myerrors"
- opsdevdao "dashoo.cn/opms_parent/app/dao/opsdev"
- opsdevmodel "dashoo.cn/opms_parent/app/model/opsdev"
- "dashoo.cn/opms_parent/app/service"
- "github.com/gogf/gf/database/gdb"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/os/gtime"
- "github.com/gogf/gf/util/gconv"
- "github.com/gogf/gf/util/gvalid"
- )
- // eventTypeToDevTaskType 运维事件类型 → 研发任务类型映射
- var eventTypeToDevTaskType = map[string]string{
- "10": "20", // 操作咨询 → 功能开发
- "20": "21", // 数据处理 → 数据处理
- "30": "35", // 系统BUG → BUG
- "40": "20", // 功能调整 → 功能开发
- "50": "20", // 二开需求 → 功能开发
- "90": "20", // 其他问题 → 功能开发
- }
- type OperationService struct {
- *service.ContextService
- Dao *opsdevdao.OpsOperationEventDao
- RecordDao *opsdevdao.OpsOperationEventRecordDao
- AttachmentDao *opsdevdao.OpsOperationEventAttachmentDao
- DeliveryProjectAttachmentDao *opsdevdao.OpsDeliveryProjectEventAttachmentDao
- WorkHourDao *opsdevdao.OpsOperationWorkHourDao
- }
- func NewOperationService(ctx context.Context) (svc *OperationService, err error) {
- svc = new(OperationService)
- if svc.ContextService, err = svc.Init(ctx); err != nil {
- return nil, err
- }
- svc.Dao = opsdevdao.NewOpsOperationEventDao(svc.Tenant)
- svc.RecordDao = opsdevdao.NewOpsOperationEventRecordDao(svc.Tenant)
- svc.AttachmentDao = opsdevdao.NewOpsOperationEventAttachmentDao(svc.Tenant)
- svc.DeliveryProjectAttachmentDao = opsdevdao.NewOpsDeliveryProjectEventAttachmentDao(svc.Tenant)
- svc.WorkHourDao = opsdevdao.NewOpsOperationWorkHourDao(svc.Tenant)
- return svc, nil
- }
- // GetList 运维事件列表
- func (s *OperationService) GetList(req *opsdevmodel.OpsOperationEventSearchReq) (total int, list []*opsdevmodel.OpsOperationEvent, err error) {
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus+" != ?", opsdevmodel.EventStatusClosed)
- if req.EventNo != "" {
- db = db.Where(s.Dao.Columns.EventNo, req.EventNo)
- }
- if req.EventTitle != "" {
- db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
- }
- if req.EventStatus != "" {
- db = db.Where(s.Dao.Columns.EventStatus, req.EventStatus)
- }
- if req.EventType != "" {
- db = db.Where(s.Dao.Columns.EventType, req.EventType)
- }
- if req.PriorityLevel != "" {
- db = db.Where(s.Dao.Columns.PriorityLevel, req.PriorityLevel)
- }
- if req.IsBig != "" {
- db = db.Where(s.Dao.Columns.IsBig, req.IsBig)
- }
- if req.IsOps != "" {
- db = db.Where(s.Dao.Columns.IsOps, req.IsOps)
- }
- if req.CustName != "" {
- db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
- }
- if req.OpsUserName != "" {
- db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
- }
- if req.ContractName != "" {
- db = db.Where(s.Dao.Columns.ContractName+" like ?", "%"+req.ContractName+"%")
- }
- if req.ProductLine != "" {
- db = db.Where(s.Dao.Columns.ProductLine, req.ProductLine)
- }
- if req.BeginTime != "" {
- db = db.Where(s.Dao.Columns.CreatedTime+" >= ?", req.BeginTime)
- }
- if req.EndTime != "" {
- db = db.Where(s.Dao.Columns.CreatedTime+" <= ?", req.EndTime)
- }
- total, err = db.Count()
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询运维事件数量失败")
- }
- pageNum, pageSize := req.GetPage()
- err = db.Page(pageNum, pageSize).Order(s.Dao.Columns.CreatedTime + " desc").Scan(&list)
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询运维事件列表失败")
- }
- return total, list, nil
- }
- // GetEntityById 运维事件详情
- func (s *OperationService) GetEntityById(req *comm_def.IdReq) (detail *opsdevmodel.OpsOperationEvent, err error) {
- if req.Id <= 0 {
- return nil, myerrors.ValidError("参数有误!")
- }
- detail = new(opsdevmodel.OpsOperationEvent)
- err = s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(detail)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询运维事件详情失败")
- }
- if detail.Id <= 0 {
- return nil, myerrors.TipsError("运维事件不存在")
- }
- return detail, nil
- }
- // Create 创建运维事件
- func (s *OperationService) Create(req *opsdevmodel.OpsOperationEventReq) (err error) {
- if err = gvalid.CheckStruct(s.Ctx, req, nil); err != nil {
- return myerrors.ValidError(err.Error())
- }
- data := gconv.Map(req)
- service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
- data["eventNo"] = s.generateEventNo()
- data["eventStatus"] = opsdevmodel.EventStatusProcessing
- data["opsUserId"] = s.GetCxtUserId()
- data["opsUserName"] = s.GetCxtUserName()
- if v, ok := data["feedbackDate"]; ok && v == "" {
- data["feedbackDate"] = gtime.Now()
- }
- if v, ok := data["assignTime"]; ok && v == "" {
- data["assignTime"] = gtime.Now()
- }
- delete(data, "completeTime")
- delete(data, "attachments")
- result, err := s.Dao.Data(data).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("创建运维事件失败")
- }
- _, err = result.LastInsertId()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("获取运维事件ID失败")
- }
- return nil
- }
- // AddWorkHour 添加工时记录
- func (s *OperationService) AddWorkHour(req *opsdevmodel.OpsOperationWorkHourAddReq) error {
- if req.EventId <= 0 {
- return myerrors.ValidError("事件ID不能为空")
- }
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.EventId).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return myerrors.TipsError("运维事件不存在")
- }
- if event.EventStatus != opsdevmodel.EventStatusProcessing && event.EventStatus != opsdevmodel.EventStatusProcessingNormal {
- return myerrors.TipsError("只有处理中的事件才能添加工作时长")
- }
- workDate, err := gtime.StrToTime(req.WorkDate)
- if err != nil {
- return myerrors.ValidError("工作日期格式错误")
- }
- today := gtime.Now().Format("Y-m-d")
- if workDate.Format("Y-m-d") > today {
- return myerrors.ValidError("工作日期不能晚于今天")
- }
- if req.WorkHour < 0.5 {
- return myerrors.ValidError("工作时长不能小于0.5小时")
- }
- opsUserId := s.GetCxtUserId()
- opsUserName := s.GetCxtUserName()
- return s.Dao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
- workHourData := g.Map{
- s.WorkHourDao.Columns.EventId: req.EventId,
- s.WorkHourDao.Columns.OpsUserId: opsUserId,
- s.WorkHourDao.Columns.OpsUserName: opsUserName,
- s.WorkHourDao.Columns.WorkDate: req.WorkDate,
- s.WorkHourDao.Columns.WorkHour: req.WorkHour,
- s.WorkHourDao.Columns.Remark: req.Remark,
- }
- service.SetCreatedInfo(workHourData, opsUserId, opsUserName)
- _, err := tx.Model(s.WorkHourDao.Table).Data(workHourData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("添加工作时长失败")
- }
- _, err = tx.Exec("UPDATE ops_operation_event SET total_work_hour = total_work_hour + ? WHERE id = ?", req.WorkHour, req.EventId)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("更新事件总工作时长失败")
- }
- return nil
- })
- }
- // DeleteAttachment 删除附件
- func (s *OperationService) DeleteAttachment(req *comm_def.IdReq) error {
- if req.Id <= 0 {
- return myerrors.ValidError("参数有误!")
- }
- attachment := new(opsdevmodel.OpsOperationEventAttachment)
- err := s.AttachmentDao.WherePri(s.AttachmentDao.Columns.Id, req.Id).Scan(attachment)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询附件失败")
- }
- if attachment.Id <= 0 {
- return myerrors.TipsError("附件不存在")
- }
- _, err = s.AttachmentDao.WherePri(s.AttachmentDao.Columns.Id, req.Id).Data(g.Map{
- s.AttachmentDao.Columns.DeletedTime: gtime.Now(),
- s.AttachmentDao.Columns.UpdatedBy: s.GetCxtUserId(),
- s.AttachmentDao.Columns.UpdatedName: s.GetCxtUserName(),
- }).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("删除附件失败")
- }
- return nil
- }
- // GetHistoryList 运维历史列表
- func (s *OperationService) GetHistoryList(req *opsdevmodel.OpsOperationEventHistorySearchReq) (total int, list []*opsdevmodel.OpsOperationEvent, err error) {
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime)
- if !req.IncludeClosed {
- db = db.Where(s.Dao.Columns.EventStatus, opsdevmodel.EventStatusClosed)
- }
- if req.ScopeType == "my" {
- db = db.Where(s.Dao.Columns.OpsUserId, s.GetCxtUserId())
- }
- if req.EventTitle != "" {
- db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
- }
- if req.CustName != "" {
- db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
- }
- if req.FeedbackReporter != "" {
- db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.FeedbackReporter+"%")
- }
- if req.OpsUserName != "" {
- db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
- }
- if req.BeginTime != "" {
- db = db.Where(s.Dao.Columns.FeedbackDate+" >= ?", req.BeginTime)
- }
- if req.EndTime != "" {
- db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
- }
- total, err = db.Count()
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询运维历史数量失败")
- }
- pageNum, pageSize := req.GetPage()
- err = db.Page(pageNum, pageSize).Order(s.Dao.Columns.CompleteTime + " desc").Scan(&list)
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询运维历史列表失败")
- }
- return total, list, nil
- }
- // Export 导出运维历史
- func (s *OperationService) Export(ctx context.Context, req *opsdevmodel.OpsOperationEventHistoryExport) (content *opsdevmodel.OpsOperationEventHistoryExportContent, err error) {
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime)
- if !req.IncludeClosed {
- db = db.Where(s.Dao.Columns.EventStatus, opsdevmodel.EventStatusClosed)
- }
- if req.ScopeType == "my" {
- db = db.Where(s.Dao.Columns.OpsUserId, s.GetCxtUserId())
- }
- if req.EventTitle != "" {
- db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
- }
- if req.CustName != "" {
- db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
- }
- if req.FeedbackReporter != "" {
- db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.FeedbackReporter+"%")
- }
- if req.OpsUserName != "" {
- db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
- }
- if req.BeginTime != "" {
- db = db.Where(s.Dao.Columns.FeedbackDate+" >= ?", req.BeginTime)
- }
- if req.EndTime != "" {
- db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
- }
- var list []*opsdevmodel.OpsOperationEvent
- err = db.Order(s.Dao.Columns.CompleteTime + " desc").Scan(&list)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询运维历史失败")
- }
- // 获取所有事件ID
- var eventIds []int
- for _, item := range list {
- eventIds = append(eventIds, item.Id)
- }
- // 获取所有事件的处理记录
- var records []*opsdevmodel.OpsOperationEventRecord
- if len(eventIds) > 0 {
- err = s.RecordDao.WhereIn(s.RecordDao.Columns.EventId, eventIds).Order(s.RecordDao.Columns.HandleDate + " desc").Scan(&records)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询处理记录失败")
- }
- }
- // 构建记录Map
- recordMap := make(map[int][]*opsdevmodel.OpsOperationEventRecord)
- for _, record := range records {
- recordMap[record.EventId] = append(recordMap[record.EventId], record)
- }
- // 构建状态Map
- statusMap := map[string]string{
- opsdevmodel.EventStatusPending: "待处理",
- opsdevmodel.EventStatusProcessing: "处理中(重点)",
- opsdevmodel.EventStatusProcessingNormal: "处理中(普通)",
- opsdevmodel.EventStatusTransfer: "转研发",
- opsdevmodel.EventStatusSuspended: "挂起",
- opsdevmodel.EventStatusClosed: "已关闭",
- }
- // 构建操作类型Map
- operateTypeMap := map[string]string{
- opsdevmodel.OperateTypeProcess: "处理",
- opsdevmodel.OperateTypeResume: "转处理",
- opsdevmodel.OperateTypeTransfer: "转研发",
- opsdevmodel.OperateTypeSuspend: "挂起",
- opsdevmodel.OperateTypeClose: "关闭",
- }
- // 构建处理结果Map
- handleResultMap := map[string]string{
- opsdevmodel.HandleResultResolved: "已解决",
- opsdevmodel.HandleResultPartially: "部分解决",
- opsdevmodel.HandleResultUnresolved: "未解决",
- }
- // 构建导出数据
- exportDataList := make([]map[string]interface{}, 0)
- for _, item := range list {
- // 构建处理过程
- processBuilder := ""
- if itemRecords, ok := recordMap[item.Id]; ok && len(itemRecords) > 0 {
- for i, record := range itemRecords {
- // 处理时间(仅年月)
- handleDate := ""
- if record.HandleDate != nil {
- handleDate = record.HandleDate.Format("Y-m-d H:i:s")
- }
- // 操作类型描述
- operateTypeStr := operateTypeMap[record.OperateType]
- if operateTypeStr == "" {
- operateTypeStr = record.OperateType
- }
- // 处理结果描述
- handleResultStr := handleResultMap[record.HandleResult]
- if handleResultStr == "" {
- handleResultStr = record.HandleResult
- }
- // 清理处理内容中的HTML标签
- cleanContent := cleanHtmlTags(record.HandleContent)
- recordStr := fmt.Sprintf("%s-%s-%s-%s-%s", handleDate, record.HandleUserName, operateTypeStr, handleResultStr, cleanContent)
- if i > 0 {
- processBuilder += "\n" + recordStr
- } else {
- processBuilder = recordStr
- }
- }
- }
- closedTime := ""
- if item.CompleteTime != nil {
- closedTime = item.CompleteTime.Format("Y-m-d")
- }
- feedbackDate := ""
- if item.FeedbackDate != nil {
- feedbackDate = item.FeedbackDate.Format("Y-m-d")
- }
- exportData := map[string]interface{}{
- "eventNo": item.EventNo,
- "eventTitle": item.EventTitle,
- "eventStatus": statusMap[item.EventStatus],
- "eventType": item.EventType,
- "custName": item.CustName,
- "opsUserName": item.OpsUserName,
- "feedbackDate": feedbackDate,
- "priorityLevel": item.PriorityLevel,
- "handleProcess": processBuilder,
- "closedTime": closedTime,
- }
- exportDataList = append(exportDataList, exportData)
- }
- // 调用公共导出方法
- exportContent := new(opsdevmodel.OpsOperationEventHistoryExportContent)
- contentBase64, err := service.CommonExportExcel(ctx, "运维历史", opsdevmodel.OpsOperationEventHistoryExportData{}, exportDataList)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("导出运维历史失败")
- }
- exportContent.Content = contentBase64
- return exportContent, nil
- }
- func (s *OperationService) ExportNonClosed(ctx context.Context, req *opsdevmodel.OpsOperationEventExport) (content *opsdevmodel.OpsOperationEventHistoryExportContent, err error) {
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus+" != ?", opsdevmodel.EventStatusClosed)
- var list []*opsdevmodel.OpsOperationEvent
- err = db.Order(s.Dao.Columns.FeedbackDate + " desc").Scan(&list)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询运维事件失败")
- }
- var eventIds []int
- for _, item := range list {
- eventIds = append(eventIds, item.Id)
- }
- var records []*opsdevmodel.OpsOperationEventRecord
- if len(eventIds) > 0 {
- err = s.RecordDao.WhereIn(s.RecordDao.Columns.EventId, eventIds).Order(s.RecordDao.Columns.HandleDate + " desc").Scan(&records)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询处理记录失败")
- }
- }
- recordMap := make(map[int][]*opsdevmodel.OpsOperationEventRecord)
- for _, record := range records {
- recordMap[record.EventId] = append(recordMap[record.EventId], record)
- }
- statusMap := map[string]string{
- opsdevmodel.EventStatusPending: "待处理",
- opsdevmodel.EventStatusProcessing: "处理中(重点)",
- opsdevmodel.EventStatusProcessingNormal: "处理中(普通)",
- opsdevmodel.EventStatusTransfer: "转研发",
- opsdevmodel.EventStatusSuspended: "挂起",
- opsdevmodel.EventStatusClosed: "已关闭",
- }
- operateTypeMap := map[string]string{
- opsdevmodel.OperateTypeProcess: "处理",
- opsdevmodel.OperateTypeResume: "转处理",
- opsdevmodel.OperateTypeTransfer: "转研发",
- opsdevmodel.OperateTypeSuspend: "挂起",
- opsdevmodel.OperateTypeClose: "关闭",
- }
- handleResultMap := map[string]string{
- opsdevmodel.HandleResultResolved: "已解决",
- opsdevmodel.HandleResultPartially: "部分解决",
- opsdevmodel.HandleResultUnresolved: "未解决",
- }
- exportDataList := make([]map[string]interface{}, 0)
- for _, item := range list {
- processBuilder := ""
- if itemRecords, ok := recordMap[item.Id]; ok && len(itemRecords) > 0 {
- for i, record := range itemRecords {
- handleDate := ""
- if record.HandleDate != nil {
- handleDate = record.HandleDate.Format("Y-m-d H:i:s")
- }
- operateTypeStr := operateTypeMap[record.OperateType]
- if operateTypeStr == "" {
- operateTypeStr = record.OperateType
- }
- handleResultStr := handleResultMap[record.HandleResult]
- if handleResultStr == "" {
- handleResultStr = record.HandleResult
- }
- cleanContent := cleanHtmlTags(record.HandleContent)
- recordStr := fmt.Sprintf("%s-%s-%s-%s-%s", handleDate, record.HandleUserName, operateTypeStr, handleResultStr, cleanContent)
- if i > 0 {
- processBuilder += "\n" + recordStr
- } else {
- processBuilder = recordStr
- }
- }
- }
- feedbackDate := ""
- if item.FeedbackDate != nil {
- feedbackDate = item.FeedbackDate.Format("Y-m-d")
- }
- exportData := map[string]interface{}{
- "eventNo": item.EventNo,
- "eventTitle": item.EventTitle,
- "eventStatus": statusMap[item.EventStatus],
- "eventType": item.EventType,
- "custName": item.CustName,
- "opsUserName": item.OpsUserName,
- "feedbackDate": feedbackDate,
- "priorityLevel": item.PriorityLevel,
- "handleProcess": processBuilder,
- }
- exportDataList = append(exportDataList, exportData)
- }
- exportContent := new(opsdevmodel.OpsOperationEventHistoryExportContent)
- contentBase64, err := service.CommonExportExcel(ctx, "运维事件", opsdevmodel.OpsOperationEventExportData{}, exportDataList)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("导出运维事件失败")
- }
- exportContent.Content = contentBase64
- return exportContent, nil
- }
- func cleanHtmlTags(content string) string {
- if content == "" {
- return ""
- }
- imgPattern := regexp.MustCompile(`src=["']([^"']+)["']`)
- imgMatches := imgPattern.FindAllStringSubmatch(content, -1)
- seen := make(map[string]bool)
- var imgUrls []string
- for _, match := range imgMatches {
- if len(match) > 1 && !seen[match[1]] {
- seen[match[1]] = true
- imgUrls = append(imgUrls, match[1])
- }
- }
- htmlTagPattern := regexp.MustCompile(`<[^>]*>`)
- result := htmlTagPattern.ReplaceAllString(content, "")
- result = strings.ReplaceAll(result, " ", " ")
- result = strings.ReplaceAll(result, "&", "&")
- result = strings.ReplaceAll(result, "<", "<")
- result = strings.ReplaceAll(result, ">", ">")
- result = strings.ReplaceAll(result, """, "\"")
- result = strings.ReplaceAll(result, "'", "'")
- result = strings.TrimSpace(result)
- if len(imgUrls) > 0 {
- result += "\n图片: "
- for i, url := range imgUrls {
- if i > 0 {
- result += ", "
- }
- result += url
- }
- }
- return result
- }
- // GetWorkHourList 获取工时登记列表
- func (s *OperationService) GetWorkHourList(req *opsdevmodel.OpsOperationWorkHourListReq) ([]*opsdevmodel.OpsOperationWorkHourListRsp, error) {
- var entities []*opsdevmodel.OpsOperationWorkHour
- err := s.WorkHourDao.FieldsEx(s.WorkHourDao.Columns.DeletedTime).
- Where(s.WorkHourDao.Columns.EventId, req.EventId).
- Order(s.WorkHourDao.Columns.CreatedTime + " desc").
- Scan(&entities)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询工时登记列表失败")
- }
- list := make([]*opsdevmodel.OpsOperationWorkHourListRsp, 0, len(entities))
- for _, entity := range entities {
- workDate := ""
- if entity.WorkDate != nil {
- workDate = entity.WorkDate.Format("Y-m-d")
- }
- createdTime := ""
- if entity.CreatedTime != nil {
- createdTime = entity.CreatedTime.Format("Y-m-d H:i:s")
- }
- list = append(list, &opsdevmodel.OpsOperationWorkHourListRsp{
- Id: entity.Id,
- WorkDate: workDate,
- WorkHour: entity.WorkHour,
- Remark: entity.Remark,
- CreatedName: entity.CreatedName,
- CreatedTime: createdTime,
- })
- }
- return list, nil
- }
- // generateEventNo 生成运维事件编号
- func (s *OperationService) generateEventNo() string {
- now := gtime.Now()
- prefix := "OPS" + now.Format("Ymd")
- seqVal, err := s.Dao.DB.GetValue("SELECT next_day_reset_val('event_no_seq')")
- if err == nil {
- return prefix + fmt.Sprintf("%04d", seqVal.Int())
- }
- var maxNoResult struct {
- EventNo string
- }
- err = s.Dao.Where("event_no like ?", prefix+"%").
- Order("event_no desc").
- Fields("event_no").
- Scan(&maxNoResult)
- if err != nil || maxNoResult.EventNo == "" {
- return prefix + "0001"
- }
- maxNoStr := maxNoResult.EventNo
- if len(maxNoStr) >= len(prefix)+4 {
- seq := maxNoStr[len(prefix):]
- seqNum := gconv.Int(seq)
- seqNum++
- return prefix + fmt.Sprintf("%04d", seqNum)
- }
- return prefix + "0001"
- }
- // Process 处理运维事件(开始/转处理/转研发/挂起/关闭)
- func (s *OperationService) Process(ctx context.Context, req *opsdevmodel.OpsOperationEventProcessReq) error {
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, int(req.Id)).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return myerrors.TipsError("运维事件不存在")
- }
- opsUserId := s.GetCxtUserId()
- opsUserName := s.GetCxtUserName()
- switch req.OperateType {
- case opsdevmodel.OperateTypeClose:
- return s.processClose(req, event, opsUserId, opsUserName)
- default:
- return s.processNormal(req, event, opsUserId, opsUserName)
- }
- }
- // processClose 关单处理(含工时调整)
- func (s *OperationService) processClose(req *opsdevmodel.OpsOperationEventProcessReq, event *opsdevmodel.OpsOperationEvent, opsUserId int, opsUserName string) error {
- return s.Dao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
- handleDate := gtime.Now()
- recordData := g.Map{
- s.RecordDao.Columns.EventId: req.Id,
- s.RecordDao.Columns.HandleUserId: opsUserId,
- s.RecordDao.Columns.HandleUserName: opsUserName,
- s.RecordDao.Columns.HandleContent: req.HandleContent,
- s.RecordDao.Columns.HandleResult: req.HandleResult,
- s.RecordDao.Columns.HandleDate: handleDate,
- s.RecordDao.Columns.OperateType: req.OperateType,
- }
- service.SetCreatedInfo(recordData, opsUserId, opsUserName)
- _, err := s.RecordDao.TX(tx).Data(recordData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("创建处理记录失败")
- }
- eventUpdateData := g.Map{
- s.Dao.Columns.EventStatus: opsdevmodel.EventStatusClosed,
- s.Dao.Columns.CompleteTime: gtime.Now(),
- s.Dao.Columns.CompleteDesc: req.HandleContent,
- s.Dao.Columns.EventResult: req.HandleResult,
- }
- service.SetUpdatedInfo(eventUpdateData, opsUserId, opsUserName)
- if req.AdjustWorkHour > 0 {
- currentTotal := event.TotalWorkHour
- if req.AdjustWorkHour < currentTotal {
- return myerrors.ValidError("工时只能增加不能减少")
- }
- if req.AdjustWorkHour > currentTotal {
- delta := req.AdjustWorkHour - currentTotal
- workHourData := g.Map{
- s.WorkHourDao.Columns.EventId: int(req.Id),
- s.WorkHourDao.Columns.OpsUserId: opsUserId,
- s.WorkHourDao.Columns.OpsUserName: opsUserName,
- s.WorkHourDao.Columns.WorkDate: gtime.Now(),
- s.WorkHourDao.Columns.WorkHour: delta,
- s.WorkHourDao.Columns.Remark: "关单调整",
- }
- service.SetCreatedInfo(workHourData, opsUserId, opsUserName)
- _, err := s.WorkHourDao.TX(tx).Data(workHourData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("创建工时调整记录失败")
- }
- eventUpdateData[s.Dao.Columns.TotalWorkHour] = req.AdjustWorkHour
- }
- }
- _, err = s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).Data(eventUpdateData).WherePri(s.Dao.Columns.Id, req.Id).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("关闭事件失败")
- }
- return nil
- })
- }
- // getDevTaskType 根据运维事件类型获取对应的研发任务类型,未匹配时兜底返回功能开发(20)
- func (s *OperationService) getDevTaskType(eventType string) string {
- if taskType, ok := eventTypeToDevTaskType[eventType]; ok {
- return taskType
- }
- return opsdevmodel.TaskTypeFeatureDev
- }
- // createDevTaskFromEvent 根据运维事件自动创建研发任务(在processNormal事务完成后调用)
- func (s *OperationService) createDevTaskFromEvent(event *opsdevmodel.OpsOperationEvent) {
- var attachments []*opsdevmodel.OpsOperationEventAttachment
- err := s.AttachmentDao.FieldsEx(s.AttachmentDao.Columns.DeletedTime).
- Where(s.AttachmentDao.Columns.EventId, event.Id).
- Scan(&attachments)
- if err != nil {
- g.Log().Errorf("createDevTaskFromEvent: query attachments failed, eventId=%d, err=%v", event.Id, err)
- }
- taskAttachments := make([]opsdevmodel.Attachment, 0, len(attachments))
- for _, att := range attachments {
- taskAttachments = append(taskAttachments, opsdevmodel.Attachment{
- FileName: att.FileName,
- FileUrl: att.FileUrl,
- FileType: att.FileType,
- })
- }
- taskType := s.getDevTaskType(event.EventType)
- taskReq := &opsdevmodel.OpsEventTaskAddReq{
- ProjectId: 0,
- TaskTitle: event.EventTitle,
- TaskDesc: event.EventDesc,
- TaskType: taskType,
- Priority: event.PriorityLevel,
- EventId: event.Id,
- EventType: opsdevmodel.EventTypeOps,
- Attachments: taskAttachments,
- }
- taskSvc, err := NewOpsEventTaskService(s.Ctx)
- if err != nil {
- g.Log().Errorf("createDevTaskFromEvent: init task service failed, eventId=%d, err=%v", event.Id, err)
- return
- }
- if err := taskSvc.Create(taskReq); err != nil {
- g.Log().Errorf("createDevTaskFromEvent: create task failed, eventId=%d, eventType=%s, taskType=%s, err=%v",
- event.Id, event.EventType, taskType, err)
- }
- }
- // processNormal 非关单处理(开始/转处理/转研发/挂起)
- func (s *OperationService) processNormal(req *opsdevmodel.OpsOperationEventProcessReq, event *opsdevmodel.OpsOperationEvent, opsUserId int, opsUserName string) error {
- handleDate := gtime.Now()
- recordData := g.Map{
- s.RecordDao.Columns.EventId: req.Id,
- s.RecordDao.Columns.HandleUserId: opsUserId,
- s.RecordDao.Columns.HandleUserName: opsUserName,
- s.RecordDao.Columns.HandleContent: req.HandleContent,
- s.RecordDao.Columns.HandleResult: req.HandleResult,
- s.RecordDao.Columns.HandleDate: handleDate,
- s.RecordDao.Columns.OperateType: req.OperateType,
- }
- service.SetCreatedInfo(recordData, opsUserId, opsUserName)
- newStatus := ""
- switch req.OperateType {
- case opsdevmodel.OperateTypeProcess:
- newStatus = opsdevmodel.EventStatusProcessing
- case opsdevmodel.OperateTypeResume:
- newStatus = opsdevmodel.EventStatusProcessing
- case opsdevmodel.OperateTypeTransfer:
- newStatus = opsdevmodel.EventStatusTransfer
- case opsdevmodel.OperateTypeSuspend:
- newStatus = opsdevmodel.EventStatusSuspended
- }
- err := s.Dao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
- _, err := s.RecordDao.TX(tx).Data(recordData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("创建处理记录失败")
- }
- if newStatus != "" {
- updateData := g.Map{
- s.Dao.Columns.EventStatus: newStatus,
- }
- service.SetUpdatedInfo(updateData, opsUserId, opsUserName)
- _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).Data(updateData).WherePri(s.Dao.Columns.Id, req.Id).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("更新事件状态失败")
- }
- }
- return nil
- })
- if err != nil {
- return err
- }
- if req.OperateType == opsdevmodel.OperateTypeTransfer {
- s.createDevTaskFromEvent(event)
- }
- return nil
- }
- // UpdateById 更新运维事件
- func (s *OperationService) UpdateById(req *opsdevmodel.UpdateOpsOperationEventReq) error {
- if req.Id <= 0 {
- return myerrors.ValidError("参数有误!")
- }
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return myerrors.TipsError("运维事件不存在")
- }
- data := g.Map{}
- if req.EventTitle != "" {
- data[s.Dao.Columns.EventTitle] = req.EventTitle
- }
- if req.EventDesc != "" {
- data[s.Dao.Columns.EventDesc] = req.EventDesc
- }
- if req.EventType != "" {
- data[s.Dao.Columns.EventType] = req.EventType
- }
- if req.EventStatus != "" {
- data[s.Dao.Columns.EventStatus] = req.EventStatus
- }
- if req.ContractId > 0 {
- data[s.Dao.Columns.ContractId] = req.ContractId
- }
- if req.ContractName != "" {
- data[s.Dao.Columns.ContractName] = req.ContractName
- }
- if req.CustId > 0 {
- data[s.Dao.Columns.CustId] = req.CustId
- }
- if req.CustName != "" {
- data[s.Dao.Columns.CustName] = req.CustName
- }
- if req.ProductLine != "" {
- data[s.Dao.Columns.ProductLine] = req.ProductLine
- }
- if req.IsBig != "" {
- data[s.Dao.Columns.IsBig] = req.IsBig
- }
- if req.IsOps != "" {
- data[s.Dao.Columns.IsOps] = req.IsOps
- }
- if req.PriorityLevel != "" {
- data[s.Dao.Columns.PriorityLevel] = req.PriorityLevel
- }
- if req.FeedbackSource != "" {
- data[s.Dao.Columns.FeedbackSource] = req.FeedbackSource
- }
- if req.FeedbackReporter != "" {
- data[s.Dao.Columns.FeedbackReporter] = req.FeedbackReporter
- }
- if req.FeedbackDate != "" {
- data[s.Dao.Columns.FeedbackDate] = req.FeedbackDate
- }
- if req.OpsUserId > 0 {
- data[s.Dao.Columns.OpsUserId] = req.OpsUserId
- }
- if req.OpsUserName != "" {
- data[s.Dao.Columns.OpsUserName] = req.OpsUserName
- }
- if req.Remark != "" {
- data[s.Dao.Columns.Remark] = req.Remark
- }
- service.SetUpdatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
- _, err = s.Dao.FieldsEx(service.UpdateFieldEx...).Data(data).WherePri(s.Dao.Columns.Id, req.Id).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("更新运维事件失败")
- }
- return nil
- }
- // DeleteByIds 根据ID批量删除运维事件(软删除)
- func (s *OperationService) DeleteByIds(req *comm_def.IdsReq) error {
- if len(req.Ids) == 0 {
- return myerrors.ValidError("参数有误!")
- }
- ids := make([]int, 0, len(req.Ids))
- for _, id := range req.Ids {
- ids = append(ids, int(id))
- }
- return s.Dao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
- // 1. 软删除事件
- _, err := s.Dao.TX(tx).Data(g.Map{
- s.Dao.Columns.DeletedTime: gtime.Now(),
- }).WhereIn(s.Dao.Columns.Id, ids).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("删除运维事件失败")
- }
- // 2. 软删除关联的处理记录
- _, err = s.RecordDao.TX(tx).Data(g.Map{
- s.RecordDao.Columns.DeletedTime: gtime.Now(),
- }).WhereIn(s.RecordDao.Columns.EventId, ids).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("删除处理记录失败")
- }
- // 3. 软删除关联的附件
- _, err = s.AttachmentDao.TX(tx).Data(g.Map{
- s.AttachmentDao.Columns.DeletedTime: gtime.Now(),
- }).WhereIn(s.AttachmentDao.Columns.EventId, ids).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("删除附件失败")
- }
- return nil
- })
- }
- // GetRecords 获取事件处理记录列表(分页,含附件)
- func (s *OperationService) GetRecords(req *opsdevmodel.OpsOperationEventRecordSearchReq) (total int, list []*opsdevmodel.OpsOperationEventRecordWithAttachments, err error) {
- if req.EventId <= 0 {
- return 0, nil, myerrors.ValidError("事件ID不能为空")
- }
- db := s.RecordDao.FieldsEx(s.RecordDao.Columns.DeletedTime).Where(s.RecordDao.Columns.EventId, req.EventId)
- total, err = db.Count()
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询处理记录数量失败")
- }
- pageNum, pageSize := req.GetPage()
- var records []*opsdevmodel.OpsOperationEventRecord
- err = db.Page(pageNum, pageSize).Order(s.RecordDao.Columns.CreatedTime + " desc").Scan(&records)
- if err != nil {
- g.Log().Error(err)
- return 0, nil, myerrors.DbError("查询处理记录列表失败")
- }
- result := make([]*opsdevmodel.OpsOperationEventRecordWithAttachments, 0, len(records))
- for _, record := range records {
- recordRsp := &opsdevmodel.OpsOperationEventRecordWithAttachments{
- OpsOperationEventRecord: *record,
- Attachments: []*opsdevmodel.OpsOperationEventAttachment{},
- }
- if record.Id > 0 {
- var attachments []*opsdevmodel.OpsOperationEventAttachment
- err := s.AttachmentDao.FieldsEx(s.AttachmentDao.Columns.DeletedTime).
- Where(s.AttachmentDao.Columns.EventRecordId, record.Id).
- Scan(&attachments)
- if err != nil {
- g.Log().Error(err)
- } else {
- recordRsp.Attachments = attachments
- }
- }
- result = append(result, recordRsp)
- }
- return total, result, nil
- }
- // UploadAttachment 上传附件
- func (s *OperationService) UploadAttachment(req *opsdevmodel.OpsOperationEventAttachmentReq) (*opsdevmodel.OpsOperationEventAttachment, error) {
- if req.EventId <= 0 {
- return nil, myerrors.ValidError("事件ID不能为空")
- }
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.EventId).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return nil, myerrors.TipsError("运维事件不存在")
- }
- data := g.Map{
- s.AttachmentDao.Columns.EventId: req.EventId,
- s.AttachmentDao.Columns.EventRecordId: req.EventRecordId,
- s.AttachmentDao.Columns.FileName: req.FileName,
- s.AttachmentDao.Columns.FileUrl: req.FileUrl,
- s.AttachmentDao.Columns.FileType: req.FileType,
- s.AttachmentDao.Columns.Remark: req.Remark,
- }
- service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
- result, err := s.AttachmentDao.Data(data).Insert()
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("上传附件失败")
- }
- id, err := result.LastInsertId()
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("获取附件ID失败")
- }
- attachment := new(opsdevmodel.OpsOperationEventAttachment)
- err = s.AttachmentDao.WherePri(s.AttachmentDao.Columns.Id, id).Scan(attachment)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询附件失败")
- }
- return attachment, nil
- }
- // GetAttachments 根据事件ID获取附件列表
- func (s *OperationService) GetAttachments(eventId int) ([]*opsdevmodel.OpsOperationEventAttachment, error) {
- if eventId <= 0 {
- return nil, myerrors.ValidError("事件ID不能为空")
- }
- var attachments []*opsdevmodel.OpsOperationEventAttachment
- err := s.AttachmentDao.FieldsEx(s.AttachmentDao.Columns.DeletedTime).
- Where(s.AttachmentDao.Columns.EventId, eventId).
- Order(s.AttachmentDao.Columns.CreatedTime + " desc").
- Scan(&attachments)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询附件列表失败")
- }
- return attachments, nil
- }
- // GetStats 获取运维事件统计数据
- func (s *OperationService) GetStats() (g.Map, error) {
- stats := g.Map{}
- // 按状态统计
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime)
- statusList, err := db.GroupBy(s.Dao.Columns.EventStatus).Fields(s.Dao.Columns.EventStatus+", count(*) as count").All()
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("统计事件状态失败")
- }
- statusCount := g.Map{}
- for _, row := range statusList {
- statusCount[gconv.String(row["event_status"])] = row["count"]
- }
- stats["statusCount"] = statusCount
- // 按优先级统计
- priorityList, err := db.GroupBy(s.Dao.Columns.PriorityLevel).Fields(s.Dao.Columns.PriorityLevel+", count(*) as count").All()
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("统计事件优先级失败")
- }
- priorityCount := g.Map{}
- for _, row := range priorityList {
- priorityCount[gconv.String(row["priority_level"])] = row["count"]
- }
- stats["priorityCount"] = priorityCount
- // 按类型统计
- typeList, err := db.GroupBy(s.Dao.Columns.EventType).Fields(s.Dao.Columns.EventType+", count(*) as count").All()
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("统计事件类型失败")
- }
- typeCount := g.Map{}
- for _, row := range typeList {
- typeCount[gconv.String(row["event_type"])] = row["count"]
- }
- stats["typeCount"] = typeCount
- return stats, nil
- }
- // GetKanbanData 获取看板数据
- func (s *OperationService) GetKanbanData(req *opsdevmodel.OpsOperationEventKanbanSearchReq) (g.Map, error) {
- // 查询所有非关闭状态的事件
- db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus+" != ?", opsdevmodel.EventStatusClosed)
- if req.KeyWords != "" {
- switch req.SearchType {
- case "eventNo":
- db = db.Where(s.Dao.Columns.EventNo, req.KeyWords)
- case "title":
- db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.KeyWords+"%")
- case "custName":
- db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.KeyWords+"%")
- case "feedbackReporter":
- db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.KeyWords+"%")
- default:
- db = db.Where(fmt.Sprintf("(%s like ? or %s like ? or %s like ? or %s = ?)",
- s.Dao.Columns.EventTitle, s.Dao.Columns.CustName, s.Dao.Columns.FeedbackReporter, s.Dao.Columns.EventNo),
- "%"+req.KeyWords+"%", "%"+req.KeyWords+"%", "%"+req.KeyWords+"%", req.KeyWords)
- }
- }
- if req.EventType != "" {
- db = db.Where(s.Dao.Columns.EventType, req.EventType)
- }
- if req.PriorityLevel != "" {
- db = db.Where(s.Dao.Columns.PriorityLevel, req.PriorityLevel)
- }
- // 待处理可查看全部,处理中/转研发/挂起仅查看当前登录人的
- userId := s.GetCxtUserId()
- if userId > 0 {
- db = db.Where(fmt.Sprintf("(%s = ? OR %s = ?)", s.Dao.Columns.EventStatus, s.Dao.Columns.OpsUserId), opsdevmodel.EventStatusPending, userId)
- }
- // 排序
- switch req.SortBy {
- case "feedbackDateAsc":
- db = db.Order(s.Dao.Columns.FeedbackDate + " asc")
- case "custName":
- db = db.Order(s.Dao.Columns.CustName + " asc")
- default:
- db = db.Order(s.Dao.Columns.FeedbackDate + " desc")
- }
- var list []*opsdevmodel.OpsOperationEvent
- err := db.Scan(&list)
- if err != nil {
- g.Log().Error(err)
- return nil, myerrors.DbError("查询看板数据失败")
- }
- // 按状态分组(处理中合并 20 + 30)
- groups := map[string][]*opsdevmodel.OpsOperationEvent{
- opsdevmodel.EventStatusPending: make([]*opsdevmodel.OpsOperationEvent, 0), // 待处理
- opsdevmodel.EventStatusProcessing: make([]*opsdevmodel.OpsOperationEvent, 0), // 处理中
- opsdevmodel.EventStatusTransfer: make([]*opsdevmodel.OpsOperationEvent, 0), // 转研发
- opsdevmodel.EventStatusSuspended: make([]*opsdevmodel.OpsOperationEvent, 0), // 挂起
- }
- for _, item := range list {
- key := item.EventStatus
- if key == opsdevmodel.EventStatusProcessingNormal {
- key = opsdevmodel.EventStatusProcessing
- }
- groups[key] = append(groups[key], item)
- }
- kanbanData := g.Map{}
- for key, items := range groups {
- kanbanData[key] = g.Map{
- "list": items,
- "count": len(items),
- }
- }
- return kanbanData, nil
- }
- // AssignOpsUser 分配运维人员
- func (s *OperationService) AssignOpsUser(req *opsdevmodel.AssignOpsUserReq) error {
- if req.Id <= 0 {
- return myerrors.ValidError("事件ID不能为空")
- }
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return myerrors.TipsError("运维事件不存在")
- }
- data := g.Map{
- s.Dao.Columns.OpsUserId: req.OpsUserId,
- s.Dao.Columns.OpsUserName: req.OpsUserName,
- s.Dao.Columns.AssignTime: gtime.Now(),
- }
- service.SetUpdatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
- _, err = s.Dao.FieldsEx(service.UpdateFieldEx...).Data(data).WherePri(s.Dao.Columns.Id, req.Id).Update()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("分配运维人员失败")
- }
- return nil
- }
- // AddRecord 添加处理记录(含附件,事务控制)
- func (s *OperationService) AddRecord(req *opsdevmodel.AddRecordReq) error {
- if req.EventId <= 0 {
- return myerrors.ValidError("事件ID不能为空")
- }
- event := new(opsdevmodel.OpsOperationEvent)
- err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.EventId).Scan(event)
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("查询运维事件失败")
- }
- if event.Id <= 0 {
- return myerrors.TipsError("运维事件不存在")
- }
- opsUserId := s.GetCxtUserId()
- opsUserName := s.GetCxtUserName()
- recordData := g.Map{
- s.RecordDao.Columns.EventId: req.EventId,
- s.RecordDao.Columns.HandleUserId: opsUserId,
- s.RecordDao.Columns.HandleUserName: opsUserName,
- s.RecordDao.Columns.HandleContent: req.HandleContent,
- s.RecordDao.Columns.HandleResult: req.HandleResult,
- s.RecordDao.Columns.HandleDate: gtime.Now(),
- }
- service.SetCreatedInfo(recordData, opsUserId, opsUserName)
- return s.RecordDao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
- result, err := s.RecordDao.TX(tx).Data(recordData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("添加处理记录失败")
- }
- recordId, err := result.LastInsertId()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("获取记录ID失败")
- }
- // 如果有附件,一并保存
- for _, att := range req.Attachments {
- attData := g.Map{
- s.AttachmentDao.Columns.EventId: req.EventId,
- s.AttachmentDao.Columns.EventRecordId: recordId,
- s.AttachmentDao.Columns.FileName: att.FileName,
- s.AttachmentDao.Columns.FileUrl: att.FileUrl,
- s.AttachmentDao.Columns.FileType: att.FileType,
- }
- service.SetCreatedInfo(attData, opsUserId, opsUserName)
- _, err := s.AttachmentDao.TX(tx).Data(attData).Insert()
- if err != nil {
- g.Log().Error(err)
- return myerrors.DbError("保存附件失败")
- }
- }
- return nil
- })
- }
|