新增钉钉待办

This commit is contained in:
jinqiming 2021-11-03 17:52:18 +08:00
parent e0dc08763d
commit c818f73f79
23 changed files with 833 additions and 630 deletions

View File

@ -32,7 +32,7 @@
<velocity.version>1.7</velocity.version>
<flowable.version>6.4.1</flowable.version>
<dingtalk.version>dingtalk-SNAPSHOT</dingtalk.version>
<aliyun.dingtalk.version>1.1.10</aliyun.dingtalk.version>
<aliyun.dingtalk.version>1.1.94</aliyun.dingtalk.version>
<hutool.version>5.4.2</hutool.version>
<commons.lang3.version>3.11</commons.lang3.version>
<com.alipay.sdk.version>3.7.4.ALL</com.alipay.sdk.version>

View File

@ -1,37 +1,31 @@
package com.snow.web.controller.system;
import java.util.List;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.snow.common.annotation.Log;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.core.page.TableDataInfo;
import com.snow.common.enums.BusinessType;
import com.snow.common.utils.poi.ExcelUtil;
import com.snow.framework.excel.FinanceAlipayFlowListener;
import com.snow.framework.excel.FinanceWeChartFlowListener;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.FinanceAlipayFlow;
import com.snow.system.domain.FinanceAlipayFlowImport;
import com.snow.system.domain.FinanceWeChatFlowImport;
import com.snow.system.domain.SysUser;
import com.snow.system.mapper.FinanceAlipayFlowMapper;
import com.snow.system.mapper.SysUserMapper;
import com.snow.system.service.IFinanceAlipayFlowService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.snow.common.annotation.Log;
import com.snow.common.enums.BusinessType;
import com.snow.system.domain.FinanceAlipayFlow;
import com.snow.system.service.IFinanceAlipayFlowService;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.utils.poi.ExcelUtil;
import com.snow.common.core.page.TableDataInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 财务支付宝流水Controller
*

View File

