From e37577f7fb4554b87c91ba775a9e15cce47f1ec4 Mon Sep 17 00:00:00 2001 From: tony <846249920@qq.com> Date: Tue, 13 Dec 2022 22:34:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B5=81=E7=A8=8B=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E6=9B=B4=E6=96=B0=E7=94=A8=E6=88=B7=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysExpressionController.java | 104 +++++ .../controller/FlowDefinitionController.java | 16 +- .../ruoyi/system/domain/SysExpression.java | 83 ++++ .../system/mapper/SysExpressionMapper.java | 61 +++ .../system/service/ISysExpressionService.java | 61 +++ .../impl/SysExpressionServiceImpl.java | 96 ++++ .../mapper/system/SysExpressionMapper.xml | 86 ++++ ruoyi-ui/src/api/flowable/definition.js | 9 + ruoyi-ui/src/api/system/expression.js | 44 ++ ruoyi-ui/src/assets/styles/index.scss | 382 ++++++++-------- .../src/components/Process/PropertyPanel.vue | 5 + .../components/Process/common/parseElement.js | 11 +- .../Process/components/nodePanel/task.vue | 428 ++++++++++++++---- ruoyi-ui/src/components/Process/index.vue | 6 +- .../src/components/flow/Expression/index.vue | 120 +++++ ruoyi-ui/src/components/flow/Role/index.vue | 200 ++++++++ ruoyi-ui/src/components/flow/User/index.vue | 235 ++++++++++ .../src/views/flowable/definition/model.vue | 8 +- .../task/finished/detail/flowview.vue | 4 - .../flowable/task/finished/detail/index.vue | 6 +- .../task/myProcess/detail/flowview.vue | 4 - .../flowable/task/myProcess/send/flowview.vue | 4 - .../views/flowable/task/record/flowview.vue | 4 - .../flowable/task/todo/detail/flowview.vue | 4 - .../views/flowable/task/todo/detail/index.vue | 141 +++--- .../src/views/system/expression/index.vue | 282 ++++++++++++ 26 files changed, 2037 insertions(+), 367 deletions(-) create mode 100755 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysExpressionController.java create mode 100755 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysExpression.java create mode 100755 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysExpressionMapper.java create mode 100755 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysExpressionService.java create mode 100755 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysExpressionServiceImpl.java create mode 100755 ruoyi-system/src/main/resources/mapper/system/SysExpressionMapper.xml create mode 100755 ruoyi-ui/src/api/system/expression.js create mode 100755 ruoyi-ui/src/components/flow/Expression/index.vue create mode 100644 ruoyi-ui/src/components/flow/Role/index.vue create mode 100644 ruoyi-ui/src/components/flow/User/index.vue create mode 100755 ruoyi-ui/src/views/system/expression/index.vue diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysExpressionController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysExpressionController.java new file mode 100755 index 00000000..99b3870e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysExpressionController.java @@ -0,0 +1,104 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.SysExpression; +import com.ruoyi.system.service.ISysExpressionService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 流程达式Controller + * + * @author ruoyi + * @date 2022-12-12 + */ +@RestController +@RequestMapping("/system/expression") +public class SysExpressionController extends BaseController +{ + @Autowired + private ISysExpressionService sysExpressionService; + + /** + * 查询流程达式列表 + */ + @PreAuthorize("@ss.hasPermi('system:expression:list')") + @GetMapping("/list") + public TableDataInfo list(SysExpression sysExpression) + { + startPage(); + List list = sysExpressionService.selectSysExpressionList(sysExpression); + return getDataTable(list); + } + + /** + * 导出流程达式列表 + */ + @PreAuthorize("@ss.hasPermi('system:expression:export')") + @Log(title = "流程达式", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysExpression sysExpression) + { + List list = sysExpressionService.selectSysExpressionList(sysExpression); + ExcelUtil util = new ExcelUtil(SysExpression.class); + util.exportExcel(response, list, "流程达式数据"); + } + + /** + * 获取流程达式详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:expression:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(sysExpressionService.selectSysExpressionById(id)); + } + + /** + * 新增流程达式 + */ + @PreAuthorize("@ss.hasPermi('system:expression:add')") + @Log(title = "流程达式", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysExpression sysExpression) + { + return toAjax(sysExpressionService.insertSysExpression(sysExpression)); + } + + /** + * 修改流程达式 + */ + @PreAuthorize("@ss.hasPermi('system:expression:edit')") + @Log(title = "流程达式", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysExpression sysExpression) + { + return toAjax(sysExpressionService.updateSysExpression(sysExpression)); + } + + /** + * 删除流程达式 + */ + @PreAuthorize("@ss.hasPermi('system:expression:remove')") + @Log(title = "流程达式", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(sysExpressionService.deleteSysExpressionByIds(ids)); + } +} diff --git a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowDefinitionController.java b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowDefinitionController.java index e6000a86..67895020 100644 --- a/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowDefinitionController.java +++ b/ruoyi-flowable/src/main/java/com/ruoyi/flowable/controller/FlowDefinitionController.java @@ -3,9 +3,12 @@ package com.ruoyi.flowable.controller; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.system.domain.FlowProcDefDto; import com.ruoyi.flowable.domain.dto.FlowSaveXmlVo; import com.ruoyi.flowable.service.IFlowDefinitionService; +import com.ruoyi.system.domain.SysExpression; +import com.ruoyi.system.service.ISysExpressionService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; import io.swagger.annotations.Api; @@ -13,6 +16,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -50,14 +54,15 @@ public class FlowDefinitionController { @Resource private ISysRoleService sysRoleService; - + @Resource + private ISysExpressionService sysExpressionService; @GetMapping(value = "/list") @ApiOperation(value = "流程定义列表", response = FlowProcDefDto.class) public AjaxResult list(@ApiParam(value = "当前页码", required = true) @RequestParam Integer pageNum, @ApiParam(value = "每页条数", required = true) @RequestParam Integer pageSize, @ApiParam(value = "流程名称", required = false) @RequestParam(required = false) String name) { - return AjaxResult.success(flowDefinitionService.list(name,pageNum, pageSize)); + return AjaxResult.success(flowDefinitionService.list(name, pageNum, pageSize)); } @@ -189,4 +194,11 @@ public class FlowDefinitionController { return AjaxResult.success(list); } + @ApiOperation(value = "指定流程达式列表") + @GetMapping("/expList") + public AjaxResult expList(SysExpression sysExpression) { + List list = sysExpressionService.selectSysExpressionList(sysExpression); + return AjaxResult.success(list); + } + } \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysExpression.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysExpression.java new file mode 100755 index 00000000..225af0de --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysExpression.java @@ -0,0 +1,83 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 流程达式对象 sys_expression + * + * @author ruoyi + * @date 2022-12-12 + */ +public class SysExpression extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 表单主键 */ + private Long id; + + /** 表达式名称 */ + @Excel(name = "表达式名称") + private String name; + + /** 表达式内容 */ + @Excel(name = "表达式内容") + private String expression; + + /** 状态 */ + private Integer status; + + public void setId(Long id) + { + this.id = id; + } + + public Long getId() + { + return id; + } + public void setName(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } + public void setExpression(String expression) + { + this.expression = expression; + } + + public String getExpression() + { + return expression; + } + public void setStatus(Integer status) + { + this.status = status; + } + + public Integer getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("name", getName()) + .append("expression", getExpression()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("createBy", getCreateBy()) + .append("updateBy", getUpdateBy()) + .append("status", getStatus()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysExpressionMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysExpressionMapper.java new file mode 100755 index 00000000..4142ebbb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysExpressionMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysExpression; + +/** + * 流程达式Mapper接口 + * + * @author ruoyi + * @date 2022-12-12 + */ +public interface SysExpressionMapper +{ + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + public SysExpression selectSysExpressionById(Long id); + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式集合 + */ + public List selectSysExpressionList(SysExpression sysExpression); + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int insertSysExpression(SysExpression sysExpression); + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int updateSysExpression(SysExpression sysExpression); + + /** + * 删除流程达式 + * + * @param id 流程达式主键 + * @return 结果 + */ + public int deleteSysExpressionById(Long id); + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysExpressionByIds(Long[] ids); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysExpressionService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysExpressionService.java new file mode 100755 index 00000000..e748490b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysExpressionService.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysExpression; + +/** + * 流程达式Service接口 + * + * @author ruoyi + * @date 2022-12-12 + */ +public interface ISysExpressionService +{ + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + public SysExpression selectSysExpressionById(Long id); + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式集合 + */ + public List selectSysExpressionList(SysExpression sysExpression); + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int insertSysExpression(SysExpression sysExpression); + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + public int updateSysExpression(SysExpression sysExpression); + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的流程达式主键集合 + * @return 结果 + */ + public int deleteSysExpressionByIds(Long[] ids); + + /** + * 删除流程达式信息 + * + * @param id 流程达式主键 + * @return 结果 + */ + public int deleteSysExpressionById(Long id); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysExpressionServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysExpressionServiceImpl.java new file mode 100755 index 00000000..677d018f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysExpressionServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.mapper.SysExpressionMapper; +import com.ruoyi.system.domain.SysExpression; +import com.ruoyi.system.service.ISysExpressionService; + +/** + * 流程达式Service业务层处理 + * + * @author ruoyi + * @date 2022-12-12 + */ +@Service +public class SysExpressionServiceImpl implements ISysExpressionService +{ + @Autowired + private SysExpressionMapper sysExpressionMapper; + + /** + * 查询流程达式 + * + * @param id 流程达式主键 + * @return 流程达式 + */ + @Override + public SysExpression selectSysExpressionById(Long id) + { + return sysExpressionMapper.selectSysExpressionById(id); + } + + /** + * 查询流程达式列表 + * + * @param sysExpression 流程达式 + * @return 流程达式 + */ + @Override + public List selectSysExpressionList(SysExpression sysExpression) + { + return sysExpressionMapper.selectSysExpressionList(sysExpression); + } + + /** + * 新增流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + @Override + public int insertSysExpression(SysExpression sysExpression) + { + sysExpression.setCreateTime(DateUtils.getNowDate()); + return sysExpressionMapper.insertSysExpression(sysExpression); + } + + /** + * 修改流程达式 + * + * @param sysExpression 流程达式 + * @return 结果 + */ + @Override + public int updateSysExpression(SysExpression sysExpression) + { + sysExpression.setUpdateTime(DateUtils.getNowDate()); + return sysExpressionMapper.updateSysExpression(sysExpression); + } + + /** + * 批量删除流程达式 + * + * @param ids 需要删除的流程达式主键 + * @return 结果 + */ + @Override + public int deleteSysExpressionByIds(Long[] ids) + { + return sysExpressionMapper.deleteSysExpressionByIds(ids); + } + + /** + * 删除流程达式信息 + * + * @param id 流程达式主键 + * @return 结果 + */ + @Override + public int deleteSysExpressionById(Long id) + { + return sysExpressionMapper.deleteSysExpressionById(id); + } +} diff --git a/ruoyi-system/src/main/resources/mapper/system/SysExpressionMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysExpressionMapper.xml new file mode 100755 index 00000000..ef3a605c --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysExpressionMapper.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + select id, name, expression, create_time, update_time, create_by, update_by, status, remark from sys_expression + + + + + + + + insert into sys_expression + + name, + expression, + create_time, + update_time, + create_by, + update_by, + status, + remark, + + + #{name}, + #{expression}, + #{createTime}, + #{updateTime}, + #{createBy}, + #{updateBy}, + #{status}, + #{remark}, + + + + + update sys_expression + + name = #{name}, + expression = #{expression}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + status = #{status}, + remark = #{remark}, + + where id = #{id} + + + + delete from sys_expression where id = #{id} + + + + delete from sys_expression where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-ui/src/api/flowable/definition.js b/ruoyi-ui/src/api/flowable/definition.js index d2243df9..535850c8 100644 --- a/ruoyi-ui/src/api/flowable/definition.js +++ b/ruoyi-ui/src/api/flowable/definition.js @@ -53,6 +53,15 @@ export function roleList(query) { }) } +// 指定流程表达式 +export function expList(query) { + return request({ + url: '/flowable/definition/expList', + method: 'get', + params: query + }) +} + // 读取xml文件 export function readXml(deployId) { return request({ diff --git a/ruoyi-ui/src/api/system/expression.js b/ruoyi-ui/src/api/system/expression.js new file mode 100755 index 00000000..4a6ed96d --- /dev/null +++ b/ruoyi-ui/src/api/system/expression.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询流程达式列表 +export function listExpression(query) { + return request({ + url: '/system/expression/list', + method: 'get', + params: query + }) +} + +// 查询流程达式详细 +export function getExpression(id) { + return request({ + url: '/system/expression/' + id, + method: 'get' + }) +} + +// 新增流程达式 +export function addExpression(data) { + return request({ + url: '/system/expression', + method: 'post', + data: data + }) +} + +// 修改流程达式 +export function updateExpression(data) { + return request({ + url: '/system/expression', + method: 'put', + data: data + }) +} + +// 删除流程达式 +export function delExpression(id) { + return request({ + url: '/system/expression/' + id, + method: 'delete' + }) +} diff --git a/ruoyi-ui/src/assets/styles/index.scss b/ruoyi-ui/src/assets/styles/index.scss index 9f536ae8..96095ef6 100644 --- a/ruoyi-ui/src/assets/styles/index.scss +++ b/ruoyi-ui/src/assets/styles/index.scss @@ -1,191 +1,191 @@ -@import './variables.scss'; -@import './mixin.scss'; -@import './transition.scss'; -@import './element-ui.scss'; -@import './sidebar.scss'; -@import './btn.scss'; - -body { - height: 100%; - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; - font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; -} - -label { - font-weight: 700; -} - -html { - height: 100%; - box-sizing: border-box; -} - -#app { - height: 100%; -} - -*, -*:before, -*:after { - box-sizing: inherit; -} - -.no-padding { - padding: 0px !important; -} - -.padding-content { - padding: 4px 0; -} - -a:focus, -a:active { - outline: none; -} - -a, -a:focus, -a:hover { - cursor: pointer; - color: inherit; - text-decoration: none; -} - -div:focus { - outline: none; -} - -.fr { - float: right; -} - -.fl { - float: left; -} - -.pr-5 { - padding-right: 5px; -} - -.pl-5 { - padding-left: 5px; -} - -.block { - display: block; -} - -.pointer { - cursor: pointer; -} - -.inlineBlock { - display: block; -} - -.clearfix { - &:after { - visibility: hidden; - display: block; - font-size: 0; - content: " "; - clear: both; - height: 0; - } -} - -aside { - background: #eef1f6; - padding: 8px 24px; - margin-bottom: 20px; - border-radius: 2px; - display: block; - line-height: 32px; - font-size: 16px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; - color: #2c3e50; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - a { - color: #337ab7; - cursor: pointer; - - &:hover { - color: rgb(32, 160, 255); - } - } -} - -//main-container全局样式 -.app-container { - padding: 20px; -} - -.components-container { - margin: 30px 50px; - position: relative; -} - -.pagination-container { - margin-top: 30px; -} - -.text-center { - text-align: center -} - -.sub-navbar { - height: 50px; - line-height: 50px; - position: relative; - width: 100%; - text-align: right; - padding-right: 20px; - transition: 600ms ease position; - background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); - - .subtitle { - font-size: 20px; - color: #fff; - } - - &.draft { - background: #d0d0d0; - } - - &.deleted { - background: #d0d0d0; - } -} - -.link-type, -.link-type:focus { - color: #337ab7; - cursor: pointer; - - &:hover { - color: rgb(32, 160, 255); - } -} - -.filter-container { - padding-bottom: 10px; - - .filter-item { - display: inline-block; - vertical-align: middle; - margin-bottom: 10px; - } -} - -//refine vue-multiselect plugin -.multiselect { - line-height: 16px; -} - -.multiselect--active { - z-index: 1000 !important; -} +@import './variables.scss'; +@import './mixin.scss'; +@import './transition.scss'; +@import './element-ui.scss'; +@import './sidebar.scss'; +@import './btn.scss'; + +body { + height: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; +} + +label { + font-weight: 700; +} + +html { + height: 100%; + box-sizing: border-box; +} + +#app { + height: 100%; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +.no-padding { + padding: 0px !important; +} + +.padding-content { + padding: 4px 0; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.fr { + float: right; +} + +.fl { + float: left; +} + +.pr-5 { + padding-right: 5px; +} + +.pl-5 { + padding-left: 5px; +} + +.block { + display: block; +} + +.pointer { + cursor: pointer; +} + +.inlineBlock { + display: block; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } +} + +aside { + background: #eef1f6; + padding: 8px 24px; + margin-bottom: 20px; + border-radius: 2px; + display: block; + line-height: 32px; + font-size: 16px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + color: #2c3e50; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + a { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } + } +} + +//main-container全局样式 +.app-container { + padding: 20px; +} + +.components-container { + margin: 30px 50px; + position: relative; +} + +.pagination-container { + margin-top: 30px; +} + +.text-center { + text-align: center +} + +.sub-navbar { + height: 50px; + line-height: 50px; + position: relative; + width: 100%; + text-align: right; + padding-right: 20px; + transition: 600ms ease position; + background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); + + .subtitle { + font-size: 20px; + color: #fff; + } + + &.draft { + background: #d0d0d0; + } + + &.deleted { + background: #d0d0d0; + } +} + +.link-type, +.link-type:focus { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } +} + +.filter-container { + padding-bottom: 10px; + + .filter-item { + display: inline-block; + vertical-align: middle; + margin-bottom: 10px; + } +} + +//refine vue-multiselect plugin +.multiselect { + line-height: 16px; +} + +.multiselect--active { + z-index: 1000 !important; +} diff --git a/ruoyi-ui/src/components/Process/PropertyPanel.vue b/ruoyi-ui/src/components/Process/PropertyPanel.vue index 970bd0f8..334c2b15 100644 --- a/ruoyi-ui/src/components/Process/PropertyPanel.vue +++ b/ruoyi-ui/src/components/Process/PropertyPanel.vue @@ -8,6 +8,7 @@ :modeler="modeler" :users="users" :groups="groups" + :exps="exps" :categorys="categorys" @dataType="dataType" /> @@ -38,6 +39,10 @@ export default { type: Array, required: true }, + exps: { + type: Array, + default: () => [] + }, modeler: { type: Object, required: true diff --git a/ruoyi-ui/src/components/Process/common/parseElement.js b/ruoyi-ui/src/components/Process/common/parseElement.js index 63cf336e..fdc6064b 100644 --- a/ruoyi-ui/src/components/Process/common/parseElement.js +++ b/ruoyi-ui/src/components/Process/common/parseElement.js @@ -41,10 +41,19 @@ export function userTaskParse(obj) { for (const key in obj) { if (key === 'candidateUsers') { obj.userType = 'candidateUsers' - obj[key] = obj[key]?.split(',') || [] + // if (obj[key].toString().indexOf(",") !== -1) { + // + // }else { + // obj[key] = obj[key].toString()?.split(',') || [] + // } } else if (key === 'candidateGroups') { obj.userType = 'candidateGroups' obj[key] = obj[key]?.split(',') || [] + // if (obj[key].toString().indexOf(",") !== -1) { + // + // }else { + // obj[key] = obj[key].toString()?.split(',') || [] + // } } else if (key === 'assignee') { obj.userType = 'assignee' } diff --git a/ruoyi-ui/src/components/Process/components/nodePanel/task.vue b/ruoyi-ui/src/components/Process/components/nodePanel/task.vue index dae7e303..ee0b891a 100644 --- a/ruoyi-ui/src/components/Process/components/nodePanel/task.vue +++ b/ruoyi-ui/src/components/Process/components/nodePanel/task.vue @@ -16,6 +16,32 @@ 编辑 + + + + + + + + 取 消 + 确 定 + + + + + + + 取 消 + 确 定 + + + + + + + 取 消 + 确 定 + + @@ -44,11 +112,19 @@ import executionListenerDialog from './property/executionListener' import taskListenerDialog from './property/taskListener' import multiInstanceDialog from './property/multiInstance' import { commonParse, userTaskParse } from '../../common/parseElement' +import FlowUser from '@/components/flow/User' +import FlowRole from '@/components/flow/Role' +import FlowExp from '@/components/flow/Expression' +import log from "@/views/monitor/job/log"; + export default { components: { executionListenerDialog, taskListenerDialog, - multiInstanceDialog + multiInstanceDialog, + FlowUser, + FlowRole, + FlowExp, }, mixins: [mixinPanel], props: { @@ -59,6 +135,10 @@ export default { groups: { type: Array, required: true + }, + exps: { + type: Array, + required: true } }, data() { @@ -66,7 +146,7 @@ export default { userTypeOption: [ { label: '指定人员', value: 'assignee' }, { label: '候选人员', value: 'candidateUsers' }, - { label: '候选组', value: 'candidateGroups' } + { label: '候选角色', value: 'candidateGroups' } ], dataTypeOption: [ { label: '固定', value: 'fixed' }, @@ -76,7 +156,23 @@ export default { executionListenerLength: 0, taskListenerLength: 0, hasMultiInstance: false, - formData: {} + userVisible: false, + roleVisible: false, + expVisible: false, + formData: {}, + assignee: null, + candidateUsers: "", + candidateGroups: null, + // 选类型 + checkType: 'single', + // 选中的值 + checkValues: null, + // 用户列表 + userList: this.users, + groupList: this.groups, + expList: this.exps, + // 表达式类型 + expType: null, } }, computed: { @@ -116,63 +212,65 @@ export default { { xType: 'select', name: 'userType', - label: '人员类型', + label: '用户类型', dic: _this.userTypeOption, show: !!_this.showConfig.userType }, - { - xType: 'radio', - name: 'dataType', - label: '指定方式', - dic: _this.dataTypeOption, - show: !!_this.showConfig.dataType, - rules: [{ required: true, message: '请指定方式' }] - }, // { - // xType: 'input', - // name: 'assigneeFixed', - // label: '指定人(表达式)', - // show: !!_this.showConfig.assigneeFixed && _this.formData.userType === 'assignee' && _this.formData.dataType === 'fixed' + // xType: 'radio', + // name: 'dataType', + // label: '指定方式', + // dic: _this.dataTypeOption, + // show: !!_this.showConfig.dataType, + // rules: [{ required: true, message: '请指定方式' }] // }, // { - // xType: 'input', - // name: 'candidateUsersFixed', - // label: '候选人(表达式)', - // show: !!_this.showConfig.candidateUsersFixed && _this.formData.userType === 'candidateUsers' && _this.formData.dataType === 'fixed' + // xType: 'select', + // name: 'assignee', + // label: '指定人员', + // allowCreate: true, + // filterable: true, + // dic: { data: _this.users, label: 'nickName', value: 'userId' }, + // show: !!_this.showConfig.assignee && _this.formData.userType === 'assignee' // }, // { - // xType: 'input', - // name: 'candidateGroupsFixed', - // label: '候选组(表达式)', - // show: !!_this.showConfig.candidateGroupsFixed && _this.formData.userType === 'candidateGroups' && _this.formData.dataType === 'fixed' + // xType: 'select', + // name: 'candidateUsers', + // label: '候选人员', + // multiple: true, + // allowCreate: true, + // filterable: true, + // dic: { data: _this.users, label: 'nickName', value: 'userId' }, + // show: !!_this.showConfig.candidateUsers && _this.formData.userType === 'candidateUsers' + // }, + // { + // xType: 'select', + // name: 'candidateGroups', + // label: '候选组', + // multiple: true, + // allowCreate: true, + // filterable: true, + // dic: { data: _this.groups, label: 'roleName', value: 'roleId' }, + // show: !!_this.showConfig.candidateGroups && _this.formData.userType === 'candidateGroups' // }, { - xType: 'select', - name: 'assignee', + xType: 'slot', + name: 'checkSingleUser', label: '指定人员', - allowCreate: true, - filterable: true, - dic: { data: _this.users, label: 'nickName', value: 'userId' }, + // rules: [{ required: true, message: '指定人员不能为空' }], + // dic: { data: _this.users, label: 'nickName', value: 'userId' }, show: !!_this.showConfig.assignee && _this.formData.userType === 'assignee' }, { - xType: 'select', - name: 'candidateUsers', + xType: 'slot', + name: 'checkMultipleUser', label: '候选人员', - multiple: true, - allowCreate: true, - filterable: true, - dic: { data: _this.users, label: 'nickName', value: 'userId' }, show: !!_this.showConfig.candidateUsers && _this.formData.userType === 'candidateUsers' }, { - xType: 'select', - name: 'candidateGroups', - label: '候选组', - multiple: true, - allowCreate: true, - filterable: true, - dic: { data: _this.groups, label: 'roleName', value: 'roleId' }, + xType: 'slot', + name: 'checkRole', + label: '候选角色', show: !!_this.showConfig.candidateGroups && _this.formData.userType === 'candidateGroups' }, { @@ -280,50 +378,51 @@ export default { types.forEach(type => { delete this.element.businessObject.$attrs[`flowable:${type}`] delete this.formData[type] + this.updateProperties({'flowable:userType': type}) }) } }, - // 动态选择流程执行人 - 'formData.dataType': function(val) { - const that = this - this.updateProperties({'flowable:dataType': val}) - if (val === 'dynamic') { - this.updateProperties({'flowable:userType': that.formData.userType}) - } - // 切换时 删除之前选中的值 - const types = ['assignee', 'candidateUsers', 'candidateGroups'] - types.forEach(type => { - delete this.element.businessObject.$attrs[`flowable:${type}`] - delete this.formData[type] - }) - // 传值到父组件 - const params = { - dataType: val, - userType: this.formData.userType - } - this.$emit('dataType', params) - }, - 'formData.assignee': function(val) { - if (this.formData.userType !== 'assignee') { - delete this.element.businessObject.$attrs[`flowable:assignee`] - return - } - this.updateProperties({'flowable:assignee': val}) - }, - 'formData.candidateUsers': function(val) { - if (this.formData.userType !== 'candidateUsers') { - delete this.element.businessObject.$attrs[`flowable:candidateUsers`] - return - } - this.updateProperties({'flowable:candidateUsers': val?.join(',')}) - }, - 'formData.candidateGroups': function(val) { - if (this.formData.userType !== 'candidateGroups') { - delete this.element.businessObject.$attrs[`flowable:candidateGroups`] - return - } - this.updateProperties({'flowable:candidateGroups': val?.join(',')}) - }, + // // 动态选择流程执行人 + // 'formData.dataType': function(val) { + // const that = this + // this.updateProperties({'flowable:dataType': val}) + // if (val === 'dynamic') { + // this.updateProperties({'flowable:userType': that.formData.userType}) + // } + // // 切换时 删除之前选中的值 + // const types = ['assignee', 'candidateUsers', 'candidateGroups'] + // types.forEach(type => { + // delete this.element.businessObject.$attrs[`flowable:${type}`] + // delete this.formData[type] + // }) + // // 传值到父组件 + // const params = { + // dataType: val, + // userType: this.formData.userType + // } + // this.$emit('dataType', params) + // }, + // 'formData.assignee': function(val) { + // if (this.formData.userType !== 'assignee') { + // delete this.element.businessObject.$attrs[`flowable:assignee`] + // return + // } + // this.updateProperties({'flowable:assignee': val}) + // }, + // 'formData.candidateUsers': function(val) { + // if (this.formData.userType !== 'candidateUsers') { + // delete this.element.businessObject.$attrs[`flowable:candidateUsers`] + // return + // } + // this.updateProperties({'flowable:candidateUsers': val?.join(',')}) + // }, + // 'formData.candidateGroups': function(val) { + // if (this.formData.userType !== 'candidateGroups') { + // delete this.element.businessObject.$attrs[`flowable:candidateGroups`] + // return + // } + // this.updateProperties({'flowable:candidateGroups': val?.join(',')}) + // }, 'formData.async': function(val) { if (val === '') val = null this.updateProperties({ 'flowable:async': val }) @@ -384,6 +483,7 @@ export default { this.computedExecutionListenerLength() this.computedTaskListenerLength() this.computedHasMultiInstance() + this.getCheckValues() }, methods: { computedExecutionListenerLength() { @@ -401,6 +501,81 @@ export default { this.hasMultiInstance = false } }, + // 数据回显 + getCheckValues(){ + const that = this; + console.log(that.element.businessObject,"this.element.businessObject") + const attrs = that.element.businessObject.$attrs; + const businessObject = that.element.businessObject; + // 指定用户 + if (attrs.hasOwnProperty("flowable:assignee")){ + const val = attrs["flowable:assignee"]; + // 查找是否动态指定人员(选中流程表达式) + if (attrs["flowable:dataType"] === "dynamic"){ + this.checkValues = that.expList.find(item => item.id == val).name; + }else { + this.checkValues = that.userList.find(item => item.userId == val).nickName; + } + // 候选用户 + } else if (attrs.hasOwnProperty("flowable:candidateUsers")) { + const val = attrs["flowable:candidateUsers"]; + if (attrs["flowable:dataType"] === "dynamic") { + this.checkValues = that.expList.find(item => item.id == val).name; + } else { + const array = []; + const vals = val.split(','); + vals.forEach(key => { + const user = that.userList.find(item => item.userId == key) + if (user) { + array.push(user.nickName); + } + }) + this.checkValues = array.join(','); + } + // if (val.indexOf(",") !== -1) { + // const vals = val.split(','); + // vals.forEach(key => { + // const user = that.userList.find(item => item.userId == key) + // if (user) { + // array.push(user.nickName); + // } + // }) + // this.checkValues = array.join(','); + // }else { + // const user = that.userList.find(item => item.userId == val); + // this.checkValues = user.nickName; + // } + } else if (businessObject.hasOwnProperty("candidateGroups")){ + // 候选角色信息 + const val = businessObject["candidateGroups"]; + if (attrs["flowable:dataType"] === "dynamic") { + this.checkValues = that.expList.find(item => item.id == val).name; + } else { + const array = []; + const vals = val.split(','); + vals.forEach(key => { + const role = that.groupList.find(item => item.roleId == key) + if (role) { + array.push(role.roleName); + } + }) + this.checkValues = array.join(','); + } + // if (val.indexOf(",") !== -1) { + // const vals = val.split(','); + // vals.forEach(key => { + // const role = that.groupList.find(item => item.roleId == key) + // if (role) { + // array.push(role.roleName); + // } + // }) + // this.checkValues = array.join(','); + // }else { + // const role = that.groupList.find(item => item.roleId == val); + // this.checkValues = role.roleName; + // } + } + }, finishExecutionListener() { if (this.dialogName === 'executionListenerDialog') { this.computedExecutionListenerLength() @@ -418,6 +593,93 @@ export default { this.computedHasMultiInstance() } this.dialogName = '' + }, + /*单选人员*/ + singleUserCheck(){ + this.userVisible = true; + this.checkType = "single"; + }, + /*多选人员*/ + multipleUserCheck(){ + this.userVisible = true; + this.checkType = "multiple"; + }, + /*单选角色*/ + singleRoleCheck(){ + this.roleVisible = true; + this.checkType = "single"; + }, + /*多选角色*/ + multipleRoleCheck(){ + this.roleVisible = true; + this.checkType = "multiple"; + }, + /*单选表达式*/ + singleExpCheck(expType){ + this.expVisible = true; + this.expType = expType; + }, + // 选中表达式 + handleSingleExpSelect(selection){ + this.deleteFlowAttar(); + console.log(this.element.businessObject,"element.businessObject") + this.updateProperties({'flowable:dataType': 'dynamic'}) + if ("assignee" === this.expType){ + this.updateProperties({'flowable:assignee': selection.id.toString()}); + }else if ("candidateUsers" === this.expType) { + this.updateProperties({'flowable:candidateUsers': selection.id.toString()}); + } + this.checkValues = selection.name; + this.expType = null; + }, + // 用户选中数据 + handleUserSelect(selection) { + console.log(selection,"handleUserSelect") + const that = this; + if (selection) { + that.deleteFlowAttar(); + this.updateProperties({'flowable:dataType': 'fixed'}) + if (selection instanceof Array){ + const userIds = selection.map(item => item.userId); + const nickName = selection.map(item => item.nickName); + that.updateProperties({'flowable:candidateUsers': userIds.join(',')}) + that.checkValues = nickName.join(','); + }else { + that.updateProperties({'flowable:assignee': selection.userId}) + that.checkValues = selection.nickName; + } + } + }, + // 角色选中数据 + handleRoleSelect(selection,name) { + const that = this; + if (selection && name) { + that.deleteFlowAttar(); + this.updateProperties({'flowable:dataType': 'fixed'}) + that.updateProperties({'flowable:candidateGroups': selection}); + that.checkValues = name; + } + }, + /*用户选中赋值*/ + checkUserComplete(){ + this.userVisible = false; + this.checkType = ""; + }, + /*候选角色选中赋值*/ + checkRoleComplete(){ + this.roleVisible = false; + this.checkType = ""; + }, + /*表达式选中赋值*/ + checkExpComplete(){ + this.expVisible = false; + }, + // 删除节点 + deleteFlowAttar(){ + delete this.element.businessObject.$attrs[`flowable:dataType`] + delete this.element.businessObject.$attrs[`flowable:assignee`] + delete this.element.businessObject.$attrs[`flowable:candidateUsers`] + delete this.element.businessObject.$attrs[`flowable:candidateGroups`] } } } diff --git a/ruoyi-ui/src/components/Process/index.vue b/ruoyi-ui/src/components/Process/index.vue index e5857d03..98aec9e9 100644 --- a/ruoyi-ui/src/components/Process/index.vue +++ b/ruoyi-ui/src/components/Process/index.vue @@ -41,7 +41,7 @@
- + @@ -79,6 +79,10 @@ export default { type: Array, default: () => [] }, + exps: { + type: Array, + default: () => [] + }, isView: { type: Boolean, default: false diff --git a/ruoyi-ui/src/components/flow/Expression/index.vue b/ruoyi-ui/src/components/flow/Expression/index.vue new file mode 100755 index 00000000..43930bd3 --- /dev/null +++ b/ruoyi-ui/src/components/flow/Expression/index.vue @@ -0,0 +1,120 @@ + + + diff --git a/ruoyi-ui/src/components/flow/Role/index.vue b/ruoyi-ui/src/components/flow/Role/index.vue new file mode 100644 index 00000000..97f3652e --- /dev/null +++ b/ruoyi-ui/src/components/flow/Role/index.vue @@ -0,0 +1,200 @@ + + + + diff --git a/ruoyi-ui/src/components/flow/User/index.vue b/ruoyi-ui/src/components/flow/User/index.vue new file mode 100644 index 00000000..397ede93 --- /dev/null +++ b/ruoyi-ui/src/components/flow/User/index.vue @@ -0,0 +1,235 @@ + + + + diff --git a/ruoyi-ui/src/views/flowable/definition/model.vue b/ruoyi-ui/src/views/flowable/definition/model.vue index e56a949a..315fcef1 100644 --- a/ruoyi-ui/src/views/flowable/definition/model.vue +++ b/ruoyi-ui/src/views/flowable/definition/model.vue @@ -6,6 +6,7 @@ :users="users" :groups="groups" :categorys="categorys" + :exps="exps" :is-view="false" @save="save" @showXML="showXML" @@ -24,7 +25,7 @@