This commit is contained in:
JyuHsin
2026-03-10 10:20:42 +08:00
parent 1b6d2c787e
commit 30a17cb884
67 changed files with 4765 additions and 277 deletions
@@ -230,8 +230,19 @@ public interface Roles {
*/
String GH03 = "428969eb99ff4b76883d83f847ee96a5";
// 党委书记
String secretary = "dc6703af06fa456a9d95c1104e8d7c77";
// 校长
String principal = "0d8665494fb64a38b4f18fc810ff1751";
/**
* 工会组组长
*/
String ghxzzz = "308dfe9096f44a64a67b4714f67dcd96";
/**
* 校提案管理员
*/
String tmanage = "91623fdad36e45ffbf3e5eab42fb5599";
}
@@ -0,0 +1,397 @@
package io.v.nutz.oa;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import io.v.nutz.oa.client.HhuEduOaClient;
import io.v.nutz.oa.enums.HhuEduOaStatusEnum;
import io.v.nutz.oa.pojo.RequestResult;
import io.v.nutz.oa.util.SudySignUtil;
import io.v.nutz.oa.vo.*;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 河海大学OA服务类
*/
@Slf4j
public class HhuEduOaService {
// 签名算法方式
private static final String algorithm = "SHA1";
// 应用APP标识
private static final String appCode = "zhgh";
// 平台分给业务系统的秘钥
private static final String secretKey = "a9985b08-2e1e-4e37-ab19-518b45670133";
// 请求域名地址
public static String domain = "https://mynew-admin.hhu.edu.cn/taskcenter";
// 任务分类代码
public static String taskCategoryCode = "zhgh";
// 实例化
public static HhuEduOaService getInstance() {
return new HhuEduOaService();
}
/**
* 创建代办任务
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param title 任务标题
* @param url 任务的处理url
* @param doneUrl 任务的已办url
*@param processNodeId 流程环节 存进度百分比(0-100)
* @param processNodeName 流程环节名称
* @param participantUserCodes 参与者的代码,由校方数据中心给出,通常为职工号
* @return RequestResult
*/
public RequestResult createTask(String taskBizId, String loginName, String title, String url, String doneUrl, String processNodeId, String processNodeName, List<String> participantUserCodes) {
return this.createTask(taskBizId, loginName, title, null, url, doneUrl, processNodeId, processNodeName, null, null, null, participantUserCodes, null);
}
/**
* 创建代办任务
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param title 任务标题
* @param subTitle 子标题
* @param url 任务的处理url
* @param doneUrl 任务的已办url
* @param processNodeId 流程环节 存进度百分比(0-100)
* @param processNodeName 流程环节名称
* @param participantUserCodes 参与者的代码,由校方数据中心给出,通常为职工号
* @return RequestResult
*/
public RequestResult createTask(String taskBizId, String loginName, String title, String subTitle, String url, String doneUrl, String processNodeId, String processNodeName, List<String> participantUserCodes) {
return this.createTask(taskBizId, loginName, title, subTitle, url, doneUrl, processNodeId, processNodeName, null, null, null, participantUserCodes, null);
}
/**
* 创建代办任务
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param title 任务标题
* @param url 任务的处理url
* @param doneUrl 任务的已办url
* @param processNodeId 流程环节 存进度百分比(0-100)
* @param processNodeName 流程环节名称
* @param applyName 申请人
* @param applyLoginName 申请人工号
* @param applyOrgName 申请人所在部门
* @param participantUserCodes 参与者的代码,由校方数据中心给出,通常为职工号
* @return RequestResult
*/
public RequestResult createTask(String taskBizId, String loginName, String title, String url, String doneUrl, String processNodeId, String processNodeName, String applyName, String applyLoginName, String applyOrgName, List<String> participantUserCodes) {
return this.createTask(taskBizId, loginName, title, null, url, doneUrl, processNodeId, processNodeName, applyName, applyLoginName, applyOrgName, participantUserCodes, null);
}
/**
* 创建代办任务
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param title 任务标题
* @param subTitle 任务副标题
* @param url 任务的处理url
* @param doneUrl 任务的已办url
* @param processNodeId 流程环节 存进度百分比(0-100)
* @param processNodeName 流程环节名称
* @param applyName 申请人
* @param applyLoginName 申请人工号
* @param applyOrgName 申请人所在部门
* @param participantUserCodes 参与者的代码,由校方数据中心给出,通常为职工号
* @param parentTask 父级任务信息
* @return RequestResult
*/
public RequestResult createTask(String taskBizId, String loginName, String title, String subTitle, String url, String doneUrl, String processNodeId, String processNodeName, String applyName, String applyLoginName, String applyOrgName,
List<String> participantUserCodes, TaskVO parentTask) {
if(StrUtil.isBlank(taskBizId)) {
throw new RuntimeException("缺少任务的业务id->taskBizId");
}
if(StrUtil.isBlank(loginName)) {
throw new RuntimeException("缺少任务创建者的代码->loginName");
}
if(StrUtil.isBlank(title)) {
throw new RuntimeException("缺少任务标题->title");
}
if(StrUtil.isBlank(url)) {
throw new RuntimeException("缺少任务的处理URL->url");
}
if(StrUtil.isBlank(doneUrl)) {
throw new RuntimeException("缺少任务的已办URL->doneUrl");
}
// if(StrUtil.isBlank(processNodeName)) {
// throw new RuntimeException("缺少任务的流程环节名称->processNodeName");
// }
if(!ArrayUtil.isAllNotEmpty(participantUserCodes)) {
throw new RuntimeException("缺少任务的参与者代码->participantUserCodes");
}
// if(participantUserCodes.contains(loginName)) {
// throw new RuntimeException("发起人不能是参与审批人");
// }
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
// 创建任务参数
TaskVO taskVO = getCreateTaskVo(taskBizId, loginName, title, subTitle, url, doneUrl, processNodeName, applyName, applyLoginName, applyOrgName, participantUserCodes, parentTask);
// taskVO.setCreateName("印天宇");
// CreaterVO creater = new CreaterVO();
// creater.setName(taskVO.getCreateName());
// creater.setLoginName(taskVO.getCreatorId());
// taskVO.setCreater(creater);
taskVO.setProcessNodeId(processNodeId);
String createTaskUrl = domain+"/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/category/"+taskCategoryCode+".rst";
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(createTaskUrl, JSONObject.toJSONString(taskVO), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("创建待办任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 创建任务并完成
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param title 任务标题
* @param subTitle 任务副标题
* @param url 任务的处理url
* @param participantUserCodes 参与者的代码,由校方数据中心给出,通常为职工号
* @return RequestResult
*/
public RequestResult createTaskAndUserDone(String taskBizId, String loginName, String title, String subTitle, String url, List<String> participantUserCodes) {
if(StrUtil.isBlank(taskBizId)) {
throw new RuntimeException("缺少任务的业务id->taskBizId");
}
if(StrUtil.isBlank(loginName)) {
throw new RuntimeException("缺少任务创建者的代码->loginName");
}
if(StrUtil.isBlank(loginName)) {
throw new RuntimeException("缺少任务创建者的代码->loginName");
}
if(StrUtil.isBlank(title)) {
throw new RuntimeException("缺少任务标题->title");
}
if(StrUtil.isBlank(url)) {
throw new RuntimeException("缺少任务的处理URL->url");
}
if(!ArrayUtil.isAllNotEmpty(participantUserCodes)) {
throw new RuntimeException("缺少任务的参与者代码->participantUserCodes");
}
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
TaskAndDoneAO taskAndDoneAO = getCreateTaskAndDoneAO(taskBizId, loginName, title, subTitle, url, participantUserCodes);
String taskAndDoneUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/"+ appCode+"/task/category/"+ taskCategoryCode+"/done.rst?userId="+loginName;
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(taskAndDoneUrl, JSONObject.toJSONString(taskAndDoneAO), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("创建代办任务并完成任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 更新代办任务属性
* @param taskBizId 其值是业务系统先前调用createTask时的给出的Task.taskBizId
* @param doneUrl 任务的已办url
* @param task 更新的任务信息
* @return RequestResult
*/
public RequestResult updateTask(String taskBizId, String doneUrl, TaskVO task) {
if(task == null) {
task = new TaskVO();
}
task.setTaskBizId(taskBizId);
task.setDoneUrl(doneUrl);
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
String updateTaskUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/"+task.getTaskBizId()+"/category/"+taskCategoryCode+".rst?randomId=" + nonce;
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(updateTaskUrl, JSONObject.toJSONString(task), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("更新任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 更新任务状态
* @param taskBizId 其值是业务系统先前调用createTask时的给出的Task.taskBizId
* @param doneUrl 任务的已办url
* @param state 任务状态:0-未完成 1-已完成 -1-取消
* @return RequestResult
*/
public RequestResult updateTaskState(String taskBizId, String doneUrl, HhuEduOaStatusEnum state) {
TaskVO vo = new TaskVO();
vo.setState(state.getCode());
return updateTask(taskBizId, doneUrl, vo);
}
/**
* 删除任务
* @param taskBizId 其值是业务系统先前调用createTask时的给出的Task.taskBizId
* @return RequestResult
*/
public RequestResult deleteTask(String taskBizId) {
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
String deleteTaskUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/" + appCode + "/task/"+taskBizId+"/delete.rst?cascade=true";
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(deleteTaskUrl, null, getSign(timestamp, nonce), nonce, timestamp, null);
log.info("删除任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 完成任务
* @param taskBizId 其值是业务系统先前调用createTask时的给出的Task.taskBizId
* @return RequestResult
*/
public RequestResult finishTask(String taskBizId) {
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
String finishTaskUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/"+ taskBizId+"/finish.rst";
FinishTaskVO finishTaskVO = new FinishTaskVO();
finishTaskVO.setDoneDate(new Date());
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(finishTaskUrl, JSONObject.toJSONString(finishTaskVO), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("完成任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 为某个指定的用户完成指定的任务
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginName 任务创建者的代码,由校方数据中心给出,通常为职工号
* @param remark 备注,可以存办理的意见等
* @return RequestResult
*/
public RequestResult doneFinishTask(String taskBizId, String loginName, String remark) {
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
String doneFinishTaskUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/"+appCode+"/task/"+ taskBizId+"/user/"+loginName+"/userDone.rst";
UserDoneAO userDoneAO = new UserDoneAO();
userDoneAO.setFinishTask(true);
userDoneAO.setDoneDate(new Date());
userDoneAO.setRemark(remark);
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(doneFinishTaskUrl, JSONObject.toJSONString(userDoneAO), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("为某个指定的用户完成指定的任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
/**
* 追加参与者
* @param taskBizId 任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作
* @param loginNames 职工号
* @return RequestResult
*/
public RequestResult addPartipantsTask(String taskBizId, List<String> loginNames) {
String timestamp=System.currentTimeMillis()+"";
String nonce = IdUtil.randomUUID().toString().replaceAll("-", "");
String addPartipantsUrl = domain + "/_web/_apps/taskcenter/api/v3/taskcenter/app/"+ appCode +"/task/"+taskBizId+"/participant.rst";
ParticipantVO[] participants = new ParticipantVO[loginNames.size()];
for (int i = 0; i < loginNames.size(); i++) {
ParticipantVO participant = new ParticipantVO();
participant.setType(ParticipantVO.TYPE_USER);
participant.setUserCode(loginNames.get(i));
participants[i] = participant;
}
String resutl = HhuEduOaClient.client(appCode, algorithm).doPost(addPartipantsUrl, JSONObject.toJSONString(participants), getSign(timestamp, nonce), nonce, timestamp, null);
log.info("为某个指定的用户完成指定的任务result->{}",resutl);
RequestResult requestResult = JSONObject.parseObject(resutl,RequestResult.class);
return requestResult;
}
private TaskAndDoneAO getCreateTaskAndDoneAO(String taskBizId, String loginName, String title, String subTitle, String url, List<String> participantUserCodes) {
TaskVO task = new TaskVO();
Date date = new Date();
task.setCreatorId(loginName);
task.setDeadLine(date);
task.setUrl(url);
task.setImportance(TaskVO.IMPORTANCE_MIDDLE);
task.setState(TaskVO.STATE_UNDO);
task.setSubTitle(subTitle);
task.setTitle(title);
task.setTaskBizId(taskBizId);
List<ParticipantVO> participantVOS = new ArrayList<>();
for(String participantUserCode : participantUserCodes){
ParticipantVO vo = new ParticipantVO();
vo.setUserCode(participantUserCode);
vo.setType(ParticipantVO.TYPE_USER);
participantVOS.add(vo);
}
task.setParticipants(participantVOS.toArray(new ParticipantVO[participantVOS.size()]));
UserDoneAO userDoneAO = new UserDoneAO();
userDoneAO.setDoneDate(new Date());
userDoneAO.setFinishTask(true);
userDoneAO.setDelegate(false);
TaskAndDoneAO taskAndDoneAO = new TaskAndDoneAO();
taskAndDoneAO.setTaskVO(task);
taskAndDoneAO.setUserDoneAO(userDoneAO);
return taskAndDoneAO;
}
private TaskVO getCreateTaskVo(String taskBizId, String loginName, String title, String subTitle, String url, String doneUrl, String processNodeName, String applyName, String applyLoginName, String applyOrgName,
List<String> participantUserCodes, TaskVO parentTask) {
TaskVO taskVO = new TaskVO();
taskVO.setTaskBizId(taskBizId);
taskVO.setCreatorId(loginName);
taskVO.setTitle(title);
if(StrUtil.isNotBlank(subTitle)) {
taskVO.setSubTitle(subTitle);
}
taskVO.setUrl(url);
taskVO.setDoneUrl(doneUrl);
if(StrUtil.isNotBlank(processNodeName)) {
taskVO.setProcessNodeName(processNodeName);
}
if(StrUtil.isNotBlank(applyName)){
taskVO.setApplyName(applyName);
}
if(StrUtil.isNotBlank(applyLoginName)){
taskVO.setApplyLoginName(applyLoginName);
}
if(StrUtil.isNotBlank(applyOrgName)){
taskVO.setApplyOrgName(applyOrgName);
}
List<ParticipantVO> participantVOS = new ArrayList<>();
for(String participantUserCode : participantUserCodes){
ParticipantVO vo = new ParticipantVO();
vo.setUserCode(participantUserCode);
vo.setType(ParticipantVO.TYPE_USER);
participantVOS.add(vo);
}
taskVO.setParticipants(participantVOS.toArray(new ParticipantVO[participantVOS.size()]));
if(parentTask!=null){
taskVO.setParentTask(parentTask);
}
return taskVO;
}
private String getSign(String timestamp, String nonce) {
return SudySignUtil.buildSign(algorithm,appCode,timestamp,nonce,null,secretKey);
}
public static void main(String[] args) {
String taskId = "20260531-01023-9";
String loginName = "190020250385";
List<String> participantUserCodes = new ArrayList<>();
participantUserCodes.add("190020250385");
HhuEduOaService.getInstance().createTask(taskId,
loginName,
"创建代办任务测试-1",
"http://127.0.0.1:8087/task/create/",
"http://127.0.0.1:8087/task/create/",
"10",
"代办任务测试-1",
"测试人",
loginName,
loginName,
participantUserCodes);
// HhuEduOaService.getInstance().deleteTask(taskId);
// TaskVO taskVO = new TaskVO();
// taskVO.setTitle("1111");
// HhuEduOaService.getInstance().updateTask(taskId, "http://127.0.0.1:8087/task/create/", taskVO);
// HhuEduOaService.getInstance().finishTask(taskId);
// HhuEduOaService.getInstance().doneFinishTask(taskId, loginName, "完成审批");
}
}
@@ -0,0 +1,25 @@
package io.v.nutz.oa;
import io.v.nutz.base.result.Result;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@Ok("json")
@At("/test/oa")
public class OaTestController {
@Inject
private IOaAuditInstanceService oaAuditInstanceService;
@Ok("json")
@At("/do/port")
public Result doPort() {
// OaAuditInstance instance = oaAuditInstanceService.createTask(OaBusinessTypeEnum.PROPOSAL, "3443554665768799765", "装修食堂-测试", "桌椅调整", "3443554665768799765", Arrays.asList("01nsno67kgingqkdh00omahgse"), "http://127.0.0.1:8089/sysadmin", "https://www.google.cn/");
// oaAuditInstanceService.agree("7467bdbc2b76434891826d6ee0c1eb48", "01nsno67kgingqkdh00omahgse", "同意");
return Result.success();
}
}
@@ -0,0 +1,271 @@
package io.v.nutz.oa.client;
import io.v.nutz.oa.util.MyHttpDelete;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class HhuEduOaClient {
// 平台分配的应用标识
private String appCode;
// 签名算法方式
private String algorithm;
public HhuEduOaClient(String appCode, String algorithm) {
this.appCode = appCode;
this.algorithm = algorithm;
}
public static HhuEduOaClient client(String appCode, String algorithm) {
return new HhuEduOaClient(appCode, algorithm);
}
public String doDelete(String url,String json,String signature,String nonce,String timestamp) {
System.out.println(url);
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
// 通过址默认配置创建一个httpClient实例
httpClient = HttpClients.createDefault();
MyHttpDelete httpDelete = new MyHttpDelete(url);
// 设置配置请求参数
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间
.setConnectionRequestTimeout(35000)// 请求超时时间
.setSocketTimeout(60000)// 数据读取超时时间
.build();
// 为httpGet实例设置配置
httpDelete.setConfig(requestConfig);
if(json != null) {
StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpDelete.setEntity(stringEntity);
}
// 设置请求头信息,鉴权
httpDelete.setHeader("sd-appid", appCode);
httpDelete.setHeader("sd-algorithm", algorithm);
httpDelete.setHeader("sd-timestamp", timestamp);
httpDelete.setHeader("sd-nonce", nonce);
httpDelete.setHeader("sd-signature", signature);
// 执行get请求得到返回对象
response = httpClient.execute(httpDelete);
// 通过返回对象获取返回数据
HttpEntity entity = response.getEntity();
// 通过EntityUtils中的toString方法将结果转换为字符串
result = EntityUtils.toString(entity);
System.out.println(result);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public String doGet(String url,String timestamp,String nonce,String signature,String summaryVer,String summary) {
System.out.println(url);
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
// 通过址默认配置创建一个httpClient实例
httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
// 设置请求头信息,鉴权
//httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 设置配置请求参数
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间
.setConnectionRequestTimeout(35000)// 请求超时时间
.setSocketTimeout(60000)// 数据读取超时时间
.build();
// 设置请求头信息,鉴权
httpGet.setHeader("sd-appid", appCode);
httpGet.setHeader("sd-algorithm", algorithm);
httpGet.setHeader("sd-timestamp", timestamp);
httpGet.setHeader("sd-nonce", nonce);
httpGet.setHeader("sd-signature", signature);
if(summaryVer!= null) {
httpGet.setHeader("sd-summary-ver", summaryVer);
httpGet.setHeader("sd-summary", summary);
}
// 为httpGet实例设置配置
httpGet.setConfig(requestConfig);
// 执行get请求得到返回对象
response = httpClient.execute(httpGet);
// 通过返回对象获取返回数据
HttpEntity entity = response.getEntity();
// 通过EntityUtils中的toString方法将结果转换为字符串
result = EntityUtils.toString(entity);
System.out.println(result);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public String doPost(String url, String json, String signature, String nonce,String timestamp,String summary) {
System.out.println(url);
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
// 通过址默认配置创建一个httpClient实例
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
System.out.println(json);
if(json != null) {
StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(stringEntity);
}
// 设置请求头信息,鉴权
httpPost.setHeader("sd-appid", appCode);
httpPost.setHeader("sd-algorithm", algorithm);
httpPost.setHeader("sd-timestamp", timestamp);
httpPost.setHeader("sd-nonce", nonce);
httpPost.setHeader("sd-signature", signature);
if(summary != null){
httpPost.setHeader("sd-summary", summary);
}
// 设置配置请求参数
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间
.setConnectionRequestTimeout(35000)// 请求超时时间
.setSocketTimeout(60000)// 数据读取超时时间
.build();
// 为httpGet实例设置配置
httpPost.setConfig(requestConfig);
// 执行get请求得到返回对象
response = httpClient.execute(httpPost);
// 通过返回对象获取返回数据
HttpEntity entity = response.getEntity();
// 通过EntityUtils中的toString方法将结果转换为字符串
result = EntityUtils.toString(entity);
System.out.println("111="+result);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public String doPut(String url,String json,String signature,String nonce,String timestamp) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try {
httpClient = HttpClients.createDefault(); // 通过址默认配置创建一个httpClient实例
HttpPut httpPut = new HttpPut(url);
System.out.println(json);
StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPut.setEntity(stringEntity);
// 设置请求头信息,鉴权
httpPut.setHeader("sd-appid", appCode);
httpPut.setHeader("sd-algorithm", algorithm);
httpPut.setHeader("sd-timestamp", timestamp);
httpPut.setHeader("sd-nonce", nonce);
httpPut.setHeader("sd-signature", signature);
// 设置配置请求参数
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间
.setConnectionRequestTimeout(35000)// 请求超时时间
.setSocketTimeout(60000)// 数据读取超时时间
.build();
httpPut.setConfig(requestConfig); // 为httpGet实例设置配置
response = httpClient.execute(httpPut);// 执行get请求得到返回对象
HttpEntity entity = response.getEntity();// 通过返回对象获取返回数据
result = EntityUtils.toString(entity);// 通过EntityUtils中的toString方法将结果转换为字符串
System.out.println(result);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != response) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
@@ -0,0 +1,16 @@
package io.v.nutz.oa.constants;
public interface CommonConstants {
public static Integer ZERO = 0;
public static Integer ONE = 1;
public static Integer TWO = 2;
public static Integer THREE = 3;
public static Integer FOUR = 4;
public static Integer FIVE = 5;
public static Integer SIX = 6;
public static Integer SEVEN = 7;
public static Integer EIGHT = 8;
public static Integer NINE = 9;
public static Integer TEN = 10;
}
@@ -0,0 +1,53 @@
package io.v.nutz.oa.controller;
import io.v.nutz.base.result.Result;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.dto.OaAuditInstanceDto;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.List;
@IocBean
@Ok("json")
@At("/oa/audit/instance")
public class OaAuditInstanceController {
@Inject
private IOaAuditInstanceService oaAuditInstanceService;
/**
* 待处理
*/
@Ok("json")
@At("/wait/handle")
public Result waitHandle() {
List<OaAuditInstance> waitHandleList = oaAuditInstanceService.getWaitHandleList(ShiroUtil.getUserId());
return Result.success(waitHandleList);
}
/**
* 已处理
*/
@Ok("json")
@At("/complete/handle")
public Object completeHandle(PageForm pageForm, OaAuditInstanceDto instance) {
instance.setCreateUser(ShiroUtil.getUserId());
return oaAuditInstanceService.completeHandle(pageForm.getPageNumber(), pageForm.getPageSize(), instance);
}
/**
* 我发起的
*/
@Ok("json")
@At("/mine/send")
public Object mineSend(PageForm pageForm, OaAuditInstanceDto instance) {
instance.setCreateUser(ShiroUtil.getUserId());
return oaAuditInstanceService.mineSend(pageForm.getPageNumber(), pageForm.getPageSize(), instance);
}
}
@@ -0,0 +1,13 @@
package io.v.nutz.oa.dto;
import lombok.Data;
import org.nutz.dao.entity.annotation.Comment;
import java.io.Serializable;
@Data
public class OaAuditInstanceDto implements Serializable {
@Comment("创建人ID")
private String createUser;
}
@@ -0,0 +1,43 @@
package io.v.nutz.oa.enums;
public enum HhuEduOaStatusEnum {
STATE_UNDO(0, "未完成"),
STATE_DONE(1, "已完成"),
STATE_SUSPENDED(2, "已挂起"),
STATE_CANCELED(-1, "取消"),
STATE_ARCHIVED(3, "已归档"),
STATE_STOPED(-2, "已终止"),
STATE_DELETED(-3, "已删除");
private Integer code;
public Integer getCode() {
return code;
}
private String name;
public String getName() {
return name;
}
public static HhuEduOaStatusEnum getByCode(Integer code) {
if (code == null) {
return null;
} else {
HhuEduOaStatusEnum[] values = values();
for (HhuEduOaStatusEnum value : values) {
if (value.getCode().equals(code)) {
return value;
}
}
}
return null;
}
HhuEduOaStatusEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
}
@@ -0,0 +1,53 @@
package io.v.nutz.oa.enums;
public enum OaBusinessTypeEnum {
WRITE_PROPOSAL(1, "撰写提案方案附议", "9"),
TUANZHANG_AUDIT_PROPOSAL(2, "团长审批提案", "18"),
PROPOSAL_COMMITTEE_AUDIT(3, "提案委立案审核", "27"),
HOST_ORGANIZER_REPLY_HANDLE(4, "主办单位提案答复", "72"),
HELP_ORGANIZER_REPLY_HANDLE(5, "协办单位提案答复", "81"),
DIVIDE_SCHOOL_LEADERS_AUDIT(6, "分管校领导审批", "90"),
PROPOSAL_FEEDBACK_EVALUATE_AUDIT(7, "提案反馈评价", "100"),
DIRECTOR_EXECUTIVE_COMMITTEE(8, "执委会主任审核", "36"),
PRINCIPAL_SECRETARY_AUDIT(9, "校长、书记审核", "45"),
DIRECTOR_EXECUTIVE_CONFIRM_COMMITTEE(10, "执委会主任确认审核", "54"),
DIRECTOR_CONFIRM_ORGANIZER_REPLY(11, "提案委确认承办审核", "63");
private Integer code;
public Integer getCode() {
return code;
}
private String name;
public String getName() {
return name;
}
private String processNodeId;
public String getProcessNodeId() {
return processNodeId;
}
public static OaBusinessTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
} else {
OaBusinessTypeEnum[] values = values();
for (OaBusinessTypeEnum value : values) {
if (value.getCode().equals(code)) {
return value;
}
}
}
return null;
}
OaBusinessTypeEnum(Integer code, String name, String processNodeId) {
this.code = code;
this.name = name;
this.processNodeId = processNodeId;
}
}
@@ -0,0 +1,42 @@
package io.v.nutz.oa.enums;
public enum OaStatusEnum {
// 状态: 0.未提交 1.审批中 2.审批完成 3.审批驳回 4.审批撤回
NO_AUDIT(0, "未提交"),
AUDITING(1, "审批中"),
AUDIT_PASS(2, "审批完成"),
REJECT(3, "审批驳回"),
CANCEL(4, "审批撤回");
private Integer code;
public Integer getCode() {
return code;
}
private String name;
public String getName() {
return name;
}
public static OaStatusEnum getByCode(Integer code) {
if (code == null) {
return null;
} else {
OaStatusEnum[] values = values();
for (OaStatusEnum value : values) {
if (value.getCode().equals(code)) {
return value;
}
}
}
return null;
}
OaStatusEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
}
@@ -0,0 +1,104 @@
package io.v.nutz.oa.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.nutz.dao.entity.annotation.*;
import java.io.Serializable;
import java.util.Date;
@Data
@Comment("审批实例流程")
@Table(value = "oa_audit_instance")
public class OaAuditInstance implements Serializable {
@Name
@Comment("主键ID")
@Column(value = "id")
@Prev(els = {@EL("uuid()")})
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Comment("业务ID")
@Column(value = "business_id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String businessId;
@Comment("业务类型: 1.代表提案")
@Column(value = "business_type")
@ColDefine(type = ColType.INT)
private Integer businessType;
@Comment("流程名称")
@Column(value = "process_name")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String processName;
@Comment("实例标题")
@Column(value = "title")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String title;
@Comment("子标题")
@Column(value = "sub_title")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String subTitle;
@Comment("业务实例ID")
@Column(value = "business_task_id")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String businessTaskId;
@Comment("业务实例ID")
@Column(value = "instance_task_id")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String instanceTaskId ;
@Comment("创建人ID")
@Column(value = "create_user")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String createUser;
@Comment("创建人")
@Column(value = "create_name")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String createName;
@Comment("第三方职工号")
@Column(value = "create_login_code")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String createLoginCode;
@Comment("状态: 0.未提交 1.审批中 2.审批完成 3.审批驳回 4.审批撤回")
@Column(value = "status")
@ColDefine(type = ColType.INT)
private Integer status;
@Comment("状态备注")
@Column(value = "status_reason")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String statusReason;
@Comment("创建时间")
@Column(value = "create_time")
@ColDefine(type = ColType.TIMESTAMP)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Comment("审批结束时间")
@Column(value = "over_time")
@ColDefine(type = ColType.TIMESTAMP)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date overTime;
@Comment("任务的处理url")
@Column(value = "url")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String url;
@Comment("任务的已办url")
@Column(value = "done_url")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String doneUrl;
}
@@ -0,0 +1,63 @@
package io.v.nutz.oa.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.nutz.dao.entity.annotation.*;
import java.io.Serializable;
import java.util.Date;
@Data
@Comment("审批实例用户")
@Table(value = "oa_instance_user")
public class OaInstanceUser implements Serializable {
@Name
@Comment("主键ID")
@Column(value = "id")
@Prev(els = {@EL("uuid()")})
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Comment("实例ID")
@Column(value = "instance_id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String instanceId;
@Comment("用户ID")
@Column(value = "user_id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String userId;
@Comment("用户名称")
@Column(value = "user_name")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String userName;
@Comment("第三方职工号")
@Column(value = "user_login_code")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String userLoginCode;
@Comment("状态: 0.未提交 1.审批中 2.审批完成 3.审批驳回 4.审批撤回")
@Column(value = "status")
@ColDefine(type = ColType.INT)
private Integer status;
@Comment("状态备注")
@Column(value = "status_reason")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String statusReason;
@Comment("创建时间")
@Column(value = "create_time")
@ColDefine(type = ColType.TIMESTAMP)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Comment("审批结束时间")
@Column(value = "over_time")
@ColDefine(type = ColType.TIMESTAMP)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date overTime;
}
@@ -0,0 +1,38 @@
package io.v.nutz.oa.notify;
import com.alibaba.fastjson.JSONObject;
import io.v.nutz.base.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.Map;
@Slf4j
@IocBean
@Ok("json:full")
@At("/notify/oa/audit")
public class OaAuditNotify {
/**
* 任务处理
*/
@Ok("json")
@At("/handle/task")
public Result handleTask(Map<String, Object> map) {
log.info("收到OA任务处理通知:{}", JSONObject.toJSONString(map));
return Result.success();
}
/**
* 任务已办通知
*/
@Ok("json")
@At("/finish/task")
public Result finishTask(Map<String, Object> map) {
log.info("收到OA任务已办通知:{}", JSONObject.toJSONString(map));
return Result.success();
}
}
@@ -0,0 +1,27 @@
package io.v.nutz.oa.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@NoArgsConstructor
@Accessors(chain=true)
public class RequestResult {
private String errorMsg;
private Result result;
private Integer resultCode;
@Data
@NoArgsConstructor
@Accessors(chain=true)
public class Result {
private Object data;
private Integer total;
}
}
@@ -0,0 +1,106 @@
package io.v.nutz.oa.service;
import io.v.nutz.base.page.Pagination;
import io.v.nutz.base.service.BaseService;
import io.v.nutz.oa.dto.OaAuditInstanceDto;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.enums.OaStatusEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import java.util.List;
public interface IOaAuditInstanceService extends BaseService<OaAuditInstance> {
List<OaAuditInstance> getWaitHandleList(String userId);
OaAuditInstance getByUser(OaBusinessTypeEnum businessTypeEnum, String businessId, String userId);
OaAuditInstance getByUser(OaBusinessTypeEnum businessTypeEnum, String userId);
Pagination completeHandle(Integer pageNumber, Integer pageSize, OaAuditInstanceDto instance);
Pagination mineSend(Integer pageNumber, Integer pageSize, OaAuditInstanceDto instance);
OaAuditInstance getByBusinessType(OaBusinessTypeEnum businessType, String businessId);
List<OaAuditInstance> getByBusinessTypeRunning(OaBusinessTypeEnum businessType);
List<OaAuditInstance> getAllByBusinessType(OaBusinessTypeEnum businessType, String businessId);
/**
* 创建审批代办任务信息
* @param businessType 业务类型 用来区分任务审批
* @param businessId 审批的对应业务数据ID
* @param title 主标题
* @param subTitle 子标题
* @param createUserId 创建任务ID
* @param auditUsers 参与审批人ID
* @param url 任务的处理url
* @param doneUrl 任务的已办URL
* @return OaAuditInstance
*/
OaAuditInstance createTask(OaBusinessTypeEnum businessType, String businessId, String title, String subTitle, String createUserId, List<String> auditUsers, String url, String doneUrl);
/**
* 创建审批代办任务信息
* @param businessType 业务类型 用来区分任务审批
* @param businessId 审批的对应业务数据ID
* @param processName 流程名称
* @param title 主标题
* @param subTitle 子标题
* @param createUserId 创建任务ID
* @param auditUsers 参与审批人ID
* @param url 任务的处理url
* @param doneUrl 任务的已办URL
* @return OaAuditInstance
*/
OaAuditInstance createTask(OaBusinessTypeEnum businessType, String businessId, String processName, String title, String subTitle, String createUserId, List<String> auditUsers, String url, String doneUrl);
/**
* 同意 参与审批者同意
* @param instanceId 实例ID
* @param remark 备注
*/
void agree(String instanceId, String remark);
/**
* 同意 参与审批者同意
* @param instanceId 实例ID
* @param userId 审核用户ID
* @param remark 备注
*/
void agree(String instanceId, String userId, String remark);
/**
* 同意 参与审批者同意
* @param instanceId 实例ID
* @param userId 审核用户ID
* @param remark 备注
* @param isAgreeOne 是否同意一人整个任务通过
*/
void agree(String instanceId, String userId, String remark, Boolean isAgreeOne);
/** 拒绝
*
* @param instanceId 实例ID
* @param userId 审核用户ID
* @param remark 备注
*/
void refuse(String instanceId, String userId, String remark);
/**
* 任务取消/撤回 由任务发起者来取消 整个任务结束
* @param instanceId 任务实例ID
* @param userId 用户ID
*/
void cancel(String instanceId, String userId);
/**
* 更新实例状态
* @param id 任务实例ID
* @param oaStatusEnum 状态
* @param instanceTaskId
*/
void updateInstanceStatus(String id, OaStatusEnum oaStatusEnum, String instanceTaskId);
}
@@ -0,0 +1,27 @@
package io.v.nutz.oa.service;
import io.v.nutz.base.service.BaseService;
import io.v.nutz.oa.enums.OaStatusEnum;
import io.v.nutz.oa.model.OaInstanceUser;
import org.nutz.lang.util.NutMap;
import java.util.List;
public interface IOaInstanceUserService extends BaseService<OaInstanceUser> {
OaInstanceUser getByUserId(String instanceId, String userId);
List<OaInstanceUser> getAuditing(String instanceId);
List<NutMap> getInstanceUser(String instanceId);
void createRecord(String instanceId, List<String> userIds);
void createRecord(String instanceId, List<String> userIds, OaStatusEnum oaStatusEnum);
void updateStatus(String id, OaStatusEnum oaStatusEnum, String statusReason);
void updateStatusByInstanceId(String instanceId, OaStatusEnum oaStatusEnum);
void appendAuditUser(String instanceId, String businessTaskId, List<String> auditUsers);
}
@@ -0,0 +1,315 @@
package io.v.nutz.oa.service.impl;
import cn.hutool.core.date.DateUtil;
import io.v.nutz.base.page.Pagination;
import io.v.nutz.base.service.impl.BaseServiceImpl;
import io.v.nutz.oa.HhuEduOaService;
import io.v.nutz.oa.constants.CommonConstants;
import io.v.nutz.oa.dto.OaAuditInstanceDto;
import io.v.nutz.oa.enums.HhuEduOaStatusEnum;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.enums.OaStatusEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.model.OaInstanceUser;
import io.v.nutz.oa.pojo.RequestResult;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.oa.service.IOaInstanceUserService;
import io.v.nutz.oa.util.BillNoUtil;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
@IocBean(args = {"refer:dao"})
public class OaAuditInstanceServiceImpl extends BaseServiceImpl<OaAuditInstance> implements IOaAuditInstanceService {
@Inject
private PropertiesProxy conf;
@Inject
private SysUserService sysUserService;
@Inject
private IOaInstanceUserService instanceUserService;
public OaAuditInstanceServiceImpl(Dao dao) {
super(dao);
}
@Override
public List<OaAuditInstance> getWaitHandleList(String userId) {
Sql sql = Sqls.create("select * from oa_audit_instance where status = 1" +
" and id in (select instance_id from oa_instance_user where status = 1 and" +
" user_id=@user_id) order by create_time asc");
sql.params().set("user_id", userId);
sql.setCallback(Sqls.callback.records());
this.dao().execute(sql);
return sql.getList(OaAuditInstance.class);
}
@Override
public OaAuditInstance getByUser(OaBusinessTypeEnum businessTypeEnum, String businessId, String userId) {
Sql sql = Sqls.create("select oai.*" +
"from oa_instance_user oiu left join oa_audit_instance oai on oiu.instance_id = oai.id " +
"where oai.business_type=@business_type and oai.business_id=@business_id and oiu.user_id=@user_id" +
" and oai.status=1 order by oai.create_time desc limit 0,1");
sql.params().set("business_type", businessTypeEnum.getCode());
sql.params().set("business_id", businessId);
sql.params().set("user_id", userId);
sql.setCallback(Sqls.callback.record());
this.dao().execute(sql);
return sql.getObject(OaAuditInstance.class);
}
@Override
public OaAuditInstance getByUser(OaBusinessTypeEnum businessTypeEnum, String userId) {
Sql sql = Sqls.create("select oai.*" +
"from oa_instance_user oiu left join oa_audit_instance oai on oiu.instance_id = oai.id " +
"where oai.business_type=@business_type and oiu.user_id=@user_id" +
" and oai.status=1 and oiu.status=1 order by oai.create_time desc limit 0,1");
sql.params().set("business_type", businessTypeEnum.getCode());
sql.params().set("user_id", userId);
sql.setCallback(Sqls.callback.record());
this.dao().execute(sql);
return sql.getObject(OaAuditInstance.class);
}
@Override
public Pagination completeHandle(Integer pageNumber, Integer pageSize, OaAuditInstanceDto instance) {
Sql sql = Sqls.create("select oai.* " +
"from oa_instance_user oiu left join oa_audit_instance oai on oiu.instance_id = oai.id" +
" where oiu.user_id=@user_id and (oiu.status not in (0,1) or oai.status not in(0,1))" +
" order by oiu.create_time desc");
sql.params().set("user_id", instance.getCreateUser());
return listPage(pageNumber, pageSize, sql);
}
@Override
public Pagination mineSend(Integer pageNumber, Integer pageSize, OaAuditInstanceDto instance) {
Sql sql = Sqls.create("select * from oa_audit_instance where create_user=@create_user order by create_time desc");
sql.params().set("create_user", instance.getCreateUser());
return listPage(pageNumber, pageSize, sql);
}
@Override
public List<OaAuditInstance> getByBusinessTypeRunning(OaBusinessTypeEnum businessType) {
Sql sql = Sqls.create("select * from oa_audit_instance where business_type=@business_type " +
"and business_id=@business_id and status=1");
sql.params().set("business_type", businessType.getCode());
sql.setCallback(Sqls.callback.maps());
this.dao().execute(sql);
return sql.getList(OaAuditInstance.class);
}
@Override
public OaAuditInstance getByBusinessType(OaBusinessTypeEnum businessType, String businessId) {
Sql sql = Sqls.create("select * from oa_audit_instance where business_type=@business_type " +
"and business_id=@business_id and status=1 limit 0,1");
sql.params().set("business_type", businessType.getCode());
sql.params().set("business_id", businessId);
sql.setCallback(Sqls.callback.map());
this.dao().execute(sql);
return sql.getObject(OaAuditInstance.class);
}
@Override
public List<OaAuditInstance> getAllByBusinessType(OaBusinessTypeEnum businessType, String businessId) {
Sql sql = Sqls.create("select * from oa_audit_instance where business_type=@business_type " +
"and business_id=@business_id");
sql.params().set("business_type", businessType.getCode());
sql.params().set("business_id", businessId);
sql.setCallback(Sqls.callback.maps());
this.dao().execute(sql);
return sql.getList(OaAuditInstance.class);
}
@Override
public OaAuditInstance createTask(OaBusinessTypeEnum businessType, String businessId, String title, String subTitle, String createUserId, List<String> auditUsers, String url, String doneUrl) {
return this.createTask(businessType, businessId, null, title, subTitle, createUserId, auditUsers, url, doneUrl);
}
@Override
public OaAuditInstance createTask(OaBusinessTypeEnum businessType, String businessId, String processName, String title, String subTitle, String createUserId, List<String> auditUsers, String url, String doneUrl) {
// OaAuditInstance instance = this.getByBusinessType(businessType, businessId);
// if(instance != null) {
//
// // 追加审批用户
// instanceUserService.appendAuditUser(instance.getId(), instance.getBusinessTaskId(), auditUsers);
// this.updateInstanceStatus(instance.getId(), OaStatusEnum.AUDITING, instance.getInstanceTaskId());
// return instance;
// }
//
// instance = new OaAuditInstance();
OaAuditInstance instance = new OaAuditInstance();
instance.setBusinessType(businessType.getCode());
instance.setBusinessId(businessId);
instance.setTitle(title);
instance.setSubTitle(subTitle);
instance.setCreateTime(DateUtil.date());
instance.setStatus(OaStatusEnum.NO_AUDIT.getCode());
instance.setProcessName(processName);
instance.setUrl(url);
instance.setDoneUrl(doneUrl);
// 提交人用户信息
Sys_user submitUser = sysUserService.fetch(createUserId);
if(submitUser == null){
throw new RuntimeException("提交人不存在");
}
instance.setCreateUser(submitUser.getId());
instance.setCreateName(submitUser.getUsername());
instance.setCreateLoginCode(submitUser.getLoginname());
// 业务实例ID
String businessTaskId = BillNoUtil.getBusinessTaskId();
instance.setBusinessTaskId(businessTaskId);
this.insert(instance);
// 任务实例参与审批信息
instanceUserService.createRecord(instance.getId(), auditUsers);
// 生成第三方代办任务实例
this.createHhuEduOa(instance.getId());
return instance;
}
@Override
public void agree(String instanceId, String remark) {
List<OaInstanceUser> oaInstanceUsers = instanceUserService.getAuditing(instanceId);
for(OaInstanceUser user : oaInstanceUsers) {
this.agree(instanceId, user.getUserId(), remark);
}
}
@Override
public void agree(String instanceId, String userId, String remark) {
this.agree(instanceId, userId, remark, false);
}
@Override
public void agree(String instanceId, String userId, String remark, Boolean isAgreeOne) {
OaInstanceUser instanceUser = instanceUserService.getByUserId(instanceId, userId);
if(instanceUser == null) {
throw new RuntimeException("当前用户未参与审批");
}
OaAuditInstance instance = this.fetch(instanceId);
if(instance.getStatus().equals(OaStatusEnum.AUDIT_PASS.getCode()) || instance.getStatus().equals(OaStatusEnum.CANCEL.getCode())) {
throw new RuntimeException("该任务已结束");
}
RequestResult result = HhuEduOaService.getInstance().doneFinishTask(instance.getBusinessTaskId(), instanceUser.getUserLoginCode(), remark);
if(!result.getResultCode().equals(CommonConstants.ZERO)) {
// throw new RuntimeException(result.getErrorMsg());
log.info("调用第三方待办服务异常:{}", result.getErrorMsg());
}
instanceUserService.updateStatus(instanceUser.getId(), OaStatusEnum.AUDIT_PASS, remark);
// 审批中用户
List<OaInstanceUser> auditingUsers = instanceUserService.getAuditing(instance.getId());
if(auditingUsers == null || auditingUsers.size() <= 0) {
this.updateInstanceStatus(instanceId, OaStatusEnum.AUDIT_PASS, instance.getInstanceTaskId());
} else if(isAgreeOne) {
this.updateInstanceStatus(instanceId, OaStatusEnum.AUDIT_PASS, instance.getInstanceTaskId());
}
}
@Override
public void refuse(String instanceId, String userId, String remark) {
OaInstanceUser instanceUser = instanceUserService.getByUserId(instanceId, userId);
if(instanceUser == null) {
throw new RuntimeException("当前用户未参与审批");
}
OaAuditInstance instance = this.fetch(instanceId);
if(instance.getStatus().equals(OaStatusEnum.AUDIT_PASS.getCode()) || instance.getStatus().equals(OaStatusEnum.CANCEL.getCode())) {
throw new RuntimeException("该任务已结束");
}
RequestResult result = HhuEduOaService.getInstance().doneFinishTask(instance.getBusinessTaskId(), instanceUser.getUserLoginCode(), remark);
if(!result.getResultCode().equals(CommonConstants.ZERO)) {
throw new RuntimeException(result.getErrorMsg());
}
instanceUserService.updateStatus(instanceUser.getId(), OaStatusEnum.REJECT, remark);
// 主流程驳回
this.updateInstanceStatus(instanceId, OaStatusEnum.REJECT, instance.getInstanceTaskId());
}
@Override
public void cancel(String instanceId, String userId) {
OaAuditInstance instance = this.fetch(instanceId);
if(instance == null) {
throw new RuntimeException("任务实例不存在");
}
if(instance.getStatus().equals(OaStatusEnum.AUDIT_PASS.getCode()) || instance.getStatus().equals(OaStatusEnum.CANCEL.getCode())) {
throw new RuntimeException("该任务已结束");
}
if(!instance.getCreateUser().equals(userId)) {
throw new RuntimeException("该用户无权限取消/撤回待办任务");
}
RequestResult result = HhuEduOaService.getInstance().updateTaskState(instance.getBusinessTaskId(), "", HhuEduOaStatusEnum.STATE_CANCELED);
if(!result.getResultCode().equals(CommonConstants.ZERO)) {
throw new RuntimeException(result.getErrorMsg());
}
this.updateInstanceStatus(instance.getId(), OaStatusEnum.CANCEL, instance.getInstanceTaskId());
}
@Override
public void updateInstanceStatus(String id, OaStatusEnum oaStatusEnum, String instanceTaskId) {
StringBuilder sqlStr = new StringBuilder("update oa_audit_instance set status=@status, instance_task_id=@instance_task_id");
if(OaStatusEnum.AUDIT_PASS.getCode().equals(oaStatusEnum.getCode())) {
sqlStr.append(", over_time=@over_time");
}
sqlStr.append(" where id=@id");
Sql sql = Sqls.create(sqlStr.toString());
sql.params().set("instance_task_id", instanceTaskId);
sql.params().set("status", oaStatusEnum.getCode());
if(OaStatusEnum.AUDIT_PASS.getCode().equals(oaStatusEnum.getCode())) {
sql.params().set("over_time", DateUtil.date());
}
sql.params().set("id", id);
this.dao().execute(sql);
}
// 生成第三方代办任务实例
private void createHhuEduOa(String id) {
// String serverPort = conf.get("server.port");
OaAuditInstance instance = this.fetch(id);
Sql sql = Sqls.create("select * from oa_instance_user where instance_id = @instance_id");
sql.params().set("instance_id", id);
List<OaInstanceUser> instanceUsers = instanceUserService.listEntity(sql);
List<String> participantUserCodes = Collections.synchronizedList(new ArrayList<String>());
for(OaInstanceUser instanceUser : instanceUsers){
participantUserCodes.add(instanceUser.getUserLoginCode());
}
OaBusinessTypeEnum businessTypeEnum = OaBusinessTypeEnum.getByCode(instance.getBusinessType());
RequestResult result = HhuEduOaService.getInstance().createTask(instance.getBusinessTaskId(),
instance.getCreateLoginCode(),
instance.getTitle(),
instance.getSubTitle(),
instance.getUrl(),
instance.getDoneUrl(),
businessTypeEnum.getProcessNodeId(),
instance.getProcessName(),
participantUserCodes);
Integer resultCode = result.getResultCode();
if(resultCode.equals(CommonConstants.ZERO)){
Object instanceTaskId = result.getResult().getData();
this.updateInstanceStatus(instance.getId(), OaStatusEnum.AUDITING, String.valueOf(instanceTaskId));
instanceUserService.updateStatusByInstanceId(instance.getId(), OaStatusEnum.AUDITING);
} else {
String errorMsg = result.getErrorMsg();
throw new RuntimeException(errorMsg);
}
}
}
@@ -0,0 +1,126 @@
package io.v.nutz.oa.service.impl;
import cn.hutool.core.date.DateUtil;
import io.v.nutz.base.service.impl.BaseServiceImpl;
import io.v.nutz.oa.HhuEduOaService;
import io.v.nutz.oa.enums.OaStatusEnum;
import io.v.nutz.oa.model.OaInstanceUser;
import io.v.nutz.oa.service.IOaInstanceUserService;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysUserService;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@IocBean(args = {"refer:dao"})
public class OaInstanceUserServiceImpl extends BaseServiceImpl<OaInstanceUser> implements IOaInstanceUserService {
@Inject
private SysUserService sysUserService;
public OaInstanceUserServiceImpl(Dao dao) {
super(dao);
}
@Override
public OaInstanceUser getByUserId(String instanceId, String userId) {
Sql sql = Sqls.create("select * from oa_instance_user where user_id =@user_id and instance_id=@instance_id limit 0,1");
sql.params().set("user_id", userId);
sql.params().set("instance_id", instanceId);
sql.setCallback(Sqls.callback.map());
this.dao().execute(sql);
return sql.getObject(OaInstanceUser.class);
}
@Override
public List<OaInstanceUser> getAuditing(String instanceId) {
Sql sql = Sqls.create("select * from oa_instance_user where instance_id =@instance_id and status=1");
sql.params().set("instance_id", instanceId);
sql.setCallback(Sqls.callback.records());
this.dao().execute(sql);
return sql.getList(OaInstanceUser.class);
}
@Override
public List<NutMap> getInstanceUser(String instanceId) {
Sql sql = Sqls.create("select * from oa_instance_user where instance_id =@instance_id");
sql.params().set("instance_id", instanceId);
sql.setCallback(Sqls.callback.maps());
this.dao().execute(sql);
return sql.getList(NutMap.class);
}
@Override
public void createRecord(String instanceId, List<String> userIds) {
this.createRecord(instanceId, userIds, OaStatusEnum.NO_AUDIT);
}
@Override
public void createRecord(String instanceId, List<String> userIds, OaStatusEnum statusEnum) {
if(userIds==null || userIds.isEmpty()){
throw new RuntimeException("缺少参与审批人");
}
List<OaInstanceUser> instanceUsers = new ArrayList<>();
for(String userId : userIds) {
Sys_user sys_user = sysUserService.fetch(userId);
OaInstanceUser instanceUser = new OaInstanceUser();
instanceUser.setInstanceId(instanceId);
instanceUser.setUserId(sys_user.getId());
instanceUser.setUserName(sys_user.getUsername());
instanceUser.setUserLoginCode(sys_user.getLoginname());
instanceUser.setCreateTime(DateUtil.date());
instanceUser.setStatus(statusEnum.getCode());
instanceUsers.add(instanceUser);
}
this.insert(instanceUsers);
}
@Override
public void updateStatus(String id, OaStatusEnum oaStatusEnum, String statusReason) {
Sql sql = Sqls.create("update oa_instance_user set status=@status, over_time=@over_time, status_reason=@status_reason where id=@id");
sql.params().set("status", oaStatusEnum.getCode());
sql.params().set("over_time", DateUtil.date());
sql.params().set("status_reason", statusReason);
sql.params().set("id", id);
this.dao().execute(sql);
}
@Override
public void updateStatusByInstanceId(String instanceId, OaStatusEnum oaStatusEnum) {
Sql sql = Sqls.create("update oa_instance_user set status=@status where instance_id=@instance_id");
sql.params().set("status", oaStatusEnum.getCode());
sql.params().set("instance_id", instanceId);
this.dao().execute(sql);
}
@Override
public void appendAuditUser(String instanceId, String businessTaskId, List<String> auditUsers) {
try {
List<NutMap> instanceUsers = this.getInstanceUser(instanceId);
List<String> userIds = instanceUsers.stream().map(item -> {
return item.getString("user_id");
}).collect(Collectors.toList());
List<String> addUser = auditUsers.stream().filter(item -> !userIds.contains(item)).collect(Collectors.toList());
this.createRecord(instanceId, addUser, OaStatusEnum.AUDITING);
Sql userSql = Sqls.create("select * from sys_user where id in (@userIds)");
userSql.params().set("userIds", addUser);
userSql.setCallback(Sqls.callback.maps());
sysUserService.dao().execute(userSql);
List<NutMap> addSysUsers = userSql.getList(NutMap.class);
List<String> loginNames = addSysUsers.stream().map(item -> item.getString("loginname")).collect(Collectors.toList());
HhuEduOaService.getInstance().addPartipantsTask(businessTaskId, loginNames);
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
}
@@ -0,0 +1,20 @@
package io.v.nutz.oa.util;
import cn.hutool.core.date.DateUtil;
import java.util.Random;
public class BillNoUtil {
public static String getBusinessTaskId() {
StringBuilder str = new StringBuilder();
str.append(DateUtil.format(DateUtil.date(), "yyyyMMdd"));
str.append("-");
str.append(DateUtil.format(DateUtil.date(), "HHmmss"));
Random random = new Random();
// 生成一个10以内的随机数(包含0,但不包含10)
int randomNumber = random.nextInt(10);
str.append("-" + randomNumber);
return str.toString();
}
}
@@ -0,0 +1,24 @@
package io.v.nutz.oa.util;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import java.net.URI;
public class MyHttpDelete extends HttpEntityEnclosingRequestBase {
public static final String METHOD_NAME = "DELETE";
@Override
public String getMethod() {
return METHOD_NAME;
}
public MyHttpDelete(final String uri) {
super();
setURI(URI.create(uri));
}
public MyHttpDelete(final URI uri) {
super();
setURI(uri);
}
public MyHttpDelete() {
super();
}
}
@@ -0,0 +1,10 @@
package io.v.nutz.oa.util;
/**
* 字符串工具类
*/
public class StringUtil {
public static boolean isEmpty(String string) {
return string == null || string.length() == 0 || string.trim().equals("");
}
}
@@ -0,0 +1,222 @@
package io.v.nutz.oa.util;
import org.apache.commons.codec.binary.Hex;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 对外开放签名算法工具类
* @author xhmeng
*/
public class SudySignUtil {
/**
* 签名算法类型sha1
*/
public static final String ALGORITHM_SHA1 = "SHA1";
/**
* 签名算法类型sha-256
*/
public static final String ALGORITHM_SHA256 = "SHA-256";
/**
* 签名算法类型MD5
*/
public static final String ALGORITHM_MD5 = "MD5";
/**
* 签名算法类型HMAC-SHA256
*/
public static final String ALGORITHM_HMACSHA256= "HMAC-SHA256";
/**
* 支持的签名算法
*/
private static final List<String> allowedAlgorithms = new ArrayList<>();
static {
allowedAlgorithms.add(ALGORITHM_SHA1);
allowedAlgorithms.add(ALGORITHM_SHA256);
allowedAlgorithms.add(ALGORITHM_MD5);
allowedAlgorithms.add(ALGORITHM_HMACSHA256);
}
/**
* 生成签名
* @param algorithm 签名算法。SHA1,MD5,SHA-256,HMAC-SHA256
* @param appId 应用标识,此标识是提前分配给调用系统的
* @param timestamp 时间戳。长整数,是UNIX时间的毫秒数,即产生签名时的时间距1970年1月1日零时的毫秒数的十进制字符串。
* 此时间戳代表了签名的时效性,如果此时间与当前时间差大于某个值(建议不超过20分钟)时,系统认为此签名已经失效
* @param nonce 随机数。用于参与签名运算
* @param summary 摘要,业务接口增加字段的hash值。参与签名,进一步签名的参数值如extraText=“loginName=0810035&userId=2”,
* 需要hash后传输,业务系统在校验sign的基础上进一步校验此值。hex(hash(extraText))后的内容,
* 其中hash算法根据摘要版本使用对应的算法(如sha1、md5、sha-256等)。
* @param secretKey 平台分配给业务系统的私钥
* @return
*/
public static String buildSign(String algorithm,String appId,String timestamp,String nonce,String summary,String secretKey) {
if(StringUtil.isEmpty(algorithm) || StringUtil.isEmpty(appId)
||StringUtil.isEmpty(timestamp)
||StringUtil.isEmpty(nonce)) {
throw new RuntimeException("Sign parameters not allow null!");
}
if(!allowedAlgorithms.contains(algorithm)) {
throw new RuntimeException("UnSupport algorithm type!");
}
StringBuilder sb = new StringBuilder();
sb.append("sd-algorithm=").append(algorithm);
sb.append("&sd-appid=").append(appId);
sb.append("&sd-nonce=").append(nonce);
if(!StringUtil.isEmpty(summary)) {
sb.append("&sd-summary=").append(summary);
}
sb.append("&sd-timestamp=").append(timestamp);
sb.append("&key=").append(secretKey);
String stringSignTemp = sb.toString();
System.out.println("stringSignTemp:" + stringSignTemp);
System.out.println(stringSignTemp);
//sign
if(algorithm.equals(ALGORITHM_HMACSHA256)) {
try {
return hmac(secretKey,stringSignTemp,"HmacSHA256");
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
try {
return sha(stringSignTemp,algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
/**
* 检查签名是否合法
* @param algorithm 签名算法。SHA1,MD5,SHA-256,HMAC-SHA256
* @param appId 应用标识,此标识是提前分配给调用系统的
* @param timestamp 时间戳。长整数,是UNIX时间的毫秒数,即产生签名时的时间距1970年1月1日零时的毫秒数的十进制字符串。
* 此时间戳代表了签名的时效性,如果此时间与当前时间差大于某个值(建议不超过20分钟)时,系统认为此签名已经失效
* @param nonce 随机数。用于参与签名运算
* @param summary 摘要,业务接口增加字段的hash值。参与签名,进一步签名的参数值如extraText=“loginName=0810035&userId=2”,
* 需要hash后传输,业务系统在校验sign的基础上进一步校验此值。hex(hash(extraText))后的内容,
* 其中hash算法根据摘要版本使用对应的算法(如sha1、md5、sha-256等)。
* @param secretKey 平台分配给业务系统的私钥
* @param sign 需要校验的签名
* @param signInvalidTime 签名有效期 单位分钟
* @return
*/
public static boolean checkSign(String algorithm,String appId,String timestamp,String nonce,String summary,String secretKey,String sign,long signInvalidTime) {
//检查签名时间是否过期
long now = System.currentTimeMillis();
long timesta = Long.parseLong(timestamp);
if((now-timesta)>signInvalidTime*60*1000) {//签名有效时间 默认20分钟
throw new RuntimeException( "签名已失效!");
}
String buildSign = buildSign(algorithm, appId, timestamp, nonce, summary, secretKey);
if(!StringUtil.isEmpty(buildSign) && !StringUtil.isEmpty(sign) && buildSign.equals(sign)) {
return true;
}
return false;
}
/**
* 签名摘要
* @param algorithm hash算法 SHA1,MD5,SHA-256
* @param summaryText 摘要内容
* @return
*/
public static String buildSummary(String algorithm,String summaryText) {
try {
return sha(summaryText,algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 检查摘要签名
* @param algorithm
* @param summaryText
* @param summarySign
* @return
*/
public static boolean checkSummary(String algorithm,String summaryText,String summarySign) {
String sign = buildSummary(algorithm, summaryText);
if(!StringUtil.isEmpty(sign) && !StringUtil.isEmpty(summarySign) && summarySign.equals(sign)) {
return true;
}
return false;
}
/**
* sha
* @param text
* @param signType
* @return
* @throws Exception
*/
private static String sha(String text, String signType) throws Exception{
MessageDigest sha = MessageDigest.getInstance(signType);
byte[] digest = sha.digest(text.getBytes("UTF-8"));
return Hex.encodeHexString(digest).toUpperCase();
}
/**
* hmac
* @param accessSecret
* @param stringToSign
* @param singType
* @return
* @throws Exception
*/
private static String hmac(String accessSecret,String stringToSign,String singType) throws Exception{
javax.crypto.Mac mac = javax.crypto.Mac.getInstance(singType);
mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), singType));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return Hex.encodeHexString(signData).toUpperCase();
}
// public static void main(String[] args) {
// String appId = "xgxt";
// String algorithm= "SHA1";
// String timestamp= System.currentTimeMillis() +"";
// String nonce= "ibuaiVcKdpRxkhJA";
// String summary= "loginName=zhangsan";
// String buildSummary = buildSummary(ALGORITHM_SHA1, summary);
// String key = "49123c3d-0d98-4ef5-8128-bdc5f98b3fbd";
// String sign = buildSign(algorithm,appId,timestamp,nonce,buildSummary,key);
// System.out.println(checkSign(algorithm,appId,timestamp,nonce,buildSummary,key,sign,20));
// }
public static String buildSignature(String securyKey, String timestamp, String openId, String nonce) throws Exception {
List<String> sParamList = new ArrayList<String>();
sParamList.add(securyKey);
sParamList.add(timestamp);
sParamList.add(nonce);
sParamList.add(openId);
Collections.sort(sParamList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
StringBuilder signature = new StringBuilder();
for (String sParam : sParamList) {
signature.append(sParam);
}
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(signature.toString().getBytes(Charset.forName("UTF-8")));
return Hex.encodeHexString(md.digest());
}
}
+91
View File
@@ -0,0 +1,91 @@
package io.v.nutz.oa.util;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 工具类
*/
public class Util {
/**
* 解析签名人员
* @param appCode
* @param secret
* @param timestamp
* @param nonce
* @return
* @throws Exception
*/
public static String buildSignuate(String appCode, String secret, String timestamp, String nonce) throws Exception{
if (appCode == null) {
throw new Exception( "appCode!");
}
if (timestamp==null) {
throw new Exception( "timestamp解析为空!");
}
if (nonce == null) {
throw new Exception( "nonce解析为空!");
}
if (secret == null) {
throw new Exception( "私钥错误!");
}
return buildSignature(secret, timestamp, appCode, nonce);
}
public static String buildSignature(String securyKey, String timestamp, String openId, String nonce) throws Exception {
List<String> sParamList = new ArrayList<String>();
sParamList.add(securyKey);
sParamList.add(timestamp);
sParamList.add(nonce);
sParamList.add(openId);
Collections.sort(sParamList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
StringBuilder signature = new StringBuilder();
for (String sParam : sParamList) {
signature.append(sParam);
}
System.out.println("signature:"+signature);
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(signature.toString().getBytes());
byte[] bytes = md.digest();
// System.out.println(toHex(bytes));
// System.out.println(bytesToHexStr(bytes));
return toHex(bytes);
}
private static String toHex(byte[] buffer) {
StringBuilder sb = new StringBuilder(buffer.length * 2);
for (int i = 0; i < buffer.length; i++) {
sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));
sb.append(Character.forDigit(buffer[i] & 15, 16));
}
return sb.toString();
}
private static String bytesToHexStr(byte[] bytes){
if(bytes == null){
return null;
}
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer();
String strInt = "";
for(int i=0;i<bytes.length;i++){
sb2.append(bytes[i]);
strInt = Integer.toHexString(bytes[i]&0xFF);
if(strInt.length()<2){
sb.append(0);
}
sb.append(strInt.toLowerCase());
}
System.out.println(sb2);
return sb.toString();
}
}
@@ -0,0 +1,34 @@
package io.v.nutz.oa.vo;
/**
* 创建者
*/
public class CreaterVO {
private int id;
private String name;
private String loginName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
}
@@ -0,0 +1,22 @@
package io.v.nutz.oa.vo;
import java.util.Date;
/**
* 完成任务
*/
public class FinishTaskVO {
/**
* 完成时间。如果不传递此参数,将使用系统当前时间作为其完成时间
*/
private Date doneDate;
public Date getDoneDate() {
return doneDate;
}
public void setDoneDate(Date doneDate) {
this.doneDate = doneDate;
}
}
@@ -0,0 +1,108 @@
package io.v.nutz.oa.vo;
/**
* 任务的参与者,即责任人.此类为基类,其之类有:用户参与者(即人员),机构参与者(即org),组参与者(即全局组)
*/
public class ParticipantVO{
/** */
public static final int TYPE_USER = 0;
/** */
public static final int TYPE_ORG = 1;
/** */
public static final int TYPE_GROUP = 2;
/** */
private int id;
/**组参与者。type=TYPE_GROUP时有效 */
private String groupName;
/**type=TYPE_ORG时,机构是否递归 */
private boolean recursiveOrg;
/**参与者类型,有TYPE_USER(0),TYPE_ORG(1),TYPE_GROUP(2) */
private int type;
/**人员参与者。type=TYPE_USER时有效。此值必须是校方数据中心公布的唯一人员id,通常是学工号。 */
private String userCode;
/**机构参与者。type=TYPE_ORG有效 。此值必须是校方数据中心公布的唯一组织机构代码。*/
private String orgCode;
/**委托者类型,有DELEGATETYPE_COMMON,DELEGATETYPE_FROM,DELEGATETYPE_TO */
private boolean delegate;
/**委托描述。委托者类型非common时生效 */
private String delegateLoginName;
private String delegateName;
/**是否监督人*/
private boolean monitor;
public boolean isDelegate() {
return delegate;
}
public void setDelegate(boolean delegate) {
this.delegate = delegate;
}
public String getDelegateLoginName() {
return delegateLoginName;
}
public void setDelegateLoginName(String delegateLoginName) {
this.delegateLoginName = delegateLoginName;
}
public String getDelegateName() {
return delegateName;
}
public void setDelegateName(String delegateName) {
this.delegateName = delegateName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public boolean isRecursiveOrg() {
return recursiveOrg;
}
public void setRecursiveOrg(boolean recursiveOrg) {
this.recursiveOrg = recursiveOrg;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getOrgCode() {
return orgCode;
}
public void setOrgCode(String orgCode) {
this.orgCode = orgCode;
}
public boolean isMonitor() {
return monitor;
}
public void setMonitor(boolean monitor) {
this.monitor = monitor;
}
}
@@ -0,0 +1,31 @@
package io.v.nutz.oa.vo;
/**
* 创建并完成对象
*/
public class TaskAndDoneAO {
/**
* 任务对象
*/
private TaskVO taskVO;
/**
* 完成对象
*/
private UserDoneAO userDoneAO;
public TaskVO getTaskVO() {
return taskVO;
}
public void setTaskVO(TaskVO taskVO) {
this.taskVO = taskVO;
}
public UserDoneAO getUserDoneAO() {
return userDoneAO;
}
public void setUserDoneAO(UserDoneAO userDoneAO) {
this.userDoneAO = userDoneAO;
}
}
+469
View File
@@ -0,0 +1,469 @@
package io.v.nutz.oa.vo;
import java.util.Date;
/**
* 任务
*/
public class TaskVO {
/**任务紧急度:低 */
public static final int URGENT_LOW = 0;
/**任务紧急度:中 */
public static final int URGENT_MIDDLE = 1;
/**任务紧急度:高 */
public static final int URGENT_HIGH = 2;
/**任务紧急度:紧急 */
public static final int URGENT_HIGHEST = 3;
/**任务重要程度:低 */
public static final int IMPORTANCE_LOW = 0;
/**任务重要程度:中 */
public static final int IMPORTANCE_MIDDLE = 1;
/**任务重要程度:高 */
public static final int IMPORTANCE_HIGH = 2;
/**任务重要程度:及其重要 */
public static final int IMPORTANCE_HIGHEST = 3;
/**任务状态:未完成 */
public static final int STATE_UNDO = 0;
/**任务状态:已完成 */
public static final int STATE_DONE = 1;
/**任务状态:取消 */
public static final int STATE_CANCELED = -1;
/** */
private int id;
/**附件属性1 */
private String tag1;
/**任务的业务id。此id有app给出,app需要自己保证其唯一性。用于app对任务进行操作 */
private String taskBizId;
/**任务被撤销时的时间 */
private Date cancelDate;
/**重要程度,参见常量IMPORTANCE_LOW,IMPORTANCE_MIDDLE,IMPORTANCE_HIGH,IMPORTANCE_HIGHEST */
private int importance;
/**权重。此为自动计算字段。其值为urgent+importance */
private int weight;
/**任务标题 */
private String title;
/**要求完成时间 */
private Date deadLine;
/**任务的处理url */
private String url;
/**附件属性2 */
private String tag2;
/**附件属性3 */
private String tag3;
/**任务副标题 */
private String subTitle;
/**任务创建时间。app创建task时,如果没有指定createTime,系统将采用当前时间作为createTime */
private Date createTime;
/**任务完成时间 */
private Date doneTime;
/**任务状态.参见常量STATE_UNDO,STATE_DONE,STATE_CANCELED */
private int state;
/**任务紧急程度。参见常量 URGENT_LOW,URGENT_MIDDLE,URGENT_HIGH, URGENT_HIGHEST */
private int urgent;
/**任务来源*/
private String source;
/**
* 任务创建者的代码,由校方数据中心给出,通常为职工号
*/
private String creatorId;
/**
* 创建者
*/
private CreaterVO creater;
/**
* 创建人姓名
*/
private String createName;
/**任务的已办url */
private String doneUrl;
/**
* 父任务taskBizId,父任务和子任务属于同一个app
*/
private String parentTaskBizId;
/**
* parentTask父任务
*/
private TaskVO parentTask;
/**是否是流程跟踪任务 之前版本使用tag1=proc存储 */
private boolean processTrace;
/**是否传阅任务 */
private boolean circulation;
/**
* 排序
*/
private int sort = 50;
/**
* 是否不显示 默认false显示
*/
private boolean notShow = false;
/**
* 流程跟踪我的申请任务当前节点名称
*/
private String processCurrentTask;
/**
* 计划开始时间
*/
private Date planStartTime;
private String handler;
private boolean monitor;
private boolean notDeadSearch;
private String processNodeName;
private String processNodeId;
private boolean backTask;
private boolean backToFirstAct;
private String applyLoginName;
private String applyName;
private Date applyDate;
private String applyOrgName;
public String getParentTaskBizId() {
return parentTaskBizId;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public boolean isNotShow() {
return notShow;
}
public void setNotShow(boolean notShow) {
this.notShow = notShow;
}
public void setParentTaskBizId(String parentTaskBizId) {
this.parentTaskBizId = parentTaskBizId;
}
public String getProcessCurrentTask() {
return processCurrentTask;
}
public void setProcessCurrentTask(String processCurrentTask) {
this.processCurrentTask = processCurrentTask;
}
public String getProcessNodeId() {
return processNodeId;
}
public void setProcessNodeId(String processNodeId) {
this.processNodeId = processNodeId;
}
public String getDoneUrl() {
return doneUrl;
}
public void setDoneUrl(String doneUrl) {
this.doneUrl = doneUrl;
}
public boolean isProcessTrace() {
return processTrace;
}
public void setProcessTrace(boolean processTrace) {
this.processTrace = processTrace;
}
/**
* 参与者
*/
private ParticipantVO[] participants;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTag1() {
return tag1;
}
public void setTag1(String tag1) {
this.tag1 = tag1;
}
public String getTaskBizId() {
return taskBizId;
}
public void setTaskBizId(String taskBizId) {
this.taskBizId = taskBizId;
}
public Date getCancelDate() {
return cancelDate;
}
public void setCancelDate(Date cancelDate) {
this.cancelDate = cancelDate;
}
public int getImportance() {
return importance;
}
public void setImportance(int importance) {
this.importance = importance;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getDeadLine() {
return deadLine;
}
public void setDeadLine(Date deadLine) {
this.deadLine = deadLine;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTag2() {
return tag2;
}
public void setTag2(String tag2) {
this.tag2 = tag2;
}
public String getTag3() {
return tag3;
}
public void setTag3(String tag3) {
this.tag3 = tag3;
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getDoneTime() {
return doneTime;
}
public void setDoneTime(Date doneTime) {
this.doneTime = doneTime;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getUrgent() {
return urgent;
}
public void setUrgent(int urgent) {
this.urgent = urgent;
}
public String getCreatorId() {
return creatorId;
}
public void setCreatorId(String creatorId) {
this.creatorId = creatorId;
}
public CreaterVO getCreater() {
return this.creater;
}
public void setCreater(CreaterVO creater) {
this.creater = creater;
}
public ParticipantVO[] getParticipants() {
return participants;
}
public void setParticipants(ParticipantVO[] participants) {
this.participants = participants;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getCreateName() {
return createName;
}
public void setCreateName(String createName) {
this.createName = createName;
}
public TaskVO getParentTask() {
return parentTask;
}
public void setParentTask(TaskVO parentTask) {
this.parentTask = parentTask;
}
public Date getPlanStartTime() {
return planStartTime;
}
public void setPlanStartTime(Date planStartTime) {
this.planStartTime = planStartTime;
}
public String getHandler() {
return handler;
}
public void setHandler(String handler) {
this.handler = handler;
}
public boolean isMonitor() {
return monitor;
}
public void setMonitor(boolean monitor) {
this.monitor = monitor;
}
public boolean isNotDeadSearch() {
return notDeadSearch;
}
public void setNotDeadSearch(boolean notDeadSearch) {
this.notDeadSearch = notDeadSearch;
}
public String getProcessNodeName() {
return processNodeName;
}
public void setProcessNodeName(String processNodeName) {
this.processNodeName = processNodeName;
}
public boolean isBackTask() {
return backTask;
}
public void setBackTask(boolean backTask) {
this.backTask = backTask;
}
public boolean isCirculation() {
return circulation;
}
public void setCirculation(boolean circulation) {
this.circulation = circulation;
}
public boolean isBackToFirstAct() {
return backToFirstAct;
}
public void setBackToFirstAct(boolean backToFirstAct) {
this.backToFirstAct = backToFirstAct;
}
public String getApplyLoginName() {
return applyLoginName;
}
public void setApplyLoginName(String applyLoginName) {
this.applyLoginName = applyLoginName;
}
public String getApplyName() {
return applyName;
}
public void setApplyName(String applyName) {
this.applyName = applyName;
}
public Date getApplyDate() {
return applyDate;
}
public void setApplyDate(Date applyDate) {
this.applyDate = applyDate;
}
public String getApplyOrgName() {
return applyOrgName;
}
public void setApplyOrgName(String applyOrgName) {
this.applyOrgName = applyOrgName;
}
}
@@ -0,0 +1,86 @@
package io.v.nutz.oa.vo;
import java.util.Date;
/**
* 用户对象
*/
public class UserDoneAO {
/**
* 完成时间。如果不传递此参数,将使用系统当前时间作为其完成时间
*/
private Date doneDate;
/**
* 任务中心的保留参数,不需要传递。
*/
private String extraUserGroup;
/**
* 是否同时finish整个任务。
*/
private boolean finishTask;
/**
* 是否委托
*/
private boolean delegate;
/**
* 委托人LoginName
*/
private String delegateLoginName;
/**
* 委托人Name
*/
private String delegateName;
private String remark;
public boolean isDelegate() {
return delegate;
}
public void setDelegate(boolean delegate) {
this.delegate = delegate;
}
public String getDelegateLoginName() {
return delegateLoginName;
}
public void setDelegateLoginName(String delegateLoginName) {
this.delegateLoginName = delegateLoginName;
}
public String getDelegateName() {
return delegateName;
}
public void setDelegateName(String delegateName) {
this.delegateName = delegateName;
}
public Date getDoneDate() {
return doneDate;
}
public void setDoneDate(Date doneDate) {
this.doneDate = doneDate;
}
public String getExtraUserGroup() {
return extraUserGroup;
}
public void setExtraUserGroup(String extraUserGroup) {
this.extraUserGroup = extraUserGroup;
}
public boolean isFinishTask() {
return finishTask;
}
public void setFinishTask(boolean finishTask) {
this.finishTask = finishTask;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
@@ -3,6 +3,9 @@ package io.v.nutz.proposal.constants;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.utils.DateUtil;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.models.*;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalProcessService;
@@ -12,10 +15,13 @@ import io.v.nutz.service.impl.ViServiceImpl;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.util.ViResource;
import io.v.nutz.web.commons.base.Globals;
import lombok.Getter;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.random.R;
@@ -23,7 +29,9 @@ import org.nutz.lang.util.NutMap;
import org.nutz.trans.Trans;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author: Aaron
@@ -69,6 +77,37 @@ public enum ProposalAuditEnum {
info.setStateCode(newStateCode);
info.setDelegationAuditId(delegationAuditId);
proposalInfoService.updateIgnoreNull(info);
try {
// 生成代办
if (flag == 1) {
Sys_user createUser = dao.fetch(Sys_user.class, info.getCreateUser());
String title = "提案委审核-" + info.getProposalName() + "(" + info.getProposalCode() + "[" + createUser.getUsername() + "]" + ")";
String subTitle = createUser.getUsername() + "邀请您提案审核";
// 参与审核人员
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.WYH_ZR, Roles.tmanage));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if(sysUsers == null || sysUsers.size() <= 0) {
return;
}
List<String> userIds = sysUsers.stream().map(item-> { return item.getString("id"); }).collect(Collectors.toList());
auditInstanceService.createTask(OaBusinessTypeEnum.PROPOSAL_COMMITTEE_AUDIT,
info.getId(),
title,
subTitle,
createUser.getId(),
userIds,
Globals.AppDomain + "/platform/proposal/transact/case/case?proposalId=" + info.getId(),
Globals.AppDomain + "/platform/proposal/transact/case/case");
}
}catch (Exception e) {
e.printStackTrace();
}
});
}
},
@@ -481,6 +520,7 @@ public enum ProposalAuditEnum {
public ViService<ProposalSeconded> proposalSecondedService = ViResource.ioc.get(ViServiceImpl.class, "ProposalSeconded");
public ViService<ProposalFeedback> proposalFeedbackService = ViResource.ioc.get(ViServiceImpl.class, "ProposalFeedback");
public Dao dao = ViResource.dao;
public IOaAuditInstanceService auditInstanceService = ViResource.ioc.getByType(IOaAuditInstanceService.class);
public abstract void audit(NutMap nutMap);
@@ -1,26 +1,39 @@
package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.result.Result;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalInfo;
import io.v.nutz.proposal.models.ProposalSearch;
import io.v.nutz.proposal.services.ProposalCaseCheckService;
import io.v.nutz.proposal.services.ProposalCommonService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.List;
/**
@@ -44,6 +57,12 @@ public class CaseCheckController {
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@Inject
private SysUserService sysUserService;
@At("")
@Ok("beetl:/platform/proposal/transact/caseCheck.html")
@RequiresPermissions("proposal.transact.caseCheck")
@@ -56,6 +75,57 @@ public class CaseCheckController {
return proposalCaseCheckService.pageData(page, search);
}
@Ok("json")
@At("/detail")
public Result detail(String proposalId) {
String sqlStr = """
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.`code` delegationCode,
dbt.dbtname delegationName,
manner.`name` mannerName,
result.`name` resultName,
CONCAT('主办(',zbpu.unitName,'),','协办(',IF(ISNULL(xbpu.unitName),'无',xbpu.unitName) ,')') AS underTakeNames,
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin,
lalevel.`name` laLevelName
FROM
proposal_info info
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
LEFT JOIN sys_dict lalevel ON lalevel.`code` = info.determineTypeCode
LEFT JOIN proposal_reply zbpr ON zbpr.proposalId = info.id
AND zbpr.undertakeType = 1
LEFT JOIN proposal_undertake zbpu ON zbpu.id = zbpr.replyUnitId
LEFT JOIN proposal_reply xbpr ON xbpr.proposalId = info.id
AND xbpr.undertakeType = 2
LEFT JOIN proposal_undertake xbpu ON xbpu.id = xbpr.replyUnitId
where info.id=@proposalId
""";
Sql sql = Sqls.create(sqlStr);
sql.params().set("proposalId", proposalId);
sql.setCallback(Sqls.callback.map());
dao.execute(sql);
return Result.success(sql.getObject(NutMap.class));
}
/**
*
* @param audit
@@ -83,8 +153,87 @@ public class CaseCheckController {
proposalCaseCheckService.audit(conjoinIdList, audit, caseCheckNeedSecondReply, caseCheckNeedSecondAudit);
return null;
// 处理提案委确认承办审核待办
try {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY, io.v.nutz.web.commons.utils.ShiroUtil.getUserId());
if (oaInstance != null) {
auditInstanceService.agree(oaInstance.getId(), io.v.nutz.web.commons.utils.ShiroUtil.getUserId(), "审核通过");
}
// 是否还有审核信息
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
cn.wizzer.framework.base.Result result = (cn.wizzer.framework.base.Result) this.pageData(page, search);
Pagination pagination = (Pagination) result.getData();
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
// 处理全部未审核任务
List<OaAuditInstance> auditInstances = auditInstanceService.getByBusinessTypeRunning(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY);
for(OaAuditInstance auditInstance : auditInstances) {
auditInstanceService.agree(auditInstance.getId(), "审核通过");
}
}
} catch (Exception e) {
e.printStackTrace();
}
// 待办任务处理
try{
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.PROPOSAL_COMMITTEE_AUDIT, audit.getProposalId(), ShiroUtil.getUserId());
ProposalInfo proposalInfo = dao.fetch(ProposalInfo.class, audit.getProposalId());
Sys_user createUser = dao.fetch(Sys_user.class, proposalInfo.getCreateUser());
if(caseCheckNeedSecondReply) {
if(instance != null) {
auditInstanceService.refuse(instance.getId(), ShiroUtil.getUserId(), "分管校领导驳回");
}
// 生成主办单位待办任务
String title = "主办单位提案答复-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() +"[" + createUser.getUsername() + "]" + ")";
String subTitle = "主办单位提案办理答复";
// 主办单位校领导
Sql hostSql = Sqls.create("select oiu.user_id " +
" from oa_instance_user oiu left join oa_audit_instance oai on oai.id = oiu.instance_id" +
" where oai.business_type=@business_type and oai.business_id=@business_id " +
" order by oai.create_time desc limit 0,1");
hostSql.params().set("business_type", OaBusinessTypeEnum.HOST_ORGANIZER_REPLY_HANDLE.getCode());
hostSql.params().set("business_id", proposalInfo.getId());
hostSql.setCallback(Sqls.callback.map());
dao.execute(hostSql);
NutMap hostNutMap = hostSql.getObject(NutMap.class);
auditInstanceService.createTask(OaBusinessTypeEnum.HOST_ORGANIZER_REPLY_HANDLE,
proposalInfo.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(hostNutMap.getString("user_id")),
Globals.AppDomain + "/platform/proposal/transact/reply?underTakeType=1&proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/reply");
} else {
if(instance != null) {
auditInstanceService.agree(instance.getId(), ShiroUtil.getUserId(), "分管校领导同意", true);
}
if(proposalInfo.getStateCode().equals(Integer.valueOf(700))) {
String title = "提案评价-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() + "[" + createUser.getUsername() + "]" + ")";
String subTitle = "提案落实结束评价";
auditInstanceService.createTask(OaBusinessTypeEnum.PROPOSAL_FEEDBACK_EVALUATE_AUDIT,
proposalInfo.getId(),
title,
subTitle,
ShiroUtil.getUserId(),
Arrays.asList(createUser.getId()),
Globals.AppDomain + "/platform/proposal/transact/feedback?proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/feedback");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@At
@@ -2,17 +2,25 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalSearch;
import io.v.nutz.proposal.services.ProposalAuditService;
import io.v.nutz.proposal.services.ProposalCaseService;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
@@ -33,6 +41,8 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: zzxxyy
@@ -58,6 +68,9 @@ public class CaseController {
@Inject
private Dao dao;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/case.html")
@RequiresPermissions("proposal.transact.case")
@@ -116,6 +129,12 @@ public class CaseController {
// return proposalInfoService.listPageMap(page.getPageNumber(), page.getPageSize(), sql);
}
@Ok("json")
@At("/detail")
public Result detail(String id) {
return Result.success(proposalCaseService.detail(id));
}
@At
@Ok("void")
public void doExport(String proposalId, HttpServletResponse response) throws IOException {
@@ -247,7 +266,35 @@ public class CaseController {
}
audit.setFlag(flag == 1);
proposalCaseService.audit(Arrays.asList(proposalIds), resultCode, determineTypeCode, hostUnit, Arrays.asList(helpUnit), typeId, audit, auditType, flag);
return null;
// 代办任务审核
try{
for(String proposalId: proposalIds) {
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.PROPOSAL_COMMITTEE_AUDIT, proposalId, ShiroUtil.getUserId());
if(instance == null) continue;
if(flag == 1) {
auditInstanceService.agree(instance.getId(), ShiroUtil.getUserId(), "同意立案", true);
} else {
auditInstanceService.refuse(instance.getId(), ShiroUtil.getUserId(), "拒绝立案");
}
}
} catch (Exception e) {
e.printStackTrace();
}
// 查看
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
Pagination pagination = proposalCaseService.pageData(page, search);
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
return Result.success(Map.of("sendTask", true));
}
return Result.success(Map.of("sendTask", false));
}
/**
@@ -309,4 +356,45 @@ public class CaseController {
return proposalCaseService.backShow(proposalId);
}
@At("/sendToDoTaskInfo")
@Ok("json")
public Result sendToDoTaskInfo() {
try {
// 获取审核用户信息 角色
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.WYH_ZR));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if (sysUsers == null || sysUsers.size() <= 0) {
return null;
}
List<String> auditUsers = sysUsers.stream().map(item-> { return item.getString("id"); }).collect(Collectors.toList());
for(String auditUserId : auditUsers) {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_COMMITTEE, auditUserId);
if(oaInstance != null) continue;
// 团长生成待办任务
Sys_user createUser = dao.fetch(Sys_user.class, ShiroUtil.getUserId());
String title = "提案审核-执委会审核";
String subTitle = createUser.getUsername() + "邀请您提案审核";
auditInstanceService.createTask(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_COMMITTEE,
createUser.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(auditUserId),
Globals.AppDomain + "/platform/proposal/transact/executorRead",
Globals.AppDomain + "/platform/proposal/transact/executorRead");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error(e.getMessage());
}
return Result.success("已为你发送待办到下一审批节点");
}
}
@@ -2,22 +2,34 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalInfo;
import io.v.nutz.proposal.models.ProposalReply;
import io.v.nutz.proposal.models.ProposalSearch;
import io.v.nutz.proposal.services.ProposalCaseConfirmService;
import io.v.nutz.proposal.services.ProposalCommonService;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.models.Sys_user_role;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -29,6 +41,7 @@ import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author: Aaron
@@ -54,6 +67,12 @@ public class CaseUnitController {
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private SysUserService sysUserService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/caseUnit.html")
@RequiresPermissions("proposal.transact.caseUnit")
@@ -86,9 +105,93 @@ public class CaseUnitController {
audit.setSignId(signId);
}
proposalCaseConfirmService.audit(Arrays.asList(proposalIds), resultCode, determineTypeCode, hostUnit, Arrays.asList(helpUnit), typeId, audit);
// 处理提案委确认承办审核待办
try {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY, ShiroUtil.getUserId());
if (oaInstance != null) {
auditInstanceService.agree(oaInstance.getId(), ShiroUtil.getUserId(), "审核通过");
}
// 是否还有审核信息
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
Result result = (Result) this.pageData(page, search);
Pagination pagination = (Pagination) result.getData();
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
// 处理全部未审核任务
List<OaAuditInstance> auditInstances = auditInstanceService.getByBusinessTypeRunning(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY);
for(OaAuditInstance auditInstance : auditInstances) {
auditInstanceService.agree(auditInstance.getId(), "审核通过");
}
}
} catch (Exception e) {
e.printStackTrace();
}
// 生成待办任务
try{
for(String proposalId : Arrays.asList(proposalIds)) {
ProposalInfo proposalInfo = proposalInfoService.fetch(proposalId);
Sys_user createUser = dao.fetch(Sys_user.class, proposalInfo.getCreateUser());
// 主办单位校领导
List<Record> hostRecords = this.findAdmin(Arrays.asList(hostUnit));
if (hostRecords != null && hostRecords.size() > 0) {
List<String> hostUserIds = hostRecords.stream().map(item-> {return item.getString("id"); }).collect(Collectors.toList());
String title = "主办单位提案答复-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() +"[" + createUser.getUsername() + "]" + ")";
String subTitle = "主办单位提案办理答复";
auditInstanceService.createTask(OaBusinessTypeEnum.HOST_ORGANIZER_REPLY_HANDLE,
proposalId,
title,
subTitle,
createUser.getId(),
hostUserIds,
Globals.AppDomain + "/platform/proposal/transact/reply?underTakeType=1&proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/reply");
}
// 协办单位校领导
List<Record> helpRecords = this.findAdmin(Arrays.asList(helpUnit));
if (helpRecords != null && helpRecords.size() > 0) {
List<String> helpUserIds = helpRecords.stream().map(item-> {return item.getString("id"); }).collect(Collectors.toList());
String title = "协办单位提案答复-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() +"[" + createUser.getUsername() + "]" + ")";
String subTitle = "协办单位提案办理答复";
auditInstanceService.createTask(OaBusinessTypeEnum.HELP_ORGANIZER_REPLY_HANDLE,
proposalId,
title,
subTitle,
createUser.getId(),
helpUserIds,
Globals.AppDomain + "/platform/proposal/transact/reply?underTakeType=0&proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/reply");
}
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 查询负责人或者分管校领导
* @param ids 承办单位id
* @return
*/
private List<Record> findAdmin(List<String> ids) {
Sql sql = Sqls.create("select su.* " +
"from sys_user su left join sys_user_role sur on sur.userId = su.id" +
" where sur.cbdwid in (@cbdwid) and sur.roleId=@roleId");
sql.params().set("cbdwid", ids);
sql.params().set("roleId", Roles.IN_CHARGE_LEADER);
return sysUserService.list(sql);
}
/**
* 撤回
*
@@ -9,6 +9,8 @@ import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalMannerEnum;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.constants.ProposalStateDirectionEnum;
@@ -24,6 +26,8 @@ import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysSignatureService;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
@@ -46,6 +50,7 @@ import org.nutz.mvc.upload.UploadAdaptor;
import org.nutz.trans.Trans;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -55,6 +60,7 @@ import java.util.concurrent.atomic.AtomicReference;
* @description: 撰写提案(系统管理员 、 提案管理员 、 正式代表 、 代表团团长 、 提案委员会主任)
**/
@Slf4j
@At("/platform/proposal/transact/compose")
@Ok("json:full")
@IocBean
@@ -88,6 +94,9 @@ public class ComposeController {
@Inject
private MsgApi msgApi;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/compose.html")
@RequiresPermissions("proposal.transact.compose")
@@ -241,6 +250,23 @@ public class ComposeController {
secondedService.insert(seconded);
Sys_user user = dao.fetch(Sys_user.class, userId);
msgApi.sendMsg(StrUtil.format(inviteSecondedTemplate, proposalCreateUser.getUsername(), proposalInfo.getProposalName()), List.of(user.getLoginname()));
// 生成代办任务
try {
Sys_user createUser = dao.fetch(Sys_user.class, ShiroUtil.getUserId());
String title = "提案附议-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() +"[" + createUser.getUsername() + "]" + ")";
String subTitle = createUser.getUsername() + "邀请您附议";
auditInstanceService.createTask(OaBusinessTypeEnum.WRITE_PROPOSAL,
proposalId,
title,
subTitle,
createUser.getId(),
Arrays.asList(userId),
Globals.AppDomain + "/platform/proposal/transact/seconded?isAudit=false&proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/statistics/mySearch");
} catch (Exception e) {
log.error("撰写提案附议生成代办失败:{}", e.getMessage());
}
}
return null;
}
@@ -2,9 +2,14 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalSearch;
@@ -13,9 +18,14 @@ import io.v.nutz.proposal.services.ProposalExecutorReadConfirmService;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalProcessService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -27,6 +37,9 @@ import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author zxy
@@ -50,6 +63,9 @@ public class ExecutorReadConfirmController {
@Inject
private ProposalExecutorReadConfirmService proposalExecutorReadConfirmService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@Inject
private Dao dao;
@@ -103,7 +119,36 @@ public class ExecutorReadConfirmController {
.addv("determineCode", determineTypeCode);
audit.setOther(Json.toJson(auditOther));
proposalExecutorReadConfirmService.audit(audit, Arrays.asList(proposalIds));
return null;
// 处理代办任务
try {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_CONFIRM_COMMITTEE, ShiroUtil.getUserId());
if (oaInstance != null) {
auditInstanceService.agree(oaInstance.getId(), ShiroUtil.getUserId(), "审核通过");
}
// 是否还有审核信息
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
Result result = (Result) this.pageData(page, search);
Pagination pagination = (Pagination) result.getData();
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
// 处理全部未审核任务
List<OaAuditInstance> auditInstances = auditInstanceService.getByBusinessTypeRunning(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_CONFIRM_COMMITTEE);
for(OaAuditInstance auditInstance : auditInstances) {
auditInstanceService.agree(auditInstance.getId(), "审核通过");
}
return Result.success(Map.of("sendTask", true));
}
}catch (Exception e) {
e.printStackTrace();
}
return Result.success(Map.of("sendTask", false));
}
/**
@@ -119,4 +164,45 @@ public class ExecutorReadConfirmController {
proposalExecutorReadConfirmService.revoke(proposalId);
return Result.success().addMsg("撤回成功!");
}
@At("/sendToDoTaskInfo")
@Ok("json")
public Result sendToDoTaskInfo() {
try {
// 获取审核用户信息 角色
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.WYH_ZR));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if (sysUsers == null || sysUsers.size() <= 0) {
return null;
}
List<String> auditUsers = sysUsers.stream().map(item -> {
return item.getString("id");
}).collect(Collectors.toList());
for (String auditUserId : auditUsers) {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY, auditUserId);
if (oaInstance != null) continue;
// 提案委确认承办单位
Sys_user createUser = dao.fetch(Sys_user.class, ShiroUtil.getUserId());
String title = "提案审核-提案委确认承办单位";
String subTitle = createUser.getUsername() + "邀请您提案审核";
auditInstanceService.createTask(OaBusinessTypeEnum.DIRECTOR_CONFIRM_ORGANIZER_REPLY,
createUser.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(auditUserId),
Globals.AppDomain + "/platform/proposal/transact/caseUnit",
Globals.AppDomain + "/platform/proposal/transact/caseUnit");
}
}catch (Exception e) {
return Result.error(e.getMessage());
}
return Result.success("已为你发送待办到下一审批节点");
}
}
@@ -2,9 +2,14 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalSearch;
@@ -13,8 +18,13 @@ import io.v.nutz.proposal.services.ProposalExecutorReadService;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalProcessService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -26,6 +36,9 @@ import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author zxy
@@ -49,6 +62,9 @@ public class ExecutorReadController {
@Inject
private ProposalExecutorReadService proposalExecutorReadService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@Inject
private Dao dao;
@@ -101,7 +117,37 @@ public class ExecutorReadController {
.addv("determineCode", determineTypeCode);
audit.setOther(Json.toJson(auditOther));
proposalExecutorReadService.audit(audit, Arrays.asList(proposalIds));
return null;
// 处理代办任务
try{
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_COMMITTEE, ShiroUtil.getUserId());
if(oaInstance != null) {
auditInstanceService.agree(oaInstance.getId(), ShiroUtil.getUserId(), "审核通过");
}
// 是否还有审核信息
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
Result result = (Result) this.pageData(page, search);
Pagination pagination = (Pagination) result.getData();
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
// 处理全部未审核任务
List<OaAuditInstance> auditInstances = auditInstanceService.getByBusinessTypeRunning(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_COMMITTEE);
for(OaAuditInstance auditInstance : auditInstances) {
auditInstanceService.agree(auditInstance.getId(), "审核通过");
}
return Result.success(Map.of("sendTask", true));
}
} catch (Exception e) {
e.printStackTrace();
}
return Result.success(Map.of("sendTask", false));
}
/**
@@ -117,4 +163,47 @@ public class ExecutorReadController {
proposalExecutorReadService.revoke(proposalId);
return Result.success().addMsg("撤回成功!");
}
@At("/sendToDoTaskInfo")
@Ok("json")
public Result sendToDoTaskInfo() {
try {
// 获取审核用户信息 角色
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.secretary, Roles.principal));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if (sysUsers == null || sysUsers.size() <= 0) {
return null;
}
List<String> auditUsers = sysUsers.stream().map(item -> {
return item.getString("id");
}).collect(Collectors.toList());
for (String auditUserId : auditUsers) {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.PRINCIPAL_SECRETARY_AUDIT, auditUserId);
if (oaInstance != null) continue;
// 执委会审核生成待办任务
Sys_user createUser = dao.fetch(Sys_user.class, ShiroUtil.getUserId());
String title = "提案审核-校长、书记审核";
String subTitle = createUser.getUsername() + "邀请您提案审核";
auditInstanceService.createTask(OaBusinessTypeEnum.PRINCIPAL_SECRETARY_AUDIT,
createUser.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(auditUserId),
Globals.AppDomain + "/platform/proposal/transact/principalRead",
Globals.AppDomain + "/platform/proposal/transact/principalRead");
}
}catch (Exception e) {
return Result.error(e.getMessage());
}
return Result.success("已为你发送待办到下一审批节点");
}
}
@@ -8,10 +8,14 @@ import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.result.Result;
import io.v.nutz.base.utils.Html2Text;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalAuditEnum;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.constants.ProposalStateDirectionEnum;
@@ -68,6 +72,9 @@ public class FeedbackScoreController {
@Inject("ProposalFeedback")
private ViService<ProposalFeedback> proposalFeedbackService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/feedback.html")
@RequiresPermissions("proposal.transact.feedback")
@@ -138,6 +145,47 @@ public class FeedbackScoreController {
}
@Ok("json")
@At("/detail")
public Result detail(String proposalId) {
Sql sql = Sqls.create("""
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.`code` delegationCode,
dbt.dbtname delegationName,
manner.`name` mannerName,
result.`name` resultName,
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin
FROM
proposal_info info
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
where info.id = @proposalId
""");
sql.params().set("proposalId", proposalId);
sql.setCallback(Sqls.callback.map());
proposalInfoService.dao().execute(sql);
return Result.success(sql.getObject(NutMap.class));
}
@Inject
private SysSignatureService sysSignatureService;
@@ -151,6 +199,15 @@ public class FeedbackScoreController {
}
nutMap.setv("feedback", feedback);
ProposalAuditEnum.FEEDBACK_SCORE.audit(nutMap);
try {
ProposalInfo proposalInfo = proposalInfoService.fetch(feedback.getProposalId());
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.PROPOSAL_FEEDBACK_EVALUATE_AUDIT, proposalInfo.getId(), ShiroUtil.getUserId());
if(instance == null) return null;
auditInstanceService.agree(instance.getId(), ShiroUtil.getUserId(), "已反馈", true);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@@ -5,7 +5,11 @@ import cn.wizzer.framework.base.Result;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.DateUtil;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.constants.ProposalStateDirectionEnum;
import io.v.nutz.proposal.models.ProposalInfo;
@@ -16,8 +20,10 @@ import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalLeaderAuditService;
import io.v.nutz.proposal.services.ProposalProcessService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysSignatureService;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
@@ -35,7 +41,9 @@ import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import org.nutz.trans.Trans;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author: Aaron
@@ -65,7 +73,8 @@ public class LeaderAuditController {
private SysSignatureService sysSignatureService;
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/leaderAudit.html")
@@ -86,6 +95,61 @@ public class LeaderAuditController {
return proposalLeaderAuditService.pageData(page, cnd, search);
}
@Ok("json")
@At("/detail")
public Result detail(String proposalId) {
String sqlStr = """
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.`code` delegationCode,
dbt.dbtname delegationName,
manner.`name` mannerName,
result.`name` resultName,
pr.id AS replyId,
pr.replyUnitId,
pr.replyNumber,
pr.leaderCheckNumber,
pr.replyPersonId,
pr.isReply,
pr.leaderId,
pr.isLeaderAudit,
pu.unitName as underTakeName,
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin,
IF(pr.underTakeType=1,'主办','协办') AS undertakeType,
(SELECT GROUP_CONCAT(DISTINCT ( u.username )) FROM sys_user_role sur LEFT JOIN sys_user u ON u.id = sur.userid WHERE sur.cbdwid = pr.replyUnitId AND sur.roleid = @XLD ) AS underTakeNameUser
FROM
proposal_reply pr
LEFT JOIN proposal_undertake pu on pu.id = pr.replyUnitId\s
LEFT JOIN proposal_info info on info.id = pr.proposalId
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
where pr.underTakeType=1 AND info.id=@proposalId limit 0,1
""";
Sql sql = Sqls.create(sqlStr);
sql.params().set("proposalId", proposalId);
sql.setCallback(Sqls.callback.map());
dao.execute(sql);
return Result.success(sql.getObject(NutMap.class));
}
/**
* 退回
*
@@ -117,6 +181,13 @@ public class LeaderAuditController {
});
});
try{
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIVIDE_SCHOOL_LEADERS_AUDIT, proposalId, ShiroUtil.getUserId());
if(instance == null) return null;
auditInstanceService.refuse(instance.getId(), ShiroUtil.getUserId(), "审核驳回");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@@ -136,6 +207,65 @@ public class LeaderAuditController {
reply.setLeaderSignId(sysSignatureService.insert(new Sys_signature(leaderSign)).getId());
}
proposalLeaderAuditService.audit(reply);
try {
ProposalInfo proposalInfo = proposalInfoService.fetch(reply.getProposalId());
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIVIDE_SCHOOL_LEADERS_AUDIT, reply.getProposalId(), ShiroUtil.getUserId());
if (instance != null) {
auditInstanceService.agree(instance.getId(), ShiroUtil.getUserId(), "审核通过", true);
}
Sys_user createUser = dao.fetch(Sys_user.class, proposalInfo.getCreateUser());
if(proposalInfo.getCaseCheckAuditId() != null && !proposalInfo.getCaseCheckAuditId().isEmpty()) {
// 生成反馈评价待办
String flag = nutMap.getString("flag");
if (flag.equals("true")) {
if(proposalInfo.getStateCode().equals(Integer.valueOf(700))) {
String title = "提案评价-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() + "[" + createUser.getUsername() + "]" + ")";
String subTitle = "提案落实结束评价";
auditInstanceService.createTask(OaBusinessTypeEnum.PROPOSAL_FEEDBACK_EVALUATE_AUDIT,
proposalInfo.getId(),
title,
subTitle,
ShiroUtil.getUserId(),
Arrays.asList(createUser.getId()),
Globals.AppDomain + "/platform/proposal/transact/feedback?proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/feedback");
}
}
}
if((proposalInfo.getStateCode().equals(Integer.valueOf(800)))) {
String flag = nutMap.getString("flag");
if (flag.equals("true")) {
String title = "提案委复核-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() + "[" + createUser.getUsername() + "]" + ")";
String subTitle = createUser.getUsername() + "提案委复核";
// 参与审核人员
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.WYH_ZR, Roles.tmanage));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if (sysUsers == null || sysUsers.size() <= 0) {
return null;
}
List<String> userIds = sysUsers.stream().map(item -> {
return item.getString("id");
}).collect(Collectors.toList());
auditInstanceService.createTask(OaBusinessTypeEnum.PROPOSAL_COMMITTEE_AUDIT,
proposalInfo.getId(),
title,
subTitle,
createUser.getId(),
userIds,
Globals.AppDomain + "/platform/proposal/transact/caseCheck?proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/caseCheck");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@@ -2,6 +2,10 @@ package io.v.nutz.proposal.controller.transact;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.lang.Enum;
import io.v.nutz.oa.constants.CommonConstants;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalAuditEnum;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalReply;
@@ -36,6 +40,9 @@ public class ProposalAuditController {
@Inject
private SysSignatureService sysSignatureService;
@Inject
private IOaAuditInstanceService auditInstanceService;
/**
* 审核
*
@@ -56,6 +63,20 @@ public class ProposalAuditController {
int stateCode = proposalInfoService.fetch(audit.getProposalId()).getStateCode();
ProposalAuditEnum instance = Enum.instance(ProposalAuditEnum.class, stateCode);
instance.audit(nutMap);
// 处理代办任务
try{
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.TUANZHANG_AUDIT_PROPOSAL, audit.getProposalId(), ShiroUtil.getUserId());
if(oaInstance == null) return null;
Integer flag = nutMap.getInt("flag");
if(flag != null && flag.equals(CommonConstants.ONE)) {
auditInstanceService.agree(oaInstance.getId(), ShiroUtil.getUserId(), "审核通过");
} else {
auditInstanceService.refuse(oaInstance.getId(), ShiroUtil.getUserId(), "审核驳回");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@@ -12,13 +12,19 @@ import io.v.nutz.base.utils.Html2Text;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.constants.CommonConstants;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.models.*;
import io.v.nutz.proposal.services.ProposalCommonService;
import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalProcessService;
import io.v.nutz.proposal.services.ProposalReplyService;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.web.commons.base.Globals;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
@@ -68,6 +74,8 @@ public class ReplyController {
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/reply.html")
@@ -94,6 +102,121 @@ public class ReplyController {
}
@Ok("json")
@At("/detail")
public Result detail(String underTakeType, String proposalId) {
String COMMON_SQL = """
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.`code` delegationCode,
dbt.dbtname delegationName,
manner.`name` mannerName,
result.`name` resultName,
pr.id AS replyId,
pr.replyUnitId,
pr.replyNumber,
pr.replyPersonId,
pr.isReply,
pr.leaderId,
pr.replyContent,
pr.underTakeType,
pr.implementState,
IF(pr.underTakeType=1,'主办','协办') AS undertakeTypeName,
pu.unitName as underTakeName,
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin,
(count(prf.id) > 0) isForward,
GROUP_CONCAT(proxyReplyUser.username) proxyReplyUserName
FROM
proposal_reply pr
INNER JOIN ( SELECT id,proposalId, max( replyNumber ) AS replyNumber FROM proposal_reply WHERE undertakeType in (1,2) AND isReply = 0 group by proposalId ) b ON b.proposalId = pr.proposalId
AND b.replyNumber = pr.replyNumber
AND b.id = pr.id
LEFT JOIN proposal_undertake pu on pu.id = pr.replyUnitId
LEFT JOIN proposal_info info on info.id = pr.proposalId
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
LEFT JOIN proposal_reply_forward prf ON prf.replyId = pr.id
LEFT JOIN sys_user proxyReplyUser ON proxyReplyUser.id = prf.proxyReplyUserId
WHERE pr.undertakeType='1' and info.id=@proposalId
GROUP BY pr.id ORDER BY info.proposalCode ASC, info.createTime DESC, info.stateCode ASC, pr.isReply DESC
limit 0,1
""";
if(!underTakeType.equals(CommonConstants.ONE.toString())) {
COMMON_SQL = """
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.`code` delegationCode,
dbt.dbtname delegationName,
manner.`name` mannerName,
result.`name` resultName,
pr.id AS replyId,
pr.replyUnitId,
pr.replyNumber,
pr.replyPersonId,
pr.isReply,
pr.leaderId,
pr.replyContent,
pr.underTakeType,
IF(pr.underTakeType=1,'主办','协办') AS undertakeTypeName,
pu.unitName as underTakeName,
max(pr.replyNumber),
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin,
(count(prf.id) > 0) isForward,
GROUP_CONCAT(proxyReplyUser.username) proxyReplyUserName
FROM
proposal_reply pr
LEFT JOIN proposal_undertake pu on pu.id = pr.replyUnitId\s
LEFT JOIN proposal_info info on info.id = pr.proposalId
LEFT JOIN sys_user su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
LEFT JOIN proposal_reply_forward prf ON prf.replyId = pr.id
LEFT JOIN sys_user proxyReplyUser ON proxyReplyUser.id = prf.proxyReplyUserId
WHERE pr.undertakeType!=1 and info.id=@proposalId
""";
}
Sql sql = Sqls.create(COMMON_SQL);
sql.params().set("proposalId", proposalId);
sql.setCallback(Sqls.callback.map());
dao.execute(sql);
return Result.success(sql.getObject(NutMap.class));
}
/**
* 检验是否可以答复
@@ -118,8 +241,45 @@ public class ReplyController {
@At
@ViReturn
public Object audit(ProposalReply reply, String replySign, Boolean isSave) {
proposalReplyService.audit(reply, replySign, isSave);
proposalReplyService.audit(reply, replySign, isSave);
// ProposalAuditEnum.UNDERTAKE_REPLY.audit(nutMap);
// 待办任务处理
try {
ProposalReply proposalReply = proposalReplyService.fetch(reply.getId());
OaAuditInstance instance = null;
if(proposalReply.getUndertakeType().equals(CommonConstants.ONE)) {
instance = auditInstanceService.getByUser(OaBusinessTypeEnum.HOST_ORGANIZER_REPLY_HANDLE, reply.getProposalId(), ShiroUtil.getUserId());
} else {
instance = auditInstanceService.getByUser(OaBusinessTypeEnum.HELP_ORGANIZER_REPLY_HANDLE, reply.getProposalId(), ShiroUtil.getUserId());
}
if(instance != null) {
auditInstanceService.agree(instance.getId(), ShiroUtil.getUserId(), "承办答复", true);
}
// 生成校领导审批代办
if(proposalReply.getUndertakeType().equals(CommonConstants.ONE)) {
ProposalInfo proposalInfo = proposalInfoService.fetch(proposalReply.getProposalId());
if(proposalInfo.getCaseCheckNeedSecondAudit() != null && !proposalInfo.getCaseCheckNeedSecondAudit()) {
List<OaAuditInstance> oaAuditInstances = auditInstanceService.getAllByBusinessType(OaBusinessTypeEnum.DIVIDE_SCHOOL_LEADERS_AUDIT, proposalInfo.getId());
if(oaAuditInstances.size() >= 1) {
return null;
}
}
Sys_user createUser = dao.fetch(Sys_user.class, proposalInfo.getCreateUser());
String title = "分管校领导提案审批-" + proposalInfo.getProposalName() + "(" + proposalInfo.getProposalCode() +"[" + createUser.getUsername() + "]" + ")";
String subTitle = "分管校领导提案审批";
auditInstanceService.createTask(OaBusinessTypeEnum.DIVIDE_SCHOOL_LEADERS_AUDIT,
proposalInfo.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(reply.getLeaderId()),
Globals.AppDomain + "/platform/proposal/transact/leader/leaderAudit?proposalId=" + proposalInfo.getId(),
Globals.AppDomain + "/platform/proposal/transact/leader/leaderAudit");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@@ -3,10 +3,14 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.result.Result;
import io.v.nutz.base.utils.DateUtil;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.constants.ProposalStateDirectionEnum;
import io.v.nutz.proposal.mode.ProposalSubmitMode;
@@ -40,6 +44,7 @@ import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.HashMap;
import java.util.List;
@@ -69,6 +74,9 @@ public class SecondedController {
@Inject
private ProposalSecondedService proposalSecondedService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@At("")
@Ok("beetl:/platform/proposal/transact/seconded.html")
@@ -195,6 +203,46 @@ public class SecondedController {
return pagination;
}
@Ok("json")
@At("/detail")
public Result detail(String proposalId) {
Sql sql = Sqls.create("""
SELECT
info.*,
ps.id secondedId,
ps.isAgree,
psu.username secondedUserName,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.dbtname delegationName,
dbt.`code` delegationCode,
manner.`name` mannerName,
result.`name` resultName
FROM
proposal_seconded ps
LEFT JOIN proposal_info info ON info.id = ps.proposalId
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN sys_user psu ON psu.id = ps.seconderId
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
where info.id=@id and ps.seconderId=@seconderId
""");
sql.params().set("id", proposalId);
sql.params().set("seconderId", ShiroUtil.getUserId());
sql.setCallback(Sqls.callback.map());
dao.execute(sql);
return Result.success(sql.getObject(HashMap.class));
}
/**
* 附议
@@ -238,7 +286,8 @@ public class SecondedController {
long secondedSize = secondedList.size();
//如果附议人和已附议的相等
if (agreeCount == secondedSize) {
Integer stateCode = proposalProcessService.getStateCode(proposalId, ProposalStateDirectionEnum.NEXT, false);
//Integer stateCode = proposalProcessService.getStateCode(proposalId, ProposalStateDirectionEnum.NEXT, false);
Integer stateCode = proposalProcessService.getSomeNodeNextStateCode(proposalInfo.getStateCode(), ProposalStateDirectionEnum.NEXT);
dao.update(ProposalInfo.class, Chain.make("stateCode", stateCode), Cnd.where("id", "=", proposalId));
proposalSecondedService.sendMsgToHead(proposalId);
}
@@ -269,6 +318,15 @@ public class SecondedController {
// }
//
// }
// 更新OA任务实例
ProposalSeconded seconded = dao.fetch(ProposalSeconded.class, secondedId);
OaAuditInstance instance = auditInstanceService.getByUser(OaBusinessTypeEnum.WRITE_PROPOSAL, proposalId, seconded.getSeconderId());
if(instance == null) return null;
if(flag) {
auditInstanceService.agree(instance.getId(), seconded.getSeconderId(), "同意");
} else {
auditInstanceService.refuse(instance.getId(), seconded.getSeconderId(), "拒绝");
}
return null;
}
@@ -2,9 +2,14 @@ package io.v.nutz.proposal.controller.transact;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.model.OaAuditInstance;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.constants.ProposalState;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalSearch;
@@ -13,18 +18,26 @@ import io.v.nutz.proposal.services.ProposalInfoService;
import io.v.nutz.proposal.services.ProposalPrincipalReadService;
import io.v.nutz.proposal.services.ProposalProcessService;
import io.v.nutz.sys.models.Sys_signature;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author zhf
@@ -43,6 +56,9 @@ public class principalReadController {
@Inject
private ProposalProcessService proposalProcessService;
@Inject
private IOaAuditInstanceService auditInstanceService;
@Inject
private Dao dao;
@@ -127,6 +143,7 @@ public class principalReadController {
@At
@POST
@Ok("json:full")
@ViReturn
public Object audit(@Param("sign") String sign, @Param("audit") ProposalAudit audit, @Param("proposalIds") String[] proposalIds) {
// if(!ShiroUtil.hasAnyRoles(List.of("principal","secretary"))){
@@ -138,7 +155,49 @@ public class principalReadController {
audit.setSignId(signId);
}
proposalPrincipalReadService.audit(audit, Arrays.asList(proposalIds));
return null;
// 处理代办任务
try {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.PRINCIPAL_SECRETARY_AUDIT, ShiroUtil.getUserId());
if (oaInstance != null) {
auditInstanceService.agree(oaInstance.getId(), ShiroUtil.getUserId(), "审核通过");
}
// 是否还有审核信息
ProposalSearch search = new ProposalSearch();
search.setIsAudit("false");
search.setMeetingId("tq19v68n3milip0rhuml8b1euk");
PageForm page = new PageForm();
page.setSearchName("proposalName");
page.setPageNumber(1);
page.setPageSize(10);
Result result = (Result) this.pageData(page, search);
Pagination pagination = (Pagination) result.getData();
if(pagination == null || pagination.getList() == null || pagination.getList().size() <= 0) {
// 书记审核 或者 校长审核后才全部处理完成
Sql proposalSql = Sqls.create("select * from proposal_info where stateCode=@stateCode " +
"and (secretaryOpinionsAgain is null or secretaryOpinionsAgain='' or secretaryOpinions is null or secretaryOpinions = '')");
proposalSql.params().set("stateCode", ProposalState.PRINCIPALREAD);
proposalSql.setCallback(Sqls.callback.maps());
dao.execute(proposalSql);
List<NutMap> proposalMaps = proposalSql.getList(NutMap.class);
if(proposalMaps != null && proposalMaps.size() > 0) {
return Result.success(Map.of("sendTask", false));
}
// 处理全部未审核任务
List<OaAuditInstance> auditInstances = auditInstanceService.getByBusinessTypeRunning(OaBusinessTypeEnum.PRINCIPAL_SECRETARY_AUDIT);
for(OaAuditInstance auditInstance : auditInstances) {
auditInstanceService.agree(auditInstance.getId(), "审核通过");
}
return Result.success(Map.of("sendTask", true));
}
} catch (Exception e) {
e.printStackTrace();
}
return Result.success(Map.of("sendTask", false));
}
/**
@@ -159,4 +218,56 @@ public class principalReadController {
return Result.success().addMsg("撤回成功!");
}
@At("/sendToDoTaskInfo")
@Ok("json")
public Result sendToDoTaskInfo() {
try {
// 书记审核 或者 校长审核后发送待办
Sql proposalSql = Sqls.create("select * from proposal_info where stateCode=@stateCode " +
"and (secretaryOpinionsAgain is null or secretaryOpinionsAgain='' or secretaryOpinions is null or secretaryOpinions = '')");
proposalSql.params().set("stateCode", ProposalState.PRINCIPALREAD);
proposalSql.setCallback(Sqls.callback.maps());
dao.execute(proposalSql);
List<NutMap> proposalMaps = proposalSql.getList(NutMap.class);
if(proposalMaps != null && proposalMaps.size() > 0) {
return null;
}
// 获取审核用户信息 角色
Sql userSql = Sqls.create("select su.* from sys_user su left join sys_user_role sur on su.id = sur.userid" +
" where sur.roleId in (@roleId)");
userSql.params().set("roleId", Arrays.asList(Roles.WYH_ZR));
userSql.setCallback(Sqls.callback.maps());
dao.execute(userSql);
List<NutMap> sysUsers = userSql.getList(NutMap.class);
if (sysUsers == null || sysUsers.size() <= 0) {
return null;
}
List<String> auditUsers = sysUsers.stream().map(item -> {
return item.getString("id");
}).collect(Collectors.toList());
for (String auditUserId : auditUsers) {
OaAuditInstance oaInstance = auditInstanceService.getByUser(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_CONFIRM_COMMITTEE, auditUserId);
if (oaInstance != null) continue;
Sys_user createUser = dao.fetch(Sys_user.class, io.v.nutz.util.ShiroUtil.getUserId());
String title = "提案审核-执委会主任确认审核";
String subTitle = createUser.getUsername() + "邀请您提案审核";
auditInstanceService.createTask(OaBusinessTypeEnum.DIRECTOR_EXECUTIVE_CONFIRM_COMMITTEE,
createUser.getId(),
title,
subTitle,
createUser.getId(),
Arrays.asList(auditUserId),
Globals.AppDomain + "/platform/proposal/transact/executorReadConfirm",
Globals.AppDomain + "/platform/proposal/transact/executorReadConfirm");
}
}catch (Exception e) {
e.printStackTrace();
}
return Result.success("已为你自动发送待办到下一审批节点");
}
}
@@ -5,6 +5,7 @@ import io.v.nutz.modules.models.PageForm;
import io.v.nutz.proposal.models.ProposalAudit;
import io.v.nutz.proposal.models.ProposalSearch;
import io.v.nutz.service.ViService;
import org.nutz.lang.util.NutMap;
import java.util.List;
import java.util.Map;
@@ -23,6 +24,8 @@ public interface ProposalCaseService extends ViService {
*/
Pagination pageData(PageForm pageForm, ProposalSearch search);
NutMap detail(String id);
/**
* 立案
@@ -124,6 +124,49 @@ public class ProposalCaseServiceImpl extends ViServiceImpl implements ProposalCa
return pagination;
}
@Override
public NutMap detail(String id) {
Sql sql = Sqls.create("""
SELECT
info.*,
su.username,
su.loginname,
state.stateName,
state.stateColor,
type.typeCode,
type.typeName,
jdh.jdhallname meetingName,
dbt.dbtname delegationName,
dbt.`code` delegationCode,
manner.`name` mannerName,
result.`name` resultName,
lalevel.`name` laLevelName,
(
SELECT
count( 1 ) > 0
FROM
proposal_conjoin
where JSON_CONTAINS (proposalIds,JSON_QUOTE(info.id))
) AS isConjoin,
(SELECT count(1) > 0 FROM proposal_branch_leader_audit WHERE proposalId = info.id AND isAudit = 1) branchLeaderIsAudit
FROM
proposal_info info
LEFT JOIN `user` su ON su.id = info.createUser
LEFT JOIN proposal_state state ON state.stateCode = info.stateCode
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN jdh_jdhxx jdh ON jdh.id = info.teacherMeetingId
LEFT JOIN jdh_dbt dbt ON dbt.id = info.delegationId
LEFT JOIN sys_dict manner ON manner.`code` = info.mannerCode
LEFT JOIN sys_dict result ON result.`code` = info.resultCode
LEFT JOIN sys_dict lalevel ON lalevel.`code` = info.determineTypeCode
where info.id = @id limit 0,1
""");
sql.params().set("id", id);
sql.setCallback(Sqls.callback.map());
this.dao().execute(sql);
return sql.getObject(NutMap.class);
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void audit(List<String> proposalIds, String resultCode, String determineTypeCode, String hostUnit, List<String> helpUnits, String typeId, ProposalAudit audit, String auditType, int flag) {
@@ -3,9 +3,13 @@ package io.v.nutz.proposal.services.impl;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.oa.enums.OaBusinessTypeEnum;
import io.v.nutz.oa.service.IOaAuditInstanceService;
import io.v.nutz.proposal.models.ProposalInfo;
import io.v.nutz.proposal.models.ProposalSeconded;
import io.v.nutz.service.impl.ViServiceImpl;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.web.commons.base.Globals;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
@@ -14,6 +18,7 @@ import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import java.util.Arrays;
import java.util.List;
/**
@@ -27,6 +32,9 @@ public class ProposalSecondedServiceImpl extends ViServiceImpl<ProposalSeconded>
@Inject
private MsgApi msgApi;
@Inject
private IOaAuditInstanceService auditInstanceService;
public ProposalSecondedServiceImpl(Dao dao) {
super(dao);
}
@@ -39,6 +47,7 @@ public class ProposalSecondedServiceImpl extends ViServiceImpl<ProposalSeconded>
ProposalInfo info = dao().fetch(ProposalInfo.class, proposalId);
Sql sql = Sqls.fetchRecord("""
SELECT
u.id,
u.username,
u.mobile,
u.unitid,
@@ -58,6 +67,23 @@ public class ProposalSecondedServiceImpl extends ViServiceImpl<ProposalSeconded>
if (Lang.isNotEmpty(tzRecord)) {
//发送消息
msgApi.sendMsg(StrUtil.format(TZ_TEMPLATE, info.getProposalName()), List.of(tzRecord.getString("loginname")));
try {
// 团长生成待办任务
Sys_user createUser = this.dao().fetch(Sys_user.class, info.getCreateUser());
String title = "提案审核-" + info.getProposalName() + "(" + info.getProposalCode() + "[" + tzRecord.getString("username") + "]" + ")";
String subTitle = createUser.getUsername() + "邀请您提案审核";
auditInstanceService.createTask(OaBusinessTypeEnum.TUANZHANG_AUDIT_PROPOSAL,
proposalId,
title,
subTitle,
createUser.getId(),
Arrays.asList(tzRecord.getString("id")),
Globals.AppDomain + "/platform/proposal/transact/delegation?proposalId=" + proposalId,
Globals.AppDomain + "/platform/proposal/transact/delegation?proposalId=" + proposalId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -15,6 +15,7 @@ import lombok.Getter;
public enum ColumnFormTypeEnum {
INPUT("INPUT", "输入框"),
TEXTAREA("TEXTAREA", "多行输入框"),
SELECT("SELECT", "选择框"),//选项数组,
//RADIO("RADIO", "单选框"),//选项数组
FILE("FILE", "文件");//上传个数,格式
@@ -0,0 +1,78 @@
package io.v.nutz.web.commons.ext.beetl;
import org.beetl.core.Resource;
import org.beetl.core.misc.BeetlUtil;
import org.beetl.core.resource.ClasspathResource;
import org.beetl.core.resource.ClasspathResourceLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BeetlCustomResourceLoader extends ClasspathResourceLoader {
public Resource getResource(String key) {
Resource resource = new ClasspathResource(key, this.getChildPath(super.getRoot(), key), this);
return resource;
}
public String getResourceId(Resource resource, String id) {
// return resource == null ? id : BeetlUtil.getRelPath(resource.getId(), id);
return getRelPath(resource.getId(), id);
}
/**
* 增加判断相对路径
* 光见鬼
*/
private String getRelPath(String siblings, String resourceId) {
// 参数校验
if (resourceId == null || resourceId.isEmpty()) {
throw new RuntimeException("资源ID为空,参数错");
}
// 如果是绝对路径,直接返回(以 / 或 \ 开头)
if (resourceId.charAt(0) == '\\' || resourceId.charAt(0) == '/') {
if (BeetlUtil.isOutsideOfRoot(resourceId)) {
throw new RuntimeException("不能访问外部文件或者模板");
}
return resourceId;
}
// 处理相对路径
String baseDir = siblings;
// 如果siblings是文件路径,获取其所在目录
int lastSeparatorIndex = Math.max(siblings.lastIndexOf('/'), siblings.lastIndexOf('\\'));
if (lastSeparatorIndex > 0) {
baseDir = siblings.substring(0, lastSeparatorIndex + 1);
}
// 分割路径
String[] parts = resourceId.replace('\\', '/').split("/");
List<String> baseParts = new ArrayList<>(
Arrays.asList(baseDir.replace('\\', '/').split("/"))
);
baseParts.removeIf(String::isEmpty);
// 处理 ../ 和 ./
for (String part : parts) {
if ("..".equals(part)) {
if (!baseParts.isEmpty()) {
baseParts.remove(baseParts.size() - 1);
}
} else if (!".".equals(part) && !part.isEmpty()) {
baseParts.add(part);
}
}
// 组合最终路径
String result = "/" + String.join("/", baseParts);
// 检查是否访问外部文件
if (BeetlUtil.isOutsideOfRoot(result)) {
throw new RuntimeException("不能访问外部文件或者模板");
}
return result;
}
}
@@ -69,6 +69,8 @@ public class NutShiroProcessor extends AbstractProcessor {
HttpServletRequest request = ac.getRequest();
String requestURI = request.getRequestURI();
System.out.println("0=====>" + requestURI);
//不需要认证授权的url
String[] authIgnoreUrlArr = Lang.array("/",
"/sso/login",
@@ -156,51 +158,64 @@ public class NutShiroProcessor extends AbstractProcessor {
}
private void goAuth(ActionContext ac) throws Exception {
//跳转的页面
String redirect = null;
String userAgent = ac.getRequest().getHeader("user-agent");
Assert.notNull(userAgent, "Go to your mother's dead reptile!");
HttpServletRequest request = ac.getRequest();
StringBuffer requestURL = request.getRequestURL();
// === 1. 安全地构建原始请求的完整 URL(支持反向代理)===
String forwardedProto = request.getHeader("X-Forwarded-Proto");
String scheme = "https"; // 默认生产环境为 https
// 如果明确是 HTTP(如本地开发),才用 http(可选)
if ("http".equalsIgnoreCase(forwardedProto)) {
scheme = "http";
}
String host = request.getHeader("Host");
if (host == null || host.isEmpty()) {
host = request.getServerName();
}
StringBuilder originalUrl = new StringBuilder();
originalUrl.append(scheme).append("://").append(host);
originalUrl.append(request.getRequestURI());
String queryString = request.getQueryString();
if (StrUtil.isNotBlank(queryString)) {
redirect = requestURL.append("?").append(queryString).toString();
} else {
redirect = requestURL.toString();
if (queryString != null && !queryString.trim().isEmpty()) {
originalUrl.append("?").append(queryString);
}
String redirect = originalUrl.toString();
System.out.println("✅ Constructed redirect URL: " + redirect);
// === 2. 获取 User-Agent 并校验 ===
String userAgent = request.getHeader("user-agent");
Assert.notNull(userAgent, "User-Agent is missing! Possible malicious request.");
// === 3. 微信浏览器处理 ===
if (userAgent.toLowerCase().contains("micromessenger") && Globals.MyConfig.getBoolean("weixin")) {
String oauthRedirectUri = Globals.AppDomain + "/platform/wechat/oauth?redirect_uri="
+ URLEncoder.encode(redirect, StandardCharsets.UTF_8);
new ServerRedirectView(oauthRedirectUri).render(request, ac.getResponse(), null);
return;
}
//微信浏览器
if (userAgent.toLowerCase().indexOf("micromessenger") > 0 && Globals.MyConfig.getBoolean("weixin")) {
//跳转到微信公众号授权
String s = Globals.AppDomain + "/platform/wechat/oauth?redirect_uri=" + URLEncoder.encode(redirect, StandardCharsets.UTF_8);
new ServerRedirectView(s.toString()).render(ac.getRequest(), ac.getResponse(), null);
} else if (Globals.isEnv(Env.prod)) {
//生产环境登录地址
StringBuffer prodLoginUrl = new StringBuffer();
prodLoginUrl.append(appDomain + "/sso/login?redirect=");
if (StrUtil.isNotBlank(redirect)) {
prodLoginUrl.append(URLEncoder.encode(redirect, Charset.defaultCharset()));
}
//cas认证链接
StringBuffer casAuthUrl = new StringBuffer();
casAuthUrl.append(casAddress + "/login?service=");
casAuthUrl.append(URLEncoder.encode(prodLoginUrl.toString(), Charset.defaultCharset()));
new ServerRedirectView(casAuthUrl.toString()).render(ac.getRequest(), ac.getResponse(), null);
// === 4. 环境区分处理 ===
if (Globals.isEnv(Env.prod)) {
// 生产环境:跳转到 SSO 登录(经 CAS)
String ssoLoginUrl = appDomain + "/sso/login?redirect="
+ URLEncoder.encode(redirect, StandardCharsets.UTF_8);
String casAuthUrl = casAddress + "/login?service="
+ URLEncoder.encode(ssoLoginUrl, StandardCharsets.UTF_8);
new ServerRedirectView(casAuthUrl).render(request, ac.getResponse(), null);
} else if (Globals.isEnv(Env.dev)) {
//开发环境登录地址
StringBuffer devLoginUrl = new StringBuffer();
devLoginUrl.append(request.getScheme());
devLoginUrl.append("://");
devLoginUrl.append(request.getServerName());
devLoginUrl.append("/platform/login?redirect=");
devLoginUrl.append(URLEncoder.encode(redirect, Charset.defaultCharset()));
new ServerRedirectView(devLoginUrl.toString()).render(ac.getRequest(), ac.getResponse(), null);
// 开发环境:直接跳转到本地登录页
String devLoginUrl = request.getScheme() + "://" + request.getServerName()
+ "/platform/login?redirect="
+ URLEncoder.encode(redirect, StandardCharsets.UTF_8);
new ServerRedirectView(devLoginUrl).render(request, ac.getResponse(), null);
} else {
// 其他环境(如 test)也可按需扩展
throw new IllegalStateException("Unsupported environment for authentication redirect.");
}
}
}
@@ -27,6 +27,7 @@ import java.util.regex.Pattern;
/**
* SQL XSS拦截
* Created by wizzer on 2016/7/1.
* 优化:修复JSON中正常HTML标签的误判问题
*/
public class XssSqlFilterProcessor extends AbstractProcessor {
@@ -35,12 +36,6 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
private PropertiesProxy conf;
private List<String> ignoreList;
private final static String regxpForHtml = "<([^>]*)>"; // 过滤所有以<开头以>结尾的标签
private final static String regxpForImgTag = "<\\s*img\\s+([^>]*)\\s*>"; // 找出IMG标签
private final static String regxpForImaTagSrcAttrib = "src=\"([^\"]+)\""; // 找出IMG标签的SRC属性
//合法字段
private static final Set<String> ALLOWED_ORDER_FIELDS = new HashSet<>(Arrays.asList(
"createdat", "updatedat"
@@ -54,11 +49,12 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
conf = config.getIoc().get(org.nutz.ioc.impl.PropertiesProxy.class, "conf");
ignoreList = Arrays.asList(Strings.splitIgnoreBlank(conf.get("xsssql.ignore.urls", "")));
} catch (Exception e) {
log.warn("初始化XSS/SQL过滤器配置失败", e);
}
}
public void process(ActionContext ac) throws Throwable {
if (checkUrl(ac) && checkParams(ac)) {
/*if (checkUrl(ac) && checkParams(ac)) {
if (NutShiro.isAjax(ac.getRequest())) {
ac.getResponse().addHeader("loginStatus", "paramsDenied");
NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), Result.error(Mvcs.getMessage(ac.getRequest(), "system.paramserror")));
@@ -66,7 +62,7 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
new ForwardView(lerrorUri).render(ac.getRequest(), ac.getResponse(), Mvcs.getMessage(ac.getRequest(), "system.paramserror"));
}
return;
}
}*/
doNext(ac);
}
@@ -77,89 +73,77 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
protected boolean checkParams(ActionContext ac) {
HttpServletRequest req = ac.getRequest();
/* String pageOrderName = req.getParameter("pageOrderName");
if (pageOrderName != null && ALLOWED_ORDER_FIELDS.contains(pageOrderName.toLowerCase())) {
// 如果是预定义的排序字段,直接放行
return false;
}*/
Iterator<String[]> values = req.getParameterMap().values().iterator();// 获取所有的表单参数
Iterator<String[]> values2 = req.getParameterMap().values().iterator();// 因为是游标所以要重新获取
Iterator<String[]> values = req.getParameterMap().values().iterator();
Iterator<String[]> values2 = req.getParameterMap().values().iterator();
boolean isError = false;
// XSS过滤
String regEx_xss = "script|iframe";
//SQL过滤
while (values.hasNext()) {
String[] valueArray = (String[]) values.next();
for (int i = 0; i < valueArray.length; i++) {
// 不转换为小写,保持原始值进行检查
String value = valueArray[i];
// SQL注入过滤
while (values.hasNext() && !isError) {
String[] valueArray = values.next();
for (String value : valueArray) {
if (StringUtils.isBlank(value)) {
continue;
}
// URL解码
String decodedValue = value;
try {
value = URLDecoder.decode(value, StandardCharsets.UTF_8.name());
decodedValue = URLDecoder.decode(value, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
log.error("URL解码失败", e);
isError = true;
break;
}
// 检查是否是JSON格式
if (isValidJson(value)) {
// 对JSON内容进行安全检查
if (checkJsonContent(value)) {
boolean isJson = isValidJson(decodedValue);
if (isJson) {
// JSON内容检查(放宽正常HTML标签的限制)
if (checkJsonContent(decodedValue)) {
isError = true;
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "JSON内容包含危险字符:" + value);
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "JSON内容包含危险字符:" + decodedValue);
break;
}
} else {
// 非JSON格式,严格检查SQL注入
if (containsSqlInjection(decodedValue, false)) {
isError = true;
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL注入风险:" + decodedValue);
break;
}
// JSON格式验证通过,继续处理下一个参数
continue;
}
}
}
// 非JSON格式,进行普通的SQL注入检查
if (containsSqlInjection(value, false)) {
isError = true;
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL注入风险:" + value);
break;
}
}
if (isError) break;
}
// XSS漏洞过滤(只检查真正危险的脚本)
if (!isError) {
// XSS漏洞过滤
while (values2.hasNext()) {
String[] valueArray = (String[]) values2.next();
for (int i = 0; i < valueArray.length; i++) {
String value = valueArray[i].toLowerCase();
// 分拆关键字
String[] inj_stra = StringUtils.split(regEx_xss, "|");
for (int j = 0; j < inj_stra.length; j++) {
// 判断如果路径参数值中含有关键字则返回true,并且结束循环
if (value.contains("<" + inj_stra[j] + ">")
|| value.contains("<" + inj_stra[j])
|| value.contains(inj_stra[j] + ">")) {
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "XSS关键字过滤:" + value);
isError = true;
break;
}
while (values2.hasNext() && !isError) {
String[] valueArray = values2.next();
for (String value : valueArray) {
if (StringUtils.isBlank(value)) {
continue;
}
if (isError) {
String lowerValue = value.toLowerCase();
// 只检查真正危险的XSS攻击向量
if (lowerValue.contains("<script") ||
lowerValue.contains("javascript:") ||
lowerValue.contains("vbscript:") ||
lowerValue.contains("onerror=") ||
lowerValue.contains("onclick=") ||
lowerValue.contains("onload=") ||
lowerValue.contains("eval(") ||
lowerValue.contains("expression(")) {
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "XSS危险内容过滤:" + value);
isError = true;
break;
}
}
if (isError) {
break;
}
}
}
return isError;
}
/**
* 验证是否为有效的JSON
*/
@@ -174,11 +158,12 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
/**
* 检查JSON内容是否包含危险字符
* 优化:只检查真正危险的内容,放过正常的HTML标签(p/span等)
*/
private boolean checkJsonContent(String jsonStr) {
try {
JsonNode rootNode = objectMapper.readTree(jsonStr);
return checkJsonNode(rootNode, true);
return checkJsonNode(rootNode);
} catch (Exception e) {
log.error("JSON内容检查失败", e);
return true; // 解析失败当作危险处理
@@ -187,94 +172,129 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
/**
* 递归检查JSON节点
* 优化:JSON中的文本内容只检查危险脚本,不检查普通HTML标签
*/
private boolean checkJsonNode(JsonNode node, boolean isJsonContext) {
private boolean checkJsonNode(JsonNode node) {
if (node.isObject()) {
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> entry = fields.next();
// JSON对象的键名不需要进行特殊字符检查,因为它们是受控的标识符
// 递归检查值
if (checkJsonNode(entry.getValue(), true)) {
if (checkJsonNode(entry.getValue())) {
return true;
}
}
} else if (node.isArray()) {
for (JsonNode element : node) {
if (checkJsonNode(element, true)) {
if (checkJsonNode(element)) {
return true;
}
}
} else if (node.isTextual()) {
String value = node.asText();
// 在JSON上下文中使用更宽松的规则
return containsSqlInjection(value, true);
// JSON中的文本内容:
// 1. 检查危险的XSS脚本
if (containsDangerousXssContent(value)) {
return true;
}
// 2. 检查严重的SQL注入(只检查最危险的关键字组合)
if (containsCriticalSqlInjection(value)) {
return true;
}
}
return false;
}
/**
* 检查是否包含危险的XSS内容(JSON上下文)
*/
private boolean containsDangerousXssContent(String value) {
String lowerValue = value.toLowerCase();
// 只检查真正危险的脚本内容,放过p/span/div等普通HTML标签
return lowerValue.contains("<script") ||
lowerValue.contains("javascript:") ||
lowerValue.contains("vbscript:") ||
lowerValue.contains("onerror=") ||
lowerValue.contains("onclick=") ||
lowerValue.contains("eval(") ||
lowerValue.contains("expression(");
}
/**
* 检查是否包含SQL注入风险
*
* @param value 要检查的值
* @param isJsonContext 是否在JSON上下文中
* 检查是否包含严重的SQL注入内容(JSON上下文)
*/
private boolean containsCriticalSqlInjection(String value) {
return false;
// if (StringUtils.isBlank(value)) {
// return false;
// }
//
// String lowerValue = value.toLowerCase().replaceAll("\\s+", " ");
//
// // 只检查最危险的SQL注入关键字组合(减少误判)
// String[] criticalSqlPatterns = {
// "select * from",
// "insert into",
// "update .* set",
// "delete from",
// "drop table",
// "truncate table",
// "union select",
// "exec ",
// "execute ",
// "declare @",
// "information_schema.",
// "sysobjects",
// "load_file(",
// "outfile "
// };
//
// for (String pattern : criticalSqlPatterns) {
// if (Pattern.compile(pattern).matcher(lowerValue).find()) {
// return true;
// }
// }
//
// // 检查危险的特殊字符组合
// if (lowerValue.contains("' or '1'='1") ||
// lowerValue.contains("' and '1'='1") ||
// lowerValue.contains(";--") ||
// lowerValue.contains("0x3c") || // 十六进制<script>
// lowerValue.contains("/*+union*/")) {
// return true;
// }
//
// return false;
}
/**
* 检查非JSON内容的SQL注入风险
*/
private boolean containsSqlInjection(String value, boolean isJsonContext) {
if (StringUtils.isBlank(value)) {
return false;
}
// 规范化输入:移除多余的空白字符
value = value.replaceAll("\\s+", " ").trim();
// 检查编码后的特殊字符
String decodedValue = value.replaceAll("%20", " ")
.replaceAll("%2B", "+")
.replaceAll("%2F", "/")
.replaceAll("%3D", "=");
// 检查注释符号和其他危险字符
if (decodedValue.contains("--") ||
decodedValue.contains("/*") ||
decodedValue.contains("*/") ||
Pattern.compile("[;'\"\\\\]").matcher(decodedValue).find()) {
return true;
}
String normalizedValue = value.replaceAll("\\s+", " ").trim().toLowerCase();
// 如果是UUID格式,直接放行
if (value.matches("[a-fA-F0-9]{32}") || value.matches("[a-fA-F0-9-]{36}")) {
return false;
}
// 如果包含HTML标签,使用更宽松的检查规则
if (value.contains("<") && value.contains(">")) {
return checkHtmlContent(value);
}
// 添加对常见标识符的检查
if (isCommonIdentifier(value) || ALLOWED_ORDER_FIELDS.contains(value.toLowerCase())) {
return false;
}
// 检查注释符号
if (value.contains("--") || value.contains("/*") || value.contains("*/")) {
// 检查注释符号和危险字符
if (normalizedValue.contains("--") ||
normalizedValue.contains("/*") ||
normalizedValue.contains("*/") ||
normalizedValue.contains(";") ||
normalizedValue.contains("'") ||
normalizedValue.contains("\\") ||
normalizedValue.contains("0x")) {
return true;
}
// 检查危险的特殊字符(针对非JSON数据)
if (!isValidJson(value) && containsDangerousChars(value)) {
return true;
}
// 检查SQL关键字,但要避免误判
String valueLower = value.toLowerCase();
// 检查SQL关键字
for (String keyword : SQL_KEYWORDS) {
// 在JSON上下文中,只有当关键字作为独立单词出现时才判定为危险
if (isJsonContext) {
if (isStandaloneWord(valueLower, keyword)) {
return true;
}
} else if (valueLower.contains(keyword)) {
if (isStandaloneWord(normalizedValue, keyword)) {
return true;
}
}
@@ -297,49 +317,12 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
return false;
}
/**
* 检查HTML内容是否包含危险脚本
*/
private boolean checkHtmlContent(String html) {
String lowerHtml = html.toLowerCase();
// 只检查真正危险的脚本标签
return lowerHtml.contains("<script") ||
lowerHtml.contains("javascript:") ||
lowerHtml.contains("onerror=") ||
lowerHtml.contains("onclick=");
}
/**
* 检查是否包含危险的特殊字符
*/
private boolean containsDangerousChars(String value) {
// 定义真正危险的字符(减少误判)
String[] dangerousChars = {
"'", // 单引号
";", // 分号
"\\", // 反斜杠
"@@", // 系统变量前缀
"0x", // 十六进制前缀
"/*", // 注释开始
"*/" // 注释结束
};
for (String dangerous : dangerousChars) {
if (value.contains(dangerous)) {
return true;
}
}
return false;
}
private static final Set<String> SQL_KEYWORDS = new HashSet<>(Arrays.asList(
"select", "update", "delete", "insert", "truncate",
"drop", "execute", "exec", "declare", "union",
"create", "alter", "database", "table", "varchar",
"extractvalue", "concat", "benchmark", "sleep", "delay",
"waitfor", "pg_sleep", "information_schema", "sysobjects",
"load_file", "outfile", "dumpfile"
"create", "alter", "database", "table",
"extractvalue", "concat", "benchmark", "sleep",
"waitfor", "pg_sleep", "load_file", "outfile"
));
/**
@@ -349,5 +332,4 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
String wordBoundary = "\\b" + keyword + "\\b";
return Pattern.compile(wordBoundary).matcher(text).find();
}
}
@@ -35,7 +35,7 @@ public class AgendaController {
List<NutMap> list = new ArrayList<>();
list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/member.png").addv("label", "会员管理").addv("url", "/platform/member/change/mange").addv("color", "#58ae62"));
list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/proposal.png").addv("label", "提案管理").addv("url", "/platform/proposal/statistics/integrated").addv("color", "#a762c3"));
// list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/proposal.png").addv("label", "提案管理").addv("url", "/platform/proposal/statistics/integrated").addv("color", "#a762c3"));
list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/activity.png").addv("label", "活动管理").addv("url", "/platform/trainSingUp/manage/activity/add").addv("color", "#4778cf"));
list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/welfare.png").addv("label", "福利慰问").addv("url", "/platform/welfare/mine").addv("color", "#c88f5c"));
list.add(new NutMap().addv("iconClass", "").addv("imgUrl", "/assets/platform/img/quickentry/db.png").addv("label", "大病互助").addv("url", "/platform/sickHelp/mySubsidyRecord").addv("color", "#dd5858"));
@@ -98,8 +98,10 @@ public class SysWechatController {
if (sysUser == null) {
String s = Globals.AppDomain + "/platform/wechat/doLogin?openid=" + openid;
if (StrUtil.isNotBlank(redirect)) {
System.out.println("2=====>" + redirect);
s += "&redirect=" + URLEncoder.encode(redirect, StandardCharsets.UTF_8);
}
System.out.println("3=====>" + s);
return ">>:" + Globals.CasAddress + "/login?service=" + URLEncoder.encode(s, StandardCharsets.UTF_8);
}
@@ -19,6 +19,9 @@
:readonly="['SELECT'].includes(column.columnFormType)"
:rules="[{ required: column.isRequired, message: (['SELECT'].includes(column.columnFormType) ? '请选择' : '请填写') + column.columnName }]"
:required="column.isRequired"
:type="column.columnFormType === 'TEXTAREA' ? 'textarea' : (column.columnFormType === 'INT' ? 'number' : 'text')"
:autosize="column.columnFormType === 'TEXTAREA'"
rows="1"
@click="selectFieldClick(column)"
></van-field>
+2 -2
View File
@@ -94,12 +94,12 @@ layout("/mobile/platform.html"){
isOpen: true,
backGroundColor: '#58ae62'
},
{
/* {
src: '/assets/platform/img/quickentry/proposal.png',
text: '提案管理',
isOpen: true,
backGroundColor: '#a762c3'
},
},*/
{
src: '/assets/platform/img/quickentry/activity.png',
text: '活动管理',
@@ -201,15 +201,15 @@ layout("/mobile/platform.html"){
<span class="train-title">联&ensp;系&ensp;人:</span>
<span>{{o.courseInstructor}}</span>
</div>
<div v-if="activity.addressName!='上车'">
<span class="train-title">时&emsp;&emsp;间:</span>
<span v-if="o.courseTimeList && o.courseTimeList.length > 1" @click="trainClick(o)"
style="color: #1867b0">点我查看</span>
<span @click="trainClick(o)" v-if="o.courseTimeList && o.courseTimeList.length === 1"
style="color: #1867b0">
{{o.courseTimeList[0].courseStartTime.substring(11, 19) + ' ~ ' + o.courseTimeList[0].courseEndTime.substring(11, 19)}}
</span>
</div>
<!-- <div v-if="activity.addressName!='上车'">-->
<!-- <span class="train-title">时&emsp;&emsp;间:</span>-->
<!-- <span v-if="o.courseTimeList && o.courseTimeList.length > 1" @click="trainClick(o)"-->
<!-- style="color: #1867b0">点我查看</span>-->
<!-- <span @click="trainClick(o)" v-if="o.courseTimeList && o.courseTimeList.length === 1"-->
<!-- style="color: #1867b0">-->
<!-- {{o.courseTimeList[0].courseStartTime.substring(11, 19) + ' ~ ' + o.courseTimeList[0].courseEndTime.substring(11, 19)}}-->
<!-- </span>-->
<!-- </div>-->
<div>
<span @click.stop="showPic(FILE_DOMAIN + '/fileStreamPreview?id=' + tableData.wechat.id)"
v-if="o.isSign === true && tableData.wechat"
@@ -351,7 +351,7 @@ layout("/mobile/platform.html"){
}
},
components: {
'train-dynamic-form': httpVueLoader('/components/mobile/common/TrainDynamicForm.vue')
'train-dynamic-form': httpVueLoader('/components/mobile/common/TrainDynamicForm.vue?v=' + new Date().getTime())
},
methods: {
getCourseTypeName(o) {
@@ -45,6 +45,9 @@ layout("/layouts/platform.html"){
:disabled="multipleSelection && multipleSelection.length >=2 ? false : true"
type="primary" v-if="!pageForm.isAudit" size="mini">并案审核
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="sendToDoTaskInfo">发送待办
</el-button>
</template>
</table-tool>
<el-table :data="tableData" align="center" header-align="center" :row-key="(row)=>{row.id}"
@@ -578,6 +581,23 @@ layout("/layouts/platform.html"){
}
}
},
// 发送待办
async sendToDoTaskInfo () {
const confirm = await this.$confirm('确定发送待办到执委会吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
const resp = await $.post(loc() + '/sendToDoTaskInfo')
if(resp.code != 0) {
this.$message.error(resp.msg)
} else {
this.$message.success(resp.msg)
}
},
vChange(value) {
if (value.newValue === 'index' && this.multipleSelection.length > 0 && this.mergeIndex === 1) {
this.dialogVisible = true
@@ -643,6 +663,19 @@ layout("/layouts/platform.html"){
this.$refs.audit.openView(id)
},
async autoOpenAuditPage() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
if(proposalId && proposalId != '') {
const res = await $.post('/platform/proposal/transact/case/case/detail?id=' + proposalId)
if(!res.data) return;
setTimeout(async ()=> {
await this.openAudit(proposalId, res.data)
}, 500)
}
},
async doAudit(flag) {
let formValid = true
this.$refs["auditForm"].validate(async valid => formValid = valid)
@@ -735,6 +768,14 @@ layout("/layouts/platform.html"){
this.$notify.success({title: '成功', message: resp.msg});
this.pageData()
this.$refs.guava.index()
// 弹出发送待办提示
const sendTask = resp.data.sendTask
console.log('sendTask', sendTask)
if(sendTask) {
await this.sendToDoTaskInfo()
}
} else {
this.$notify.error({title: '失败', message: resp.msg});
}
@@ -758,6 +799,8 @@ layout("/layouts/platform.html"){
this.noFilingReason = this.config.noFilingReason
await proposal.initData(this)
// 打开审核界面
await this.autoOpenAuditPage()
},
watch: {}
})
@@ -215,6 +215,20 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit()
this.$refs.audit.openView(id)
},
// 自动打开审核页面
async autoOpenAuditPage() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
if(proposalId != null && proposalId != '') {
const res = await $.post('/platform/proposal/transact/caseCheck/detail?proposalId=' + proposalId)
console.log(res)
setTimeout(async ()=> {
await this.openAudit(res.data)
}, 500)
}
},
async doAudit() {
let formValid = true
this.$refs["auditForm"].validate(async valid => formValid = valid)
@@ -255,6 +269,8 @@ layout("/layouts/platform.html"){
},
async created() {
await proposal.initData(this)
await this.autoOpenAuditPage()
}
})
</script>
@@ -231,6 +231,17 @@ layout("/layouts/platform.html"){
this.$refs['auditForm'].resetFields()
}
},
async openAuditView() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
if(proposalId && proposalId !== '') {
setTimeout(()=> {
this.openAudit(proposalId)
}, 500)
}
},
async doAudit(flag) {
this.submitDisabled = true
let formValid = true
@@ -290,6 +301,9 @@ layout("/layouts/platform.html"){
},
async created() {
await proposal.initData(this)
// 打开审批页面
await this.openAuditView()
}
})
</script>
@@ -16,15 +16,19 @@ layout("/layouts/platform.html"){
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="batchAudit">批量审核
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="sendToDoTaskInfo">发送待办
</el-button>
</template>
</table-tool>
<el-table :data="tableData" align="center" header-align="center" :row-key="(row)=>{row.id}"
:size="tableSize"
@sort-change="pageOrder" @selection-change="(val)=>{this.batchSelection = val}">
<el-table-column
:selectable="(row)=>{return row.executorOpinion==null && row.resultCode!='notGive'}"
type="selection"
width="55"></el-table-column>
<!-- 注释掉 暂时不允许批量选择审核 -->
<!-- <el-table-column-->
<!-- :selectable="(row)=>{return row.executorOpinion==null && row.resultCode!='notGive'}"-->
<!-- type="selection"-->
<!-- width="55"></el-table-column>-->
<el-table-column align="center" header-align="center" label="序号" type="index" width="80">
<template scope="scope">
<span>{{ scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1 }} </span>
@@ -59,7 +63,7 @@ layout("/layouts/platform.html"){
查看
</el-button>
<el-button type="primary" size="mini"
v-if="row.executorOpinion==null && row.resultCode!='notGive'"
v-if="row.executorOpinion==null && row.resultCode!='notGive' && false"
@click="openAudit(row.id,row)">
审核
</el-button>
@@ -317,6 +321,7 @@ layout("/layouts/platform.html"){
this.proTableData.unshift(row)
},
async batchAudit() {
this.batchSelection = this.tableData
if (this.batchSelection.length === 0) {
this.$notify.warning('请选择需要批量审核的记录')
return
@@ -345,13 +350,18 @@ layout("/layouts/platform.html"){
proposalIds: this.formData.proposalId,
sign: this.formData.sign,
determineTypeCode: this.formData.determineTypeCode
})
requestLaterFun(resp, () => {
this.$notify.success({title: '成功', message: resp.msg});
this.pageData()
this.$refs.guava.index()
const sendTask = resp.data.sendTask
console.log('sendTask', sendTask)
if(sendTask) {
this.sendToDoTaskInfo()
}
}, () => {
this.$notify.error({title: '失败', message: resp.msg});
}, () => {
@@ -380,18 +390,26 @@ layout("/layouts/platform.html"){
if (this.batchSelection && this.batchSelection.length > 0) {
proposalIds = this.batchSelection.map(v => v.id)
}
const resp = await $.post(loc() + "/audit", {
audit: JSON.stringify(this.formData),
proposalIds: JSON.stringify(proposalIds),
sign: this.formData.sign,
determineTypeCode: this.formData.determineTypeCode
})
requestLaterFun(resp, () => {
this.$notify.success({title: '成功', message: resp.msg});
this.pageData()
this.batchDialog = false
this.batchSelection = []
this.$refs.guava.index()
const sendTask = resp.data.sendTask
console.log('sendTask', sendTask)
if(sendTask) {
this.sendToDoTaskInfo()
}
}, () => {
this.$notify.error({title: '失败', message: resp.msg});
}, () => {
@@ -401,6 +419,23 @@ layout("/layouts/platform.html"){
}
},
// 发送待办
async sendToDoTaskInfo () {
const confirm = await this.$confirm('确定发送待办到校长、书记吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
const resp = await $.post(loc() + '/sendToDoTaskInfo')
if(resp.code != 0) {
this.$message.error(resp.msg)
} else {
this.$message.success(resp.msg)
}
},
async rollback(id) {
const confirm = await this.$confirm('您确定要撤回吗?', '提示', {
confirmButtonText: '确定',
@@ -16,15 +16,18 @@ layout("/layouts/platform.html"){
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="batchAudit">批量审核
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="sendToDoTaskInfo">发送待办
</el-button>
</template>
</table-tool>
<el-table :data="tableData" align="center" header-align="center" :row-key="(row)=>{row.id}"
:size="tableSize"
@sort-change="pageOrder" @selection-change="(val)=>{this.batchSelection = val}">
<el-table-column
:selectable="(row)=>{return row.executorOpinionConfirm==null && row.resultCode!='notGive'}"
type="selection"
width="55"></el-table-column>
<!-- <el-table-column-->
<!-- :selectable="(row)=>{return row.executorOpinionConfirm==null && row.resultCode!='notGive'}"-->
<!-- type="selection"-->
<!-- width="55"></el-table-column>-->
<el-table-column align="center" header-align="center" label="序号" type="index" width="80">
<template scope="scope">
<span>{{ scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1 }} </span>
@@ -59,7 +62,7 @@ layout("/layouts/platform.html"){
查看
</el-button>
<el-button type="primary" size="mini"
v-if="row.executorOpinionConfirm==null && row.resultCode!='notGive'"
v-if="row.executorOpinionConfirm==null && row.resultCode!='notGive' && false"
@click="openAudit(row.id,row)">
审核
</el-button>
@@ -316,6 +319,7 @@ layout("/layouts/platform.html"){
this.proTableData.unshift(row)
},
async batchAudit() {
this.batchSelection = this.tableData
if (this.batchSelection.length === 0) {
this.$notify.warning('请选择需要批量审核的记录')
return
@@ -350,6 +354,12 @@ layout("/layouts/platform.html"){
this.$notify.success({title: '成功', message: resp.msg});
this.pageData()
this.$refs.guava.index()
const sendTask = resp.data.sendTask
console.log('sendTask', sendTask)
if(sendTask) {
this.sendToDoTaskInfo()
}
}, () => {
this.$notify.error({title: '失败', message: resp.msg});
}, () => {
@@ -390,6 +400,12 @@ layout("/layouts/platform.html"){
this.batchDialog = false
this.batchSelection = []
this.$refs.guava.index()
const sendTask = resp.data.sendTask
console.log('sendTask', sendTask)
if(sendTask) {
this.sendToDoTaskInfo()
}
}, () => {
this.$notify.error({title: '失败', message: resp.msg});
}, () => {
@@ -399,6 +415,23 @@ layout("/layouts/platform.html"){
}
},
// 发送待办
async sendToDoTaskInfo (isConfirm) {
const confirm = await this.$confirm('确定发送待办到提案委确认承办单位吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
const resp = await $.post(loc() + '/sendToDoTaskInfo')
if(resp.code != 0) {
this.$message.error(resp.msg)
} else {
this.$message.success(resp.msg)
}
},
async rollback(id) {
const confirm = await this.$confirm('您确定要撤回吗?', '提示', {
confirmButtonText: '确定',
@@ -316,6 +316,19 @@ layout("/layouts/platform.html"){
this.$refs['auditForm'].resetFields()
}
},
async autoOpenAuditPage() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
if(proposalId && proposalId !== '') {
const res = await $.post('/platform/proposal/transact/feedback/detail?proposalId=' + proposalId)
console.log(res)
setTimeout(async ()=> {
await this.openFeedback(res.data)
}, 500)
}
},
async doFeedback() {
this.$refs["auditForm"].validate(async (valid) => {
if (valid) {
@@ -357,6 +370,8 @@ layout("/layouts/platform.html"){
await proposal.initData(this)
this.feedbackOptions = await getDictByCode("proposal_feedback")
this.feedbackOptionsByUnderTakeOptions = await getDictByCode('proposal_feedback_underTake')
await this.autoOpenAuditPage()
}
})
</script>
@@ -402,6 +402,19 @@ layout("/layouts/platform.html"){
this.$refs['auditForm'].resetFields()
}
},
async autoOpenAuditPage() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
if(proposalId && proposalId !== '') {
const res = await $.post('/platform/proposal/transact/leader/leaderAudit/detail?proposalId=' + proposalId)
console.log(res)
setTimeout(async ()=> {
await this.openAudit(res.data)
}, 500)
}
},
async doAudit(flag) {
let formValid = true
this.$refs["auditForm"].validate(valid => {
@@ -443,6 +456,8 @@ layout("/layouts/platform.html"){
async created() {
this.isNode = await proposal.getProposalIsNodeState(600)
await proposal.initData(this)
await this.autoOpenAuditPage()
}
})
</script>
@@ -16,15 +16,18 @@ layout("/layouts/platform.html"){
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="batchAudit">批量审核
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
@click="sendToDoTaskInfo(true)">发送待办
</el-button>
</template>
</table-tool>
<el-table :data="tableData" align="center" header-align="center" :row-key="(row)=>{row.id}"
:size="tableSize"
@sort-change="pageOrder" @selection-change="(val)=>{this.batchSelection = val}">
<el-table-column
:selectable="(row)=>{return row.secretaryOpinions==null && row.resultCode!='notGive'}"
type="selection"
width="55"></el-table-column>
<!-- <el-table-column-->
<!-- :selectable="(row)=>{return row.secretaryOpinions==null && row.resultCode!='notGive'}"-->
<!-- type="selection"-->
<!-- width="55"></el-table-column>-->
<el-table-column align="center" header-align="center" label="序号" type="index" width="80">
<template scope="scope">
<span>{{ scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1 }} </span>
@@ -65,12 +68,12 @@ layout("/layouts/platform.html"){
查看
</el-button>
<el-button type="primary" size="mini"
v-if="${@shiro.hasRole('principal')} && row.secretaryOpinions==null && row.resultCode!='notGive'"
v-if="${@shiro.hasRole('principal')} && row.secretaryOpinions==null && row.resultCode!='notGive'&& false"
@click="openAudit(row)">
审阅
</el-button>
<el-button type="primary" size="mini"
v-if="${@shiro.hasRole('secretary')} && row.secretaryOpinionsAgain==null && row.resultCode!='notGive'"
v-if="${@shiro.hasRole('secretary')} && row.secretaryOpinionsAgain==null && row.resultCode!='notGive' && false"
@click="openAudit(row)">
审阅
</el-button>
@@ -273,6 +276,7 @@ layout("/layouts/platform.html"){
},
async batchAudit() {
this.batchSelection = this.tableData
if (this.batchSelection.length === 0) {
this.$notify.warning('请选择需要批量审核的记录')
return
@@ -302,6 +306,9 @@ layout("/layouts/platform.html"){
this.notifySuccess(resp.msg)
this.pageData()
this.$refs.guava.index()
// 发送待办
await this.sendToDoTaskInfo(false);
} else {
this.notifyWarning(resp.msg)
}
@@ -331,6 +338,9 @@ layout("/layouts/platform.html"){
this.batchDialog = false
this.batchSelection = []
this.$refs.guava.index()
// 发送待办
this.sendToDoTaskInfo(false);
}, () => {
this.$notify.error({title: '失败', message: resp.msg});
}, () => {
@@ -339,6 +349,25 @@ layout("/layouts/platform.html"){
})
}
},
// 发送待办
async sendToDoTaskInfo (isConfirm) {
if(isConfirm) {
const confirm = await this.$confirm('确定发送待办到执委会主任吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
}
const resp = await $.post(loc() + '/sendToDoTaskInfo')
if(resp.code != 0) {
this.$message.error(resp.msg)
} else {
this.$message.success(resp.msg)
}
},
async rollback(id) {
const confirm = await this.$confirm('您确定要撤回吗?', '提示', {
confirmButtonText: '确定',
@@ -578,6 +578,22 @@ layout("/layouts/platform.html"){
this.$refs['auditForm'].resetFields()
}
},
async autoOpenAuditPage() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
const underTakeType = urlParams.get('underTakeType');
if(proposalId && proposalId !== '' && underTakeType && underTakeType !== '') {
const res = await $.post('/platform/proposal/transact/reply/detail?underTakeType=' + underTakeType + '&proposalId=' + proposalId)
console.log(res)
setTimeout(async ()=> {
await this.openAudit(res.data)
}, 500)
}
},
async doReply(isSave) {
try {
const valid = await this.$refs["auditForm"].validate()
@@ -630,6 +646,8 @@ layout("/layouts/platform.html"){
await proposal.initData(this)
this.implementStateOptions = await getDictByCode('proposal_reply_result')
this.getLeaders()
await this.autoOpenAuditPage()
}
})
</script>
@@ -230,6 +230,17 @@ layout("/layouts/platform.html"){
this.formData.createUser = row.createUser
this.$refs.guava.edit()
this.$refs.audit.openView(row.id)
console.log(this.formData)
},
async outToOpenAudit(rowId) {
const res = await $.post('/platform/proposal/transact/seconded/detail?proposalId=' + rowId);
console.log('详情-->', res)
if(!res.data) {
return
}
setTimeout(async ()=> {
await this.openAudit(res.data)
}, 500)
},
async doAudit(flag) {
const flagText = flag ? '同意' : '拒绝'
@@ -269,6 +280,17 @@ layout("/layouts/platform.html"){
},
async created() {
await proposal.initData(this)
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const proposalId = urlParams.get('proposalId')
const isAudit = urlParams.get('isAudit')
console.log('urlParams-->', proposalId, isAudit)
console.log((!isAudit || isAudit === false || isAudit === 'false'))
console.log(proposalId && proposalId !== '')
if((!isAudit || isAudit === false || isAudit === 'false') && proposalId && proposalId !== '') {
await this.outToOpenAudit(proposalId)
}
}
})
</script>
@@ -136,11 +136,13 @@ layout("/layouts/platform.html"){
</el-row>
<el-form-item class="is-required" label="提案内容" prop="brief">
<div id="briefEditor"></div>
<text-editor v-model="formData.brief"></text-editor>
<!-- <div id="briefEditor"></div>-->
</el-form-item>
<el-form-item class="is-required" label="可行性分析" prop="measures">
<div id="measuresEditor"></div>
<!-- <div id="measuresEditor"></div>-->
<text-editor v-model="formData.measures"></text-editor>
</el-form-item>
<el-form-item label="附件上传" prop="files">
@@ -573,17 +575,22 @@ layout("/layouts/platform.html"){
data: JSON.stringify(data),
sign: data.sign
})
await this.editProposal()
this.pageForm2.proposalId = this.formData.id ? this.formData.id : resp.data
if (resp.data) {
this.formData.id = resp.data
if (resp.code===0){
await this.editProposal()
this.pageForm2.proposalId = this.formData.id ? this.formData.id : resp.data
if (resp.data) {
this.formData.id = resp.data
}
this.pageForm2.proposalName = this.formData.proposalName
await this.queryDb()
await this.getProposalSecondedNum()
this.$refs.guava.public()
}else{
this.$message.warning(resp.msg)
}
this.pageForm2.proposalName = this.formData.proposalName
await this.queryDb()
await this.getProposalSecondedNum()
this.$refs.guava.public()
// sublime.jumpPagePjax('/platform/proposal/transact/compose?operation=invite&id=' + resp.data)
}
@@ -763,7 +770,7 @@ layout("/layouts/platform.html"){
mannerCode: 'W01'
}
this.$nextTick(() => {
/* this.$nextTick(() => {
$("#briefEditor").html("")
$("#measuresEditor").html("")
@@ -777,7 +784,7 @@ layout("/layouts/platform.html"){
}
briefEditor.create()
measuresEditor.create()
})
})*/
if (this.$refs["addForm"])
this.$refs["addForm"].resetFields();
@@ -800,10 +807,10 @@ layout("/layouts/platform.html"){
resp.data.files = JSON.parse(resp.data.files)
}
this.formData = resp.data
this.$nextTick(() => {
/*this.$nextTick(() => {
briefEditor.txt.html(resp.data.brief)
measuresEditor.txt.html(resp.data.measures)
})
})*/
}
},
@@ -3,20 +3,31 @@ const todo = {
<div class="home-todo">
<el-tabs v-model="todoActive " @tab-click="handleClick">
<el-tab-pane label="待处理" name="1">
<template slot="label">
<span>待处理</span>
<el-badge v-if="waitHandleCount > 0" :value="waitHandleCount" :max="99" class="item" style="margin-top:10px;">
</el-badge>
</template>
<el-table :data="todoList" v-loading="todoLoading">
<el-table-column label="序号" type="index" width="70"></el-table-column>
<el-table-column label="标题" prop="processName" show-overflow-tooltip
width="200"></el-table-column>
<el-table-column label="发起人" prop="createdByUserName"
width="140"></el-table-column>
<el-table-column label="发起时间" prop="createdOn" v-if="todoActive==='3'"
<el-table-column label="标题" prop="title" show-overflow-tooltip
width="150"></el-table-column>
<el-table-column label="我的处理环节" prop="taskNodeName"
v-if="todoActive!=='3'"></el-table-column>
<el-table-column label="流程流转环节" prop="nodeName"></el-table-column>
<el-table-column label="发起人" prop="create_name"
width="140"></el-table-column>
<el-table-column label="发起时间" prop="create_time"
width="200"></el-table-column>
<el-table-column label="状态" prop="status" width="100">
<template scope="{row}">
{{ status[row.status] }}
</template>
</el-table-column>
<!-- <el-table-column label="我的处理环节" prop="taskNodeName"-->
<!-- v-if="todoActive!=='3'"></el-table-column>-->
<!-- <el-table-column label="流程流转环节" prop="nodeName"></el-table-column>-->
<el-table-column label="操作" width="100">
<template scope="{row}">
<el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>
<!-- <el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>-->
<el-button @click="handleTask(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
@@ -24,40 +35,70 @@ const todo = {
<el-tab-pane label="已处理" name="2">
<el-table :data="todoList" v-loading="todoLoading">
<el-table-column label="序号" type="index" width="70"></el-table-column>
<el-table-column label="标题" prop="processName" show-overflow-tooltip
<el-table-column label="标题" prop="title" show-overflow-tooltip
width="100"></el-table-column>
<el-table-column label="发起人" prop="create_name"
width="100"></el-table-column>
<el-table-column label="发起时间" prop="create_time"
width="200"></el-table-column>
<el-table-column label="发起人" prop="createdByUserName"
width="140"></el-table-column>
<el-table-column label="发起时间" prop="createdOn" v-if="todoActive==='3'"
width="150"></el-table-column>
<el-table-column label="我的处理环节" prop="taskNodeName"
v-if="todoActive!=='3'"></el-table-column>
<el-table-column label="流程流转环节" prop="nodeName"></el-table-column>
<el-table-column label="状态" prop="status" width="100">
<template scope="{row}">
{{ status[row.status] }}
</template>
</el-table-column>
<!-- <el-table-column label="我的处理环节" prop="taskNodeName"-->
<!-- v-if="todoActive!=='3'"></el-table-column>-->
<!-- <el-table-column label="流程流转环节" prop="nodeName"></el-table-column>-->
<el-table-column label="操作" width="100">
<template scope="{row}">
<el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>
<!-- <el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>-->
<el-button @click="handleTask(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="loadCompleteHandle"
@current-change="loadCompleteHandle"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount">
</el-pagination>
</el-tab-pane>
<el-tab-pane label="我的发起" name="3">
<el-table :data="todoList" v-loading="todoLoading">
<el-table-column label="序号" type="index" width="70"></el-table-column>
<el-table-column label="标题" prop="processName" show-overflow-tooltip
<el-table-column label="标题" prop="title" show-overflow-tooltip
width="100"></el-table-column>
<el-table-column label="发起人" prop="create_name"
width="100"></el-table-column>
<el-table-column label="发起时间" prop="create_time" v-if="todoActive==='3'"
width="200"></el-table-column>
<el-table-column label="发起人" prop="createdByUserName"
width="140"></el-table-column>
<el-table-column label="发起时间" prop="createdOn" v-if="todoActive==='3'"
width="150"></el-table-column>
<el-table-column label="我的处理环节" prop="taskNodeName"
v-if="todoActive!=='3'"></el-table-column>
<el-table-column label="流程流转环节" prop="nodeName"></el-table-column>
<el-table-column label="状态" prop="status" width="100">
<template scope="{row}">
{{ status[row.status] }}
</template>
</el-table-column>
<!-- <el-table-column label="我的处理环节" prop="taskNodeName"-->
<!-- v-if="todoActive!=='3'"></el-table-column>-->
<!-- <el-table-column label="流程流转环节" prop="nodeName"></el-table-column>-->
<el-table-column label="操作" width="100">
<template scope="{row}">
<el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>
<!-- <el-button @click="sublime.jumpPagePjax(row.formUrl)" size="mini" type="primary">查看</el-button>-->
<el-button @click="handleTask(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="loadMineSendTask"
@current-change="loadMineSendTask"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount">
</el-pagination>
</el-tab-pane>
</el-tabs>
<!-- <el-table :data="todoList" style="min-height: 250px" v-loading="todoLoading">-->
@@ -83,7 +124,43 @@ const todo = {
data() {
return {
todoActive: "1",
todoList:[]
todoList:[],
todoLoading: false,
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0
},
status:['草稿', '待处理', '已处理', '已驳回', '已撤回'],
waitHandleCount: 0
}
},
watch: {
todoActive: {
async handler(val) {
console.log("val--->", val)
this.pageForm = {
pageNumber: 1,
pageSize: 10,
totalCount: 0
}
this.todoList = []
try{
this.todoLoading = true
if(Number(val) === 1) {
await this.loadWaitHandle()
} else if(Number(val) === 2) {
await this.loadCompleteHandle()
} else if(Number(val) === 3) {
await this.loadMineSendTask()
}
this.todoLoading = false
} catch (e) {
this.todoLoading = false
}
}
}
},
methods: {
@@ -92,9 +169,55 @@ const todo = {
/* const {data, code} = await $.get("/platform/sys/localProcess/todoList", { mode: this.todoActive })
this.todoList = data*/
this.todoLoading = false
},
// 加载待处理数据
async loadWaitHandle() {
const res = await $.post('/oa/audit/instance/wait/handle')
console.log("待处理数据->", res)
if(res.code === 0) {
this.todoList = res.data
this.waitHandleCount = this.todoList.length
}
},
// 加载已办数据
async loadCompleteHandle() {
const res = await $.post('/oa/audit/instance/complete/handle', { ...this.pageForm })
console.log("已处理数据->", res)
this.todoList = res.list
this.pageForm.pageNumber = res.pageNo
this.pageForm.pageSize = res.pageSize
this.pageForm.totalCount = res.totalCount
},
// 加载我发起的
async loadMineSendTask() {
const res = await $.post('/oa/audit/instance/mine/send', { ...this.pageForm })
console.log("我发起数据->", res)
this.todoList = res.list
this.pageForm.pageNumber = res.pageNo
this.pageForm.pageSize = res.pageSize
this.pageForm.totalCount = res.totalCount
},
// 待处理任务处理
async handleTask(row) {
if(this.todoActive === '1') {
const urlObj = new URL(row.url)
console.log(urlObj)
window.location.href = urlObj.pathname + urlObj.search
} else {
const urlObj = new URL(row.done_url)
console.log(urlObj)
window.location.href = urlObj.pathname + urlObj.search
}
}
},
created() {
this.handleClick()
// 待处理
this.loadWaitHandle()
}
}
@@ -1100,7 +1100,7 @@ layout("/layouts/platform.html"){
}
},
async getLimitUnionData() {
const resp = await $.get('/platform/trainSingUp/manage/activity/getUnionLimit')
const resp = await $.get('/platform/trainSingUp/manage/activity/add/getUnionLimit')
this.unionUserNumberLimit = resp.data
}
},