Merge branch 'feature/develop1.8'

This commit is contained in:
qimingjin 2021-11-14 16:06:40 +08:00
commit 0b5190c86d
231 changed files with 8315 additions and 1965 deletions

View File

@ -161,6 +161,19 @@ V1.6 2021-05-17
- 5.0 重构钉钉回调注册管理
- 6.0 重构消息中心模块,支持站内信
- 7.0 重修复分配系统角色时会自动删除流程角色
V1.8 2021-11-14
- 1.0 新增系统任务模块
- 系统创建任务后,可同步到钉钉待办任务
- 2.0 解耦系统与钉钉的强依赖,新增是否同步配置
- 3.0 新增钉钉外部联系人模块
- 系统管理钉钉外部联系人
- 4.0 完善系统用户和钉钉用户同步机制
- 5.0 新增流程待办,流程完结,系统任务站内信消息通知
- 6.0 新增手机号,姓名,身份证,秘钥等重要隐私信息脱敏
- 7.0 重构部分代码
## 未来规划
- 1.0 表单设计器与流程结合

112
pom.xml
View File

@ -8,7 +8,7 @@
<version>2.0.0</version>
<name>snow</name>
<url>http://snowblog.shop.csj361.com</url>
<url>http://dingflow.xyz:9527</url>
<description>snow管理系统</description>
<properties>
@ -32,6 +32,18 @@
<velocity.version>1.7</velocity.version>
<flowable.version>6.4.1</flowable.version>
<dingtalk.version>dingtalk-SNAPSHOT</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>
<easyexcel.version>2.1.6</easyexcel.version>
<com.aliyun.oss.version>3.9.1</com.aliyun.oss.version>
<commons.lang.version>2.6</commons.lang.version>
<lombok.version>1.18.10</lombok.version>
<zhyd.oauth.version>1.15.6</zhyd.oauth.version>
<jsqlparser.version>1.4</jsqlparser.version>
<googlecode.aviator.version>2.3.3</googlecode.aviator.version>
<kotlin.stdlib.verson>1.3.70</kotlin.stdlib.verson>
</properties>
<!-- 依赖声明 -->
@ -178,7 +190,26 @@
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--hu-tool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.snow</groupId>
@ -235,7 +266,84 @@
<version>${snow.version}</version>
</dependency>
<!--支付宝-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>${com.alipay.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>${aliyun.dingtalk.version}</version>
</dependency>
<!--aliExcel解析包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<!--阿里云oss-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${com.aliyun.oss.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!--sql解析组装-->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>${jsqlparser.version}</version>
</dependency>
<!-- 第三方授权登录 -->
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
<version>${zhyd.oauth.version}</version>
</dependency>
<!--flowable工作流-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
</dependency>
<!--flowable整合设计器-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable.version}</version>
</dependency>
<!--Aviator是一个轻量级、高性能的Java表达式执行引擎它动态地将表达式编译成字节码并运行。可被用于动态的公式计算、规则执行和过滤等场景-->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>${googlecode.aviator.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.stdlib.verson}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -27,12 +27,6 @@
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>spring-boot-starter-jimureport</artifactId>
<version>1.3.21-beta</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--test-->
<dependency>
@ -47,31 +41,6 @@
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!--防止进入swagger页面报类型转换错误排除2.9.2中的引用手动增加1.5.21版本-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
<!-- swagger2-UI-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>

View File

@ -7,7 +7,6 @@ import com.snow.common.utils.StringUtils;
import com.snow.common.utils.file.FileUtils;
import com.snow.framework.storage.StorageService;
import com.snow.system.domain.SysFile;
import com.snow.system.service.impl.SysFileServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -19,7 +18,6 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.file.Path;
/**
* 通用请求处理
@ -43,14 +41,10 @@ public class CommonController
* @param fileKey 文件名称
*/
@GetMapping("common/download")
public void fileDownload(String fileKey ,HttpServletResponse response, HttpServletRequest request)
{
try
{
public void fileDownload(String fileKey ,HttpServletResponse response, HttpServletRequest request) {
try {
storageService.load(fileKey);
}
catch (Exception e)
{
} catch (Exception e) {
log.error("下载文件失败", e);
}
}
@ -60,19 +54,15 @@ public class CommonController
*/
@PostMapping("/common/upload")
@ResponseBody
public AjaxResult uploadFile(MultipartFile file)
{
try
{
public AjaxResult uploadFile(MultipartFile file) {
try {
SysFile store = storageService.store(file);
AjaxResult ajax = AjaxResult.success();
ajax.put("fileKey",store.getKey());
ajax.put("fileName", store.getName());
ajax.put("url", store.getUrl());
return ajax;
}
catch (Exception e)
{
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}

View File

@ -14,6 +14,7 @@ import com.snow.system.domain.DingtalkCallBack;
import com.snow.system.service.impl.DingtalkCallBackServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
@ -35,6 +36,8 @@ public class CallBackController {
@Autowired
private DingtalkCallBackServiceImpl dingtalkCallBackService;
@Value("${is.sync.dingtalk:false}")
private Boolean isSyncDingTalk;
private static final String EVENT_TYPE="EventType";
@ -63,7 +66,7 @@ public class CallBackController {
}
dingtalkCallBack=dingtalkCallBacks.get(0);
try {
log.info("begin callback------》 signature:{},timestamp:{},nonce:{},body:{}" ,signature,timestamp,nonce,body);
log.info("\n @@begin callback------》 signature:{},timestamp:{},nonce:{},body:{}" ,signature,timestamp,nonce,body);
DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(dingtalkCallBack.getToken(),dingtalkCallBack.getAesKey(),dingtalkCallBack.getCorpId());
// 从post请求的body中获取回调信息的加密数据进行解密处理
@ -81,14 +84,15 @@ public class CallBackController {
return dingTalkEncryptor.getEncryptedMap(Constants.CALL_BACK_SUCCESS_RETURN, timestamp, nonce);
}
//调用工厂模式异步处理数据
SyncSysInfoFactory syncSysInfoFactory = new SyncSysInfoFactory();
ISyncSysInfo iSyncSysInfo = syncSysInfoFactory.getSyncSysInfoService(type);
iSyncSysInfo.SyncSysInfo(type, callBackContent);
if(isSyncDingTalk){
SyncSysInfoFactory syncSysInfoFactory = new SyncSysInfoFactory();
ISyncSysInfo iSyncSysInfo = syncSysInfoFactory.getSyncSysInfoService(type);
iSyncSysInfo.SyncSysInfo(type, callBackContent);
}
// 返回success的加密信息表示回调处理成功
return dingTalkEncryptor.getEncryptedMap(Constants.CALL_BACK_SUCCESS_RETURN, timestamp, nonce);
} catch (Exception e) {
//todo 失败短信或者邮件通知并记录下数据
log.error("process callback fail------》 signature:{},timestamp:{},nonce:{},body:{}" ,signature,timestamp,nonce,body, e);
log.error("@@dingTalkCallBack fail------》 signature:{},timestamp:{},nonce:{},body:{}" ,signature,timestamp,nonce,body, e);
return Constants.CALL_BACK_FAIL_RETURN;
}
}

View File

@ -8,9 +8,9 @@ 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.DingFlowTaskType;
import com.snow.dingtalk.model.DingFinishTaskRequest;
import com.snow.dingtalk.model.DingTaskVO;
import com.snow.dingtalk.model.FlowExecuteTaskRequest;
import com.snow.dingtalk.model.request.DingFinishTaskRequest;
import com.snow.dingtalk.model.response.DingTaskResponse;
import com.snow.dingtalk.model.request.FlowExecuteTaskRequest;
import com.snow.dingtalk.service.impl.DingOfficialFlowServiceImpl;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysDingHiTask;
@ -176,7 +176,7 @@ public class DingTaskController extends BaseController
//获取任务节点
List<OapiProcessinstanceGetResponse.TaskTopVo> tasks = processInstanceDetail.getTasks();
DingTaskVO dingTaskVO=new DingTaskVO();
DingTaskResponse dingTaskVO=new DingTaskResponse();
if(CollectionUtil.isNotEmpty(tasks)){
tasks.stream().filter(taskTopVo -> taskTopVo.getTaskid().equals(sysDingHiTask.getTaskId())).collect(Collectors.toList()).forEach(t->{
BeanUtil.copyProperties(t,dingTaskVO);

View File

@ -0,0 +1,117 @@
package com.snow.web.controller.dingtalk;
import cn.hutool.core.util.ObjectUtil;
import com.dingtalk.api.response.OapiExtcontactListlabelgroupsResponse;
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.dingtalk.model.request.ExtContactUserRequest;
import com.snow.dingtalk.service.ExtContactUserService;
import com.snow.system.domain.SysUser;
import com.snow.system.service.ISysUserService;
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.*;
import java.util.List;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/11/4 11:01
*/
@Controller
@RequestMapping("/ding/extContactUser")
public class ExtContactUserController extends BaseController {
private String prefix = "ding/extContactUser";
@Autowired
private ExtContactUserService extContactUserService;
@Autowired
private ISysUserService userService;
@RequiresPermissions("system:extContactUser:view")
@GetMapping()
public String user()
{
return prefix + "/extContactUser";
}
@RequiresPermissions("system:extContactUser:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo getList() {
startPage();
List<ExtContactUserRequest> extContactUserList = extContactUserService.getExtContactUserList(null,null);
return pageBySubList(extContactUserList);
}
@GetMapping("/add")
public String add(ModelMap mmap)
{
List<OapiExtcontactListlabelgroupsResponse.OpenLabelGroup> extContactUserLabelGroupsList = extContactUserService.getExtContactUserLabelGroupsList();
mmap.put("label",extContactUserLabelGroupsList);
return prefix + "/add";
}
@RequiresPermissions("system:extContactUser:add")
@Log(title = "外部联系人", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(ExtContactUserRequest extContactUserRequest)
{
String extContactUser = extContactUserService.createExtContactUser(extContactUserRequest);
return AjaxResult.success(extContactUser);
}
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") String userid, ModelMap mmap)
{
ExtContactUserRequest extContactUserDetail = extContactUserService.getExtContactUserDetail(userid);
SysUser sysUser = userService.selectUserByDingUserId(userid);
if(ObjectUtil.isNotNull(sysUser)){
extContactUserDetail.setFollowerUserId(sysUser.getUserName());
}
mmap.put("extContactUser", extContactUserDetail);
return prefix + "/edit";
}
@RequiresPermissions("system:extContactUser:edit")
@Log(title = "外部联系人", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(ExtContactUserRequest extContactUserRequest)
{
return toAjax(extContactUserService.updateExtContactUser(extContactUserRequest));
}
@RequiresPermissions("system:extContactUser:remove")
@Log(title = "外部联系人", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(extContactUserService.deleteExtContactUser(ids));
}
@GetMapping("/detail/{id}")
@RequiresPermissions("system:extContactUser:detail")
public String detail(@PathVariable("id") String userId, ModelMap mmap)
{
ExtContactUserRequest extContactUserRequest = extContactUserService.getExtContactUserDetail(userId);
SysUser sysUser = userService.selectUserByDingUserId(userId);
if(ObjectUtil.isNotNull(sysUser)){
extContactUserRequest.setFollowerUserId(sysUser.getUserName());
}
mmap.put("extContactUser", extContactUserRequest);
return prefix + "/detail";
}
}

View File

@ -2,10 +2,7 @@ package com.snow.web.controller.dingtalk;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUtil;
import com.dingtalk.api.response.OapiProcessListbyuseridResponse;
import com.dingtalk.api.response.OapiProcessTemplateManageGetResponse;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.google.common.collect.Lists;
import com.snow.common.core.controller.BaseController;
@ -14,11 +11,14 @@ import com.snow.common.core.page.TableDataInfo;
import com.snow.common.enums.DingFlowOperationType;
import com.snow.common.enums.DingFlowTaskType;
import com.snow.common.utils.DateUtils;
import com.snow.dingtalk.model.*;
import com.snow.dingtalk.model.request.FlowExecuteTaskRequest;
import com.snow.dingtalk.model.request.FlowTerminateProcessInstanceRequest;
import com.snow.dingtalk.model.request.StartFlowRequest;
import com.snow.dingtalk.model.response.DingOperationRecordResponse;
import com.snow.dingtalk.model.response.DingTaskResponse;
import com.snow.dingtalk.service.impl.DingOfficialFlowServiceImpl;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysDingProcinst;
import com.snow.system.domain.SysDingRuTask;
import com.snow.system.domain.SysUser;
import com.snow.system.service.impl.SysDingProcinstServiceImpl;
import com.snow.system.service.impl.SysDingRuTaskServiceImpl;
@ -33,7 +33,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
@ -167,10 +166,10 @@ public class OfficialFlowController extends BaseController {
List<OapiProcessinstanceGetResponse.FormComponentValueVo> formComponentValues = processInstanceDetail.getFormComponentValues();
//获取操作记录
List<OapiProcessinstanceGetResponse.OperationRecordsVo> operationRecords = processInstanceDetail.getOperationRecords();
List<DingOperationRecordVO> dingOperationRecordVOList=Lists.newArrayList();
List<DingOperationRecordResponse> dingOperationRecordVOList=Lists.newArrayList();
if(CollectionUtil.isNotEmpty(operationRecords)){
operationRecords.forEach(t->{
DingOperationRecordVO dingOperationRecordVO=new DingOperationRecordVO();
DingOperationRecordResponse dingOperationRecordVO=new DingOperationRecordResponse();
BeanUtil.copyProperties(t,dingOperationRecordVO);
SysUser sysUser = sysUserService.selectUserByDingUserId(t.getUserid());
dingOperationRecordVO.setUserName(sysUser.getUserName());
@ -190,10 +189,10 @@ public class OfficialFlowController extends BaseController {
//获取任务节点
List<OapiProcessinstanceGetResponse.TaskTopVo> tasks = processInstanceDetail.getTasks();
List<DingTaskVO> dingTaskVOList=Lists.newArrayList();
List<DingTaskResponse> dingTaskVOList=Lists.newArrayList();
if(CollectionUtil.isNotEmpty(tasks)){
tasks.stream().filter(t->!t.getTaskStatus().equals(DingFlowTaskType.CANCELED.getCode())).collect(Collectors.toList()).forEach(t->{
DingTaskVO dingTaskVO=new DingTaskVO();
DingTaskResponse dingTaskVO=new DingTaskResponse();
BeanUtil.copyProperties(t,dingTaskVO);
dingTaskVO.defaultTaskSpendTime();
SysUser sysUser = sysUserService.selectUserByDingUserId(t.getUserid());

View File

@ -16,6 +16,7 @@ import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -50,8 +51,7 @@ public class FlowController extends BaseController {
* @return
*/
@GetMapping("/toFinishTask")
public String toFinishTask(String taskId,ModelMap mmap)
{
public String toFinishTask(String taskId,ModelMap mmap) {
Task task = flowableTaskService.getTask(taskId);
//获取业务参数
AppForm appFrom = appFormService.getAppFrom(task.getProcessInstanceId());
@ -69,8 +69,7 @@ public class FlowController extends BaseController {
@RequiresPermissions("system:flow:finishTask")
@ResponseBody
@RepeatSubmit
public AjaxResult finishTask(FinishTaskDTO finishTaskDTO)
{
public AjaxResult finishTask(FinishTaskDTO finishTaskDTO) {
SysUser sysUser = ShiroUtils.getSysUser();
finishTaskDTO.setUserId(String.valueOf(sysUser.getUserId()));
flowableTaskService.submitTask(finishTaskDTO);
@ -83,8 +82,7 @@ public class FlowController extends BaseController {
*/
@RequiresPermissions("flow:get:todoList")
@GetMapping("/toDoMyTask")
public String todoTask()
{
public String todoTask() {
return prefix+"/myTask";
}
@ -93,10 +91,9 @@ public class FlowController extends BaseController {
* 获取我的待办列表
*/
@RequiresPermissions("flow:get:todoList")
@PostMapping("/findTasksByUserId")
@RequestMapping("/findTasksByUserId")
@ResponseBody
public TableDataInfo findTasksByUserId(TaskBaseDTO taskBaseDTO)
{
public TableDataInfo findTasksByUserId(TaskBaseDTO taskBaseDTO) {
Long userId = ShiroUtils.getUserId();
PageModel<TaskVO> taskList = flowableTaskService.findTasksByUserId(String.valueOf(userId), taskBaseDTO);
return getFlowDataTable(taskList);
@ -120,8 +117,7 @@ public class FlowController extends BaseController {
*/
@RequiresPermissions("flow:get:getMyStartProcess")
@GetMapping("/toMyStartProcess")
public String getMyHistoricProcessInstance()
{
public String getMyHistoricProcessInstance() {
return prefix+"/myStartProcess";
}
@ -138,7 +134,6 @@ public class FlowController extends BaseController {
SysUser sysUser = ShiroUtils.getSysUser();
processInstanceDTO.setStartedUserId(String.valueOf(sysUser.getUserId()));
PageModel<ProcessInstanceVO> historicProcessInstance = flowableService.getHistoricProcessInstance(processInstanceDTO);
log.info(JSON.toJSONString(historicProcessInstance.getPagedRecords()));
return getFlowDataTable(historicProcessInstance);
}
@ -149,16 +144,17 @@ public class FlowController extends BaseController {
*/
@GetMapping("/myStartProcessDetail")
@RequiresPermissions("system:flow:myStartProcessDetail")
public String myStartProcessDetail(String processInstanceId,ModelMap modelMap)
{
//已审批的
public String myStartProcessDetail(String processInstanceId,ModelMap modelMap) {
ProcessInstanceVO processInstanceVo = flowableService.getProcessInstanceVoById(processInstanceId);
//已审批的任务
HistoricTaskInstanceDTO historicTaskInstanceDTO=new HistoricTaskInstanceDTO();
historicTaskInstanceDTO.setProcessInstanceId(processInstanceId);
//historicTaskInstanceDTO.setProcessStatus(1);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableTaskService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
//获取业务数据
AppForm appFrom = appFormService.getAppFrom(processInstanceId);
modelMap.put("historicTaskInstanceList",historicTaskInstanceList);
modelMap.put("processInstanceId",processInstanceId);
modelMap.put("processInstance",processInstanceVo);
modelMap.put("busVarUrl",appFrom.getBusVarUrl());
modelMap.put("appId",ReflectUtil.getFieldValue(appFrom,"id"));
return prefix +"/myStartProcessDetail";
@ -168,12 +164,11 @@ public class FlowController extends BaseController {
* 跳转我的已办
* @return
*/
@RequiresPermissions("flow:process:getMyTakePartInProcess")
@GetMapping("/toMyTakePartInProcess")
public String getMyTakePartInProcess()
{
@RequiresPermissions("flow:process:getMyTakePartInTask")
@GetMapping("/toMyTakePartInTask")
public String getMyTakePartInProcess() {
return prefix+"/myTakePartInProcess";
return prefix+"/my-taked";
}
/**
@ -181,16 +176,32 @@ public class FlowController extends BaseController {
* @param historicTaskInstanceDTO
* @return
*/
@RequiresPermissions("flow:process:getMyTakePartInProcess")
@PostMapping("/getMyTakePartInProcess")
@RequiresPermissions("flow:process:getMyTakePartInTask")
@PostMapping("/getMyTakePartInTask")
@ResponseBody
public TableDataInfo getMyTakePartInProcess(HistoricTaskInstanceDTO historicTaskInstanceDTO){
SysUser sysUser = ShiroUtils.getSysUser();
historicTaskInstanceDTO.setUserId(String.valueOf(sysUser.getUserId()));
PageModel<HistoricTaskInstanceVO> historicTaskInstance = flowableService.getHistoricTaskInstance(historicTaskInstanceDTO);
PageModel<HistoricTaskInstanceVO> historicTaskInstance = flowableTaskService.getHistoricTaskInstance(historicTaskInstanceDTO);
return getFlowDataTable(historicTaskInstance);
}
@RequiresPermissions("flow:process:myTaskedDetail")
@GetMapping("/getMyTaskedDetail")
public String getMyTaskedDetail(String taskId,ModelMap modelMap){
//获取任务实例
HistoricTaskInstanceVO hisTask = flowableTaskService.getHisTask(taskId);
//获取业务数据
AppForm appFrom = appFormService.getAppFrom(hisTask.getProcessInstanceId());
//获取流程实例
ProcessInstanceVO processInstanceVo = flowableService.getProcessInstanceVoById(hisTask.getProcessInstanceId());
modelMap.put("hisTask",hisTask);
modelMap.put("appFrom",appFrom);
modelMap.put("processInstance",processInstanceVo);
modelMap.put("busVarUrl",appFrom.getBusVarUrl());
modelMap.put("appId",ReflectUtil.getFieldValue(appFrom,"id"));
return prefix+"/my-task-detail";
}
/**
* 转办任务
* @return
@ -224,8 +235,7 @@ public class FlowController extends BaseController {
* 选择用户
*/
@GetMapping("/selectUser")
public String selectUser(String taskId,Integer flag,ModelMap mmap)
{
public String selectUser(String taskId,Integer flag,ModelMap mmap) {
mmap.put("taskId",taskId);
mmap.put("flag",flag);
return prefix + "/selectUser";
@ -236,8 +246,7 @@ public class FlowController extends BaseController {
@RequiresPermissions("flow:process:activeProcessInstance")
@ResponseBody
@RepeatSubmit
public AjaxResult activeProcessInstance(String id)
{
public AjaxResult activeProcessInstance(String id) {
flowableService.suspendOrActiveProcessInstance(id,FlowInstanceEnum.ACTIVATE.getCode());
return AjaxResult.success();
}
@ -246,10 +255,40 @@ public class FlowController extends BaseController {
@RequiresPermissions("flow:process:suspendProcessInstance")
@ResponseBody
@RepeatSubmit
public AjaxResult suspendProcessInstance(String id)
{
public AjaxResult suspendProcessInstance(String id) {
flowableService.suspendOrActiveProcessInstance(id,FlowInstanceEnum.SUSPEND.getCode());
return AjaxResult.success();
}
/**
* 跳转任务详情界面
* @return 跳转的页面
*/
@GetMapping("/toTaskDetail")
public String toTaskDetail(String taskId,ModelMap mmap) {
TaskVO task = flowableTaskService.getHisTask(taskId);
//获取业务参数
AppForm appFrom = appFormService.getAppFrom(task.getProcessInstanceId());
mmap.put("appFrom", appFrom);
mmap.put("taskId", taskId);
mmap.put("processInstanceId", task.getProcessInstanceId());
return task.getFormKey();
}
/**
* 取消流程
* @param id 流程实例id
* @param reason 理由
* @return
*/
@PostMapping("/cancelProcessInstance")
@RequiresPermissions("flow:process:cancelProcessInstance")
@ResponseBody
@RepeatSubmit
public AjaxResult cancelProcessInstanceFlag(String id,String reason) {
flowableService.cancelProcessInstance(id,reason);
return AjaxResult.success();
}
}

View File

@ -73,6 +73,14 @@ public class FlowModelerController extends BaseController
return prefix + "/deployment";
}
@RequiresPermissions("modeler:deployment:detail")
@GetMapping("/getDeploymentDetail/{id}")
public String getDeploymentDetail(@PathVariable("id")String id , ModelMap modelMap) {
DeploymentVO deploymentDetailById = flowableService.getDeploymentDetailById(id);
modelMap.put("deploymentVO",deploymentDetailById);
return prefix + "/deployment-detail";
}
/**
* 查询发布实例列表
*/

View File

@ -57,14 +57,14 @@ public class FlowUserController extends BaseController {
*/
@GetMapping(value = "/rest/getUserGroupList")
public FlowRemoteVO getUserGroupList(@RequestParam(value = "filter",required = false) String filter) {
startPage();
List<RemoteGroup> flowUserGroupList = flowableUserService.getFlowUserGroupList(filter);
TableDataInfo dataTable = getDataTable(flowUserGroupList);
List<RemoteGroup> flowUserGroupList = flowableUserService.getLinkFlowUserGroupList(filter);
FlowRemoteVO flowRemoteVO = new FlowRemoteVO();
flowRemoteVO.setData(dataTable.getRows());
flowRemoteVO.setSize(dataTable.getPageSize());
flowRemoteVO.setStart(dataTable.getPageIndex());
flowRemoteVO.setTotal(dataTable.getTotal());
flowRemoteVO.setData(flowUserGroupList);
// flowRemoteVO.setSize(dataTable.getPageSize());
// flowRemoteVO.setStart(dataTable.getPageIndex());
flowRemoteVO.setTotal(flowUserGroupList.size());
return flowRemoteVO;
}
}

View File

@ -3,32 +3,23 @@ package com.snow.web.controller.front;
import cn.hutool.core.collection.CollectionUtil;
import com.snow.common.config.Global;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.page.PageModel;
import com.snow.common.enums.MessageReadStatus;
import com.snow.common.utils.ServletUtils;
import com.snow.flowable.domain.FlowGeneralSituationVO;
import com.snow.flowable.domain.HistoricTaskInstanceDTO;
import com.snow.flowable.domain.HistoricTaskInstanceVO;
import com.snow.flowable.service.FlowableService;
import com.snow.framework.shiro.service.SysPasswordService;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysMenu;
import com.snow.system.domain.SysMessageTransition;
import com.snow.system.domain.SysNotice;
import com.snow.system.domain.SysUser;
import com.snow.system.service.ISysConfigService;
import com.snow.system.service.ISysDingRuTaskService;
import com.snow.system.service.ISysMessageTransitionService;
import com.snow.system.service.ISysOperLogService;
import com.snow.system.service.impl.*;
import com.snow.system.service.impl.SysMenuServiceImpl;
import com.snow.system.service.impl.SysNoticeServiceImpl;
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.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@ -67,23 +58,7 @@ public class FrontIndexController extends BaseController {
return prefix + "/index";
}
/**
* 登录
* @param request
* @param response
* @return
*/
@GetMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response)
{
// 如果是Ajax请求返回Json字符串
if (ServletUtils.isAjaxRequest(request))
{
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
}
return prefix+"/login";
}
/**

View File

@ -0,0 +1,46 @@
package com.snow.web.controller.front;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.utils.StringUtils;
import com.snow.framework.shiro.auth.LoginType;
import com.snow.framework.shiro.auth.UserToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/7/9 9:05
*/
@Controller
@RequestMapping("/front")
public class FrontLoginController extends BaseController {
/**
* 登录
* @return
*/
@PostMapping("/login")
@ResponseBody
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe){
UserToken token = new UserToken(username, password, LoginType.OFFICIAL_WEBSITE, rememberMe);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return success();
} catch (AuthenticationException e) {
String msg = "用户或密码错误";
if (StringUtils.isNotEmpty(e.getMessage())) {
msg = e.getMessage();
}
return error(msg);
}
}
}

View File

@ -1,35 +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
*
@ -141,19 +137,37 @@ public class FinanceFlowController extends BaseController
}
@Log(title = "财务支付宝流水", businessType = BusinessType.IMPORT)
@Log(title = "财务账单流水", businessType = BusinessType.IMPORT)
@RequiresPermissions("system:flow:import")
@PostMapping("/importData")
@ResponseBody
public AjaxResult importData(MultipartFile file, String tradeRealName,String tradeAccount,String billType) throws Exception
{
SysUser sysUser = ShiroUtils.getSysUser();
FinanceAlipayFlowListener financeAlipayFlowListener = new FinanceAlipayFlowListener(financeAlipayFlowService, sysUser, tradeAccount,tradeRealName,Integer.parseInt(billType));
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), FinanceAlipayFlowImport.class, financeAlipayFlowListener).build();
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
// 这里千万别忘记关闭读的时候会创建临时文件到时磁盘会崩的
excelReader.finish();
if(billType.equals("1")){
FinanceAlipayFlowListener financeAlipayFlowListener = new FinanceAlipayFlowListener(financeAlipayFlowService, sysUser, tradeAccount,tradeRealName,Integer.parseInt(billType));
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), FinanceAlipayFlowImport.class, financeAlipayFlowListener).build();
ReadSheet readSheet = EasyExcel.readSheet(0)
// 这里可以设置1因为头就是一行如果多行头可以设置其他值不传入也可以因为默认会根据DemoData 来解析他没有指定头也就是默认1行
.headRowNumber(5).build();
excelReader.read(readSheet);
// 这里千万别忘记关闭读的时候会创建临时文件到时磁盘会崩的
excelReader.finish();
}else if(billType.equals("2")){
FinanceWeChartFlowListener financeWeChartFlowListener = new FinanceWeChartFlowListener(financeAlipayFlowService, sysUser, tradeAccount,tradeRealName,Integer.parseInt(billType));
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), FinanceWeChatFlowImport.class, financeWeChartFlowListener).build();
//微信账单是从第十五行开始读的
ReadSheet readSheet = EasyExcel.readSheet(0)
// 这里可以设置1因为头就是一行如果多行头可以设置其他值不传入也可以因为默认会根据DemoData 来解析他没有指定头也就是默认1行
.headRowNumber(17).build();
excelReader.read(readSheet);
// 这里千万别忘记关闭读的时候会创建临时文件到时磁盘会崩的
excelReader.finish();
}
return AjaxResult.success("导入成功");
}
}

View File

@ -1,6 +1,10 @@
package com.snow.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import com.snow.system.service.ISysUserService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -37,6 +41,9 @@ public class SysDeptController extends BaseController
@Autowired
private ISysDeptService deptService;
@Autowired
private ISysUserService sysUserService;
@RequiresPermissions("system:dept:view")
@GetMapping()
public String dept()
@ -87,6 +94,15 @@ public class SysDeptController extends BaseController
public String edit(@PathVariable("deptId") Long deptId, ModelMap mmap)
{
SysDept dept = deptService.selectDeptById(deptId);
//组装用户名
List<String> leader = dept.getLeader();
if(CollUtil.isNotEmpty(leader)){
List<String> leadsNameList = leader.stream().map(t -> {
return sysUserService.selectUserByDingUserId(t).getUserName();
}).collect(Collectors.toList());
dept.setLeader(leadsNameList);
}
if (StringUtils.isNotNull(dept) && 100L == deptId)
{
dept.setParentName("");

View File

@ -10,12 +10,14 @@ import com.snow.common.core.page.PageModel;
import com.snow.common.core.text.Convert;
import com.snow.common.enums.DingFlowTaskType;
import com.snow.common.enums.MessageEventType;
import com.snow.common.enums.NoticeType;
import com.snow.common.utils.CookieUtils;
import com.snow.common.utils.DateUtils;
import com.snow.common.utils.ServletUtils;
import com.snow.common.utils.StringUtils;
import com.snow.flowable.domain.*;
import com.snow.flowable.service.FlowableService;
import com.snow.flowable.service.FlowableTaskService;
import com.snow.framework.shiro.service.SysPasswordService;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.*;
@ -62,6 +64,9 @@ public class SysIndexController extends BaseController
@Autowired
private FlowableService flowableService;
@Autowired
private FlowableTaskService flowableTaskService;
@Autowired
private SysDingtalkSyncLogServiceImpl sysDingtalkSyncLogService;
@ -164,7 +169,7 @@ public class SysIndexController extends BaseController
mmap.put("flowGeneralSituation",flowGeneralSituation);
SysNotice sysNotice=new SysNotice();
sysNotice.setStatus("0");
sysNotice.setNoticeType("1");
sysNotice.setNoticeType(NoticeType.NOTICE_TYPE.getCode());
List<SysNotice> sysNotices = sysNoticeService.selectNoticeList(sysNotice);
mmap.put("sysNotices",sysNotices);
if(CollectionUtil.isNotEmpty(sysNotices)&&sysNotices.size()>5){
@ -177,7 +182,7 @@ public class SysIndexController extends BaseController
historicTaskInstanceDTO.setPageNum(1);
historicTaskInstanceDTO.setPageSize(5);
historicTaskInstanceDTO.setUserId(String.valueOf(sysUser.getUserId()));
PageModel<HistoricTaskInstanceVO> historicTaskInstance = flowableService.getHistoricTaskInstance(historicTaskInstanceDTO);
PageModel<HistoricTaskInstanceVO> historicTaskInstance = flowableTaskService.getHistoricTaskInstance(historicTaskInstanceDTO);
mmap.put("historicTaskInstanceList",historicTaskInstance.getPagedRecords());
mmap.put("historicTaskInstanceSize",historicTaskInstance.getPagedRecords().size());
return "main";
@ -282,16 +287,4 @@ public class SysIndexController extends BaseController
mmap.put("historicProcessInstanceList",historicProcessInstanceList);
return "big_screen";
}
public Integer getMyDingTalkRunTask(){
SysUser user = ShiroUtils.getSysUser();
SysDingRuTask sysDingRuTask=new SysDingRuTask();
sysDingRuTask.setAssignee(user.getDingUserId());
sysDingRuTask.setTaskState(DingFlowTaskType.RUNNING.getCode());
List<SysDingRuTask> sysDingRuTaskList = sysDingRuTaskService.selectSysDingRuTaskList(sysDingRuTask);
return sysDingRuTaskList.size();
}
}

View File

@ -1,6 +1,6 @@
package com.snow.web.controller.system;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollUtil;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.core.page.TableDataInfo;
@ -14,7 +14,6 @@ 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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@ -36,6 +35,11 @@ public class SysMessageCenterController extends BaseController
@Autowired
private ISysMessageTransitionService sysMessageTransitionService;
/**
* 跳转消息中心界面
* @param mmap
* @return
*/
@RequiresPermissions("system:messageCenter:view")
@GetMapping()
public String messageCenter(ModelMap mmap)
@ -47,14 +51,15 @@ public class SysMessageCenterController extends BaseController
sysMessageTransition.setOrderBy("update_time desc");
List<SysMessageTransition> sysMessageTransitions = sysMessageTransitionService.selectSysMessageTransitionList(sysMessageTransition);
if(CollectionUtil.isNotEmpty(sysMessageTransitions)){
//拜访日志tab页数据
if(CollUtil.isNotEmpty(sysMessageTransitions)){
List<SysMessageTransition> visitLogsList = sysMessageTransitions.stream().filter(t -> t.getMessageType().equals(MessageEventType.SEND_VISIT_LOG.getCode())).collect(Collectors.toList());
long count = visitLogsList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
mmap.put("visitLogCount",count);
long visitLogCount = visitLogsList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
mmap.put("visitLogCount",visitLogCount);
mmap.put("visitLogs",visitLogsList);
}
if(CollectionUtil.isNotEmpty(sysMessageTransitions)){
if(CollUtil.isNotEmpty(sysMessageTransitions)){
List<SysMessageTransition> emailList = sysMessageTransitions.stream().filter(t -> t.getMessageType().equals(MessageEventType.SEND_EMAIL.getCode())).collect(Collectors.toList());
SysMessageTransition.init(emailList);
long count = emailList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
@ -62,6 +67,30 @@ public class SysMessageCenterController extends BaseController
mmap.put("emailList",emailList);
}
//待办tab页数据
if(CollUtil.isNotEmpty(sysMessageTransitions)){
List<SysMessageTransition> todoTaskList = sysMessageTransitions.stream().filter(t -> t.getMessageType().equals(MessageEventType.INNER_TASK_TODO.getCode())).collect(Collectors.toList());
long count = todoTaskList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
mmap.put("todoTaskCount",count);
mmap.put("todoTaskList",todoTaskList);
}
//流程完结tab页数据
if(CollUtil.isNotEmpty(sysMessageTransitions)){
List<SysMessageTransition> processEndList = sysMessageTransitions.stream().filter(t -> t.getMessageType().equals(MessageEventType.INNER_PROCESS_END.getCode())).collect(Collectors.toList());
long count = processEndList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
mmap.put("processEndCount",count);
mmap.put("processEndList",processEndList);
}
//系统任务
if(CollUtil.isNotEmpty(sysMessageTransitions)){
List<SysMessageTransition> sysTaskList = sysMessageTransitions.stream().filter(t -> t.getMessageType().equals(MessageEventType.INNER_SYS_TASK_COMPLETE.getCode())
||t.getMessageType().equals(MessageEventType.INNER_SYS_TODO_TASK.getCode())).collect(Collectors.toList());
long count = sysTaskList.stream().filter(t -> t.getMessageReadStatus() == 0).count();
mmap.put("sysTaskCount",count);
mmap.put("sysTaskList",sysTaskList);
}
return prefix + "/messageCenter";
}
@ -94,7 +123,7 @@ public class SysMessageCenterController extends BaseController
* @param id
* @return
*/
@PostMapping( "/remarkRead")
@RequestMapping( "/remarkRead")
@ResponseBody
public AjaxResult remarkRead(Long id)
{

View File

@ -71,7 +71,7 @@ public class SysNoticeController extends BaseController
@ResponseBody
public AjaxResult addSave(SysNotice notice)
{
notice.setCreateBy(ShiroUtils.getLoginName());
notice.setCreateBy(ShiroUtils.getSysUser().getUserName());
return toAjax(noticeService.insertNotice(notice));
}
@ -94,7 +94,7 @@ public class SysNoticeController extends BaseController
@ResponseBody
public AjaxResult editSave(SysNotice notice)
{
notice.setUpdateBy(ShiroUtils.getLoginName());
notice.setUpdateBy(ShiroUtils.getSysUser().getUserName());
return toAjax(noticeService.updateNotice(notice));
}

View File

@ -19,7 +19,7 @@ import com.snow.flowable.domain.customer.SysOaCustomerForm;
import com.snow.flowable.service.FlowableService;
import com.snow.flowable.service.FlowableTaskService;
import com.snow.framework.util.ShiroUtils;
import com.snow.framework.web.domain.common.MessageEventDTO;
import com.snow.common.core.domain.MessageEventDTO;
import com.snow.system.domain.SysOaCustomer;
import com.snow.system.domain.SysOaCustomerVisitLog;
import com.snow.system.domain.SysOaRegion;

View File

@ -14,15 +14,11 @@ import com.snow.common.enums.BusinessType;
import com.snow.common.enums.MessageEventType;
import com.snow.common.enums.SysEmailSearchType;
import com.snow.common.utils.StringUtils;
import com.snow.common.utils.poi.ExcelUtil;
import com.snow.framework.util.ShiroUtils;
import com.snow.framework.web.domain.common.MessageEventDTO;
import com.snow.framework.web.domain.common.SysSendEmailDTO;
import com.snow.framework.web.service.MailService;
import com.snow.common.core.domain.MessageEventDTO;
import com.snow.system.domain.*;
import com.snow.system.service.ISysOaEmailService;
import com.snow.system.service.ISysSequenceService;
import com.snow.system.service.impl.SysMessageTemplateServiceImpl;
import com.snow.system.service.impl.SysMessageTransitionServiceImpl;
import com.snow.system.service.impl.SysUserServiceImpl;
import org.apache.commons.collections.CollectionUtils;

View File

@ -195,7 +195,7 @@ public class SysOaLeaveController extends BaseController
historicTaskInstanceDTO.setBusinessKey(sysOaLeave.getLeaveNo());
historicTaskInstanceDTO.setProcessInstanceId(sysOaLeave.getProcessInstanceId());
historicTaskInstanceDTO.setProcessStatus(WorkRecordStatus.FINISHED);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableTaskService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
String spendTime = DateUtil.formatBetween(sysOaLeave.getStartTime(), sysOaLeave.getEndTime(), BetweenFormater.Level.SECOND);
sysOaLeave.setLeaveTime(spendTime);
mmap.put("sysOaLeave", sysOaLeave);

View File

@ -0,0 +1,367 @@
package com.snow.web.controller.system;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.constant.MessageConstants;
import com.snow.common.core.domain.MessageEventDTO;
import com.snow.common.enums.DingFlowTaskType;
import com.snow.common.enums.DingTalkListenerType;
import com.snow.common.enums.MessageEventType;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.*;
import com.snow.system.domain.SysOaTaskDistribute;
import com.snow.system.event.SyncEvent;
import com.snow.system.service.ISysOaTaskDistributeService;
import com.snow.system.service.ISysUserService;
import org.apache.commons.compress.utils.Sets;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
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 org.springframework.stereotype.Controller;
import com.snow.system.service.ISysOaTaskService;
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;
/**
* 系统任务Controller
* 当任务被分配后判断是否同步到钉钉系统
* @author 没用的阿吉
* @date 2021-07-29
*/
@Controller
@RequestMapping("/system/task")
public class SysOaTaskController extends BaseController
{
private String prefix = "system/task";
@Autowired
private ISysOaTaskService sysOaTaskService;
@Autowired
private ISysOaTaskDistributeService sysOaTaskDistributeService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private ApplicationContext applicationContext;
@RequiresPermissions("system:task:view")
@GetMapping()
public String task()
{
return prefix + "/task";
}
/**
* 查询系统任务列表
*/
@RequiresPermissions("system:task:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(SysOaTask sysOaTask)
{
startPage();
List<SysOaTask> list = sysOaTaskService.selectSysOaTaskList(sysOaTask);
return getDataTable(list);
}
/**
* 任务分配列表
*/
@RequiresPermissions("system:task:taskDistributeList")
@PostMapping("/taskDistributeList")
@ResponseBody
public TableDataInfo taskDistributeList(SysOaTaskDistribute sysOaTaskDistribute)
{
startPage();
List<SysOaTaskDistribute> list = sysOaTaskDistributeService.selectSysOaTaskDistributeList(sysOaTaskDistribute);
if(CollUtil.isNotEmpty(list)){
warpSysOaTask(list);
}
return getDataTable(list);
}
/**
* 查询我发起系统任务列表
*/
@RequiresPermissions("system:task:myList")
@PostMapping("/myList")
@ResponseBody
public TableDataInfo myList(SysOaTask sysOaTask)
{
startPage();
SysUser sysUser = ShiroUtils.getSysUser();
sysOaTask.setCreateBy(String.valueOf(sysUser.getUserId()));
List<SysOaTask> list = sysOaTaskService.selectSysOaTaskList(sysOaTask);
return getDataTable(list);
}
/**
* 我的待处理任务
* @param sysOaTaskDistribute
* @return
*/
@RequiresPermissions("system:task:waitList")
@PostMapping("/waitList")
@ResponseBody
public TableDataInfo waitList(SysOaTaskDistribute sysOaTaskDistribute)
{
startPage();
SysUser sysUser = ShiroUtils.getSysUser();
sysOaTaskDistribute.setTaskExecuteStatusList(Lists.newArrayList(DingFlowTaskType.RUNNING.getCode(),DingFlowTaskType.PROCESSING.getCode()));
sysOaTaskDistribute.setTaskDistributeId(String.valueOf(sysUser.getUserId()));
List<SysOaTaskDistribute> sysOaTaskDistributes = sysOaTaskDistributeService.selectSysOaTaskDistributeList(sysOaTaskDistribute);
if(CollUtil.isNotEmpty(sysOaTaskDistributes)){
warpSysOaTask(sysOaTaskDistributes);
}
return getDataTable(sysOaTaskDistributes);
}
/**
* 我处理的任务
* @param sysOaTaskDistribute
* @return
*/
@RequiresPermissions("system:task:handleList")
@PostMapping("/handleList")
@ResponseBody
public TableDataInfo handleList(SysOaTaskDistribute sysOaTaskDistribute)
{
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);
}
return getDataTable(sysOaTaskDistributes);
}
/**
* 导出系统任务列表
*/
@RequiresPermissions("system:task:export")
@Log(title = "系统任务", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(SysOaTask sysOaTask)
{
List<SysOaTask> list = sysOaTaskService.selectSysOaTaskList(sysOaTask);
ExcelUtil<SysOaTask> util = new ExcelUtil<SysOaTask>(SysOaTask.class);
return util.exportExcel(list, "task");
}
/**
* 新增系统任务
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存系统任务
*/
@RequiresPermissions("system:task:add")
@Log(title = "系统任务", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(SysOaTask sysOaTask)
{
SysUser sysUser = ShiroUtils.getSysUser();
sysOaTask.setCreateBy(String.valueOf(sysUser.getUserId()));
return toAjax(sysOaTaskService.insertSysOaTask(sysOaTask));
}
@RequiresPermissions("system:task:start")
@PostMapping("/start")
@ResponseBody
public AjaxResult start(Long id)
{
SysOaTaskDistribute sysOaTaskDistribute =new SysOaTaskDistribute();
sysOaTaskDistribute.setId(id);
sysOaTaskDistribute.setTaskStartTime(new Date());
sysOaTaskDistribute.setTaskExecuteStatus(DingFlowTaskType.PROCESSING.getCode());
return toAjax(sysOaTaskDistributeService.updateSysOaTaskDistribute(sysOaTaskDistribute));
}
/**
* 处理系统任务
*/
@GetMapping("/handle/{id}")
public String handle(@PathVariable("id") Long id, ModelMap mmap)
{
SysOaTaskDistribute sysOaTaskDistribute = sysOaTaskDistributeService.selectSysOaTaskDistributeById(id);
warpSysOaTask(Lists.newArrayList(sysOaTaskDistribute));
mmap.put("sysOaTaskDistribute", sysOaTaskDistribute);
return prefix + "/handle";
}
/**
* 处理保存系统任务
*/
@RequiresPermissions("system:task:handle")
@Log(title = "系统任务", businessType = BusinessType.UPDATE)
@PostMapping("/handle")
@ResponseBody
public AjaxResult handleSave(SysOaTaskDistribute sysOaTaskDistribute)
{
sysOaTaskDistribute.setTaskCompleteTime(new Date());
sysOaTaskDistribute.setTaskExecuteId(String.valueOf(ShiroUtils.getUserId()));
sysOaTaskDistribute.setUpdateBy(String.valueOf(ShiroUtils.getUserId()));
sysOaTaskDistribute.setTaskExecuteStatus(DingFlowTaskType.COMPLETED.getCode());
sendInnerMessage(sysOaTaskDistribute);
//事件发送
SyncEvent<SysOaTaskDistribute> syncEvent = new SyncEvent(sysOaTaskDistribute, DingTalkListenerType.UPDATE_TODO_TASK_EXECUTOR_STATUS);
applicationContext.publishEvent(syncEvent);
return toAjax(sysOaTaskDistributeService.updateSysOaTaskDistribute(sysOaTaskDistribute));
}
/**
* 发送站内信
* @param sysOaTaskDistribute 参数
*/
private void sendInnerMessage(SysOaTaskDistribute sysOaTaskDistribute){
MessageEventDTO messageEventDTO=new MessageEventDTO(MessageEventType.INNER_SYS_TASK_COMPLETE.getCode());
messageEventDTO.setProducerId(sysOaTaskDistribute.getCreateBy());
messageEventDTO.setConsumerIds(Sets.newHashSet(sysOaTaskDistribute.getTaskDistributeId()));
messageEventDTO.setMessageEventType(MessageEventType.INNER_SYS_TASK_COMPLETE);
messageEventDTO.setMessageShow(2);
Map<String,Object> map= new HashMap<>();
map.put("startUser",ShiroUtils.getUserName());
map.put("businessKey", sysOaTaskDistribute.getTaskNo());
map.put("startTime", DateUtil.formatDateTime(sysOaTaskDistribute.getTaskCompleteTime()));
map.put("id",sysOaTaskDistribute.getId());
messageEventDTO.setParamMap(map);
messageEventDTO.setTemplateCode(MessageConstants.INNER_SYS_TASK_COMPLETE);
applicationContext.publishEvent(messageEventDTO);
}
/**
* 修改系统任务
*/
@GetMapping("/edit/{taskNo}")
public String edit(@PathVariable("taskNo") String taskNo, ModelMap mmap)
{
SysOaTask sysOaTask = sysOaTaskService.selectSysOaTaskById(taskNo);
mmap.put("sysOaTask", sysOaTask);
return prefix + "/edit";
}
/**
* 修改保存系统任务
*/
@RequiresPermissions("system:task:edit")
@Log(title = "系统任务", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(SysOaTask sysOaTask)
{
SysOaTaskDistribute sysOaTaskDistribute=new SysOaTaskDistribute();
sysOaTaskDistribute.setSysOaTask(sysOaTask);
SyncEvent<SysOaTaskDistribute> syncEvent = new SyncEvent(sysOaTaskDistribute, DingTalkListenerType.WORK_RECORD_UPDATE);
applicationContext.publishEvent(syncEvent);
return toAjax(sysOaTaskService.updateSysOaTask(sysOaTask));
}
/**
* 删除系统任务
*/
@RequiresPermissions("system:task:remove")
@Log(title = "系统任务", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(sysOaTaskService.deleteSysOaTaskByIds(ids));
}
/**
* 任务详情
* @param taskNo 任务编码
* @param mmap
* @return
*/
@GetMapping("/detail/{id}")
@RequiresPermissions("system:task:detail")
public String detail(@PathVariable("id") String taskNo, ModelMap mmap)
{
SysOaTask sysOaTask = sysOaTaskService.selectSysOaTaskById(taskNo);
SysOaTaskDistribute sysOaTaskDistribute=new SysOaTaskDistribute();
sysOaTaskDistribute.setTaskNo(taskNo);
List<SysOaTaskDistribute> sysOaTaskDistributes = sysOaTaskDistributeService.selectSysOaTaskDistributeList(sysOaTaskDistribute);
mmap.put("sysOaTask", sysOaTask);
mmap.put("sysOaTaskDistributes", sysOaTaskDistributes);
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
* @param mmap
* @return
*/
@GetMapping("/taskDistribute/detail/{id}")
@RequiresPermissions("system:taskDistribute:detail")
public String taskDistributeDetail(@PathVariable("id") Long id, ModelMap mmap)
{
SysOaTaskDistribute sysOaTaskDistribute = sysOaTaskDistributeService.selectSysOaTaskDistributeById(id);
warpSysOaTask(Lists.newArrayList(sysOaTaskDistribute));
mmap.put("sysOaTask", sysOaTaskDistribute);
return prefix + "/taskDistributeDetail";
}
private void warpSysOaTask(List<SysOaTaskDistribute> sysOaTaskDistributes){
sysOaTaskDistributes.forEach(t->{
SysOaTask sysOaTask = sysOaTaskService.selectSysOaTaskById(t.getTaskNo());
sysOaTask.setCreateBy(sysUserService.selectUserById(Long.parseLong(sysOaTask.getCreateBy())).getUserName());
if(ObjectUtil.isNotNull(t.getTaskDistributeId())){
t.setTaskDistributeId(sysUserService.selectUserById(Long.parseLong(t.getTaskDistributeId())).getUserName());
}
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

@ -3,11 +3,10 @@ package com.snow.web.controller.system;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.snow.common.constant.Constants;
import com.snow.common.constant.MessageConstants;
import com.snow.common.constant.UserConstants;
import com.snow.common.enums.MessageEventType;
import com.snow.framework.web.domain.common.MessageEventDTO;
import com.snow.common.core.domain.MessageEventDTO;
import com.snow.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

View File

@ -3,6 +3,7 @@ package com.snow.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import com.snow.common.constant.SequenceConstants;
import com.snow.system.service.impl.SysSequenceServiceImpl;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
@ -124,7 +125,7 @@ public class SysUserController extends BaseController
public String add(ModelMap mmap)
{
String jobNumber = sysSequenceService.getNewSequenceNo("SNOW");
String jobNumber = sysSequenceService.getNewSequenceNo(SequenceConstants.OA_SNOW);
mmap.put("jobNumber",jobNumber);
mmap.put("roles", roleService.selectRoleAll().stream().filter(r -> !r.isAdmin()&&r.getRoleType().equals(UserConstants.SYSTEM_ROLE_TYPE)).collect(Collectors.toList()));
mmap.put("posts", postService.selectPostAll());
@ -317,4 +318,13 @@ public class SysUserController extends BaseController
SysUser sysUser = userService.selectUserById(id);
return AjaxResult.success(sysUser);
}
/**
* 多选用户
* @return
*/
@GetMapping("/selectMultiUser")
public String selectMultiUser() {
return prefix + "/selectMultiUser";
}
}

View File

@ -1,24 +0,0 @@
package com.snow.web.controller.tool;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.snow.common.core.controller.BaseController;
/**
* swagger 接口
*
* @author snow
*/
@Controller
@RequestMapping("/tool/swagger")
public class SwaggerController extends BaseController
{
@RequiresPermissions("tool:swagger:view")
@GetMapping()
public String index()
{
return redirect("/swagger-ui.html");
}
}

View File

@ -1,175 +0,0 @@
package com.snow.web.controller.tool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
/**
* swagger 用户测试方法
*
* @author snow
*/
@Api("用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
{
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
}
@ApiOperation("获取用户列表")
@GetMapping("/list")
public AjaxResult userList()
{
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
return AjaxResult.success(userList);
}
@ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
@GetMapping("/{userId}")
public AjaxResult getUser(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
return AjaxResult.success(users.get(userId));
}
else
{
return error("用户不存在");
}
}
@ApiOperation("新增用户")
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
@PostMapping("/save")
public AjaxResult save(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
}
return AjaxResult.success(users.put(user.getUserId(), user));
}
@ApiOperation("更新用户")
@ApiImplicitParam(name = "userEntity", value = "新增用户信息", dataType = "UserEntity")
@PutMapping("/update")
public AjaxResult update(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
}
if (users.isEmpty() || !users.containsKey(user.getUserId()))
{
return error("用户不存在");
}
users.remove(user.getUserId());
return AjaxResult.success(users.put(user.getUserId(), user));
}
@ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
@DeleteMapping("/{userId}")
public AjaxResult delete(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
users.remove(userId);
return success();
}
else
{
return error("用户不存在");
}
}
}
@ApiModel("用户实体")
class UserEntity
{
@ApiModelProperty("用户ID")
private Integer userId;
@ApiModelProperty("用户名称")
private String username;
@ApiModelProperty("用户密码")
private String password;
@ApiModelProperty("用户手机")
private String mobile;
public UserEntity()
{
}
public UserEntity(Integer userId, String username, String password, String mobile)
{
this.userId = userId;
this.username = username;
this.password = password;
this.mobile = mobile;
}
public Integer getUserId()
{
return userId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getMobile()
{
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}

View File

@ -1,69 +0,0 @@
package com.snow.web.core.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.snow.common.config.Global;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2的接口配置
*
* @author snow
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
/** 是否开启swagger */
@Value("${swagger.enabled}")
private boolean enabled;
/**
* 创建API
*/
@Bean
public Docket createRestApi()
{
return new Docket(DocumentationType.SWAGGER_2)
// 是否启用Swagger
.enable(enabled)
// 用来创建该API的基本信息展示在文档的页面中自定义展示的信息
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描所有有注解的api用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包中的swagger注解
//.apis(RequestHandlerSelectors.basePackage("com.snow.project.tool.swagger"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
/**
* 添加摘要信息
*/
private ApiInfo apiInfo()
{
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题若依管理系统_接口文档")
// 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
// 作者信息
.contact(new Contact(Global.getName(), null, null))
// 版本
.version("版本号:" + Global.getVersion())
.build();
}
}

View File

@ -6,9 +6,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/snow?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
url: jdbc:mysql://rm-bp1j1554xv1qs04295o.mysql.rds.aliyuncs.com:3306/snow-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: cloud_root
password: Jin!152377
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@ -149,6 +149,9 @@ swagger:
#登录后是否显示最新的公告
is:
notice: true
#是否开启同步钉钉
sync:
dingtalk: true
flowable:
#关闭定时任务JOB

View File

@ -6,6 +6,7 @@ user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次帐户锁定10分钟
user.password.delete=对不起,您的账号已被删除
user.type.error=用户类型错误
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功

View File

@ -0,0 +1,8 @@
/**
* Minified by jsDelivr using Terser v5.3.5.
* Original file: /npm/js-base64@3.6.0/base64.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):function(){const r=e.Base64,o=t();o.noConflict=()=>(e.Base64=r,o),e.Meteor&&(Base64=o),e.Base64=o}()}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:this,(function(){"use strict";const e="3.6.0",t="function"==typeof atob,r="function"==typeof btoa,o="function"==typeof Buffer,n="function"==typeof TextDecoder?new TextDecoder:void 0,a="function"==typeof TextEncoder?new TextEncoder:void 0,f=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="],i=(e=>{let t={};return e.forEach(((e,r)=>t[e]=r)),t})(f),c=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,u=String.fromCharCode.bind(String),s="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):(e,t=(e=>e))=>new Uint8Array(Array.prototype.slice.call(e,0).map(t)),d=e=>e.replace(/[+\/]/g,(e=>"+"==e?"-":"_")).replace(/=+$/m,""),l=e=>e.replace(/[^A-Za-z0-9\+\/]/g,""),h=e=>{let t,r,o,n,a="";const i=e.length%3;for(let i=0;i<e.length;){if((r=e.charCodeAt(i++))>255||(o=e.charCodeAt(i++))>255||(n=e.charCodeAt(i++))>255)throw new TypeError("invalid character found");t=r<<16|o<<8|n,a+=f[t>>18&63]+f[t>>12&63]+f[t>>6&63]+f[63&t]}return i?a.slice(0,i-3)+"===".substring(i):a},p=r?e=>btoa(e):o?e=>Buffer.from(e,"binary").toString("base64"):h,y=o?e=>Buffer.from(e).toString("base64"):e=>{let t=[];for(let r=0,o=e.length;r<o;r+=4096)t.push(u.apply(null,e.subarray(r,r+4096)));return p(t.join(""))},A=(e,t=!1)=>t?d(y(e)):y(e),b=e=>{if(e.length<2)return(t=e.charCodeAt(0))<128?e:t<2048?u(192|t>>>6)+u(128|63&t):u(224|t>>>12&15)+u(128|t>>>6&63)+u(128|63&t);var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return u(240|t>>>18&7)+u(128|t>>>12&63)+u(128|t>>>6&63)+u(128|63&t)},g=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,B=e=>e.replace(g,b),x=o?e=>Buffer.from(e,"utf8").toString("base64"):a?e=>y(a.encode(e)):e=>p(B(e)),C=(e,t=!1)=>t?d(x(e)):x(e),m=e=>C(e,!0),U=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,F=e=>{switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return u(55296+(t>>>10))+u(56320+(1023&t));case 3:return u((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return u((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},w=e=>e.replace(U,F),S=e=>{if(e=e.replace(/\s+/g,""),!c.test(e))throw new TypeError("malformed base64.");e+="==".slice(2-(3&e.length));let t,r,o,n="";for(let a=0;a<e.length;)t=i[e.charAt(a++)]<<18|i[e.charAt(a++)]<<12|(r=i[e.charAt(a++)])<<6|(o=i[e.charAt(a++)]),n+=64===r?u(t>>16&255):64===o?u(t>>16&255,t>>8&255):u(t>>16&255,t>>8&255,255&t);return n},E=t?e=>atob(l(e)):o?e=>Buffer.from(e,"base64").toString("binary"):S,v=o?e=>s(Buffer.from(e,"base64")):e=>s(E(e),(e=>e.charCodeAt(0))),D=e=>v(z(e)),R=o?e=>Buffer.from(e,"base64").toString("utf8"):n?e=>n.decode(v(e)):e=>w(E(e)),z=e=>l(e.replace(/[-_]/g,(e=>"-"==e?"+":"/"))),T=e=>R(z(e)),Z=e=>({value:e,enumerable:!1,writable:!0,configurable:!0}),j=function(){const e=(e,t)=>Object.defineProperty(String.prototype,e,Z(t));e("fromBase64",(function(){return T(this)})),e("toBase64",(function(e){return C(this,e)})),e("toBase64URI",(function(){return C(this,!0)})),e("toBase64URL",(function(){return C(this,!0)})),e("toUint8Array",(function(){return D(this)}))},I=function(){const e=(e,t)=>Object.defineProperty(Uint8Array.prototype,e,Z(t));e("toBase64",(function(e){return A(this,e)})),e("toBase64URI",(function(){return A(this,!0)})),e("toBase64URL",(function(){return A(this,!0)}))},O={version:e,VERSION:"3.6.0",atob:E,atobPolyfill:S,btoa:p,btoaPolyfill:h,fromBase64:T,toBase64:C,encode:C,encodeURI:m,encodeURL:m,utob:B,btou:w,decode:T,isValid:e=>{if("string"!=typeof e)return!1;const t=e.replace(/\s+/g,"").replace(/=+$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(t)||!/[^\s0-9a-zA-Z\-_]/.test(t)},fromUint8Array:A,toUint8Array:D,extendString:j,extendUint8Array:I,extendBuiltins:()=>{j(),I()},Base64:{}};return Object.keys(O).forEach((e=>O.Base64[e]=O[e])),O}));
//# sourceMappingURL=/sm/8bca8602e2256d240cef904e1c1df432ccfdd2a2a73f6911c60be79e526e3e1e.map

View File

@ -1 +1,71 @@
function $childNode(o){return window.frames[o]}function animationHover(o,e){o=$(o),o.hover(function(){o.addClass("animated "+e)},function(){window.setTimeout(function(){o.removeClass("animated "+e)},2e3)})}function WinMove(){var o="[class*=col]",e=".ibox-title",i="[class*=col]";$(o).sortable({handle:e,connectWith:i,tolerance:"pointer",forcePlaceholderSize:!0,opacity:.8}).disableSelection()}var $parentNode=window.parent.document;if($(".tooltip-demo").tooltip({selector:"[data-toggle=tooltip]",container:"body"}),$(".modal").appendTo("body"),$("[data-toggle=popover]").popover(),$(".collapse-link").click(function(){var o=$(this).closest("div.ibox"),e=$(this).find("i"),i=o.find("div.ibox-content");i.slideToggle(200),e.toggleClass("fa-chevron-up").toggleClass("fa-chevron-down"),o.toggleClass("").toggleClass("border-bottom"),setTimeout(function(){o.resize(),o.find("[id^=map-]").resize()},50)}),$(".close-link").click(function(){var o=$(this).closest("div.ibox");o.remove()}),top==this){var gohome='<div class="gohome"><a class="animated bounceInUp" href="index.html?v=4.0" title="返回首页"><i class="fa fa-home"></i></a></div>';$("body").append(gohome)}
var $parentNode = window.parent.document;
function $childNode(name) {
return window.frames[name]
}
// tooltips
$('.tooltip-demo').tooltip({
selector: "[data-toggle=tooltip]",
container: "body"
});
// 使用animation.css修改Bootstrap Modal
$('.modal').appendTo("body");
$("[data-toggle=popover]").popover();
//折叠ibox
$('.collapse-link').click(function () {
var ibox = $(this).closest('div.ibox');
var button = $(this).find('i');
var content = ibox.find('div.ibox-content');
content.slideToggle(200);
button.toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');
ibox.toggleClass('').toggleClass('border-bottom');
setTimeout(function () {
ibox.resize();
ibox.find('[id^=map-]').resize();
}, 50);
});
//关闭ibox
$('.close-link').click(function () {
var content = $(this).closest('div.ibox');
content.remove();
});
//判断当前页面是否在iframe中
if (top == this) {
var gohome = '<div class="gohome"><a class="animated bounceInUp" href="index.html?v=4.0" title="返回首页"><i class="fa fa-home"></i></a></div>';
$('body').append(gohome);
}
//animation.css
function animationHover(element, animation) {
element = $(element);
element.hover(
function () {
element.addClass('animated ' + animation);
},
function () {
//动画完成之前移除class
window.setTimeout(function () {
element.removeClass('animated ' + animation);
}, 2000);
});
}
//拖动面板
function WinMove() {
var element = "[class*=col]";
var handle = ".ibox-title";
var connect = "[class*=col]";
$(element).sortable({
handle: handle,
connectWith: connect,
tolerance: 'pointer',
forcePlaceholderSize: true,
opacity: 0.8,
}).disableSelection();
};

View File

@ -236,8 +236,7 @@
<div class="col-xs-8">
<div class="inline-people-select">
<ul class="simple-list">
<li ng-click="confirmGroup(group);" ng-repeat="group in popup.groupResults"
ng-class="{'active': $index == popup.selectedGroupIndex}">
<li ng-click="confirmGroup(group);" ng-repeat="group in popup.groupResults" ng-class="{'active': $index == popup.selectedGroupIndex}">
{{group.name}}
</li>
</ul>

View File

@ -63,7 +63,7 @@
</span>
<i class="glyphicon {{currentAppDefinition.definition.icon}}"></i>
<div class="dropdown btn-group btn-group-sm" activiti-fix-dropdown-bug>
<!-- <div class="dropdown btn-group btn-group-sm" activiti-fix-dropdown-bug>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
{{account.firstName && account.firstName != 'null' ? account.firstName : ''}} {{account.lastName && account.lastName != 'null' ? account.lastName : ''}}
<span class="glyphicon glyphicon-chevron-down" style="font-size: 10px" aria-hidden="true"></span>
@ -71,7 +71,7 @@
<ul class="dropdown-menu pull-right">
<li><a href="" ng-click="logout()" translate>GENERAL.ACTION.LOGOUT</a></li>
</ul>
</div>
</div>-->
</div>
</div>
</div>

View File

@ -0,0 +1,95 @@
$(function() {
validateKickout();
validateRule();
$('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url);
});
});
$("#btnSubmit").click(function () {
login();
})
function login() {
$.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val();
var rememberMe = $("input[name='rememberme']").is(':checked');
var url= ctx +"front/login";
console.log("==========================>"+url)
$.ajax({
type: "post",
url: url,
data: {
"username": username,
"password": password,
"validateCode": validateCode,
"rememberMe": rememberMe
},
success: function(r) {
if (r.code == 0) {
location.href ='/front/main';
} else {
$.modal.closeLoading();
$('.imgcode').click();
$(".code").val("");
$.modal.msg(r.msg);
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
rules: {
username: {
required: true
},
password: {
required: true
}
},
messages: {
username: {
required: icon + "请输入您的用户名",
},
password: {
required: icon + "请输入您的密码",
}
}
})
}
function validateKickout() {
if (getParam("kickout") == 1) {
layer.alert("<font color='red'>您已在别处登录,请您修改密码或重新登录</font>", {
icon: 0,
title: "系统提示"
},
function(index) {
//关闭弹窗
layer.close(index);
if (top != self) {
top.location = self.location;
} else {
var url = location.search;
if (url) {
var oldUrl = window.location.href;
var newUrl= oldUrl.substring(0, oldUrl.indexOf('?'));
self.location= newUrl;
}
}
});
}
}
function getParam(paramName) {
var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
}

View File

@ -1288,6 +1288,20 @@ var table = {
$.modal.open("修改" + table.options.modalName, $.operate.editUrl(id));
}
},
handle: function(id) {
table.set();
if($.common.isEmpty(id) && table.options.type == table_type.bootstrapTreeTable) {
var row = $("#" + table.options.id).bootstrapTreeTable('getSelections')[0];
if ($.common.isEmpty(row)) {
$.modal.alertWarning("请至少选择一条记录");
return;
}
var url = table.options.handleUrl.replace("{id}", row[table.options.uniqueId]);
$.modal.open("处理" + table.options.modalName, url);
} else {
$.modal.open("处理" + table.options.modalName, $.operate.handleUrl(id));
}
},
// 修改信息以tab页展现
editTab: function(id) {
table.set();
@ -1329,6 +1343,20 @@ var table = {
}
return url;
},
handleUrl: function(id) {
var url = "/404.html";
if ($.common.isNotEmpty(id)) {
url = table.options.handleUrl.replace("{id}", id);
} else {
var id = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
if (id.length == 0) {
$.modal.alertWarning("请至少选择一条记录");
return;
}
url = table.options.handleUrl.replace("{id}", id);
}
return url;
},
// 保存信息 刷新表格
save: function(url, data, callback) {
var config = {

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<title>Ding-Flow可视化大屏</title>
<title>DingFlow可视化大屏</title>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<link th:href="@{/css/comon0.css}" rel="stylesheet"/>

View File

@ -0,0 +1,148 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增外部用户')" />
<th:block th:include="include :: select2-css" />
</head>
<body>
<div class="main-content">
<form id="form-user-add" class="form-horizontal">
<h4 class="form-header h4">基本信息</h4>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">姓名:</label>
<div class="col-sm-8">
<input name="name" placeholder="请输入用户名称" class="form-control" type="text" maxlength="30" required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">归属用户:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="hidden" name="followerUserId" id="followerUserId" required>
<input class="form-control" type="text" name="followerUserName" onclick="selectUserInfo()" id="followerUserName" required>
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">手机号码:</label>
<div class="col-sm-8">
<div class="input-group">
<input id="mobile" name="mobile" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11" required>
<span class="input-group-addon"><i class="fa fa-mobile"></i></span>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">邮箱:</label>
<div class="col-sm-8">
<div class="input-group">
<input id="email" name="email" class="form-control email" type="text" maxlength="20" placeholder="请输入邮箱" required>
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">企业名称:</label>
<div class="col-sm-8">
<input id="companyName" name="companyName" class="form-control" type="text" placeholder="请输入企业名称" required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-xs-4 control-label is-required">岗位:</label>
<div class="col-xs-8">
<input id="title" name="title" class="form-control" type="text" maxlength="20" placeholder="请输入岗位" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-sm-2 control-label is-required">地址:</label>
<div class="col-sm-8">
<input id="address" name="address" class="form-control" type="text" maxlength="120" placeholder="请输入地址" required>
</div>
</div>
</div>
</div>
<h4 class="form-header h4">其他信息</h4>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-2 control-label">标签:</label>
<div class="col-xs-10">
<div class="row" th:each="dict : ${label}">
<label class="col-xs-2 control-label" th:text="${dict.name}"></label>
<div class="radio-box" th:each="label : ${dict.labels}">
<input type="radio" th:id="${'faqType_' + label.id}" name="labelIds" th:value="${label.id}">
<label th:for="${'faqType_' + label.id}" th:text="${label.name}"></label>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-2 control-label">备注:</label>
<div class="col-xs-10">
<textarea name="remark" maxlength="500" class="form-control" rows="3"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="row">
<div class="col-sm-offset-5 col-sm-10">
<button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
<button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: select2-js" />
<script>
var prefix = ctx + "ding/extContactUser";
function submitHandler() {
if ($.validate.form()) {
var data = $("#form-user-add").serializeArray();
$.operate.saveTab(prefix + "/add", data);
}
}
function selectUserInfo() {
var url = "/system/dept/selectUser/0";
$.modal.open("选择用户",url,"","",doSubmitOne);
}
function doSubmitOne(index, layero){
var body = layer.getChildFrame('body', index);
var iframeWin = layero.find('iframe')[0];
iframeWin.contentWindow.submitHandler(index, layero);
$("#followerUserId").val(body.find('#dingUserId').val());
$("#followerUserName").val(body.find('#userName').val());
layer.close(index);
}
</script>
</body>
</html>

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('外部联系人详情')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<div class="form-group">
<label class="col-sm-3 control-label">姓名:</label>
<div class="form-control-static" th:text="${extContactUser.name}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">负责人:</label>
<div class="form-control-static" th:text="${extContactUser.followerUserId}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">公司:</label>
<div class="form-control-static" th:text="${extContactUser.companyName}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">职位:</label>
<div class="form-control-static" th:text="${extContactUser.title}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">地址:</label>
<div class="form-control-static" th:text="${extContactUser.address}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="form-control-static" th:text="${extContactUser.remark}">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
</body>
</html>

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('编辑外部联系人')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-dept-edit" th:object="${extContactUser}">
<h4 class="form-header h4">基本信息</h4>
<input class="form-control" type="hidden" name="userId" th:field="*{userid}">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">姓名:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="deptName" th:field="*{name}" id="deptName" required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">负责人:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="hidden" name="followerUserId" id="followerUserId" required>
<input class="form-control" type="text" name="followerUserName" onclick="selectUserInfo()" th:value="${extContactUser.followerUserId}" id="followerUserName" readonly="true">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">手机号码:</label>
<div class="col-sm-8">
<div class="input-group">
<input id="mobile" name="mobile" placeholder="请输入手机号码" th:field="*{mobile}" class="form-control" type="text" maxlength="11" required>
<span class="input-group-addon"><i class="fa fa-mobile"></i></span>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">邮箱:</label>
<div class="col-sm-8">
<div class="input-group">
<input id="email" name="email" class="form-control email" th:field="*{email}" type="text" maxlength="20" placeholder="请输入邮箱" required>
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">企业名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="companyName" th:field="*{companyName}" placeholder="请输入企业名称" required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-xs-4 control-label is-required">岗位:</label>
<div class="col-xs-8">
<input id="title" name="title" class="form-control" type="text" th:field="*{title}" maxlength="20" placeholder="请输入岗位" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-sm-2 control-label is-required">地址:</label>
<div class="col-sm-8">
<input id="address" name="address" class="form-control" type="text" maxlength="120" placeholder="请输入地址" required>
</div>
</div>
</div>
</div>
<h4 class="form-header h4">其他信息</h4>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-2 control-label">备注:</label>
<div class="col-xs-10">
<textarea name="remark" maxlength="500" th:value="${extContactUser.remark}" class="form-control" rows="3"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
var prefix = ctx + "ding/extContactUser";
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-dept-edit').serialize());
}
}
function selectUserInfo() {
var url = "/system/dept/selectUser/0";
$.modal.open("选择用户",url,"","",doSubmitOne);
}
function doSubmitOne(index, layero){
var body = layer.getChildFrame('body', index);
var iframeWin = layero.find('iframe')[0];
iframeWin.contentWindow.submitHandler(index, layero);
$("#followerUserId").val(body.find('#dingUserId').val());
$("#followerUserName").val(body.find('#userName').val());
layer.close(index);
}
</script>
</body>
</html>

View File

@ -0,0 +1,146 @@
<!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="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="name"/>
</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="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.addTab()()" shiro:hasPermission="system:extContactUser:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:extContactUser:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table" data-show-print="true" data-print-as-filtered-and-sorted-on-ui="true"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: bootstrap-table-print-js" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:extContactUser:edit')}]];
var detailFlag = [[${@permission.hasPermi('system:extContactUser:detail')}]];
var removeFlag = [[${@permission.hasPermi('system:extContactUser:remove')}]];
var prefix = ctx + "ding/extContactUser";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
detailUrl:prefix + "/detail/{id}",
printPageBuilder: printPageBuilder,
modalName: "外部联系人",
columns: [{
checkbox: true,
printIgnore: true
},
{
field: 'userid',
title: '用户id',
visible: false,
printIgnore: true
},
{
field: 'name',
title: '用户名称'
},
{
field: 'mobile',
title: '电话'
},
{
field: 'companyName',
title: '所属公司'
},
{
field: 'title',
title: '职位'
},
{
title: '操作',
align: 'center',
printIgnore: true,
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.userid + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.userid + '\')"><i class="fa fa-search-plus"></i>详情</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.userid + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
// 自定义打印页面模板
function printPageBuilder(table) {
return `
<html>
<head>
<style type="text/css" media="print">
@page {
size: auto;
margin: 25px 0 25px 0;
}
</style>
<style type="text/css" media="all">
table {
border-collapse: collapse;
font-size: 12px;
}
table, th, td {
border: 1px solid grey;
}
th, td {
text-align: center;
vertical-align: middle;
}
p {
font-weight: bold;
margin-left:20px;
}
table {
width:95%;
margin-left:3%;
margin-right:3%;
}
div.bs-table-print {
text-align:center;
}
</style>
</head>
<title>打印外部联系人</title>
<body>
<h1 style="text-align:center">打印外部联系人 </h1>
<div class="bs-table-print">${table}</div>
</body>
</html>`
}
</script>
</body>
</html>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<head>
<th:block th:include="include :: header('我发起的流程详情')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<input name="deploymentId" id="deploymentId" th:value="${deploymentVO.id}" type="hidden" >
<div class="ibox float-e-margins">
<h4 class="form-header h4">发布概况</h4>
<div class="vertical-timeline-block" >
<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('flow_category',deploymentVO.category)}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">流程名称:</label>
<span class="form-control-static" th:text="${deploymentVO.name}">
</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">发布key</label>
<span class="form-control-static" th:text="${deploymentVO.key}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">发布时间:</label>
<span class="form-control-static" th:text="${#dates.format(deploymentVO.deploymentTime, '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="form-control-static" th:text="${deploymentVO.isNew}">
</span>
</div>
</div>
<div class="float-e-margins">
<h4 class="form-header h4">流程定义表单</h4>
<div class="vertical-timeline-block" >
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-10 col-sm-10 ">
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>定义名称</th>
<th>定义key</th>
<th>版本</th>
<th>定义描述</th>
</tr>
</thead>
<tbody>
<tr th:each="processDef,iterStat : ${deploymentVO.processDefVOList}">
<td>[[${processDef.id}]]</td>
<td>[[${processDef.name}]]</td>
<td>[[${processDef.key}]]</td>
<td>[[${processDef.version}]]</td>
<td>[[${processDef.description}]]</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="float-e-margins">
<h4 class="form-header h4">流程图</h4>
<div class="vertical-timeline-block" >
<div class="row">
<div class="col-xs-1 col-sm-1 "></div>
<div class="col-xs-10 col-sm-10 ">
<img class="imgcode" width="95%"/>
</div>
</div>
</div>
</div>
<br>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
$(function () {
var deploymentId= $("#deploymentId").val();
var url ='/modeler/getFlowPicture?id='+deploymentId+'&resourceName=';
$(".imgcode").attr("src", url);
});
function getProcessDiagram() {
var appId= $("#appId").val();
var busVarUrl= $("#busVarUrl").val();
$.modal.open('业务单', busVarUrl+"/"+appId);
}
</script>
</body>
</html>

View File

@ -53,6 +53,7 @@
var editFlag = [[${@permission.hasPermi('system:flow:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:flow:remove')}]];
var flowCategoryDatas = [[${@dict.getType('flow_category')}]];
var detailFlag = [[${@permission.hasPermi('modeler:deployment:detail')}]];
var prefix = ctx + "modeler";
$(function() {
var options = {
@ -61,6 +62,7 @@
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
importUrl: prefix + "/importData",
detailUrl: prefix + "/getDeploymentDetail/{id}",
importTemplateUrl: prefix + "/importTemplate",
modalName: "流程发布实例",
columns: [{
@ -104,8 +106,8 @@
var getXmlUrl=prefix+'/getXml?id='+row.id+'&resourceName=';
var actions = [];
/* actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="previewXml(\'' + processDefinition.deploymentId + '\',\''+processDefinition.diagramResourceName+'\');"><i class="fa fa-edit"></i>流程图</a> ');*/
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="previewXml(\'' + row.id+ '\',);"><i class="fa fa-edit"></i>流程图</a> ');
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detail(\'' + row.id + '\')"><i class="fa fa-eye"></i>详情</a> ');
/* actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="previewXml(\'' + row.id+ '\',);"><i class="fa fa-edit"></i>流程图</a> ');*/
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="'+getXmlUrl+'" target="_blank"><i class="fa fa-eye"></i>XML</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
@ -120,7 +122,6 @@
* @param tableId
*/
function previewXml(deploymentId) {
console.log(JSON.stringify(deploymentId));
var preViewUrl=prefix+'/getFlowPicture?id='+deploymentId+'&resourceName=';
$.modal.openTab("预览流程图", preViewUrl);
}

View File

@ -38,7 +38,7 @@
var prefixFlow = ctx + "flow";
$(function() {
var options = {
url: prefixFlow + "/getMyTakePartInProcess",
url: prefixFlow + "/getMyTakePartInTask",
modalName: "我的已办",
striped: true, //是否显示行间隔色
showToggle: false,
@ -62,7 +62,18 @@
field: 'taskName',
title: '任务名称'
},
{
field: 'isPass',
title: '处理结果',
formatter: function(value, row, index) {
if(value=="true"){
return '<span class="text-success">通过</span> ';
}else if(value=="false"){
return '<span class="text-danger" >驳回</span> ';
}
return '<span class="text-primary" >其他</span> ';
}
},
{
field: 'businessKey',
title: '单号',
@ -73,8 +84,12 @@
},
{
field: 'assignee',
title: '任务完成人'
field: 'startUserName',
title: '流程发起人'
},
{
field: 'startTime',
title: '创建时间'
},
{
@ -85,13 +100,12 @@
field: 'handleTaskTime',
title: '任务耗时'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="fromDetailUrl(\''+row.fromDetailUrl+'\')"><i class="fa fa-eye"></i>详情</a> ');
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="taskDetail(\'' + row.taskId + '\')"><i class="fa fa-eye"></i>详情</a> ');
return actions.join('');
}
}]
@ -100,10 +114,11 @@
});
function getProcessDiagram(processInstanceId) {
var preViewUrl=prefix+'/getProcessDiagram?processInstanceId='+processInstanceId;
$.modal.openTab("流程图", preViewUrl);
function taskDetail(taskId) {
var url=prefixFlow+'/getMyTaskedDetail?taskId='+taskId;
$.modal.openTab("已办任务详情", url);
}
function fromDetailUrl(url) {
$.modal.openTab("详情", url);
}

View File

@ -0,0 +1,185 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<head>
<th:block th:include="include :: header('我发起的流程详情')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-sequence-edit" >
<input name="processInstanceId" id="processInstanceId" th:value="${processInstance.id}" type="hidden" >
<input name="busVarUrl" id="busVarUrl" th:value="${busVarUrl}" type="hidden" >
<input name="appId" id="appId" th:value="${appId}" type="hidden" >
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程概况</h4>
<div class="vertical-timeline-block" >
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">流程名称:</label>
<div class="form-control-static" th:text="${processInstance.processDefinitionName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程状态:</label>
<div class="form-control-static" th:if="${processInstance.isFinished==0}">
<span class="badge badge-info">进行中</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==1}">
<span class="badge badge-success">结束</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==2}">
<span class="badge badge-warning">取消</span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">发起人:</label>
<div class="form-control-static" th:text="${processInstance.startUserName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程已用时:</label>
<div class="form-control-static" th:text="${processInstance.processSpendTime}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">开始时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.startTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">结束时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.endTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1" th:if="${processInstance.isFinished==2}">
<label class="col-sm-3 control-label">取消原因:</label>
<div class="form-control-static" th:text="${processInstance.deleteReason}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">业务单详情:</label>
<div class="form-control-static" >
<a href="javascript:void(0)" onclick="getProcessDiagram()">
[[${processInstance.businessKey}]]
</a>
</div>
</div>
</div>
</div>
</div>
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程图</h4>
<div class="vertical-timeline-block" >
<img class="imgcode" width="85%"/>
</div>
</div>
<div class="ibox float-e-margins form-horizontal">
<h4 class="form-header h4">任务概况</h4>
<div id="ibox-content">
<div id="vertical-timeline" class="vertical-container light-timeline light-dark">
<div class="vertical-timeline-block" >
<div class="vertical-timeline-icon navy-bg">
<i class="fa fa-hand-o-right"></i>
</div>
<div class="vertical-timeline-content ">
<h2 th:text="${hisTask.taskName }"></h2>
<br class="form-group">
<div class="row">
<div class="col-md-4" th:if="${hisTask.isStart} == ''">
<label >审批结果:</label>
<label th:switch="${hisTask.isPass}">
<span class="btn-outline btn-danger" th:case="'false'">驳回</span>
<span class="btn-outline btn-success" th:case="'true'">通过</span>
<span class="btn-outline btn-info" th:case=" ''">待审核</span>
</label>
</div>
<div class="col-md-4" th:if="${hisTask.assigneeName} != null">
<label >审批人:</label>
<span th:text="${hisTask.assigneeName}"></span>
</div>
<div class="col-md-4" th:if="${hisTask.handleTaskTime} != null">
<label>任务历时:</label>
<label>
<span th:text="${hisTask.handleTaskTime}"></span>
</label>
</div>
</div>
</br>
<div class="row" >
<div class="col-md-12">
<label>可审批人:</label>
<span th:each="userName:${hisTask.handleUserList}">
<label th:if="${userName} ne ''">&nbsp;&nbsp
<span th:text="${userName}"></span>
</label>
</span>
</div>
</div>
</br>
<div class="row">
<div class="col-md-12">
<span class="vertical-date">
<label>任务时间:</label> <small th:text="${#dates.format(hisTask.startTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
<label>~</label> <small th:text="${#dates.format(hisTask.completeTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
</span>
</div>
</div>
</br>
<div class="row">
<div class="col-md-12">
<div th:each="comment:${hisTask.commentList}">
<label>审批意见:</label>
<label th:if="${comment.fullMessage} ne ''">
<span th:text="${comment.fullMessage}"></span>
</label>
</div>
</div>
</div>
</br>
<div class="row">
<div class="col-md-12">
<div th:each="attachment:${hisTask.attachmentList}">
<label>附件:</label>
<label th:if="${attachment.url} ne ''">
<a th:href="${attachment.url}" target="_blank"><span th:text="${attachment.name}"></span></a>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
$(function () {
var processInstanceId= $("#processInstanceId").val();
var url ="/modeler/getProcessDiagram?processInstanceId="+processInstanceId;
$(".imgcode").attr("src", url);
});
function getProcessDiagram() {
var appId= $("#appId").val();
var busVarUrl= $("#busVarUrl").val();
$.modal.open('业务单', busVarUrl+"/"+appId);
}
</script>
</body>
</html>

View File

@ -38,12 +38,15 @@
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: select2-js" />
<script th:inline="javascript">
var detailFlag = [[${@permission.hasPermi('system:flow:myStartProcessDetail')}]];
var processInstanceStatusDatas = [[${@dict.getType('process_instance_status')}]];
var activeProcessInstanceFlag = [[${@permission.hasPermi('system:flow:activeProcessInstance')}]];
var suspendProcessInstanceFlag = [[${@permission.hasPermi('system:flow:suspendProcessInstance')}]];
var cancelProcessInstanceFlag = [[${@permission.hasPermi('system:flow:cancelProcessInstance')}]];
var prefixFlow = ctx + "flow";
$(function() {
var options = {
url: prefixFlow + "/getMyHistoricProcessInstance",
@ -64,6 +67,10 @@
return index+1;
}
},
{
field: 'id',
title: '实例id'
},
{
field: 'processDefinitionName',
title: '流程名称'
@ -115,24 +122,94 @@
if(processInstanceStatus==2&&isFinished==0){
actions.push('<a class="btn btn-success btn-xs ' + activeProcessInstanceFlag + '" href="javascript:void(0)" onclick="$.operate.activeProcessInstance(\'' + row.id + '\')"><i class="fa fa-eye"></i>激活</a> ');
}
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="getProcessDiagram(\'' + row.id + '\')"><i class="fa fa-eye"></i>详情</a>');
if(isFinished==0) {
actions.push('<a class="btn btn-warning btn-xs ' + cancelProcessInstanceFlag + '" href="javascript:void(0)" onclick="cancelProcessInstance(\'' + row.id + '\')"><i class="fa fa-delicious"></i>取消</a> ');
}
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="myStartProcessDetail(\'' + row.id + '\')"><i class="fa fa-eye"></i>详情</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
function getProcessDiagram(processInstanceId) {
function myStartProcessDetail(processInstanceId) {
var preViewUrl=prefixFlow+'/myStartProcessDetail?processInstanceId='+processInstanceId;
$.modal.openTab("详情", preViewUrl);
$.modal.openTab("流程详情", preViewUrl);
}
function fromDetailUrl(detailUrl) {
$.modal.openTab("详情", detailUrl);
}
// 取消流程
function cancelProcessInstance(id) {
layer.open({
type: 1,
area: ['500px', '350px'],
fix: false,
//不固定
maxmin: false,
shade: 0.3,
title: '取消流程',
content: $('#deleteProcessInstanceTpl').html(),
btn: ['<i class="fa fa-check"></i>提交', '<i class="fa fa-remove"></i> 取消'],
// 弹层外区域关闭
shadeClose: true,
btn1: function(index, layero){
var reason = layero.find('#reason').val();
if(reason==''||reason==null){
$.modal.msgWarning("取消理由不能为空");
return false;
}
var index = layer.load(2, {shade: false});
$.modal.disable();
var formData = new FormData(layero.find('form')[0]);
formData.set("id",id);
$.ajax({
url: prefixFlow+"/deleteProcessInstance",
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function (result) {
if (result.code == web_status.SUCCESS) {
$.modal.closeAll();
$.modal.alertSuccess(result.msg);
$.table.refresh();
} else {
layer.close(index);
$.modal.enable();
$.modal.alertError(result.msg);
}
}
});
}
});
}
</script>
</body>
<!-- 导入区域 -->
<script id="deleteProcessInstanceTpl" type="text/template">
<form enctype="multipart/form-data" class=" form-horizontal m mt20 mb10" >
<div class="col-xs-offset-1">
<div class="row">
<div class="form-group">
<label class="col-sm-3 control-label">取消理由:</label>
<div class="col-sm-8">
<textarea name="reason" id="reason" class="form-control" rows="7" placeholder="请输入取消理由..." required></textarea>
</div>
</div>
</div>
<!--<font color="red" class="pull-left mt10">
提示仅允许导入“xls”或“xlsx”格式文件
</font>-->
</div>
</form>
</script>
</html>

View File

@ -10,16 +10,73 @@
<input name="busVarUrl" id="busVarUrl" th:value="${busVarUrl}" type="hidden" >
<input name="appId" id="appId" th:value="${appId}" type="hidden" >
<div class="ibox float-e-margins" id="busPage">
<h4 class="form-header h4">业务数据</h4>
<p>
<div class="row">
<div class="col-sm-offset-1 col-sm-10">
<a class="btn btn-info btn-large" href="javascript:void(0)" onclick="getProcessDiagram()"><i class="fa fa-eye"></i>获取业务单</a>
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程概况</h4>
<div class="vertical-timeline-block" >
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">流程名称:</label>
<div class="form-control-static" th:text="${processInstance.processDefinitionName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程状态:</label>
<div class="form-control-static" th:if="${processInstance.isFinished==0}">
<span class="badge badge-info">进行中</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==1}">
<span class="badge badge-success">结束</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==2}">
<span class="badge badge-warning">取消</span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">发起人:</label>
<div class="form-control-static" th:text="${processInstance.startUserName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程已用时:</label>
<div class="form-control-static" th:text="${processInstance.processSpendTime}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">开始时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.startTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">结束时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.endTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1" th:if="${processInstance.isFinished==2}">
<label class="col-sm-3 control-label">取消原因:</label>
<div class="form-control-static" th:text="${processInstance.deleteReason}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">业务单详情:</label>
<div class="form-control-static" >
<a href="javascript:void(0)" onclick="getProcessDiagram()">
[[${processInstance.businessKey}]]
</a>
</div>
</div>
</div>
</div>
</p>
</div>
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程图</h4>
<div class="vertical-timeline-block" >

View File

@ -64,7 +64,7 @@
<div class="col-lg-6 features-text wow fadeInLeft">
<!--<small>DingFlow</small>-->
<h2>DingFlow</h2>
<p>  DingFlow项目也叫Snow系统。项目之初是笔者的一个flowable学习demo取其雪之意念及雪之人便有了Snow。后来 在公司集成钉钉接口时偶然间发现钉钉自带工作流插件便想利用业余时间打造一款开源的面向中小型企业管理系统。该管理系统能和钉钉数据打通企业可以通过钉钉移动化办公也可通过系统开发满足自身不同需求。DingFlow取其DingTalk和Flowable的前四个单词组成。寓意着构建钉钉工作流一体化。目前系统还处于初始孵化阶段 虽然目标很明确但是具体的实施方案还不够详细。笔者也呼吁有能之士能参与进来一起携手做好DingFlow。</p>
<p>  DingFlow项目也叫Snow系统。项目之初是笔者的一个flowable学习demo取其雪之意为之Snow。后来在公司集成钉钉接口时偶然间发现钉钉自带工作流插件便想利用业余时间打造一款开源的面向中小型企业管理系统。该管理系统能和钉钉数据打通企业可以通过钉钉移动化办公也可通过系统开发满足自身不同需求。DingFlow取其DingTalk和Flowable的前四个单词组成。寓意着构建钉钉工作流一体化。目前系统还处于初始孵化阶段虽然目标很明确但是具体的实施方案还不够详细。笔者也呼吁有能之士能参与进来一起携手做好DingFlow。</p>
<a href="" class="btn btn-primary">学到更多</a>
</div>
<div class="col-lg-6 text-right wow fadeInRight">
@ -551,7 +551,7 @@
<form id="signupForm" autocomplete="off">
<div class="form-group"><!--<label>用户名</label> --><input type="text" name="username" class="form-control uname" placeholder="请输入用户名" /></div>
<div class="form-group"><!--<label>密码</label> --><input type="password" name="password" placeholder="请输入密码" class="form-control pword"></div>
<div class="row m-t form-group" th:if="${captchaEnabled==true}">
<div class="row m-t form-group">
<div class="col-xs-6">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" />
</div>
@ -596,7 +596,7 @@
<script src="/static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="/static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="/static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.3.1}"></script>
<script src="/static/ruoyi/front-login.js" th:src="@{/ruoyi/front-login.js}"></script>
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
<script th:inline="javascript">
$(document).ready(function () {
@ -650,99 +650,6 @@
// Activate WOW.js plugin for animation on scrol
new WOW().init();
$(function() {
validateKickout();
validateRule();
$('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url);
});
});
$("#btnSubmit").click(function () {
login();
})
function login() {
$.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val();
var rememberMe = $("input[name='rememberme']").is(':checked');
$.ajax({
type: "post",
url: ctx + "login",
data: {
"username": username,
"password": password,
"validateCode": validateCode,
"rememberMe": rememberMe
},
success: function(r) {
if (r.code == 0) {
location.href ='/front/main';
} else {
$.modal.closeLoading();
$('.imgcode').click();
$(".code").val("");
$.modal.msg(r.msg);
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#signupForm").validate({
rules: {
username: {
required: true
},
password: {
required: true
}
},
messages: {
username: {
required: icon + "请输入您的用户名",
},
password: {
required: icon + "请输入您的密码",
}
}
})
}
function validateKickout() {
if (getParam("kickout") == 1) {
layer.alert("<font color='red'>您已在别处登录,请您修改密码或重新登录</font>", {
icon: 0,
title: "系统提示"
},
function(index) {
//关闭弹窗
layer.close(index);
if (top != self) {
top.location = self.location;
} else {
var url  =  location.search;
if (url) {
var oldUrl  = window.location.href;
var newUrl  = oldUrl.substring(0,  oldUrl.indexOf('?'));
self.location  = newUrl;
}
}
});
}
}
function getParam(paramName) {
var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
}
</script>
</body>

View File

@ -22,6 +22,7 @@
<a id="scroll-up" href="#" class="btn btn-sm display"><i class="fa fa-angle-double-up"></i></a>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/js/base64.min.js}"></script>
<!-- bootstrap-table 表格插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=20200727}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=20200727}"></script>

View File

@ -123,8 +123,8 @@
</a>
<ul class="dropdown-menu dropdown-alerts">
<li th:each="sysMessages,iterStat:${sysMessageList}" class="mt5">
<a href="javascript:void(0)" th:onclick="messageDetail([[${sysMessages.pcUrl}]]);">
<i th:class="${sysMessages.iconClass}"></i>[[${sysMessages.producerUser.userName}]]发送来一条消息<span class="pull-right text-muted small">[[${sysMessages.spendTime}]]</span>
<a href="javascript:void(0)" th:onclick="messageDetail([[${sysMessages.pcUrl}]]);" >
<i th:class="${sysMessages.iconClass}"></i><span class="text-success">[[${sysMessages.producerUser!=null?sysMessages.producerUser.userName:'系统'}]]</span> 发送来一条消息<span class="pull-right text-muted small">[[${sysMessages.spendTime}]]</span>
</a>
</li>
<li class="divider"></li>
@ -284,7 +284,6 @@ function messageDetail(url){
area : ["70%", "80%"],
content : [url, 'yes']
})
}
function mailDetailAll() {

View File

@ -23,7 +23,7 @@
<body class="signin">
<div class="signinpanel">
<div class="row">
<h1>欢迎使用 <strong>DingFLow 后台管理系统</strong></h1>
<h1>欢迎使用 <strong>DingFlow 后台管理系统</strong></h1>
</div>
<div class="row">
<div class="col-sm-8">

View File

@ -7,10 +7,19 @@
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-flow-add">
<div class="form-group">
<label class="col-sm-3 control-label">账单类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('bill_type')}">
<input type="radio" th:id="${'billType_' + dict.dictCode}" name=" billType" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'billType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易号:</label>
<div class="col-sm-8">
<input name="tradeNo" class="form-control" type="text">
<input name="tradeNo" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
@ -23,8 +32,7 @@
<label class="col-sm-3 control-label">交易创建时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="tradeCreateTime" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input name="tradeCreateTime" class="datetime-input form-control" placeholder="yyyy-MM-dd HH:mm:ss" type="text" required>
</div>
</div>
</div>
@ -32,17 +40,55 @@
<label class="col-sm-3 control-label">交易支付时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="payTime" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input name="payTime" class="datetime-input form-control" placeholder="yyyy-MM-dd HH:mm:ss" type="text" required>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">最近修改时间</label>
<div class="form-group">
<label class="col-sm-3 control-label">收支类型</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="lastModifyTime" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<div class="radio-box" th:each="dict : ${@dict.getType('income_expenditure_type')}">
<input type="radio" th:id="${'incomeExpenditureType_' + dict.dictCode}" name="incomeExpenditureType" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'incomeExpenditureType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">真实收支类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('finance_real_sz_type')}">
<input type="radio" th:id="${'realIncomeExpenditureType_' + dict.dictCode}" name="realIncomeExpenditureType" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'realIncomeExpenditureType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">商品:</label>
<div class="col-sm-8">
<input name="goodsName" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易金额:</label>
<div class="col-sm-8">
<input name="tradePrice" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">财务用途:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('real_finance_type')}">
<input type="radio" th:id="${'realFinanceType_' + dict.dictCode}" name="realFinanceType" th:value="${dict.dictValue}" th:checked="${dict.default}" >
<label th:for="${'realFinanceType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易状态:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('trade_status_type')}">
<input type="radio" th:id="${'tradeStatus_' + dict.dictCode}" name="tradeStatus" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'tradeStatus_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
@ -61,36 +107,14 @@
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易对方:</label>
<div class="col-sm-8">
<input name="counterparty" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易金额:</label>
<div class="col-sm-8">
<input name="tradePrice" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易状态:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('trade_status_type')}">
<input type="radio" th:id="${'tradeStatus_' + dict.dictCode}" name="tradeStatus" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'tradeStatus_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">收支类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('income_expenditure_type')}">
<input type="radio" th:id="${'incomeExpenditureType_' + dict.dictCode}" name="incomeExpenditureType" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'incomeExpenditureType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">服务费:</label>
<div class="col-sm-8">
@ -112,12 +136,6 @@
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">所属人:</label>
<div class="col-sm-8">
<input name="belongUserId" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易主体账户:</label>
<div class="col-sm-8">
@ -147,7 +165,7 @@
}
$("input[name='tradeCreateTime']").datetimepicker({
format: "yyyy-mm-dd",
format: "yyyy-mm-dd hh:mm:ss",
minView: "month",
autoclose: true
});

View File

@ -11,20 +11,47 @@
<div class="form-group">
<label class="col-sm-3 control-label">交易号:</label>
<div class="col-sm-8">
<input name="tradeNo" th:field="*{tradeNo}" class="form-control" type="text">
<input name="tradeNo" th:field="*{tradeNo}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">商家订单号:</label>
<div class="col-sm-8">
<input name="orderNo" th:field="*{orderNo}" class="form-control" type="text">
<input name="orderNo" th:field="*{orderNo}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">商品:</label>
<div class="col-sm-8">
<input name="goodsName" th:field="*{goodsName}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易对方:</label>
<div class="col-sm-8">
<input name="counterparty" th:field="*{counterparty}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易金额:</label>
<div class="col-sm-8">
<input name="tradePrice" th:field="*{tradePrice}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">财务用途:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('real_finance_type')}">
<input type="radio" th:id="${'realFinanceType_' + dict.dictCode}" name="realFinanceType" th:value="${dict.dictValue}" th:field="*{realFinanceType}">
<label th:for="${'realFinanceType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易创建时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="tradeCreateTime" th:value="${#dates.format(financeAlipayFlow.tradeCreateTime, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
<input name="tradeCreateTime" th:value="${#dates.format(financeAlipayFlow.tradeCreateTime, 'yyyy-MM-dd hh:mm:ss')}" class="form-control" placeholder="yyyy-MM-dd" type="text" readonly>
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
@ -33,16 +60,7 @@
<label class="col-sm-3 control-label">交易支付时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="payTime" th:value="${#dates.format(financeAlipayFlow.payTime, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">最近修改时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="lastModifyTime" th:value="${#dates.format(financeAlipayFlow.lastModifyTime, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
<input name="payTime" th:value="${#dates.format(financeAlipayFlow.payTime, 'yyyy-MM-dd hh:mm:ss')}" class="form-control" placeholder="yyyy-MM-dd" type="text" readonly="readonly">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
@ -62,19 +80,8 @@
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易对方:</label>
<div class="col-sm-8">
<input name="counterparty" th:field="*{counterparty}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易金额:</label>
<div class="col-sm-8">
<input name="tradePrice" th:field="*{tradePrice}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<div class="form-group">
<label class="col-sm-3 control-label">交易状态:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('trade_status_type')}">
@ -92,6 +99,15 @@
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">真实收支类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('finance_real_sz_type')}">
<input type="radio" th:id="${'realIncomeExpenditureType_' + dict.dictCode}" name="realIncomeExpenditureType" th:value="${dict.dictValue}" th:field="*{realIncomeExpenditureType}">
<label th:for="${'realIncomeExpenditureType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">服务费:</label>
<div class="col-sm-8">
@ -113,18 +129,6 @@
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">所属人:</label>
<div class="col-sm-8">
<input name="belongUserId" th:field="*{belongUserId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易主体账户:</label>
<div class="col-sm-8">
<input name="tradeAccount" th:field="*{tradeAccount}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易真实姓名:</label>
<div class="col-sm-8">
@ -147,18 +151,6 @@
}
}
$("input[name='tradeCreateTime']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
});
$("input[name='payTime']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
});
$("input[name='lastModifyTime']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",

View File

@ -17,7 +17,7 @@
<input type="text" name="tradeNo"/>
</li>
<li>
<label>商家订单号:</label>
<label>订单号:</label>
<input type="text" name="orderNo"/>
</li>
<li>
@ -39,16 +39,16 @@
</select>
</li>
<li>
<label>收支类型</label>
<select name="incomeExpenditureType" th:with="type=${@dict.getType('income_expenditure_type')}">
<label>真实收支:</label>
<select name="realIncomeExpenditureType" th:with="type=${@dict.getType('real_income_expenditure_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
<label>资金状态</label>
<select name="capitalStatus" th:with="type=${@dict.getType('capital_status')}">
<label>财务用途</label>
<select name="realFinanceType" th:with="type=${@dict.getType('real_finance_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
@ -76,8 +76,14 @@
<a class="btn btn-info" onclick="$.table.importExcelAlipay()" shiro:hasPermission="system:flow:import">
<i class="fa fa-upload"></i> 导入
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:flow:export">
<!-- <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:flow:export">
<i class="fa fa-download"></i> 导出
</a>-->
<a class="btn btn-primary" onclick="designDicType('134')" shiro:hasPermission="system:flow:designTradeType">
<i class="fa fa-sort-numeric-desc"></i> 设计收支类型
</a>
<a class="btn btn-warning" onclick="designDicType('135')" shiro:hasPermission="system:flow:designTradeType">
<i class="fa fa-cny"></i> 设计财务用途
</a>
</div>
<div class="col-sm-12 select-table table-striped">
@ -93,6 +99,8 @@
var tradeTypeDatas = [[${@dict.getType('trade_type')}]];
var tradeStatusDatas = [[${@dict.getType('trade_status_type')}]];
var incomeExpenditureTypeDatas = [[${@dict.getType('income_expenditure_type')}]];
var realIncomeExpenditureTypeDatas = [[${@dict.getType('finance_real_sz_type')}]];
var realFinanceTypeDatas = [[${@dict.getType('real_finance_type')}]];
var capitalStatusDatas = [[${@dict.getType('capital_status')}]];
var billTypeDatas = [[${@dict.getType('bill_type')}]];
var prefix = ctx + "system/flow";
@ -107,7 +115,10 @@
importUrl: prefix + "/importData",
importTemplateUrl: prefix + "/importTemplate",
modalName: "财务账单流水",
columns: [{
showFooter: true,
footerStyle: footerStyle,
columns:
[{
checkbox: true
},
{
@ -119,11 +130,7 @@
field: 'tradeNo',
title: '交易号',
formatter: function(value, row, index) {
if(value==null||value==''){
return '';
}else {
return value.substr(0,8);
}
return $.table.tooltip(value);
}
},
@ -131,25 +138,28 @@
field: 'orderNo',
title: '商家订单号',
formatter: function(value, row, index) {
if(value==null||value==''){
return '';
}else {
return value.substr(0,8);
}
return $.table.tooltip(value);
}
},
{
field: 'goodsName',
title: '商品',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
field: 'goodsName',
title: '商品'
},
{
field: 'tradePrice',
title: '交易金额'
field: 'realFinanceType',
title: '财务用途',
formatter: function(value, row, index) {
return $.table.selectDictLabel(realFinanceTypeDatas, value);
}
},
{
field: 'payTime',
title: '交易支付时间'
},
field: 'tradePrice',
title: '交易金额(元)'
},
{
field: 'billType',
title: '账单类型',
@ -166,7 +176,10 @@
},
{
field: 'counterparty',
title: '交易对方'
title: '交易对方',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
@ -178,16 +191,60 @@
},
{
field: 'incomeExpenditureType',
title: '收支类型',
title: '账单收支类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(incomeExpenditureTypeDatas, value);
},
footerFormatter:function (value) {
var tradePrice = 0;
for (var i in value) {
//支出
if(value[i].realIncomeExpenditureType==2){
tradePrice+=parseFloat(value[i].tradePrice);
}
}
return "总收入:" + tradePrice;
}
},
{
field: 'realIncomeExpenditureType',
title: '真实收支类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(realIncomeExpenditureTypeDatas, value);
},
footerFormatter:function (value) {
var tradePrice = 0;
for (var i in value) {
//支出
if(value[i].realIncomeExpenditureType==1){
tradePrice+=parseFloat(value[i].tradePrice);
}
}
return "总支出:" + tradePrice;
}
},
{
field: 'payTime',
title: '交易时间',
footerFormatter:function (value) {
var tradePrice = 0;
for (var i in value) {
//支出
if(value[i].realIncomeExpenditureType==1){
tradePrice-=parseFloat(value[i].tradePrice);
}else if(value[i].realIncomeExpenditureType==2){
tradePrice += parseFloat(value[i].tradePrice);
}
}
return "总金额:" + tradePrice;
}
},
/*
{
field: 'belongUserName',
title: '所属人'
},
},*/
{
title: '操作',
align: 'center',
@ -201,6 +258,23 @@
};
$.table.init(options);
});
function importTemplate(fileName) {
window.location.href = "/common/downloadExcel?fileName="+fileName;
}
/*字典列表-详细*/
function designDicType(dictId) {
var url = '/system/dict/detail/' + dictId;
$.modal.openTab("字典数据", url);
}
function footerStyle(column) {
return {
tradePrice: {
css: { color: 'red', 'font-weight': 'normal' }
}
}[column.field]
}
</script>
</body>
<!-- 导入区域 -->
@ -209,12 +283,20 @@
<div class="col-xs-offset-1">
<div class="row">
<div class="form-group">
<label class="col-sm-3 control-label">导入数据</label>
<div class="col-sm-4">
<input type="file" id="file" name="file"/>
<label class="col-sm-3 control-label">下载模板</label>
<div class="col-sm-3">
<a onclick="importTemplate('alipay_record_excel.xlsx')" class="btn btn-xs btn-danger"><i class="fa fa-file-excel-o"></i> 下载支付宝模板</a>
</div>
<div class="col-sm-4">
<a onclick="$.table.importTemplate()" class="btn btn-xs btn-danger"><i class="fa fa-file-excel-o"></i> 下载模板</a>
<div class="col-sm-3">
<a onclick="importTemplate('wechat_excel')" class="btn btn-xs btn-danger"><i class="fa fa-file-excel-o"></i> 下载微信模板</a>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="col-sm-3 control-label">导入数据:</label>
<div class="col-sm-5">
<input type="file" id="file" name="file"/>
</div>
</div>
</div>
@ -246,7 +328,7 @@
</div>
</div>
<font color="red" class="pull-left mt10">
提示仅允许导入“xls”或“xlsx”格式文件
提示仅允许导入“xls”或“xlsx”格式文件支付宝和微信导出的账单是csv格式请转换成支持的格式再导入。<h4>切记:千万不要直接改文件后缀名字!!!</h4>
</font>
</div>
</form>

View File

@ -47,7 +47,8 @@
<label class="col-sm-3 control-label">附件:</label>
<div class="form-control-static">
<input type="hidden" name="fileUrl" id="fileKey" th:value="${appFrom.fileUrl}">
<a id="fileName"></a>
<a id="fileName"></a>
</div>
</div>
<th:block th:include="include :: approvalpage" />
@ -77,6 +78,9 @@
$("#fileName").text(data.name);
});
function preview(url) {
window.open('http://47.98.36.102:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
}
$(".file-upload").each(function (i) {
var val = $("input[name='" + this.id + "']").val();
@ -89,6 +93,7 @@
}).on('fileuploaded', function (event, data, previewId, index) {
files.push({"key": data.response.fileKey,"name": data.response.fileName, "url":data.response.url});
console.log("===================>"+JSON.stringify(data));
}).on('fileremoved', function (event, id, index) {
$("input[name='" + event.currentTarget.id + "']").val('')
})
@ -114,7 +119,6 @@
}
console.log(data);
$.operate.saveTab("/flow/finishTask", data);
$.operate.saveTab("/flow/finishTask", data);
}
}

View File

@ -55,7 +55,7 @@
<div class="form-group">
<label class="col-sm-3 control-label">附件:</label>
<div class="col-sm-8">
<input type="hidden" name="fileUrl" id="filekey" th:value="*{appFrom.fileUrl}">
<input type="hidden" name="fileUrl" id="filekey" th:value="*{fileUrl}">
<div class="form-control-static">
<a id="fileName"></a>
</div>
@ -94,6 +94,7 @@
autoReplace: true
}).on('fileuploaded', function (event, data, previewId, index) {
files.push({"key": data.response.fileKey,"name": data.response.fileName, "url":data.response.url});
console.log("===================>"+JSON.stringify(data));
}).on('fileremoved', function (event, id, index) {
$("input[name='" + event.currentTarget.id + "']").val('')
})

View File

@ -59,6 +59,7 @@
<input type="hidden" name="fileUrl" id="filekey" th:field="*{fileUrl}">
<div class="form-control-static">
<a id="fileName"></a>
<button id="preview">预览</button>
</div>
<div class="file-loading">
<input class="form-control file-upload" id="fileUrl" name="file" type="file">
@ -82,6 +83,17 @@
}
}
$(function() {
var filekey=$("#fileKey").val()
var data= $.common.getFileByKey(filekey);
console.log(JSON.stringify(data))
$("#preview").click(function () {
preview(data.url);
})
});
function preview(url) {
window.open('http://47.98.36.102:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
}
$(".file-upload").each(function (i) {
var val = $("input[name='" + this.id + "']").val()
$(this).fileinput({

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('人事审批')" />
<th:block th:include="include :: header('请假详情')" />
<th:block th:include="include :: jsonview-css" />
<th:block th:include="include :: bootstrap-fileinput-css"/>
</head>
@ -45,10 +45,10 @@
<input type="hidden" name="fileUrl" id="fileKey" th:value="${sysOaLeave.fileUrl}">
<div class="form-control-static">
<a id="fileName"></a>
<a th:onclick="preview(${appFrom.fileUrl})">预览</a>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
@ -67,6 +67,9 @@
$('#fileName').attr('href',"../../../common/download?fileKey="+filekey);
$("#fileName").text(data.name);
});
function preview(url) {
window.open('http://47.98.36.102:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
}
$(".file-upload").each(function (i) {
var val = $("input[name='" + this.id + "']").val();

View File

@ -15,14 +15,24 @@
<a data-toggle="tab" href="#tab-1"> 拜访日志 <span class="label label-info pull-right">[[${visitLogCount}]]</span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-2"> 站内邮件 <span class="label label-info pull-right" >[[${emailListCount}]]</span></a>
</li>
<li class=""><a data-toggle="tab" href="#tab-3"> 第二个选项卡</a>
<li class="">
<a data-toggle="tab" href="#tab-3"> 流程待办 <span class="label label-info pull-right" >[[${todoTaskCount}]]</span></a>
</li>
<li class=""><a data-toggle="tab" href="#tab-4"> 第二个选项卡</a>
<li class="">
<a data-toggle="tab" href="#tab-4"> 流程完结 <span class="label label-info pull-right" >[[${processEndCount}]]</span></a>
</li>
<li class="">
<a data-toggle="tab" href="#tab-5"> 系统任务 <span class="label label-info pull-right" >[[${sysTaskCount}]]</span></a>
</li>
</ul>
<div class="tab-content ">
<div id="tab-1" class="tab-pane active">
@ -43,7 +53,7 @@
<strong th:text="${#dates.format(visitLog.createTime, 'yyyy-MM-dd HH:mm:ss')}"></strong>
</p>
<label > [[${visitLog.messageContent}]]</label>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${visitLog.pcUrl}]]);"> 查看详情 </a>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${visitLog.id}]],[[${visitLog.pcUrl}]]);"> 查看详情 </a>
<p>
<small class="badge badge-warning"> <i class="fa fa-clock-o"></i>[[${visitLog.spendTime}]]</small>
</p>
@ -53,10 +63,11 @@
</div>
</div>
</div>
<div id="tab-2" class="tab-pane">
<div class="panel-body">
<h3>站内邮件</h3>
<div id="vertical-timeline" class="vertical-container light-timeline" th:each="email,iterStat : ${emailList}">
<div id="vertical-timeline1" class="vertical-container light-timeline" th:each="email,iterStat : ${emailList}">
<div class="vertical-timeline-block">
<div class="vertical-timeline-icon blue-bg">
<i th:class="${email.iconClass}"></i>
@ -71,10 +82,10 @@
<strong th:text="${#dates.format(email.createTime, 'yyyy-MM-dd HH:mm:ss')}"></strong>
</p>
<label >
<a class="text-info" href="#"></i> @[[${email.producerUser.userName}]]</a>
<a class="text-info" href="#"></i> @[[${email.producerUser.userName}]]</a>
</label>
<label > 发来一条站内邮件,请及时查看。</label>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${email.redirectUrl}]]);"> 查看详情 </a>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${email.id}]],${email.redirectUrl}]]);"> 查看详情 </a>
<p>
<small class="badge badge-warning"> <i class="fa fa-clock-o"></i>[[${email.spendTime}]]</small>
</p>
@ -84,33 +95,104 @@
</div>
</div>
</div>
<div id="tab-3" class="tab-pane">
<div class="panel-body">
<strong>栅格系统</strong>
<h3>流程待办</h3>
<div id="vertical-timeline2" class="vertical-container light-timeline" th:each="todoTask,iterStat : ${todoTaskList}">
<div class="vertical-timeline-block">
<div class="vertical-timeline-icon blue-bg">
<i th:class="${todoTask.iconClass}"></i>
</div>
<p>Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统随着屏幕或视口viewport尺寸的增加系统会自动分为最多12列。它包含了易于使用的预定义类还有强大的mixin 用于生成更具语义的布局。</p>
<div class="vertical-timeline-content">
<p>
<label th:switch="${todoTask.messageReadStatus}">
<span class="label label-danger" th:case="'0'">未读</span>
<span class="label label-success" th:case="'1'">已读</span>
</label>
<strong th:text="${#dates.format(todoTask.createTime, 'yyyy-MM-dd HH:mm:ss')}"></strong>
</p>
<p >[[${todoTask.messageContent}]]</p>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${todoTask.id}]],[[${todoTask.pcUrl}]]);"> 查看详情 </a>
<p>
<!--<small class="badge badge-warning"> <i class="fa fa-clock-o"></i>[[${todoTask.spendTime}]]</small>-->
</p>
</div>
<hr>
</div>
</div>
</div>
</div>
<div id="tab-4" class="tab-pane">
<div class="panel-body">
<strong>栅格系统</strong>
<h3>流程完结</h3>
<div id="vertical-timeline4" class="vertical-container light-timeline" th:each="processEnd,iterStat : ${processEndList}">
<div class="vertical-timeline-block">
<div class="vertical-timeline-icon blue-bg">
<i th:class="${processEnd.iconClass}"></i>
</div>
<p>Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统随着屏幕或视口viewport尺寸的增加系统会自动分为最多12列。它包含了易于使用的预定义类还有强大的mixin 用于生成更具语义的布局。</p>
<div class="vertical-timeline-content">
<p>
<label th:switch="${processEnd.messageReadStatus}">
<span class="label label-danger" th:case="'0'">未读</span>
<span class="label label-success" th:case="'1'">已读</span>
</label>
<strong th:text="${#dates.format(processEnd.createTime, 'yyyy-MM-dd HH:mm:ss')}"></strong>
</p>
<p >[[${processEnd.messageContent}]]</p>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${processEnd.id}]],[[${processEnd.pcUrl}]]);"> 查看详情 </a>
</div>
<hr>
</div>
</div>
</div>
</div>
<div id="tab-5" class="tab-pane">
<div class="panel-body">
<h3>系统任务</h3>
<div id="vertical-timeline5" class="vertical-container light-timeline" th:each="sysTask,iterStat : ${sysTaskList}">
<div class="vertical-timeline-block">
<div class="vertical-timeline-icon blue-bg">
<i th:class="${sysTask.iconClass}"></i>
</div>
<div class="vertical-timeline-content">
<p>
<label th:switch="${sysTask.messageReadStatus}">
<span class="label label-danger" th:case="'0'">未读</span>
<span class="label label-success" th:case="'1'">已读</span>
</label>
<strong th:text="${#dates.format(sysTask.createTime, 'yyyy-MM-dd HH:mm:ss')}"></strong>
</p>
<p >[[${sysTask.messageContent}]]</p>
<a href="javascript:void(0)" class="btn btn-sm btn-success" th:onclick="messageDetail([[${sysTask.id}]],[[${sysTask.pcUrl}]]);"> 查看详情 </a>
</div>
<hr>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
function messageDetail(url){
function messageDetail(id,url){
//先标记为已读
markRead(id);
//在跳转到页面
layer.open({
type : 2,
shadeClose : true,
@ -120,6 +202,32 @@
})
}
function markRead(id){
var config = {
url: "/system/messageCenter/remarkRead",
type: "post",
dataType: "json",
data: {
"id":id
},
success: function(result) {
if (typeof callback == "function") {
callback(result);
}
if (result.code == web_status.SUCCESS) {
$(".messageReadStatus badge badge-primary").show();
$(".messageReadStatus badge badge-danger").hide();
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg)
} else {
$.modal.alertError(result.msg);
}
$.modal.closeLoading();
}
};
$.ajax(config)
}
</script>
</body>
</html>

View File

@ -8,7 +8,6 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-notice-edit" th:object="${notice}">
<input id="noticeId" name="noticeId" th:field="*{noticeId}" type="hidden">
<input id="blackboardId" name="blackboardId" th:field="*{blackboardId}" type="hidden">
<div class="form-group">
<label class="col-sm-2 control-label is-required">公告标题:</label>
<div class="col-sm-10">

View File

@ -87,11 +87,12 @@
$(this).fileinput({
'uploadUrl': '/common/upload',
initialPreviewAsData: true,
allowedFileExtensions: ['jpg', 'gif', 'png',".docx","doc","ppt","pptx","xls","xlsx","vsd","rtf","wps","pdf","txt"],//接收的文件后缀
allowedFileExtensions: ['jpg', 'gif', 'png',".docx","doc","ppt","pptx","xls","xlsx","vsd","rtf","wps","pdf","txt","zip"],//接收的文件后缀
initialPreview: [val],
maxFileCount: 1,
autoReplace: true
}).on('fileuploaded', function (event, data, previewId, index) {
console.log("===================>"+JSON.stringify(data));
files.push({"key": data.response.fileKey,"name": data.response.fileName, "url":data.response.url});
// $("input[name='" + event.currentTarget.id + "']").val(data.response.url)
}).on('fileremoved', function (event, id, index) {

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('分配角色选择用户')" />
<th:block th:include="include :: header('选择用户')" />
</head>
<body class="gray-bg">

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增系统任务')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-task-add">
<div class="form-group">
<label class="col-sm-3 control-label is-required">任务类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('sys_task_type')}">
<input type="radio" th:id="${'taskType_' + dict.dictCode}" name="taskType" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'taskType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">任务名称:</label>
<div class="col-sm-8">
<input name="taskName" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">任务内容:</label>
<div class="col-sm-8">
<textarea name="taskContent" class="form-control" rows="7" required></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">紧急程度:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('sys_oa_task_priority')}">
<input type="radio" th:id="${'taskType_' + dict.dictCode}" name="priority" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'taskType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">执行人:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="hidden" name="taskDistributeId" id="taskDistributeId">
<input class="form-control" type="text" name="transitionPersonName" onclick="selectUserInfo()" id="transitionPersonName" readonly="true">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">期望完成时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="expectedTime" class="datetime-input form-control" placeholder="yyyy-MM-dd HH:mm:ss" type="text" required>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">任务来源:</label>
<div class="col-sm-8">
<input name="taskSource" class="form-control" type="text">
</div>
</div>
<!-- <div class="form-group">
<label class="col-sm-3 control-label">任务跳转URL</label>
<div class="col-sm-8">
<input name="taskUrl" class="form-control" type="text">
</div>
</div>-->
</form>
</div>
<div class="row">
<div class="col-sm-offset-5 col-sm-10">
<button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
<button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "system/task"
$("#form-task-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-task-add').serialize());
}
}
function selectUserInfo() {
var url = "/system/user/selectMultiUser";
$.modal.open("选择用户",url,"","",doSubmit);
}
function doSubmit(index, layero){
var body = layer.getChildFrame('body', index);
var iframeWin = layero.find('iframe')[0];
iframeWin.contentWindow.submitHandler(index, layero);
$("#taskDistributeId").val(body.find('#id').val());
$("#transitionPersonName").val(body.find('#userName').val());
layer.close(index);
}
</script>
</body>
</html>

View File

@ -0,0 +1,93 @@
<!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.taskNo}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务标题:</label>
<span class="form-control-static" th:text="${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.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.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.taskContent}">
</span>
</div>
</div>
<h2 class="form-header h2" align="center" >任务分配记录</h2>
<div class=" timeline">
<div class="timeline-item" >
<div class="row" th:each="logs,iterStat:${sysOaTaskDistributes}">
<div class="col-xs-3 date">
<i class="fa fa-tasks"></i>
<small class="text-navy" th:text="${#dates.format(logs.createTime, 'yyyy-MM-dd hh:mm:ss')}"></small>
</div>
<div class="col-xs-7 content">
<p>
<strong>1.任务执行状态:</strong>
<span class="m-b-xs" th:text="${@dict.getLabel('ding_task_status',logs.taskExecuteStatus)}">
</span>
</p>
<p>
<strong>2.任务执行人:</strong>
</p>
<p th:text="${logs.taskExecuteId}">
</p>
<p>
<strong>3.任务反馈:</strong>
</p>
<p class="m-b-xs" th:text="${logs.taskFeedback}">
</p>
</div>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
</body>
</html>

View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改系统任务')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-task-edit" th:object="${sysOaTask}">
<div class="form-group">
<label class="col-sm-3 control-label is-required">任务编号:</label>
<div class="col-sm-8">
<input name="taskNo" th:field="*{taskNo}" class="form-control" type="text" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">任务名称:</label>
<div class="col-sm-8">
<input name="taskName" th:field="*{taskName}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">任务类型:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('sys_task_type')}">
<input type="radio" th:id="${'taskType_' + dict.dictCode}" name="taskType" th:value="${dict.dictValue}" th:field="*{taskType}">
<label th:for="${'taskType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">紧急程度:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('sys_oa_task_priority')}">
<input type="radio" th:id="${'taskType_' + dict.dictCode}" name="priority" th:value="${dict.dictValue}" th:checked="${dict.default}">
<label th:for="${'taskType_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">任务内容:</label>
<div class="col-sm-8">
<textarea name="taskContent" class="form-control" rows="7" th:field="*{taskContent}"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">执行人:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="hidden" name="taskDistributeId" id="taskDistributeId" th:field="*{taskDistributeId}">
<input class="form-control" type="text" name="transitionPersonName" onclick="selectUserInfo()" id="transitionPersonName" readonly="true">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">任务状态:</label>
<div class="col-sm-8">
<select name="taskStatus" class="form-control m-b" th:with="type=${@dict.getType('ding_task_status')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{taskStatus}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">任务来源:</label>
<div class="col-sm-8">
<input name="taskSource" th:field="*{taskSource}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/task";
$("#form-task-edit").validate({
focusCleanup: true
});
function selectUserInfo() {
var url = "/system/user/selectMultiUser";
$.modal.open("选择用户",url,"","",doSubmit);
}
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-task-edit').serialize());
}
}
function doSubmit(index, layero){
var body = layer.getChildFrame('body', index);
var iframeWin = layero.find('iframe')[0];
iframeWin.contentWindow.submitHandler(index, layero);
$("#taskDistributeId").val(body.find('#id').val());
$("#transitionPersonName").val(body.find('#userName').val());
layer.close(index);
}
</script>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('处理任务')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-task-edit" th:object="${sysOaTaskDistribute}">
<input name="taskNo" th:field="*{sysOaTask.taskNo}" type="hidden">
<input name="id" th:field="*{id}" type="hidden">
<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="${sysOaTaskDistribute.sysOaTask.taskName}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务状态:</label>
<span class="form-control-static" th:text="${@dict.getLabel('ding_task_status',sysOaTaskDistribute.sysOaTask.taskStatus)}">
</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',sysOaTaskDistribute.sysOaTask.priority)}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label ">任务分配人:</label>
<span class="form-control-static" th:text="${sysOaTaskDistribute.taskDistributeId}">
</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_task_type',sysOaTaskDistribute.sysOaTask.taskType)}">
</span>
</div>
<div class="col-xs-5 col-sm-5 ">
<label class="control-label">任务来源:</label>
<span class="form-control-static" th:text="*{sysOaTask.taskSource}">
</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.taskContent}">
</span>
</div>
</div>
</br>
<h2 class="form-header h2" align="center" >任务反馈</h2>
<div class="form-group">
<label class="col-sm-2 control-label is-required">开始时间:</label>
<div class="col-sm-10">
<input name="taskStartTime" class="datetime-input form-control" placeholder="yyyy-MM-dd HH:mm:ss" th:value="${#dates.format(sysOaTaskDistribute.taskStartTime, 'yyyy-MM-dd hh:mm:ss')}" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label is-required">任务反馈:</label>
<div class="col-sm-10">
<textarea name="taskFeedback" class="form-control" rows="6" required></textarea>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "system/task";
$("#form-task-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/handle", $('#form-task-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,472 @@
<!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.addTab()" shiro:hasPermission="system:task:add">
<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;
}
},
{
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",
removeUrl: prefix + "/remove",
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",
detailUrl: prefix + "/taskDistributedDetail/{id}",
exportUrl: prefix + "/export",
createUrl: prefix + "/add",
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('');
}
}]
});
};
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,82 @@
<!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>
<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="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="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>
</div>
<th:block th:include="include :: footer" />
</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