@ -4,6 +4,8 @@ import java.util.Date;
import java.util.List;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.snow.common.enums.DingFlowTaskType;
@ -54,7 +56,7 @@ public class SysOaTaskController extends BaseController
@GetMapping()
public String task()
{
return prefix + "/task1";
return prefix + "/task";
}
/**
@ -131,6 +133,7 @@ public class SysOaTaskController extends BaseController
startPage();
SysUser sysUser = ShiroUtils.getSysUser();
sysOaTaskDistribute.setTaskExecuteId(String.valueOf(sysUser.getUserId()));
sysOaTaskDistribute.setTaskExecuteStatus(DingFlowTaskType.COMPLETED.getCode());
List<SysOaTaskDistribute> sysOaTaskDistributes = sysOaTaskDistributeService.selectSysOaTaskDistributeList(sysOaTaskDistribute);
if(CollUtil.isNotEmpty(sysOaTaskDistributes)){
warpSysOaTask(sysOaTaskDistributes);
@ -268,6 +271,22 @@ public class SysOaTaskController extends BaseController
return prefix + "/detail";
}
/**
* 我处理的详情
* @param taskNo
* @param mmap
* @return
*/
@GetMapping("/taskDistributedDetail/{id}")
@RequiresPermissions("system:task:taskDistributedDetail")
public String taskDistributedDetail(@PathVariable("id") Long id, ModelMap mmap)
{
SysOaTaskDistribute sysOaTaskDistribute = sysOaTaskDistributeService.selectSysOaTaskDistributeById(id);
warpSysOaTask(Lists.newArrayList(sysOaTaskDistribute));
mmap.put("sysOaTask", sysOaTaskDistribute);
return prefix + "/taskDistributedDetail";
}
/**
* 任务分配详情
* @param id
@ -294,6 +313,9 @@ public class SysOaTaskController extends BaseController
if(ObjectUtil.isNotNull(t.getTaskExecuteId())){
t.setTaskExecuteId(sysUserService.selectUserById(Long.parseLong(t.getTaskExecuteId())).getUserName());
}
if(ObjectUtil.isNotNull(t.getTaskStartTime())&&ObjectUtil.isNotNull(t.getTaskCompleteTime())){
t.setSpendTime(DateUtil.formatBetween(t.getTaskStartTime(),t.getTaskCompleteTime(), BetweenFormater.Level.SECOND));
}
t.setSysOaTask(sysOaTask);
t.setCreateBy(sysUserService.selectUserById(Long.parseLong(t.getCreateBy())).getUserName());
});

View File

@ -1,84 +1,260 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('系统任务列表')" />
<th:block th:include="include :: header('任务中心')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>任务名称:</label>
<input type="text" name="taskName"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskStatus" th:with="type=${@dict.getType('ding_task_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<label>任务类型:</label>
<select name="taskType" th:with="type=${@dict.getType('sys_task_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<!-- <li>
<label>任务来源:</label>
<input type="text" name="taskSource"/>
</li>-->
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="wrapper wrapper-content animated fadeIn">
<div class="row m-b-lg ">
<div class="col-sm-12">
<div class="tabs-container">
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:task:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:task:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:task:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:task:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
<div class="tabs-left">
<ul class="nav nav-tabs">
<li class="active">
<a data-toggle="tab" href="#tab-1"> 待处理 <span class="label label-info pull-right"></span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-2"> 我创建 <span class="label label-info pull-right" ></span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-3"> 已处理 <span class="label label-info pull-right" ></span></a>
</li>
</ul>
<div class="tab-content ">
<div id="tab-1" class="tab-pane active">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="formId3">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="myTaskNo"/>
</li>
<li>
<label>任务名称:</label>
<input type="text" name="taskName" id="myTaskName"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskStatus" id="myTaskStatus" th:with="type=${@dict.getType('ding_task_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('formId3','bootstrap-table3')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('formId3','bootstrap-table3')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar1" role="group">
<a class="btn btn-warning" onclick="$.table.exportExcel('formId3')" shiro:hasPermission="system:task:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table3"></table>
</div>
</div>
</div>
<div id="tab-2" class="tab-pane">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="myformId">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="taskNo"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskStatus" id="taskStatus" th:with="type=${@dict.getType('ding_task_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('myformId','bootstrap-table1')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('myformId','bootstrap-table1')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar2" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:task:edit">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:task:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table1"></table>
</div>
</div>
</div>
<div id="tab-3" class="tab-pane">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="formId2">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="myTaskNoEd"/>
</li>
<li>
<label>任务名称:</label>
<input type="text" name="taskName" id="myTaskNameEd"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskType" id="myTaskTypeEd" th:with="type=${@dict.getType('sys_task_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('formId2','bootstrap-table2')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('formId2','bootstrap-table2')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table2"></table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:task:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:task:remove')}]];
var taskStatusDatas = [[${@dict.getType('ding_task_status')}]];
var taskTypeDatas = [[${@dict.getType('sys_task_type')}]];
var prefix = ctx + "system/task";
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "系统任务",
columns: [{
checkbox: true
var editFlag = [[${@permission.hasPermi('system:task:edit')}]];
var handleFlag = [[${@permission.hasPermi('system:task:handle')}]];
var removeFlag = [[${@permission.hasPermi('system:task:remove')}]];
var startFlag = [[${@permission.hasPermi('system:task:start')}]];
var taskStatusDatas = [[${@dict.getType('ding_task_status')}]];
var taskTypeDatas = [[${@dict.getType('sys_task_type')}]];
var prefix = ctx + "system/task";
$(function() {
var options = {
id:"bootstrap-table3",
url: prefix + "/waitList",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
handleUrl: prefix + "/handle/{id}",
modalName: "系统任务",
toolbar: "toolbar1",
queryParams:queryParams,
columns: [{
checkbox: true
},
{
field: 'id',
title: '任务编号',
visible: false
},
{
field: 'taskNo',
title: '任务编号',
},
{
field: 'taskName',
title: '任务名称',
formatter: function(value, row, index) {
return row.sysOaTask.taskName;
}
},
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, row.sysOaTask.taskType);
}
},
{
field: 'createBy',
title: '指派人',
formatter: function(value, row, index) {
return row.sysOaTask.createBy;
}
},
{
field: 'taskStartTime',
title: '开始时间',
formatter: function(value, row, index) {
if(row.taskStartTime==null||row.taskStartTime==''){
return '未开始'
}else {
return value;
}
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
if(row.taskExecuteStatus=='RUNNING') {
actions.push('<a class="btn btn-info btn-xs ' + startFlag + '" href="javascript:void(0)" onclick="startTask(\''+row.id+'\')"><i class="fa fa-hourglass-start"></i>开始</a> ');
}
if(row.taskExecuteStatus=='PROCESSING') {
actions.push('<a class="btn btn-success btn-xs ' + handleFlag + '" href="javascript:void(0)" onclick="$.operate.handle(\'' + row.id + '\')"><i class="fa fa-edit"></i>处理</a>');
}
return actions.join('');
}
}]
};
$.table.init(options);
function queryParams(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#myTaskNo").val();
search.taskStatus = $("#myTaskStatus").val();
return search;
}
var options1 = {
id: "bootstrap-table1",
url: prefix + "/myList",
detailUrl: prefix + "/detail/{id}",
updateUrl: prefix + "/edit/{id}",
createUrl: prefix + "/add",
toolbar: "toolbar2",
queryParams:queryParamMy,
detailView: true,
onExpandRow : function(index, row, $detail) {
initChildTable(index, row, $detail);
},
modalName: "我创建",
columns: [{
checkbox: true
},
{
field: 'taskNo',
title: '任务编号',
@ -95,18 +271,18 @@
return row.taskContent.substring(0,20)+"...";
}
},
{
/* {
field: 'taskStatus',
title: '任务状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskStatusDatas, value);
return $.table.selectDictLabel(taskStatusDatas, value);
}
},
},*/
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, value);
return $.table.selectDictLabel(taskTypeDatas, value);
}
},
{
@ -118,14 +294,177 @@
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs " href="javascript:void(0)" onclick="$.operate.detail(\'' + row.taskNo + '\')"><i class="fa fa-eye"></i>详情</a> ');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.taskNo + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.taskNo + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
};
$.table.init(options1);
function queryParamMy(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#taskNo").val();
search.taskName = $("#taskName").val();
search.taskStatus = $("#taskStatus").val();
return search;
}
var options2 = {
id: "bootstrap-table2",
url: prefix + "/handleList",
detailUrl: prefix + "/taskDistributedDetail/{id}",
exportUrl: prefix + "/export",
modalName: "我处理的",
columns: [{
checkbox: false
},
{
field: 'id',
title: 'id',
visible: false
},
{
field: 'taskNo',
title: '任务编号',
visible: true
},
{
field: 'taskName',
title: '任务名称',
formatter: function(value, row, index) {
return row.sysOaTask.taskName;
}
},
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, row.sysOaTask.taskType);
}
},
{
field: 'createBy',
title: '分配人',
formatter: function(value, row, index) {
return row.sysOaTask.createBy;
}
},
{
field: 'taskStartTime',
title: '开始时间'
},
{
field: 'taskCompleteTime',
title: '完成时间'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs " href="javascript:void(0)" onclick="$.operate.detail(\'' + row.id + '\')"><i class="fa fa-eye"></i>详情</a> ');
return actions.join('');
}
}]
};
$.table.init(options2);
function queryParam(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#myTaskNoEd").val();
search.taskName = $("#myTaskNameEd").val();
search.taskStatus = $("#myTaskStatusEd").val();
return search;
}
});
initChildTable = function(index, row, $detail) {
var childTable = $detail.html('<table style="table-layout:fixed"></table>').find('table');
$(childTable).bootstrapTable({
url: prefix + "/taskDistributeList",
method: 'post',
sidePagination: "server",
contentType: "application/x-www-form-urlencoded",
queryParams : {
taskNo: row.taskNo
},
columns: [
{
field: 'id',
title: '主键ID',
visible: false
},
{
field: 'index',
align: 'center',
title: "序号",
formatter: function (value, row, index) {
var columnIndex = $.common.sprintf("<input type='hidden' name='index' value='%s'>", $.table.serialNumber(index));
return columnIndex + $.table.serialNumber(index);
}
},
{
field: 'taskNo',
title: '任务编号',
formatter: function(value, row, index) {
return row.taskNo.substring(0,5)+"...";
}
},
{
field: 'taskDistributeId',
title: '待处理人'
},
{
field: 'taskExecuteStatus',
title: '任务状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskStatusDatas, value);
}
},
{
field: 'taskStartTime',
title: '开始时间'
},
{
field: 'taskCompleteTime',
title: '完成时间'
},
{
field: 'taskFeedback',
title: '任务反馈',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="detailLog(\'' + row.id + '\')"><i class="fa fa-edit"></i>详情</a> ');
return actions.join('');
}
}]
});
</script>
};
function startTask(id) {
$.modal.confirm("确定开始该条任务吗?", function() {
var url = prefix + '/start';
$.operate.submit(url, "post", "json", { "id": id });
});
}
function detailLog(id) {
var url = prefix + '/taskDistribute/detail/'+id;
$.modal.open("详情", url);
}
</script>
</body>
</html>

