工单
- 根据百度百科:
根据字面意思我们可以把它理解为工作单据。工单定义由一个和多个作业组成的简单维修或制造计划,上级部门下达任务,下级部门领受任务的依据。工单可以是独立的,也可以是大型项目的一部分,可以为工单定义子工单。
为了便于理解工单,先介绍下标准工单基本标准工单由表头和一个或者多个作业行组成。下面对标准工单的表头和作业行做详细的说明。
工单系统Ticket system又称为工单管理系统(还可以称为问题工单系统,事务工单系统,事务追踪系统issue tracking system,支持工单系统support ticket system)),它是一种网络软件系统,根据不同组织,部门和外部客户的需求,来由针对的管理,维护和追踪一系列的问题和请求。一个完善功能的工单系统又可以称为帮助台系统。 - 工作流中包含的模块:
流程图:
流条件设置为例:${headerPass==true}
,${attachePass==false}
等等
工单实体类:
| id | 主键ID |
| type | 类型 |
| description | 申请事由 |
| instanceId | 流程实例ID |
| disposeBy | 审批人 |
| headerBy | 部门领导 |
| attacheBy | 信息化专责 |
| leaderBy | 信息化主管 |
| outBy | 归档人 |
| outTime | 归档时间 |
| userName | 用户名 |
| nickName | 昵称 |
| createBy | 创建人 |
| createTime | 创建时间 |
| updateBy | 更新人 |
| updateTime | 更新时间 |
| valid | 有效 |
| doneTime | 确认时间 |
| taskId | 任务ID |
| taskName | 任务名称 |
| remark | 备注 |
| taskDefinitionKey | 任务定义Key |
| suspendState | 流程实例状态 1 激活 2 挂起 |
实体类增加Getter and Setter以及toString()方法.
Controller:
@RestController
@Api("工单相关接口")
@RequestMapping("/system/order")
public class SysOrderController extends BaseController {
@Autowired
private ISysOrderService sysOrderService;
@Autowired
private RedisCache redisCache;
private String RES_KEY = "orderKey";
/**
* 查询工单列表
*/
@ApiOperation("查询工单列表")
@GetMapping("/list")
public TableDataInfo list(SysOrder sysOrder) {
startPage();
sysOrder.setCreateBy(SecurityUtils.getUsername());
sysOrder.setType(redisCache.getCacheObject(RES_KEY));
List<SysOrder> list = sysOrderService.selectSysOrderList(sysOrder);
return getDataTable(list);
}
/**
* 导出工单列表
*/
@ApiOperation("导出工单列表")
@Log(title = "工单", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public AjaxResult export(SysOrder sysOrder) {
List<SysOrder> list = sysOrderService.selectSysOrderList(sysOrder);
ExcelUtil<SysOrder> util = new ExcelUtil<SysOrder>(SysOrder.class);
return util.exportExcel(list, "order");
}
/**
* 获取工单详细信息
*/
@ApiOperation("获取工单详细信息")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return AjaxResult.success(sysOrderService.selectSysOrderById(id));
}
/**
* 新增工单
*/
@ApiOperation("新增工单")
@PreAuthorize("@ss.hasPermi('system:order:add')")
@Log(title = "工单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysOrder sysOrder) {
return AjaxResult.success(sysOrderService.insertSysOrder(sysOrder));
}
/**
* 修改工单
*/
@ApiOperation("修改工单")
// @PreAuthorize("@ss.hasPermi('system:order:edit')")
@Log(title = "工单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysOrder sysOrder) {
return toAjax(sysOrderService.updateSysOrder(sysOrder));
}
/**
* 删除工单
*/
@ApiOperation("删除工单")
// @PreAuthorize("@ss.hasPermi('system:order:remove')")
@Log(title = "工单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(sysOrderService.deleteSysOrderByIds(ids));
}
//自定义内容
@ApiOperation("新增工单并提交流程业务")
@PostMapping(value = "/addAndSubmit")
public AjaxResult addAndSubmit(@Validated @RequestBody SysOrder sysOrder) {
sysOrderService.addAndSubmit(sysOrder);
return AjaxResult.success();
}
@Log(title = "工单业务", businessType = BusinessType.UPDATE)
@PostMapping("/submitApply")
@ResponseBody
public AjaxResult submitApply2(@RequestBody SysOrder sysOrder) {
sysOrderService.submitApply2(sysOrder, redisCache.getCacheObject(RES_KEY));
return AjaxResult.success();
}
@Log(title = "工单业务", businessType = BusinessType.UPDATE)
@PostMapping("/submitApply/{id}")
@ResponseBody
public AjaxResult submitApply(@PathVariable Long id) {
String applyUserId = SecurityUtils.getUsername();
sysOrderService.submitApply(id, applyUserId, redisCache.getCacheObject(RES_KEY));
return AjaxResult.success();
}
//待办
@Log(title = "工单业务")
@GetMapping("/taskList")
@ResponseBody
public TableDataInfo taskList(SysOrder sysOrder) {
startPage();
sysOrder.setType(redisCache.getCacheObject(RES_KEY));
List<SysOrder> list = sysOrderService.findTodoTasks(sysOrder);
return getDataTable(list);
}
/**
* 我的已办列表
*
* @param sysOrder
* @return
*/
@GetMapping("/taskDoneList")
@ResponseBody
public TableDataInfo taskDoneList(SysOrder sysOrder) {
startPage();
sysOrder.setType(redisCache.getCacheObject(RES_KEY));
List<SysOrder> list = sysOrderService.findDoneTasks(sysOrder);
return getDataTable(list);
}
/**
* 完成任务
*
* @return
*/
@PostMapping(value = "/complete")
@ResponseBody
public AjaxResult complete(@Validated @RequestBody SysOrder sysOrder) {
sysOrderBasicService.complete(sysOrder);
return AjaxResult.success("任务已完成");
}
}
Service:
public interface ISysOrderService {
public SysOrder selectSysOrderById(Long id);
public List<SysOrder> selectSysOrderList(SysOrder sysOrder);
public Long insertSysOrder(SysOrder sysOrder);
public int updateSysOrder(SysOrder sysOrder);
public int deleteSysOrderByIds(Long[] ids);
public int deleteSysOrderById(Long id);
//自定义内容
public ProcessInstance submitApply(Long id, String applyUser, String key);
public ProcessInstance submitApply2(SysOrder sysOrder, String applyUser, String key);
public List<SysOrder> findTodoTasks(SysOrder sysOrder);
public List<SysOrder> findDoneTasks(SysOrder sysOrder);
public ProcessInstance addAndSubmit(SysOrder sysOrder);
public void complete(SysOrder sysOrder);
ServiceImpl:
@Service
@Transactional
public class SysOrderServiceImpl implements ISysOrderService {
@Autowired
private SysOrderMapper sysOrderMapper;
@Autowired
private TaskService taskService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private IProcessService processService;
@Autowired
private RedisCache redisCache;
private String KEY = "orderKey";
private String TABLE_NAME = "sys_order";
@Override
public SysOrder selectSysOrderById(Long id) {
return sysOrderMapper.selectSysOrderById(id);
}
@Override
public List<SysOrder> selectSysOrderList(SysOrder sysOrder) {
sysOrder.setUserName(SecurityUtils.getUsername());
return sysOrderMapper.selectOwnList(sysOrder);
}
@Override
public Long insertSysOrder(SysOrder sysOrder) {
sysOrder.setType(redisCache.getCacheObject(KEY));
sysOrder.setCreateBy(SecurityUtils.getUsername());
sysOrder.setCreateTime(DateUtils.getNowDate());
sysOrderMapper.insertSysOrder(sysOrder);
return sysOrder.getId();
}
@Override
public int updateSysOrder(SysOrder sysOrder) {
if (sysOrder.getId() == null || sysOrder.getId() < 0) throw new UtilException("请选择要修改的工单");
SysOrder order = selectSysOrderById(sysOrder.getId());
sysOrder.setUpdateTime(DateUtils.getNowDate());
sysOrder.setUpdateBy(SecurityUtils.getUsername());
return sysOrderMapper.updateSysOrder(sysOrder);
}
@Override
public int deleteSysOrderByIds(Long[] ids) {
for (int i = 0; i < ids.length; i++) {
deleteSysOrderById(ids[i]);
}
return ids.length;
}
@Override
public int deleteSysOrderById(Long id) {
SysOrder order = selectSysOrderById(id);
order.setValid("1");
return updateSysOrder(order);
}
@Override
public ProcessInstance submitApply(Long id, String applyUser, String key) {
SysOrder entity = selectSysOrderById(id);
String businessKey = entity.getId().toString(); // 实体类 ID,作为流程的业务 key
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("createBy", applyUser);
variables.put("headerBy", entity.getHeaderBy());
variables.put("outBy", SecurityUtils.getUsername());
ProcessInstance processInstance = processService.submitApproval(applyUser, businessKey, key, variables);
String processInstanceId = processInstance.getId();
entity.setInstanceId(processInstanceId); // 建立双向关系
sysOrderMapper.updateSysOrder(entity);
return processInstance;
}
@Override
public ProcessInstance submitApply2(SysOrder sysOrder, String key) {
if (null == sysOrder.getId() || sysOrder.getId() < 0) throw new UtilException("请选择工单");
if (null == sysOrder.getHeaderBy()) throw new UtilException("请选择部门主管");
String businessKey = sysOrder.getId().toString(); // 实体类 ID,作为流程的业务 key
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("createBy", SecurityUtils.getUsername());
variables.put("headerBy", sysOrderBasic.getHeaderBy());
variables.put("outBy", SecurityUtils.getUsername());
ProcessInstance processInstance = processService.submitApproval(SecurityUtils.getUsername(), businessKey, key, variables);
String processInstanceId = processInstance.getId();
sysOrder.setInstanceId(processInstanceId); // 建立双向关系
sysOrderMapper.updateSysOrder(sysOrder);
return processInstance;
}
@Override
public ProcessInstance addAndSubmit(SysOrder sysOrder) {
Long id = insertSysOrder(sysOrder);
String applyUserId = SecurityUtils.getUsername();
return submitApply(id, applyUserId, redisCache.getCacheObject(KEY));
}
@Override
public List<SysOrder> findTodoTasks(SysOrder sysOrder) {
sysOrder.setUserName(SecurityUtils.getUsername());
return sysOrderMapper.selectProcessTodo(sysOrder);
}
@Override
public List<SysOrder> findDoneTasks(SysOrder sysOrder) {
sysOrder.setUserName(SecurityUtils.getUsername());
List<SysOrder> sysOrders = sysOrderMapper.selectProcessDone(sysOrder);
return sysOrders;
}
@Override
public void complete(SysOrder sysOrder) {
if (sysOrder.getTaskId() == null) {
List<Task> taskList = taskService.createTaskQuery()
.processInstanceId(sysOrder.getInstanceId())
// .singleResult();
.list();
if (!CollectionUtils.isEmpty(taskList)) {
TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
sysOrder.setTaskId(task.getId());
}
}
Map<String, Object> map = processService.complete(sysOrder, redisCache.getCacheObject(KEY));
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(sysOrder.getInstanceId()).singleResult();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String parameterName = entry.getKey();
if (StringUtils.isEmpty(parameterName)) continue;
if ("attacheBy".equals(parameterName)) {
sysOrder.setId(Long.parseLong(processInstance.getBusinessKey()));
sysOrder.setAttacheBy(map.get(parameterName).toString());
sysOrderMapper.updateSysOrder(sysOrder);
}
if ("leaderBy".equals(parameterName)) {
sysOrder.setId(Long.parseLong(processInstance.getBusinessKey()));
sysOrder.setLeaderBy(map.get(parameterName).toString());
sysOrderMapper.updateSysOrder(sysOrder);
}
}
}
}
Mapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.order.mapper.SysOrderMapper">
<resultMap type="SysOrder" id="SysOrderResult">
<result property="id" column="id" />
<result property="instanceId" column="instance_id" />
<result property="type" column="type" />
<result property="description" column="description" />
<result property="disposeBy" column="dispose_by" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<result property="valid" column="valid" />
<result property="state" column="state" />
<result property="headerBy" column="header_by" />
<result property="attacheBy" column="attache_by" />
<result property="leaderBy" column="leader_by" />
<result property="outBy" column="out_by" />
<result property="outTime" column="out_time" />
<result property="userName" column="user_name" />
<result property="nickName" column="nick_name" />
<result property="disposeByName" column="dispose_by_name"/>
<result property="taskId" column="task_id" />
<result property="taskName" column="task_name" />
<result property="doneTime" column="done_time" />
<result property="taskDefinitionKey" column="task_definition_key" />
</resultMap>
<sql id="selectSysOrderVo">
select a.id, a.instance_id, a.type,
a.description, a.create_by, a.create_time, a.update_by, a.update_time, a.remark, a.valid, a.state, a.header_by, a.attache_by,
a.leader_by, a.out_by, a.out_time,u.user_name,u.nick_name
from sys_order a
left join sys_user u on a.create_by=u.user_name
</sql>
<select id="selectOwnList" parameterType="SysOrder" resultMap="SysOrderResult">
select * from (select a.*,b.`ID_` task_id, b.`NAME_` task_name,b.`SUSPENSION_STATE_`suspend_state,
b.`ASSIGNEE_` dispose_by,c.nick_name dispose_by_name ,b.PROC_DEF_ID_,d.nick_name
from sys_order a ,act_ru_task b ,sys_user c,sys_user d
where a.instance_id = b.`PROC_INST_ID_` and b.`ASSIGNEE_` = c.user_name and a.create_by=d.user_name
union all
select a.*,'' task_id,'' task_name,'' suspend_state,'' dispose_by, '' dispose_by_name,'' PROC_DEF_ID_,'' nick_name from sys_order_basic a
where a.instance_id is null) t
where t.create_by=#{userName}
order by t.id desc
</select>
<select id="selectSysOrderList" parameterType="SysOrder" resultMap="SysOrderResult">
<include refid="selectSysOrderVo"/>
<where>
<if test="instanceId != null and instanceId != ''"> and instance_id = #{instanceId}</if>
<if test="type != null and type != ''"> and type = #{type}</if>
<if test="description != null and description != ''"> and description = #{description}</if>
<if test="disposeBy != null and disposeBy != ''"> and dispose_by = #{disposeBy}</if>
<if test="valid != null and valid != ''"> and valid = #{valid}</if>
<if test="state != null and state != ''"> and state = #{state}</if>
<if test="headerBy != null and headerBy != ''"> and header_by = #{headerBy}</if>
<if test="attacheBy != null and attacheBy != ''"> and attache_by = #{attacheBy}</if>
<if test="leaderBy != null and leaderBy != ''"> and leader_by = #{leaderBy}</if>
<if test="outBy != null and outBy != ''"> and out_by = #{outBy}</if>
<if test="outTime != null "> and out_time = #{outTime}</if>and valid = 0
<if test="createBy != null and createBy != ''"> and a.create_by = #{createBy}</if>
</where>
order by create_time desc
</select>
<select id="selectProcessDone" parameterType="SysOrder" resultMap="SysOrderResult">
select a.*,b.`ID_` task_id, b.`NAME_` task_name,
b.`ASSIGNEE_` dispose_by_act,b.`END_TIME_` done_time,b.`TASK_DEF_KEY_` task_definition_key,
d.nick_name dispose_by_name_act ,
c.nick_name, concat(c.nick_name,'(',c.user_name,')') dispose_by_name
from sys_order a ,act_hi_taskinst b,sys_user c,sys_user d
where a.instance_id = b.`PROC_INST_ID_` and b.`ASSIGNEE_` = c.user_name and b.`ASSIGNEE_` = d.user_name
and b.`ASSIGNEE_` =#{userName}
and not exists (select * from act_ru_task ru where ru.`ID_` = b.`ID_`)
order by a.id desc,b.START_TIME_ desc
</select>
<select id="selectProcessTodo" parameterType="SysOrder" resultMap="SysOrderResult">
select a.*,b.`ID_` task_id, b.`NAME_` task_name,b.`SUSPENSION_STATE_`suspend_state,
b.`ASSIGNEE_` dispose_by,d.nick_name dispose_by_name ,b.`TASK_DEF_KEY_` task_definition_key,
c.nick_name,concat(c.nick_name,'(',c.user_name,')') dispose_by_name
from sys_order a ,act_ru_task b ,sys_user c ,sys_user d
where a.instance_id = b.`PROC_INST_ID_` and a.create_by = c.user_name and b.`ASSIGNEE_` = d.user_name
and b.`ASSIGNEE_`= #{userName}
order by a.id desc,b.CREATE_TIME_ desc
</select>
<select id="selectSysOrderById" parameterType="Long" resultMap="SysOrderResult">
<include refid="selectSysOrderVo"/>
where a.id = #{id}
</select>
<select id="selectSysOrderByMap" parameterType="map" resultMap="SysOrderResult">
<include refid="selectSysOrderBasicVo"/>
<where>
<trim suffixOverrides="and">
<if test="id!=null and id!=''">
a.id = #{id} and
</if>
<if test="type != null and type != ''">a.type = #{type} and </if>
</trim></where>
</select>
<insert id="insertSysOrder" parameterType="SysOrder" useGeneratedKeys="true" keyProperty="id">
insert into sys_order
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="instanceId != null">instance_id,</if>
<if test="type != null">type,</if>
<if test="description != null">description,</if>
<if test="disposeBy != null">dispose_by,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
<if test="state != null">state,</if>
<if test="headerBy != null">header_by,</if>
<if test="attacheBy != null">attache_by,</if>
<if test="leaderBy != null">leader_by,</if>
<if test="outBy != null">out_by,</if>
<if test="outTime != null">out_time,</if>valid,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="instanceId != null">#{instanceId},</if>
<if test="type != null">#{type},</if>
<if test="description != null">#{description},</if>
<if test="disposeBy != null">#{disposeBy},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
<if test="state != null">#{state},</if>
<if test="headerBy != null">#{headerBy},</if>
<if test="attacheBy != null">#{attacheBy},</if>
<if test="leaderBy != null">#{leaderBy},</if>
<if test="outBy != null">#{outBy},</if>
<if test="outTime != null">#{outTime},</if>0,
</trim>
</insert>
<update id="updateSysOrder" parameterType="SysOrder">
update sys_order
<trim prefix="SET" suffixOverrides=",">
<if test="instanceId != null">instance_id = #{instanceId},</if>
<if test="type != null">type = #{type},</if>
<if test="description != null">description = #{description},</if>
<if test="disposeBy != null">dispose_by = #{disposeBy},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="valid != null">valid = #{valid},</if>
<if test="state != null">state = #{state},</if>
<if test="headerBy != null">header_by = #{headerBy},</if>
<if test="attacheBy != null">attache_by = #{attacheBy},</if>
<if test="leaderBy != null">leader_by = #{leaderBy},</if>
<if test="outBy != null">out_by = #{outBy},</if>
<if test="outTime != null">out_time = #{outTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteSysOrderById" parameterType="Long">
delete from sys_order where id = #{id}
</delete>
<delete id="deleteSysOrderByIds" parameterType="String">
delete from sys_order where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>