plat_task.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. package plat
  2. import (
  3. "bytes"
  4. "context"
  5. "dashoo.cn/micro/app/dao/plat"
  6. model "dashoo.cn/micro/app/model/plat"
  7. "dashoo.cn/micro/app/service"
  8. "database/sql"
  9. "fmt"
  10. "github.com/360EntSecGroup-Skylar/excelize"
  11. "github.com/gogf/gf/errors/gerror"
  12. "github.com/gogf/gf/frame/g"
  13. "github.com/gogf/gf/os/gtime"
  14. "github.com/gogf/gf/util/gconv"
  15. "strconv"
  16. )
  17. type taskService struct {
  18. *service.ContextService
  19. Dao *plat.PlatTaskDao
  20. }
  21. func NewTaskService(ctx context.Context) (svc *taskService, err error) {
  22. svc = new(taskService)
  23. if svc.ContextService, err = svc.Init(ctx); err != nil {
  24. return nil, err
  25. }
  26. svc.Dao = plat.NewPlatTaskDao(svc.Tenant)
  27. return svc, nil
  28. }
  29. // 任务信息列表
  30. func (s *taskService) GetList(req *model.SearchPlatTaskReq) (total int, TaskList []*model.PlatTaskEx, err error) {
  31. TaskModel := s.Dao.InnerJoin("plat_task_handle", "plat_task_handle.task_id=plat_task.id")
  32. if req.TaskTitle != "" {
  33. TaskModel = TaskModel.Where("plat_task.task_title LIKE ?", "%"+req.TaskTitle+"%")
  34. }
  35. if req.TaskType != "" {
  36. TaskModel = TaskModel.Where("plat_task.task_type", req.TaskType)
  37. }
  38. if req.TaskStatus != "" {
  39. TaskModel = TaskModel.Where("plat_task.task_status", req.TaskStatus)
  40. }
  41. if req.IsOverdue != "" {
  42. TaskModel = TaskModel.Where("plat_task.is_overdue", req.IsOverdue)
  43. }
  44. if req.MainUserId != "" {
  45. TaskModel = TaskModel.Where("plat_task.main_user_id", req.MainUserId)
  46. }
  47. if req.TargetId != "" {
  48. TaskModel = TaskModel.Where("plat_task.target_id", req.TargetId)
  49. }
  50. if req.TargetType != "" {
  51. TaskModel = TaskModel.Where("plat_task.target_type", req.TargetType)
  52. }
  53. if req.MySelf == "1" {
  54. TaskModel = TaskModel.Where("plat_task.created_by", s.GetCxtUserId())
  55. }
  56. if req.IsMain == "1" {
  57. TaskModel = TaskModel.Where("plat_task.main_user_id", s.GetCxtUserId())
  58. }
  59. if req.OperateType == "1" {
  60. TaskModel = TaskModel.Where(fmt.Sprintf("plat_task_handle.task_status='10' AND (plat_task_handle.main_user_id=%v OR FIND_IN_SET(%v, plat_task_handle.owner_user_id))", s.GetCxtUserId(), s.GetCxtUserId()))
  61. } else if req.OperateType == "2" {
  62. TaskModel = TaskModel.Where("plat_task.created_by", s.GetCxtUserId())
  63. } else if req.OperateType == "3" {
  64. TaskModel = TaskModel.Where(fmt.Sprintf("plat_task_handle.task_status='20' AND plat_task_handle.handle_user_id=%v", s.GetCxtUserId()))
  65. }
  66. TaskModel.Group("plat_task.id")
  67. total, err = TaskModel.Count()
  68. if err != nil {
  69. g.Log().Error(err)
  70. err = gerror.New("获取总行数失败")
  71. return
  72. }
  73. err = TaskModel.Page(req.GetPage()).Order("plat_task.created_time DESC").Fields("plat_task.*,plat_task_handle.step").Scan(&TaskList)
  74. return
  75. }
  76. // 导出数据
  77. func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent, err error) {
  78. var con model.ExportContent
  79. // 获取数据
  80. total, list, err := s.GetList(&req.SearchPlatTaskReq)
  81. if err != nil {
  82. return nil, err
  83. }
  84. //rsp.List
  85. f := excelize.NewFile()
  86. // Create a new sheet.
  87. index := f.NewSheet("Sheet1")
  88. for index, item := range req.Columns {
  89. sheetPosition := service.Div(index+1) + "1"
  90. f.SetCellValue("Sheet1", sheetPosition, item)
  91. }
  92. if total > 0 {
  93. // 构造用户和类型填充数据
  94. userMap := make(map[int]string, 0)
  95. typeMap := make(map[string]string, 0)
  96. users, err := s.Dao.DB.Model("sys_user").FindAll()
  97. if err != nil {
  98. return nil, err
  99. }
  100. types, err := s.Dao.DB.Model("sys_dict_data").Where("dict_type='TaskType'").FindAll()
  101. if err != nil {
  102. return nil, err
  103. }
  104. for _, item := range users {
  105. userMap[item["id"].Int()] = item["user_name"].String()
  106. }
  107. for _, item := range types {
  108. typeMap[item["dict_value"].String()] = item["dict_label"].String()
  109. }
  110. // 构造excel数据
  111. for lineNum, item := range list {
  112. for index, value := range req.Columns {
  113. if value == "督办标题" {
  114. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskTitle)
  115. }
  116. if value == "督办类型" {
  117. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), typeMap[item.TaskType])
  118. }
  119. if value == "状态" {
  120. data := ""
  121. if item.TaskStatus == "10" {
  122. data = "进行中"
  123. } else if item.TaskStatus == "20" {
  124. data = "关闭"
  125. }
  126. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
  127. }
  128. if value == "超期" {
  129. data := ""
  130. if item.TaskStatus == "10" {
  131. data = "否"
  132. } else if item.TaskStatus == "20" {
  133. data = "是"
  134. }
  135. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
  136. }
  137. if value == "督办说明" {
  138. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskDesc)
  139. }
  140. if value == "关联对象" {
  141. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TargetName)
  142. }
  143. if value == "负责人" {
  144. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.MainUserId])
  145. }
  146. if value == "督办人" {
  147. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.SupervisorUserId])
  148. }
  149. if value == "开始时间" {
  150. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskStartDate.Format("Y-m-d H:i:s"))
  151. }
  152. if value == "结束时间" {
  153. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskEndDate.Format("Y-m-d H:i:s"))
  154. }
  155. if value == "创建时间" {
  156. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.CreatedTime.Format("Y-m-d H:i:s"))
  157. }
  158. }
  159. }
  160. }
  161. f.SetActiveSheet(index)
  162. var buffer *bytes.Buffer
  163. buffer, _ = f.WriteToBuffer()
  164. con.Content = buffer.Bytes()
  165. return &con, err
  166. }
  167. // 统计
  168. func (s *taskService) Statistics(req *model.SearchPlatTaskReq) (*model.TaskNumberCount, error) {
  169. var result model.TaskNumberCount
  170. // 统计数量
  171. count, err := s.Dao.InnerJoin("plat_task_handle", "plat_task.Id=plat_task_handle.task_id").Where(fmt.Sprintf("plat_task_handle.task_status='10' AND (plat_task_handle.main_user_id=%v OR FIND_IN_SET(%v, plat_task_handle.owner_user_id))", s.GetCxtUserId(), s.GetCxtUserId())).Group("plat_task.Id").Count()
  172. if err != nil {
  173. return nil, err
  174. }
  175. result.ToDoNumber = count
  176. return &result, nil
  177. }
  178. // 添加信息
  179. func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
  180. platTask := new(model.PlatTask)
  181. if err = gconv.Struct(req, platTask); err != nil {
  182. return
  183. }
  184. platTask.IsOverdue = "10" // 是否超期(10否20是)
  185. if platTask.TaskStartDate == nil {
  186. platTask.TaskStartDate = gtime.Now()
  187. }
  188. // 填充创建信息
  189. service.SetCreatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
  190. // 填充更新信息
  191. //service.SetUpdatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
  192. res, err := s.Dao.Insert(platTask)
  193. if err != nil {
  194. return
  195. }
  196. // 创建操作任务
  197. id, _ := res.LastInsertId()
  198. platTask.Id = int(id)
  199. nextHandle := createNextTaskHandel(s, platTask, 10)
  200. _, err = s.Dao.DB.Model("plat_task_handle").Insert(nextHandle)
  201. if err != nil {
  202. return
  203. }
  204. // 流程日志
  205. err = CreateTaskLog(s, nil, int(id), s.GetCxtUserId(), s.GetCxtUserName(), "创建督办", "创建督办成功", "")
  206. return
  207. }
  208. // 修改状态
  209. func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
  210. data := ""
  211. where := fmt.Sprintf("id='%v'", req.TaskId)
  212. nodeName := "状态修改"
  213. desc := "修改成功"
  214. // 类型合规判断
  215. if req.Type == "TaskStatus" {
  216. data = fmt.Sprintf("task_status='%v'", req.NowStatus)
  217. nodeName = "状态修改"
  218. if req.NowStatus == "20" {
  219. desc = "关闭"
  220. data += fmt.Sprintf(",task_end_date='%v'", gtime.Now().Format("Y-m-d H:i:s"))
  221. }
  222. } else if req.Type == "IsOverdue" {
  223. nodeName = "超期状态修改"
  224. if req.NowStatus == "20" {
  225. desc = "超期"
  226. }
  227. data = fmt.Sprintf("is_overdue='%v'", req.NowStatus)
  228. } else {
  229. return fmt.Errorf("类型不匹配,请仔细检查")
  230. }
  231. // 读取现有数据
  232. task, err := s.Dao.Where(where).FindOne()
  233. if err != nil {
  234. return err
  235. }
  236. // 状态数据一致性判断
  237. if (req.Type == "TaskStatus" && task.TaskStatus != req.OldStatus) || (req.Type == "IsOverdue" && task.IsOverdue != req.OldStatus) {
  238. return fmt.Errorf("状态不匹配,进行该操作")
  239. }
  240. // 更新数据
  241. _, err = s.Dao.Update(data, where)
  242. if err != nil {
  243. return
  244. }
  245. // 流程日志
  246. taskId, _ := strconv.Atoi(req.TaskId)
  247. err = CreateTaskLog(s, nil, taskId, s.GetCxtUserId(), s.GetCxtUserName(), nodeName, desc, "")
  248. return
  249. }
  250. //步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  251. // 督办任务处理
  252. func (s *taskService) Handle(req *model.HandleReq) (err error) {
  253. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  254. logNodeName := ""
  255. logDesc := ""
  256. var taskHandle model.PlatTaskHandle
  257. err = s.Dao.DB.Model("plat_task_handle").Where(fmt.Sprintf("task_id='%v' AND step=%v AND task_status='10' AND (main_user_id=%v OR FIND_IN_SET(%v, owner_user_id))", req.Step, req.TaskId, s.GetCxtUserId(), s.GetCxtUserId())).Scan(&taskHandle)
  258. if err != nil {
  259. if err == sql.ErrNoRows {
  260. return fmt.Errorf("数据不匹配,刷新数据重试")
  261. }
  262. return err
  263. }
  264. now := gtime.Now()
  265. // 数据暂存,不做任何流程修改
  266. if req.Step == 15 {
  267. // 暂存
  268. logNodeName = "暂存"
  269. logDesc = s.GetCxtUserName() + "暂存进展信息"
  270. // 1 标记删除旧的进展数据
  271. _, err = s.Dao.DB.Model("plat_task_progress").Update(fmt.Sprintf("deleted_time='%v'", now.Format("Y-m-d H:i:s")), fmt.Sprintf("task_id='%v'", req.TaskId))
  272. if err != nil {
  273. return err
  274. }
  275. // 2 保存新的数据
  276. _, err = s.Dao.DB.Model("plat_task_progress").Save(req.ProgressList)
  277. if err != nil {
  278. return err
  279. }
  280. } else {
  281. var nextHandle = new (model.PlatTaskHandle)
  282. task, err := s.Dao.Where("id", req.TaskId).FindOne()
  283. if err != nil {
  284. return err
  285. }
  286. // 构造更新数据
  287. handleData := g.Map{
  288. "task_status": "20",
  289. "handle_user_id": s.GetCxtUserId(),
  290. "handle_date": now.Format("Y-m-d H:i:s"),
  291. "handle_status": req.HandleStatus,
  292. "handle_desc": req.HandleDesc,
  293. "updated_by": s.GetCxtUserId(),
  294. "updated_name": s.GetCxtUserName(),
  295. "updated_time": now.Format("Y-m-d H:i:s"),
  296. }
  297. taskData := g.Map{
  298. "updated_by": s.GetCxtUserId(),
  299. "updated_name": s.GetCxtUserName(),
  300. "updated_time": now.Format("Y-m-d H:i:s"),
  301. }
  302. // 督办任务接收
  303. if req.Step == 10 {
  304. // 接收任务
  305. taskData["task_status"] = "20"
  306. taskData["receive_date"] = now.Format("Y-m-d H:i:s")
  307. nextHandle = createNextTaskHandel(s, task, 20)
  308. logNodeName = "接收"
  309. logDesc = s.GetCxtUserName() + "接收督办任务"
  310. } else if req.Step == 20 {
  311. // 提交数据
  312. nextHandle = createNextTaskHandel(s, task, 30)
  313. logNodeName = "提交"
  314. logDesc = s.GetCxtUserName() + "提交督办任务"
  315. // 更新进展数据
  316. for index, progress := range req.ProgressList {
  317. // 填充创建信息
  318. if progress.CreatedBy == 0 {
  319. service.SetCreatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  320. }
  321. // 填充更新信息
  322. service.SetUpdatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  323. }
  324. // 保存督办进展
  325. // 1 标记删除旧的进展数据
  326. _, err = s.Dao.DB.Model("plat_task_progress").Update(fmt.Sprintf("deleted_time='%v'", now.Format("Y-m-d H:i:s")), fmt.Sprintf("task_id='%v'", req.TaskId))
  327. if err != nil {
  328. return err
  329. }
  330. // 2 保存新的数据
  331. _, err = s.Dao.DB.Model("plat_task_progress").Save(req.ProgressList)
  332. if err != nil {
  333. return err
  334. }
  335. } else if req.Step == 30 {
  336. // 督办人审批
  337. taskData["approver_id"] = s.GetCxtUserId()
  338. taskData["appro_date"] = now.Format("Y-m-d H:i:s")
  339. taskData["appro_status"] = req.HandleStatus
  340. taskData["appro_desc"] = req.HandleDesc
  341. logNodeName = "审批"
  342. if req.HandleStatus == "审批通过" {
  343. logDesc = s.GetCxtUserName() + "审批通过"
  344. nextHandle = createNextTaskHandel(s, task, 40)
  345. } else if req.HandleStatus == "审批退回" {
  346. logDesc = s.GetCxtUserName() + "审批退回"
  347. nextHandle = createNextTaskHandel(s, task, 20)
  348. }
  349. } else if req.Step == 40 {
  350. // 监办人评价
  351. taskData["evaluator_id"] = s.GetCxtUserId()
  352. taskData["evaluate_date"] = now.Format("Y-m-d H:i:s")
  353. taskData["evaluate_status"] = req.HandleStatus
  354. taskData["evaluate_desc"] = req.HandleDesc
  355. logNodeName = "评价"
  356. if req.HandleStatus == "审批通过" {
  357. // 监办人评价,审批通过,任务结束
  358. logDesc = s.GetCxtUserName() + "审批通过"
  359. nextHandle = nil
  360. taskData["actual_close_date"] = now.Format("Y-m-d H:i:s")
  361. taskData["task_status"] = "30"
  362. } else if req.HandleStatus == "审批退回" {
  363. logDesc = s.GetCxtUserName() + "审批通过"
  364. nextHandle = createNextTaskHandel(s, task, 20)
  365. }
  366. }
  367. // 更新数据
  368. // 更新督办任务数据
  369. _, err = s.Dao.Update(taskData, fmt.Sprintf("id='%v'", req.TaskId))
  370. if err != nil {
  371. return err
  372. }
  373. // 更新任务数据
  374. _, err = s.Dao.DB.Model("plat_task_handle").Update(handleData, fmt.Sprintf("ID='%v'", taskHandle.ID))
  375. if err != nil {
  376. return err
  377. }
  378. // 创建下一条任务
  379. if nextHandle != nil {
  380. _, err = s.Dao.DB.Model("plat_task_handle").Save(nextHandle)
  381. if err != nil {
  382. return err
  383. }
  384. }
  385. }
  386. // 流程日志
  387. err = CreateTaskLog(s, nil, req.TaskId, s.GetCxtUserId(), s.GetCxtUserName(), logNodeName, logDesc, "")
  388. if err != nil {
  389. return err
  390. }
  391. return fmt.Errorf("未知步骤,无法操作")
  392. }
  393. // 任务日志创建方法
  394. func CreateTaskLog(s1 *taskService, s2 *taskProgressService, taskId, userId int, userName, nodeName, desc, remark string) (err error) {
  395. var log model.PlatTaskLog
  396. startTime := gtime.Now()
  397. endTime := startTime
  398. // 默认为当前时间,然后随已有日志情况进行更新
  399. if s1 != nil {
  400. logs, err := s1.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  401. if err != nil && err != sql.ErrNoRows {
  402. return err
  403. }
  404. if len(logs) > 0 {
  405. startTime = logs[0]["end_time"].GTime()
  406. }
  407. } else {
  408. logs, err := s2.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  409. if err != nil && err != sql.ErrNoRows {
  410. return err
  411. }
  412. if len(logs) > 0 {
  413. startTime = logs[0]["end_time"].GTime()
  414. }
  415. }
  416. // 填入日志相关数据
  417. log.TaskId = taskId
  418. log.NodeName = nodeName
  419. log.Desc = desc
  420. log.StartTime = startTime
  421. log.EndTime = endTime
  422. log.Remark = remark
  423. log.CreatedTime = endTime
  424. log.CreatedName = userName
  425. log.CreatedBy = userId
  426. if s1 != nil {
  427. _, err = s1.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  428. } else {
  429. _, err = s2.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  430. }
  431. return err
  432. }
  433. // 创建个人的督办任务(其中,暂存不会生成个人任务,不会改变任何东西,只会新增一条日志)
  434. func createNextTaskHandel(s *taskService, task *model.PlatTask, step int) *model.PlatTaskHandle {
  435. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  436. var personTask model.PlatTaskHandle
  437. personTask.TaskId = task.Id
  438. personTask.TaskStatus = "10"
  439. personTask.Step = step
  440. // 督办任务为发起时
  441. if step == 10 {
  442. personTask.MainUserId = task.MainUserId
  443. personTask.OwnerUserId = task.OwnerUserId
  444. } else if step == 20 {
  445. // 提交给督办人审批
  446. personTask.MainUserId = task.SupervisorUserId
  447. } else if step == 30 {
  448. // 提交给监办人评价
  449. personTask.MainUserId = task.WatchUserId
  450. }
  451. // 填充创建信息
  452. service.SetCreatedInfo(&personTask, s.GetCxtUserId(), s.GetCxtUserName())
  453. return &personTask
  454. }