commit
This commit is contained in:
@@ -2,8 +2,6 @@ package com.budwk.app.flow.service;
|
||||
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学校 OA 待办同步服务。
|
||||
*/
|
||||
@@ -52,19 +50,17 @@ public interface SchoolOaTodoService {
|
||||
* @param pcUrl PC端福利选择地址
|
||||
* @param appUrl 手机端福利选择地址
|
||||
* @param creatorId 待办创建人ID
|
||||
* @param receiverIds 待办接收人ID集合
|
||||
* @param receiverId 待办接收人ID
|
||||
* @return 学校OA待办唯一值
|
||||
*/
|
||||
void createWelfareReminderTodos(String projectId, String title, String pcUrl, String appUrl, String creatorId, List<String> receiverIds);
|
||||
String createWelfareReminderTodo(String projectId, String title, String pcUrl, String appUrl, String creatorId, String receiverId);
|
||||
|
||||
/**
|
||||
* 将用户当前福利项目下的全部学校OA提醒待办统一办结。
|
||||
* 将指定的学校OA福利提醒待办改为已办。
|
||||
*
|
||||
* @param projectId 福利项目ID
|
||||
* @param userId 完成选择的用户ID
|
||||
* @param pcUrl PC端福利选择地址
|
||||
* @param appUrl 手机端福利选择地址
|
||||
* @param uniqueId 创建待办时记录的学校OA唯一值
|
||||
*/
|
||||
void completeWelfareReminderTodos(String projectId, String userId, String pcUrl, String appUrl);
|
||||
void completeWelfareReminderTodo(String uniqueId);
|
||||
|
||||
/**
|
||||
* 删除用户已完成福利选择对应的学校OA提醒待办。
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 学校 OA 待办同步服务实现。
|
||||
@@ -202,11 +201,11 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createWelfareReminderTodos(String projectId, String title, String pcUrl, String appUrl, String creatorId, List<String> receiverIds) {
|
||||
public String createWelfareReminderTodo(String projectId, String title, String pcUrl, String appUrl, String creatorId, String receiverId) {
|
||||
if (!isSchoolOaEnabled("创建福利选择提醒待办", null, null)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.hasBlank(projectId, title, pcUrl, appUrl, creatorId) || receiverIds == null || receiverIds.isEmpty()) {
|
||||
if (StrUtil.hasBlank(projectId, title, pcUrl, appUrl, creatorId, receiverId)) {
|
||||
throw new BaseException("学校OA福利选择提醒待办参数不完整");
|
||||
}
|
||||
|
||||
@@ -215,33 +214,23 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
throw new BaseException("学校OA福利选择提醒待办创建人工号或姓名为空,userId={}", creatorId);
|
||||
}
|
||||
|
||||
String creatorTime = formatTime(System.currentTimeMillis());
|
||||
for (String receiverId : receiverIds) {
|
||||
Sys_user receiver = dao.fetch(Sys_user.class, receiverId);
|
||||
if (receiver == null || StrUtil.hasBlank(receiver.getLoginname(), receiver.getUsername())) {
|
||||
throw new BaseException("学校OA福利选择提醒待办接收人工号或姓名为空,userId={}", receiverId);
|
||||
}
|
||||
sendWelfareReminderTodo(projectId, title, pcUrl, appUrl, creator, receiver, creatorTime);
|
||||
Sys_user receiver = dao.fetch(Sys_user.class, receiverId);
|
||||
if (receiver == null || StrUtil.hasBlank(receiver.getLoginname(), receiver.getUsername())) {
|
||||
throw new BaseException("学校OA福利选择提醒待办接收人工号或姓名为空,userId={}", receiverId);
|
||||
}
|
||||
return sendWelfareReminderTodo(projectId, title, pcUrl, appUrl, creator, receiver,
|
||||
formatTime(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeWelfareReminderTodos(String projectId, String userId, String pcUrl, String appUrl) {
|
||||
if (!isSchoolOaEnabled("办结福利选择提醒流程", null, null)
|
||||
|| StrUtil.hasBlank(projectId, userId, pcUrl, appUrl)) {
|
||||
public void completeWelfareReminderTodo(String uniqueId) {
|
||||
if (!isSchoolOaEnabled("完成福利选择提醒待办", null, null) || StrUtil.isBlank(uniqueId)) {
|
||||
return;
|
||||
}
|
||||
String flowId = buildWelfareReminderFlowId(projectId, userId);
|
||||
JSONObject body = JSONUtil.createObj();
|
||||
body.set("flowId", flowId);
|
||||
body.set("stepName", "福利选择完成");
|
||||
body.set("pcUrl", pcUrl);
|
||||
body.set("appUrl", appUrl);
|
||||
String updateFlowUrl = requireConfig("school-oa.todo.update-flow-url");
|
||||
String responseBody = sendTodoRequest(updateFlowUrl, body,
|
||||
"学校OA福利选择提醒流程办结失败", "学校OA福利选择提醒流程办结异常");
|
||||
log.info("学校OA福利选择提醒流程办结成功,projectId={},userId={},flowId={},response={}",
|
||||
projectId, userId, flowId, responseBody);
|
||||
String updateUrl = requireConfig("school-oa.todo.update-url").replace("{uniqueId}", uniqueId);
|
||||
String responseBody = sendTodoRequest(updateUrl,
|
||||
"学校OA福利选择提醒待办完成失败", "学校OA福利选择提醒待办完成异常");
|
||||
log.info("学校OA福利选择提醒待办完成成功,uniqueId={},response={}", uniqueId, responseBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -413,8 +402,9 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
/**
|
||||
* 按学校OA固定待办格式创建福利选择提醒,标题承载自定义提醒内容。
|
||||
*/
|
||||
private void sendWelfareReminderTodo(String projectId, String title, String pcUrl, String appUrl,
|
||||
Sys_user creator, Sys_user receiver, String creatorTime) {
|
||||
private String sendWelfareReminderTodo(String projectId, String title, String pcUrl, String appUrl,
|
||||
Sys_user creator, Sys_user receiver, String creatorTime) {
|
||||
String uniqueId = buildWelfareReminderUniqueId(projectId, receiver.getId());
|
||||
JSONObject body = new JSONObject();
|
||||
body.set("flowTypeName", "福利选择");
|
||||
body.set("flowId", buildWelfareReminderFlowId(projectId, receiver.getId()));
|
||||
@@ -427,8 +417,8 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
body.set("appUrl", appUrl);
|
||||
body.set("pcPreviewUrl", pcUrl);
|
||||
body.set("appPreviewUrl", appUrl);
|
||||
// 每次提醒使用新的唯一值,重复提醒直接新增待办,不删除或覆盖历史提醒。
|
||||
body.set("uniqueId", buildWelfareReminderUniqueId(projectId, receiver.getId()));
|
||||
// 同一项目和用户固定使用一个唯一值,确保学校OA最多存在一条福利提醒待办。
|
||||
body.set("uniqueId", uniqueId);
|
||||
body.set("receiveCode", receiver.getLoginname());
|
||||
body.set("receiveName", receiver.getUsername());
|
||||
body.set("receiveTime", creatorTime);
|
||||
@@ -440,10 +430,17 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
JSONObject response = executeWelfareReminderTodoRequest(insertUrl, requestBody, projectId, receiver.getLoginname());
|
||||
String responseMessage = response.getStr("message", "");
|
||||
if (response.getInt("state", 0) != 200) {
|
||||
// 历史待办已存在时视为创建成功,由本系统补记待办记录并阻止后续重复创建。
|
||||
if (StrUtil.contains(responseMessage, "已存在")) {
|
||||
log.info("学校OA福利选择提醒待办已存在,按发送成功处理,projectId={},receiveCode={},uniqueId={}",
|
||||
projectId, receiver.getLoginname(), uniqueId);
|
||||
return uniqueId;
|
||||
}
|
||||
throw new BaseException("学校OA福利选择提醒待办创建失败:{}", StrUtil.blankToDefault(responseMessage, JSONUtil.toJsonStr(response)));
|
||||
}
|
||||
log.info("学校OA福利选择提醒待办创建成功,projectId={},receiveCode={},response={}",
|
||||
projectId, receiver.getLoginname(), JSONUtil.toJsonStr(response));
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,18 +462,14 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同一项目和用户共用流程标识,用户完成选择后可一次办结该流程下的全部提醒待办。
|
||||
*/
|
||||
/** 同一项目和用户共用固定流程标识。 */
|
||||
private String buildWelfareReminderFlowId(String projectId, String userId) {
|
||||
return "welfare_reminder_" + projectId + "_" + userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次福利提醒生成新的待办唯一值,允许对同一用户重复发送多条学校OA待办。
|
||||
*/
|
||||
/** 同一项目和用户固定使用一个待办唯一值。 */
|
||||
private String buildWelfareReminderUniqueId(String projectId, String userId) {
|
||||
return buildWelfareReminderFlowId(projectId, userId) + "_" + UUID.randomUUID().toString().replace("-", "");
|
||||
return buildWelfareReminderFlowId(projectId, userId);
|
||||
}
|
||||
|
||||
private String buildAppTaskUrl(String h5FormKey, ProcessTask task) {
|
||||
|
||||
+2
@@ -89,6 +89,7 @@ public class ClubRegistApplyController {
|
||||
public Result submit(@Valid @Param("club") SysClub club,
|
||||
@Param("::deleteIds") List<String> deleteIds,
|
||||
@Param("::managePerson") List<NutMap> managePerson) {
|
||||
sysClubService.validateRequiredFiles(club);
|
||||
sysClubService.validateManagePerson(managePerson);
|
||||
SysClub sysClub;
|
||||
if (StrUtil.isBlank(club.getId())) {
|
||||
@@ -119,6 +120,7 @@ public class ClubRegistApplyController {
|
||||
@Param("::deleteIds") List<String> deleteIds,
|
||||
@Param("::managePerson") List<NutMap> managePerson,
|
||||
@Param("taskId") Long taskId) {
|
||||
sysClubService.validateRequiredFiles(club);
|
||||
sysClubService.validateManagePerson(managePerson);
|
||||
if (StrUtil.isBlank(club.getId())) {
|
||||
sysClubService.doAdd(club, managePerson);
|
||||
|
||||
@@ -45,6 +45,13 @@ public interface SysClubService extends BaseService<SysClub> {
|
||||
*/
|
||||
void validateManagePerson(List<NutMap> managePerson);
|
||||
|
||||
/**
|
||||
* 校验协会正式提交时申请成立报告和章程草案是否已上传。
|
||||
*
|
||||
* @param club 协会申请信息
|
||||
*/
|
||||
void validateRequiredFiles(SysClub club);
|
||||
|
||||
/**
|
||||
* 下载协会申请成立报告模板。
|
||||
*
|
||||
|
||||
@@ -273,6 +273,17 @@ public class SysClubServiceImpl extends BaseServiceImpl<SysClub> implements SysC
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateRequiredFiles(SysClub club) {
|
||||
// 文件上传组件提交空数组时,不能仅依赖 Bean Validation 的 @NotEmpty,需要在正式提交前显式校验。
|
||||
if (club == null || ObjectUtil.isEmpty(club.getEstablishReport())) {
|
||||
throw new BaseException("请上传申请成立报告");
|
||||
}
|
||||
if (ObjectUtil.isEmpty(club.getRulesFile())) {
|
||||
throw new BaseException("请上传章程草案");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<ClubRegisterPageVo> minePageData(ClubUserPageForm pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
|
||||
+5
-4
@@ -22,6 +22,7 @@ import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
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;
|
||||
@@ -102,7 +103,7 @@ public class WelfareSelectionSituationController {
|
||||
@SaCheckPermission("welfare.selection.situation")
|
||||
@ApiOperation("预览福利选择提醒接收人数")
|
||||
public Result previewReminder(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm, @Param("userIds") String[] userIds) {
|
||||
return Result.success(situationService.countReminderRecipients(pageForm, userIds));
|
||||
return Result.success(situationService.previewReminder(pageForm, userIds));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -113,11 +114,11 @@ public class WelfareSelectionSituationController {
|
||||
if (StrUtil.isBlank(content)) {
|
||||
return Result.error("提醒内容不能为空");
|
||||
}
|
||||
int recipientCount = situationService.sendReminder(pageForm, userIds, content.trim());
|
||||
if (recipientCount == 0) {
|
||||
NutMap sendResult = situationService.sendReminder(pageForm, userIds, content.trim());
|
||||
if (sendResult.getInt("recipientCount", 0) == 0) {
|
||||
return Result.error("当前筛选条件下没有可提醒的人员");
|
||||
}
|
||||
return Result.success("提醒已发送给" + recipientCount + "人");
|
||||
return Result.success(sendResult.getString("summary"), sendResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.budwk.app.zhgh.welfare.model;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Index;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableIndexes;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 福利选择学校OA提醒待办记录。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("welfare_reminder_todo")
|
||||
@Comment("福利选择学校OA提醒待办记录")
|
||||
@TableIndexes({
|
||||
@Index(name = "UK_WELFARE_REMINDER_TODO_PROJECT_USER", fields = {"projectId", "userId"}, unique = true),
|
||||
@Index(name = "IDX_WELFARE_REMINDER_TODO_STATUS", fields = {"todoStatus"}, unique = false)
|
||||
})
|
||||
public class WelfareReminderTodo extends BaseModel {
|
||||
|
||||
/** 待办正在发送。 */
|
||||
public static final int STATUS_SENDING = 0;
|
||||
/** 学校OA待办已创建,等待用户处理。 */
|
||||
public static final int STATUS_PENDING = 1;
|
||||
/** 用户已完成福利选择,学校OA待办已办结。 */
|
||||
public static final int STATUS_COMPLETED = 2;
|
||||
/** 学校OA待办发送失败,可使用原唯一值重试。 */
|
||||
public static final int STATUS_FAILED = 3;
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("福利项目ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String projectId;
|
||||
|
||||
@Column
|
||||
@Comment("接收用户ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String userId;
|
||||
|
||||
@Column
|
||||
@Comment("学校OA流程ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String oaFlowId;
|
||||
|
||||
@Column
|
||||
@Comment("学校OA待办唯一值")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String oaUniqueId;
|
||||
|
||||
@Column
|
||||
@Comment("接收人工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String receiverCode;
|
||||
|
||||
@Column
|
||||
@Comment("接收人姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String receiverName;
|
||||
|
||||
@Column
|
||||
@Comment("发送人ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String senderId;
|
||||
|
||||
@Column
|
||||
@Comment("发送人工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String senderCode;
|
||||
|
||||
@Column
|
||||
@Comment("发送人姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String senderName;
|
||||
|
||||
@Column
|
||||
@Comment("待办标题")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String title;
|
||||
|
||||
@Column
|
||||
@Comment("提醒内容")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String content;
|
||||
|
||||
@Column
|
||||
@Comment("状态:0发送中、1待办、2已办、3发送失败")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer todoStatus;
|
||||
|
||||
@Column
|
||||
@Comment("发送成功时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date sendTime;
|
||||
|
||||
@Column
|
||||
@Comment("办结时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date finishTime;
|
||||
|
||||
@Column
|
||||
@Comment("发送失败原因")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
||||
private String failMessage;
|
||||
}
|
||||
+6
-5
@@ -4,6 +4,7 @@ import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.welfare.model.WelfareList;
|
||||
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -15,13 +16,13 @@ public interface WelfareSelectionSituationService extends BaseService<WelfareLis
|
||||
void receiveXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 统计当前筛选范围内可接收提醒的人员数量。
|
||||
* 预览当前筛选范围内的提醒发送情况。
|
||||
*
|
||||
* @param pageForm 当前页面筛选条件
|
||||
* @param userIds 已勾选的人员ID;为空时按筛选条件查询全部人员
|
||||
* @return 去重后的接收人数量
|
||||
* @return 包含接收人数、预计新增OA待办数、已有OA待办数及OA开关状态的预览结果
|
||||
*/
|
||||
int countReminderRecipients(WelfareSelectionSituationPageForm pageForm, String[] userIds);
|
||||
NutMap previewReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds);
|
||||
|
||||
/**
|
||||
* 向当前筛选范围内的人员发送福利选择提醒。
|
||||
@@ -29,9 +30,9 @@ public interface WelfareSelectionSituationService extends BaseService<WelfareLis
|
||||
* @param pageForm 当前页面筛选条件
|
||||
* @param userIds 已勾选的人员ID;为空时按筛选条件查询全部人员
|
||||
* @param content 自定义提醒内容
|
||||
* @return 实际发送的去重后接收人数量
|
||||
* @return 包含消息成功数、OA待办成功数、已有待办跳过数、OA待办失败数及提示文案的发送结果
|
||||
*/
|
||||
int sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content);
|
||||
NutMap sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content);
|
||||
|
||||
/**
|
||||
* 用户完成福利选择后将对应的学校OA提醒待办改为已办。
|
||||
|
||||
+220
-12
@@ -25,6 +25,7 @@ import com.budwk.app.zhgh.dayofficework.message.strategy.impl.LocalMessageSendSt
|
||||
import com.budwk.app.zhgh.welfare.model.WelfareList;
|
||||
import com.budwk.app.zhgh.welfare.model.WelfareProject;
|
||||
import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
|
||||
import com.budwk.app.zhgh.welfare.model.WelfareReminderTodo;
|
||||
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
|
||||
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -125,15 +126,23 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countReminderRecipients(WelfareSelectionSituationPageForm pageForm, String[] userIds) {
|
||||
return getReminderRecipientIds(pageForm, userIds).size();
|
||||
public NutMap previewReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds) {
|
||||
List<String> recipientIds = getReminderRecipientIds(pageForm, userIds);
|
||||
boolean todoEnabled = Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSchoolOa"));
|
||||
int existingTodoCount = todoEnabled ? getExistingReminderTodoUserIds(pageForm.getProjectId(), recipientIds).size() : 0;
|
||||
return NutMap.NEW()
|
||||
.addv("recipientCount", recipientIds.size())
|
||||
.addv("newTodoCount", todoEnabled ? recipientIds.size() - existingTodoCount : 0)
|
||||
.addv("existingTodoCount", existingTodoCount)
|
||||
.addv("todoEnabled", todoEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content) {
|
||||
public NutMap sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content) {
|
||||
List<String> recipientIds = getReminderRecipientIds(pageForm, userIds);
|
||||
if (recipientIds.isEmpty()) {
|
||||
return 0;
|
||||
return buildReminderResult(0, 0, 0, 0, 0,
|
||||
Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSchoolOa")));
|
||||
}
|
||||
// 各消息渠道统一使用福利业务标题,学校OA再拼接自定义正文作为待办标题。
|
||||
String title = "智慧工会职工福利:";
|
||||
@@ -148,26 +157,225 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
||||
if (Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSms")) && !receiverUsers.isEmpty()) {
|
||||
smsService.massSendByUsers(receiverUsers, title, content, pcUrl, appUrl);
|
||||
}
|
||||
// AppSchoolOa 控制学校OA福利提醒待办创建,待办与接收人按项目保持唯一。
|
||||
if (Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSchoolOa"))) {
|
||||
schoolOaTodoService.createWelfareReminderTodos(pageForm.getProjectId(), title + content,
|
||||
pcUrl, appUrl, SecurityUtil.getUserId(), recipientIds);
|
||||
|
||||
boolean todoEnabled = Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSchoolOa"));
|
||||
int todoSuccessCount = 0;
|
||||
int existingTodoCount = 0;
|
||||
int todoFailedCount = 0;
|
||||
if (todoEnabled) {
|
||||
Map<String, Sys_user> receiverUserMap = receiverUsers.stream()
|
||||
.collect(Collectors.toMap(Sys_user::getId, user -> user, (left, right) -> left));
|
||||
for (String recipientId : recipientIds) {
|
||||
WelfareReminderTodo reminderTodo = getReminderTodo(pageForm.getProjectId(), recipientId);
|
||||
if (isExistingReminderTodo(reminderTodo)) {
|
||||
existingTodoCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Sys_user receiver = receiverUserMap.get(recipientId);
|
||||
try {
|
||||
// 发送前先落库为“发送中”,确保每一次实际发起的OA待办都可追溯。
|
||||
reminderTodo = saveSendingReminderTodo(reminderTodo, pageForm.getProjectId(), receiver,
|
||||
SecurityUtil.getUserId(), title + content, content);
|
||||
String uniqueId = schoolOaTodoService.createWelfareReminderTodo(pageForm.getProjectId(), title + content,
|
||||
pcUrl, appUrl, SecurityUtil.getUserId(), recipientId);
|
||||
if (StrUtil.isBlank(uniqueId)) {
|
||||
throw new IllegalStateException("学校OA待办开关状态已变化,本次待办未发送");
|
||||
}
|
||||
reminderTodo.setOaUniqueId(uniqueId);
|
||||
reminderTodo.setTodoStatus(WelfareReminderTodo.STATUS_PENDING);
|
||||
reminderTodo.setSendTime(new Date());
|
||||
reminderTodo.setFinishTime(null);
|
||||
reminderTodo.setFailMessage(null);
|
||||
dao().update(reminderTodo);
|
||||
todoSuccessCount++;
|
||||
} catch (Exception e) {
|
||||
todoFailedCount++;
|
||||
saveReminderTodoFailure(reminderTodo, pageForm.getProjectId(), recipientId, receiver,
|
||||
title + content, content, e);
|
||||
log.error("学校OA福利选择提醒待办发送失败,projectId={},userId={}",
|
||||
pageForm.getProjectId(), recipientId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return recipientIds.size();
|
||||
return buildReminderResult(recipientIds.size(), recipientIds.size(), todoSuccessCount,
|
||||
existingTodoCount, todoFailedCount, todoEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeReminderTodo(String projectId, String userId) {
|
||||
WelfareReminderTodo reminderTodo = getReminderTodo(projectId, userId);
|
||||
if (reminderTodo == null || !Objects.equals(reminderTodo.getTodoStatus(), WelfareReminderTodo.STATUS_PENDING)
|
||||
|| StrUtil.isBlank(reminderTodo.getOaUniqueId())) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String pcUrl = buildWelfareSelectionUrl("/platform/welfare/userSelect");
|
||||
String appUrl = buildWelfareSelectionUrl("/platform/h5/welfare/userSelect/list");
|
||||
schoolOaTodoService.completeWelfareReminderTodos(projectId, userId, pcUrl, appUrl);
|
||||
schoolOaTodoService.completeWelfareReminderTodo(reminderTodo.getOaUniqueId());
|
||||
reminderTodo.setTodoStatus(WelfareReminderTodo.STATUS_COMPLETED);
|
||||
reminderTodo.setFinishTime(new Date());
|
||||
reminderTodo.setFailMessage(null);
|
||||
dao().update(reminderTodo);
|
||||
} catch (Exception e) {
|
||||
// 学校OA流程办结失败不能影响用户完成福利选择,后续可根据日志人工处理。
|
||||
reminderTodo.setFailMessage(limitFailureMessage(e.getMessage()));
|
||||
dao().update(reminderTodo);
|
||||
log.error("学校OA福利选择提醒流程办结失败,projectId={},userId={}", projectId, userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询项目和用户对应的唯一提醒待办记录。
|
||||
*/
|
||||
private WelfareReminderTodo getReminderTodo(String projectId, String userId) {
|
||||
if (StrUtil.hasBlank(projectId, userId)) {
|
||||
return null;
|
||||
}
|
||||
return dao().fetch(WelfareReminderTodo.class, Cnd.where(WelfareReminderTodo::getProjectId, "=", projectId)
|
||||
.and(WelfareReminderTodo::getUserId, "=", userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送中、待办和已办记录均表示该项目已创建过OA待办,重复提醒时不再创建第二条。
|
||||
* 发送失败记录允许沿用原唯一值重试。
|
||||
*/
|
||||
private boolean isExistingReminderTodo(WelfareReminderTodo reminderTodo) {
|
||||
return reminderTodo != null && !Objects.equals(reminderTodo.getTodoStatus(), WelfareReminderTodo.STATUS_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量统计已存在的OA待办接收人,供发送预览显示重复跳过数量。
|
||||
*/
|
||||
private Set<String> getExistingReminderTodoUserIds(String projectId, List<String> userIds) {
|
||||
if (StrUtil.isBlank(projectId) || userIds.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return dao().query(WelfareReminderTodo.class, Cnd.where(WelfareReminderTodo::getProjectId, "=", projectId)
|
||||
.and(WelfareReminderTodo::getUserId, "in", userIds)
|
||||
.and(WelfareReminderTodo::getTodoStatus, "!=", WelfareReminderTodo.STATUS_FAILED))
|
||||
.stream()
|
||||
.map(WelfareReminderTodo::getUserId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建或重置待办发送记录。固定的流程ID和唯一值保证同一项目、同一用户最多一条OA待办。
|
||||
*/
|
||||
private WelfareReminderTodo saveSendingReminderTodo(WelfareReminderTodo reminderTodo, String projectId,
|
||||
Sys_user receiver, String senderId, String title, String content) {
|
||||
if (receiver == null || StrUtil.hasBlank(receiver.getId(), receiver.getLoginname(), receiver.getUsername())) {
|
||||
throw new IllegalArgumentException("学校OA福利选择提醒接收人信息不完整");
|
||||
}
|
||||
Sys_user sender = dao().fetch(Sys_user.class, senderId);
|
||||
if (sender == null || StrUtil.hasBlank(sender.getLoginname(), sender.getUsername())) {
|
||||
throw new IllegalArgumentException("学校OA福利选择提醒创建人信息不完整");
|
||||
}
|
||||
|
||||
boolean newRecord = reminderTodo == null;
|
||||
WelfareReminderTodo record = newRecord ? new WelfareReminderTodo() : reminderTodo;
|
||||
String uniqueId = buildWelfareReminderUniqueId(projectId, receiver.getId());
|
||||
record.setProjectId(projectId);
|
||||
record.setUserId(receiver.getId());
|
||||
record.setOaFlowId(uniqueId);
|
||||
record.setOaUniqueId(uniqueId);
|
||||
record.setReceiverCode(receiver.getLoginname());
|
||||
record.setReceiverName(receiver.getUsername());
|
||||
record.setSenderId(sender.getId());
|
||||
record.setSenderCode(sender.getLoginname());
|
||||
record.setSenderName(sender.getUsername());
|
||||
record.setTitle(limitText(title, 500));
|
||||
record.setContent(limitText(content, 500));
|
||||
record.setTodoStatus(WelfareReminderTodo.STATUS_SENDING);
|
||||
record.setSendTime(null);
|
||||
record.setFinishTime(null);
|
||||
record.setFailMessage(null);
|
||||
if (newRecord) {
|
||||
dao().insert(record);
|
||||
} else {
|
||||
dao().update(record);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存OA待办发送失败原因;若发送前校验失败导致记录尚未创建,则补建一条失败记录。
|
||||
*/
|
||||
private void saveReminderTodoFailure(WelfareReminderTodo reminderTodo, String projectId, String userId,
|
||||
Sys_user receiver, String title, String content, Exception exception) {
|
||||
WelfareReminderTodo record = reminderTodo == null ? getReminderTodo(projectId, userId) : reminderTodo;
|
||||
if (record == null) {
|
||||
record = new WelfareReminderTodo();
|
||||
record.setProjectId(projectId);
|
||||
record.setUserId(userId);
|
||||
record.setOaFlowId(buildWelfareReminderUniqueId(projectId, userId));
|
||||
record.setOaUniqueId(buildWelfareReminderUniqueId(projectId, userId));
|
||||
record.setSenderId(SecurityUtil.getUserId());
|
||||
if (receiver != null) {
|
||||
record.setReceiverCode(receiver.getLoginname());
|
||||
record.setReceiverName(receiver.getUsername());
|
||||
}
|
||||
Sys_user sender = dao().fetch(Sys_user.class, SecurityUtil.getUserId());
|
||||
if (sender != null) {
|
||||
record.setSenderCode(sender.getLoginname());
|
||||
record.setSenderName(sender.getUsername());
|
||||
}
|
||||
record.setTitle(limitText(title, 500));
|
||||
record.setContent(limitText(content, 500));
|
||||
record.setTodoStatus(WelfareReminderTodo.STATUS_FAILED);
|
||||
record.setFailMessage(limitFailureMessage(exception.getMessage()));
|
||||
dao().insert(record);
|
||||
return;
|
||||
}
|
||||
record.setTodoStatus(WelfareReminderTodo.STATUS_FAILED);
|
||||
record.setFailMessage(limitFailureMessage(exception.getMessage()));
|
||||
dao().update(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装发送统计和前端提示,消息与OA待办分别计数,避免把重复跳过误报为发送成功。
|
||||
*/
|
||||
private NutMap buildReminderResult(int recipientCount, int messageSuccessCount, int todoSuccessCount,
|
||||
int existingTodoCount, int todoFailedCount, boolean todoEnabled) {
|
||||
StringBuilder summary = new StringBuilder("消息发送成功").append(messageSuccessCount).append("人");
|
||||
if (todoEnabled) {
|
||||
summary.append(",OA待办发送成功").append(todoSuccessCount).append("人");
|
||||
if (existingTodoCount > 0) {
|
||||
summary.append(",").append(existingTodoCount).append("人已有OA待办未重复发送");
|
||||
}
|
||||
if (todoFailedCount > 0) {
|
||||
summary.append(",OA待办发送失败").append(todoFailedCount).append("人");
|
||||
}
|
||||
} else {
|
||||
summary.append(",学校OA待办开关未开启");
|
||||
}
|
||||
return NutMap.NEW()
|
||||
.addv("recipientCount", recipientCount)
|
||||
.addv("messageSuccessCount", messageSuccessCount)
|
||||
.addv("todoSuccessCount", todoSuccessCount)
|
||||
.addv("existingTodoCount", existingTodoCount)
|
||||
.addv("todoFailedCount", todoFailedCount)
|
||||
.addv("todoEnabled", todoEnabled)
|
||||
.addv("summary", summary.append("。").toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库失败原因字段最多保存1000个字符,避免外部接口返回超长文本导致二次写库失败。
|
||||
*/
|
||||
private String limitFailureMessage(String message) {
|
||||
String safeMessage = StrUtil.blankToDefault(message, "未知异常");
|
||||
return safeMessage.length() > 1000 ? safeMessage.substring(0, 1000) : safeMessage;
|
||||
}
|
||||
|
||||
/** 按数据库字段长度截取发送内容,避免超长文本影响待办记录落库。 */
|
||||
private String limitText(String text, int maxLength) {
|
||||
String safeText = StrUtil.nullToEmpty(text);
|
||||
return safeText.length() > maxLength ? safeText.substring(0, maxLength) : safeText;
|
||||
}
|
||||
|
||||
/** 同一项目和用户固定使用一个OA待办唯一值。 */
|
||||
private String buildWelfareReminderUniqueId(String projectId, String userId) {
|
||||
return "welfare_reminder_" + projectId + "_" + userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用系统配置的绝对域名构造学校外部平台可访问的福利选择地址。
|
||||
*/
|
||||
|
||||
@@ -85,6 +85,7 @@ layout("/layouts/platform.html"){
|
||||
await this.doHandle("onSave")
|
||||
},
|
||||
onSubmit() {
|
||||
if (!this.validateRequiredFiles()) return
|
||||
this.$refs.clubFormRef.$refs.form.validate().then(() => {
|
||||
this.doHandle("onSubmit")
|
||||
}).catch(() => {
|
||||
@@ -92,12 +93,26 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
},
|
||||
onFinishTask() {
|
||||
if (!this.validateRequiredFiles()) return
|
||||
this.$refs.clubFormRef.$refs.form.validate().then(() => {
|
||||
this.doHandle("onFinishTask")
|
||||
}).catch(() => {
|
||||
this.$message.warning({ title: "警告", message: "存在必填项未填写!" })
|
||||
})
|
||||
},
|
||||
// 文件上传组件使用数组承载文件,提交前显式检查空数组,避免表单校验误判为已填写。
|
||||
validateRequiredFiles() {
|
||||
const formData = this.$refs.clubFormRef.formData
|
||||
if (!formData.establishReport || formData.establishReport.length === 0) {
|
||||
this.$message.warning({ title: "警告", message: "请上传申请成立报告" })
|
||||
return false
|
||||
}
|
||||
if (!formData.rulesFile || formData.rulesFile.length === 0) {
|
||||
this.$message.warning({ title: "警告", message: "请上传章程草案" })
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
async doHandle(type) {
|
||||
let formData = {}
|
||||
try {
|
||||
|
||||
@@ -391,6 +391,10 @@ const optionSelect = {
|
||||
userName: "",
|
||||
userSign: ""
|
||||
}
|
||||
// PC端本人选择时默认当前登录人作为收货人;管理员代选仍由管理员填写目标用户收货人。
|
||||
if (!this.isProxySelect && this.$store.state.user && this.$store.state.user.username) {
|
||||
this.$set(this.contactForm, "userName", this.$store.state.user.username)
|
||||
}
|
||||
|
||||
this.getProjectInfo()
|
||||
},
|
||||
@@ -440,7 +444,11 @@ const optionSelect = {
|
||||
this.hasSubmittedBefore = this.userSelection.length > 0
|
||||
|
||||
if (this.userSelection && this.userSelection.length > 0) {
|
||||
this.contactForm.mobile = this.userSelection[0]?.mobile
|
||||
this.$set(this.contactForm, "mobile", this.userSelection[0]?.mobile || "")
|
||||
// 已有选择记录时优先回显历史收货人;历史记录为空时保留本人默认值。
|
||||
if (this.userSelection[0]?.userName) {
|
||||
this.$set(this.contactForm, "userName", this.userSelection[0].userName)
|
||||
}
|
||||
this.$set(this.contactForm, "userSign", this.userSelection[0]?.userSign || "")
|
||||
} else {
|
||||
if (this.isProxySelect) {
|
||||
|
||||
@@ -126,7 +126,9 @@ layout("/layouts/platform.html"){
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="发送福利选择提醒" :visible.sync="reminderVisible" width="500px" :close-on-click-modal="false">
|
||||
<el-alert :title="'发送模式:' + reminderModeText + ';本次将向' + reminderCount + '人发送消息'" type="warning" :closable="false"></el-alert>
|
||||
<el-alert :title="'发送模式:' + reminderModeText + ';本次将向' + reminderCount + '人发送消息,预计新增OA待办' + reminderNewTodoCount + '条'" type="warning" :closable="false"></el-alert>
|
||||
<el-alert v-if="reminderExistingTodoCount > 0" class="mt10" :title="'已有' + reminderExistingTodoCount + '人存在OA待办,本次仅发送消息,不重复创建待办'" type="info" :closable="false"></el-alert>
|
||||
<el-alert v-if="!reminderTodoEnabled" class="mt10" title="学校OA待办开关未开启,本次只发送消息" type="info" :closable="false"></el-alert>
|
||||
<el-form label-width="80px" class="mt20">
|
||||
<el-form-item label="提醒内容">
|
||||
<el-input v-model="reminderContent" type="textarea" :rows="5" maxlength="500" show-word-limit placeholder="请输入提醒内容"></el-input>
|
||||
@@ -174,6 +176,9 @@ layout("/layouts/platform.html"){
|
||||
reminderVisible: false,
|
||||
reminderContent: "",
|
||||
reminderCount: 0,
|
||||
reminderNewTodoCount: 0,
|
||||
reminderExistingTodoCount: 0,
|
||||
reminderTodoEnabled: false,
|
||||
reminderSending: false
|
||||
}
|
||||
},
|
||||
@@ -270,11 +275,14 @@ layout("/layouts/platform.html"){
|
||||
this.$message.error(response.msg)
|
||||
return
|
||||
}
|
||||
if (response.data === 0) {
|
||||
if (!response.data || response.data.recipientCount === 0) {
|
||||
this.$message.warning("当前筛选条件下没有可提醒的人员")
|
||||
return
|
||||
}
|
||||
this.$set(this, "reminderCount", response.data)
|
||||
this.$set(this, "reminderCount", response.data.recipientCount)
|
||||
this.$set(this, "reminderNewTodoCount", response.data.newTodoCount)
|
||||
this.$set(this, "reminderExistingTodoCount", response.data.existingTodoCount)
|
||||
this.$set(this, "reminderTodoEnabled", response.data.todoEnabled)
|
||||
this.$set(this, "reminderContent", "请及时完成本次福利选择。")
|
||||
this.$set(this, "reminderVisible", true)
|
||||
},
|
||||
@@ -294,7 +302,11 @@ layout("/layouts/platform.html"){
|
||||
{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }
|
||||
)
|
||||
if (response.code === 0) {
|
||||
this.$message.success(response.msg)
|
||||
if (response.data && response.data.todoFailedCount > 0) {
|
||||
this.$message.warning(response.msg)
|
||||
} else {
|
||||
this.$message.success(response.msg)
|
||||
}
|
||||
this.closeReminder()
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
@@ -308,6 +320,10 @@ layout("/layouts/platform.html"){
|
||||
closeReminder() {
|
||||
this.$set(this, "reminderVisible", false)
|
||||
this.$set(this, "reminderContent", "")
|
||||
this.$set(this, "reminderCount", 0)
|
||||
this.$set(this, "reminderNewTodoCount", 0)
|
||||
this.$set(this, "reminderExistingTodoCount", 0)
|
||||
this.$set(this, "reminderTodoEnabled", false)
|
||||
},
|
||||
|
||||
// 管理员待选
|
||||
|
||||
Reference in New Issue
Block a user