@ -10,6 +10,24 @@
<input name="userId" type="hidden" th:field="*{userId}" />
<input name="deptId" type="hidden" th:field="*{deptId}" id="treeId"/>
<h4 class="form-header h4">基本信息</h4>
<div class="row" th:if="${user.userType eq '00'}">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label">工号:</label>
<div class="col-sm-8">
<input name="jobnumber" class="form-control" type="text" th:field="*{jobnumber}" readonly >
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">工作地点:</label>
<div class="col-sm-8">
<input name="workPlace" class="form-control" type="text" th:field="*{workPlace}" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
@ -202,7 +220,7 @@
/*用户管理-修改-选择部门树*/
function selectDeptTree() {
var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
var deptId = $.common.isEmpty($("#treeId").val()) ? "1" : $("#treeId").val();
var url = ctx + "system/dept/selectDeptTree/" + deptId;
var options = {
title: '选择部门',

View File

@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('多选用户')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-11 search-collapse">
<form id="role-form">
<div class="select-list">
<ul>
<li>
用户名称:<input type="text" name="userName"/>
</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>
<form class="form-horizontal m" id="form-resign-add">
<div class="col-sm-12 select-table table-striped">
<input id="id" name="id" type="hidden" />
<input id="userName" name="userName" type="hidden" />
<input id="dingUserId" name="dingUserId" type="hidden" />
<input id="email" name="email" type="hidden" />
<table id="bootstrap-table"></table>
</div>
</form>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
$(function() {
var options = {
url: "/system/user/list",
queryParams: queryParams,
sortName: "createTime",
sortOrder: "desc",
modalName: "用户",
showSearch: false,
showRefresh: false,
showToggle: false,
showColumns: false,
clickToSelect: true,
singleSelect:false,
rememberSelected: true,
columns: [{
field: 'state',
checkbox: true
},
{
field: 'userId',
title: '用户ID',
visible: false
},
{
field: 'userName',
title: '用户名称'
},
{
field: 'email',
title: '邮箱'
},
{
field: 'dingUserId',
title: '钉钉ID',
visible: false
}]
};
$.table.init(options);
});
function queryParams(params) {
var search = $.table.queryParams(params);
return search;
}
/* 添加用户-选择用户-提交 */
function submitHandler() {
var rows = $.table.selectFirstColumns();
var id=$.table.selectNColumns(1);
var userName=$.table.selectNColumns(2);
var email=$.table.selectNColumns(3);
var dingUserId=$.table.selectNColumns(4);
if (rows.length == 0) {
$.modal.alertWarning("请至少选择一条记录");
return;
}
$("#id").val(id);
$("#userName").val(userName);
$("#email").val(email);
$("#dingUserId").val(dingUserId);
}
</script>
</body>
</html>

View File

@ -46,6 +46,12 @@
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
用户类型:<select name="userType" th:with="type=${@dict.getType('sys_user_type')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li class="select-time">
<label>创建时间: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
@ -93,6 +99,7 @@
var editFlag = [[${@permission.hasPermi('system:user:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:user:remove')}]];
var resetPwdFlag = [[${@permission.hasPermi('system:user:resetPwd')}]];
var datas = [[${@dict.getType('sys_user_type')}]];
var prefix = ctx + "system/user";
$(function() {
@ -154,6 +161,13 @@
return statusTools(row);
}
},
{
field: 'userType',
title: '用户类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(datas, value);
}
},
{
field: 'createTime',
title: '创建时间',

View File

@ -52,11 +52,9 @@
</dependency>
<!--常用工具类 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<!-- JSON工具类 -->
@ -104,26 +102,22 @@
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.2</version>
</dependency>
<!--aliExcel解析包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<!--阿里云oss-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.9.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
@ -134,14 +128,12 @@
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>1.4</version>
</dependency>
<!-- 第三方授权登录 -->
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
<version>1.15.6</version>
</dependency>
<!-- HttpClient -->
@ -150,23 +142,19 @@
<artifactId>httpclient</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.7.4.ALL</version>
</dependency>
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
</dependency>
</dependencies>

View File

@ -0,0 +1,20 @@
package com.snow.common.annotation;
import java.lang.annotation.*;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/9/30 10:50
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Documented
public @interface FormulaChinese {
/**
* 计算汉化名称
* @return
*/
String name() default "";
}

View File

@ -0,0 +1,43 @@
package com.snow.common.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.snow.common.config.SensitiveSerialize;
import com.snow.common.enums.SensitiveTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author qimingjin
* @Title:
* @Description: 对象脱敏注解类
* @date 2021/11/11 15:19
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {
/**
* 脱敏数据类型, 非Customer时, 将忽略 refixNoMaskLen suffixNoMaskLen maskStr
*/
SensitiveTypeEnum type() default SensitiveTypeEnum.CUSTOMER;
/**
* 前置不需要打码的长度
*/
int prefixNoMaskLen() default 0;
/**
* 后置不需要打码的长度
*/
int suffixNoMaskLen() default 0;
/**
* 用什么打码
*/
String maskStr() default "*";
}

View File

@ -1,7 +1,8 @@
package com.snow.common.annotation;
import com.snow.common.enums.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.snow.common.enums.DingTalkLogType;
import com.snow.common.enums.DingTalkSyncType;
import com.snow.common.enums.SyncLogType;
import java.lang.annotation.*;
@ -17,10 +18,10 @@ public @interface SyncLog
{
/**
* 模块描述
* 日志类型
*/
public DingTalkListenerType dingTalkListenerType();
public DingTalkLogType dingTalkLogType();
/**

View File

@ -0,0 +1,94 @@
package com.snow.common.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.snow.common.annotation.Sensitive;
import com.snow.common.enums.SensitiveTypeEnum;
import com.snow.common.utils.DesensitizedUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/11/11 15:16
*/
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveTypeEnum type;
private Integer prefixNoMaskLen;
private Integer suffixNoMaskLen;
private String maskStr;
@Override
public void serialize(final String origin, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider) throws IOException {
switch (type) {
case CHINESE_NAME:
jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));
break;
case ID_CARD:
jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));
break;
case FIXED_PHONE:
jsonGenerator.writeString(DesensitizedUtils.fixedPhone(origin));
break;
case MOBILE_PHONE:
jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));
break;
case ADDRESS:
jsonGenerator.writeString(DesensitizedUtils.address(origin));
break;
case EMAIL:
jsonGenerator.writeString(DesensitizedUtils.email(origin));
break;
case BANK_CARD:
jsonGenerator.writeString(DesensitizedUtils.bankCard(origin));
break;
case PASSWORD:
jsonGenerator.writeString(DesensitizedUtils.password(origin));
break;
case KEY:
jsonGenerator.writeString(DesensitizedUtils.key(origin));
break;
case CUSTOMER:
jsonGenerator.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));
break;
default:
throw new IllegalArgumentException("unKnow sensitive type enum " + type);
}
}
@Override
public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
final BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
if (sensitive == null) {
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
}
if (sensitive != null) {
return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(),
sensitive.suffixNoMaskLen(), sensitive.maskStr());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}

