plat_task.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. package plat
  2. import (
  3. "bytes"
  4. "context"
  5. workflowModel "dashoo.cn/micro/app/model/workflow"
  6. workflowService "dashoo.cn/micro/app/service/workflow"
  7. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  8. "dashoo.cn/opms_libary/plugin/dingtalk/workflow"
  9. "dashoo.cn/opms_libary/utils"
  10. "database/sql"
  11. "errors"
  12. "fmt"
  13. "strconv"
  14. "strings"
  15. "dashoo.cn/opms_libary/myerrors"
  16. "github.com/360EntSecGroup-Skylar/excelize"
  17. "github.com/gogf/gf/frame/g"
  18. "github.com/gogf/gf/os/gtime"
  19. "github.com/gogf/gf/util/gconv"
  20. "dashoo.cn/micro/app/dao/plat"
  21. model "dashoo.cn/micro/app/model/plat"
  22. "dashoo.cn/micro/app/service"
  23. )
  24. var PlatTaskApprovalProcessCode = "PROC-B2BE7E92-8A12-4CFF-83CD-FF23F397CCE2"
  25. type taskService struct {
  26. *service.ContextService
  27. Dao *plat.PlatTaskDao
  28. }
  29. func NewTaskService(ctx context.Context) (svc *taskService, err error) {
  30. svc = new(taskService)
  31. if svc.ContextService, err = svc.Init(ctx); err != nil {
  32. return nil, err
  33. }
  34. svc.Dao = plat.NewPlatTaskDao(svc.Tenant)
  35. return svc, nil
  36. }
  37. // GetList 任务信息列表
  38. func (s *taskService) GetList(req *model.SearchPlatTaskReq) (total int, TaskList []*model.PlatTaskEx, err error) {
  39. orderBy := "plat_task.created_time DESC"
  40. TaskModel := s.Dao.LeftJoin("plat_task_handle", "plat_task_handle.task_id=plat_task.id")
  41. if req.TaskId != "" {
  42. TaskModel = TaskModel.Where("plat_task.id", req.TaskId)
  43. }
  44. if req.TaskTitle != "" {
  45. TaskModel = TaskModel.Where("plat_task.task_title LIKE ?", "%"+req.TaskTitle+"%")
  46. }
  47. if req.TaskType != "" {
  48. TaskModel = TaskModel.Where("plat_task.task_type", req.TaskType)
  49. }
  50. if req.Source != "" {
  51. TaskModel = TaskModel.Where("plat_task.source", req.Source)
  52. }
  53. if req.TaskStatus != "" {
  54. TaskModel = TaskModel.Where("plat_task.task_status", req.TaskStatus)
  55. }
  56. // 是否超期(10否20是30全部(或为空查询全部))
  57. if req.IsOverdue != "" {
  58. today := gtime.Now().Format("Y-m-d 00:00:00")
  59. if req.IsOverdue == "10" {
  60. TaskModel = TaskModel.Where("plat_task.task_end_date >= ? OR (plat_task.task_status<>'10' && plat_task.task_status<>'20')", today)
  61. } else if req.IsOverdue == "20" {
  62. TaskModel = TaskModel.Where("plat_task.task_end_date < ? AND (plat_task.task_status='10' OR plat_task.task_status='20')", today)
  63. }
  64. }
  65. if req.MainUserId != "" {
  66. TaskModel = TaskModel.Where("plat_task.main_user_id", req.MainUserId)
  67. }
  68. if req.SupervisorUserId != "" {
  69. TaskModel = TaskModel.Where("plat_task.supervisor_user_id", req.SupervisorUserId)
  70. }
  71. if req.CreatedById != "" {
  72. TaskModel = TaskModel.Where("plat_task.created_by", req.CreatedById)
  73. }
  74. if req.TargetId != "" {
  75. TaskModel = TaskModel.Where("plat_task.target_id", req.TargetId)
  76. }
  77. if req.TargetType != "" {
  78. TaskModel = TaskModel.Where("plat_task.target_type", req.TargetType)
  79. }
  80. if req.MySelf == "1" {
  81. TaskModel = TaskModel.Where("plat_task.created_by", s.GetCxtUserId())
  82. }
  83. if req.IsMain == "1" {
  84. TaskModel = TaskModel.Where("plat_task.main_user_id", s.GetCxtUserId())
  85. }
  86. if req.OperateType == "1" { // 我的待办
  87. orderBy = "plat_task.task_status ASC, plat_task.created_time DESC"
  88. 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()))
  89. } else if req.OperateType == "2" { // 我发起的
  90. TaskModel = TaskModel.Where("plat_task.created_by", s.GetCxtUserId())
  91. } else if req.OperateType == "3" { // 我处理的
  92. TaskModel = TaskModel.Where(fmt.Sprintf("plat_task_handle.task_status='20' AND plat_task_handle.handle_user_id=%v", s.GetCxtUserId()))
  93. } else if req.OperateType == "4" { // 抄送我的
  94. TaskModel = TaskModel.Where(fmt.Sprintf("FIND_IN_SET(%v, plat_task.copy_user_id)", s.GetCxtUserId()))
  95. }
  96. // 超期时间:为空 全部;1/3/5/>5(超期1天之内;超期1-3天之间;超期3-5天,超期5天以上)
  97. if req.OverdueDays != "" {
  98. if req.OverdueDays == "1" {
  99. date := gtime.Now().AddDate(0, 0, -1).Format("Y-m-d")
  100. TaskModel = TaskModel.Where("plat_task.task_end_date LIKE ? AND (plat_task.task_status='10' OR plat_task.task_status='20')", "%"+date+"%")
  101. } else if req.OverdueDays == "3" {
  102. date1 := gtime.Now().AddDate(0, 0, -1).Format("Y-m-d 00:00:00")
  103. date2 := gtime.Now().AddDate(0, 0, -3).Format("Y-m-d 00:00:00")
  104. TaskModel = TaskModel.Where(fmt.Sprintf("plat_task.task_end_date >= '%v' AND plat_task.task_end_date < '%v' AND (plat_task.task_status='10' OR plat_task.task_status='20')", date2, date1))
  105. } else if req.OverdueDays == "5" {
  106. date1 := gtime.Now().AddDate(0, 0, -3).Format("Y-m-d 00:00:00")
  107. date2 := gtime.Now().AddDate(0, 0, -5).Format("Y-m-d 00:00:00")
  108. TaskModel = TaskModel.Where(fmt.Sprintf("plat_task.task_end_date >= '%v' AND plat_task.task_end_date < '%v' AND (plat_task.task_status='10' OR plat_task.task_status='20')", date2, date1))
  109. } else if req.OverdueDays == ">5" {
  110. date := gtime.Now().AddDate(0, 0, -5).Format("Y-m-d 00:00:00")
  111. TaskModel = TaskModel.Where("plat_task.task_end_date < ? AND (plat_task.task_status='10' OR plat_task.task_status='20')", date)
  112. }
  113. }
  114. TaskModel = TaskModel.Group("plat_task.id")
  115. total, err = TaskModel.Count()
  116. if err != nil {
  117. g.Log().Error(err)
  118. err = myerrors.DbError("获取总行数失败。")
  119. return
  120. }
  121. err = TaskModel.Page(req.GetPage()).Order(orderBy).Fields("plat_task.*,plat_task_handle.step").Scan(&TaskList)
  122. return
  123. }
  124. // Export 导出数据
  125. func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent, err error) {
  126. var con model.ExportContent
  127. // 获取数据
  128. total, list, err := s.GetList(&req.SearchPlatTaskReq)
  129. if err != nil {
  130. return nil, err
  131. }
  132. //rsp.List
  133. f := excelize.NewFile()
  134. // Create a new sheet.
  135. index := f.NewSheet("Sheet1")
  136. for index, item := range req.Columns {
  137. sheetPosition := service.Div(index+1) + "1"
  138. f.SetCellValue("Sheet1", sheetPosition, item)
  139. }
  140. if total > 0 {
  141. // 构造用户和类型填充数据
  142. userMap := make(map[int]string, 0)
  143. typeMap := make(map[string]string, 0)
  144. users, err := s.Dao.DB.Model("sys_user").FindAll()
  145. if err != nil {
  146. return nil, err
  147. }
  148. types, err := s.Dao.DB.Model("sys_dict_data").Where("dict_type='TaskType'").FindAll()
  149. if err != nil {
  150. return nil, err
  151. }
  152. for _, item := range users {
  153. userMap[item["id"].Int()] = item["nick_name"].String()
  154. }
  155. for _, item := range types {
  156. typeMap[item["dict_value"].String()] = item["dict_label"].String()
  157. }
  158. // 构造excel数据
  159. for lineNum, item := range list {
  160. for index, value := range req.Columns {
  161. if value == "督办标题" {
  162. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskTitle)
  163. }
  164. if value == "督办类型" {
  165. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), typeMap[item.TaskType])
  166. }
  167. if value == "状态" {
  168. data := ""
  169. if item.TaskStatus == "10" {
  170. data = "发起"
  171. } else if item.TaskStatus == "20" {
  172. data = "进行中"
  173. } else if item.TaskStatus == "30" {
  174. data = "流程完成"
  175. }
  176. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
  177. }
  178. if value == "督办事项来源" {
  179. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.Source)
  180. }
  181. if value == "超期" {
  182. data := ""
  183. if gtime.Now().Format("Y-m-d H:i:s") <= item.TaskEndDate.Format("Y-m-d 23:59:59") {
  184. data = "否"
  185. } else {
  186. data = "是"
  187. }
  188. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
  189. }
  190. if value == "督办说明" {
  191. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskDesc)
  192. }
  193. if value == "关联对象" {
  194. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TargetName)
  195. }
  196. if value == "负责人" {
  197. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.MainUserId])
  198. }
  199. if value == "协办人" {
  200. names := ""
  201. if item.OwnerUserId != "" {
  202. ids := strings.Split(item.OwnerUserId, ",")
  203. for _, id := range ids {
  204. if names == "" {
  205. names = userMap[gconv.Int(id)]
  206. } else {
  207. names += "," + userMap[gconv.Int(id)]
  208. }
  209. }
  210. }
  211. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), names)
  212. }
  213. if value == "督办人" {
  214. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.SupervisorUserId])
  215. }
  216. if value == "发布时间" {
  217. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskStartDate.Format("Y-m-d"))
  218. }
  219. if value == "要求完成时间" {
  220. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskEndDate.Format("Y-m-d"))
  221. }
  222. if value == "创建时间" {
  223. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.CreatedTime.Format("Y-m-d H:i:s"))
  224. }
  225. }
  226. }
  227. }
  228. f.SetActiveSheet(index)
  229. var buffer *bytes.Buffer
  230. buffer, _ = f.WriteToBuffer()
  231. con.Content = buffer.Bytes()
  232. return &con, err
  233. }
  234. // Statistics 统计
  235. func (s *taskService) Statistics(req *model.SearchPlatTaskReq) (*model.TaskNumberCount, error) {
  236. var result model.TaskNumberCount
  237. // 是否超期
  238. where := ""
  239. // 是否超期(10否20是30全部(或为空查询全部))
  240. if req.IsOverdue == "20" {
  241. today := gtime.Now().Format("Y-m-d 00:00:00")
  242. where = fmt.Sprintf("plat_task.task_end_date < '%v' AND (plat_task.task_status='10' OR plat_task.task_status='20')", today)
  243. }
  244. // 统计数量
  245. 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())).Where(where).Group("plat_task.Id").Count()
  246. if err != nil {
  247. return nil, err
  248. }
  249. result.ToDoNumber = count
  250. return &result, nil
  251. }
  252. // StatisticsNumber 统计(主要统计超期数量)
  253. func (s *taskService) StatisticsNumber(req *model.SearchPlatTaskReq) (*model.TaskNumberCount, error) {
  254. var result model.TaskNumberCount
  255. // 是否超期
  256. where := ""
  257. orderBy := "plat_task.created_time DESC"
  258. // 是否超期(10否20是30全部(或为空查询全部))
  259. if req.IsOverdue == "20" {
  260. today := gtime.Now().Format("Y-m-d 00:00:00")
  261. where = fmt.Sprintf("plat_task.task_end_date < '%v' AND (plat_task.task_status='10' OR plat_task.task_status='20')", today)
  262. }
  263. if req.OperateType == "1" { // 我的待办
  264. orderBy = "plat_task.task_status ASC, plat_task.created_time DESC"
  265. if where == "" {
  266. 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())
  267. } else {
  268. where += fmt.Sprintf(" AND 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())
  269. }
  270. }
  271. // 统计数量
  272. count, err := s.Dao.InnerJoin("plat_task_handle", "plat_task.Id=plat_task_handle.task_id").Where(where).Order(orderBy).Group("plat_task.Id").Count()
  273. if err != nil {
  274. return nil, err
  275. }
  276. result.ToDoNumber = count
  277. return &result, nil
  278. }
  279. // Create 添加信息
  280. func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
  281. platTask := new(model.PlatTask)
  282. if err = gconv.Struct(req, platTask); err != nil {
  283. return
  284. }
  285. // 初始数据
  286. platTask.IsOverdue = "10" // 是否超期(10否20是)
  287. if platTask.TaskStartDate == nil || platTask.TaskStartDate.IsZero() {
  288. platTask.TaskStartDate = gtime.Now()
  289. }
  290. // 填充创建信息
  291. service.SetCreatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
  292. // 填充更新信息
  293. //service.SetUpdatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
  294. res, err := s.Dao.Insert(platTask)
  295. if err != nil {
  296. return
  297. }
  298. // 创建操作任务
  299. id, _ := res.LastInsertId()
  300. platTask.Id = int(id)
  301. err = s.startDingApproval(platTask)
  302. if err != nil {
  303. return
  304. }
  305. // 流程日志
  306. err = CreateTaskLog(s, nil, int(id), s.GetCxtUserId(), s.GetCxtUserName(), "创建督办", "创建督办成功", "")
  307. return
  308. }
  309. // AddTaskApproval 创建督办之后,需要钉钉审批才能生效
  310. func (s *taskService) AddTaskApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  311. task, err := s.Dao.Where("id = ?", flow.BizCode).FindOne()
  312. if err != nil {
  313. return fmt.Errorf("创建督办审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  314. }
  315. if err != nil {
  316. return err
  317. }
  318. if task == nil {
  319. return fmt.Errorf("督办不存在:%s Id: %d", flow.BizCode, flow.Id)
  320. }
  321. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  322. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  323. }
  324. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  325. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  326. }
  327. if msg.ProcessType == "terminate" {
  328. _, err = s.Dao.Update("task_status='50'", fmt.Sprintf("id='%v'", task.Id))
  329. if err != nil {
  330. return err
  331. }
  332. // 流程日志
  333. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "撤销", "")
  334. } else {
  335. if msg.Result == "agree" {
  336. nextHandle := createNextTaskHandel(s, task, 10)
  337. _, err = s.Dao.DB.Insert("plat_task_handle", nextHandle)
  338. if err != nil {
  339. return err
  340. }
  341. //// 发送消息通知
  342. //go taskNotifyMessage(task.MainUserId, task.OwnerUserId, fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  343. // 流程日志
  344. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "通过", "")
  345. } else if msg.Result == "refuse" {
  346. _, err = s.Dao.Update("task_status='40'", fmt.Sprintf("id='%v'", task.Id))
  347. if err != nil {
  348. return err
  349. }
  350. // 流程日志
  351. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "拒绝", "")
  352. }
  353. }
  354. return err
  355. }
  356. // ChangeStatus 修改状态
  357. func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
  358. data := ""
  359. where := fmt.Sprintf("id='%v'", req.TaskId)
  360. nodeName := "状态修改"
  361. desc := "修改成功"
  362. // 类型合规判断
  363. if req.Type == "TaskStatus" {
  364. data = fmt.Sprintf("task_status='%v'", req.NowStatus)
  365. nodeName = "状态修改"
  366. if req.NowStatus == "20" {
  367. desc = "关闭"
  368. data += fmt.Sprintf(",task_end_date='%v'", gtime.Now().Format("Y-m-d H:i:s"))
  369. }
  370. } else if req.Type == "IsOverdue" {
  371. nodeName = "超期状态修改"
  372. if req.NowStatus == "20" {
  373. desc = "超期"
  374. }
  375. data = fmt.Sprintf("is_overdue='%v'", req.NowStatus)
  376. } else {
  377. err = myerrors.TipsError("类型不匹配,请仔细检查。")
  378. return err
  379. }
  380. // 读取现有数据
  381. task, err := s.Dao.Where(where).FindOne()
  382. if err != nil {
  383. return err
  384. }
  385. if task == nil {
  386. err = myerrors.TipsError("数据异常,无匹配数据。")
  387. return err
  388. }
  389. // 状态数据一致性判断
  390. if (req.Type == "TaskStatus" && task.TaskStatus != req.OldStatus) || (req.Type == "IsOverdue" && task.IsOverdue != req.OldStatus) {
  391. err = myerrors.TipsError("状态不匹配,进行该操作")
  392. return err
  393. }
  394. // 更新数据
  395. _, err = s.Dao.Update(data, where)
  396. if err != nil {
  397. return
  398. }
  399. // 流程日志
  400. taskId, _ := strconv.Atoi(req.TaskId)
  401. err = CreateTaskLog(s, nil, taskId, s.GetCxtUserId(), s.GetCxtUserName(), nodeName, desc, "")
  402. return
  403. }
  404. // Handle 督办任务处理
  405. //步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  406. func (s *taskService) Handle(req *model.HandleReq) (err error) {
  407. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  408. // 处理结果(10接收20提交30审批通过40审批退回)
  409. logNodeName := ""
  410. logDesc := ""
  411. var taskHandle model.PlatTaskHandle
  412. if req.Step != 15 {
  413. 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.TaskId, req.Step, s.GetCxtUserId(), s.GetCxtUserId())).Scan(&taskHandle)
  414. if err != nil {
  415. if err == sql.ErrNoRows {
  416. err = myerrors.TipsError("数据不匹配,刷新数据重试")
  417. return err
  418. }
  419. return err
  420. }
  421. }
  422. now := gtime.Now()
  423. // 数据暂存,不做任何流程修改
  424. if req.Step == 15 {
  425. // 暂存
  426. logNodeName = "暂存"
  427. logDesc = s.GetCxtUserName() + "暂存进展信息"
  428. // 更新进展数据
  429. err = s.saveProgressList(req, now)
  430. if err != nil {
  431. return err
  432. }
  433. } else {
  434. var nextHandle = new(model.PlatTaskHandle)
  435. task, err := s.Dao.Where("id", req.TaskId).FindOne()
  436. if err != nil {
  437. return err
  438. }
  439. if task == nil {
  440. err = myerrors.TipsError("数据异常,无匹配数据")
  441. return err
  442. }
  443. // 构造更新数据
  444. handleData := g.Map{
  445. "task_status": "20",
  446. "handle_user_id": s.GetCxtUserId(),
  447. "handle_date": now.Format("Y-m-d H:i:s"),
  448. "handle_status": req.HandleStatus,
  449. "handle_desc": req.HandleDesc,
  450. "updated_by": s.GetCxtUserId(),
  451. "updated_name": s.GetCxtUserName(),
  452. "updated_time": now.Format("Y-m-d H:i:s"),
  453. }
  454. taskData := g.Map{
  455. "updated_by": s.GetCxtUserId(),
  456. "updated_name": s.GetCxtUserName(),
  457. "updated_time": now.Format("Y-m-d H:i:s"),
  458. }
  459. // 督办任务接收
  460. if req.Step == 10 {
  461. // 接收任务
  462. taskData["task_status"] = "20"
  463. taskData["receive_date"] = now.Format("Y-m-d H:i:s")
  464. nextHandle = createNextTaskHandel(s, task, 20)
  465. logNodeName = "接收"
  466. logDesc = s.GetCxtUserName() + "接收督办任务"
  467. } else if req.Step == 20 {
  468. // 提交数据
  469. nextHandle = createNextTaskHandel(s, task, 30)
  470. logNodeName = "提交"
  471. logDesc = s.GetCxtUserName() + "提交督办任务"
  472. // 更新进展数据
  473. err = s.saveProgressList(req, now)
  474. if err != nil {
  475. return err
  476. }
  477. } else if req.Step == 30 {
  478. // 督办人审批
  479. taskData["approver_id"] = s.GetCxtUserId()
  480. taskData["appro_date"] = now.Format("Y-m-d H:i:s")
  481. taskData["appro_status"] = req.HandleStatus
  482. taskData["appro_desc"] = req.HandleDesc
  483. logNodeName = "审批"
  484. if req.HandleStatus == "30" {
  485. logDesc = s.GetCxtUserName() + "审批通过"
  486. if req.IsComplete == "10" {
  487. // 任务完成
  488. nextHandle = createNextTaskHandel(s, task, 40)
  489. } else {
  490. // 任务未完成,继续执行
  491. nextHandle = createNextTaskHandel(s, task, 20)
  492. }
  493. } else if req.HandleStatus == "40" {
  494. logDesc = s.GetCxtUserName() + "审批退回"
  495. nextHandle = createNextTaskHandel(s, task, 20)
  496. }
  497. } else if req.Step == 40 {
  498. // 监办人评价
  499. taskData["evaluator_id"] = s.GetCxtUserId()
  500. taskData["evaluate_date"] = now.Format("Y-m-d H:i:s")
  501. taskData["evaluate_status"] = req.HandleStatus
  502. taskData["evaluate_desc"] = req.HandleDesc
  503. logNodeName = "评价"
  504. if req.HandleStatus == "30" {
  505. // 监办人评价,审批通过,任务结束
  506. logDesc = s.GetCxtUserName() + "审批通过"
  507. if req.IsComplete == "10" {
  508. // 任务完成
  509. nextHandle = nil
  510. taskData["actual_close_date"] = now.Format("Y-m-d H:i:s")
  511. taskData["task_status"] = "30"
  512. } else {
  513. // 任务未完成,继续执行
  514. nextHandle = createNextTaskHandel(s, task, 20)
  515. }
  516. } else if req.HandleStatus == "40" {
  517. logDesc = s.GetCxtUserName() + "审批退回"
  518. nextHandle = createNextTaskHandel(s, task, 20)
  519. }
  520. } else {
  521. err = myerrors.TipsError("未知步骤,无法操作")
  522. return err
  523. }
  524. // 更新数据
  525. // 更新督办任务数据
  526. _, err = s.Dao.Update(taskData, fmt.Sprintf("id='%v'", req.TaskId))
  527. if err != nil {
  528. return err
  529. }
  530. // 更新任务数据
  531. _, err = s.Dao.DB.Update("plat_task_handle", handleData, fmt.Sprintf("ID='%v'", taskHandle.ID))
  532. if err != nil {
  533. return err
  534. }
  535. // 创建下一条任务
  536. if nextHandle != nil {
  537. _, err = s.Dao.DB.Save("plat_task_handle", nextHandle)
  538. if err != nil {
  539. return err
  540. }
  541. // 只有督办、监办人需要发送提醒
  542. if req.Step == 20 {
  543. go taskNotifyMessage(task.SupervisorUserId, "", fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  544. } else if req.Step == 30 && req.HandleStatus == "30" {
  545. go taskNotifyMessage(task.WatchUserId, "", fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  546. }
  547. }
  548. }
  549. // 流程日志
  550. err = CreateTaskLog(s, nil, req.TaskId, s.GetCxtUserId(), s.GetCxtUserName(), logNodeName, logDesc, "")
  551. if err != nil {
  552. return err
  553. }
  554. return nil
  555. }
  556. // CreateTaskLog 任务日志创建方法
  557. func CreateTaskLog(s1 *taskService, s2 *taskProgressService, taskId, userId int, userName, nodeName, desc, remark string) (err error) {
  558. var log model.PlatTaskLog
  559. startTime := gtime.Now()
  560. endTime := startTime
  561. // 默认为当前时间,然后随已有日志情况进行更新
  562. if s1 != nil {
  563. logs, err := s1.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  564. if err != nil && err != sql.ErrNoRows {
  565. return err
  566. }
  567. if len(logs) > 0 {
  568. startTime = logs[0]["end_time"].GTime()
  569. }
  570. } else {
  571. logs, err := s2.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  572. if err != nil && err != sql.ErrNoRows {
  573. return err
  574. }
  575. if len(logs) > 0 {
  576. startTime = logs[0]["end_time"].GTime()
  577. }
  578. }
  579. // 填入日志相关数据
  580. log.TaskId = taskId
  581. log.NodeName = nodeName
  582. log.Desc = desc
  583. log.StartTime = startTime
  584. log.EndTime = endTime
  585. log.Remark = remark
  586. log.CreatedTime = endTime
  587. log.CreatedName = userName
  588. log.CreatedBy = userId
  589. if s1 != nil {
  590. _, err = s1.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  591. } else {
  592. _, err = s2.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  593. }
  594. return err
  595. }
  596. // 创建个人的督办任务(其中,暂存不会生成个人任务,不会改变任何东西,只会新增一条日志)
  597. func createNextTaskHandel(s *taskService, task *model.PlatTask, step int) *model.PlatTaskHandle {
  598. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  599. var personTask model.PlatTaskHandle
  600. personTask.TaskId = task.Id
  601. personTask.TaskStatus = "10"
  602. personTask.Step = step
  603. // 督办任务为发起时
  604. if step == 10 {
  605. personTask.MainUserId = task.MainUserId
  606. personTask.OwnerUserId = task.OwnerUserId
  607. } else if step == 20 {
  608. // 创建提交任务
  609. personTask.MainUserId = task.MainUserId
  610. personTask.OwnerUserId = task.OwnerUserId
  611. } else if step == 30 {
  612. // 提交给督办人审批
  613. personTask.MainUserId = task.SupervisorUserId
  614. } else if step == 40 {
  615. // 提交给监办人评价
  616. personTask.MainUserId = task.WatchUserId
  617. }
  618. // 填充创建信息
  619. service.SetCreatedInfo(&personTask, s.GetCxtUserId(), s.GetCxtUserName())
  620. return &personTask
  621. }
  622. func (s *taskService) startDingApproval(task *model.PlatTask) error {
  623. dictMap := make(map[string]string, 0)
  624. userMap := make(map[int]string, 0)
  625. teamNames := ""
  626. dicts, err := s.Dao.DB.Model("sys_dict_data").Where("dict_type = 'plat_task_source'").FindAll()
  627. if err != nil && err != sql.ErrNoRows {
  628. return err
  629. }
  630. if len(dicts) == 0 {
  631. return errors.New("督办来源数据缺失,请前往配置")
  632. }
  633. for _, dict := range dicts {
  634. dictMap[dict["dict_value"].String()] = dict["dict_label"].String()
  635. }
  636. users, err := s.Dao.DB.Model("sys_user").FindAll()
  637. if err != nil && err != sql.ErrNoRows {
  638. return err
  639. }
  640. if len(users) == 0 {
  641. return errors.New("用户数据数据缺失,请前往配置")
  642. }
  643. for _, user := range users {
  644. userMap[user["id"].Int()] = user["nick_name"].String()
  645. }
  646. if task.OwnerUserId != "" {
  647. ids := strings.Split(task.OwnerUserId, ",")
  648. for _, id := range ids {
  649. if teamNames == "" {
  650. teamNames = userMap[gconv.Int(id)]
  651. } else {
  652. teamNames += "," + userMap[gconv.Int(id)]
  653. }
  654. }
  655. }
  656. workflowSrv, err := workflowService.NewFlowService(s.Ctx)
  657. if err != nil {
  658. return err
  659. }
  660. _, err = workflowSrv.StartProcessInstance(gconv.String(task.Id), "40", "", &workflow.StartProcessInstanceRequest{
  661. ProcessCode: &PlatTaskApprovalProcessCode,
  662. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  663. {
  664. Id: utils.String("TextField-K2AD4O5B"),
  665. Name: utils.String("督办标题"),
  666. Value: utils.String(task.TaskTitle),
  667. },
  668. {
  669. Id: utils.String("DDDateField_C7LJMHNU6N40"),
  670. Name: utils.String("发布时间"),
  671. Value: utils.String(task.CreatedTime.Format("Y-m-d")),
  672. },
  673. {
  674. Id: utils.String("DDSelectField_OF3POKFZ43K"),
  675. Name: utils.String("督办来源"),
  676. Value: utils.String(dictMap[task.Source]),
  677. },
  678. {
  679. Id: utils.String("TextField_VPO2N6I4N5S0"),
  680. Name: utils.String("督办内容"),
  681. Value: utils.String(task.TaskDesc),
  682. },
  683. {
  684. Id: utils.String("DDAttachment_18RP41VRTITC0"),
  685. Name: utils.String("附件"),
  686. Value: utils.String(""),
  687. },
  688. {
  689. Id: utils.String("DDPhotoField_11WXOUDIZ85C0"),
  690. Name: utils.String("图片"),
  691. Value: utils.String(""),
  692. },
  693. {
  694. Id: utils.String("TextField_1ER7VNEEGU0W0"),
  695. Name: utils.String("督办人"),
  696. Value: utils.String(userMap[task.SupervisorUserId]),
  697. },
  698. {
  699. Id: utils.String("TextField_OKAEW6GD2FK0"),
  700. Name: utils.String("监办人"),
  701. Value: utils.String(userMap[task.WatchUserId]),
  702. },
  703. {
  704. Id: utils.String("TextField_G97RO96HMXK0"),
  705. Name: utils.String("被督办人"),
  706. Value: utils.String(userMap[task.MainUserId]),
  707. },
  708. {
  709. Id: utils.String("TextField_1FKS6CUW7REO0"),
  710. Name: utils.String("共同完成人"),
  711. Value: utils.String(teamNames),
  712. },
  713. {
  714. Id: utils.String("DDDateField_T9YBZCDTB680"),
  715. Name: utils.String("要求完成时间"),
  716. Value: utils.String(task.TaskEndDate.Format("Y-m-d")),
  717. },
  718. {
  719. Id: utils.String("TextField_LMV0Q71JD5C0"),
  720. Name: utils.String("备注"),
  721. Value: utils.String(task.Remark),
  722. },
  723. },
  724. })
  725. if err != nil {
  726. return err
  727. }
  728. return err
  729. }
  730. // 处理暂存、提交任务进展
  731. func (s *taskService) saveProgressList(req *model.HandleReq, now *gtime.Time) (err error) {
  732. ids := ""
  733. deleteWhere := fmt.Sprintf("task_id='%v'", req.TaskId)
  734. for index, progress := range req.ProgressList {
  735. if progress.Id != 0 {
  736. if ids == "" {
  737. ids = fmt.Sprintf("%v", progress.Id)
  738. } else {
  739. ids += fmt.Sprintf(",%v", progress.Id)
  740. }
  741. }
  742. req.ProgressList[index].TaskId = req.TaskId
  743. // 填充创建信息
  744. if progress.CreatedBy == 0 {
  745. service.SetCreatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  746. }
  747. // 填充更新信息
  748. service.SetUpdatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  749. }
  750. if ids != "" {
  751. deleteWhere += fmt.Sprintf(" AND ID NOT IN (%v)", ids)
  752. }
  753. // 保存督办进展
  754. // 1 标记删除旧的进展数据
  755. _, err = s.Dao.DB.Update("plat_task_progress", fmt.Sprintf("deleted_time='%v'", now.Format("Y-m-d H:i:s")), deleteWhere)
  756. if err != nil {
  757. return err
  758. }
  759. // 2 保存新的数据
  760. if len(req.ProgressList) > 0 {
  761. _, err = s.Dao.DB.Save("plat_task_progress", req.ProgressList)
  762. if err != nil {
  763. return err
  764. }
  765. }
  766. return nil
  767. }