View File

@ -1,448 +0,0 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('任务中心')" />
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeIn">
<div class="row m-b-lg ">
<div class="col-sm-12">
<div class="tabs-container">
<div class="tabs-left">
<ul class="nav nav-tabs">
<li class="active">
<a data-toggle="tab" href="#tab-1"> 待处理 <span class="label label-info pull-right"></span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-2"> 我创建 <span class="label label-info pull-right" ></span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-3"> 已处理 <span class="label label-info pull-right" ></span></a>
</li>
</ul>
<div class="tab-content ">
<div id="tab-1" class="tab-pane active">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="formId3">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="myTaskNo"/>
</li>
<li>
<label>任务名称:</label>
<input type="text" name="taskName" id="myTaskName"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskStatus" id="myTaskStatus" th:with="type=${@dict.getType('ding_task_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('formId3','bootstrap-table3')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('formId3','bootstrap-table3')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar1" role="group">
<a class="btn btn-warning" onclick="$.table.exportExcel('formId3')" shiro:hasPermission="system:task:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table3"></table>
</div>
</div>
</div>
<div id="tab-2" class="tab-pane">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="myformId">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="taskNo"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskStatus" id="taskStatus" th:with="type=${@dict.getType('ding_task_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('myformId','bootstrap-table1')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('myformId','bootstrap-table1')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar2" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:task:edit">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:task:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table1"></table>
</div>
</div>
</div>
<div id="tab-3" class="tab-pane">
<div class="panel-body">
<div class="col-sm-12 search-collapse">
<form id="formId2">
<div class="select-list">
<ul>
<li>
<label>任务编号:</label>
<input type="text" name="taskNo" id="myTaskNoEd"/>
</li>
<li>
<label>任务名称:</label>
<input type="text" name="taskName" id="myTaskNameEd"/>
</li>
<li>
<label>任务状态:</label>
<select name="taskType" id="myTaskTypeEd" th:with="type=${@dict.getType('sys_task_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('formId2','bootstrap-table2')"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('formId2','bootstrap-table2')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table2"></table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:task:edit')}]];
var handleFlag = [[${@permission.hasPermi('system:task:handle')}]];
var removeFlag = [[${@permission.hasPermi('system:task:remove')}]];
var startFlag = [[${@permission.hasPermi('system:task:start')}]];
var taskStatusDatas = [[${@dict.getType('ding_task_status')}]];
var taskTypeDatas = [[${@dict.getType('sys_task_type')}]];
var prefix = ctx + "system/task";
$(function() {
var options = {
id:"bootstrap-table3",
url: prefix + "/waitList",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
handleUrl: prefix + "/handle/{id}",
modalName: "系统任务",
toolbar: "toolbar1",
queryParams:queryParams,
columns: [{
checkbox: true
},
{
field: 'id',
title: '任务编号',
visible: false
},
{
field: 'taskNo',
title: '任务编号',
},
{
field: 'taskName',
title: '任务名称',
formatter: function(value, row, index) {
return row.sysOaTask.taskName;
}
},
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, row.sysOaTask.taskType);
}
},
{
field: 'createBy',
title: '指派人',
formatter: function(value, row, index) {
return row.sysOaTask.createBy;
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
if(row.taskExecuteStatus=='RUNNING') {
actions.push('<a class="btn btn-info btn-xs ' + startFlag + '" href="javascript:void(0)" onclick="startTask(\''+row.id+'\')"><i class="fa fa-hourglass-start"></i>开始</a> ');
}
if(row.taskExecuteStatus=='PROCESSING') {
actions.push('<a class="btn btn-success btn-xs ' + handleFlag + '" href="javascript:void(0)" onclick="$.operate.handle(\'' + row.id + '\')"><i class="fa fa-edit"></i>处理</a>');
}
return actions.join('');
}
}]
};
$.table.init(options);
function queryParams(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#myTaskNo").val();
search.taskStatus = $("#myTaskStatus").val();
return search;
}
var options1 = {
id: "bootstrap-table1",
url: prefix + "/myList",
detailUrl: prefix + "/detail/{id}",
updateUrl: prefix + "/edit/{id}",
createUrl: prefix + "/add",
toolbar: "toolbar2",
queryParams:queryParamMy,
detailView: true,
onExpandRow : function(index, row, $detail) {
initChildTable(index, row, $detail);
},
modalName: "我创建",
columns: [{
checkbox: true
},
{
field: 'taskNo',
title: '任务编号',
visible: true
},
{
field: 'taskName',
title: '任务名称'
},
{
field: 'taskContent',
title: '任务内容',
formatter: function(value, row, index) {
return row.taskContent.substring(0,20)+"...";
}
},
/* {
field: 'taskStatus',
title: '任务状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskStatusDatas, value);
}
},*/
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, value);
}
},
{
field: 'taskSource',
title: '任务来源'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs " href="javascript:void(0)" onclick="$.operate.detail(\'' + row.taskNo + '\')"><i class="fa fa-eye"></i>详情</a> ');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.taskNo + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.taskNo + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options1);
function queryParamMy(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#taskNo").val();
search.taskName = $("#taskName").val();
search.taskStatus = $("#taskStatus").val();
return search;
}
var options2 = {
id: "bootstrap-table2",
url: prefix + "/handleList",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "我处理的",
columns: [{
checkbox: true
},
{
field: 'taskNo',
title: '任务编号',
visible: true
},
{
field: 'taskName',
title: '任务名称',
formatter: function(value, row, index) {
return row.sysOaTask.taskName;
}
},
{
field: 'taskType',
title: '任务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskTypeDatas, row.sysOaTask.taskType);
}
},
{
field: 'createBy',
title: '分配人',
formatter: function(value, row, index) {
return row.sysOaTask.createBy;
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-info btn-xs " href="javascript:void(0)" onclick="$.operate.detail(\'' + row.taskNo + '\')"><i class="fa fa-eye"></i>详情</a> ');
return actions.join('');
}
}]
};
$.table.init(options2);
function queryParam(params) {
var search = $.table.queryParams(params);
search.taskNo = $("#myTaskNoEd").val();
search.taskName = $("#myTaskNameEd").val();
search.taskStatus = $("#myTaskStatusEd").val();
return search;
}
});
initChildTable = function(index, row, $detail) {
var childTable = $detail.html('<table style="table-layout:fixed"></table>').find('table');
$(childTable).bootstrapTable({
url: prefix + "/taskDistributeList",
method: 'post',
sidePagination: "server",
contentType: "application/x-www-form-urlencoded",
queryParams : {
taskNo: row.taskNo
},
columns: [
{
field: 'id',
title: '主键ID',
visible: false
},
{
field: 'index',
align: 'center',
title: "序号",
formatter: function (value, row, index) {
var columnIndex = $.common.sprintf("<input type='hidden' name='index' value='%s'>", $.table.serialNumber(index));
return columnIndex + $.table.serialNumber(index);
}
},
{
field: 'taskNo',
title: '任务编号',
formatter: function(value, row, index) {
return row.taskNo.substring(0,5)+"...";
}
},
{
field: 'taskDistributeId',
title: '待处理人'
},
{
field: 'taskExecuteStatus',
title: '任务状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(taskStatusDatas, value);
}
},
{
field: 'taskStartTime',
title: '开始时间'
},
{
field: 'taskCompleteTime',
title: '完成时间'
},
{
field: 'taskFeedback',
title: '任务反馈',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="detailLog(\'' + row.id + '\')"><i class="fa fa-edit"></i>详情</a> ');
return actions.join('');
}
}]
});
};
function startTask(id) {
$.modal.confirm("确定开始该条任务吗?", function() {
var url = prefix + '/start';
$.operate.submit(url, "post", "json", { "id": id });
});
}
function detailLog(id) {
var url = prefix + '/taskDistribute/detail/'+id;
$.modal.open("详情", url);
}
</script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet" />
<link th:href="@{/css/font-awesome.min.css}" rel="stylesheet" />
<!-- bootstrap-table 表格插件样式 -->
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet" />
<link th:href="@{/css/style.css}" rel="stylesheet" />
<link th:href="@{/ruoyi/css/ry-ui.css}" rel="stylesheet" />
<th:block th:include="include :: jsonview-css" />
</head>
<body class="white-bg" >
<form class="form-horizontal m-t">
<h2 class="form-header h2" align="center" >任务信息</h2>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务编号:</label>
<span class="form-control-static" th:text="${sysOaTask.sysOaTask.taskNo}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务标题:</label>
<span class="form-control-static" th:text="${sysOaTask.sysOaTask.taskName}">
</span>
</div>
</div>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-5 col-sm-5">
<label class="control-label">紧急程度:</label>
<span class="form-control-static" th:text="${@dict.getLabel('sys_oa_task_priority',sysOaTask.sysOaTask.priority)}">
</span>
</div>
<div class="col-xs-5 col-sm-5">
<label class="control-label">任务类型:</label>
<span class="form-control-static" th:text="${@dict.getLabel('sys_task_type',sysOaTask.sysOaTask.taskType)}">
</span>
</div>
</div>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-10 col-sm-10">
<label class="control-label">任务内容:</label>
<span class="form-control-static" th:text="${sysOaTask.sysOaTask.taskContent}">
</span>
</div>
</div>
<br/>
<h2 class="form-header h2" align="center" >任务分配记录</h2>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">开始时间:</label>
<span class="text-navy" th:text="${#dates.format(sysOaTask.taskStartTime, 'yyyy-MM-dd hh:mm:ss')}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">结束时间:</label>
<span class="text-navy" th:text="${#dates.format(sysOaTask.taskCompleteTime, 'yyyy-MM-dd hh:mm:ss')}">
</span>
</div>
</div>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">执行状态:</label>
<span class="m-b-xs" th:text="${@dict.getLabel('ding_task_status',sysOaTask.taskExecuteStatus)}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务用时:</label>
<span class="text-danger" th:text="${sysOaTask.spendTime}">
</span>
</div>
</div>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务分配人:</label>
<span class="form-control-static" th:text="${sysOaTask.taskDistributeId}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务执行人:</label>
<span class="form-control-static" th:text="${sysOaTask.taskExecuteId}">
</span>
</div>
</div>
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-10 col-sm-10">
<label class="control-label">任务反馈:</label>
<span class="form-control-static" th:text="${sysOaTask.taskFeedback}">
</span>
</div>
</div>
</form>
<th:block th:include="include :: footer" />
</body>
</html>

