operation.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. package opsdev
  2. import (
  3. "context"
  4. "fmt"
  5. "regexp"
  6. "strings"
  7. "dashoo.cn/common_definition/comm_def"
  8. "dashoo.cn/opms_libary/myerrors"
  9. opsdevdao "dashoo.cn/opms_parent/app/dao/opsdev"
  10. opsdevmodel "dashoo.cn/opms_parent/app/model/opsdev"
  11. "dashoo.cn/opms_parent/app/service"
  12. "github.com/gogf/gf/database/gdb"
  13. "github.com/gogf/gf/frame/g"
  14. "github.com/gogf/gf/os/gtime"
  15. "github.com/gogf/gf/util/gconv"
  16. "github.com/gogf/gf/util/gvalid"
  17. )
  18. type OperationService struct {
  19. *service.ContextService
  20. Dao *opsdevdao.OpsOperationEventDao
  21. RecordDao *opsdevdao.OpsOperationEventRecordDao
  22. AttachmentDao *opsdevdao.OpsOperationEventAttachmentDao
  23. }
  24. func NewOperationService(ctx context.Context) (svc *OperationService, err error) {
  25. svc = new(OperationService)
  26. if svc.ContextService, err = svc.Init(ctx); err != nil {
  27. return nil, err
  28. }
  29. svc.Dao = opsdevdao.NewOpsOperationEventDao(svc.Tenant)
  30. svc.RecordDao = opsdevdao.NewOpsOperationEventRecordDao(svc.Tenant)
  31. svc.AttachmentDao = opsdevdao.NewOpsOperationEventAttachmentDao(svc.Tenant)
  32. return svc, nil
  33. }
  34. // GetList 运维事件列表
  35. func (s *OperationService) GetList(req *opsdevmodel.OpsOperationEventSearchReq) (total int, list []*opsdevmodel.OpsOperationEvent, err error) {
  36. db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus+" != ?", opsdevmodel.EventStatusClosed)
  37. if req.EventNo != "" {
  38. db = db.Where(s.Dao.Columns.EventNo, req.EventNo)
  39. }
  40. if req.EventTitle != "" {
  41. db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
  42. }
  43. if req.EventStatus != "" {
  44. db = db.Where(s.Dao.Columns.EventStatus, req.EventStatus)
  45. }
  46. if req.EventType != "" {
  47. db = db.Where(s.Dao.Columns.EventType, req.EventType)
  48. }
  49. if req.PriorityLevel != "" {
  50. db = db.Where(s.Dao.Columns.PriorityLevel, req.PriorityLevel)
  51. }
  52. if req.IsBig != "" {
  53. db = db.Where(s.Dao.Columns.IsBig, req.IsBig)
  54. }
  55. if req.IsOps != "" {
  56. db = db.Where(s.Dao.Columns.IsOps, req.IsOps)
  57. }
  58. if req.CustName != "" {
  59. db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
  60. }
  61. if req.OpsUserName != "" {
  62. db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
  63. }
  64. if req.ContractName != "" {
  65. db = db.Where(s.Dao.Columns.ContractName+" like ?", "%"+req.ContractName+"%")
  66. }
  67. if req.ProductLine != "" {
  68. db = db.Where(s.Dao.Columns.ProductLine, req.ProductLine)
  69. }
  70. if req.BeginTime != "" {
  71. db = db.Where(s.Dao.Columns.CreatedTime+" >= ?", req.BeginTime)
  72. }
  73. if req.EndTime != "" {
  74. db = db.Where(s.Dao.Columns.CreatedTime+" <= ?", req.EndTime)
  75. }
  76. total, err = db.Count()
  77. if err != nil {
  78. g.Log().Error(err)
  79. return 0, nil, myerrors.DbError("查询运维事件数量失败")
  80. }
  81. pageNum, pageSize := req.GetPage()
  82. err = db.Page(pageNum, pageSize).Order(s.Dao.Columns.CreatedTime + " desc").Scan(&list)
  83. if err != nil {
  84. g.Log().Error(err)
  85. return 0, nil, myerrors.DbError("查询运维事件列表失败")
  86. }
  87. return total, list, nil
  88. }
  89. // GetEntityById 运维事件详情
  90. func (s *OperationService) GetEntityById(req *comm_def.IdReq) (detail *opsdevmodel.OpsOperationEvent, err error) {
  91. if req.Id <= 0 {
  92. return nil, myerrors.ValidError("参数有误!")
  93. }
  94. detail = new(opsdevmodel.OpsOperationEvent)
  95. err = s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(detail)
  96. if err != nil {
  97. g.Log().Error(err)
  98. return nil, myerrors.DbError("查询运维事件详情失败")
  99. }
  100. if detail.Id <= 0 {
  101. return nil, myerrors.TipsError("运维事件不存在")
  102. }
  103. return detail, nil
  104. }
  105. // Create 创建运维事件
  106. func (s *OperationService) Create(req *opsdevmodel.OpsOperationEventReq) (err error) {
  107. if err = gvalid.CheckStruct(s.Ctx, req, nil); err != nil {
  108. return myerrors.ValidError(err.Error())
  109. }
  110. data := gconv.Map(req)
  111. service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  112. data["eventNo"] = generateEventNo()
  113. data["eventStatus"] = opsdevmodel.EventStatusProcessing
  114. data["opsUserId"] = s.GetCxtUserId()
  115. data["opsUserName"] = s.GetCxtUserName()
  116. if v, ok := data["feedbackDate"]; ok && v == "" {
  117. data["feedbackDate"] = gtime.Now()
  118. }
  119. if v, ok := data["assignTime"]; ok && v == "" {
  120. data["assignTime"] = gtime.Now()
  121. }
  122. delete(data, "completeTime")
  123. result, err := s.Dao.Data(data).Insert()
  124. if err != nil {
  125. g.Log().Error(err)
  126. return myerrors.DbError("创建运维事件失败")
  127. }
  128. id, err := result.LastInsertId()
  129. if err != nil {
  130. g.Log().Error(err)
  131. return nil
  132. }
  133. recordData := g.Map{
  134. s.RecordDao.Columns.EventId: id,
  135. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  136. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  137. s.RecordDao.Columns.HandleContent: "创建运维事件",
  138. s.RecordDao.Columns.HandleResult: opsdevmodel.HandleResultUnresolved,
  139. s.RecordDao.Columns.HandleDate: gtime.Now(),
  140. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeProcess,
  141. }
  142. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  143. _, err = s.RecordDao.Data(recordData).Insert()
  144. if err != nil {
  145. g.Log().Error(err)
  146. }
  147. return nil
  148. }
  149. // UpdateById 更新运维事件
  150. func (s *OperationService) UpdateById(req *opsdevmodel.UpdateOpsOperationEventReq) (err error) {
  151. if err = gvalid.CheckStruct(s.Ctx, req, nil); err != nil {
  152. return myerrors.ValidError(err.Error())
  153. }
  154. event := new(opsdevmodel.OpsOperationEvent)
  155. err = s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(event)
  156. if err != nil {
  157. g.Log().Error(err)
  158. return myerrors.DbError("查询运维事件失败")
  159. }
  160. if event.Id <= 0 {
  161. return myerrors.TipsError("运维事件不存在")
  162. }
  163. if err = s.checkNotClosed(event); err != nil {
  164. return err
  165. }
  166. data := gconv.Map(req.OpsOperationEventReq)
  167. if v, ok := data["feedbackDate"]; ok && v == "" {
  168. delete(data, "feedbackDate")
  169. }
  170. delete(data, "assignTime")
  171. delete(data, "completeTime")
  172. service.SetUpdatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  173. _, err = s.Dao.FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, req.Id).Data(data).Update()
  174. if err != nil {
  175. g.Log().Error(err)
  176. return myerrors.DbError("更新运维事件失败")
  177. }
  178. return nil
  179. }
  180. // DeleteByIds 批量删除运维事件
  181. func (s *OperationService) DeleteByIds(req *comm_def.IdsReq) (err error) {
  182. if len(req.Ids) == 0 {
  183. return myerrors.ValidError("参数有误!")
  184. }
  185. _, err = s.Dao.WherePri(req.Ids).Data(g.Map{
  186. s.Dao.Columns.DeletedTime: gtime.Now(),
  187. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  188. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  189. }).Update()
  190. if err != nil {
  191. g.Log().Error(err)
  192. return myerrors.DbError("删除运维事件失败")
  193. }
  194. return nil
  195. }
  196. // checkNotClosed 校验事件未关闭,已关闭的事件不允许操作
  197. func (s *OperationService) checkNotClosed(event *opsdevmodel.OpsOperationEvent) error {
  198. if event.EventStatus == opsdevmodel.EventStatusClosed {
  199. return myerrors.TipsError("该事件已关闭,无法进行操作")
  200. }
  201. return nil
  202. }
  203. // Process 处理运维事件
  204. func (s *OperationService) Process(ctx context.Context, req *opsdevmodel.OpsOperationEventProcessReq) error {
  205. if req.Id <= 0 {
  206. return myerrors.TipsError("任务ID不能为空")
  207. }
  208. event := new(opsdevmodel.OpsOperationEvent)
  209. err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(event)
  210. if err != nil {
  211. g.Log().Error(err)
  212. return myerrors.DbError("查询运维事件失败")
  213. }
  214. if event.Id <= 0 {
  215. return myerrors.TipsError("运维事件不存在")
  216. }
  217. if err := s.checkNotClosed(event); err != nil {
  218. return err
  219. }
  220. switch req.OperateType {
  221. case opsdevmodel.OperateTypeProcess:
  222. return s.processStart(ctx, event, req)
  223. case opsdevmodel.OperateTypeResume:
  224. return s.processResume(ctx, event, req)
  225. case opsdevmodel.OperateTypeTransfer:
  226. return s.processTransfer(ctx, event, req)
  227. case opsdevmodel.OperateTypeSuspend:
  228. return s.processSuspend(ctx, event, req)
  229. case opsdevmodel.OperateTypeClose:
  230. return s.processClose(ctx, event, req)
  231. default:
  232. return myerrors.TipsError("未知的操作类型")
  233. }
  234. }
  235. func (s *OperationService) processStart(ctx context.Context, event *opsdevmodel.OpsOperationEvent, req *opsdevmodel.OpsOperationEventProcessReq) error {
  236. if event.EventStatus != opsdevmodel.EventStatusPending {
  237. return myerrors.TipsError("当前事件状态不能进行此操作")
  238. }
  239. return s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  240. _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, event.Id).Data(g.Map{
  241. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusProcessing,
  242. s.Dao.Columns.OpsUserId: s.GetCxtUserId(),
  243. s.Dao.Columns.OpsUserName: s.GetCxtUserName(),
  244. s.Dao.Columns.AssignTime: gtime.Now(),
  245. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  246. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  247. s.Dao.Columns.UpdatedTime: gtime.Now(),
  248. }).Update()
  249. if err != nil {
  250. return err
  251. }
  252. recordData := g.Map{
  253. s.RecordDao.Columns.EventId: event.Id,
  254. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  255. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  256. s.RecordDao.Columns.HandleContent: req.HandleContent,
  257. s.RecordDao.Columns.HandleResult: opsdevmodel.HandleResultUnresolved,
  258. s.RecordDao.Columns.HandleDate: gtime.Now(),
  259. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeProcess,
  260. }
  261. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  262. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  263. if err != nil {
  264. return err
  265. }
  266. return nil
  267. })
  268. }
  269. func (s *OperationService) processClose(ctx context.Context, event *opsdevmodel.OpsOperationEvent, req *opsdevmodel.OpsOperationEventProcessReq) error {
  270. if event.EventStatus == opsdevmodel.EventStatusPending {
  271. return myerrors.TipsError("待处理状态不能直接关闭,请先接收")
  272. }
  273. if event.EventStatus == opsdevmodel.EventStatusSuspended {
  274. return myerrors.TipsError("挂起状态不允许关闭事件,请先转处理")
  275. }
  276. return s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  277. _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, event.Id).Data(g.Map{
  278. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusClosed,
  279. s.Dao.Columns.CompleteTime: gtime.Now(),
  280. s.Dao.Columns.CompleteDesc: req.HandleContent,
  281. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  282. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  283. s.Dao.Columns.UpdatedTime: gtime.Now(),
  284. }).Update()
  285. if err != nil {
  286. return err
  287. }
  288. recordData := g.Map{
  289. s.RecordDao.Columns.EventId: event.Id,
  290. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  291. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  292. s.RecordDao.Columns.HandleContent: req.HandleContent,
  293. s.RecordDao.Columns.HandleResult: req.HandleResult,
  294. s.RecordDao.Columns.HandleDate: gtime.Now(),
  295. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeClose,
  296. }
  297. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  298. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  299. if err != nil {
  300. return err
  301. }
  302. return nil
  303. })
  304. }
  305. func (s *OperationService) processTransfer(ctx context.Context, event *opsdevmodel.OpsOperationEvent, req *opsdevmodel.OpsOperationEventProcessReq) error {
  306. if event.EventStatus != opsdevmodel.EventStatusProcessing && event.EventStatus != opsdevmodel.EventStatusProcessingNormal {
  307. return myerrors.TipsError("当前事件状态不能转研发")
  308. }
  309. return s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  310. _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, event.Id).Data(g.Map{
  311. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusTransfer,
  312. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  313. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  314. s.Dao.Columns.UpdatedTime: gtime.Now(),
  315. }).Update()
  316. if err != nil {
  317. return err
  318. }
  319. recordData := g.Map{
  320. s.RecordDao.Columns.EventId: event.Id,
  321. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  322. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  323. s.RecordDao.Columns.HandleContent: req.HandleContent,
  324. s.RecordDao.Columns.HandleResult: opsdevmodel.HandleResultUnresolved,
  325. s.RecordDao.Columns.HandleDate: gtime.Now(),
  326. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeTransfer,
  327. }
  328. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  329. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  330. if err != nil {
  331. return err
  332. }
  333. return nil
  334. })
  335. }
  336. func (s *OperationService) processSuspend(ctx context.Context, event *opsdevmodel.OpsOperationEvent, req *opsdevmodel.OpsOperationEventProcessReq) error {
  337. if event.EventStatus != opsdevmodel.EventStatusProcessing && event.EventStatus != opsdevmodel.EventStatusProcessingNormal && event.EventStatus != opsdevmodel.EventStatusTransfer {
  338. return myerrors.TipsError("当前事件状态不能挂起")
  339. }
  340. return s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  341. _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, event.Id).Data(g.Map{
  342. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusSuspended,
  343. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  344. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  345. s.Dao.Columns.UpdatedTime: gtime.Now(),
  346. }).Update()
  347. if err != nil {
  348. return err
  349. }
  350. recordData := g.Map{
  351. s.RecordDao.Columns.EventId: event.Id,
  352. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  353. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  354. s.RecordDao.Columns.HandleContent: req.HandleContent,
  355. s.RecordDao.Columns.HandleResult: opsdevmodel.HandleResultUnresolved,
  356. s.RecordDao.Columns.HandleDate: gtime.Now(),
  357. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeSuspend,
  358. }
  359. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  360. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  361. if err != nil {
  362. return err
  363. }
  364. return nil
  365. })
  366. }
  367. func (s *OperationService) processResume(ctx context.Context, event *opsdevmodel.OpsOperationEvent, req *opsdevmodel.OpsOperationEventProcessReq) error {
  368. if event.EventStatus != opsdevmodel.EventStatusSuspended {
  369. return myerrors.TipsError("当前事件状态不能转处理")
  370. }
  371. return s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  372. _, err := s.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, event.Id).Data(g.Map{
  373. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusProcessing,
  374. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  375. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  376. s.Dao.Columns.UpdatedTime: gtime.Now(),
  377. }).Update()
  378. if err != nil {
  379. return err
  380. }
  381. recordData := g.Map{
  382. s.RecordDao.Columns.EventId: event.Id,
  383. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  384. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  385. s.RecordDao.Columns.HandleContent: req.HandleContent,
  386. s.RecordDao.Columns.HandleResult: opsdevmodel.HandleResultUnresolved,
  387. s.RecordDao.Columns.HandleDate: gtime.Now(),
  388. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeResume,
  389. }
  390. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  391. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  392. if err != nil {
  393. return err
  394. }
  395. return nil
  396. })
  397. }
  398. // GetRecords 获取运维事件处理记录
  399. func (s *OperationService) GetRecords(req *opsdevmodel.OpsOperationEventRecordSearchReq) (total int, list []*opsdevmodel.OpsOperationEventRecord, err error) {
  400. if req.EventId <= 0 {
  401. return 0, nil, myerrors.ValidError("事件ID不能为空")
  402. }
  403. db := s.RecordDao.FieldsEx(s.RecordDao.Columns.DeletedTime).Where(s.RecordDao.Columns.EventId, req.EventId)
  404. total, err = db.Count()
  405. if err != nil {
  406. g.Log().Error(err)
  407. return 0, nil, myerrors.DbError("查询处理记录数量失败")
  408. }
  409. pageNum, pageSize := req.GetPage()
  410. err = db.Page(pageNum, pageSize).Order(s.RecordDao.Columns.CreatedTime + " desc").Scan(&list)
  411. if err != nil {
  412. g.Log().Error(err)
  413. return 0, nil, myerrors.DbError("查询处理记录列表失败")
  414. }
  415. return total, list, nil
  416. }
  417. // UploadAttachment 上传附件
  418. func (s *OperationService) UploadAttachment(req *opsdevmodel.OpsOperationEventAttachmentReq) (attachment *opsdevmodel.OpsOperationEventAttachment, err error) {
  419. if req.EventId <= 0 {
  420. return nil, myerrors.ValidError("事件ID不能为空")
  421. }
  422. if req.FileName == "" {
  423. return nil, myerrors.ValidError("文件名不能为空")
  424. }
  425. if req.FileUrl == "" {
  426. return nil, myerrors.ValidError("文件地址不能为空")
  427. }
  428. event := new(opsdevmodel.OpsOperationEvent)
  429. err = s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.EventId).Scan(event)
  430. if err != nil {
  431. g.Log().Error(err)
  432. return nil, myerrors.DbError("查询运维事件失败")
  433. }
  434. if err := s.checkNotClosed(event); err != nil {
  435. return nil, err
  436. }
  437. data := g.Map{
  438. s.AttachmentDao.Columns.EventId: req.EventId,
  439. s.AttachmentDao.Columns.EventRecordId: req.EventRecordId,
  440. s.AttachmentDao.Columns.FileName: req.FileName,
  441. s.AttachmentDao.Columns.FileUrl: req.FileUrl,
  442. s.AttachmentDao.Columns.FileType: req.FileType,
  443. s.AttachmentDao.Columns.Remark: req.Remark,
  444. }
  445. service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  446. _, err = s.AttachmentDao.Data(data).Insert()
  447. if err != nil {
  448. g.Log().Error(err)
  449. return nil, myerrors.DbError("上传附件失败")
  450. }
  451. // 查询刚插入的记录
  452. attachment = new(opsdevmodel.OpsOperationEventAttachment)
  453. err = s.AttachmentDao.Where(s.AttachmentDao.Columns.EventId, req.EventId).
  454. Order(s.AttachmentDao.Columns.Id + " desc").Scan(attachment)
  455. if err != nil {
  456. g.Log().Error(err)
  457. return nil, myerrors.DbError("查询附件失败")
  458. }
  459. return attachment, nil
  460. }
  461. // GetAttachments 获取事件附件列表
  462. func (s *OperationService) GetAttachments(eventId int) (list []*opsdevmodel.OpsOperationEventAttachment, err error) {
  463. if eventId <= 0 {
  464. return nil, myerrors.ValidError("事件ID不能为空")
  465. }
  466. err = s.AttachmentDao.FieldsEx(s.AttachmentDao.Columns.DeletedTime).
  467. Where(s.AttachmentDao.Columns.EventId, eventId).
  468. Order(s.AttachmentDao.Columns.CreatedTime + " desc").Scan(&list)
  469. if err != nil {
  470. g.Log().Error(err)
  471. return nil, myerrors.DbError("查询附件列表失败")
  472. }
  473. return list, nil
  474. }
  475. // GetStats 运维事件统计
  476. func (s *OperationService) GetStats() (result g.Map, err error) {
  477. result = g.Map{}
  478. statusCounts := []struct {
  479. key string
  480. status string
  481. }{
  482. {"pending", opsdevmodel.EventStatusPending},
  483. {"processingKey", opsdevmodel.EventStatusProcessing},
  484. {"processingNormal", opsdevmodel.EventStatusProcessingNormal},
  485. {"transfer", opsdevmodel.EventStatusTransfer},
  486. {"suspended", opsdevmodel.EventStatusSuspended},
  487. {"closed", opsdevmodel.EventStatusClosed},
  488. }
  489. for _, sc := range statusCounts {
  490. count, err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus, sc.status).Count()
  491. if err != nil {
  492. g.Log().Error(err)
  493. return nil, myerrors.DbError("查询运维事件统计失败")
  494. }
  495. result[sc.key] = count
  496. }
  497. today := gtime.Now().Format("Y-m-d")
  498. todayNewCount, err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.CreatedTime+" >= ?", today+" 00:00:00").Count()
  499. if err != nil {
  500. g.Log().Error(err)
  501. return nil, myerrors.DbError("查询今日新增数量失败")
  502. }
  503. result["todayNew"] = todayNewCount
  504. return result, nil
  505. }
  506. // generateEventNo 生成事件编号
  507. func generateEventNo() string {
  508. return fmt.Sprintf("OPS%s", gtime.Now().Format("YmdHis"))
  509. }
  510. // GetKanbanData 看板数据
  511. func (s *OperationService) GetKanbanData(req *opsdevmodel.OpsOperationEventKanbanSearchReq) (result g.Map, err error) {
  512. result = g.Map{}
  513. columns := []struct {
  514. Status string
  515. Name string
  516. Key string
  517. }{
  518. {opsdevmodel.EventStatusPending, "待处理", "10"},
  519. {opsdevmodel.EventStatusProcessing, "处理中(重点)", "20"},
  520. {opsdevmodel.EventStatusProcessingNormal, "处理中(普通)", "30"},
  521. {opsdevmodel.EventStatusTransfer, "转研发", "40"},
  522. {opsdevmodel.EventStatusSuspended, "挂起", "70"},
  523. }
  524. for _, col := range columns {
  525. db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus, col.Status)
  526. if req.KeyWords != "" {
  527. switch req.SearchType {
  528. case "custName":
  529. db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.KeyWords+"%")
  530. case "feedbackReporter":
  531. db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.KeyWords+"%")
  532. case "eventNo":
  533. db = db.Where(s.Dao.Columns.EventNo+" like ?", "%"+req.KeyWords+"%")
  534. default:
  535. db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.KeyWords+"%")
  536. }
  537. }
  538. if req.EventType != "" {
  539. db = db.Where(s.Dao.Columns.EventType, req.EventType)
  540. }
  541. if req.PriorityLevel != "" {
  542. db = db.Where(s.Dao.Columns.PriorityLevel, req.PriorityLevel)
  543. }
  544. count, err := db.Count()
  545. if err != nil {
  546. g.Log().Error(err)
  547. return nil, myerrors.DbError("查询看板数据失败")
  548. }
  549. var list []*opsdevmodel.OpsOperationEvent
  550. err = db.Scan(&list)
  551. if err != nil {
  552. g.Log().Error(err)
  553. return nil, myerrors.DbError("查询看板数据失败")
  554. }
  555. result[col.Key] = g.Map{
  556. "status": col.Key,
  557. "name": col.Name,
  558. "count": count,
  559. "list": list,
  560. }
  561. }
  562. return result, nil
  563. }
  564. // AssignOpsUser 接收/分配运维人员
  565. func (s *OperationService) AssignOpsUser(req *opsdevmodel.AssignOpsUserReq) error {
  566. event := new(opsdevmodel.OpsOperationEvent)
  567. err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.Id).Scan(event)
  568. if err != nil {
  569. g.Log().Error(err)
  570. return myerrors.DbError("查询运维事件失败")
  571. }
  572. if event.Id <= 0 {
  573. return myerrors.TipsError("运维事件不存在")
  574. }
  575. if err := s.checkNotClosed(event); err != nil {
  576. return err
  577. }
  578. if event.EventStatus != opsdevmodel.EventStatusPending {
  579. return myerrors.TipsError("只有待处理状态的事件才能分配运维人员")
  580. }
  581. opsUserId := req.OpsUserId
  582. opsUserName := req.OpsUserName
  583. if opsUserId <= 0 {
  584. opsUserId = s.GetCxtUserId()
  585. }
  586. if opsUserName == "" {
  587. opsUserName = s.GetCxtUserName()
  588. }
  589. _, err = s.Dao.FieldsEx(service.UpdateFieldEx...).WherePri(s.Dao.Columns.Id, req.Id).Data(g.Map{
  590. s.Dao.Columns.EventStatus: opsdevmodel.EventStatusProcessing,
  591. s.Dao.Columns.OpsUserId: opsUserId,
  592. s.Dao.Columns.OpsUserName: opsUserName,
  593. s.Dao.Columns.AssignTime: gtime.Now(),
  594. s.Dao.Columns.UpdatedBy: s.GetCxtUserId(),
  595. s.Dao.Columns.UpdatedName: s.GetCxtUserName(),
  596. s.Dao.Columns.UpdatedTime: gtime.Now(),
  597. }).Update()
  598. if err != nil {
  599. g.Log().Error(err)
  600. return myerrors.DbError("分配运维人员失败")
  601. }
  602. return nil
  603. }
  604. // AddRecord 添加处理记录
  605. func (s *OperationService) AddRecord(req *opsdevmodel.AddRecordReq) error {
  606. if req.EventId <= 0 {
  607. return myerrors.ValidError("事件ID不能为空")
  608. }
  609. event := new(opsdevmodel.OpsOperationEvent)
  610. err := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).WherePri(s.Dao.Columns.Id, req.EventId).Scan(event)
  611. if err != nil {
  612. g.Log().Error(err)
  613. return myerrors.DbError("查询运维事件失败")
  614. }
  615. if event.Id <= 0 {
  616. return myerrors.TipsError("运维事件不存在")
  617. }
  618. if err := s.checkNotClosed(event); err != nil {
  619. return err
  620. }
  621. data := g.Map{
  622. s.RecordDao.Columns.EventId: req.EventId,
  623. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  624. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  625. s.RecordDao.Columns.HandleContent: req.HandleContent,
  626. s.RecordDao.Columns.HandleResult: req.HandleResult,
  627. s.RecordDao.Columns.HandleDate: gtime.Now(),
  628. s.RecordDao.Columns.OperateType: opsdevmodel.OperateTypeProcess,
  629. }
  630. service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  631. _, err = s.RecordDao.Data(data).Insert()
  632. if err != nil {
  633. g.Log().Error(err)
  634. return myerrors.DbError("添加处理记录失败")
  635. }
  636. return nil
  637. }
  638. // DeleteAttachment 删除附件
  639. func (s *OperationService) DeleteAttachment(req *comm_def.IdReq) error {
  640. if req.Id <= 0 {
  641. return myerrors.ValidError("参数有误!")
  642. }
  643. attachment := new(opsdevmodel.OpsOperationEventAttachment)
  644. err := s.AttachmentDao.WherePri(s.AttachmentDao.Columns.Id, req.Id).Scan(attachment)
  645. if err != nil {
  646. g.Log().Error(err)
  647. return myerrors.DbError("查询附件失败")
  648. }
  649. if attachment.Id <= 0 {
  650. return myerrors.TipsError("附件不存在")
  651. }
  652. _, err = s.AttachmentDao.WherePri(s.AttachmentDao.Columns.Id, req.Id).Data(g.Map{
  653. s.AttachmentDao.Columns.DeletedTime: gtime.Now(),
  654. s.AttachmentDao.Columns.UpdatedBy: s.GetCxtUserId(),
  655. s.AttachmentDao.Columns.UpdatedName: s.GetCxtUserName(),
  656. }).Update()
  657. if err != nil {
  658. g.Log().Error(err)
  659. return myerrors.DbError("删除附件失败")
  660. }
  661. return nil
  662. }
  663. // GetHistoryList 运维历史列表
  664. func (s *OperationService) GetHistoryList(req *opsdevmodel.OpsOperationEventHistorySearchReq) (total int, list []*opsdevmodel.OpsOperationEvent, err error) {
  665. db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime)
  666. if !req.IncludeClosed {
  667. db = db.Where(s.Dao.Columns.EventStatus, opsdevmodel.EventStatusClosed)
  668. }
  669. if req.ScopeType == "my" {
  670. db = db.Where(s.Dao.Columns.OpsUserId, s.GetCxtUserId())
  671. }
  672. if req.EventTitle != "" {
  673. db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
  674. }
  675. if req.CustName != "" {
  676. db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
  677. }
  678. if req.FeedbackReporter != "" {
  679. db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.FeedbackReporter+"%")
  680. }
  681. if req.OpsUserName != "" {
  682. db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
  683. }
  684. if req.BeginTime != "" {
  685. db = db.Where(s.Dao.Columns.FeedbackDate+" >= ?", req.BeginTime)
  686. }
  687. if req.EndTime != "" {
  688. db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
  689. }
  690. total, err = db.Count()
  691. if err != nil {
  692. g.Log().Error(err)
  693. return 0, nil, myerrors.DbError("查询运维历史数量失败")
  694. }
  695. pageNum, pageSize := req.GetPage()
  696. err = db.Page(pageNum, pageSize).Order(s.Dao.Columns.CompleteTime + " desc").Scan(&list)
  697. if err != nil {
  698. g.Log().Error(err)
  699. return 0, nil, myerrors.DbError("查询运维历史列表失败")
  700. }
  701. return total, list, nil
  702. }
  703. // Export 导出运维历史
  704. func (s *OperationService) Export(ctx context.Context, req *opsdevmodel.OpsOperationEventHistoryExport) (content *opsdevmodel.OpsOperationEventHistoryExportContent, err error) {
  705. db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime)
  706. if !req.IncludeClosed {
  707. db = db.Where(s.Dao.Columns.EventStatus, opsdevmodel.EventStatusClosed)
  708. }
  709. if req.ScopeType == "my" {
  710. db = db.Where(s.Dao.Columns.OpsUserId, s.GetCxtUserId())
  711. }
  712. if req.EventTitle != "" {
  713. db = db.Where(s.Dao.Columns.EventTitle+" like ?", "%"+req.EventTitle+"%")
  714. }
  715. if req.CustName != "" {
  716. db = db.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
  717. }
  718. if req.FeedbackReporter != "" {
  719. db = db.Where(s.Dao.Columns.FeedbackReporter+" like ?", "%"+req.FeedbackReporter+"%")
  720. }
  721. if req.OpsUserName != "" {
  722. db = db.Where(s.Dao.Columns.OpsUserName+" like ?", "%"+req.OpsUserName+"%")
  723. }
  724. if req.BeginTime != "" {
  725. db = db.Where(s.Dao.Columns.FeedbackDate+" >= ?", req.BeginTime)
  726. }
  727. if req.EndTime != "" {
  728. db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
  729. }
  730. var list []*opsdevmodel.OpsOperationEvent
  731. err = db.Order(s.Dao.Columns.CompleteTime + " desc").Scan(&list)
  732. if err != nil {
  733. g.Log().Error(err)
  734. return nil, myerrors.DbError("查询运维历史失败")
  735. }
  736. // 获取所有事件ID
  737. var eventIds []int
  738. for _, item := range list {
  739. eventIds = append(eventIds, item.Id)
  740. }
  741. // 获取所有事件的处理记录
  742. var records []*opsdevmodel.OpsOperationEventRecord
  743. if len(eventIds) > 0 {
  744. err = s.RecordDao.WhereIn(s.RecordDao.Columns.EventId, eventIds).Order(s.RecordDao.Columns.HandleDate + " desc").Scan(&records)
  745. if err != nil {
  746. g.Log().Error(err)
  747. return nil, myerrors.DbError("查询处理记录失败")
  748. }
  749. }
  750. // 构建记录Map
  751. recordMap := make(map[int][]*opsdevmodel.OpsOperationEventRecord)
  752. for _, record := range records {
  753. recordMap[record.EventId] = append(recordMap[record.EventId], record)
  754. }
  755. // 构建状态Map
  756. statusMap := map[string]string{
  757. opsdevmodel.EventStatusPending: "待处理",
  758. opsdevmodel.EventStatusProcessing: "处理中(重点)",
  759. opsdevmodel.EventStatusProcessingNormal: "处理中(普通)",
  760. opsdevmodel.EventStatusTransfer: "转研发",
  761. opsdevmodel.EventStatusSuspended: "挂起",
  762. opsdevmodel.EventStatusClosed: "已关闭",
  763. }
  764. // 构建操作类型Map
  765. operateTypeMap := map[string]string{
  766. opsdevmodel.OperateTypeProcess: "处理",
  767. opsdevmodel.OperateTypeResume: "转处理",
  768. opsdevmodel.OperateTypeTransfer: "转研发",
  769. opsdevmodel.OperateTypeSuspend: "挂起",
  770. opsdevmodel.OperateTypeClose: "关闭",
  771. }
  772. // 构建处理结果Map
  773. handleResultMap := map[string]string{
  774. opsdevmodel.HandleResultResolved: "已解决",
  775. opsdevmodel.HandleResultPartially: "部分解决",
  776. opsdevmodel.HandleResultUnresolved: "未解决",
  777. }
  778. // 构建导出数据
  779. exportDataList := make([]map[string]interface{}, 0)
  780. for _, item := range list {
  781. // 构建处理过程
  782. processBuilder := ""
  783. if itemRecords, ok := recordMap[item.Id]; ok && len(itemRecords) > 0 {
  784. for i, record := range itemRecords {
  785. // 处理时间(仅年月)
  786. handleDate := ""
  787. if record.HandleDate != nil {
  788. handleDate = record.HandleDate.Format("Y-m-d H:i:s")
  789. }
  790. // 操作类型描述
  791. operateTypeStr := operateTypeMap[record.OperateType]
  792. if operateTypeStr == "" {
  793. operateTypeStr = record.OperateType
  794. }
  795. // 处理结果描述
  796. handleResultStr := handleResultMap[record.HandleResult]
  797. if handleResultStr == "" {
  798. handleResultStr = record.HandleResult
  799. }
  800. // 清理处理内容中的HTML标签
  801. cleanContent := cleanHtmlTags(record.HandleContent)
  802. recordStr := fmt.Sprintf("%s-%s-%s-%s-%s", handleDate, record.HandleUserName, operateTypeStr, handleResultStr, cleanContent)
  803. if i > 0 {
  804. processBuilder += "\n" + recordStr
  805. } else {
  806. processBuilder = recordStr
  807. }
  808. }
  809. }
  810. closedTime := ""
  811. if item.CompleteTime != nil {
  812. closedTime = item.CompleteTime.Format("Y-m-d")
  813. }
  814. feedbackDate := ""
  815. if item.FeedbackDate != nil {
  816. feedbackDate = item.FeedbackDate.Format("Y-m-d")
  817. }
  818. exportData := map[string]interface{}{
  819. "eventNo": item.EventNo,
  820. "eventTitle": item.EventTitle,
  821. "eventStatus": statusMap[item.EventStatus],
  822. "eventType": item.EventType,
  823. "custName": item.CustName,
  824. "opsUserName": item.OpsUserName,
  825. "feedbackDate": feedbackDate,
  826. "priorityLevel": item.PriorityLevel,
  827. "handleProcess": processBuilder,
  828. "closedTime": closedTime,
  829. }
  830. exportDataList = append(exportDataList, exportData)
  831. }
  832. // 调用公共导出方法
  833. exportContent := new(opsdevmodel.OpsOperationEventHistoryExportContent)
  834. contentBase64, err := service.CommonExportExcel(ctx, "运维历史", opsdevmodel.OpsOperationEventHistoryExportData{}, exportDataList)
  835. if err != nil {
  836. g.Log().Error(err)
  837. return nil, myerrors.DbError("导出运维历史失败")
  838. }
  839. exportContent.Content = contentBase64
  840. return exportContent, nil
  841. }
  842. func (s *OperationService) ExportNonClosed(ctx context.Context, req *opsdevmodel.OpsOperationEventExport) (content *opsdevmodel.OpsOperationEventHistoryExportContent, err error) {
  843. db := s.Dao.FieldsEx(s.Dao.Columns.DeletedTime).Where(s.Dao.Columns.EventStatus+" != ?", opsdevmodel.EventStatusClosed)
  844. var list []*opsdevmodel.OpsOperationEvent
  845. err = db.Order(s.Dao.Columns.FeedbackDate + " desc").Scan(&list)
  846. if err != nil {
  847. g.Log().Error(err)
  848. return nil, myerrors.DbError("查询运维事件失败")
  849. }
  850. var eventIds []int
  851. for _, item := range list {
  852. eventIds = append(eventIds, item.Id)
  853. }
  854. var records []*opsdevmodel.OpsOperationEventRecord
  855. if len(eventIds) > 0 {
  856. err = s.RecordDao.WhereIn(s.RecordDao.Columns.EventId, eventIds).Order(s.RecordDao.Columns.HandleDate + " desc").Scan(&records)
  857. if err != nil {
  858. g.Log().Error(err)
  859. return nil, myerrors.DbError("查询处理记录失败")
  860. }
  861. }
  862. recordMap := make(map[int][]*opsdevmodel.OpsOperationEventRecord)
  863. for _, record := range records {
  864. recordMap[record.EventId] = append(recordMap[record.EventId], record)
  865. }
  866. statusMap := map[string]string{
  867. opsdevmodel.EventStatusPending: "待处理",
  868. opsdevmodel.EventStatusProcessing: "处理中(重点)",
  869. opsdevmodel.EventStatusProcessingNormal: "处理中(普通)",
  870. opsdevmodel.EventStatusTransfer: "转研发",
  871. opsdevmodel.EventStatusSuspended: "挂起",
  872. opsdevmodel.EventStatusClosed: "已关闭",
  873. }
  874. operateTypeMap := map[string]string{
  875. opsdevmodel.OperateTypeProcess: "处理",
  876. opsdevmodel.OperateTypeResume: "转处理",
  877. opsdevmodel.OperateTypeTransfer: "转研发",
  878. opsdevmodel.OperateTypeSuspend: "挂起",
  879. opsdevmodel.OperateTypeClose: "关闭",
  880. }
  881. handleResultMap := map[string]string{
  882. opsdevmodel.HandleResultResolved: "已解决",
  883. opsdevmodel.HandleResultPartially: "部分解决",
  884. opsdevmodel.HandleResultUnresolved: "未解决",
  885. }
  886. exportDataList := make([]map[string]interface{}, 0)
  887. for _, item := range list {
  888. processBuilder := ""
  889. if itemRecords, ok := recordMap[item.Id]; ok && len(itemRecords) > 0 {
  890. for i, record := range itemRecords {
  891. handleDate := ""
  892. if record.HandleDate != nil {
  893. handleDate = record.HandleDate.Format("Y-m-d H:i:s")
  894. }
  895. operateTypeStr := operateTypeMap[record.OperateType]
  896. if operateTypeStr == "" {
  897. operateTypeStr = record.OperateType
  898. }
  899. handleResultStr := handleResultMap[record.HandleResult]
  900. if handleResultStr == "" {
  901. handleResultStr = record.HandleResult
  902. }
  903. cleanContent := cleanHtmlTags(record.HandleContent)
  904. recordStr := fmt.Sprintf("%s-%s-%s-%s-%s", handleDate, record.HandleUserName, operateTypeStr, handleResultStr, cleanContent)
  905. if i > 0 {
  906. processBuilder += "\n" + recordStr
  907. } else {
  908. processBuilder = recordStr
  909. }
  910. }
  911. }
  912. feedbackDate := ""
  913. if item.FeedbackDate != nil {
  914. feedbackDate = item.FeedbackDate.Format("Y-m-d")
  915. }
  916. exportData := map[string]interface{}{
  917. "eventNo": item.EventNo,
  918. "eventTitle": item.EventTitle,
  919. "eventStatus": statusMap[item.EventStatus],
  920. "eventType": item.EventType,
  921. "custName": item.CustName,
  922. "opsUserName": item.OpsUserName,
  923. "feedbackDate": feedbackDate,
  924. "priorityLevel": item.PriorityLevel,
  925. "handleProcess": processBuilder,
  926. }
  927. exportDataList = append(exportDataList, exportData)
  928. }
  929. exportContent := new(opsdevmodel.OpsOperationEventHistoryExportContent)
  930. contentBase64, err := service.CommonExportExcel(ctx, "运维事件", opsdevmodel.OpsOperationEventExportData{}, exportDataList)
  931. if err != nil {
  932. g.Log().Error(err)
  933. return nil, myerrors.DbError("导出运维事件失败")
  934. }
  935. exportContent.Content = contentBase64
  936. return exportContent, nil
  937. }
  938. func cleanHtmlTags(content string) string {
  939. if content == "" {
  940. return ""
  941. }
  942. imgPattern := regexp.MustCompile(`src=["']([^"']+)["']`)
  943. imgMatches := imgPattern.FindAllStringSubmatch(content, -1)
  944. seen := make(map[string]bool)
  945. var imgUrls []string
  946. for _, match := range imgMatches {
  947. if len(match) > 1 && !seen[match[1]] {
  948. seen[match[1]] = true
  949. imgUrls = append(imgUrls, match[1])
  950. }
  951. }
  952. htmlTagPattern := regexp.MustCompile(`<[^>]*>`)
  953. result := htmlTagPattern.ReplaceAllString(content, "")
  954. result = strings.ReplaceAll(result, "&nbsp;", " ")
  955. result = strings.ReplaceAll(result, "&amp;", "&")
  956. result = strings.ReplaceAll(result, "&lt;", "<")
  957. result = strings.ReplaceAll(result, "&gt;", ">")
  958. result = strings.ReplaceAll(result, "&quot;", "\"")
  959. result = strings.ReplaceAll(result, "&#39;", "'")
  960. result = strings.TrimSpace(result)
  961. if len(imgUrls) > 0 {
  962. result += "\n图片: "
  963. for i, url := range imgUrls {
  964. if i > 0 {
  965. result += ", "
  966. }
  967. result += url
  968. }
  969. }
  970. return result
  971. }