commit
This commit is contained in:
@@ -32,6 +32,8 @@ public class RedisConstant {
|
||||
// 短信token
|
||||
public final static String REDIS_SMS_TOKEN_KEY = PLATFORM_REDIS_PREFIX + "platfrom:sms:token:";
|
||||
|
||||
public final static String REDIS_TODO_TOKEN_KEY = PLATFORM_REDIS_PREFIX + "platfrom:todo:token:";
|
||||
|
||||
public final static String REDIS_KEY_API_SIGN_DEPLOY_NONCE = PLATFORM_REDIS_PREFIX + "api:sign:deploy:nonce:";
|
||||
public final static String REDIS_KEY_API_SIGN_OPEN_NONCE = PLATFORM_REDIS_PREFIX + "api:sign:open:nonce:";
|
||||
|
||||
|
||||
@@ -2,12 +2,131 @@ package com.budwk.app.base.sms;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信/消息发送服务接口
|
||||
* 保持参数直观可见,调用者无需查看实体类即可知晓参数含义
|
||||
*/
|
||||
public interface SmsService {
|
||||
|
||||
/**
|
||||
* 单发
|
||||
* @param loginName 工号
|
||||
* @param content 内容
|
||||
*/
|
||||
void send(String loginName, String content);
|
||||
/**
|
||||
* 单发普通消息(无标题)
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param content 消息内容(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSingleMessage(String loginName, String content);
|
||||
|
||||
/**
|
||||
* 单发普通消息(带标题)
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param title 消息标题(可选,可为null)
|
||||
* @param content 消息内容(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSingleMessage(String loginName, String title, String content);
|
||||
|
||||
/**
|
||||
* 单发文本卡片消息
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl);
|
||||
|
||||
/**
|
||||
* 单发文本卡片消息(带标题)
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param title 卡片标题(可选,可为null)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl);
|
||||
|
||||
/**
|
||||
* 单发图文卡片消息
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @param picUrl 图片链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl);
|
||||
|
||||
/**
|
||||
* 单发图文卡片消息(带标题)
|
||||
* @param loginName 接收人工号(必填)
|
||||
* @param title 卡片标题(可选,可为null)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @param picUrl 图片链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl);
|
||||
|
||||
/**
|
||||
* 群发普通消息(多人接收相同内容)
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param content 消息内容(必填)
|
||||
* @return void
|
||||
*/
|
||||
void massSendMessage(List<String> loginNames, String content);
|
||||
|
||||
/**
|
||||
* 群发普通消息(多人接收相同内容)
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param title 消息标题(可选,可为null)
|
||||
* @param content 消息内容(必填)
|
||||
* @return void
|
||||
*/
|
||||
void massSendMessage(List<String> loginNames, String title, String content);
|
||||
|
||||
/**
|
||||
* 群发短信文本卡片消息
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl);
|
||||
|
||||
/**
|
||||
* 群发短信文本卡片消息
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param title 卡片标题(可选,可为null)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl);
|
||||
|
||||
/**
|
||||
* 群发图文卡片消息
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @param picUrl 图片链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl);
|
||||
|
||||
/**
|
||||
* 群发图文卡片消息
|
||||
* @param loginNames 接收人工号列表(必填,不能为空列表)
|
||||
* @param title 卡片标题(可选,可为null)
|
||||
* @param content 卡片内容(必填)
|
||||
* @param pcUrl PC端跳转链接(必填)
|
||||
* @param mobileUrl 移动端跳转链接(必填)
|
||||
* @param picUrl 图片链接(必填)
|
||||
* @return
|
||||
*/
|
||||
void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,171 @@
|
||||
package com.budwk.app.base.sms.impl.ncu;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.sms.SmsService;
|
||||
import com.budwk.app.base.sms.impl.ncu.util.SmsTokenUtil;
|
||||
import com.budwk.app.web.commons.base.Globals;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.Lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* 南昌大学短信实现
|
||||
*/
|
||||
@IocBean
|
||||
@Slf4j
|
||||
@IocBean
|
||||
public class SmsNcuServiceImpl implements SmsService {
|
||||
|
||||
private static final String SEND_MSG_URL = "https://api.ucpass.cn/sms/send";
|
||||
private static final String APP_ID = "";
|
||||
@Inject
|
||||
private SmsTokenUtil smsTokenUtil;
|
||||
|
||||
private static final String SEND_MSG_URL = "https://poa.ncu.edu.cn/apis/messagecenter/v1/poaMessage/messageSend";
|
||||
private static final String APP_ID = "72e34a101d3011f1a74cbae5193504f4";
|
||||
private static final String TEMPLATE_ID = "MT1773223005000";
|
||||
|
||||
@Override
|
||||
public void send(String loginName, String content) {
|
||||
String token = SmsTokenUtil.getToken();
|
||||
}
|
||||
@Override
|
||||
public void sendSingleMessage(String loginName, String content) {
|
||||
this.sendSingleMessage(loginName, "智慧工会", content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSingleMessage(String loginName, String title, String content) {
|
||||
this.massSendMessage(List.of(loginName), title, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) {
|
||||
this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) {
|
||||
this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) {
|
||||
this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
|
||||
this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendMessage(List<String> loginNames, String content) {
|
||||
this.massSendMessage(loginNames, "智慧工会", content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendMessage(List<String> loginNames, String title, String content) {
|
||||
String list = String.join(",", loginNames);
|
||||
this.doSend("text", list, title, content, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl) {
|
||||
this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) {
|
||||
String list = String.join(",", loginNames);
|
||||
this.doSend("textCard", list, title, content, pcUrl, mobileUrl, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl) {
|
||||
this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
|
||||
String list = String.join(",", loginNames);
|
||||
this.doSend("news", list, title, content, pcUrl, mobileUrl, picUrl);
|
||||
}
|
||||
|
||||
private void doSend(String sendType,
|
||||
String receivers,
|
||||
String title,
|
||||
String content,
|
||||
String pcUrl,
|
||||
String mobileUrl,
|
||||
String picUrl) {
|
||||
if(!Globals.sso) {
|
||||
log.error("【log】本地开发模式不允许调用消息接口");
|
||||
return;
|
||||
}
|
||||
if(!Globals.MyConfig.getBoolean("AppNotify", false)) {
|
||||
log.error("【log】消息配置未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Lang.isEmpty(receivers)) {
|
||||
log.error("【log】send fail by receivers is null");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String token = smsTokenUtil.getToken();
|
||||
if (Lang.isEmpty(token)) {
|
||||
log.error("【log】send fail by token is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("appId", APP_ID);
|
||||
params.put("sendId", "");
|
||||
params.put("sendType", Stream.of("WECHAT").toArray());
|
||||
params.put("messageTypeCode", TEMPLATE_ID);
|
||||
params.put("promise", false);
|
||||
params.put("importantIdentity", false);
|
||||
params.put("toPersons", receivers);
|
||||
|
||||
Map<String, Object> dataParams = new HashMap<>();
|
||||
dataParams.put("title", title);
|
||||
dataParams.put("paramValueJson", Map.of("content", content));
|
||||
|
||||
if ("textCard".equals(sendType)) {
|
||||
dataParams.put("url", pcUrl);
|
||||
dataParams.put("mobileUrl", mobileUrl);
|
||||
}
|
||||
if ("news".equals(sendType)) {
|
||||
dataParams.put("url", pcUrl);
|
||||
dataParams.put("mobileUrl", mobileUrl);
|
||||
dataParams.put("coverImageUrl", picUrl);
|
||||
}
|
||||
params.put("data", dataParams);
|
||||
|
||||
log.info("【log】发送消息通知,请求参数:{}", Json.toJson(params));
|
||||
String body = HttpUtil.createPost(SEND_MSG_URL)
|
||||
.header("Authorization", token)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Json.toJson(params)).execute().body();
|
||||
JSONObject resultJsonBody = JSONUtil.parseObj(body);
|
||||
log.info("【log】发送消息通知,接口响应数据:{}", body);
|
||||
|
||||
if (resultJsonBody.getInt("code") == 0) {
|
||||
log.info("【log】发送消息通知成功");
|
||||
JSONObject data = resultJsonBody.getJSONObject("data");
|
||||
String sendId = data.getStr("sendId");
|
||||
System.out.println(sendId);
|
||||
} else {
|
||||
log.info("【log】发送消息通知失败:{}", resultJsonBody.getStr("message"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("【log】发送消息通知失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,13 @@ import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RedisConstant;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.integration.jedis.RedisService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.mvc.Mvcs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -18,21 +23,19 @@ import java.util.Map;
|
||||
* @Date 2025/12/3 9:53
|
||||
* @注释 :短信token工具类
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean
|
||||
public class SmsTokenUtil {
|
||||
|
||||
@Inject
|
||||
private static RedisService redisService;
|
||||
private RedisService redisService;
|
||||
|
||||
private static final String TOKEN_URL = "https://api.ucpass.cn/token";
|
||||
private static final String TOKEN_URL = "https://poa.ncu.edu.cn/oauth2/token";
|
||||
private static final String CLINT_ID = "dP7SXC1MoYAJHPh6k8Cgsda8tGY=";
|
||||
private static final String CLINT_SECRET = "PFAwVcXOsVFzP3Jwb4RyO5V97o8j8zNTQ8QSTre8oIc=";
|
||||
private static final String SCOPE = "messagecenter:v1:sendMessage";
|
||||
|
||||
private static final String CLINT_ID = "";
|
||||
|
||||
private static final String CLINT_SECRET = "";
|
||||
|
||||
private static final String SCOPE = "";
|
||||
|
||||
|
||||
public static String getToken() {
|
||||
public String getToken() {
|
||||
String key = RedisConstant.REDIS_SMS_TOKEN_KEY;
|
||||
String token = redisService.get(key);
|
||||
if (StrUtil.isBlank(token)) {
|
||||
@@ -48,7 +51,8 @@ public class SmsTokenUtil {
|
||||
.formStr(param).execute().body();
|
||||
|
||||
JSONObject resultJsonBody = JSONUtil.parseObj(body);
|
||||
if (resultJsonBody.getInt("code") == 200) {
|
||||
log.info("【log】获取消息token接口回调数据:{}", Json.toJson(resultJsonBody));
|
||||
if (StrUtil.isNotBlank(resultJsonBody.getStr("access_token"))) {
|
||||
String accessToken = resultJsonBody.getStr("access_token");
|
||||
Integer expiresIn = resultJsonBody.getInt("expires_in");
|
||||
redisService.setex(key, expiresIn, accessToken);
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.budwk.app.flow.service.FlowCommonService;
|
||||
import com.budwk.app.flow.vo.HighLightVO;
|
||||
import com.budwk.app.flow.vo.ProcessInstanceVO;
|
||||
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||
import com.budwk.app.todo.service.TodoService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -52,6 +53,8 @@ public class FlowCommonController {
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private FlowCommonService flowCommonService;
|
||||
@Inject
|
||||
private TodoService todoService;
|
||||
|
||||
@At("/approval/form")
|
||||
@SaCheckLogin
|
||||
@@ -281,6 +284,7 @@ public class FlowCommonController {
|
||||
// 发送任务撤回事件 确保上面执行成功
|
||||
for (ProcessTask task : taskList) {
|
||||
ProcessPublisher.notify(ProcessEvent.builder().eventType(ProcessEventTypeEnum.PROCESS_TASK_REVOKE).sourceId(task.getId()).build());
|
||||
todoService.taskTerminate(task);
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.budwk.app.flow.listenter;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.budwk.app.flow.engine.event.ProcessEvent;
|
||||
import com.budwk.app.flow.engine.event.ProcessEventListener;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
|
||||
import com.budwk.app.todo.service.TodoService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -16,12 +18,19 @@ public class ProcessTaskEndEventListener implements ProcessEventListener {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private TodoService todoService;
|
||||
|
||||
@Override
|
||||
public void onEvent(ProcessEvent event) {
|
||||
if (event.getEventType() == ProcessEventTypeEnum.PROCESS_TASK_END) {
|
||||
Long sourceId = event.getSourceId();
|
||||
ProcessTask task = dao.fetch(ProcessTask.class, sourceId);
|
||||
|
||||
// 好了,任务完成,就可以调接口完成待办了
|
||||
if (!ObjectUtil.equals(0, task.getTaskParentId().intValue())) {
|
||||
todoService.taskHandle(task);
|
||||
}
|
||||
System.out.println("流程任务完成事件:" + task.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.flow.listenter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.event.ProcessEvent;
|
||||
import com.budwk.app.flow.engine.event.ProcessEventListener;
|
||||
@@ -8,6 +9,8 @@ import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.entity.ProcessTaskActor;
|
||||
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
|
||||
import com.budwk.app.todo.service.TodoService;
|
||||
import com.budwk.app.web.commons.base.Globals;
|
||||
import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -30,6 +33,8 @@ public class ProcessTaskStartEventListener implements ProcessEventListener {
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private GlobalMessageSendService globalMessageSendService;
|
||||
@Inject
|
||||
private TodoService todoService;
|
||||
|
||||
@Override
|
||||
public void onEvent(ProcessEvent event) {
|
||||
@@ -58,13 +63,23 @@ public class ProcessTaskStartEventListener implements ProcessEventListener {
|
||||
List<ProcessTaskActor> taskActors = dao.query(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId()));
|
||||
|
||||
for (ProcessTaskActor taskActor : taskActors) {
|
||||
|
||||
JSONObject config = new JSONObject();
|
||||
config.set("pcUrl", Globals.AppDomain + task.getFormKey());
|
||||
|
||||
// 模拟发送消息
|
||||
String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", taskActor.getActorName(), instanceName, taskDisplayName);
|
||||
log.info(message);
|
||||
String message = "";
|
||||
if(StrUtil.isNotBlank(task.getH5FormKey())) {
|
||||
config.set("mobileUrl", Globals.AppDomain + task.getH5FormKey());
|
||||
message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}。", instanceName, taskDisplayName);
|
||||
} else {
|
||||
config.set("mobileUrl", Globals.AppDomain + "/platform/tooltip/h5");
|
||||
message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{},请到电脑端智慧工会系统审核。", instanceName, taskDisplayName);
|
||||
}
|
||||
log.info(message);
|
||||
|
||||
globalMessageSendService.sendMessage(taskDisplayName, message, 2, List.of(taskActor.getActorId()), null);
|
||||
}
|
||||
|
||||
|
||||
todoService.addTransaction(task);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.expression.ExpressionUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.vo.LabelValueVO;
|
||||
@@ -32,6 +31,8 @@ import com.budwk.app.flow.service.ProcessTaskService;
|
||||
import com.budwk.app.flow.vo.HighLightVO;
|
||||
import com.budwk.app.flow.vo.ProcessInstanceVO;
|
||||
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||
import com.budwk.app.todo.service.TodoService;
|
||||
import com.budwk.app.todo.service.impl.TodoServiceImpl;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
@@ -42,7 +43,9 @@ 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;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.Mvcs;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -281,7 +284,7 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
|
||||
List<ProcessTask> processTaskList = flowEngine.processTaskService().getDoingTaskList(processInstanceId, new String[]{});
|
||||
// 拿到历史任务-按更新时间倒序
|
||||
List<ProcessTask> hisProcessTaskList = flowEngine.processTaskService().query(Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId).desc(ProcessTask::getUpdatedAt));
|
||||
processTaskList.forEach(task -> {
|
||||
processTaskList.forEach(task -> {
|
||||
if (!vo.getActiveNodeNames().contains(task.getTaskName())) {
|
||||
vo.getActiveNodeNames().add(task.getTaskName());
|
||||
recursionModel(processModel.getStart(), processInstance, processTaskList, hisProcessTaskList, task.getTaskName(), vo);
|
||||
@@ -556,6 +559,14 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
|
||||
public void deleteProcessInstanceById(Long processInstanceId) {
|
||||
List<ProcessTask> taskList = dao().query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId));
|
||||
List<Long> taskIds = taskList.stream().map(ProcessTask::getId).toList();
|
||||
|
||||
// 删除学校待办
|
||||
if(Lang.isNotEmpty(taskList)) {
|
||||
ProcessTask task = taskList.get(taskList.size() - 1);
|
||||
TodoService todoService = Mvcs.getIoc().get(TodoServiceImpl.class);
|
||||
todoService.deleteProcessInstance(task);
|
||||
}
|
||||
|
||||
dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getId, "in", taskIds));
|
||||
dao().clear(ProcessInstance.class, Cnd.where(ProcessInstance::getId, "=", processInstanceId));
|
||||
}
|
||||
|
||||
+4
-4
@@ -32,10 +32,10 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy {
|
||||
return true; // 短信发送支持异步
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean isEnabled() {
|
||||
// return true;
|
||||
// }
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String title, String content, Integer type, List<String> receiverIds, JSONObject config) {
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
package com.budwk.app.zhgh.democratic.executiveCommittee.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.executiveCommittee.models.ExecutiveCommitteeTwoPush;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.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.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author zhf
|
||||
* @date 2026/3/20 10:51
|
||||
* @description 正式委员录入
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/executiveCommittee/formalPush")
|
||||
@Ok("json:full")
|
||||
@Slf4j
|
||||
@Api(tags = "执委会推选-正式委员录入")
|
||||
public class ExecutiveCommitteeFormalPushController {
|
||||
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private BaseService baseService;
|
||||
|
||||
@At("/index")
|
||||
@SaCheckPermission("executiveCommittee.formalPush")
|
||||
@Ok("beetl:/platform/zhgh/democratic/executiveCommittee/formalPush/index.html")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@ApiOperation("分页查询")
|
||||
@SaCheckPermission("executiveCommittee.formalPush")
|
||||
public Result pageData(PageForm pageForm,
|
||||
String teacherMeetId,
|
||||
String delegationId,
|
||||
String unionId,
|
||||
String roleCode) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t1.*,
|
||||
t2.loginName,
|
||||
t2.userName,
|
||||
t3.name AS unitName,
|
||||
t4.name unionName,
|
||||
t5.sex,
|
||||
TIMESTAMPDIFF(
|
||||
YEAR,
|
||||
t5.birthday,
|
||||
CURDATE()) AS age,
|
||||
t6.name AS delegationName
|
||||
FROM
|
||||
`executive_committee_two_push` t1
|
||||
LEFT JOIN executive_committee_one_push t2 on t2.userId=t1.userId and t2.teacherMeetId=t1.teacherMeetId
|
||||
LEFT JOIN sys_unit t3 ON t2.unitId = t3.id
|
||||
LEFT JOIN `sys_union` t4 ON t4.id = t3.unionid
|
||||
LEFT JOIN `vw_user` t5 ON t5.id = t1.userId
|
||||
LEFT JOIN teacher_congress_delegation t6 ON t6.id = t2.delegationId
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("t1.teacherMeetId", "=", teacherMeetId);
|
||||
cnd.andEX("t2.delegationId", "=", delegationId);
|
||||
cnd.andEX("t1.roleCode", "=", roleCode);
|
||||
cnd.andEX("t1.isFormal", "=", true);
|
||||
if (StpUtil.hasRole(RoleConstant.SYSADMIN.name()) ||
|
||||
StpUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name()) ||
|
||||
StpUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
|
||||
cnd.andEX("t4.id", "=", unionId);
|
||||
} else {
|
||||
cnd.andEX("t4.id", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("t2.userName", pageForm.getSearchKeyword());
|
||||
group.orLike("t2.loginName", pageForm.getSearchKeyword());
|
||||
cnd.and(group);
|
||||
}
|
||||
cnd.asc("t6.code").asc("t2.firstLetter");
|
||||
sql.setCondition(cnd);
|
||||
return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("executiveCommittee.formalPush")
|
||||
@ApiOperation("查询可以推选委员和已经推选的人员")
|
||||
public Result getDelegationUser(String teacherMeetId) {
|
||||
List<ExecutiveCommitteeTwoPush> twoPushList = dao.query(ExecutiveCommitteeTwoPush.class,
|
||||
Cnd.where("teacherMeetId", "=", teacherMeetId).and(ExecutiveCommitteeTwoPush::getRoleCode, "is not", null));
|
||||
|
||||
List<ExecutiveCommitteeTwoPush> userValue = twoPushList.stream().filter(ExecutiveCommitteeTwoPush::getIsFormal).toList();
|
||||
List<String> userIds = userValue.stream().map(ExecutiveCommitteeTwoPush::getUserId).toList();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t2.id userId,
|
||||
t2.username userName,
|
||||
t2.loginname loginName,
|
||||
t2.unitName,
|
||||
t2.sex,
|
||||
t2.professionalTitle,
|
||||
t2.professionalLevel,
|
||||
t1.roleCode,
|
||||
TIMESTAMPDIFF(
|
||||
YEAR,
|
||||
t2.birthday,
|
||||
CURDATE()) age
|
||||
FROM
|
||||
executive_committee_two_push t1
|
||||
LEFT JOIN `vw_user` t2 ON t1.userId = t2.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("t1.teacherMeetId", "=", teacherMeetId);
|
||||
cnd.andEX("t1.userId", "not in", userIds);
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> userData = baseService.listMap(sql);
|
||||
return Result.success(Map.of("userData", userData, "userValue", userValue));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("executiveCommittee.formalPush")
|
||||
@SLog(tag = "执委会推选-正式委员录入", msg = "推选委员")
|
||||
public Result addOnePush(@Param("userValue") String[] userValue,
|
||||
String teacherMeetId) {
|
||||
try {
|
||||
if (ObjectUtil.isEmpty(userValue)) {
|
||||
return Result.error("请选择要录入的委员!");
|
||||
}
|
||||
if (ObjectUtil.isEmpty(teacherMeetId)) {
|
||||
return Result.error("请选择教代会!");
|
||||
}
|
||||
List<ExecutiveCommitteeTwoPush> twoPushList = dao.query(ExecutiveCommitteeTwoPush.class, Cnd.where(ExecutiveCommitteeTwoPush::getTeacherMeetId, "=", teacherMeetId).and(ExecutiveCommitteeTwoPush::getUserId, "in", userValue));
|
||||
List<String> ids = twoPushList.stream().map(ExecutiveCommitteeTwoPush::getId).toList();
|
||||
dao.update(ExecutiveCommitteeTwoPush.class, Chain.make("isFormal", true), Cnd.where("id", "in", ids));
|
||||
return Result.success("添加成功!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("添加失败!");
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("executiveCommittee.formalPush")
|
||||
@SLog(tag = "执委会推选-正式委员录入", msg = "删除推选的人")
|
||||
public Result doDelete(@Valid String id, @Valid String teacherMeetId) {
|
||||
dao.update(ExecutiveCommitteeTwoPush.class, Chain.make("isFormal", false), Cnd.where("id", "=", id));
|
||||
return Result.success("删除成功!");
|
||||
}
|
||||
|
||||
}
|
||||
-1
@@ -270,7 +270,6 @@ public class ExecutiveCommitteeUnionPushController {
|
||||
// 自动完成第一个申请任务
|
||||
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
|
||||
for (ProcessTask task : doingTaskList) {
|
||||
args.put(FlowConst.NEXT_NODE_OPERATOR, ExecutiveCommitteeUnionPushInfo.getUserId());
|
||||
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
|
||||
}
|
||||
});
|
||||
|
||||
+11
@@ -66,4 +66,15 @@ public class ExecutiveCommitteeTwoPush extends BaseModel implements Serializable
|
||||
@Comment("推选时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private DateTime pushDate;
|
||||
|
||||
@Column
|
||||
@Comment("录入类型1.执委会委员/2.工会委员会委员/3.经审委员会委员")
|
||||
@ColDefine(type = ColType.VARCHAR,width = 30)
|
||||
private String roleCode;
|
||||
|
||||
@Column
|
||||
@Comment("是否正式委员")
|
||||
@Default("0")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Boolean isFormal;
|
||||
}
|
||||
|
||||
+15
-9
@@ -2,11 +2,14 @@ package com.budwk.app.zhgh.democratic.proposal.controller.query;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.controller.vo.ProposalInfoPageVO;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalQueryComprehensiveParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -24,7 +27,6 @@ import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Arrays;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/proposal/query/comprehensive")
|
||||
@@ -65,6 +67,7 @@ public class ProposalQueryComprehensiveController {
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN pru.isMaster = 0 THEN pru.unitName END) AS slaveUnitNames
|
||||
FROM
|
||||
proposal_info info
|
||||
LEFT JOIN vw_user us ON us.loginname=info.createUserLoginName
|
||||
LEFT JOIN proposal_type type on type.id = info.typeId
|
||||
LEFT JOIN proposal_merge mer ON mer.proposalId = info.id
|
||||
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
|
||||
@@ -77,25 +80,25 @@ public class ProposalQueryComprehensiveController {
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if(ArrayUtil.isNotEmpty(pageForm.getOrigins())){
|
||||
if (ArrayUtil.isNotEmpty(pageForm.getOrigins()) && ObjectUtil.isNotEmpty(pageForm.getCommonKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
|
||||
// 案名
|
||||
if(ArrayUtil.contains(pageForm.getOrigins(),"name")){
|
||||
if (ArrayUtil.contains(pageForm.getOrigins(), "name")) {
|
||||
for (String keyword : pageForm.getCommonKeyword().split(" ")) {
|
||||
seg.orLike("info.name", keyword);
|
||||
}
|
||||
}
|
||||
|
||||
// 案由
|
||||
if(ArrayUtil.contains(pageForm.getOrigins(),"brief")){
|
||||
if (ArrayUtil.contains(pageForm.getOrigins(), "brief")) {
|
||||
for (String keyword : pageForm.getCommonKeyword().split(" ")) {
|
||||
seg.orLike("info.brief", keyword);
|
||||
}
|
||||
}
|
||||
|
||||
// 提案人
|
||||
if(ArrayUtil.contains(pageForm.getOrigins(),"createUserName")){
|
||||
if (ArrayUtil.contains(pageForm.getOrigins(), "createUserName")) {
|
||||
for (String keyword : pageForm.getCommonKeyword().split(" ")) {
|
||||
seg.orLike("info.createUserName", keyword);
|
||||
seg.orLike("info.createUserLoginName", keyword);
|
||||
@@ -103,21 +106,24 @@ public class ProposalQueryComprehensiveController {
|
||||
}
|
||||
|
||||
// 答复内容
|
||||
if(ArrayUtil.contains(pageForm.getOrigins(),"answer")){
|
||||
if (ArrayUtil.contains(pageForm.getOrigins(), "answer")) {
|
||||
for (String keyword : pageForm.getCommonKeyword().split(" ")) {
|
||||
seg.orLike("JSON_EXTRACT(replyTask.variable,'$.tf_opinion')", keyword);
|
||||
}
|
||||
}
|
||||
|
||||
if(!seg.isEmpty()){
|
||||
if (!seg.isEmpty()) {
|
||||
cnd.and(seg);
|
||||
}
|
||||
}
|
||||
|
||||
if(StrUtil.isNotBlank(pageForm.getUnderTakeUnitId())){
|
||||
if (StrUtil.isNotBlank(pageForm.getUnderTakeUnitId())) {
|
||||
cnd.andEX("pru.unitId", "=", pageForm.getUnderTakeUnitId());
|
||||
}
|
||||
ProposalQueryComprehensiveParam.buildSearch(cnd, pageForm);
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(),RoleConstant.SCHOOL_UNION_PROPOSAL_ADMIN.name())){
|
||||
cnd.and("us.unionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
cnd.groupBy("info.id");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ public class ProposalCommitteeFilingUnitController {
|
||||
}
|
||||
|
||||
for (ProcessInstance instance : instanceList) {
|
||||
instance.setProcessDefineId(400L);
|
||||
instance.setProcessDefineId(399L);
|
||||
}
|
||||
|
||||
baseService.update(tasks);
|
||||
|
||||
+1
-3
@@ -1,13 +1,11 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.controller.transact;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.bpm.service.BpmService;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalSecondedService;
|
||||
@@ -101,7 +99,7 @@ public class ProposalSecondedController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.taskName", "=", "second");
|
||||
|
||||
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||
if (!SecurityUtil.getUserLoginname().equals("sysadmin")) {
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -1,24 +1,23 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.interceptor;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.FlowInterceptor;
|
||||
import com.budwk.app.flow.engine.core.Execution;
|
||||
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName ProposalDelegationPrefixInterceptor
|
||||
* @Author JyuHsin
|
||||
@@ -77,6 +76,12 @@ public class ProposalDelegationPrefixInterceptor implements FlowInterceptor {
|
||||
|
||||
execution.getArgs().set(FlowConst.TASK_FORM_DATA_PREFIX + "delegationAudit", delegationAudit);
|
||||
|
||||
ProcessTask processTask = execution.getProcessTask();
|
||||
Dict dict = JSONUtil.toBean(processTask.getVariable(), Dict.class);
|
||||
dict.set(FlowConst.TASK_FORM_DATA_PREFIX + "delegationAudit", delegationAudit);
|
||||
processTask.setVariable(JSONUtil.toJsonStr(dict));
|
||||
dao.update(processTask);
|
||||
|
||||
// 存储一些参数,方便查询副团长
|
||||
execution.getArgs().set("sessionId", proposalInfo.getSessionId());
|
||||
execution.getArgs().set("delegationId", proposalInfo.getDelegationId());
|
||||
|
||||
+20
-14
@@ -4,6 +4,7 @@ import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import com.budwk.app.base.param.ExportTableColumns;
|
||||
@@ -192,25 +193,30 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
// 添加序号,去除富文本,获取附议人
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).put("index", i + 1);
|
||||
list.get(i).put("brief", HtmlUtil.cleanHtmlTag(list.get(i).getString("brief")));
|
||||
list.get(i).put("measures", HtmlUtil.cleanHtmlTag(list.get(i).getString("measures")));
|
||||
list.get(i).put("brief", HtmlUtil.cleanHtmlTag(list.get(i).getString("brief")).replaceAll(" "," "));
|
||||
list.get(i).put("measures", HtmlUtil.cleanHtmlTag(list.get(i).getString("measures")).replaceAll(" "," "));
|
||||
|
||||
// 流程实例
|
||||
ProcessInstance instance = dao().fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", list.get(i).getString("id")));
|
||||
|
||||
// 查询附议人信息
|
||||
ProcessTask inviteTask = dao().fetch(ProcessTask.class,
|
||||
Cnd.where(ProcessTask::getProcessInstanceId, "=", instance.getId())
|
||||
.and(ProcessTask::getTaskName, "=", "invite")
|
||||
.and(ProcessTask::getTaskState, "in",
|
||||
List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
|
||||
.desc(ProcessTask::getCreatedAt));
|
||||
if (ObjectUtil.isNotEmpty(instance)){
|
||||
ProcessTask inviteTask = dao().fetch(ProcessTask.class,
|
||||
Cnd.where(ProcessTask::getProcessInstanceId, "=", instance.getId())
|
||||
.and(ProcessTask::getTaskName, "=", "invite")
|
||||
.and(ProcessTask::getTaskState, "in",
|
||||
List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
|
||||
.desc(ProcessTask::getCreatedAt));
|
||||
|
||||
if (inviteTask != null) {
|
||||
NutMap variable = Json.fromJson(NutMap.class, inviteTask.getVariable());
|
||||
List<NutMap> seconders = variable.getAsList(FlowConst.TASK_FORM_DATA_PREFIX + "seconder", NutMap.class);
|
||||
list.get(i).put("secondedUserNames", seconders.stream().map(v -> v.getString("userName")).collect(Collectors.joining(",")));
|
||||
if (inviteTask != null) {
|
||||
NutMap variable = Json.fromJson(NutMap.class, inviteTask.getVariable());
|
||||
List<NutMap> seconders = variable.getAsList(FlowConst.TASK_FORM_DATA_PREFIX + "seconder", NutMap.class);
|
||||
if (seconders != null){
|
||||
list.get(i).put("secondedUserNames", seconders.stream().map(v -> v.getString("userName")).collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
@@ -570,8 +576,8 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
// 添加序号,去除富文本,获取附议人
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).put("index", i + 1);
|
||||
list.get(i).put("brief", HtmlUtil.cleanHtmlTag(list.get(i).getString("brief")));
|
||||
list.get(i).put("measures", HtmlUtil.cleanHtmlTag(list.get(i).getString("measures")));
|
||||
list.get(i).put("brief", HtmlUtil.cleanHtmlTag(list.get(i).getString("brief")).replaceAll(" "," "));
|
||||
list.get(i).put("measures", HtmlUtil.cleanHtmlTag(list.get(i).getString("measures")).replaceAll(" "," "));
|
||||
|
||||
// 流程实例
|
||||
// ProcessInstance instance = dao().fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", list.get(i).getString("id")));
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<!-- 引入 core 包和对应 css-->
|
||||
<script src="/assets/platform/plugins/logicflow/logic-flow.js"></script>
|
||||
<link rel="stylesheet" href="/assets/platform/plugins/logicflow/index.css"/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@logicflow/extension@2.1.4/dist/index.min.js"></script>
|
||||
<script src="/assets/platform/plugins/logicflow/index.min.js"></script>
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/@logicflow/extension@2.1.4/dist/index.min.js"></script>-->
|
||||
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
|
||||
<style>
|
||||
#snaker-flow-preview {
|
||||
|
||||
@@ -103,6 +103,9 @@ const REGISTER_INFO_COMPONENT = {
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="批复文件" v-if="!task.ext.isFirstTaskNode">
|
||||
<file-preview :files="task.taskFormData.approvalFiles" complete_result></file-preview>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
|
||||
task.taskFormData.opinion }}
|
||||
</el-descriptions-item>
|
||||
|
||||
@@ -5,6 +5,15 @@ layout("/layouts/platform.html"){
|
||||
.left-span-label {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.flow-task-form .el-form-item {
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
/* 可选:如果上传组件需要占满整行,可以强制其容器宽度 */
|
||||
.flow-task-form .el-form-item__content {
|
||||
/* 如果内容被挤压,可以取消注释下面这行 */
|
||||
/* width: calc(100% - 200px); */
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
@@ -73,8 +82,17 @@ layout("/layouts/platform.html"){
|
||||
<div class="process-title">
|
||||
{{formData.taskName}}
|
||||
</div>
|
||||
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":"
|
||||
class="flow-task-form">
|
||||
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="100px" label-suffix=":">
|
||||
<el-form-item label="批复文件" prop="approvalFiles" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<file-upload
|
||||
:value.sync="formData.tf_approvalFiles"
|
||||
:upload_number="5"
|
||||
upload_result_category="array"
|
||||
complete_result
|
||||
upload_mode="file"
|
||||
accept=".doc,.docx,.xls,.xlsx,.pdf"
|
||||
></file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批意见" prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
@@ -122,7 +140,7 @@ layout("/layouts/platform.html"){
|
||||
this.$refs.guava.public(() => {
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
taskName: row.curTaskName,
|
||||
}
|
||||
this.showApprovalForm = true
|
||||
this.$refs.registerInfoRef.onOpen(row)
|
||||
@@ -145,6 +163,7 @@ layout("/layouts/platform.html"){
|
||||
this.$message.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ layout("/layouts/platform.html"){
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="$refs.onePushFormalRef.onOpen(pageForm.teacherMeetId)"
|
||||
>候选人录入
|
||||
>候选委员录入
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ const DELEGATION_TWO_PUSH_FORMAL_DIALOG = {
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="dialogVisible"
|
||||
title="执委会\工会委员会候选人、经审委员会委员录入"
|
||||
title="候选委员录入"
|
||||
width="70%"
|
||||
|
||||
>
|
||||
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="姓名/工号">
|
||||
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号" clearable>
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="教代会">
|
||||
<el-select
|
||||
v-model="pageForm.teacherMeetId"
|
||||
filterable
|
||||
placeholder="请选择教代会"
|
||||
style="width:100%;"
|
||||
@change="teacherMeetChange(pageForm.teacherMeetId)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in teacherMeets"
|
||||
:key="item.id"
|
||||
:label="item.fullName"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select clearable filterable placeholder="请选择所属工会" style="width: 100%"
|
||||
v-model="pageForm.unionId">
|
||||
<el-option :key="item.id" :label="item.name" :value="item.id"
|
||||
v-for="item in unionOptions"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="代表团">
|
||||
<el-select clearable filterable placeholder="请选择代表团" style="width: 100%"
|
||||
v-model="pageForm.delegationId">
|
||||
<el-option :key="item.id" :label="item.name" :value="item.id"
|
||||
v-for="item in delegations"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="委员类别">
|
||||
<el-select
|
||||
v-model="pageForm.roleCode"
|
||||
filterable
|
||||
placeholder="请选择委员类别"
|
||||
clearable
|
||||
style="width:100%;"
|
||||
>
|
||||
<el-option label="执委会委员" value="1"></el-option>
|
||||
<el-option label="工会委员会委员" value="2"></el-option>
|
||||
<el-option label="经审委员会委员" value="3"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mt10">
|
||||
<table-tool label="上报列表">
|
||||
<el-button
|
||||
icon="el-icon-check"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="$refs.onePushFormalRef.onOpen(pageForm.teacherMeetId)"
|
||||
>正式委员录入
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="tableData"
|
||||
row-key="id"
|
||||
@sort-change="pageOrder"
|
||||
v-loading="tableLoading"
|
||||
>
|
||||
<el-table-column :index="indexMethod" align="center" header-align="center"
|
||||
label="序号"
|
||||
fixed
|
||||
type="index"
|
||||
width="50"></el-table-column>
|
||||
<el-table-column align="center" label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column align="center" label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column align="center" label="年龄" prop="age"></el-table-column>
|
||||
<el-table-column align="center" label="性别" prop="sex"></el-table-column>
|
||||
<el-table-column align="center" label="代表团" prop="delegationName"></el-table-column>
|
||||
<el-table-column align="center" label="所属工会" prop="unionName"></el-table-column>
|
||||
<el-table-column align="center" label="所属单位" prop="unitName"></el-table-column>
|
||||
<el-table-column label="委员类别" prop="roleCode">
|
||||
<template scope="{row}">
|
||||
<el-tag v-if="row.roleCode === '1'">执委会委员</el-tag>
|
||||
<el-tag v-if="row.roleCode === '2'">工会委员会委员</el-tag>
|
||||
<el-tag v-if="row.roleCode === '3'">经审委员会委员</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" width="100" fixed="right">
|
||||
<template scope="{row}">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="danger"
|
||||
@click="onDelete(row)"
|
||||
>删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</template>
|
||||
</guava>
|
||||
<push-formal-dialog ref="onePushFormalRef" @refresh="doSearch"></push-formal-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<!--#include("pushFormalDialog.js"){}#-->
|
||||
const vue = new Vue({
|
||||
el: '#app',
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {
|
||||
pageDataUrl: "/platform/executiveCommittee/formalPush/pageData",
|
||||
pageForm: {
|
||||
teacherMeetId: null,
|
||||
unionId: null
|
||||
},
|
||||
teacherMeets: [],
|
||||
unionOptions: [],
|
||||
delegations: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"push-formal-dialog": PUSH_FORMAL_DIALOG
|
||||
},
|
||||
async created() {
|
||||
this.unionOptions = await this.$businessTool.listUnion()
|
||||
await this.getAllJdh()
|
||||
},
|
||||
methods: {
|
||||
async teacherMeetChange(val) {
|
||||
this.$set(this.pageForm, 'delegationId', null)
|
||||
this.getAllDelegation(val)
|
||||
this.doSearch()
|
||||
},
|
||||
getAllDelegation(id) {
|
||||
this.$axios.post("/platform/teacherCongress/common/listDelegation", {sessionId: id}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
this.delegations = resp.data
|
||||
}
|
||||
})
|
||||
},
|
||||
getAllJdh() {
|
||||
this.$axios.post("/platform/teacherCongress/common/listSession", {}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
this.teacherMeets = resp.data
|
||||
if (this.teacherMeets && this.teacherMeets.length > 0) {
|
||||
this.$set(this.pageForm, 'teacherMeetId', this.teacherMeets[0].id)
|
||||
this.getAllDelegation(this.teacherMeets[0].id)
|
||||
this.pageData()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onDelete(row) {
|
||||
this.$confirm('确定要删除该条数据吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const resp = await this.$axios.post('/platform/executiveCommittee/formalPush/doDelete', {
|
||||
id: row.id,
|
||||
teacherMeetId: this.pageForm.teacherMeetId
|
||||
})
|
||||
if (resp.code === 0) {
|
||||
this.doSearch()
|
||||
this.$message.success(resp.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
|
||||
.pushFormDialog .el-transfer-panel__item.el-checkbox {
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-right: 0;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.pushFormDialog .el-checkbox__input {
|
||||
vertical-align: top;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.pushFormDialog .transfer-item {
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.pushFormDialog .el-transfer-panel {
|
||||
height: 60vh;
|
||||
width: unset !important;
|
||||
flex: 2 !important;
|
||||
}
|
||||
|
||||
.pushFormDialog .el-transfer-panel__body {
|
||||
height: calc(100% - 40px) !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pushFormDialog .el-transfer-panel__list.is-filterable {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
const PUSH_FORMAL_DIALOG = {
|
||||
template: /*language=HTML*/ `
|
||||
<div class="pushFormDialog">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="dialogVisible"
|
||||
title="正式委员录入"
|
||||
width="70%"
|
||||
|
||||
>
|
||||
<el-transfer
|
||||
ref="transfer"
|
||||
v-model="userValue"
|
||||
:data="userData"
|
||||
filter-placeholder="请按姓名模糊搜索"
|
||||
:filter-method="filterMethod"
|
||||
:props="{key: 'userId',label: 'name'}"
|
||||
:right-default-checked="rightChecked"
|
||||
:titles="['可推选人员名单', '当前选择']"
|
||||
filterable
|
||||
class="transfer-high"
|
||||
>
|
||||
<div slot-scope="{ option }">
|
||||
<div class="transfer-item">
|
||||
<div class="transfer-item-name">{{ option.userName }} - {{ option.loginName }} -
|
||||
{{option.unitName}}
|
||||
</div>
|
||||
<div class="transfer-item-details">
|
||||
<span class="detail-item">
|
||||
{{option.sex}}
|
||||
</span>
|
||||
<span class="detail-item">{{ option.age }}岁</span>
|
||||
<span class="detail-item">{{ option.professionalTitle }}</span>
|
||||
<span class="detail-item" style="color:#ee0a24;">{{ option.roleCode==='1'?'执委会委员':option.roleCode==='2'?'工会委员会委员':'经审委员会委员' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-transfer>
|
||||
<span slot="footer">
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
||||
</span>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
userValue: [],
|
||||
userData: [],
|
||||
rightChecked: [],
|
||||
attendanceRightChecked: [],
|
||||
teacherMeetId: null,
|
||||
prepareGroupQuotaCount: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onOpen(teacherMeetId) {
|
||||
this.dialogVisible = true
|
||||
this.teacherMeetId = teacherMeetId
|
||||
this.userValue = []
|
||||
this.userData = []
|
||||
const {
|
||||
code,
|
||||
data
|
||||
} = await this.$axios.post('/platform/executiveCommittee/formalPush/getDelegationUser', {teacherMeetId: teacherMeetId})
|
||||
if (code === 0) {
|
||||
data.userData.forEach(v => {
|
||||
this.userData.push({userId: v.userId, ...v})
|
||||
})
|
||||
this.prepareGroupQuotaCount = data.prepareGroupQuotaCount
|
||||
}
|
||||
},
|
||||
filterMethod(query, item) {
|
||||
return item.userName.indexOf(query) > -1
|
||||
},
|
||||
async onConfirm() {
|
||||
const {
|
||||
code,
|
||||
msg
|
||||
} = await this.$axios.post('/platform/executiveCommittee/formalPush/addOnePush', {
|
||||
userValue: JSON.stringify(this.userValue),
|
||||
teacherMeetId: this.teacherMeetId
|
||||
})
|
||||
if (code === 0) {
|
||||
this.dialogVisible = false
|
||||
this.$message.success(msg)
|
||||
this.$emit('refresh')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
+1
-1
@@ -31,12 +31,12 @@ const PUSH_FORMAL_DIALOG = {
|
||||
</span>
|
||||
<span class="detail-item">{{ option.age }}岁</span>
|
||||
<span class="detail-item">{{ option.professionalTitle }}</span>
|
||||
<span class="detail-item" style="color:#ee0a24;">{{ option.roleCode==='1'?'执委会委员':option.roleCode==='2'?'工会委员会委员':'经审委员会委员' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-transfer>
|
||||
<span slot="footer">
|
||||
<span style="color:red;font-size: 15px; display:flex;text-align: right;">推选名额:{{prepareGroupQuotaCount}}个</span>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
||||
|
||||
+2
-2
@@ -71,9 +71,9 @@ const merge = {
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核意见" prop="approvalOpinion"
|
||||
<el-form-item label="审核意见" prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.approvalOpinion"></user-opinion-textarea>
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
|
||||
+1
-1
@@ -209,7 +209,7 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
methods: {
|
||||
doUpData(){
|
||||
this.$.axios.post(loc()+"/doUpData")
|
||||
this.$axios.post(loc()+"/doUpData")
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
|
||||
Reference in New Issue
Block a user