View File

@ -34,6 +34,7 @@ public enum DingTalkListenerType {
WORK_RECORD_UPDATE(3,20,"更新待办"),
WORK_RECORD_DELETE(4,20,"删除待办"),
/**
* 审批任务开始结束转交

View File

@ -73,20 +73,20 @@ public class BaseService {
}
/**
* 钉钉新版服务费token获取
* @return token值
*/
public String getDingTalkTokenV2(){
//创建缓存缓存默认是7100S
TimedCache<String, String> timedCache = CacheUtil.newTimedCache(7100);
if(StringUtils.isEmpty(timedCache.get(TOKENV2))) {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
try {
Client client = new Client(config);
GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest()
.setAppKey(sysConfigService.selectConfigByKey(Constants.ENTERPRICE_APP_KEY))
.setAppSecret(sysConfigService.selectConfigByKey(Constants.ENTERPRICE_APP_SECRET));
try {
GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest);
GetAccessTokenResponse accessToken = createClient().getAccessToken(getAccessTokenRequest);
timedCache.put(TOKENV2,accessToken.getBody().getAccessToken());
return accessToken.getBody().getAccessToken();
} catch (Exception exception) {
@ -105,6 +105,18 @@ public class BaseService {
}
}
/**
* 创建createClient
* @return
* @throws Exception
*/
public Client createClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new Client(config);
}
/**
* 记录钉钉异常信息
* @param url

View File

@ -30,7 +30,7 @@ public class SyncDingTalkInfoFactory {
return new CallBackService();
}
else if(type.equals(DingTalkListenerType.WORK_RECODE_CREATE.getType())){
return new WorkRecodeService();
return new WorkRecodeEventService();
}
else if(type.equals(DingTalkListenerType.BLACKBOARD_CREATE.getType())){
return new BlackboardService();

View File

@ -23,7 +23,7 @@ public class SyncEventListener implements ApplicationListener<SyncEvent> {
@Override
public void onApplicationEvent(SyncEvent syncEvent) {
log.info("/n @@进入钉钉模块监听器.....,配置的开关为:{}",isSyncDingTalk);
log.info(" @@进入钉钉模块监听器.....,配置的开关为:{}",isSyncDingTalk);
if(isSyncDingTalk){
log.info("监听到的事件类型:"+JSON.toJSONString(syncEvent));
SyncDingTalkInfoFactory syncEventListenerFactory = new SyncDingTalkInfoFactory();

View File

@ -3,9 +3,9 @@ package com.snow.dingtalk.listener;
import com.alibaba.fastjson.JSON;
import com.snow.common.enums.DingTalkListenerType;
import com.snow.common.utils.spring.SpringUtils;
import com.snow.dingtalk.model.WorkrecordAddRequest;
import com.snow.dingtalk.service.impl.WorkRecodeServiceImpl;
import com.snow.framework.web.domain.common.SysSendMessageDTO;
import com.snow.system.domain.SysOaTask;
import com.snow.system.event.SyncEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@Slf4j
public class WorkRecodeService implements ISyncDingTalkInfo {
public class WorkRecodeEventService implements ISyncDingTalkInfo {
private WorkRecodeServiceImpl workRecodeService=SpringUtils.getBean(WorkRecodeServiceImpl.class);
@ -29,8 +29,21 @@ public class WorkRecodeService implements ISyncDingTalkInfo {
Integer code = eventType.getCode();
//钉钉创建待办
if(code.equals(DingTalkListenerType.WORK_RECODE_CREATE.getCode())){
WorkrecordAddRequest workrecordAddRequest=(WorkrecordAddRequest)syncEvent.getSource();
workRecodeService.create(workrecordAddRequest);
SysOaTask sysOaTask=(SysOaTask)syncEvent.getSource();
log.info("@@创建钉钉待办系统传入的参数:{}",JSON.toJSONString(sysOaTask));
workRecodeService.createTodoTask(sysOaTask);
}
//更新钉钉待办
if(code.equals(DingTalkListenerType.WORK_RECORD_UPDATE.getCode())){
SysOaTask sysOaTask=(SysOaTask)syncEvent.getSource();
log.info("@@更新钉钉待办系统传入的参数:{}",JSON.toJSONString(sysOaTask));
workRecodeService.updateTodoTask(sysOaTask);
}
//删除钉钉待办
if(code.equals(DingTalkListenerType.WORK_RECORD_DELETE.getCode())){
String taskId=(String)syncEvent.getSource();
log.info("@@删除钉钉待办系统传入的参数:{}",JSON.toJSONString(taskId));
workRecodeService.deleteTodoTask(taskId);
}
//钉钉发送普通消息
else if(code.equals(DingTalkListenerType.ASYNCSEND_V2.getCode())){

View File

@ -54,4 +54,11 @@ public interface UserService {
* @return
*/
OapiUserGetbyunionidResponse.UserGetByUnionIdResponse getUserByUnionId(String unionId);
/**
* 根据系统用户id获取用户UnionId
* @param sysUserId 系统用户id
* @return UnionId
*/
String getUnionIdBySysUserId(Long sysUserId);
}

View File

@ -1,9 +1,11 @@
package com.snow.dingtalk.service;
import com.aliyun.dingtalktodo_1_0.models.GetTodoTaskBySourceIdResponseBody;
import com.dingtalk.api.response.OapiWorkrecordGetbyuseridResponse;
import com.snow.dingtalk.model.WorkrecordAddRequest;
import com.snow.dingtalk.model.WorkrecordGetbyuseridRequest;
import com.snow.framework.web.domain.common.SysSendMessageDTO;
import com.snow.system.domain.SysOaTask;
import org.springframework.stereotype.Service;
/**
@ -20,13 +22,51 @@ public interface WorkRecodeService {
* @param workrecordAddRequest
* @return
*/
@Deprecated
String create(WorkrecordAddRequest workrecordAddRequest);
/**
* 创建待办
* @param sysOaTask
* @return
*/
String createTodoTask(SysOaTask sysOaTask);
/**
* 删除待办
* @param taskId
* @return
*/
String deleteTodoTask(String taskId);
/**
* 更新待办()
* @param sysOaTask
* @return
*/
Boolean updateTodoTask(SysOaTask sysOaTask);
/**
* 更新待办状态
* @param status 是否
* @return
*/
Boolean updateTodoTaskExecutorStatus(String taskId,Boolean status);
/**
* 根据业务id获取待办详情()
* @param businessId
* @return
*/
GetTodoTaskBySourceIdResponseBody getTodoTaskByBusinessId(String businessId);
/**
* 根据用户ID获取待办
* @param workrecordGetbyuseridRequest
* @return
*/
@Deprecated
OapiWorkrecordGetbyuseridResponse.PageResult getWorkRecordByUserId(WorkrecordGetbyuseridRequest workrecordGetbyuseridRequest);
/**
@ -35,6 +75,7 @@ public interface WorkRecodeService {
* @param recordId
* @return
*/
@Deprecated
Boolean update(String userId,String recordId);
/**

View File

@ -16,17 +16,16 @@ import com.snow.dingtalk.model.UserListRequest;
import com.snow.dingtalk.service.UserService;
import com.snow.system.domain.SysPost;
import com.snow.system.domain.SysUser;
import com.snow.system.service.ISysConfigService;
import com.snow.system.service.ISysUserService;
import com.snow.system.service.impl.SysConfigServiceImpl;
import com.snow.system.service.impl.SysPostServiceImpl;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author qimingjin
@ -42,6 +41,8 @@ public class UserServiceImpl extends BaseService implements UserService {
private SysConfigServiceImpl isysConfigService=SpringUtils.getBean(SysConfigServiceImpl.class);
private ISysUserService sysUserService=SpringUtils.getBean(ISysUserService.class);
public OapiSnsGetuserinfoBycodeResponse.UserInfo getUserInfoByCode(String authCode) {
String appId= isysConfigService.selectConfigByKey("ding.login.appid");
@ -222,4 +223,9 @@ public class UserServiceImpl extends BaseService implements UserService {
}
}
@Override
public String getUnionIdBySysUserId(Long sysUserId) {
return getUserByUserId(sysUserService.selectUserById(sysUserId).getDingUserId()).getUnionid();
}
}

View File

@ -1,10 +1,10 @@
package com.snow.dingtalk.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.dingtalktodo_1_0.Client;
import com.aliyun.dingtalktodo_1_0.models.CreateTodoTaskHeaders;
import com.aliyun.dingtalktodo_1_0.models.CreateTodoTaskRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.dingtalktodo_1_0.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
@ -13,10 +13,7 @@ import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiWorkrecordAddRequest;
import com.dingtalk.api.request.OapiWorkrecordGetbyuseridRequest;
import com.dingtalk.api.request.OapiWorkrecordUpdateRequest;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiWorkrecordAddResponse;
import com.dingtalk.api.response.OapiWorkrecordGetbyuseridResponse;
import com.dingtalk.api.response.OapiWorkrecordUpdateResponse;
import com.dingtalk.api.response.*;
import com.snow.common.annotation.SyncLog;
import com.snow.common.constant.Constants;
import com.snow.common.enums.DingTalkListenerType;
@ -29,10 +26,14 @@ import com.snow.dingtalk.common.BaseConstantUrl;
import com.snow.dingtalk.common.BaseService;
import com.snow.dingtalk.model.WorkrecordAddRequest;
import com.snow.dingtalk.model.WorkrecordGetbyuseridRequest;
import com.snow.dingtalk.service.UserService;
import com.snow.dingtalk.service.WorkRecodeService;
import com.snow.framework.util.ShiroUtils;
import com.snow.framework.web.domain.common.SysSendMessageDTO;
import com.snow.system.domain.SysMessageTemplate;
import com.snow.system.domain.SysOaTask;
import com.snow.system.service.ISysMessageTemplateService;
import com.snow.system.service.ISysUserService;
import com.snow.system.service.impl.SysConfigServiceImpl;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
@ -41,6 +42,8 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
@ -57,6 +60,11 @@ public class WorkRecodeServiceImpl extends BaseService implements WorkRecodeServ
private ISysMessageTemplateService sysMessageTemplateService=SpringUtils.getBean(ISysMessageTemplateService.class);
private UserService userService=SpringUtils.getBean(UserService.class);
private ISysUserService sysUserService=SpringUtils.getBean(ISysUserService.class);
/**
* 创建工作待办
* @param workrecordAddRequest
@ -83,45 +91,124 @@ public class WorkRecodeServiceImpl extends BaseService implements WorkRecodeServ
}
@Override
public String createTodoTask(SysOaTask sysOaTask) {
List<String> taskDistributeId = sysOaTask.getTaskDistributeId();
public void createV2() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
Client client = new com.aliyun.dingtalktodo_1_0.Client(config);
CreateTodoTaskHeaders createTodoTaskHeaders = new CreateTodoTaskHeaders();
createTodoTaskHeaders.xAcsDingtalkAccessToken = getDingTalkTokenV2();
CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs notifyConfigs = new CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs()
.setDingNotify("1");
CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl detailUrl = new CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl()
.setAppUrl("dingtalk://dingtalkclient/action/open_mini_app?miniAppId={0}&ddMode=push&page=pages%2ftask-detail%2ftask-detail%3ftaskId%3d{1}")
.setPcUrl("https://todo.dingtalk.com/ding-portal/detail/task/{0}");
.setAppUrl(sysOaTask.getTaskUrl())
.setPcUrl(sysOaTask.getTaskUrl());
CreateTodoTaskRequest createTodoTaskRequest = new CreateTodoTaskRequest()
.setSourceId("isv_dingtalkTodo1")
.setSubject("接入钉钉待办")
.setCreatorId("PUoiinWIpa2yH2ymhiiGiP6g")
.setDescription("应用可以调用该接口发起一个钉钉待办任务该待办事项会出现在钉钉客户端“待办”页面需要注意的是通过开放接口发起的待办目前仅支持直接跳转ISV应用详情页ISV在调该接口时需传入自身应用详情页链接")
.setDueTime(1617675000000L)
.setExecutorIds(Arrays.asList(
"PUoiinWIpa2yH2ymhiiGiP6g"
))
.setParticipantIds(Arrays.asList(
"PUoiinWIpa2yH2ymhiiGiP6g"
))
.setDetailUrl(detailUrl);
.setSourceId(sysOaTask.getTaskNo())
.setSubject(sysOaTask.getTaskName())
.setCreatorId(userService.getUnionIdBySysUserId(Long.parseLong(sysOaTask.getCreateBy())))
.setDescription(sysOaTask.getTaskContent())
.setDetailUrl(detailUrl)
.setIsOnlyShowExecutor(true)
.setPriority(sysOaTask.getPriority())
.setNotifyConfigs(notifyConfigs);
if (ObjectUtil.isNotNull(sysOaTask.getTaskCompleteTime())) {
createTodoTaskRequest.setDueTime(sysOaTask.getTaskCompleteTime().getTime());
}
//执行者id
if(CollUtil.isNotEmpty(taskDistributeId)){
List<String> executorIds = taskDistributeId.stream().map(t -> {
return userService.getUnionIdBySysUserId(Long.parseLong(t));
}).collect(Collectors.toList());
createTodoTaskRequest.setExecutorIds(executorIds);
}
try {
client.createTodoTaskWithOptions("PUoiinWIpa2yH2ymhiiGiP6g", createTodoTaskRequest, createTodoTaskHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code message 属性可帮助开发定位问题
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code message 属性可帮助开发定位问题
}
CreateTodoTaskResponse response = createTodoClient().createTodoTaskWithOptions(userService.getUnionIdBySysUserId(Long.parseLong(sysOaTask.getCreateBy())), createTodoTaskRequest, createTodoTaskHeaders, new RuntimeOptions());
return response.getBody().id;
} catch (Exception err) {
log.error("@@调用钉钉创建待办的时候出现异常,异常信息为:{}",err.getMessage());
throw new SyncDataException(JSON.toJSONString(createTodoTaskRequest),err.getMessage());
}
}
@Override
public String deleteTodoTask(String taskId) {
String dingUserId = ShiroUtils.getDingUserId();
OapiV2UserGetResponse.UserGetResponse user = userService.getUserByUserId(dingUserId);
DeleteTodoTaskHeaders deleteTodoTaskHeaders = new DeleteTodoTaskHeaders();
deleteTodoTaskHeaders.xAcsDingtalkAccessToken = getDingTalkTokenV2();
DeleteTodoTaskRequest deleteTodoTaskRequest = new DeleteTodoTaskRequest()
.setOperatorId(user.getUnionid());
try {
DeleteTodoTaskResponse deleteTodoTaskResponse = createTodoClient().deleteTodoTaskWithOptions(user.getUnionid(), taskId, deleteTodoTaskRequest, deleteTodoTaskHeaders, new RuntimeOptions());
return deleteTodoTaskResponse.getBody().requestId;
} catch (Exception exception) {
log.error("@@调用钉钉删除待办的时候出现异常,异常信息为:{}",exception.getMessage());
throw new SyncDataException(JSON.toJSONString(deleteTodoTaskRequest),exception.getMessage());
}
}
@Override
public Boolean updateTodoTask(SysOaTask sysOaTask) {
UpdateTodoTaskHeaders updateTodoTaskHeaders = new UpdateTodoTaskHeaders();
updateTodoTaskHeaders.xAcsDingtalkAccessToken = getDingTalkTokenV2();
UpdateTodoTaskRequest updateTodoTaskRequest = new UpdateTodoTaskRequest()
.setSubject(sysOaTask.getTaskName())
.setDescription(sysOaTask.getTaskContent())
.setExecutorIds(Arrays.asList(
""
));
//设置是否完成
if(ObjectUtil.isNotNull(sysOaTask.getTaskCompleteTime())){
updateTodoTaskRequest.setDone(true);
}else {
updateTodoTaskRequest.setDone(false);
}
if(ObjectUtil.isNotNull(sysOaTask.getExpectedTime())){
updateTodoTaskRequest.setDueTime(sysOaTask.getExpectedTime().getTime());
}
try {
UpdateTodoTaskResponse updateTodoTaskResponse = createTodoClient().updateTodoTaskWithOptions(userService.getUnionIdBySysUserId(Long.parseLong(sysOaTask.getUpdateBy())), sysOaTask.getDingTaskId(), updateTodoTaskRequest, updateTodoTaskHeaders, new RuntimeOptions());
return updateTodoTaskResponse.getBody().result;
}catch (Exception err) {
log.error("@@调用钉钉更新待办的时候出现异常,异常信息为:{}",err.getMessage());
throw new SyncDataException(JSON.toJSONString(updateTodoTaskRequest),err.getMessage());
}
}
@Override
public Boolean updateTodoTaskExecutorStatus(String taskId,Boolean status) {
UpdateTodoTaskExecutorStatusHeaders updateTodoTaskExecutorStatusHeaders = new UpdateTodoTaskExecutorStatusHeaders();
updateTodoTaskExecutorStatusHeaders.xAcsDingtalkAccessToken = getDingTalkTokenV2();
UpdateTodoTaskExecutorStatusRequest.UpdateTodoTaskExecutorStatusRequestExecutorStatusList executorStatusList0 = new UpdateTodoTaskExecutorStatusRequest.UpdateTodoTaskExecutorStatusRequestExecutorStatusList()
.setId(taskId)
.setIsDone(status);
UpdateTodoTaskExecutorStatusRequest updateTodoTaskExecutorStatusRequest = new UpdateTodoTaskExecutorStatusRequest()
.setExecutorStatusList(java.util.Arrays.asList(
executorStatusList0
));
try {
UpdateTodoTaskExecutorStatusResponse response = createTodoClient().updateTodoTaskExecutorStatusWithOptions("PUoiinWIpa2yH2ymhiiGiP6g", taskId, updateTodoTaskExecutorStatusRequest, updateTodoTaskExecutorStatusHeaders, new RuntimeOptions());
return response.getBody().result;
} catch (Exception err) {
log.error("@@调用钉钉更新办状态的时候出现异常,异常信息为:{}",err.getMessage());
throw new SyncDataException(JSON.toJSONString(updateTodoTaskExecutorStatusRequest),err.getMessage());
}
}
@Override
public GetTodoTaskBySourceIdResponseBody getTodoTaskByBusinessId(String businessId) {
GetTodoTaskBySourceIdHeaders getTodoTaskBySourceIdHeaders = new GetTodoTaskBySourceIdHeaders();
getTodoTaskBySourceIdHeaders.xAcsDingtalkAccessToken = getDingTalkTokenV2();
try {
GetTodoTaskBySourceIdResponse respose = createTodoClient().getTodoTaskBySourceIdWithOptions("user123", businessId, getTodoTaskBySourceIdHeaders, new RuntimeOptions());
return respose.getBody();
} catch (Exception err) {
log.error("@@调用钉钉获取待办详情的时候出现异常,异常信息为:{}",err.getMessage());
throw new SyncDataException(JSON.toJSONString(getTodoTaskBySourceIdHeaders),err.getMessage());
}
}
/**
* 根据用户ID获取待办
* @param workrecordGetbyuseridRequest
@ -226,4 +313,17 @@ public class WorkRecodeServiceImpl extends BaseService implements WorkRecodeServ
throw new SyncDataException(JSON.toJSONString(request),e.getErrMsg());
}
}
public Client createTodoClient(){
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
Client client = null;
try {
return new Client(config);
} catch (Exception exception) {
log.error("@@调用钉钉待办初始化client的时候出现异常异常信息为:{}",exception.getMessage());
throw new SyncDataException(JSON.toJSONString(config),exception.getMessage());
}
}
}

View File

@ -1,6 +1,6 @@
package com.snow.dingtalk.sync;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.snow.common.annotation.SyncLog;
@ -169,8 +169,8 @@ public class SyncFlowService implements ISyncSysInfo {
OapiProcessinstanceGetResponse.ProcessInstanceTopVo processInstanceDetail = dingOfficialFlowService.getProcessInstanceDetail(procInstId);
//获取任务节点(写入钉钉待办表)
List<OapiProcessinstanceGetResponse.TaskTopVo> tasks = processInstanceDetail.getTasks();
if(CollectionUtil.isNotEmpty(tasks)){
tasks.stream().forEach(t->{
if(CollUtil.isNotEmpty(tasks)){
tasks.forEach(t->{
//第二步运行中的任务保存到本地表
if(t.getTaskStatus().equals(DingFlowTaskType.RUNNING.getCode())){
SysDingRuTask querySysDingRuTask = sysDingRuTaskService.selectSysDingRuTaskById(t.getTaskid());
@ -197,8 +197,8 @@ public class SyncFlowService implements ISyncSysInfo {
OapiProcessinstanceGetResponse.ProcessInstanceTopVo processInstanceDetail = dingOfficialFlowService.getProcessInstanceDetail(procInstId);
//获取任务节点(写入钉钉待办表)
List<OapiProcessinstanceGetResponse.TaskTopVo> tasks = processInstanceDetail.getTasks();
if(CollectionUtil.isNotEmpty(tasks)){
tasks.stream().forEach(t->{
if(CollUtil.isNotEmpty(tasks)){
tasks.forEach(t->{
//第二步删除运行中的任务更新历史任务表
if(t.getTaskStatus().equals(DingFlowTaskType.COMPLETED.getCode())){
SysDingRuTask querySysDingRuTask = sysDingRuTaskService.selectSysDingRuTaskById(t.getTaskid());

View File

@ -68,6 +68,11 @@ public class ShiroUtils
return getSysUser().getUserId().longValue();
}
public static String getDingUserId()
{
return getSysUser().getDingUserId();
}
public static String getLoginName()
{
return getSysUser().getLoginName();

View File

@ -22,6 +22,11 @@ public class SysOaTask extends BaseEntity
/** 任务编号 */
private String taskNo;
/**
* 钉钉待办taskId
*/
private String dingTaskId;
/** 任务名称 */
@Excel(name = "任务名称")
private String taskName;

View File

@ -1,12 +1,11 @@
package com.snow.system.mapper;
import java.util.List;
import java.util.Set;
import com.snow.system.domain.SysAuthUser;
import com.snow.system.domain.SysUser;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户表 数据层
*

View File

@ -1,12 +1,11 @@
package com.snow.system.service;
import java.util.List;
import java.util.Set;
import com.snow.system.domain.SysAuthUser;
import com.snow.system.domain.SysUser;
import com.snow.system.domain.SysUserRole;
import java.util.List;
/**
* 用户 业务层
*

View File

@ -67,6 +67,11 @@ public class SysOaTaskDistribute extends BaseEntity
@Excel(name = "删除标识")
private Long isDelete;
/**
* 任务花费时间
*/
private String spendTime;
/**
* 任务主表
*/

View File

@ -95,7 +95,6 @@ public class SysOaTaskServiceImpl implements ISysOaTaskService
//任务分配人
sysOaTaskDistribute.setTaskDistributeId(sysOaTask.getCreateBy());
sysOaTaskDistribute.setTaskNo(newSequenceNo);
sysOaTaskDistribute.setTaskCompleteTime(sysOaTask.getTaskCompleteTime());
sysOaTaskDistribute.setTaskExecuteStatus(DingFlowTaskType.RUNNING.getCode());
sysOaTaskDistribute.setCreateBy(sysOaTask.getCreateBy());
sysOaTaskDistributeService.insertSysOaTaskDistribute(sysOaTaskDistribute);
@ -152,6 +151,9 @@ public class SysOaTaskServiceImpl implements ISysOaTaskService
if(CollUtil.isNotEmpty(sysOaTaskDistributes)){
throw new BusinessException("任务编号:"+taskNo+"已分配,不允许删除操作");
}
//发送事件
SyncEvent<String> syncEvent = new SyncEvent(taskNo, DingTalkListenerType.WORK_RECODE_CREATE);
applicationContext.publishEvent(syncEvent);
return sysOaTaskMapper.deleteSysOaTaskById(taskNo);
}
}

