plat_task.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  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. // 流程日志
  302. err = CreateTaskLog(s, nil, int(id), s.GetCxtUserId(), s.GetCxtUserName(), "创建督办", "创建督办成功", "")
  303. nextHandle := createNextTaskHandel(s, platTask, 10)
  304. _, err = s.Dao.DB.Insert("plat_task_handle", nextHandle)
  305. if err != nil {
  306. return err
  307. }
  308. // 流程日志
  309. err = CreateTaskLog(s, nil, platTask.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "通过", "")
  310. return
  311. }
  312. // AddTaskApproval 创建督办之后,需要钉钉审批才能生效
  313. func (s *taskService) AddTaskApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  314. task, err := s.Dao.Where("id = ?", flow.BizCode).FindOne()
  315. if err != nil {
  316. return fmt.Errorf("创建督办审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  317. }
  318. if err != nil {
  319. return err
  320. }
  321. if task == nil {
  322. return fmt.Errorf("督办不存在:%s Id: %d", flow.BizCode, flow.Id)
  323. }
  324. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  325. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  326. }
  327. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  328. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  329. }
  330. if msg.ProcessType == "terminate" {
  331. _, err = s.Dao.Update("task_status='50'", fmt.Sprintf("id='%v'", task.Id))
  332. if err != nil {
  333. return err
  334. }
  335. // 流程日志
  336. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "撤销", "")
  337. } else {
  338. if msg.Result == "agree" {
  339. nextHandle := createNextTaskHandel(s, task, 10)
  340. _, err = s.Dao.DB.Insert("plat_task_handle", nextHandle)
  341. if err != nil {
  342. return err
  343. }
  344. //// 发送消息通知
  345. //go taskNotifyMessage(task.MainUserId, task.OwnerUserId, fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  346. // 流程日志
  347. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "通过", "")
  348. } else if msg.Result == "refuse" {
  349. _, err = s.Dao.Update("task_status='40'", fmt.Sprintf("id='%v'", task.Id))
  350. if err != nil {
  351. return err
  352. }
  353. // 流程日志
  354. err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "拒绝", "")
  355. }
  356. }
  357. return err
  358. }
  359. // ChangeStatus 修改状态
  360. func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
  361. data := ""
  362. where := fmt.Sprintf("id='%v'", req.TaskId)
  363. nodeName := "状态修改"
  364. desc := "修改成功"
  365. // 类型合规判断
  366. if req.Type == "TaskStatus" {
  367. data = fmt.Sprintf("task_status='%v'", req.NowStatus)
  368. nodeName = "状态修改"
  369. if req.NowStatus == "20" {
  370. desc = "关闭"
  371. data += fmt.Sprintf(",task_end_date='%v'", gtime.Now().Format("Y-m-d H:i:s"))
  372. }
  373. } else if req.Type == "IsOverdue" {
  374. nodeName = "超期状态修改"
  375. if req.NowStatus == "20" {
  376. desc = "超期"
  377. }
  378. data = fmt.Sprintf("is_overdue='%v'", req.NowStatus)
  379. } else {
  380. err = myerrors.TipsError("类型不匹配,请仔细检查。")
  381. return err
  382. }
  383. // 读取现有数据
  384. task, err := s.Dao.Where(where).FindOne()
  385. if err != nil {
  386. return err
  387. }
  388. if task == nil {
  389. err = myerrors.TipsError("数据异常,无匹配数据。")
  390. return err
  391. }
  392. // 状态数据一致性判断
  393. if (req.Type == "TaskStatus" && task.TaskStatus != req.OldStatus) || (req.Type == "IsOverdue" && task.IsOverdue != req.OldStatus) {
  394. err = myerrors.TipsError("状态不匹配,进行该操作")
  395. return err
  396. }
  397. // 更新数据
  398. _, err = s.Dao.Update(data, where)
  399. if err != nil {
  400. return
  401. }
  402. // 流程日志
  403. taskId, _ := strconv.Atoi(req.TaskId)
  404. err = CreateTaskLog(s, nil, taskId, s.GetCxtUserId(), s.GetCxtUserName(), nodeName, desc, "")
  405. return
  406. }
  407. // Handle 督办任务处理
  408. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  409. func (s *taskService) Handle(req *model.HandleReq) (err error) {
  410. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  411. // 处理结果(10接收20提交30审批通过40审批退回)
  412. logNodeName := ""
  413. logDesc := ""
  414. var taskHandle model.PlatTaskHandle
  415. if req.Step != 15 {
  416. 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)
  417. if err != nil {
  418. if err == sql.ErrNoRows {
  419. err = myerrors.TipsError("数据不匹配,刷新数据重试")
  420. return err
  421. }
  422. return err
  423. }
  424. }
  425. now := gtime.Now()
  426. // 数据暂存,不做任何流程修改
  427. if req.Step == 15 {
  428. // 暂存
  429. logNodeName = "暂存"
  430. logDesc = s.GetCxtUserName() + "暂存进展信息"
  431. // 更新进展数据
  432. err = s.saveProgressList(req, now)
  433. if err != nil {
  434. return err
  435. }
  436. } else {
  437. var nextHandle = new(model.PlatTaskHandle)
  438. task, err := s.Dao.Where("id", req.TaskId).FindOne()
  439. if err != nil {
  440. return err
  441. }
  442. if task == nil {
  443. err = myerrors.TipsError("数据异常,无匹配数据")
  444. return err
  445. }
  446. // 构造更新数据
  447. handleData := g.Map{
  448. "task_status": "20",
  449. "handle_user_id": s.GetCxtUserId(),
  450. "handle_date": now.Format("Y-m-d H:i:s"),
  451. "handle_status": req.HandleStatus,
  452. "handle_desc": req.HandleDesc,
  453. "updated_by": s.GetCxtUserId(),
  454. "updated_name": s.GetCxtUserName(),
  455. "updated_time": now.Format("Y-m-d H:i:s"),
  456. }
  457. taskData := g.Map{
  458. "updated_by": s.GetCxtUserId(),
  459. "updated_name": s.GetCxtUserName(),
  460. "updated_time": now.Format("Y-m-d H:i:s"),
  461. }
  462. // 督办任务接收
  463. if req.Step == 10 {
  464. // 接收任务
  465. taskData["task_status"] = "20"
  466. taskData["receive_date"] = now.Format("Y-m-d H:i:s")
  467. nextHandle = createNextTaskHandel(s, task, 20)
  468. logNodeName = "接收"
  469. logDesc = s.GetCxtUserName() + "接收督办任务"
  470. } else if req.Step == 20 {
  471. // 提交数据
  472. nextHandle = createNextTaskHandel(s, task, 30)
  473. logNodeName = "提交"
  474. logDesc = s.GetCxtUserName() + "提交督办任务"
  475. // 更新进展数据
  476. err = s.saveProgressList(req, now)
  477. if err != nil {
  478. return err
  479. }
  480. } else if req.Step == 30 {
  481. // 督办人审批
  482. taskData["approver_id"] = s.GetCxtUserId()
  483. taskData["appro_date"] = now.Format("Y-m-d H:i:s")
  484. taskData["appro_status"] = req.HandleStatus
  485. taskData["appro_desc"] = req.HandleDesc
  486. logNodeName = "审批"
  487. if req.HandleStatus == "30" {
  488. logDesc = s.GetCxtUserName() + "审批通过"
  489. if req.IsComplete == "10" {
  490. // 任务完成
  491. nextHandle = createNextTaskHandel(s, task, 40)
  492. } else {
  493. // 任务未完成,继续执行
  494. nextHandle = createNextTaskHandel(s, task, 20)
  495. }
  496. } else if req.HandleStatus == "40" {
  497. logDesc = s.GetCxtUserName() + "审批退回"
  498. nextHandle = createNextTaskHandel(s, task, 20)
  499. }
  500. } else if req.Step == 40 {
  501. // 监办人评价
  502. taskData["evaluator_id"] = s.GetCxtUserId()
  503. taskData["evaluate_date"] = now.Format("Y-m-d H:i:s")
  504. taskData["evaluate_status"] = req.HandleStatus
  505. taskData["evaluate_desc"] = req.HandleDesc
  506. logNodeName = "评价"
  507. if req.HandleStatus == "30" {
  508. // 监办人评价,审批通过,任务结束
  509. logDesc = s.GetCxtUserName() + "审批通过"
  510. if req.IsComplete == "10" {
  511. // 任务完成
  512. nextHandle = nil
  513. taskData["actual_close_date"] = now.Format("Y-m-d H:i:s")
  514. taskData["task_status"] = "30"
  515. } else {
  516. // 任务未完成,继续执行
  517. nextHandle = createNextTaskHandel(s, task, 20)
  518. }
  519. } else if req.HandleStatus == "40" {
  520. logDesc = s.GetCxtUserName() + "审批退回"
  521. nextHandle = createNextTaskHandel(s, task, 20)
  522. }
  523. } else {
  524. err = myerrors.TipsError("未知步骤,无法操作")
  525. return err
  526. }
  527. // 更新数据
  528. // 更新督办任务数据
  529. _, err = s.Dao.Update(taskData, fmt.Sprintf("id='%v'", req.TaskId))
  530. if err != nil {
  531. return err
  532. }
  533. // 更新任务数据
  534. _, err = s.Dao.DB.Update("plat_task_handle", handleData, fmt.Sprintf("ID='%v'", taskHandle.ID))
  535. if err != nil {
  536. return err
  537. }
  538. // 创建下一条任务
  539. if nextHandle != nil {
  540. _, err = s.Dao.DB.Save("plat_task_handle", nextHandle)
  541. if err != nil {
  542. return err
  543. }
  544. // 只有督办、监办人需要发送提醒
  545. if req.Step == 20 {
  546. go taskNotifyMessage(task.SupervisorUserId, "", fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  547. } else if req.Step == 30 && req.HandleStatus == "30" {
  548. go taskNotifyMessage(task.WatchUserId, "", fmt.Sprintf("%v督办任务需要处理", task.TaskTitle))
  549. }
  550. }
  551. }
  552. // 流程日志
  553. err = CreateTaskLog(s, nil, req.TaskId, s.GetCxtUserId(), s.GetCxtUserName(), logNodeName, logDesc, "")
  554. if err != nil {
  555. return err
  556. }
  557. return nil
  558. }
  559. // CreateTaskLog 任务日志创建方法
  560. func CreateTaskLog(s1 *taskService, s2 *taskProgressService, taskId, userId int, userName, nodeName, desc, remark string) (err error) {
  561. var log model.PlatTaskLog
  562. startTime := gtime.Now()
  563. endTime := startTime
  564. // 默认为当前时间,然后随已有日志情况进行更新
  565. if s1 != nil {
  566. logs, err := s1.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  567. if err != nil && err != sql.ErrNoRows {
  568. return err
  569. }
  570. if len(logs) > 0 {
  571. startTime = logs[0]["end_time"].GTime()
  572. }
  573. } else {
  574. logs, err := s2.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
  575. if err != nil && err != sql.ErrNoRows {
  576. return err
  577. }
  578. if len(logs) > 0 {
  579. startTime = logs[0]["end_time"].GTime()
  580. }
  581. }
  582. // 填入日志相关数据
  583. log.TaskId = taskId
  584. log.NodeName = nodeName
  585. log.Desc = desc
  586. log.StartTime = startTime
  587. log.EndTime = endTime
  588. log.Remark = remark
  589. log.CreatedTime = endTime
  590. log.CreatedName = userName
  591. log.CreatedBy = userId
  592. if s1 != nil {
  593. _, err = s1.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  594. } else {
  595. _, err = s2.Dao.DB.Save(plat.PlatTaskLog.Table, log)
  596. }
  597. return err
  598. }
  599. // 创建个人的督办任务(其中,暂存不会生成个人任务,不会改变任何东西,只会新增一条日志)
  600. func createNextTaskHandel(s *taskService, task *model.PlatTask, step int) *model.PlatTaskHandle {
  601. // 步骤号(10接收 15暂存 20提交 30审批(督办人) 40评价(监办人))
  602. var personTask model.PlatTaskHandle
  603. personTask.TaskId = task.Id
  604. personTask.TaskStatus = "10"
  605. personTask.Step = step
  606. // 督办任务为发起时
  607. if step == 10 {
  608. personTask.MainUserId = task.MainUserId
  609. personTask.OwnerUserId = task.OwnerUserId
  610. } else if step == 20 {
  611. // 创建提交任务
  612. personTask.MainUserId = task.MainUserId
  613. personTask.OwnerUserId = task.OwnerUserId
  614. } else if step == 30 {
  615. // 提交给督办人审批
  616. personTask.MainUserId = task.SupervisorUserId
  617. } else if step == 40 {
  618. // 提交给监办人评价
  619. personTask.MainUserId = task.WatchUserId
  620. }
  621. // 填充创建信息
  622. service.SetCreatedInfo(&personTask, s.GetCxtUserId(), s.GetCxtUserName())
  623. return &personTask
  624. }
  625. func (s *taskService) startDingApproval(task *model.PlatTask) error {
  626. dictMap := make(map[string]string, 0)
  627. userMap := make(map[int]string, 0)
  628. teamNames := ""
  629. dicts, err := s.Dao.DB.Model("sys_dict_data").Where("dict_type = 'plat_task_source'").FindAll()
  630. if err != nil && err != sql.ErrNoRows {
  631. return err
  632. }
  633. if len(dicts) == 0 {
  634. return errors.New("督办来源数据缺失,请前往配置")
  635. }
  636. for _, dict := range dicts {
  637. dictMap[dict["dict_value"].String()] = dict["dict_label"].String()
  638. }
  639. users, err := s.Dao.DB.Model("sys_user").FindAll()
  640. if err != nil && err != sql.ErrNoRows {
  641. return err
  642. }
  643. if len(users) == 0 {
  644. return errors.New("用户数据数据缺失,请前往配置")
  645. }
  646. for _, user := range users {
  647. userMap[user["id"].Int()] = user["nick_name"].String()
  648. }
  649. if task.OwnerUserId != "" {
  650. ids := strings.Split(task.OwnerUserId, ",")
  651. for _, id := range ids {
  652. if teamNames == "" {
  653. teamNames = userMap[gconv.Int(id)]
  654. } else {
  655. teamNames += "," + userMap[gconv.Int(id)]
  656. }
  657. }
  658. }
  659. workflowSrv, err := workflowService.NewFlowService(s.Ctx)
  660. if err != nil {
  661. return err
  662. }
  663. _, err = workflowSrv.StartProcessInstance(gconv.String(task.Id), "40", "", &workflow.StartProcessInstanceRequest{
  664. ProcessCode: &PlatTaskApprovalProcessCode,
  665. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  666. {
  667. Id: utils.String("TextField-K2AD4O5B"),
  668. Name: utils.String("督办标题"),
  669. Value: utils.String(task.TaskTitle),
  670. },
  671. {
  672. Id: utils.String("DDDateField_C7LJMHNU6N40"),
  673. Name: utils.String("发布时间"),
  674. Value: utils.String(task.CreatedTime.Format("Y-m-d")),
  675. },
  676. {
  677. Id: utils.String("DDSelectField_OF3POKFZ43K"),
  678. Name: utils.String("督办来源"),
  679. Value: utils.String(dictMap[task.Source]),
  680. },
  681. {
  682. Id: utils.String("TextField_VPO2N6I4N5S0"),
  683. Name: utils.String("督办内容"),
  684. Value: utils.String(task.TaskDesc),
  685. },
  686. {
  687. Id: utils.String("DDAttachment_18RP41VRTITC0"),
  688. Name: utils.String("附件"),
  689. Value: utils.String(""),
  690. },
  691. {
  692. Id: utils.String("DDPhotoField_11WXOUDIZ85C0"),
  693. Name: utils.String("图片"),
  694. Value: utils.String(""),
  695. },
  696. {
  697. Id: utils.String("TextField_1ER7VNEEGU0W0"),
  698. Name: utils.String("督办人"),
  699. Value: utils.String(userMap[task.SupervisorUserId]),
  700. },
  701. {
  702. Id: utils.String("TextField_OKAEW6GD2FK0"),
  703. Name: utils.String("监办人"),
  704. Value: utils.String(userMap[task.WatchUserId]),
  705. },
  706. {
  707. Id: utils.String("TextField_G97RO96HMXK0"),
  708. Name: utils.String("被督办人"),
  709. Value: utils.String(userMap[task.MainUserId]),
  710. },
  711. {
  712. Id: utils.String("TextField_1FKS6CUW7REO0"),
  713. Name: utils.String("共同完成人"),
  714. Value: utils.String(teamNames),
  715. },
  716. {
  717. Id: utils.String("DDDateField_T9YBZCDTB680"),
  718. Name: utils.String("要求完成时间"),
  719. Value: utils.String(task.TaskEndDate.Format("Y-m-d")),
  720. },
  721. {
  722. Id: utils.String("TextField_LMV0Q71JD5C0"),
  723. Name: utils.String("备注"),
  724. Value: utils.String(task.Remark),
  725. },
  726. },
  727. })
  728. if err != nil {
  729. return err
  730. }
  731. return err
  732. }
  733. // 处理暂存、提交任务进展
  734. func (s *taskService) saveProgressList(req *model.HandleReq, now *gtime.Time) (err error) {
  735. ids := ""
  736. deleteWhere := fmt.Sprintf("task_id='%v'", req.TaskId)
  737. for index, progress := range req.ProgressList {
  738. if progress.Id != 0 {
  739. if ids == "" {
  740. ids = fmt.Sprintf("%v", progress.Id)
  741. } else {
  742. ids += fmt.Sprintf(",%v", progress.Id)
  743. }
  744. }
  745. req.ProgressList[index].TaskId = req.TaskId
  746. // 填充创建信息
  747. if progress.CreatedBy == 0 {
  748. service.SetCreatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  749. }
  750. // 填充更新信息
  751. service.SetUpdatedInfo(req.ProgressList[index], s.GetCxtUserId(), s.GetCxtUserName())
  752. }
  753. if ids != "" {
  754. deleteWhere += fmt.Sprintf(" AND ID NOT IN (%v)", ids)
  755. }
  756. // 保存督办进展
  757. // 1 标记删除旧的进展数据
  758. _, err = s.Dao.DB.Update("plat_task_progress", fmt.Sprintf("deleted_time='%v'", now.Format("Y-m-d H:i:s")), deleteWhere)
  759. if err != nil {
  760. return err
  761. }
  762. // 2 保存新的数据
  763. if len(req.ProgressList) > 0 {
  764. _, err = s.Dao.DB.Save("plat_task_progress", req.ProgressList)
  765. if err != nil {
  766. return err
  767. }
  768. }
  769. return nil
  770. }