commit
This commit is contained in:
@@ -2,6 +2,8 @@ package com.budwk.app.flow.service;
|
|||||||
|
|
||||||
import com.budwk.app.flow.entity.ProcessTask;
|
import com.budwk.app.flow.entity.ProcessTask;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学校 OA 待办同步服务。
|
* 学校 OA 待办同步服务。
|
||||||
*/
|
*/
|
||||||
@@ -41,4 +43,24 @@ public interface SchoolOaTodoService {
|
|||||||
* @param processInstanceId 本系统流程实例 ID,用于定位最后一个已完成审批任务并把学校 OA 节点名称改为完结
|
* @param processInstanceId 本系统流程实例 ID,用于定位最后一个已完成审批任务并把学校 OA 节点名称改为完结
|
||||||
*/
|
*/
|
||||||
void updateFlowFinishedStepName(Long processInstanceId);
|
void updateFlowFinishedStepName(Long processInstanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建福利选择提醒待办。
|
||||||
|
*
|
||||||
|
* @param projectId 福利项目ID,用于构造学校OA业务标识
|
||||||
|
* @param title 待办标题,学校OA接口没有独立正文时用于展示提醒内容
|
||||||
|
* @param pcUrl PC端福利选择地址
|
||||||
|
* @param appUrl 手机端福利选择地址
|
||||||
|
* @param creatorId 待办创建人ID
|
||||||
|
* @param receiverIds 待办接收人ID集合
|
||||||
|
*/
|
||||||
|
void createWelfareReminderTodos(String projectId, String title, String pcUrl, String appUrl, String creatorId, List<String> receiverIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户已完成福利选择对应的学校OA提醒待办。
|
||||||
|
*
|
||||||
|
* @param projectId 福利项目ID
|
||||||
|
* @param userId 完成选择的用户ID
|
||||||
|
*/
|
||||||
|
void deleteWelfareReminderTodo(String projectId, String userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,41 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
|||||||
throw new BaseException("学校OA待办修改失败:未找到可修改的已完成流程任务,instanceId={}", processInstanceId);
|
throw new BaseException("学校OA待办修改失败:未找到可修改的已完成流程任务,instanceId={}", processInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createWelfareReminderTodos(String projectId, String title, String pcUrl, String appUrl, String creatorId, List<String> receiverIds) {
|
||||||
|
if (!isSchoolOaEnabled("创建福利选择提醒待办", null, null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StrUtil.hasBlank(projectId, title, pcUrl, appUrl, creatorId) || receiverIds == null || receiverIds.isEmpty()) {
|
||||||
|
throw new BaseException("学校OA福利选择提醒待办参数不完整");
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_user creator = dao.fetch(Sys_user.class, creatorId);
|
||||||
|
if (creator == null || StrUtil.hasBlank(creator.getLoginname(), creator.getUsername())) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteWelfareReminderTodo(String projectId, String userId) {
|
||||||
|
if (!isSchoolOaEnabled("删除福利选择提醒待办", null, null) || StrUtil.hasBlank(projectId, userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String uniqueId = buildWelfareReminderUniqueId(projectId, userId);
|
||||||
|
String deleteUrl = requireConfig("school-oa.todo.delete-url").replace("{uniqueId}", uniqueId);
|
||||||
|
sendTodoRequest(deleteUrl, "学校OA福利选择提醒待办删除失败", "学校OA福利选择提醒待办删除异常");
|
||||||
|
log.info("学校OA福利选择提醒待办删除成功,projectId={},userId={},uniqueId={}", projectId, userId, uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调用学校 OA 创建待办接口,接口失败时直接抛出异常,让本系统事务回滚。
|
* 调用学校 OA 创建待办接口,接口失败时直接抛出异常,让本系统事务回滚。
|
||||||
*/
|
*/
|
||||||
@@ -354,6 +389,59 @@ public class SchoolOaTodoServiceImpl implements SchoolOaTodoService {
|
|||||||
return baseUrl + separator + "taskId=" + task.getId() + "&instanceId=" + task.getProcessInstanceId();
|
return baseUrl + separator + "taskId=" + task.getId() + "&instanceId=" + task.getProcessInstanceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按学校OA固定待办格式创建福利选择提醒,标题承载自定义提醒内容。
|
||||||
|
*/
|
||||||
|
private void sendWelfareReminderTodo(String projectId, String title, String pcUrl, String appUrl,
|
||||||
|
Sys_user creator, Sys_user receiver, String creatorTime) {
|
||||||
|
JSONObject body = new JSONObject();
|
||||||
|
body.set("flowTypeName", "福利选择");
|
||||||
|
body.set("flowId", "welfare_reminder_" + projectId);
|
||||||
|
body.set("title", title);
|
||||||
|
body.set("stepName", "福利选择提醒");
|
||||||
|
body.set("creatorCode", creator.getLoginname());
|
||||||
|
body.set("creatorName", creator.getUsername());
|
||||||
|
body.set("creatorTime", creatorTime);
|
||||||
|
body.set("pcUrl", pcUrl);
|
||||||
|
body.set("appUrl", appUrl);
|
||||||
|
body.set("pcPreviewUrl", pcUrl);
|
||||||
|
body.set("appPreviewUrl", appUrl);
|
||||||
|
body.set("uniqueId", buildWelfareReminderUniqueId(projectId, receiver.getId()));
|
||||||
|
body.set("receiveCode", receiver.getLoginname());
|
||||||
|
body.set("receiveName", receiver.getUsername());
|
||||||
|
body.set("receiveTime", creatorTime);
|
||||||
|
|
||||||
|
String insertUrl = requireConfig("school-oa.todo.insert-url");
|
||||||
|
String requestBody = JSONUtil.toJsonStr(body);
|
||||||
|
log.info("学校OA福利选择提醒待办创建请求,url={},projectId={},receiveCode={},body={}",
|
||||||
|
insertUrl, projectId, receiver.getLoginname(), requestBody);
|
||||||
|
try {
|
||||||
|
HttpRequest request = HttpUtil.createPost(insertUrl);
|
||||||
|
setTodoRequestHeaders(request);
|
||||||
|
request.body(requestBody);
|
||||||
|
String responseBody = request.execute().body();
|
||||||
|
JSONObject response = JSONUtil.parseObj(responseBody);
|
||||||
|
if (response.getInt("state", 0) != 200) {
|
||||||
|
throw new BaseException("学校OA福利选择提醒待办创建失败:{}", response.getStr("message", responseBody));
|
||||||
|
}
|
||||||
|
log.info("学校OA福利选择提醒待办创建成功,projectId={},receiveCode={},response={}",
|
||||||
|
projectId, receiver.getLoginname(), responseBody);
|
||||||
|
} catch (BaseException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("学校OA福利选择提醒待办创建异常,url={},projectId={},receiveCode={},body={}",
|
||||||
|
insertUrl, projectId, receiver.getLoginname(), requestBody, e);
|
||||||
|
throw new BaseException("学校OA福利选择提醒待办创建异常:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 福利提醒待办按项目和接收人保持唯一;用户完成选择后可据此精确删除待办。
|
||||||
|
*/
|
||||||
|
private String buildWelfareReminderUniqueId(String projectId, String userId) {
|
||||||
|
return "welfare_reminder_" + projectId + "_" + userId;
|
||||||
|
}
|
||||||
|
|
||||||
private String buildAppTaskUrl(String h5FormKey, ProcessTask task) {
|
private String buildAppTaskUrl(String h5FormKey, ProcessTask task) {
|
||||||
// 部分流程没有配置 H5 审核页,学校 OA 的移动端地址为空时按要求传固定域名兜底。
|
// 部分流程没有配置 H5 审核页,学校 OA 的移动端地址为空时按要求传固定域名兜底。
|
||||||
if (StrUtil.isBlank(h5FormKey)) {
|
if (StrUtil.isBlank(h5FormKey)) {
|
||||||
|
|||||||
+23
@@ -94,9 +94,32 @@ public class WelfareSelectionSituationController {
|
|||||||
welfareUserSelection.setSelectTime(new Date());
|
welfareUserSelection.setSelectTime(new Date());
|
||||||
}
|
}
|
||||||
dao.insert(selections);
|
dao.insert(selections);
|
||||||
|
situationService.clearReminderTodo(projectId, userId);
|
||||||
return Result.success("选择成功");
|
return Result.success("选择成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("welfare.selection.situation")
|
||||||
|
@ApiOperation("预览福利选择提醒接收人数")
|
||||||
|
public Result previewReminder(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm, @Param("userIds") String[] userIds) {
|
||||||
|
return Result.success(situationService.countReminderRecipients(pageForm, userIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SLog(type = "welfare", tag = "选择情况", msg = "发送福利选择提醒")
|
||||||
|
@SaCheckPermission("welfare.selection.situation")
|
||||||
|
@ApiOperation("发送福利选择提醒")
|
||||||
|
public Result sendReminder(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm, @Param("userIds") String[] userIds, String content) {
|
||||||
|
if (StrUtil.isBlank(content)) {
|
||||||
|
return Result.error("提醒内容不能为空");
|
||||||
|
}
|
||||||
|
int recipientCount = situationService.sendReminder(pageForm, userIds, content.trim());
|
||||||
|
if (recipientCount == 0) {
|
||||||
|
return Result.error("当前筛选条件下没有可提醒的人员");
|
||||||
|
}
|
||||||
|
return Result.success("提醒已发送给" + recipientCount + "人");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("welfare.selection.situation")
|
@SaCheckPermission("welfare.selection.situation")
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.budwk.app.zhgh.welfare.model.WelfareList;
|
|||||||
import com.budwk.app.zhgh.welfare.model.WelfareProject;
|
import com.budwk.app.zhgh.welfare.model.WelfareProject;
|
||||||
import com.budwk.app.zhgh.welfare.model.WelfareUserSelection;
|
import com.budwk.app.zhgh.welfare.model.WelfareUserSelection;
|
||||||
import com.budwk.app.zhgh.welfare.service.WelfareProjectService;
|
import com.budwk.app.zhgh.welfare.service.WelfareProjectService;
|
||||||
|
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
@@ -37,6 +38,8 @@ public class WelfareUserSelectController {
|
|||||||
private Dao dao;
|
private Dao dao;
|
||||||
@Inject
|
@Inject
|
||||||
private WelfareProjectService welfareProjectService;
|
private WelfareProjectService welfareProjectService;
|
||||||
|
@Inject
|
||||||
|
private WelfareSelectionSituationService situationService;
|
||||||
|
|
||||||
@At("")
|
@At("")
|
||||||
@Ok("beetl:/platform/zhgh/welfare/select/index.html")
|
@Ok("beetl:/platform/zhgh/welfare/select/index.html")
|
||||||
@@ -103,6 +106,7 @@ public class WelfareUserSelectController {
|
|||||||
welfareUserSelection.setSelectTime(new Date());
|
welfareUserSelection.setSelectTime(new Date());
|
||||||
}
|
}
|
||||||
dao.insert(selections);
|
dao.insert(selections);
|
||||||
|
situationService.clearReminderTodo(projectId, SecurityUtil.getUserId());
|
||||||
return Result.success("选择成功");
|
return Result.success("选择成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
@@ -14,4 +14,31 @@ public interface WelfareSelectionSituationService extends BaseService<WelfareLis
|
|||||||
void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
|
void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
|
||||||
void receiveXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
|
void receiveXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计当前筛选范围内可接收提醒的人员数量。
|
||||||
|
*
|
||||||
|
* @param pageForm 当前页面筛选条件
|
||||||
|
* @param userIds 已勾选的人员ID;为空时按筛选条件查询全部人员
|
||||||
|
* @return 去重后的接收人数量
|
||||||
|
*/
|
||||||
|
int countReminderRecipients(WelfareSelectionSituationPageForm pageForm, String[] userIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向当前筛选范围内的人员发送福利选择提醒。
|
||||||
|
*
|
||||||
|
* @param pageForm 当前页面筛选条件
|
||||||
|
* @param userIds 已勾选的人员ID;为空时按筛选条件查询全部人员
|
||||||
|
* @param content 自定义提醒内容
|
||||||
|
* @return 实际发送的去重后接收人数量
|
||||||
|
*/
|
||||||
|
int sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户完成福利选择后清除对应的学校OA提醒待办。
|
||||||
|
*
|
||||||
|
* @param projectId 福利项目ID
|
||||||
|
* @param userId 完成选择的用户ID
|
||||||
|
*/
|
||||||
|
void clearReminderTodo(String projectId, String userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+120
-6
@@ -13,10 +13,15 @@ import com.budwk.app.base.service.impl.BaseServiceImpl;
|
|||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.PageUtil;
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
//import com.budwk.app.sys.models.Sys_file;
|
//import com.budwk.app.sys.models.Sys_file;
|
||||||
|
import com.budwk.app.base.sms.SmsService;
|
||||||
|
import com.budwk.app.flow.service.SchoolOaTodoService;
|
||||||
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
import com.budwk.app.sys.services.SysFileService;
|
import com.budwk.app.sys.services.SysFileService;
|
||||||
|
import com.budwk.app.web.commons.base.Globals;
|
||||||
//import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
//import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
||||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.message.strategy.impl.LocalMessageSendStrategy;
|
||||||
import com.budwk.app.zhgh.welfare.model.WelfareList;
|
import com.budwk.app.zhgh.welfare.model.WelfareList;
|
||||||
import com.budwk.app.zhgh.welfare.model.WelfareProject;
|
import com.budwk.app.zhgh.welfare.model.WelfareProject;
|
||||||
import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
|
import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
|
||||||
@@ -51,6 +56,12 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SysFileService sysFileService;
|
private SysFileService sysFileService;
|
||||||
|
@Inject
|
||||||
|
private LocalMessageSendStrategy localMessageSendStrategy;
|
||||||
|
@Inject
|
||||||
|
private SmsService smsService;
|
||||||
|
@Inject
|
||||||
|
private SchoolOaTodoService schoolOaTodoService;
|
||||||
@Override
|
@Override
|
||||||
public Pagination pageData(WelfareSelectionSituationPageForm pageForm) {
|
public Pagination pageData(WelfareSelectionSituationPageForm pageForm) {
|
||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
@@ -113,6 +124,107 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int countReminderRecipients(WelfareSelectionSituationPageForm pageForm, String[] userIds) {
|
||||||
|
return getReminderRecipientIds(pageForm, userIds).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int sendReminder(WelfareSelectionSituationPageForm pageForm, String[] userIds, String content) {
|
||||||
|
List<String> recipientIds = getReminderRecipientIds(pageForm, userIds);
|
||||||
|
if (recipientIds.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
String title = "福利选择提醒";
|
||||||
|
String pcUrl = buildWelfareSelectionUrl("/platform/welfare/userSelect");
|
||||||
|
String appUrl = buildWelfareSelectionUrl("/platform/h5/welfare/userSelect/list");
|
||||||
|
|
||||||
|
// 本地消息始终发送,确保外部渠道关闭时仍可在系统内查看提醒。
|
||||||
|
localMessageSendStrategy.send(title, content, 2, recipientIds, null);
|
||||||
|
|
||||||
|
List<String> receiverLoginNames = dao().query(Sys_user.class, Cnd.where(Sys_user::getId, "in", recipientIds)).stream()
|
||||||
|
.map(Sys_user::getLoginname)
|
||||||
|
.filter(StrUtil::isNotBlank)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
// AppSms 控制学校消息平台发送,消息链接跳转到手机端福利选择列表。
|
||||||
|
if (Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSms")) && !receiverLoginNames.isEmpty()) {
|
||||||
|
smsService.massSend(receiverLoginNames, title, content, appUrl);
|
||||||
|
}
|
||||||
|
// AppSchoolOa 控制学校OA待办;学校OA没有正文栏位,标题使用自定义提醒内容。
|
||||||
|
if (Boolean.TRUE.equals(Globals.MyConfig.getBoolean("AppSchoolOa"))) {
|
||||||
|
schoolOaTodoService.createWelfareReminderTodos(pageForm.getProjectId(), title + ":" + content,
|
||||||
|
pcUrl, appUrl, SecurityUtil.getUserId(), recipientIds);
|
||||||
|
}
|
||||||
|
return recipientIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearReminderTodo(String projectId, String userId) {
|
||||||
|
try {
|
||||||
|
schoolOaTodoService.deleteWelfareReminderTodo(projectId, userId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 学校OA删除失败不能影响用户完成福利选择,后续可根据日志人工处理。
|
||||||
|
log.error("删除学校OA福利选择提醒待办失败,projectId={},userId={}", projectId, userId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用系统配置的绝对域名构造学校外部平台可访问的福利选择地址。
|
||||||
|
*/
|
||||||
|
private String buildWelfareSelectionUrl(String path) {
|
||||||
|
return StrUtil.removeSuffix(Globals.AppDomain, "/") + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据当前筛选条件和数据权限获取提醒接收人,避免前端传入范围外人员。
|
||||||
|
*/
|
||||||
|
private List<String> getReminderRecipientIds(WelfareSelectionSituationPageForm pageForm, String[] userIds) {
|
||||||
|
if (StrUtil.isBlank(pageForm.getProjectId())) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT DISTINCT
|
||||||
|
t1.userId
|
||||||
|
FROM
|
||||||
|
welfare_list t1
|
||||||
|
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId AND t2.selectUserId = t1.userId
|
||||||
|
LEFT JOIN sys_user t4 ON t4.id = t1.userId
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()) || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ADMIN.name()) || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WENTI_SPORTS.name())) {
|
||||||
|
cnd.and("t1.welfareUnionId", "=", SecurityUtil.getUnionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
cnd.and("t1.projectId", "=", pageForm.getProjectId());
|
||||||
|
cnd.andEX("t2.selectOptionId", "=", pageForm.getWelfareOptionId());
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getUserName())) {
|
||||||
|
cnd.where().andLike("t4.username", pageForm.getUserName());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getLoginName())) {
|
||||||
|
cnd.where().andLike("t4.loginname", pageForm.getLoginName());
|
||||||
|
}
|
||||||
|
cnd.andEX("t1.welfareUnitId", "in", pageForm.getUnitIds());
|
||||||
|
cnd.andEX("t1.welfareUnionId", "=", pageForm.getUnionId());
|
||||||
|
if (pageForm.getIsSelect() != null) {
|
||||||
|
cnd.and("t2.id", pageForm.getIsSelect() ? "IS NOT" : "IS", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> selectedUserIds = Arrays.stream(userIds == null ? new String[0] : userIds)
|
||||||
|
.filter(StrUtil::isNotBlank)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
cnd.andEX("t1.userId", "in", selectedUserIds.toArray(new String[0]));
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
return listMap(sql).stream()
|
||||||
|
.map(map -> map.getString("userId"))
|
||||||
|
.filter(StrUtil::isNotBlank)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
|
public void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
|
||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
@@ -124,6 +236,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
|
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
|
||||||
GROUP_CONCAT(DISTINCT t2.userName) AS userName2,
|
GROUP_CONCAT(DISTINCT t2.userName) AS userName2,
|
||||||
GROUP_CONCAT(DISTINCT t2.receiveAddress) AS receiveAddress,
|
GROUP_CONCAT(DISTINCT t2.receiveAddress) AS receiveAddress,
|
||||||
|
GROUP_CONCAT(DISTINCT CASE WHEN t2.createdBy IS NOT NULL AND t2.createdBy <> t2.selectUserId THEN CONCAT(t5.username, '代选') END) AS remark,
|
||||||
t4.username AS userName,
|
t4.username AS userName,
|
||||||
t4.loginname AS loginName,
|
t4.loginname AS loginName,
|
||||||
t4.sex
|
t4.sex
|
||||||
@@ -132,6 +245,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId AND t2.selectUserId = t1.userId
|
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId AND t2.selectUserId = t1.userId
|
||||||
LEFT JOIN welfare_project_subject_option t3 ON t3.id = t2.selectOptionId
|
LEFT JOIN welfare_project_subject_option t3 ON t3.id = t2.selectOptionId
|
||||||
LEFT JOIN sys_user t4 ON t4.id = t1.userId
|
LEFT JOIN sys_user t4 ON t4.id = t1.userId
|
||||||
|
LEFT JOIN sys_user t5 ON t5.id = t2.createdBy
|
||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
@@ -189,6 +303,8 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
if(project.getProvideMode() == 3){
|
if(project.getProvideMode() == 3){
|
||||||
entities.add(new ExcelExportEntity("收货地址", "receiveAddress", 40));
|
entities.add(new ExcelExportEntity("收货地址", "receiveAddress", 40));
|
||||||
}
|
}
|
||||||
|
// 备注仅反映当前选择记录的创建人;本人重新选择后创建人变为本人,备注自动为空。
|
||||||
|
entities.add(new ExcelExportEntity("备注", "remark", 20));
|
||||||
|
|
||||||
// 设置导出参数
|
// 设置导出参数
|
||||||
ExportParams exportParams = new ExportParams();
|
ExportParams exportParams = new ExportParams();
|
||||||
@@ -257,9 +373,9 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
return map;
|
return map;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
// 分组
|
// 按所属工会分组生成工作表;历史名单可能缺少工会名称,统一归入未分配工会,避免空分组键导致导出失败。
|
||||||
Map<String, List<Map<String, Object>>> listMap = safeList.stream()
|
Map<String, List<Map<String, Object>>> listMap = safeList.stream()
|
||||||
.collect(Collectors.groupingBy(n -> (String) n.get("welfareUnionName")));
|
.collect(Collectors.groupingBy(n -> StrUtil.blankToDefault((String) n.get("welfareUnionName"), "未分配工会")));
|
||||||
|
|
||||||
// 构建 Excel 列
|
// 构建 Excel 列
|
||||||
List<ExcelExportEntity> entities = new ArrayList<>();
|
List<ExcelExportEntity> entities = new ArrayList<>();
|
||||||
@@ -268,10 +384,8 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
optionList.forEach(option -> {
|
optionList.forEach(option -> {
|
||||||
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
|
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
|
||||||
});
|
});
|
||||||
ExcelExportEntity userSignEntity = new ExcelExportEntity("签字", "userSign", 20);
|
// 签字功能已取消,保留空白文本列供线下签字,不能按图片类型导出。
|
||||||
userSignEntity.setType(2);
|
entities.add(new ExcelExportEntity("签字", "userSign", 20));
|
||||||
userSignEntity.setExportImageType(2);
|
|
||||||
entities.add(userSignEntity);
|
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
Workbook workbook = new HSSFWorkbook();
|
Workbook workbook = new HSSFWorkbook();
|
||||||
|
|||||||
+11
-3
@@ -387,6 +387,8 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
|
|||||||
exportEntities.add(new ExcelExportEntity("所在分工会", "welfareUnionName", 20));
|
exportEntities.add(new ExcelExportEntity("所在分工会", "welfareUnionName", 20));
|
||||||
exportEntities.add(new ExcelExportEntity("所在单位", "welfareUnitName", 20));
|
exportEntities.add(new ExcelExportEntity("所在单位", "welfareUnitName", 20));
|
||||||
exportEntities.add(new ExcelExportEntity("所选福利", "selectOptionName", 50));
|
exportEntities.add(new ExcelExportEntity("所选福利", "selectOptionName", 50));
|
||||||
|
// 备注仅反映当前选择记录的创建人;本人重新选择后创建人变为本人,备注自动为空。
|
||||||
|
exportEntities.add(new ExcelExportEntity("备注", "remark", 20));
|
||||||
|
|
||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
@@ -397,13 +399,15 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
|
|||||||
wpus.mobile,
|
wpus.mobile,
|
||||||
wpus.selectOptionId,
|
wpus.selectOptionId,
|
||||||
wpso.optionName,
|
wpso.optionName,
|
||||||
GROUP_CONCAT(DISTINCT wpso.optionName, '(', wpus.selectNum, '份)') selectOptionName
|
GROUP_CONCAT(DISTINCT wpso.optionName, '(', wpus.selectNum, '份)') selectOptionName,
|
||||||
|
GROUP_CONCAT(DISTINCT CASE WHEN wpus.createdBy IS NOT NULL AND wpus.createdBy <> wpus.selectUserId THEN CONCAT(selectOperator.username, '代选') END) AS remark
|
||||||
FROM
|
FROM
|
||||||
welfare_project_user_selection wpus
|
welfare_project_user_selection wpus
|
||||||
LEFT JOIN welfare_list wl ON wl.userId = wpus.selectUserId
|
LEFT JOIN welfare_list wl ON wl.userId = wpus.selectUserId
|
||||||
AND wl.projectId = wpus.welfareId
|
AND wl.projectId = wpus.welfareId
|
||||||
LEFT JOIN sys_user u ON u.id = wpus.selectUserId
|
LEFT JOIN sys_user u ON u.id = wpus.selectUserId
|
||||||
LEFT JOIN welfare_project_subject_option wpso ON wpso.id = wpus.selectOptionId
|
LEFT JOIN welfare_project_subject_option wpso ON wpso.id = wpus.selectOptionId
|
||||||
|
LEFT JOIN sys_user selectOperator ON selectOperator.id = wpus.createdBy
|
||||||
WHERE
|
WHERE
|
||||||
wpus.welfareId = @projectId
|
wpus.welfareId = @projectId
|
||||||
GROUP BY
|
GROUP BY
|
||||||
@@ -498,11 +502,15 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
|
|||||||
|
|
||||||
for (NutMap union : mapUnions) {
|
for (NutMap union : mapUnions) {
|
||||||
// 福利人数
|
// 福利人数
|
||||||
long teacherSum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id"))).count();
|
long teacherSum = welfareSelectionList.stream()
|
||||||
|
.filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId").equals(union.getString("id")))
|
||||||
|
.count();
|
||||||
union.put("teacherSum", teacherSum);
|
union.put("teacherSum", teacherSum);
|
||||||
|
|
||||||
// 已选人数
|
// 已选人数
|
||||||
long selectedNum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
|
long selectedNum = welfareSelectionList.stream()
|
||||||
|
.filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId").equals(union.getString("id")) && v.getBoolean("has_selected"))
|
||||||
|
.count();
|
||||||
union.put("selectedNum", selectedNum);
|
union.put("selectedNum", selectedNum);
|
||||||
|
|
||||||
// 未选人数
|
// 未选人数
|
||||||
|
|||||||
@@ -66,11 +66,9 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
<el-card class="mt10" shadow="never">
|
<el-card class="mt10" shadow="never">
|
||||||
<table-tool :app="this" label="选择情况">
|
<table-tool :app="this" label="选择情况">
|
||||||
<el-radio-group v-model="pageForm.isSelect" size="small" @change="doSearch">
|
<el-button type="primary" size="small" icon="el-icon-message" @click="openReminder">
|
||||||
<el-radio-button :label="null">全部</el-radio-button>
|
一键提醒
|
||||||
<el-radio-button :label="true">已选择</el-radio-button>
|
</el-button>
|
||||||
<el-radio-button :label="false">未选择</el-radio-button>
|
|
||||||
</el-radio-group>
|
|
||||||
|
|
||||||
<el-button type="primary" size="small" icon="el-icon-download" style="margin-left: 10px" @click="exportXlsx">
|
<el-button type="primary" size="small" icon="el-icon-download" style="margin-left: 10px" @click="exportXlsx">
|
||||||
导出选择情况表
|
导出选择情况表
|
||||||
@@ -79,17 +77,25 @@ layout("/layouts/platform.html"){
|
|||||||
<el-button type="primary" size="small" icon="el-icon-download" style="margin-left: 10px" @click="receiveXlsx">
|
<el-button type="primary" size="small" icon="el-icon-download" style="margin-left: 10px" @click="receiveXlsx">
|
||||||
导出领取表
|
导出领取表
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
<el-radio-group v-model="pageForm.isSelect" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="null">全部</el-radio-button>
|
||||||
|
<el-radio-button :label="true">已选择</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未选择</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
</table-tool>
|
</table-tool>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:size="tableSize"
|
:size="tableSize"
|
||||||
@sort-change="pageOrder"
|
@sort-change="pageOrder"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-loading="tableLoading"
|
v-loading="tableLoading"
|
||||||
>
|
>
|
||||||
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
<el-table-column :index="indexMethod" label="序号" type="index" width="80px"></el-table-column>
|
<el-table-column :index="indexMethod" label="序号" type="index" width="80px"></el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
@@ -118,6 +124,19 @@ layout("/layouts/platform.html"){
|
|||||||
<el-dialog title="代选" :visible.sync="optionSelectVisible" width="60%">
|
<el-dialog title="代选" :visible.sync="optionSelectVisible" width="60%">
|
||||||
<option-select ref="optionSelectRef" @refresh="optionSelectVisible=false;doSearch();"></option-select>
|
<option-select ref="optionSelectRef" @refresh="optionSelectVisible=false;doSearch();"></option-select>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog title="发送福利选择提醒" :visible.sync="reminderVisible" width="500px" :close-on-click-modal="false">
|
||||||
|
<el-alert :title="'本次将向' + reminderCount + '人发送消息'" type="warning" :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>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="closeReminder">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="reminderSending" @click="sendReminder">确认发送</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</guava>
|
</guava>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -150,7 +169,12 @@ layout("/layouts/platform.html"){
|
|||||||
{ prop: "selectedOptions", label: "所选福利", sortable: true },
|
{ prop: "selectedOptions", label: "所选福利", sortable: true },
|
||||||
{ prop: "mobile", label: "联系电话", sortable: true }
|
{ prop: "mobile", label: "联系电话", sortable: true }
|
||||||
],
|
],
|
||||||
optionSelectVisible: false
|
optionSelectVisible: false,
|
||||||
|
selectedRows: [],
|
||||||
|
reminderVisible: false,
|
||||||
|
reminderContent: "",
|
||||||
|
reminderCount: 0,
|
||||||
|
reminderSending: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -204,6 +228,75 @@ layout("/layouts/platform.html"){
|
|||||||
this.$downLoad("/platform/welfare/selection/situation/receiveXlsx", { pageForm: JSON.stringify(this.pageForm) })
|
this.$downLoad("/platform/welfare/selection/situation/receiveXlsx", { pageForm: JSON.stringify(this.pageForm) })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 记录当前表格勾选人员;未勾选时提醒当前筛选范围内的全部人员。
|
||||||
|
handleSelectionChange(rows) {
|
||||||
|
this.$set(this, "selectedRows", rows)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 构建提醒请求参数,数组参数使用表单格式,保证后端可以绑定为 String[]。
|
||||||
|
buildReminderRequest() {
|
||||||
|
const params = ["pageForm=" + encodeURIComponent(JSON.stringify(this.pageForm))]
|
||||||
|
this.selectedRows.map((row) => row.userId).forEach((userId) => {
|
||||||
|
params.push("userIds=" + encodeURIComponent(userId))
|
||||||
|
})
|
||||||
|
return params.join("&")
|
||||||
|
},
|
||||||
|
|
||||||
|
// 发送前由后端按当前筛选条件计算实际接收人数。
|
||||||
|
async openReminder() {
|
||||||
|
if (!this.pageForm.projectId) {
|
||||||
|
this.$message.warning("请先选择福利项目")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const response = await this.$axios.post(
|
||||||
|
"/platform/welfare/selection/situation/previewReminder",
|
||||||
|
this.buildReminderRequest(),
|
||||||
|
{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }
|
||||||
|
)
|
||||||
|
if (response.code !== 0) {
|
||||||
|
this.$message.error(response.msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (response.data === 0) {
|
||||||
|
this.$message.warning("当前筛选条件下没有可提醒的人员")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$set(this, "reminderCount", response.data)
|
||||||
|
this.$set(this, "reminderContent", "福利选择提醒:请及时完成本次福利选择。")
|
||||||
|
this.$set(this, "reminderVisible", true)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 后端会在发送前再次计算接收人,确保发送范围符合当前权限和筛选条件。
|
||||||
|
async sendReminder() {
|
||||||
|
if (!this.reminderContent || !this.reminderContent.trim()) {
|
||||||
|
this.$message.warning("请输入提醒内容")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$set(this, "reminderSending", true)
|
||||||
|
const request = this.buildReminderRequest() + "&content=" + encodeURIComponent(this.reminderContent.trim())
|
||||||
|
try {
|
||||||
|
const response = await this.$axios.post(
|
||||||
|
"/platform/welfare/selection/situation/sendReminder",
|
||||||
|
request,
|
||||||
|
{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }
|
||||||
|
)
|
||||||
|
if (response.code === 0) {
|
||||||
|
this.$message.success(response.msg)
|
||||||
|
this.closeReminder()
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.msg)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.$set(this, "reminderSending", false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关闭提醒弹窗并清空输入内容,避免下次发送误用上次的消息。
|
||||||
|
closeReminder() {
|
||||||
|
this.$set(this, "reminderVisible", false)
|
||||||
|
this.$set(this, "reminderContent", "")
|
||||||
|
},
|
||||||
|
|
||||||
// 管理员待选
|
// 管理员待选
|
||||||
proxySelect(row) {
|
proxySelect(row) {
|
||||||
this.optionSelectVisible = true
|
this.optionSelectVisible = true
|
||||||
|
|||||||
Reference in New Issue
Block a user