View File

@ -1,33 +1,27 @@
package com.snow.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollUtil;
import com.snow.common.annotation.DataScope;
import com.snow.common.constant.UserConstants;
import com.snow.common.core.text.Convert;
import com.snow.common.enums.DingTalkListenerType;
import com.snow.common.exception.BusinessException;
import com.snow.common.utils.StringUtils;
import com.snow.common.utils.security.Md5Utils;
import com.snow.system.domain.*;
import com.snow.system.event.SyncEvent;
import org.apache.commons.compress.utils.Lists;
import com.snow.system.mapper.*;
import com.snow.system.service.ISysConfigService;
import com.snow.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.snow.common.annotation.DataScope;
import com.snow.common.constant.UserConstants;
import com.snow.common.core.text.Convert;
import com.snow.common.exception.BusinessException;
import com.snow.common.utils.StringUtils;
import com.snow.common.utils.security.Md5Utils;
import com.snow.system.mapper.SysPostMapper;
import com.snow.system.mapper.SysRoleMapper;
import com.snow.system.mapper.SysUserMapper;
import com.snow.system.mapper.SysUserPostMapper;
import com.snow.system.mapper.SysUserRoleMapper;
import com.snow.system.service.ISysConfigService;
import com.snow.system.service.ISysUserService;
import java.util.ArrayList;
import java.util.List;
/**
* 用户 业务层处理
@ -286,7 +280,7 @@ public class SysUserServiceImpl implements ISysUserService
public void insertUserAuth(Long userId, Long[] roleIds)
{
List<SysUserRole> sysUserRoles = userRoleMapper.selectUserRoleByUserId(userId);
if(CollectionUtil.isNotEmpty(sysUserRoles)){
if(CollUtil.isNotEmpty(sysUserRoles)){
sysUserRoles.forEach(t->{
SysRole sysRole = roleMapper.selectRoleById(t.getRoleId());
if(sysRole.getRoleType()==1){