View File

@ -0,0 +1,24 @@
package com.snow.common.constant;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/11/12 14:26
*/
public class CacheConstants {
/**
* 系统网址域名缓存key
*/
public static final String SYS_DOMAIN="sys_config:sys.website.domain";
/**
* 钉钉企业内部APPkey
*/
public static final String ENTERPRICE_APP_KEY="sys_config:enterprice.app.key";
/**
* 钉钉企业内部ENTERPRICE_APP_SECRET
*/
public static final String ENTERPRICE_APP_SECRET="sys_config:enterprice.app.secret";
}

View File

@ -168,6 +168,12 @@ public class Constants
*/
public static final String Ding_Flow="DingFlow";
/**
* 中文
*/
public static final String ZH_CN="zh_CN";
/**
* 支付宝公钥
*/

View File

@ -37,4 +37,23 @@ public class MessageConstants {
*/
public static final String CUSTOMER_VISIT_LOG_CODE="1411568525448978432";
/**
* 站内信任务创建模板
*/
public static final String INNER_TASK_CREATED_CODE="1415927384573616128";
/**
* 站内信流程完结模板
*/
public static final String INNER_PROCESS_END_CODE="1416370192572882944";
/**
* 站内系统任务待办模板
*/
public static final String INNER_SYS_TODO_TASK="1457582416733544448";
/**
* 系统任务完成模板
*/
public static final String INNER_SYS_TASK_COMPLETE="1457591320074919936";
}

View File

@ -32,6 +32,19 @@ public class SequenceConstants {
*/
public static final String OA_EMAIL_SEQUENCE="OA_YJ";
/**
* 客户
*/
public static final String OA_CUSTOMER_SEQUENCE="OA_KH";
/**
* 任务单
*/
public static final String OA_TASK_SEQUENCE="OA_RW";
/**
* 工号前缀
*/
public static final String OA_SNOW="SNOW";
}

View File

@ -1,12 +1,10 @@
package com.snow.framework.web.domain.common;
package com.snow.common.core.domain;
import com.snow.common.enums.DingTalkMessageType;
import com.snow.common.enums.MessageEventType;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Set;

View File

@ -13,7 +13,12 @@ public enum DingFlowTaskType {
PAUSED("PAUSED", "暂停"),
CANCELED("CANCELED", "取消"),
COMPLETED("COMPLETED", "完成"),
TERMINATED("TERMINATED", "终止");
TERMINATED("TERMINATED", "终止"),
//20211015
PROCESSING("PROCESSING","处理中")
;
private final String code;
private final String info;
@ -35,18 +40,18 @@ public enum DingFlowTaskType {
}
public static DingFlowTaskType getType(String info) {
for (DingFlowTaskType dingFLowOperationType:DingFlowTaskType.values()){
if(dingFLowOperationType.getInfo().equals(info)){
return dingFLowOperationType;
for (DingFlowTaskType dingFlowTaskType:DingFlowTaskType.values()){
if(dingFlowTaskType.getInfo().equals(info)){
return dingFlowTaskType;
}
}
return null;
}
public static DingFlowTaskType getCode(String code) {
for (DingFlowTaskType dingFLowOperationType:DingFlowTaskType.values()){
if(dingFLowOperationType.getCode().equals(code)){
return dingFLowOperationType;
for (DingFlowTaskType dingFlowTaskType:DingFlowTaskType.values()){
if(dingFlowTaskType.getCode().equals(code)){
return dingFlowTaskType;
}
}
return null;

View File

@ -14,10 +14,27 @@ public enum DingTalkListenerType {
DEPARTMENT_DELETED(3,2,"org_dept_remove"),
//*****************************用户相关
USER_CREATE(1,1,"user_add_org"),
USER_DELETE(3,1,"user_leave_org"),
USER_UPDATE(2,1,"user_modify_org"),
//*********************外部联系人
CREATE_EXT_CONTACT_USER(1,3,"create_ext_contact_user"),
UPDATE_EXT_CONTACT_USER(2,3,"update_ext_contact_user"),
DELETE_EXT_CONTACT_USER(3,3,"delete_ext_contact_user"),
EXT_CONTACT_USER_LIST(4,3,"ext_contact_user_list"),
GET_EXT_CONTACT_USER(5,3,"get_ext_contact_user"),
//*******************回调
CALL_BACK_CHECK_URL(1,10, "回调check_url"),
CALL_BACK_REGISTER(1,10, "回调注册"),
@ -28,13 +45,20 @@ public enum DingTalkListenerType {
CALL_BACK_FAILED_RESULT(23,10, "获取回调失败结果"),
//*****************待办
WORK_RECODE_CREATE(1,20, "创建待办"),
GET_WORK_RECORD_USER(2,20,"获取用户待办"),
WORK_RECORD_UPDATE(3,20,"更新待办"),
WORK_RECORD_DELETE(4,20,"删除待办"),
UPDATE_TODO_TASK_EXECUTOR_STATUS(7,20,"更新任务执行状态"),
WORK_RECODE_OLD_CREATE(8,20, "创建待办(old)"),
/**
* 审批任务开始结束转交
*/
@ -46,6 +70,9 @@ public enum DingTalkListenerType {
*/
BPMS_INSTANCE_CHANGE(6,20,"bpms_instance_change"),
/**
* 发送钉钉工作通知
*/
ASYNCSEND_V2(10,20,"发送钉钉消息"),
@ -53,7 +80,11 @@ public enum DingTalkListenerType {
BLACKBOARD_UPDATE(2,30,"公告更新"),
BLACKBOARD_DELETE(3,30,"公告删除")
BLACKBOARD_DELETE(3,30,"公告删除"),
GET_TOKEN(1,40,"获取DingTalkToken"),
GET_TOKEN_V2(2,40,"获取DingTalkTokenV2")
;

View File

@ -0,0 +1,130 @@
package com.snow.common.enums;
/**
* @author qimingjin
* @Title: 钉钉日志类型
* @Description:
* @date 2020/9/18 10:18
*/
public enum DingTalkLogType {
DEPARTMENT_CREATE(1, 1,"新建部门"),
DEPARTMENT_UPDATE(1, 2,"更新部门"),
DEPARTMENT_DELETED(1,3,"删除部门"),
DEPARTMENT_QUERY(1,4,"查询"),
//*****************************用户相关
USER_CREATE(2,1,"新增用户"),
USER_DELETE(2,3,"删除(离职)用户"),
USER_UPDATE(2,2,"更新用户"),
//*********************外部联系人
CREATE_EXT_CONTACT_USER(3,1,"新增外部联系人"),
UPDATE_EXT_CONTACT_USER(3,2,"更新外部联系人"),
DELETE_EXT_CONTACT_USER(3,3,"删除外部联系人"),
EXT_CONTACT_USER_LIST(3,4,"获取外部联系人列表"),
GET_EXT_CONTACT_USER(3,4,"获取外部联系人详情"),
//*******************回调
CALL_BACK_CHECK_URL(4,6, "回调check_url"),
CALL_BACK_REGISTER(4,1, "回调注册"),
CALL_BACK_UPDATE(4,2, "回调更新"),
CALL_BACK_DELETE(4,3, "回调删除"),
CALL_BACK_FAILED_RESULT(4,4, "获取回调失败结果"),
//*****************待办
WORK_RECODE_CREATE(5,1, "创建待办"),
GET_WORK_RECORD_USER(5,4,"获取用户待办"),
WORK_RECORD_UPDATE(5,2,"更新待办"),
WORK_RECORD_DELETE(5,3,"删除待办"),
UPDATE_TODO_TASK_EXECUTOR_STATUS(5,2,"更新任务执行状态"),
/**
* 发送钉钉工作通知
*/
ASYNCSEND_V2(6,5,"发送钉钉消息"),
/**
* 公告
*/
BLACKBOARD_CREATE(7,1,"公告创建"),
BLACKBOARD_UPDATE(7,2,"公告更新"),
BLACKBOARD_DELETE(7,3,"公告删除"),
/**
* token
*/
GET_TOKEN(8,4,"获取DingTalkToken"),
GET_TOKEN_V2(8,4,"获取DingTalkTokenV2")
;
//模块
private final Integer moduleType;
/**
* 操作类型 1--新增 2--更新 3--删除 4- 查询 5--发送消息
*/
private final Integer businessType;
/**
* 标题
*/
private final String title;
DingTalkLogType(Integer moduleType, Integer businessType, String title)
{
this.moduleType = moduleType;
this.businessType = businessType;
this.title=title;
}
public Integer getModuleType()
{
return moduleType;
}
public String getTitle()
{
return title;
}
public Integer getBusinessType() {
return businessType;
}
public static DingTalkLogType getType(String title) {
for (DingTalkLogType dingTalkListenerType: DingTalkLogType.values()){
if(dingTalkListenerType.getTitle().equals(title)){
return dingTalkListenerType;
}
}
return null;
}
}

View File

@ -8,7 +8,8 @@ package com.snow.common.enums;
*/
public enum DingTalkMessageType {
TEXT(1, "text"),
LINK(2, "link");
LINK(2, "link"),
MARKDOWN(3,"markdown");
private final Integer code;
private final String info;

View File

@ -16,8 +16,8 @@ public enum FinanceTradeType {
WX_SINGLE_RED_PACKETS(7, "微信红包(单发)"),
WX_RED_PACKETS_REFUND(8, "微信红包-退款"),
SCANNER_QR_CODE_PAYMENT(9, "扫二维码付款"),
QR_CODE_PAYMENT(10, "二维码收款");
QR_CODE_PAYMENT(10, "二维码收款"),
GROUP_COLLECTION(11, "群收款");
private final Integer code;
private final String info;

View File

@ -9,6 +9,10 @@ package com.snow.common.enums;
public enum MessageEventType {
TASK_TODO("TASK_TODO", "任务待办"),
INNER_TASK_TODO("INNER_TASK_TODO", "站内信任务待办"),
INNER_PROCESS_END("INNER_PROCESS_END", "站内信流程完结"),
TASK_FINISH("TASK_FINISH", "任务完成"),
SEND_EMAIL("SEND_EMAIL", "发送邮件"),
@ -18,6 +22,10 @@ public enum MessageEventType {
SEND_VISIT_LOG("SEND_VISIT_LOG", "发送拜访日志"),
REGISTER_ACCOUNT_SUCCESS("REGISTER_ACCOUNT_SUCCESS", "成功注册账户"),
INNER_SYS_TODO_TASK("INNER_SYS_TODO_TASK", "站内信系统任务待办"),
INNER_SYS_TASK_COMPLETE("INNER_SYS_TASK_COMPLETE", "站内信系统任务待办"),
;

View File

@ -0,0 +1,33 @@
package com.snow.common.enums;
/**
* @author qimingjin
* @Title: 系统通知类型
* @Description:
* @date 2021/6/11 14:10
*/
public enum NoticeType {
NOTICE_TYPE("1", "系统公告"),
NOTIFY_TYPE("2", "系统通知"),
SYS_BANNER("2", "Banner")
;
private final String code;
private final String info;
NoticeType(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -0,0 +1,51 @@
package com.snow.common.enums;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2021/11/11 15:15
*/
public enum SensitiveTypeEnum {
/**
* 自定义
*/
CUSTOMER,
/**
* 用户名, *, *
*/
CHINESE_NAME,
/**
* 身份证号, 110110********1234
*/
ID_CARD,
/**
* 座机号, ****1234
*/
FIXED_PHONE,
/**
* 手机号, 176****1234
*/
MOBILE_PHONE,
/**
* 地址, 北京********
*/
ADDRESS,
/**
* 电子邮件, s*****o@xx.com
*/
EMAIL,
/**
* 银行卡, 622202************1234
*/
BANK_CARD,
/**
* 密码, 永远是 ******, 与长度无关
*/
PASSWORD,
/**
* 密钥, 永远是 ******, 与长度无关
*/
KEY
}

View File

@ -0,0 +1,30 @@
package com.snow.common.enums;
/**
* 任务状态
*
* @author snow
*/
public enum TaskStatus
{
UN_FINISH("un_finish", "未结束"), FINISH("finish", "结束");
private final String code;
private final String info;
TaskStatus(String code, String info)
{
this.code = code;
this.info = info;
}
public String getCode()
{
return code;
}
public String getInfo()
{
return info;
}
}

View File

@ -0,0 +1,16 @@
package com.snow.common.exception.user;
/**
* 用户账号已被删除
*
* @author snow
*/
public class UserTypeException extends UserException
{
private static final long serialVersionUID = 1L;
public UserTypeException()
{
super("user.type.error", null);
}
}

View File

@ -23,6 +23,8 @@ public class CacheUtils
private static final String SYS_CACHE = "sys-cache";
private static final String SYS_CONFIG = "sys-config";
/**
* 获取SYS_CACHE缓存
*
@ -34,6 +36,16 @@ public class CacheUtils
return get(SYS_CACHE, key);
}
/**
* 获取SYS_Config缓存
*
* @param key
* @return
*/
public static Object getSysConfig(String key)
{
return get(SYS_CONFIG, key);
}
/**
* 获取SYS_CACHE缓存
*
@ -47,6 +59,18 @@ public class CacheUtils
return value != null ? value : defaultValue;
}
/**
* 获取SYS_Config缓存
* @param key 缓存key
* @param defaultValue 默认值
* @return
*/
public static Object getSysConfig(String key, Object defaultValue)
{
Object value = getSysConfig(key);
return value != null ? value : defaultValue;
}
/**
* 写入SYS_CACHE缓存
*

View File

@ -0,0 +1,160 @@
package com.snow.common.utils;
import cn.hutool.core.util.StrUtil;
/**
* @author qimingjin
* @Title: 脱敏utils
* @Description:
* @date 2021/11/11 15:14
*/
public class DesensitizedUtils {
/**
* 对字符串进行脱敏操作
*
* @param origin 原始字符串
* @param prefixNoMaskLen 左侧需要保留几位明文字段
* @param suffixNoMaskLen 右侧需要保留几位明文字段
* @param maskStr 用于遮罩的字符串, '*'
* @return 脱敏后结果
*/
public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
if (origin == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0, n = origin.length(); i < n; i++) {
if (i < prefixNoMaskLen) {
sb.append(origin.charAt(i));
continue;
}
if (i > (n - suffixNoMaskLen - 1)) {
sb.append(origin.charAt(i));
continue;
}
sb.append(maskStr);
}
return sb.toString();
}
/**
* 中文姓名只显示最后一个汉字其他隐藏为星号比如**
*
* @param fullName 姓名
* @return 结果
*/
public static String chineseName(String fullName) {
if (fullName == null) {
return null;
}
return desValue(fullName, 0, 1, "*");
}
/**
* 身份证号显示前六位, 四位其他隐藏共计18位或者15位比如340304*******1234
*
* @param id 身份证号码
* @return 结果
*/
public static String idCardNum(String id) {
return desValue(id, 6, 4, "*");
}
/**
* 固定电话后四位其他隐藏比如 ****1234
*
* @param num 固定电话
* @return 结果
*/
public static String fixedPhone(String num) {
return desValue(num, 0, 4, "*");
}
/**
* 手机号码前三位后四位其他隐藏比如135****6810
*
* @param num 手机号码
* @return 结果
*/
public static String mobilePhone(String num) {
return desValue(num, 3, 4, "*");
}
/**
* 地址只显示到地区不显示详细地址比如北京市海淀区****
*
* @param address 地址
* @return 结果
*/
public static String address(String address) {
return desValue(address, 6, 0, "*");
}
/**
* 电子邮箱 邮箱前缀仅显示第一个字母前缀其他隐藏用星号代替@及后面的地址显示比如d**@126.com
*
* @param email 电子邮箱
* @return 结果
*/
public static String email(String email) {
if (email == null) {
return null;
}
int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
String preEmail = desValue(email.substring(0, index), 1, 0, "*");
return preEmail + email.substring(index);
}
/**
* 银行卡号前六位后四位其他用星号隐藏每位1个星号比如622260**********1234
*
* @param cardNum 银行卡号
* @return 结果
*/
public static String bankCard(String cardNum) {
return desValue(cardNum, 6, 4, "*");
}
/**
* 密码密码的全部字符都用*代替比如******
*
* @param password 密码
* @return 结果
*/
public static String password(String password) {
if (password == null) {
return null;
}
return "******";
}
/**
* 密钥密钥除了最后三位全部都用*代替比如***xdS 脱敏后长度为6如果明文长度不足三位则按实际长度显示剩余位置补*
*
* @param key 密钥
* @return 结果
*/
public static String key(String key) {
if (key == null) {
return null;
}
int viewLength = 6;
StringBuilder tmpKey = new StringBuilder(desValue(key, 0, 3, "*"));
if (tmpKey.length() > viewLength) {
return tmpKey.substring(tmpKey.length() - viewLength);
} else if (tmpKey.length() < viewLength) {
int buffLength = viewLength - tmpKey.length();
for (int i = 0; i < buffLength; i++) {
tmpKey.insert(0, "*");
}
return tmpKey.toString();
} else {
return tmpKey.toString();
}
}
}

View File

@ -22,6 +22,7 @@ public class PatternUtils {
* @param templateBody
* @return
*/
@Deprecated
public static String builderTemplateBody(Map<String,Object> map, String templateBody){
String re = "(?<=\\$\\{).*?(?=\\})";
Pattern p = Pattern.compile(re);

View File

@ -0,0 +1,41 @@
package com.snow.common.utils.formula;
import com.snow.common.annotation.FormulaChinese;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 表达式计算引擎
*/
@Slf4j
public class MathEnv {
/**
* 根据对象获取变量和值
* @param o
* @return
*/
public Map<String, Object> getEnv(Object o) {
Map<String, Object> env = new HashMap<>(30);
Field[] fields = o.getClass().getDeclaredFields();
for (Field f : fields) {
FormulaChinese annotation = f.getAnnotation(FormulaChinese.class);
if (null != annotation) {
String name = annotation.name();
f.setAccessible(true);
Object fieldVal = null;
try {
fieldVal = f.get(o);
} catch (IllegalAccessException e) {
log.info("exception:{}", e);
throw new RuntimeException(e);
}
env.put(name, fieldVal);
}
}
return env;
}
}

View File

@ -0,0 +1,48 @@
package com.snow.common.utils.formula;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.Map;
/**
* 表达式计算引擎
*/
@Slf4j
public class MathFormula {
/**
* 通过对象执行公式
* @param mathformula
* @param o
* @return
*/
public static BigDecimal executeFormula(String mathformula, Object o) {
MathEnv mathEnv = new MathEnv();
Map<String, Object> env = mathEnv.getEnv(o);
return compileAndExecute(mathformula, env);
}
/**
* 通过Map执行公式
* @param mathFormula
* @param env
* @return
*/
private static BigDecimal compileAndExecute(String mathFormula, Map<String, Object> env) {
// 打印计算公式
log.info("**************************************************");
log.info("@@传入的计算公式 => {}", mathFormula);
Expression compiledExp = AviatorEvaluator.compile(mathFormula);
// 打印变量和值
env.entrySet().forEach(e ->log.info("{} => {}", e.getKey(), e.getValue()));
// 打印结果
BigDecimal result = (BigDecimal) compiledExp.execute(env);
log.info("@@根据公式计算结果 => {}", result);
log.info("**************************************************");
return result;
}
}

View File

@ -3,23 +3,15 @@ package com.snow.common.utils.poi;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.snow.common.annotation.Excel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.Future;
/**
* @author qimingjin

View File

@ -36,12 +36,15 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -73,22 +73,17 @@ public class SyncLogAspect
{
// 获得注解
SyncLog controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
if (controllerLog == null) {
return;
}
// 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser();
SysDingtalkSyncLog sysDingtalkSyncLog = new SysDingtalkSyncLog();
if(StringUtils.isNotNull(currentUser)){
sysDingtalkSyncLog.setOperName(currentUser.getUserName());
if (StringUtils.isNotNull(currentUser.getDept())
&& StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
{
if (StringUtils.isNotNull(currentUser.getDept()) && StringUtils.isNotEmpty(currentUser.getDept().getDeptName())) {
sysDingtalkSyncLog.setDeptName(currentUser.getDept().getDeptName());
}
// 请求的地址
String ip = ShiroUtils.getIp();
sysDingtalkSyncLog.setOperIp(ip);
@ -102,15 +97,13 @@ public class SyncLogAspect
// 返回参数
sysDingtalkSyncLog.setJsonResult(StringUtils.substring(JSON.marshal(jsonResult), 0, 2000));
Optional.ofNullable(ServletUtils.getRequest()).ifPresent(t->sysDingtalkSyncLog.setOperUrl(ServletUtils.getRequest().getRequestURI()));
if (e != null)
{
if (e != null) {
if(e instanceof SyncDataException){
sysDingtalkSyncLog.setStatus(BusinessStatus.FAIL.ordinal());
sysDingtalkSyncLog.setOperDingtalkParam(((SyncDataException) e).getRequestParam());
sysDingtalkSyncLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}else if(e instanceof ApiException){
sysDingtalkSyncLog.setStatus(BusinessStatus.FAIL.ordinal());
// sysDingtalkSyncLog.setOperDingtalkParam(((ApiException) e).getErrMsg());
sysDingtalkSyncLog.setErrorMsg(StringUtils.substring(((ApiException) e).getErrMsg(), 0, 2000));
}
else {
@ -149,9 +142,9 @@ public class SyncLogAspect
*/
public void getControllerMethodDescription(SyncLog log, JoinPoint joinPoint, SysDingtalkSyncLog sysDingtalkSyncLog) throws Exception
{
sysDingtalkSyncLog.setTitle(log.dingTalkListenerType().getInfo());
sysDingtalkSyncLog.setModuleType(log.dingTalkListenerType().getType());
sysDingtalkSyncLog.setBusinessType(log.dingTalkListenerType().getCode());
sysDingtalkSyncLog.setTitle(log.dingTalkLogType().getTitle());
sysDingtalkSyncLog.setModuleType(log.dingTalkLogType().getModuleType());
sysDingtalkSyncLog.setBusinessType(log.dingTalkLogType().getBusinessType());
// 设置操作人类别
sysDingtalkSyncLog.setOperatorType(log.dingTalkSyncType().getCode());
sysDingtalkSyncLog.setLogType(log.syncLogTpye().getCode());

Some files were not shown because too many files have changed in this diff Show More