Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -1,39 +1,56 @@
|
|||||||
package com.budwk.app.base.sms;
|
package com.budwk.app.base.sms;
|
||||||
|
|
||||||
|
import com.budwk.app.base.sms.model.MsgPlatformResponse;
|
||||||
|
import com.budwk.app.base.sms.model.MsgPlatformSmsRequest;
|
||||||
|
import com.budwk.app.base.sms.model.MsgPlatformWechatRequest;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface SmsService {
|
public interface SmsService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单发
|
* 发送短信消息。
|
||||||
* @param loginName 工号
|
*
|
||||||
* @param content 内容
|
* @param request 短信请求参数,需传接收人、发送人、模板ID或消息内容等字段
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
*/
|
*/
|
||||||
void send(String loginName, String content);
|
MsgPlatformResponse sendSms(MsgPlatformSmsRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单发
|
* 通过工号发送短信文本消息的便捷方法。
|
||||||
* @param loginName 工号
|
* controller 只需要传接收人工号,以及短信内容即可。
|
||||||
* @param title 标题
|
*
|
||||||
* @param content 内容
|
* @param account 接收人工号
|
||||||
|
* @param content 短信内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
*/
|
*/
|
||||||
void send(String loginName, String title, String content);
|
MsgPlatformResponse sendSmsByAccount(String account, String content);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单发
|
* 通过手机号发送短信文本消息的便捷方法。
|
||||||
* @param loginName 工号
|
* controller 只需要传接收人手机号,以及短信内容即可。
|
||||||
* @param title 标题
|
*
|
||||||
* @param content 内容
|
* @param mobile 接收人手机号
|
||||||
* @param link 链接
|
* @param content 短信内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
*/
|
*/
|
||||||
void send(String loginName, String title, String content, String link);
|
MsgPlatformResponse sendSmsByMobile(String mobile, String content);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 群发 多人接收内容相同时使用该方法
|
* 发送微信消息。
|
||||||
* @param loginNames 工号
|
*
|
||||||
* @param title 标题
|
* @param request 微信请求参数,需传接收人、发送人、消息类型、模板ID或消息内容等字段
|
||||||
* @param content 内容
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
* @param link 链接
|
|
||||||
*/
|
*/
|
||||||
void massSend(List<String> loginNames, String title, String content, String link);
|
MsgPlatformResponse sendWechat(MsgPlatformWechatRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送微信文本消息的便捷方法。
|
||||||
|
* controller 只需要传接收人工号或手机号,以及微信文本内容即可。
|
||||||
|
*
|
||||||
|
* @param accountOrMobile 接收人工号或手机号
|
||||||
|
* @param content 微信文本内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
MsgPlatformResponse sendWechatTextByAccountOrMobile(String accountOrMobile, String content);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,544 @@
|
|||||||
|
package com.budwk.app.base.sms.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import cn.hutool.http.HttpRequest;
|
||||||
|
import cn.hutool.http.HttpResponse;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
|
import com.budwk.app.base.sms.SmsService;
|
||||||
|
import com.budwk.app.base.sms.model.*;
|
||||||
|
import com.budwk.app.web.commons.base.Globals;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.integration.jedis.RedisService;
|
||||||
|
import org.nutz.ioc.impl.PropertiesProxy;
|
||||||
|
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 org.nutz.lang.Strings;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
import org.nutz.log.Log;
|
||||||
|
import org.nutz.log.Logs;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SmsJshvcServiceImpl
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/11/26 19:32
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean
|
||||||
|
public class SmsServiceImpl implements SmsService {
|
||||||
|
private static final Log log = Logs.get();
|
||||||
|
private static final String SMS_API_PATH = "/tp_mp/api/SmsService/saveSmsInfo";
|
||||||
|
private static final String WECHAT_API_PATH = "/tp_mp/api/WechatService/saveWechatInfo";
|
||||||
|
private static final int MAX_RECEIVER_COUNT = 500;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PropertiesProxy conf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送短信消息。
|
||||||
|
*
|
||||||
|
* @param request 短信请求参数,需传接收人、发送人、模板ID或消息内容等字段
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MsgPlatformResponse sendSms(MsgPlatformSmsRequest request) {
|
||||||
|
validateCommonRequest(request);
|
||||||
|
JSONObject payload = buildCommonPayload(request, true);
|
||||||
|
return doPost(SMS_API_PATH, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过工号发送短信文本消息的便捷方法。
|
||||||
|
* 该方法适合 controller 里只传“工号 + 内容”的简单场景,发送人信息从配置中读取。
|
||||||
|
*
|
||||||
|
* @param account 接收人工号
|
||||||
|
* @param content 短信内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MsgPlatformResponse sendSmsByAccount(String account, String content) {
|
||||||
|
MsgPlatformSmsRequest request = new MsgPlatformSmsRequest();
|
||||||
|
request.setInfo(content);
|
||||||
|
request.setRecipients(buildAccountRecipients(account));
|
||||||
|
fillDefaultSenderInfo(request);
|
||||||
|
return sendSms(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过手机号发送短信文本消息的便捷方法。
|
||||||
|
* 该方法适合 controller 里只传“手机号 + 内容”的简单场景,发送人信息从配置中读取。
|
||||||
|
*
|
||||||
|
* @param mobile 接收人手机号
|
||||||
|
* @param content 短信内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MsgPlatformResponse sendSmsByMobile(String mobile, String content) {
|
||||||
|
MsgPlatformSmsRequest request = new MsgPlatformSmsRequest();
|
||||||
|
request.setInfo(content);
|
||||||
|
request.setRecipients(buildMobileRecipients(mobile));
|
||||||
|
request.setCustomVar(Map.of("1","","2","","3",content));
|
||||||
|
fillDefaultSenderInfo(request);
|
||||||
|
return sendSms(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送微信消息。
|
||||||
|
*
|
||||||
|
* @param request 微信请求参数,需传接收人、发送人、消息类型、模板ID或消息内容等字段
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MsgPlatformResponse sendWechat(MsgPlatformWechatRequest request) {
|
||||||
|
validateCommonRequest(request);
|
||||||
|
if (Strings.isBlank(request.getWechatType())) {
|
||||||
|
request.setWechatType("text");
|
||||||
|
}
|
||||||
|
if ("news".equalsIgnoreCase(request.getWechatType()) && Strings.isBlank(request.getInfo())) {
|
||||||
|
if (request.getNewsItems() == null || request.getNewsItems().isEmpty()) {
|
||||||
|
throw new BaseException("微信图文消息必须传 info 或 newsItems");
|
||||||
|
}
|
||||||
|
request.setInfo(JSONUtil.toJsonStr(request.getNewsItems()));
|
||||||
|
}
|
||||||
|
JSONObject payload = buildCommonPayload(request, false);
|
||||||
|
payload.set("wechat_type", request.getWechatType());
|
||||||
|
return doPost(WECHAT_API_PATH, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送微信文本消息的便捷方法。
|
||||||
|
* 该方法适合 controller 里只传“工号/手机号 + 内容”的简单场景,发送人信息从配置中读取。
|
||||||
|
*
|
||||||
|
* @param accountOrMobile 接收人工号或手机号
|
||||||
|
* @param content 微信文本内容
|
||||||
|
* @return 通讯平台返回结果,返回类型为 {@link MsgPlatformResponse}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MsgPlatformResponse sendWechatTextByAccountOrMobile(String accountOrMobile, String content) {
|
||||||
|
MsgPlatformWechatRequest request = new MsgPlatformWechatRequest();
|
||||||
|
request.setInfo(content);
|
||||||
|
request.setWechatType("text");
|
||||||
|
request.setRecipients(buildWechatRecipients(accountOrMobile));
|
||||||
|
fillDefaultSenderInfo(request);
|
||||||
|
return sendWechat(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装平台公共请求体。
|
||||||
|
*
|
||||||
|
* @param request 平台请求参数
|
||||||
|
* @param includeMobile 是否在 person_info 第 5 段写入手机号
|
||||||
|
* @return 返回发送给第三方平台的 JSON 对象
|
||||||
|
*/
|
||||||
|
private JSONObject buildCommonPayload(MsgPlatformBaseRequest request, boolean includeMobile) {
|
||||||
|
JSONObject payload = new JSONObject();
|
||||||
|
payload.set("tp_name", getRequiredConfig("msg.platform.tp-name", "请先配置 msg.platform.tp-name"));
|
||||||
|
payload.set("secret_key", getSecretKey());
|
||||||
|
payload.set("person_info", resolvePersonInfo(request, includeMobile));
|
||||||
|
payload.set("template_id", Strings.sNull(request.getTemplateId()));
|
||||||
|
payload.set("info", Strings.sNull(request.getInfo()));
|
||||||
|
payload.set("send_priority", Strings.isBlank(request.getSendPriority()) ? "3" : request.getSendPriority());
|
||||||
|
payload.set("send_user_id", Strings.sNull(request.getSendUserId()));
|
||||||
|
payload.set("send_user_name", Strings.sNull(request.getSendUserName()));
|
||||||
|
payload.set("send_time", Strings.sNull(request.getSendTime()));
|
||||||
|
payload.set("send_unit_id", Strings.sNull(request.getSendUnitId()));
|
||||||
|
payload.set("send_unit_name", Strings.sNull(request.getSendUnitName()));
|
||||||
|
payload.set("send_user_sign", Strings.sNull(request.getSendUserSign()));
|
||||||
|
payload.set("receipt_id", Strings.isBlank(request.getReceiptId()) ? "0" : request.getReceiptId());
|
||||||
|
if (request.getCustomVar() != null && !request.getCustomVar().isEmpty()) {
|
||||||
|
payload.set("custom_var", JSONUtil.toJsonStr(request.getCustomVar()));
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验公共请求参数,避免 controller 传错参数后才到第三方接口报错。
|
||||||
|
*
|
||||||
|
* @param request 平台请求参数
|
||||||
|
*/
|
||||||
|
private void validateCommonRequest(MsgPlatformBaseRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
throw new BaseException("请求参数不能为空");
|
||||||
|
}
|
||||||
|
if (Strings.isBlank(request.getPersonInfo()) && (request.getRecipients() == null || request.getRecipients().isEmpty())) {
|
||||||
|
throw new BaseException("personInfo 和 recipients 不能同时为空");
|
||||||
|
}
|
||||||
|
if (Strings.isBlank(request.getTemplateId()) && Strings.isBlank(request.getInfo())) {
|
||||||
|
throw new BaseException("templateId 和 info 至少需要传一个");
|
||||||
|
}
|
||||||
|
if (Strings.isBlank(request.getSendUserId())) {
|
||||||
|
throw new BaseException("sendUserId 不能为空");
|
||||||
|
}
|
||||||
|
if (Strings.isBlank(request.getSendUserName())) {
|
||||||
|
throw new BaseException("sendUserName 不能为空");
|
||||||
|
}
|
||||||
|
if (Strings.isBlank(request.getSendPriority())) {
|
||||||
|
request.setSendPriority("3");
|
||||||
|
}
|
||||||
|
if ("4".equals(request.getSendPriority()) && Strings.isBlank(request.getSendTime())) {
|
||||||
|
throw new BaseException("sendPriority=4 时必须传 sendTime");
|
||||||
|
}
|
||||||
|
validateReceiverCount(request.getPersonInfo(), request.getRecipients());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 person_info。
|
||||||
|
* 已传原始 personInfo 时直接使用;否则根据 recipients 自动拼接平台要求的格式。
|
||||||
|
*
|
||||||
|
* @param request 平台请求参数
|
||||||
|
* @param includeMobile 是否在第 5 段写入手机号
|
||||||
|
* @return 平台要求的 person_info 字符串
|
||||||
|
*/
|
||||||
|
private String resolvePersonInfo(MsgPlatformBaseRequest request, boolean includeMobile) {
|
||||||
|
if (Strings.isNotBlank(request.getPersonInfo())) {
|
||||||
|
return request.getPersonInfo();
|
||||||
|
}
|
||||||
|
List<MsgPlatformRecipient> recipients = request.getRecipients();
|
||||||
|
if (recipients == null || recipients.isEmpty()) {
|
||||||
|
throw new BaseException("接收人列表不能为空");
|
||||||
|
}
|
||||||
|
return recipients.stream().map(recipient -> buildReceiverLine(recipient, includeMobile)).collect(Collectors.joining("^@^"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将单个接收人转成平台要求的分隔符格式。
|
||||||
|
*
|
||||||
|
* @param recipient 接收人对象
|
||||||
|
* @param includeMobile 是否在最后一段补手机号
|
||||||
|
* @return 单个接收人的 person_info 片段
|
||||||
|
*/
|
||||||
|
private String buildReceiverLine(MsgPlatformRecipient recipient, boolean includeMobile) {
|
||||||
|
if (recipient == null) {
|
||||||
|
throw new BaseException("接收人信息中存在空对象");
|
||||||
|
}
|
||||||
|
List<String> segments = new ArrayList<>(5);
|
||||||
|
segments.add(Strings.sNull(recipient.getName()));
|
||||||
|
segments.add(Strings.sNull(recipient.getAccount()));
|
||||||
|
segments.add(Strings.sNull(recipient.getUnitId()));
|
||||||
|
segments.add(Strings.sNull(recipient.getUnitName()));
|
||||||
|
if (includeMobile) {
|
||||||
|
segments.add(resolveSmsMobile(recipient));
|
||||||
|
} else {
|
||||||
|
segments.add("");
|
||||||
|
}
|
||||||
|
return String.join("|", segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析短信接收人手机号。
|
||||||
|
* 如果 controller 传的是手机号,则校验手机号格式;
|
||||||
|
* 如果传的是工号,则允许手机号为空,按“姓名|工号|部门ID|部门名称|”格式发送。
|
||||||
|
*
|
||||||
|
* @param recipient 接收人信息
|
||||||
|
* @return 短信 person_info 第 5 段内容
|
||||||
|
*/
|
||||||
|
private String resolveSmsMobile(MsgPlatformRecipient recipient) {
|
||||||
|
String mobile = recipient.getMobile();
|
||||||
|
if (Strings.isBlank(mobile)) {
|
||||||
|
if (Strings.isBlank(recipient.getAccount())) {
|
||||||
|
throw new BaseException("短信接收人手机号和工号不能同时为空");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (!mobile.matches("^\\d{11}$")) {
|
||||||
|
throw new BaseException("短信接收人手机号必须为11位数字");
|
||||||
|
}
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验接收人数量,避免超过第三方平台单次上限。
|
||||||
|
*
|
||||||
|
* @param personInfo 原始 person_info
|
||||||
|
* @param recipients 接收人列表
|
||||||
|
*/
|
||||||
|
private void validateReceiverCount(String personInfo, List<MsgPlatformRecipient> recipients) {
|
||||||
|
int receiverCount;
|
||||||
|
if (Strings.isNotBlank(personInfo)) {
|
||||||
|
receiverCount = personInfo.split("\\^@\\^", -1).length;
|
||||||
|
} else {
|
||||||
|
receiverCount = recipients == null ? 0 : recipients.size();
|
||||||
|
}
|
||||||
|
if (receiverCount > MAX_RECEIVER_COUNT) {
|
||||||
|
throw new BaseException("单次发送人数不能超过" + MAX_RECEIVER_COUNT + "人");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建工号发送专用接收人列表。
|
||||||
|
*
|
||||||
|
* @param account controller 传入的工号
|
||||||
|
* @return 仅包含一个接收人的列表
|
||||||
|
*/
|
||||||
|
private List<MsgPlatformRecipient> buildAccountRecipients(String account) {
|
||||||
|
if (Strings.isBlank(account)) {
|
||||||
|
throw new BaseException("接收人工号不能为空");
|
||||||
|
}
|
||||||
|
MsgPlatformRecipient recipient = new MsgPlatformRecipient();
|
||||||
|
recipient.setAccount(account);
|
||||||
|
List<MsgPlatformRecipient> recipients = new ArrayList<>(1);
|
||||||
|
recipients.add(recipient);
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建手机号发送专用接收人列表。
|
||||||
|
*
|
||||||
|
* @param mobile controller 传入的手机号
|
||||||
|
* @return 仅包含一个接收人的列表
|
||||||
|
*/
|
||||||
|
private List<MsgPlatformRecipient> buildMobileRecipients(String mobile) {
|
||||||
|
if (Strings.isBlank(mobile)) {
|
||||||
|
throw new BaseException("接收人手机号不能为空");
|
||||||
|
}
|
||||||
|
if (!mobile.matches("^\\d{11}$")) {
|
||||||
|
throw new BaseException("接收人手机号必须为11位数字");
|
||||||
|
}
|
||||||
|
MsgPlatformRecipient recipient = new MsgPlatformRecipient();
|
||||||
|
recipient.setMobile(mobile);
|
||||||
|
List<MsgPlatformRecipient> recipients = new ArrayList<>(1);
|
||||||
|
recipients.add(recipient);
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建微信便捷发送专用接收人列表。
|
||||||
|
*
|
||||||
|
* @param accountOrMobile controller 传入的企业微信成员ID、工号或手机号
|
||||||
|
* @return 仅包含一个接收人的列表
|
||||||
|
*/
|
||||||
|
private List<MsgPlatformRecipient> buildWechatRecipients(String accountOrMobile) {
|
||||||
|
if (Strings.isBlank(accountOrMobile)) {
|
||||||
|
throw new BaseException("微信接收人工号或手机号不能为空");
|
||||||
|
}
|
||||||
|
MsgPlatformRecipient recipient = new MsgPlatformRecipient();
|
||||||
|
recipient.setAccount(accountOrMobile);
|
||||||
|
List<MsgPlatformRecipient> recipients = new ArrayList<>(1);
|
||||||
|
recipients.add(recipient);
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为便捷发送方法补默认发送人信息。
|
||||||
|
* 这些字段从配置中读取,避免 controller 每次重复传固定参数。
|
||||||
|
*
|
||||||
|
* @param request 平台请求参数
|
||||||
|
*/
|
||||||
|
private void fillDefaultSenderInfo(MsgPlatformBaseRequest request) {
|
||||||
|
request.setSendUserId(getRequiredConfig("msg.platform.default-send-user-id", "请先配置 msg.platform.default-send-user-id"));
|
||||||
|
request.setSendUserName(getRequiredConfig("msg.platform.default-send-user-name", "请先配置 msg.platform.default-send-user-name"));
|
||||||
|
request.setSendUnitId(conf.get("msg.platform.default-send-unit-id", ""));
|
||||||
|
request.setSendUnitName(conf.get("msg.platform.default-send-unit-name", ""));
|
||||||
|
request.setSendUserSign(conf.get("msg.platform.default-send-user-sign", ""));
|
||||||
|
request.setTemplateId(conf.get("msg.platform.default-template-id", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用地大通讯平台 REST 接口。
|
||||||
|
*
|
||||||
|
* @param apiPath 具体接口路径
|
||||||
|
* @param payload 发送报文
|
||||||
|
* @return 平台响应结果
|
||||||
|
*/
|
||||||
|
private MsgPlatformResponse doPost(String apiPath, JSONObject payload) {
|
||||||
|
|
||||||
|
if (!Globals.sso){
|
||||||
|
log.error("【log】开发模式不允许发送消息通知");
|
||||||
|
MsgPlatformResponse response = new MsgPlatformResponse();
|
||||||
|
response.setHttpStatus(200);
|
||||||
|
response.setCode(0);
|
||||||
|
response.setResult(true);
|
||||||
|
response.setMsg("开发模式不允许发送消息通知");
|
||||||
|
response.setRawBody(JSONUtil.toJsonStr(payload));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if (!Globals.MyConfig.getBoolean("AppSms", false)) {
|
||||||
|
log.error("【log】短信配置未开启");
|
||||||
|
MsgPlatformResponse response = new MsgPlatformResponse();
|
||||||
|
response.setHttpStatus(200);
|
||||||
|
response.setCode(0);
|
||||||
|
response.setResult(true);
|
||||||
|
response.setMsg("短信配置未开启");
|
||||||
|
response.setRawBody(JSONUtil.toJsonStr(payload));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if (!conf.getBoolean("msg.platform.enabled", false)) {
|
||||||
|
MsgPlatformResponse response = new MsgPlatformResponse();
|
||||||
|
response.setHttpStatus(200);
|
||||||
|
response.setCode(0);
|
||||||
|
response.setResult(true);
|
||||||
|
response.setMsg("通讯平台未启用,已跳过实际发送");
|
||||||
|
response.setRawBody(JSONUtil.toJsonStr(payload));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
try {
|
||||||
|
String requestBody = JSONUtil.toJsonStr(payload);
|
||||||
|
log.error("发送内容:=================================================="+requestBody);
|
||||||
|
String requestUrl = buildRequestUrl(apiPath);
|
||||||
|
log.warnf("发送地址:=================================================="+requestUrl);
|
||||||
|
connection = (HttpURLConnection) new URL(requestUrl).openConnection();
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
connection.setConnectTimeout(conf.getInt("msg.platform.connect-timeout", 5000));
|
||||||
|
connection.setReadTimeout(conf.getInt("msg.platform.read-timeout", 10000));
|
||||||
|
try (OutputStream outputStream = connection.getOutputStream()) {
|
||||||
|
outputStream.write(requestBody.getBytes(StandardCharsets.UTF_8));
|
||||||
|
outputStream.flush();
|
||||||
|
}
|
||||||
|
int httpStatus = connection.getResponseCode();
|
||||||
|
String responseBody = readResponseBody(connection, httpStatus);
|
||||||
|
MsgPlatformResponse response = parseResponse(httpStatus, responseBody);
|
||||||
|
log.warnf("接口调用返回结果=============================="+responseBody);
|
||||||
|
if (response.getCode() != null && response.getCode() != 0) {
|
||||||
|
log.warnf("通讯平台调用失败, httpStatus=%s, body=%s", httpStatus, responseBody);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("调用通讯平台接口异常", e);
|
||||||
|
throw new BaseException("调用通讯平台接口失败: " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (connection != null) {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建完整请求地址,支持配置带或不带结尾斜杠的 base-url。
|
||||||
|
*
|
||||||
|
* @param apiPath 接口路径
|
||||||
|
* @return 完整请求地址
|
||||||
|
*/
|
||||||
|
private String buildRequestUrl(String apiPath) {
|
||||||
|
String baseUrl = getRequiredConfig("msg.platform.base-url", "请先配置 msg.platform.base-url");
|
||||||
|
if (baseUrl.endsWith("/")) {
|
||||||
|
return baseUrl.substring(0, baseUrl.length() - 1) + apiPath;
|
||||||
|
}
|
||||||
|
return baseUrl + apiPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取第三方接口响应报文。
|
||||||
|
*
|
||||||
|
* @param connection HttpURLConnection
|
||||||
|
* @param httpStatus HTTP 状态码
|
||||||
|
* @return 原始响应字符串
|
||||||
|
* @throws IOException 读取流失败时抛出
|
||||||
|
*/
|
||||||
|
private String readResponseBody(HttpURLConnection connection, int httpStatus) throws IOException {
|
||||||
|
InputStream inputStream = httpStatus >= 200 && httpStatus < 400 ? connection.getInputStream() : connection.getErrorStream();
|
||||||
|
if (inputStream == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
builder.append(line);
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析平台响应体。
|
||||||
|
*
|
||||||
|
* @param httpStatus HTTP 状态码
|
||||||
|
* @param responseBody 原始响应字符串
|
||||||
|
* @return 解析后的平台响应对象
|
||||||
|
*/
|
||||||
|
private MsgPlatformResponse parseResponse(int httpStatus, String responseBody) {
|
||||||
|
MsgPlatformResponse response = new MsgPlatformResponse();
|
||||||
|
response.setHttpStatus(httpStatus);
|
||||||
|
response.setRawBody(responseBody);
|
||||||
|
if (Strings.isBlank(responseBody)) {
|
||||||
|
response.setCode(httpStatus);
|
||||||
|
response.setResult(false);
|
||||||
|
response.setMsg("通讯平台未返回响应内容");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
if (!JSONUtil.isTypeJSON(responseBody)) {
|
||||||
|
response.setCode(httpStatus);
|
||||||
|
response.setResult(false);
|
||||||
|
response.setMsg("通讯平台返回内容不是合法JSON");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = JSONUtil.parseObj(responseBody);
|
||||||
|
response.setCode(jsonObject.getInt("code"));
|
||||||
|
response.setMsg(jsonObject.getStr("msg"));
|
||||||
|
response.setResult(jsonObject.getBool("result"));
|
||||||
|
response.setMsgId(jsonObject.getStr("msg_id"));
|
||||||
|
response.setRemainingQuota(jsonObject.getInt("remaining_quota"));
|
||||||
|
response.setDescription(jsonObject.getStr("description"));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取平台密钥。
|
||||||
|
* 优先读取已加密密钥;未配置时再根据原始密钥按“Base64 后 SHA”规则自动计算。
|
||||||
|
*
|
||||||
|
* @return 平台要求的 secret_key
|
||||||
|
*/
|
||||||
|
private String getSecretKey() {
|
||||||
|
String encryptedSecretKey = conf.get("msg.platform.encrypted-secret-key", "");
|
||||||
|
if (Strings.isNotBlank(encryptedSecretKey)) {
|
||||||
|
return encryptedSecretKey;
|
||||||
|
}
|
||||||
|
String rawSecret = getRequiredConfig("msg.platform.raw-secret-key", "请先配置 msg.platform.raw-secret-key 或 msg.platform.encrypted-secret-key");
|
||||||
|
return shaHex(rawSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取必填配置项。
|
||||||
|
*
|
||||||
|
* @param key 配置 key
|
||||||
|
* @param errorMessage 配置缺失时抛出的异常信息
|
||||||
|
* @return 配置值
|
||||||
|
*/
|
||||||
|
private String getRequiredConfig(String key, String errorMessage) {
|
||||||
|
String value = conf.get(key, "");
|
||||||
|
if (Strings.isBlank(value)) {
|
||||||
|
throw new BaseException(errorMessage);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 SHA 十六进制摘要。
|
||||||
|
*
|
||||||
|
* @param content 待加密内容
|
||||||
|
* @return SHA 十六进制字符串
|
||||||
|
*/
|
||||||
|
private String shaHex(String content) {
|
||||||
|
try {
|
||||||
|
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
|
||||||
|
messageDigest.update(content.getBytes());
|
||||||
|
byte[] hash = messageDigest.digest();
|
||||||
|
return Base64.getEncoder().encodeToString(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BaseException("生成通讯平台 secret_key 失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
package com.budwk.app.base.sms.impl.jshvc;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
|
||||||
import cn.hutool.http.HttpRequest;
|
|
||||||
import cn.hutool.http.HttpResponse;
|
|
||||||
import com.budwk.app.base.sms.SmsService;
|
|
||||||
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.lang.Lang;
|
|
||||||
import org.nutz.lang.util.NutMap;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ClassName SmsJshvcServiceImpl
|
|
||||||
* @Author JyuHsin
|
|
||||||
* @Date 2025/11/26 19:32
|
|
||||||
* @Version 1.0
|
|
||||||
* @Description TODO
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@IocBean
|
|
||||||
public class SmsJshvcServiceImpl implements SmsService {
|
|
||||||
|
|
||||||
private static final String APPID = "";
|
|
||||||
private static final String APP_SECRET = "";
|
|
||||||
private static final String TOKEN_URL = "";
|
|
||||||
private static final String MSG_URL = "";
|
|
||||||
private static final String REDIS_KEY_MSG_ACCESS_TOKEN = "msg:token:";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private RedisService redisService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String loginName, String content) {
|
|
||||||
// send(loginName, "智慧工会", content);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String loginName, String title, String content) {
|
|
||||||
send(loginName, "智慧工会", content, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String loginName, String title, String content, String link) {
|
|
||||||
// Map<String, String> paramMap = Map.of("userId", loginName);
|
|
||||||
// doSend(title, content, List.of(paramMap), link);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void massSend(List<String> loginNames, String title, String content, String link) {
|
|
||||||
// List<Map<String, String>> receivers = loginNames.stream()
|
|
||||||
// .map(name -> Map.of("userId", name))
|
|
||||||
// .toList();
|
|
||||||
// doSend(title, content, receivers, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sign: 请求签名:(accessToken + 第一个receivers 的userID )的32位小写的MD5加密值,其中如果相应部分没有则忽略
|
|
||||||
* msgType: 0: 普通消息(默认) 1: 必读消息 2: 验证码(为验证码时消息一定不入收件箱)
|
|
||||||
* expiredTime: 当msgType 为1必读消息 ,该字段为必填字段 格式:yyyy-MM-dd HH:mm:ss
|
|
||||||
* sendType: 1.只发送PC门户 2.只发送移动校园 3.邮件 4.短信 5.微信企业号 6.钉钉企业内部应用工作通知 7.微信服务号 8.welink
|
|
||||||
* wxSendType: 当发送类型为5时此字段才会生效:text(文本消息)、textcard(文本卡片)、nes(图文卡片,如果图文,则qyWeChatImgUrl必填)、button(按钮卡片详见示例),不传默认为text
|
|
||||||
* receiverType: 1:用户 2:用户组 3:部门,默认为1
|
|
||||||
*
|
|
||||||
* @param title
|
|
||||||
* @param content
|
|
||||||
* @param receivers
|
|
||||||
*/
|
|
||||||
private void doSend(String title, String content, List<Map<String, String>> receivers, String link) {
|
|
||||||
|
|
||||||
if (Lang.isEmpty(receivers)) {
|
|
||||||
log.error("send fail by receivers is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取token
|
|
||||||
String accessToken = buildAccessToken();
|
|
||||||
// 获取第一个接收人的userID
|
|
||||||
String firstUserId = receivers.get(0).get("userId");
|
|
||||||
// md5小写加密生成签名
|
|
||||||
String sign = DigestUtil.md5Hex(accessToken + firstUserId);
|
|
||||||
|
|
||||||
NutMap paramsMap = new NutMap();
|
|
||||||
paramsMap.put("sign", sign);
|
|
||||||
paramsMap.put("msgType", "0");
|
|
||||||
paramsMap.put("subject", title);
|
|
||||||
paramsMap.put("content", content);
|
|
||||||
paramsMap.put("sendType", "5");
|
|
||||||
paramsMap.put("receivers", receivers);
|
|
||||||
if (StrUtil.isBlank(link)) {
|
|
||||||
paramsMap.put("wxSendType", "text");
|
|
||||||
} else {
|
|
||||||
paramsMap.put("wxSendType", "textcard");
|
|
||||||
paramsMap.put("mobileUrl", link);
|
|
||||||
// 这是图文卡片,后面用到再对接吧
|
|
||||||
// paramsMap.put("qyWeChatImgUrl", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("send params: {}", Json.toJson(paramsMap));
|
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.post(MSG_URL)
|
|
||||||
.header("appId", APPID)
|
|
||||||
.header("accessToken", accessToken)
|
|
||||||
.body(Json.toJson(paramsMap));
|
|
||||||
|
|
||||||
try {
|
|
||||||
HttpResponse response = request.execute();
|
|
||||||
log.info("send response body: {}", response.body());
|
|
||||||
|
|
||||||
NutMap bodyMap = Json.fromJson(NutMap.class, response.body());
|
|
||||||
if (bodyMap.getInt("status") == 200) {
|
|
||||||
log.info("send success code: {}, msg: {}", bodyMap.getInt("status"), bodyMap.getString("msg"));
|
|
||||||
} else {
|
|
||||||
log.error("send error code: {}, msg: {}", bodyMap.getInt("status"), bodyMap.getString("msg"));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to send: {}", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildAccessToken() {
|
|
||||||
String token = redisService.get(REDIS_KEY_MSG_ACCESS_TOKEN);
|
|
||||||
if (StrUtil.isNotBlank(token)) {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
HttpRequest request = HttpRequest.get(TOKEN_URL);
|
|
||||||
request.header("appId", APPID);
|
|
||||||
request.header("appSecret", APP_SECRET);
|
|
||||||
|
|
||||||
HttpResponse response = request.execute();
|
|
||||||
|
|
||||||
log.info("accessToken response: {}", Json.toJson(response.body()));
|
|
||||||
|
|
||||||
NutMap bodyMap = Json.fromJson(NutMap.class, response.body());
|
|
||||||
if (bodyMap.getInt("errcode") == 0) {
|
|
||||||
log.info("accessToken status: {}", bodyMap.getInt("errorcode"));
|
|
||||||
redisService.setex(REDIS_KEY_MSG_ACCESS_TOKEN, 60 * 120, bodyMap.getString("data"));
|
|
||||||
return bodyMap.getString("data");
|
|
||||||
} else {
|
|
||||||
log.error("accessToken status: {}", bodyMap.getInt("errorcode"));
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通讯平台公共请求参数。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MsgPlatformBaseRequest {
|
||||||
|
/**
|
||||||
|
* 接收人信息原始字符串。
|
||||||
|
* 如果 controller 已经按平台要求拼好了 person_info,可以直接传该字段;
|
||||||
|
* 否则可只传 recipients,由 service 自动组装。
|
||||||
|
*/
|
||||||
|
private String personInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人列表。
|
||||||
|
* 当 personInfo 为空时,service 会根据该列表自动拼接平台要求的 person_info 字符串。
|
||||||
|
*/
|
||||||
|
private List<MsgPlatformRecipient> recipients;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板ID。
|
||||||
|
* templateId 和 info 至少需要传一个,使用模板发送时优先传该字段。
|
||||||
|
*/
|
||||||
|
private String templateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容。
|
||||||
|
* templateId 和 info 至少需要传一个;不使用模板时,需要传完整消息内容。
|
||||||
|
*/
|
||||||
|
private String info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送优先级。
|
||||||
|
* 3 表示立即发送,4 表示定时发送。
|
||||||
|
*/
|
||||||
|
private String sendPriority = "3";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送人账号。
|
||||||
|
*/
|
||||||
|
private String sendUserId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送人姓名。
|
||||||
|
*/
|
||||||
|
private String sendUserName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量。
|
||||||
|
* 使用模板发送时可传该字段,service 会自动转成平台要求的 JSON 字符串。
|
||||||
|
*/
|
||||||
|
private Map<String, String> customVar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时发送时间,格式必须为 yyyy-MM-dd HH:mm:ss。
|
||||||
|
* 当 sendPriority=4 时该字段必填。
|
||||||
|
*/
|
||||||
|
private String sendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送机构ID。
|
||||||
|
*/
|
||||||
|
private String sendUnitId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送机构名称。
|
||||||
|
*/
|
||||||
|
private String sendUnitName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送签名。
|
||||||
|
* 旧通用模板或特定签名场景可传该字段。
|
||||||
|
*/
|
||||||
|
private String sendUserSign;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回执ID。
|
||||||
|
* 不需要回执时可保持默认值 0。
|
||||||
|
*/
|
||||||
|
private String receiptId = "0";
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信图文消息单条数据。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MsgPlatformNewsItem {
|
||||||
|
/**
|
||||||
|
* 图文标题。
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图文描述。
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击跳转链接。
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图文封面图片链接。
|
||||||
|
*/
|
||||||
|
private String picurl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通讯平台接收人信息。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MsgPlatformRecipient {
|
||||||
|
/**
|
||||||
|
* 接收人姓名,对应 person_info 中的第 1 段。
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人账号,对应 person_info 中的第 2 段。
|
||||||
|
* 短信场景一般传学工号;微信场景可传企业微信成员ID、学工号或手机号。
|
||||||
|
*/
|
||||||
|
private String account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人部门ID,对应 person_info 中的第 3 段。
|
||||||
|
*/
|
||||||
|
private String unitId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人部门名称,对应 person_info 中的第 4 段。
|
||||||
|
*/
|
||||||
|
private String unitName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收人手机号,对应短信 person_info 中的第 5 段。
|
||||||
|
* 微信接口不会使用该字段,微信接口会自动补空串以保留分隔符格式。
|
||||||
|
*/
|
||||||
|
private String mobile;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通讯平台响应结果。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MsgPlatformResponse {
|
||||||
|
/**
|
||||||
|
* HTTP 状态码,便于 controller 定位网络层问题。
|
||||||
|
*/
|
||||||
|
private Integer httpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台返回业务状态码,0 表示成功。
|
||||||
|
*/
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台返回消息提示。
|
||||||
|
*/
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台返回业务是否成功。
|
||||||
|
*/
|
||||||
|
private Boolean result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送成功后的消息ID。
|
||||||
|
*/
|
||||||
|
private String msgId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信剩余额度,仅短信接口返回。
|
||||||
|
*/
|
||||||
|
private Integer remainingQuota;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台失败描述。
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台原始响应报文,排查问题时可直接查看。
|
||||||
|
*/
|
||||||
|
private String rawBody;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信发送请求参数。
|
||||||
|
*/
|
||||||
|
public class MsgPlatformSmsRequest extends MsgPlatformBaseRequest {
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.budwk.app.base.sms.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信发送请求参数。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class MsgPlatformWechatRequest extends MsgPlatformBaseRequest {
|
||||||
|
/**
|
||||||
|
* 微信消息类型。
|
||||||
|
* 可传 text、news、image、file、video、voice,默认 text。
|
||||||
|
*/
|
||||||
|
private String wechatType = "text";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图文消息列表。
|
||||||
|
* 当 wechatType=news 且未直接传 info 时,service 会将该列表转成平台要求的 JSON 数组字符串。
|
||||||
|
*/
|
||||||
|
private List<MsgPlatformNewsItem> newsItems;
|
||||||
|
}
|
||||||
@@ -26,44 +26,45 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class FlowUnitPartySecretaryHandler implements AssignmentHandler {
|
public class FlowUnitPartySecretaryHandler implements AssignmentHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> assign(TaskModel model, Execution execution) {
|
public List<String> assign(TaskModel model, Execution execution) {
|
||||||
String unitId = SecurityUtil.getUnitId();
|
String unitId = SecurityUtil.getUnitId();
|
||||||
|
|
||||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||||
Sys_role role = sysRoleService.getByCode(RoleConstant.UNIT_PARTY_SECRETARY);
|
Sys_role role = sysRoleService.getByCode(RoleConstant.UNIT_PARTY_SECRETARY);
|
||||||
|
|
||||||
View_user user = ServiceContext.find(Dao.class).fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId()));
|
View_user user = ServiceContext.find(Dao.class).fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId()));
|
||||||
List<Sys_user_role> roles;
|
List<Sys_user_role> roles;
|
||||||
if(user.getUnionName().contains("行政")){
|
|
||||||
List<Sys_unit> unitList = ServiceContext.find(Dao.class).query(Sys_unit.class, Cnd.where(Sys_unit::getUnionId, "=", user.getUnionId()));
|
|
||||||
List<String> unitIds = unitList.stream().map(Sys_unit::getId).toList();
|
|
||||||
roles = ServiceContext.find(Dao.class).query(
|
|
||||||
Sys_user_role.class,
|
|
||||||
Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
|
||||||
.and(Sys_user_role::getUnitId, "in", unitIds)
|
|
||||||
);
|
|
||||||
}else{
|
|
||||||
roles = ServiceContext.find(Dao.class).query(
|
|
||||||
Sys_user_role.class,
|
|
||||||
Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
|
||||||
.and(Sys_user_role::getUnitId, "=", unitId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Lang.isEmpty(roles)) {
|
roles = ServiceContext.find(Dao.class).query(
|
||||||
throw new RuntimeException("当前登录用户所在单位未设置单位党委书记,请联系校工会进行设置。");
|
Sys_user_role.class,
|
||||||
}
|
Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||||
return roles.stream().map(Sys_user_role::getUserId).toList();
|
.and(Sys_user_role::getUnitId, "=", unitId)
|
||||||
}
|
);
|
||||||
|
|
||||||
@Override
|
if (Lang.isEmpty(roles)) {
|
||||||
public String getMessage() {
|
List<Sys_unit> unitList = ServiceContext.find(Dao.class).query(Sys_unit.class, Cnd.where(Sys_unit::getUnionId, "=", user.getUnionId()));
|
||||||
return "获取当前登录用户所在单位党委书记,若是行政就找出行政分下的党委书记。因为行政只有一个党委书记";
|
List<String> unitIds = unitList.stream().map(Sys_unit::getId).toList();
|
||||||
}
|
roles = ServiceContext.find(Dao.class).query(
|
||||||
|
Sys_user_role.class,
|
||||||
|
Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||||
|
.and(Sys_user_role::getUnitId, "in", unitIds)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
if (Lang.isEmpty(roles)) {
|
||||||
public int getOrder() {
|
throw new RuntimeException("当前登录用户所在单位未设置单位党委书记,请联系校工会进行设置。");
|
||||||
return AssignmentHandler.super.getOrder();
|
}
|
||||||
}
|
return roles.stream().map(Sys_user_role::getUserId).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "获取当前登录用户所在单位党委书记";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return AssignmentHandler.super.getOrder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,15 @@ import com.budwk.app.sys.services.SysUserService;
|
|||||||
import com.budwk.app.sys.views.View_user;
|
import com.budwk.app.sys.views.View_user;
|
||||||
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.democratic.proposal.models.ProposalConfig;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Chain;
|
import org.nutz.dao.Chain;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
@@ -146,10 +149,20 @@ public class SysUnitController {
|
|||||||
@At
|
@At
|
||||||
@ApiOperation("按关键字查询单位下的人员")
|
@ApiOperation("按关键字查询单位下的人员")
|
||||||
@Ok("json:{ignoreNull:true}")
|
@Ok("json:{ignoreNull:true}")
|
||||||
public Result listUserSelect(@Valid String unitId, @Valid String keyWord) {
|
public Result listUserSelect(@Valid String unitId, @Valid String keyWord, @Valid String roleCode) {
|
||||||
Sql sql = Sqls.create("select id,loginname,username,unitname from vw_user $condition");
|
Sql sql = Sqls.create("select id,loginname,username,unitname from vw_user $condition");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.and(View_user::getUnitId, "=", unitId);
|
// 选择校领导角色时,人员范围来自提案配置中的校领导单位;其他角色仍限定当前单位。
|
||||||
|
if ("UNIT_SCHOOL_LEADER".equals(roleCode)) {
|
||||||
|
ProposalConfig proposalConfig = sysUnitService.dao().fetch(ProposalConfig.class, Cnd.NEW());
|
||||||
|
if (proposalConfig == null || Lang.isEmpty(proposalConfig.getSchoolLeaderUnitIds())) {
|
||||||
|
return Result.error("请在提案基础设置里配置校领导单位!");
|
||||||
|
}
|
||||||
|
cnd.and(View_user::getUnitId, "in", proposalConfig.getSchoolLeaderUnitIds());
|
||||||
|
} else {
|
||||||
|
cnd.and(View_user::getUnitId, "=", unitId);
|
||||||
|
}
|
||||||
|
cnd.and(View_user::getMember, "=", 1);
|
||||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
seg.orLike(View_user::getLoginname, keyWord, true);
|
seg.orLike(View_user::getLoginname, keyWord, true);
|
||||||
seg.orLike(View_user::getUsername, keyWord, true);
|
seg.orLike(View_user::getUsername, keyWord, true);
|
||||||
@@ -165,13 +178,14 @@ public class SysUnitController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@Ok("json")
|
@Ok("json")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result insertUnitUserRole(String userId, String roleCode, String unitId) {
|
public Result insertUnitUserRole(String userId, String roleCode, String unitId) {
|
||||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||||
if (Lang.isEmpty(role)) {
|
if (Lang.isEmpty(role)) {
|
||||||
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
||||||
}
|
}
|
||||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unitId", "=", unitId));
|
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unitId", "=", unitId).and("underTakeId", "=", unitId));
|
||||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId()).add("userId", userId).add("unitId", unitId));
|
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId()).add("userId", userId).add("unitId", unitId).add("underTakeId", unitId));
|
||||||
sysRoleService.clearCache();
|
sysRoleService.clearCache();
|
||||||
sysUserService.clearCache();
|
sysUserService.clearCache();
|
||||||
return Result.success();
|
return Result.success();
|
||||||
@@ -179,12 +193,13 @@ public class SysUnitController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@Ok("json")
|
@Ok("json")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result deleteUnitUserRole(String userId, String roleCode, String unitId) {
|
public Result deleteUnitUserRole(String userId, String roleCode, String unitId) {
|
||||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||||
if (Lang.isEmpty(role)) {
|
if (Lang.isEmpty(role)) {
|
||||||
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
||||||
}
|
}
|
||||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unitId", "=", unitId));
|
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unitId", "=", unitId).and("underTakeId", "=", unitId));
|
||||||
sysRoleService.clearCache();
|
sysRoleService.clearCache();
|
||||||
sysUserService.clearCache();
|
sysUserService.clearCache();
|
||||||
return Result.success();
|
return Result.success();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cn.hutool.http.HtmlUtil;
|
|||||||
import com.budwk.app.base.constant.RedisConstant;
|
import com.budwk.app.base.constant.RedisConstant;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.base.sms.SmsService;
|
import com.budwk.app.base.sms.SmsService;
|
||||||
|
import com.budwk.app.base.sms.model.MsgPlatformWechatRequest;
|
||||||
import com.budwk.app.base.utils.ManyAddOrRenewUtil;
|
import com.budwk.app.base.utils.ManyAddOrRenewUtil;
|
||||||
import com.budwk.app.sys.models.Sys_msg;
|
import com.budwk.app.sys.models.Sys_msg;
|
||||||
import com.budwk.app.sys.models.Sys_msg_user;
|
import com.budwk.app.sys.models.Sys_msg_user;
|
||||||
@@ -102,11 +103,12 @@ public class SysMsgServiceImpl extends BaseServiceImpl<Sys_msg> implements SysMs
|
|||||||
});
|
});
|
||||||
|
|
||||||
//发送学校平台消息
|
//发送学校平台消息
|
||||||
// for (String loginName : loginNames) {
|
|
||||||
// smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote());
|
|
||||||
// }
|
|
||||||
ThreadUtil.execute(() -> {
|
ThreadUtil.execute(() -> {
|
||||||
//smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl());
|
for (String loginName : loginNames) {
|
||||||
|
smsService.sendSmsByAccount(loginName,sysMsg.getNote());
|
||||||
|
smsService.sendWechatTextByAccountOrMobile(loginName,sysMsg.getNote());
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return sysMsg;
|
return sysMsg;
|
||||||
|
|||||||
+31
-4
@@ -24,6 +24,8 @@ import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
|||||||
import com.budwk.app.zhgh.activity.basic.param.ActivityUserScopePageParam;
|
import com.budwk.app.zhgh.activity.basic.param.ActivityUserScopePageParam;
|
||||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||||
import com.budwk.app.zhgh.activity.basic.template.UserTemp;
|
import com.budwk.app.zhgh.activity.basic.template.UserTemp;
|
||||||
|
import com.budwk.app.zhgh.club.model.SysClub;
|
||||||
|
import com.budwk.app.zhgh.club.service.SysClubService;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
@@ -84,6 +86,9 @@ public class ActivityBasicScopeController {
|
|||||||
@Inject
|
@Inject
|
||||||
private RedisService redisService;
|
private RedisService redisService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SysClubService sysClubService;
|
||||||
|
|
||||||
@At("")
|
@At("")
|
||||||
@Ok("beetl:platform/zhgh/activity/basic/userScope/index.html")
|
@Ok("beetl:platform/zhgh/activity/basic/userScope/index.html")
|
||||||
@SaCheckPermission("activity.basic.scope")
|
@SaCheckPermission("activity.basic.scope")
|
||||||
@@ -97,7 +102,6 @@ public class ActivityBasicScopeController {
|
|||||||
* @return {@link Result}
|
* @return {@link Result}
|
||||||
*/
|
*/
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.basic")
|
|
||||||
public Result pageData(@Param("data") ActivityUserScopePageParam pageForm) {
|
public Result pageData(@Param("data") ActivityUserScopePageParam pageForm) {
|
||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
@@ -216,6 +220,8 @@ public class ActivityBasicScopeController {
|
|||||||
return Result.success(new NutMap() {{
|
return Result.success(new NutMap() {{
|
||||||
addv("is_A06", StpUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name()));
|
addv("is_A06", StpUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name()));
|
||||||
addv("is_H04", StpUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()));
|
addv("is_H04", StpUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()));
|
||||||
|
addv("is_H02", StpUtil.hasRole(RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name()));
|
||||||
|
addv("is_CLUB_PRESIDENT", StpUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name()));
|
||||||
addv("is_sysadmin", StpUtil.hasRole(RoleConstant.SYSADMIN.name()));
|
addv("is_sysadmin", StpUtil.hasRole(RoleConstant.SYSADMIN.name()));
|
||||||
addv("unionid", SecurityUtil.getUnionId());
|
addv("unionid", SecurityUtil.getUnionId());
|
||||||
}});
|
}});
|
||||||
@@ -344,9 +350,30 @@ public class ActivityBasicScopeController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())){
|
boolean isBranchUnionChairman = AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name());
|
||||||
cnd.andEX("u.unionid", "=", SecurityUtil.getUnionId());
|
boolean isClubPresident = AuthUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name());
|
||||||
|
if (isBranchUnionChairman && isClubPresident) {
|
||||||
|
// 同时具备分工会主席和社团会长身份时,未额外筛选前默认查看两类权限范围的并集。
|
||||||
|
List<String> manageClubIdList = sysClubService.getMyManageClub().stream().map(SysClub::getId).toList();
|
||||||
|
SqlExpressionGroup scopeGroup = new SqlExpressionGroup();
|
||||||
|
scopeGroup.or("u.unionid", "=", SecurityUtil.getUnionId());
|
||||||
|
if (!manageClubIdList.isEmpty()) {
|
||||||
|
scopeGroup.or("clubuser.clubid", "in", manageClubIdList);
|
||||||
|
}
|
||||||
|
cnd.and(scopeGroup);
|
||||||
|
} else if (isClubPresident) {
|
||||||
|
// 社团会长设置活动人员范围时,只允许查看自己可管理社团下的成员。
|
||||||
|
List<String> manageClubIdList = sysClubService.getMyManageClub().stream().map(SysClub::getId).toList();
|
||||||
|
if (manageClubIdList.isEmpty()) {
|
||||||
|
cnd.and("clubuser.clubid", "in", List.of("__EMPTY_CLUB_ID__"));
|
||||||
|
} else {
|
||||||
|
cnd.and("clubuser.clubid", "in", manageClubIdList);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 分工会主席等分工会侧角色,继续只允许查看本分工会人员。
|
||||||
|
cnd.andEX("u.unionid", "=", SecurityUtil.getUnionId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String[] unionIds = getUnionIds(activityUserScopePageParam);
|
String[] unionIds = getUnionIds(activityUserScopePageParam);
|
||||||
if (Lang.isNotEmpty(unionIds)) {
|
if (Lang.isNotEmpty(unionIds)) {
|
||||||
|
|||||||
+12
-2
@@ -21,6 +21,7 @@ import org.nutz.dao.Cnd;
|
|||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
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.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.json.Json;
|
import org.nutz.json.Json;
|
||||||
@@ -125,8 +126,17 @@ public class ActivityCultureApplyUserController {
|
|||||||
public Result queryTeammate(@Valid String keyword, Integer signUpMethod, String tissueId) {
|
public Result queryTeammate(@Valid String keyword, Integer signUpMethod, String tissueId) {
|
||||||
Sql sql = Sqls.create("select id userId,username userName,loginname loginName,sex,mobile,unitName from vw_user $condition limit 0,10");
|
Sql sql = Sqls.create("select id userId,username userName,loginname loginName,sex,mobile,unitName from vw_user $condition limit 0,10");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.or(Cnd.likeEX("username", keyword));
|
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
|
||||||
cnd.or(Cnd.likeEX("loginname", keyword));
|
keywordGroup.andLike("username", keyword);
|
||||||
|
keywordGroup.orLike("loginname", keyword);
|
||||||
|
cnd.and(keywordGroup);
|
||||||
|
if (StrUtil.isNotBlank(tissueId)) {
|
||||||
|
ActivityTissue tissue = dao.fetch(ActivityTissue.class, tissueId);
|
||||||
|
// 组队/分工会报名选人时,候选人必须落在活动新建时配置的参加人员范围内。
|
||||||
|
if (ObjectUtil.isNotNull(tissue) && ObjectUtil.isNotNull(tissue.getGroupId())) {
|
||||||
|
cnd.and("id", "in", activityBasicScopeService.buildGroupUserIdSubSql(tissue.getGroupId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (signUpMethod == 3) {
|
if (signUpMethod == 3) {
|
||||||
cnd.and("unionid", "=", SecurityUtil.getUnionId());
|
cnd.and("unionid", "=", SecurityUtil.getUnionId());
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -112,7 +112,7 @@ public class ActivityCultureAuditActivityController {
|
|||||||
cnd.andEX("tissue.unionId", "=", unionId);
|
cnd.andEX("tissue.unionId", "=", unionId);
|
||||||
cnd.andEX("tissue.activity_type", "=", activity_type);
|
cnd.andEX("tissue.activity_type", "=", activity_type);
|
||||||
if (approval) {
|
if (approval) {
|
||||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||||
} else {
|
} else {
|
||||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -161,6 +161,11 @@ public class ActivityCultureUserStatisticsController {
|
|||||||
cnd.and("tissue.signUpMethod", "in", List.of(1, 2, 3));
|
cnd.and("tissue.signUpMethod", "in", List.of(1, 2, 3));
|
||||||
if (activity_type == 40002) {
|
if (activity_type == 40002) {
|
||||||
cnd.and("tissue.unionId", "=", SecurityUtil.getUnionId());
|
cnd.and("tissue.unionId", "=", SecurityUtil.getUnionId());
|
||||||
|
} else if (activity_type == 40003) {
|
||||||
|
// 协会会长进入社团报名统计时,只允许查看自己管理社团下的活动名称。
|
||||||
|
List<SysClub> myManageClub = sysClubService.getMyManageClub();
|
||||||
|
List<String> clubIdList = myManageClub.stream().map(SysClub::getId).collect(Collectors.toList());
|
||||||
|
cnd.and("tissue.clubId", "in", clubIdList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 只查询流程实例状态为20的数据(已完成状态)
|
// 只查询流程实例状态为20的数据(已完成状态)
|
||||||
|
|||||||
+6
-5
@@ -169,34 +169,35 @@ public class ActivityPrizeListController {
|
|||||||
Map fourMap = NutMap.NEW();
|
Map fourMap = NutMap.NEW();
|
||||||
Map fiveMap = NutMap.NEW();
|
Map fiveMap = NutMap.NEW();
|
||||||
|
|
||||||
|
// 部分历史数据可能未配置竞赛类别,分组汇总时需要做空值保护,避免筛选时空指针
|
||||||
//甲组
|
//甲组
|
||||||
List<NutMap> oneList = allList.stream().filter(a -> a.getString("bszbName").equals("甲组")).collect(toList());
|
List<NutMap> oneList = allList.stream().filter(a -> Objects.equals("甲组", a.getString("bszbName"))).collect(toList());
|
||||||
if (Lang.isNotEmpty(oneList)) {
|
if (Lang.isNotEmpty(oneList)) {
|
||||||
oneMap = oneList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
oneMap = oneList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
//乙组
|
//乙组
|
||||||
List<NutMap> twoList = allList.stream().filter(a -> a.getString("bszbName").equals("乙组")).collect(toList());
|
List<NutMap> twoList = allList.stream().filter(a -> Objects.equals("乙组", a.getString("bszbName"))).collect(toList());
|
||||||
if (Lang.isNotEmpty(twoList)) {
|
if (Lang.isNotEmpty(twoList)) {
|
||||||
twoMap = twoList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
twoMap = twoList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//丙组
|
//丙组
|
||||||
List<NutMap> threeList = allList.stream().filter(a -> a.getString("bszbName").equals("丙组")).collect(toList());
|
List<NutMap> threeList = allList.stream().filter(a -> Objects.equals("丙组", a.getString("bszbName"))).collect(toList());
|
||||||
if (Lang.isNotEmpty(threeList)) {
|
if (Lang.isNotEmpty(threeList)) {
|
||||||
threeMap = threeList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
threeMap = threeList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//丁组
|
//丁组
|
||||||
List<NutMap> fourList = allList.stream().filter(a -> a.getString("bszbName").equals("丁组")).collect(toList());
|
List<NutMap> fourList = allList.stream().filter(a -> Objects.equals("丁组", a.getString("bszbName"))).collect(toList());
|
||||||
if (Lang.isNotEmpty(fourList)) {
|
if (Lang.isNotEmpty(fourList)) {
|
||||||
fourMap = fourList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
fourMap = fourList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
//团体
|
//团体
|
||||||
List<NutMap> fiveList = allList.stream().filter(a -> a.getString("bszbName").equals("团体")).collect(toList());
|
List<NutMap> fiveList = allList.stream().filter(a -> Objects.equals("团体", a.getString("bszbName"))).collect(toList());
|
||||||
if (Lang.isNotEmpty(fiveList)) {
|
if (Lang.isNotEmpty(fiveList)) {
|
||||||
fiveMap = fiveList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
fiveMap = fiveList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||||
}
|
}
|
||||||
|
|||||||
+45
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.activity.sports.controller;
|
|||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.service.BaseService;
|
import com.budwk.app.base.service.BaseService;
|
||||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
@@ -9,6 +10,8 @@ import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
|||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
||||||
|
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService;
|
||||||
|
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsService;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
@@ -19,7 +22,12 @@ import org.nutz.lang.Lang;
|
|||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
import org.nutz.mvc.annotation.At;
|
import org.nutz.mvc.annotation.At;
|
||||||
import org.nutz.mvc.annotation.Ok;
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
import org.nutz.mvc.annotation.AdaptBy;
|
||||||
|
import org.nutz.mvc.upload.TempFile;
|
||||||
|
import org.nutz.mvc.upload.UploadAdaptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -45,6 +53,10 @@ public class ActivitySportsReadingController {
|
|||||||
public Dao dao;
|
public Dao dao;
|
||||||
@Inject
|
@Inject
|
||||||
public BaseService baseService;
|
public BaseService baseService;
|
||||||
|
@Inject
|
||||||
|
private ActivitySportsService activitySportsService;
|
||||||
|
@Inject
|
||||||
|
private ActivitySportsApplyUserService activitySportsApplyUserService;
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.reading")
|
@SaCheckPermission("activity.reading")
|
||||||
@@ -150,5 +162,38 @@ public class ActivitySportsReadingController {
|
|||||||
return Result.success(apply);
|
return Result.success(apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@SaCheckPermission("activity.reading")
|
||||||
|
public void downloadImportTemplate(HttpServletResponse response) {
|
||||||
|
checkManageRole();
|
||||||
|
activitySportsApplyUserService.downloadImportTemplate(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("activity.reading")
|
||||||
|
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
|
||||||
|
public Result importUserActivitys(@Param("file") TempFile file, @Param("businessId") String activityId) {
|
||||||
|
checkManageRole();
|
||||||
|
return Result.success(activitySportsApplyUserService.importUserActivitys(file, activityId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@SaCheckPermission("activity.reading")
|
||||||
|
public void doExportByEnroll(String id, String unionId, HttpServletResponse response) {
|
||||||
|
checkManageRole();
|
||||||
|
activitySportsService.exportXlsx(id, unionId, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参考原项目,导入和整表导出只开放给校工会管理员和系统管理员,避免普通阅览权限误操作。
|
||||||
|
*/
|
||||||
|
private void checkManageRole() {
|
||||||
|
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||||
|
throw new BaseException("您没有操作权限");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -6,7 +6,9 @@ import com.budwk.app.base.service.BaseService;
|
|||||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
||||||
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
import org.nutz.mvc.upload.TempFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ActivitySportsApplyUserService extends BaseService<ActivitySchoolApply> {
|
public interface ActivitySportsApplyUserService extends BaseService<ActivitySchoolApply> {
|
||||||
@@ -31,4 +33,20 @@ public interface ActivitySportsApplyUserService extends BaseService<ActivityScho
|
|||||||
|
|
||||||
List<NutMap> getUserUnion(String query);
|
List<NutMap> getUserUnion(String query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载报名人员导入模板。
|
||||||
|
*
|
||||||
|
* @param response 响应流
|
||||||
|
*/
|
||||||
|
void downloadImportTemplate(HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入报名人员并返回错误明细,全部成功时返回 null。
|
||||||
|
*
|
||||||
|
* @param file 导入文件
|
||||||
|
* @param activityId 活动ID
|
||||||
|
* @return 导入错误统计
|
||||||
|
*/
|
||||||
|
NutMap importUserActivitys(TempFile file, String activityId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+234
-1
@@ -1,22 +1,33 @@
|
|||||||
package com.budwk.app.zhgh.activity.sports.service.impl;
|
package com.budwk.app.zhgh.activity.sports.service.impl;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.sys.models.Sys_user;
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
|
import com.budwk.app.zhgh.activity.basic.models.ActivityEvent;
|
||||||
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.activity.basic.service.ActivityBasicScopeService;
|
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||||
|
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
||||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
||||||
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolEvent;
|
||||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolTeam;
|
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolTeam;
|
||||||
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
||||||
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService;
|
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService;
|
||||||
|
import com.budwk.app.zhgh.activity.sports.template.ActivitySportsApplyImportTemp;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Chain;
|
import org.nutz.dao.Chain;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
@@ -31,7 +42,9 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
|||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.Strings;
|
import org.nutz.lang.Strings;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
import org.nutz.mvc.upload.TempFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -487,4 +500,224 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
|||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
return listMap(sql);
|
return listMap(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void downloadImportTemplate(HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
ExportParams exportParams = new ExportParams();
|
||||||
|
exportParams.setType(ExcelType.XSSF);
|
||||||
|
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, ActivitySportsApplyImportTemp.class, new ArrayList<>());
|
||||||
|
CommonDownloadUtil.download("报名人员导入模板.xlsx", workbook, response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BaseException("下载导入模板失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public NutMap importUserActivitys(TempFile file, String activityId) {
|
||||||
|
if (file == null) {
|
||||||
|
throw new BaseException("请选择导入文件");
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(activityId)) {
|
||||||
|
throw new BaseException("请先选择活动名称");
|
||||||
|
}
|
||||||
|
ActivitySchool activitySchool = dao().fetch(ActivitySchool.class, activityId);
|
||||||
|
if (activitySchool == null) {
|
||||||
|
throw new BaseException("活动不存在");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<ActivitySportsApplyImportTemp> importList = ExcelImportUtil.importExcel(file.getFile(), ActivitySportsApplyImportTemp.class, new ImportParams());
|
||||||
|
if (Lang.isEmpty(importList)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<ActivitySportsApplyImportTemp> errorList = new ArrayList<>();
|
||||||
|
int totalCount = 0;
|
||||||
|
int successCount = 0;
|
||||||
|
String currentUnionId = getUnionId();
|
||||||
|
for (ActivitySportsApplyImportTemp importTemp : importList) {
|
||||||
|
totalCount++;
|
||||||
|
String loginName = normalizeLoginName(importTemp.getLoginName());
|
||||||
|
if (StrUtil.isBlank(loginName)) {
|
||||||
|
importTemp.setNotes("工号不能为空");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Sys_user sysUser = dao().fetch(Sys_user.class, Cnd.where("loginname", "=", loginName));
|
||||||
|
if (sysUser == null) {
|
||||||
|
importTemp.setNotes("此用户不存在,请检查工号");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ActivityBasicUnit basicUnit = dao().fetch(ActivityBasicUnit.class, Cnd.where("id", "=", sysUser.getUnitId()));
|
||||||
|
if (basicUnit == null) {
|
||||||
|
importTemp.setNotes("请检查该人员活动单位是否配置正确");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ActivityBasicUnion basicUnion = dao().fetch(ActivityBasicUnion.class, Cnd.where("id", "=", basicUnit.getUnionId()));
|
||||||
|
if (basicUnion == null) {
|
||||||
|
importTemp.setNotes("请检查该人员所属活动工会是否配置正确");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!hasImportAuth() && !basicUnion.getId().equals(currentUnionId)) {
|
||||||
|
importTemp.setNotes("此用户不是当前工会人员");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String identityName = normalizeIdentityName(importTemp.getIdentity());
|
||||||
|
String projectCode = normalizeText(importTemp.getProjectCode());
|
||||||
|
if (StrUtil.isBlank(projectCode) && StrUtil.isBlank(identityName)) {
|
||||||
|
importTemp.setNotes("项目编号和身份不能同时为空");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivitySchoolApply activitySchoolApply = buildBaseApply(activityId, sysUser, basicUnit, basicUnion);
|
||||||
|
if (StrUtil.isNotBlank(identityName)) {
|
||||||
|
fillIdentityInfo(activitySchoolApply, identityName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(projectCode) && StrUtil.isNotBlank(identityName)) {
|
||||||
|
replaceUnionRoleUser(activitySchoolApply, identityName);
|
||||||
|
insert(activitySchoolApply);
|
||||||
|
successCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityEvent activityEvent = dao().fetch(ActivityEvent.class, Cnd.where("projectCode", "=", projectCode));
|
||||||
|
if (activityEvent == null) {
|
||||||
|
importTemp.setNotes("项目编号不存在,请检查后重试");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ActivitySchoolEvent schoolEvent = dao().fetch(ActivitySchoolEvent.class, Cnd.where("activityId", "=", activityId).and("eventId", "=", activityEvent.getId()));
|
||||||
|
if (schoolEvent == null) {
|
||||||
|
importTemp.setNotes("该项目不属于当前活动,请检查项目编号");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
activitySchoolApply.setEventId(schoolEvent.getEventId());
|
||||||
|
activitySchoolApply.setAwardsMode(activityEvent.getProjectType());
|
||||||
|
if ("2".equals(activityEvent.getProjectType())) {
|
||||||
|
ActivitySchoolTeam schoolTeam = dao().fetch(ActivitySchoolTeam.class, Cnd.where("activityId", "=", activityId).and("eventId", "=", schoolEvent.getEventId()).asc("location"));
|
||||||
|
if (schoolTeam == null) {
|
||||||
|
importTemp.setNotes("团体项目未配置队伍信息,请先维护小队");
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
activitySchoolApply.setTeamId(schoolTeam.getId());
|
||||||
|
activitySchoolApply.setTeam(schoolTeam.getName());
|
||||||
|
}
|
||||||
|
// 兼容参考项目导入逻辑:带项目编号的记录按运动员处理。
|
||||||
|
activitySchoolApply.setIdentity(List.of("1"));
|
||||||
|
clear(Cnd.where("activityId", "=", activityId).and("userId", "=", sysUser.getId()).and("eventId", "=", schoolEvent.getEventId()));
|
||||||
|
insert(activitySchoolApply);
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Lang.isNotEmpty(errorList)) {
|
||||||
|
NutMap result = NutMap.NEW();
|
||||||
|
result.setv("totalCount", totalCount);
|
||||||
|
result.setv("successCount", successCount);
|
||||||
|
result.setv("errorCount", errorList.size());
|
||||||
|
result.setv("errorList", errorList.stream().map(v -> NutMap.NEW()
|
||||||
|
.addv("工会", normalizeText(v.getUnionName()))
|
||||||
|
.addv("工号", normalizeText(v.getLoginName()))
|
||||||
|
.addv("姓名", normalizeText(v.getUserName()))
|
||||||
|
.addv("性别", normalizeText(v.getSex()))
|
||||||
|
.addv("项目编号", normalizeText(v.getProjectCode()))
|
||||||
|
.addv("身份", normalizeText(v.getIdentity()))
|
||||||
|
.addv("错误信息", normalizeText(v.getNotes()))).collect(Collectors.toList()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BaseException("导入报名人员失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入记录统一补齐报名基础字段,避免多入口写入时字段不一致。
|
||||||
|
*/
|
||||||
|
private ActivitySchoolApply buildBaseApply(String activityId, Sys_user sysUser, ActivityBasicUnit basicUnit, ActivityBasicUnion basicUnion) {
|
||||||
|
ActivitySchoolApply activitySchoolApply = new ActivitySchoolApply();
|
||||||
|
activitySchoolApply.setActivityId(activityId);
|
||||||
|
activitySchoolApply.setUnitId(basicUnit.getId());
|
||||||
|
activitySchoolApply.setUnionId(basicUnion.getId());
|
||||||
|
activitySchoolApply.setApplyUser(SecurityUtil.getUserId());
|
||||||
|
activitySchoolApply.setUserId(sysUser.getId());
|
||||||
|
activitySchoolApply.setLoginname(sysUser.getLoginname());
|
||||||
|
activitySchoolApply.setUsername(sysUser.getUsername());
|
||||||
|
activitySchoolApply.setSex(sysUser.getSex());
|
||||||
|
activitySchoolApply.setMobile(sysUser.getMobile());
|
||||||
|
activitySchoolApply.setProfessionalLevel(sysUser.getProfessionalLevel());
|
||||||
|
activitySchoolApply.setBirthday(sysUser.getBirthday() == null ? null : DateUtil.formatDate(sysUser.getBirthday()));
|
||||||
|
activitySchoolApply.setApplyDate(DateUtil.now());
|
||||||
|
activitySchoolApply.setStatus(2);
|
||||||
|
activitySchoolApply.setUnitname(basicUnit.getName());
|
||||||
|
activitySchoolApply.setActivityUnionId(basicUnion.getId());
|
||||||
|
activitySchoolApply.setActivityUnionName(basicUnion.getName());
|
||||||
|
return activitySchoolApply;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色类导入只保留当前活动当前工会当前人员的一条对应身份记录,防止重复导入产生脏数据。
|
||||||
|
*/
|
||||||
|
private void replaceUnionRoleUser(ActivitySchoolApply activitySchoolApply, String identityName) {
|
||||||
|
Cnd cnd = Cnd.where("activityId", "=", activitySchoolApply.getActivityId())
|
||||||
|
.and("activityUnionId", "=", activitySchoolApply.getActivityUnionId())
|
||||||
|
.and("userId", "=", activitySchoolApply.getUserId());
|
||||||
|
if ("教练".equals(identityName)) {
|
||||||
|
cnd.and("unionCoach", "=", true);
|
||||||
|
} else if ("领队".equals(identityName)) {
|
||||||
|
cnd.and("unionLeader", "=", true);
|
||||||
|
} else if ("团长".equals(identityName)) {
|
||||||
|
cnd.and("unionHead", "=", true);
|
||||||
|
} else if ("工作人员".equals(identityName)) {
|
||||||
|
cnd.and("unionStaff", "=", true);
|
||||||
|
}
|
||||||
|
clear(cnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一处理导入身份映射,保证页面展示、导出与后续查询读取到一致的身份字段。
|
||||||
|
*/
|
||||||
|
private void fillIdentityInfo(ActivitySchoolApply activitySchoolApply, String identityName) {
|
||||||
|
if ("教练".equals(identityName)) {
|
||||||
|
activitySchoolApply.setUnionCoach(true);
|
||||||
|
activitySchoolApply.setIdentity(List.of("2"));
|
||||||
|
} else if ("领队".equals(identityName)) {
|
||||||
|
activitySchoolApply.setUnionLeader(true);
|
||||||
|
activitySchoolApply.setIdentity(List.of("3"));
|
||||||
|
} else if ("团长".equals(identityName)) {
|
||||||
|
activitySchoolApply.setUnionHead(true);
|
||||||
|
activitySchoolApply.setIdentity(List.of("6"));
|
||||||
|
} else if ("工作人员".equals(identityName)) {
|
||||||
|
activitySchoolApply.setUnionStaff(true);
|
||||||
|
activitySchoolApply.setIdentity(List.of("7"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasImportAuth() {
|
||||||
|
return AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeLoginName(String loginName) {
|
||||||
|
return StrUtil.isBlank(loginName) ? "" : loginName.replaceAll("\\s+", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeText(String text) {
|
||||||
|
return StrUtil.trimToEmpty(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeIdentityName(String identity) {
|
||||||
|
String identityName = normalizeText(identity);
|
||||||
|
if ("运动员".equals(identityName)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return identityName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.budwk.app.zhgh.activity.sports.template;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 体育活动报名导入模板
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ActivitySportsApplyImportTemp {
|
||||||
|
|
||||||
|
@Excel(name = "工会", width = 20)
|
||||||
|
private String unionName;
|
||||||
|
|
||||||
|
@Excel(name = "工号", width = 20)
|
||||||
|
private String loginName;
|
||||||
|
|
||||||
|
@Excel(name = "姓名", width = 20)
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Excel(name = "性别", width = 12)
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
@Excel(name = "项目编号", width = 20)
|
||||||
|
private String projectCode;
|
||||||
|
|
||||||
|
@Excel(name = "身份", width = 20)
|
||||||
|
private String identity;
|
||||||
|
|
||||||
|
@Excel(name = "备注", width = 30)
|
||||||
|
private String notes;
|
||||||
|
}
|
||||||
+21
@@ -9,6 +9,7 @@ import com.budwk.app.base.page.Pagination;
|
|||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.service.BaseService;
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.sys.models.Sys_home_activity;
|
||||||
import com.budwk.app.sys.models.Sys_user;
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
import com.budwk.app.sys.services.SysMsgService;
|
import com.budwk.app.sys.services.SysMsgService;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
@@ -81,17 +82,20 @@ public class ActivityWorksCollectionManageController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result insert(@Param("data") @Valid Activity_works_collection worksCollection) {
|
public Result insert(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||||
worksCollection.setIsSubmit(true);
|
worksCollection.setIsSubmit(true);
|
||||||
dao.insertWith(worksCollection, "subjectTypes");
|
dao.insertWith(worksCollection, "subjectTypes");
|
||||||
worksCollection.getSubjectTypes().forEach(item -> {
|
worksCollection.getSubjectTypes().forEach(item -> {
|
||||||
dao.insertLinks(item, "worksTypes");
|
dao.insertLinks(item, "worksTypes");
|
||||||
});
|
});
|
||||||
|
syncHomeActivity(worksCollection);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result save(@Param("data") @Valid Activity_works_collection worksCollection) {
|
public Result save(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||||
worksCollection.setIsSubmit(false);
|
worksCollection.setIsSubmit(false);
|
||||||
dao.insertWith(worksCollection, "subjectTypes");
|
dao.insertWith(worksCollection, "subjectTypes");
|
||||||
@@ -122,6 +126,7 @@ public class ActivityWorksCollectionManageController {
|
|||||||
Cnd.where(Activity_works_worksType::getId, "not in ", workIds)
|
Cnd.where(Activity_works_worksType::getId, "not in ", workIds)
|
||||||
.and(Activity_works_worksType::getSubjectId,"=",item.getId()));
|
.and(Activity_works_worksType::getSubjectId,"=",item.getId()));
|
||||||
});
|
});
|
||||||
|
syncHomeActivity(worksCollection);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +137,7 @@ public class ActivityWorksCollectionManageController {
|
|||||||
dao.delete(Activity_works_collection.class, id);
|
dao.delete(Activity_works_collection.class, id);
|
||||||
dao.clear(Activity_works_collection_upload.class, Cnd.where(Activity_works_collection_upload::getActivityId, "=", id));
|
dao.clear(Activity_works_collection_upload.class, Cnd.where(Activity_works_collection_upload::getActivityId, "=", id));
|
||||||
dao.clear(Activity_works_subjectType.class, Cnd.where(Activity_works_subjectType::getActivityId, "=", id));
|
dao.clear(Activity_works_subjectType.class, Cnd.where(Activity_works_subjectType::getActivityId, "=", id));
|
||||||
|
dao.delete(Sys_home_activity.class, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,11 +154,26 @@ public class ActivityWorksCollectionManageController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result enableChange(@Valid String id, @Valid Boolean enable) {
|
public Result enableChange(@Valid String id, @Valid Boolean enable) {
|
||||||
dao.update(Activity_works_collection.class, Chain.make("enable", enable), Cnd.where("id", "=", id));
|
dao.update(Activity_works_collection.class, Chain.make("enable", enable), Cnd.where("id", "=", id));
|
||||||
|
Activity_works_collection worksCollection = dao.fetch(Activity_works_collection.class, id);
|
||||||
|
worksCollection.setEnable(enable);
|
||||||
|
syncHomeActivity(worksCollection);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步作品征集到首页活动表:开启的活动写入首页,关闭的活动移除首页入口。
|
||||||
|
*/
|
||||||
|
private void syncHomeActivity(Activity_works_collection worksCollection) {
|
||||||
|
if (Boolean.TRUE.equals(worksCollection.getEnable())) {
|
||||||
|
dao.insertOrUpdate(worksCollection.covertToSysHomeActivity());
|
||||||
|
} else {
|
||||||
|
dao.delete(Sys_home_activity.class, worksCollection.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
public Result sendNotice(@Valid String id) {
|
public Result sendNotice(@Valid String id) {
|
||||||
|
|||||||
+24
-3
@@ -11,6 +11,7 @@ import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
|||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.FieldFilter;
|
import org.nutz.dao.FieldFilter;
|
||||||
@@ -18,6 +19,7 @@ import org.nutz.dao.Sqls;
|
|||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
import org.nutz.dao.util.Daos;
|
import org.nutz.dao.util.Daos;
|
||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.mvc.annotation.At;
|
import org.nutz.mvc.annotation.At;
|
||||||
@@ -94,11 +96,17 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
*/
|
*/
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result insert(@Param("data") @Valid Activity_works_collection_upload upload) {
|
public Result insert(@Param("data") @Valid Activity_works_collection_upload upload) {
|
||||||
|
|
||||||
String activityId = upload.getActivityId();
|
String activityId = upload.getActivityId();
|
||||||
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, activityId);
|
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, activityId);
|
||||||
if (activity.getEndDateTime().getTime() < System.currentTimeMillis()){
|
long now = System.currentTimeMillis();
|
||||||
|
// 作品上传只允许在活动开始时间和结束时间之间提交,防止活动未开始或已结束后继续上传。
|
||||||
|
if (activity.getStartDateTime().getTime() > now) {
|
||||||
|
return Result.error("活动未开始,不能上传!");
|
||||||
|
}
|
||||||
|
if (activity.getEndDateTime().getTime() < now){
|
||||||
return Result.error("活动已结束!");
|
return Result.error("活动已结束!");
|
||||||
}
|
}
|
||||||
if (activity.getActivityGroupId() != null) {
|
if (activity.getActivityGroupId() != null) {
|
||||||
@@ -124,9 +132,15 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result update(@Param("data") @Valid Activity_works_collection_upload upload) {
|
public Result update(@Param("data") @Valid Activity_works_collection_upload upload) {
|
||||||
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, upload.getActivityId());
|
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, upload.getActivityId());
|
||||||
if (activity.getEndDateTime().getTime() < System.currentTimeMillis()){
|
long now = System.currentTimeMillis();
|
||||||
|
// 编辑作品同样按活动时间窗口控制,避免过期或未开始活动被继续提交作品信息。
|
||||||
|
if (activity.getStartDateTime().getTime() > now) {
|
||||||
|
return Result.error("活动未开始,不能上传!");
|
||||||
|
}
|
||||||
|
if (activity.getEndDateTime().getTime() < now){
|
||||||
return Result.error("活动已结束!");
|
return Result.error("活动已结束!");
|
||||||
}
|
}
|
||||||
dao.updateIgnoreNull(upload);
|
dao.updateIgnoreNull(upload);
|
||||||
@@ -155,12 +169,19 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
|
/**
|
||||||
|
* 查询当前登录人有权限上传作品的活动主题。
|
||||||
|
*
|
||||||
|
* @param year 活动年度,前端传年度选择框的 yyyy 值,按活动开始时间所在年份过滤。
|
||||||
|
* @return Result,data 为活动列表,仅返回 id、name,且保留已开启和面向对象权限过滤。
|
||||||
|
*/
|
||||||
@ApiOperation("获取有权限的活动列表")
|
@ApiOperation("获取有权限的活动列表")
|
||||||
@Ok("json:{ignoreNull:true}")
|
@Ok("json:{ignoreNull:true}")
|
||||||
public Result listPerMissionActivity() {
|
public Result listPerMissionActivity(Long year) {
|
||||||
Dao extDao = Daos.ext(dao, FieldFilter.create(Activity_works_collection.class, "id|name|"));
|
Dao extDao = Daos.ext(dao, FieldFilter.create(Activity_works_collection.class, "id|name|"));
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.and(Activity_works_collection::getEnable,"=",1);
|
cnd.and(Activity_works_collection::getEnable,"=",1);
|
||||||
|
cnd.andEX("YEAR(startDateTime)", "=", year);
|
||||||
cnd.desc(Activity_works_collection::getStartDateTime);
|
cnd.desc(Activity_works_collection::getStartDateTime);
|
||||||
List<Activity_works_collection> list = extDao.query(Activity_works_collection.class, cnd);
|
List<Activity_works_collection> list = extDao.query(Activity_works_collection.class, cnd);
|
||||||
list = list.stream().filter(item -> {
|
list = list.stream().filter(item -> {
|
||||||
|
|||||||
+20
-1
@@ -1,6 +1,8 @@
|
|||||||
package com.budwk.app.zhgh.activity.workscollection.models;
|
package com.budwk.app.zhgh.activity.workscollection.models;
|
||||||
|
|
||||||
import com.budwk.app.base.model.BaseModel;
|
import com.budwk.app.base.model.BaseModel;
|
||||||
|
import com.budwk.app.sys.models.Sys_home_activity;
|
||||||
|
import com.budwk.app.sys.services.SysHomeConvert;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.nutz.dao.entity.annotation.*;
|
import org.nutz.dao.entity.annotation.*;
|
||||||
@@ -17,7 +19,7 @@ import java.util.List;
|
|||||||
@Table("activity_works_collection")
|
@Table("activity_works_collection")
|
||||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||||
@Comment("作品征集活动")
|
@Comment("作品征集活动")
|
||||||
public class Activity_works_collection extends BaseModel {
|
public class Activity_works_collection extends BaseModel implements SysHomeConvert {
|
||||||
|
|
||||||
@Name
|
@Name
|
||||||
@Comment("ID")
|
@Comment("ID")
|
||||||
@@ -123,4 +125,21 @@ public class Activity_works_collection extends BaseModel {
|
|||||||
@Many(field = "activityId")
|
@Many(field = "activityId")
|
||||||
private List<Activity_works_collection_upload> uploads;
|
private List<Activity_works_collection_upload> uploads;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sys_home_activity covertToSysHomeActivity() {
|
||||||
|
Sys_home_activity sysHomeActivity = new Sys_home_activity();
|
||||||
|
sysHomeActivity.setId(this.getId());
|
||||||
|
sysHomeActivity.setName(this.getName());
|
||||||
|
sysHomeActivity.setCover(this.getCover());
|
||||||
|
sysHomeActivity.setContent(this.getContent());
|
||||||
|
sysHomeActivity.setUrl("/platform/activity/worksCollection/upload");
|
||||||
|
sysHomeActivity.setH5Url("/platform/activity/worksCollection/upload/h5");
|
||||||
|
sysHomeActivity.setStartDate(this.getStartDateTime());
|
||||||
|
sysHomeActivity.setEndDate(this.getEndDateTime());
|
||||||
|
sysHomeActivity.setAllowUserGroupId(this.getActivityGroupId());
|
||||||
|
sysHomeActivity.setEnable(Boolean.TRUE.equals(this.getEnable()));
|
||||||
|
sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName());
|
||||||
|
return sysHomeActivity;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -68,7 +68,7 @@ public class ClubUserJoinApplyController {
|
|||||||
@Inject
|
@Inject
|
||||||
private ClubUserJoinService clubUserJoinService;
|
private ClubUserJoinService clubUserJoinService;
|
||||||
|
|
||||||
@At("/")
|
@At("")
|
||||||
@SaCheckPermission("club.join.apply")
|
@SaCheckPermission("club.join.apply")
|
||||||
@Ok("beetl:/platform/zhgh/club/join/apply/index.html")
|
@Ok("beetl:/platform/zhgh/club/join/apply/index.html")
|
||||||
public void index() {
|
public void index() {
|
||||||
@@ -128,6 +128,12 @@ public class ClubUserJoinApplyController {
|
|||||||
@SLog(tag = "社团管理系统-申请入/退会", msg = "申请社团入/退会")
|
@SLog(tag = "社团管理系统-申请入/退会", msg = "申请社团入/退会")
|
||||||
public Result submit(@Param("data") ClubUserApply clubUserApply,
|
public Result submit(@Param("data") ClubUserApply clubUserApply,
|
||||||
@Param("mode") Boolean mode) {
|
@Param("mode") Boolean mode) {
|
||||||
|
if (Boolean.TRUE.equals(mode)) {
|
||||||
|
String qualificationMsg = clubUserJoinService.checkJoinQualification(SecurityUtil.getUserId());
|
||||||
|
if (StrUtil.isNotBlank(qualificationMsg)) {
|
||||||
|
return Result.error(99, qualificationMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(mode == false) {
|
if(mode == false) {
|
||||||
clubUserApply = clubUserJoinService.buildExitApply(clubUserApply.getClubId(), SecurityUtil.getUserId());
|
clubUserApply = clubUserJoinService.buildExitApply(clubUserApply.getClubId(), SecurityUtil.getUserId());
|
||||||
if (ObjectUtil.isEmpty(clubUserApply)) {
|
if (ObjectUtil.isEmpty(clubUserApply)) {
|
||||||
@@ -192,6 +198,10 @@ public class ClubUserJoinApplyController {
|
|||||||
@ApiOperation("校验是否申请过社团")
|
@ApiOperation("校验是否申请过社团")
|
||||||
@SaCheckPermission(value = {"club.join.apply", "h5.club.join.apply"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"club.join.apply", "h5.club.join.apply"}, mode = SaMode.OR)
|
||||||
public Result checkApplyClub(@Valid String clubId) {
|
public Result checkApplyClub(@Valid String clubId) {
|
||||||
|
String qualificationMsg = clubUserJoinService.checkJoinQualification(SecurityUtil.getUserId());
|
||||||
|
if (StrUtil.isNotBlank(qualificationMsg)) {
|
||||||
|
return Result.error(99, qualificationMsg);
|
||||||
|
}
|
||||||
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
||||||
if (user.getMember() != 1) {
|
if (user.getMember() != 1) {
|
||||||
return Result.error(99, "抱歉,您不满足入会的条件!");
|
return Result.error(99, "抱歉,您不满足入会的条件!");
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ public class ClubUserJoinApprovalController {
|
|||||||
@Inject
|
@Inject
|
||||||
private ClubUserJoinService clubUserJoinService;
|
private ClubUserJoinService clubUserJoinService;
|
||||||
|
|
||||||
@At("/")
|
@At("")
|
||||||
@SaCheckPermission("club.join.clubApproval")
|
@SaCheckPermission("club.join.clubApproval")
|
||||||
@Ok("beetl:/platform/zhgh/club/join/clubApproval/index.html")
|
@Ok("beetl:/platform/zhgh/club/join/clubApproval/index.html")
|
||||||
public void index() {}
|
public void index() {}
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ public class ClubUserJoinMineController {
|
|||||||
@Inject
|
@Inject
|
||||||
private ClubUserJoinService clubUserJoinService;
|
private ClubUserJoinService clubUserJoinService;
|
||||||
|
|
||||||
@At("/")
|
@At("")
|
||||||
@SaCheckPermission("club.join.mine")
|
@SaCheckPermission("club.join.mine")
|
||||||
@Ok("beetl:/platform/zhgh/club/join/mine/index.html")
|
@Ok("beetl:/platform/zhgh/club/join/mine/index.html")
|
||||||
public void index() {}
|
public void index() {}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class ClubCommonController {
|
|||||||
@SaCheckLogin
|
@SaCheckLogin
|
||||||
public Result listClubByRole() {
|
public Result listClubByRole() {
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name())) {
|
||||||
// 报销申请只允许选择当前用户已加入的协会,避免看到未加入的协会数据。
|
// 报销申请只允许选择当前用户已加入的协会,避免看到未加入的协会数据。
|
||||||
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
|
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
|
||||||
List<String> myClubId = clubUsers.stream().map(ClubUser::getClubId).distinct().toList();
|
List<String> myClubId = clubUsers.stream().map(ClubUser::getClubId).distinct().toList();
|
||||||
@@ -78,4 +78,12 @@ public class ClubCommonController {
|
|||||||
return Result.success(list);
|
return Result.success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckLogin
|
||||||
|
public Result listManageClubByRole() {
|
||||||
|
// 活动人员范围设置只允许按“可管理的社团”选择,避免把仅作为成员加入的社团也展示出来。
|
||||||
|
List<SysClub> clubList = sysClubService.getMyManageClub();
|
||||||
|
return Result.success(clubList);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,4 +25,12 @@ public interface ClubUserJoinService extends BaseService<ClubUserApply> {
|
|||||||
* @return 入会时间
|
* @return 入会时间
|
||||||
*/
|
*/
|
||||||
java.util.Date resolveJoinTime(String clubId, String userId);
|
java.util.Date resolveJoinTime(String clubId, String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验当前用户是否满足申请加入社团的资格。
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 校验不通过时返回提示语,通过时返回null
|
||||||
|
*/
|
||||||
|
String checkJoinQualification(String userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
package com.budwk.app.zhgh.club.service.impl;
|
||||||
|
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.sys.views.View_user;
|
import com.budwk.app.sys.views.View_user;
|
||||||
import com.budwk.app.zhgh.club.model.ClubUser;
|
import com.budwk.app.zhgh.club.model.ClubUser;
|
||||||
import com.budwk.app.zhgh.club.model.ClubUserApply;
|
import com.budwk.app.zhgh.club.model.ClubUserApply;
|
||||||
@@ -15,10 +18,37 @@ import java.util.List;
|
|||||||
|
|
||||||
@IocBean(args = {"refer:dao"})
|
@IocBean(args = {"refer:dao"})
|
||||||
public class ClubUserJoinServiceImpl extends BaseServiceImpl<ClubUserApply> implements ClubUserJoinService {
|
public class ClubUserJoinServiceImpl extends BaseServiceImpl<ClubUserApply> implements ClubUserJoinService {
|
||||||
|
private static final List<String> ALLOW_JOIN_PERSON_TYPES = List.of(
|
||||||
|
"教职工",
|
||||||
|
"未起薪人员",
|
||||||
|
"教职工新入会",
|
||||||
|
"教职工其他",
|
||||||
|
"劳动服务公司",
|
||||||
|
"后勤聘用人员",
|
||||||
|
"退休人员[一]",
|
||||||
|
"退休人员[二]",
|
||||||
|
"校聘劳务派遣全额"
|
||||||
|
);
|
||||||
|
|
||||||
public ClubUserJoinServiceImpl(Dao dao) {
|
public ClubUserJoinServiceImpl(Dao dao) {
|
||||||
super(dao);
|
super(dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String checkJoinQualification(String userId) {
|
||||||
|
View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", userId));
|
||||||
|
if (user == null) {
|
||||||
|
return "抱歉,您不满足入会的条件!";
|
||||||
|
}
|
||||||
|
if (user.getMember() == null || user.getMember() != 1) {
|
||||||
|
return "抱歉,您不满足入会的条件!";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(user.getPersonType()) || !ALLOW_JOIN_PERSON_TYPES.contains(user.getPersonType())) {
|
||||||
|
return "抱歉,您不满足入会的条件!";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClubUserApply buildExitApply(String clubId, String userId) {
|
public ClubUserApply buildExitApply(String clubId, String userId) {
|
||||||
// 优先复用最近一次申请记录中的补充信息,避免用户重复填写基础资料。
|
// 优先复用最近一次申请记录中的补充信息,避免用户重复填写基础资料。
|
||||||
|
|||||||
@@ -275,7 +275,14 @@ public class SysClubServiceImpl extends BaseServiceImpl<SysClub> implements SysC
|
|||||||
}
|
}
|
||||||
cnd.andEX("year(info.createTime)", "=", pageForm.getYear());
|
cnd.andEX("year(info.createTime)", "=", pageForm.getYear());
|
||||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||||
cnd.desc("createTime");
|
// 我的注册列表默认按社团编码升序展示,点击表头时按用户选择的方向排序。
|
||||||
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.asc("info.clubCode");
|
||||||
|
} else if ("clubCode".equals(pageForm.getPageOrderName())) {
|
||||||
|
cnd.orderBy("info.clubCode", PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
} else {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
}
|
||||||
cnd.groupBy("info.id");
|
cnd.groupBy("info.id");
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
return listPageVO(pageForm, sql, ClubRegisterPageVo.class);
|
return listPageVO(pageForm, sql, ClubRegisterPageVo.class);
|
||||||
|
|||||||
+11
-13
@@ -1,6 +1,7 @@
|
|||||||
package com.budwk.app.zhgh.dayofficework.message.strategy.impl;
|
package com.budwk.app.zhgh.dayofficework.message.strategy.impl;
|
||||||
|
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.base.sms.SmsService;
|
||||||
import com.budwk.app.sys.models.Sys_user;
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel;
|
import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel;
|
||||||
import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy;
|
import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy;
|
||||||
@@ -21,6 +22,8 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Dao dao;
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private SmsService smsService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GlobalMessageChannel getChannel() {
|
public GlobalMessageChannel getChannel() {
|
||||||
@@ -70,29 +73,24 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送短信消息
|
* 发送短信消息。
|
||||||
|
* 接收人由全局消息服务传入的用户ID或登录名查询得到,发送时使用用户工号对接通讯平台;
|
||||||
|
* 返回结果由 SmsService 内部解析并记录,当前策略只负责逐个用户触发发送并记录异常。
|
||||||
*/
|
*/
|
||||||
private void sendSmsMessage(String title, String content, Integer type, List<Sys_user> users, JSONObject config) {
|
private void sendSmsMessage(String title, String content, Integer type, List<Sys_user> users, JSONObject config) {
|
||||||
for (Sys_user user : users) {
|
for (Sys_user user : users) {
|
||||||
try {
|
try {
|
||||||
String mobile = user.getMobile();
|
String loginName = user.getLoginname();
|
||||||
if (mobile == null || mobile.trim().isEmpty()) {
|
if (loginName == null || loginName.trim().isEmpty()) {
|
||||||
log.warn("用户{}没有手机号,跳过短信发送", user.getUsername());
|
log.warn("用户{}没有工号,跳过短信发送", user.getUsername());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建短信内容
|
// 构建短信内容
|
||||||
String smsContent = buildSmsContent(title, content, type);
|
String smsContent = buildSmsContent(title, content, type);
|
||||||
|
|
||||||
// 执行发送
|
smsService.sendSmsByAccount(loginName, smsContent);
|
||||||
|
log.info("短信发送完成:用户{},工号:{}", user.getUsername(), loginName);
|
||||||
boolean success = true;
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
log.info("短信发送成功:用户{},手机号:{}", user.getUsername(), mobile);
|
|
||||||
} else {
|
|
||||||
log.warn("短信发送失败:用户{},手机号:{}", user.getUsername(), mobile);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("发送短信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e);
|
log.error("发送短信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.message.strategy.impl;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.base.sms.SmsService;
|
||||||
|
import com.budwk.app.sys.models.Sys_user;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信发送策略
|
||||||
|
*/
|
||||||
|
@IocBean
|
||||||
|
@Slf4j
|
||||||
|
public class WechatMessageSendStrategy implements GlobalMessageSendStrategy {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private SmsService smsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GlobalMessageChannel getChannel() {
|
||||||
|
return GlobalMessageChannel.WECHAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportAsync() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(String title, String content, Integer type, List<String> receiverIds, JSONObject config) {
|
||||||
|
try {
|
||||||
|
log.info("开始发送微信消息,标题:{},接收人数量:{}", title, receiverIds.size());
|
||||||
|
|
||||||
|
// receiverIds 为 sys_user.id,按用户ID查询后使用工号对接通讯平台微信文本消息接口。
|
||||||
|
List<Sys_user> users = dao.query(Sys_user.class, Cnd.where(Sys_user::getId, "in", receiverIds));
|
||||||
|
sendWechatMessage(title, content, type, users, config);
|
||||||
|
|
||||||
|
log.info("微信消息发送完成,标题:{},接收人数量:{}", title, users.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("微信消息发送失败,标题:{},错误:{}", title, e.getMessage(), e);
|
||||||
|
throw new RuntimeException("微信消息发送失败:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendByLoginName(String title, String content, Integer type, List<String> receiverLoginNames, JSONObject config) {
|
||||||
|
try {
|
||||||
|
log.info("开始发送微信消息(按登录名),标题:{},接收人数量:{}", title, receiverLoginNames.size());
|
||||||
|
|
||||||
|
// receiverLoginNames 为 sys_user.loginname,查询用户后仍使用工号作为通讯平台接收人标识。
|
||||||
|
List<Sys_user> users = dao.query(Sys_user.class, Cnd.where(Sys_user::getLoginname, "in", receiverLoginNames));
|
||||||
|
sendWechatMessage(title, content, type, users, config);
|
||||||
|
|
||||||
|
log.info("微信消息发送完成(按登录名),标题:{},接收人数量:{}", title, users.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("微信消息发送失败(按登录名),标题:{},错误:{}", title, e.getMessage(), e);
|
||||||
|
throw new RuntimeException("微信消息发送失败:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送微信文本消息。
|
||||||
|
* 接收人来自全局消息服务传入的用户ID或登录名,方法内部转换为 Sys_user 后取工号发送;
|
||||||
|
* SmsService 返回 MsgPlatformResponse,当前策略按单人发送记录日志,单个用户失败不影响其他接收人。
|
||||||
|
*/
|
||||||
|
private void sendWechatMessage(String title, String content, Integer type, List<Sys_user> users, JSONObject config) {
|
||||||
|
for (Sys_user user : users) {
|
||||||
|
try {
|
||||||
|
String loginName = user.getLoginname();
|
||||||
|
if (loginName == null || loginName.trim().isEmpty()) {
|
||||||
|
log.warn("用户{}没有工号,跳过微信发送", user.getUsername());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String wechatContent = buildWechatContent(title, content, type);
|
||||||
|
smsService.sendWechatTextByAccountOrMobile(loginName, wechatContent);
|
||||||
|
log.info("微信发送完成:用户{},工号:{}", user.getUsername(), loginName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送微信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建微信文本内容。
|
||||||
|
* type=2 表示待办消息,其余类型按系统通知处理,内容格式保持与短信策略一致。
|
||||||
|
*/
|
||||||
|
private String buildWechatContent(String title, String content, Integer type) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (type != null && type == 2) {
|
||||||
|
sb.append("【待办通知】");
|
||||||
|
} else {
|
||||||
|
sb.append("【系统通知】");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(title);
|
||||||
|
if (content != null && !content.trim().isEmpty()) {
|
||||||
|
sb.append(":").append(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-1
@@ -457,9 +457,13 @@ public class SiteCugApplyController {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当预约日期就是今天时,已经过了开始时间的时间块直接标记为不可预约,
|
||||||
|
* 这样全天候和分段预约在前端展示时都会统一变成禁用状态。
|
||||||
|
*/
|
||||||
private NutMap buildAvailabilityBlock(String day, int startMinute, int endMinute, List<int[]> reservedRanges, List<int[]> disabledRanges, boolean siteClosed, int groupIndex, String groupLabel) {
|
private NutMap buildAvailabilityBlock(String day, int startMinute, int endMinute, List<int[]> reservedRanges, List<int[]> disabledRanges, boolean siteClosed, int groupIndex, String groupLabel) {
|
||||||
String status = "available";
|
String status = "available";
|
||||||
if (siteClosed || intersectsAny(startMinute, endMinute, disabledRanges)) {
|
if (siteClosed || isExpiredAvailabilityBlock(day, startMinute) || intersectsAny(startMinute, endMinute, disabledRanges)) {
|
||||||
status = "closed";
|
status = "closed";
|
||||||
} else if (intersectsAny(startMinute, endMinute, reservedRanges)) {
|
} else if (intersectsAny(startMinute, endMinute, reservedRanges)) {
|
||||||
status = "reserved";
|
status = "reserved";
|
||||||
@@ -478,6 +482,19 @@ public class SiteCugApplyController {
|
|||||||
.addv("endDateTime", day + " " + formatMinutes(endMinute) + ":00");
|
.addv("endDateTime", day + " " + formatMinutes(endMinute) + ":00");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅在当天按“时间块开始时间是否已经过去”判断是否失效,
|
||||||
|
* 避免用户继续选中已经开始或已经结束的预约时段。
|
||||||
|
*/
|
||||||
|
private boolean isExpiredAvailabilityBlock(String day, int startMinute) {
|
||||||
|
String today = DateUtil.today();
|
||||||
|
if (!StrUtil.equals(today, day)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DateTime blockStart = DateUtil.parseDateTime(day + " " + formatMinutes(startMinute) + ":00");
|
||||||
|
return !blockStart.isAfter(DateUtil.date());
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSiteClosed(SiteCugInfo siteInfo, String day, Set<String> holidaySet) {
|
private boolean isSiteClosed(SiteCugInfo siteInfo, String day, Set<String> holidaySet) {
|
||||||
if (isWeekend(day)) {
|
if (isWeekend(day)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+26
-17
@@ -113,22 +113,23 @@ public class UnionReimburseApplyController {
|
|||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @At
|
@At
|
||||||
// @ApiOperation("重新提交申请")
|
@ApiOperation("重新提交申请")
|
||||||
// @Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
// @SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||||
// public Result submitAgain(@Param("data") UnionReimburse unionReimburse, @Param("taskId") Long taskId) {
|
public Result submitAgain(@Param("data") UnionReimburse unionReimburse, @Param("taskId") Long taskId) {
|
||||||
// if (StrUtil.isBlank(unionReimburse.getId())) unionReimburse.setCreateTime(new Date());
|
// 退回重提也必须复用当前提交保存逻辑,避免绕过发票明细落库和提交校验。
|
||||||
//
|
Result result = unionReimburseService.saveApply(unionReimburse, 2);
|
||||||
// dao.insertOrUpdate(unionReimburse);
|
if (result.getCode() != 0) {
|
||||||
//
|
return result;
|
||||||
// Dict dict = Dict.create();
|
}
|
||||||
// dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
|
|
||||||
// dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
Dict dict = Dict.create();
|
||||||
// dict.set("userId", unionReimburse.getCondolenceUserId());
|
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
|
||||||
// flowCommonService.executeTask(dict);
|
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
||||||
// return Result.success();
|
flowCommonService.executeTask(dict);
|
||||||
// }
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckLogin
|
@SaCheckLogin
|
||||||
@@ -179,6 +180,14 @@ public class UnionReimburseApplyController {
|
|||||||
return Result.success(pagination.getList());
|
return Result.success(pagination.getList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("查询付款人")
|
||||||
|
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||||
|
@SLog(type = "unionReimburse", tag = "查询付款人", msg = "按经费来源查询付款人")
|
||||||
|
public Result listPayerUser(String keyword, String reimburseFundSource, String clubId) {
|
||||||
|
return Result.success(unionReimburseService.listPayerUser(keyword, reimburseFundSource, clubId));
|
||||||
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@ApiOperation("查询职工慰问类型")
|
@ApiOperation("查询职工慰问类型")
|
||||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||||
@@ -267,6 +276,6 @@ public class UnionReimburseApplyController {
|
|||||||
@ApiOperation("统一查询经费余额")
|
@ApiOperation("统一查询经费余额")
|
||||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
||||||
return unionReimburseService.getBudgetBalance(reimburseFundSource, clubId);
|
return unionReimburseService.getBudgetBalance(reimburseFundSource, clubId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -7,6 +7,7 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
|||||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.dev33.satoken.annotation.SaMode;
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
@@ -26,12 +27,14 @@ import io.swagger.annotations.Api;
|
|||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Chain;
|
import org.nutz.dao.Chain;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
@@ -117,12 +120,10 @@ public class UnionReimburseCollectController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
@SaCheckPermission(value = {"unionReimburse.collect", "h5.unionReimburse.collect"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.collect", "h5.unionReimburse.collect"}, mode = SaMode.OR)
|
||||||
public Result updateActuallyAmount(String id,Double realMoney) {
|
public Result updateActuallyAmount(String id,Double realMoney) {
|
||||||
UnionReimburse unionReimburse = unionReimburseService.fetch(id);
|
return unionReimburseService.updateActuallyAmount(id, realMoney);
|
||||||
unionReimburse.setRealMoney(realMoney);
|
|
||||||
unionReimburseService.updateIgnoreNull(unionReimburse);
|
|
||||||
return Result.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@@ -237,6 +238,9 @@ public class UnionReimburseCollectController {
|
|||||||
item.setReimburseFundSource(typeDict.getName());
|
item.setReimburseFundSource(typeDict.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (StrUtil.isNotBlank(item.getCreateTime())) {
|
||||||
|
item.setCreateTime(DateUtil.format(DateUtil.parse(item.getCreateTime()), "yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
|
||||||
// 拼接备注字段(仿照系统代码逻辑,使用activityName和condolenceName字段)
|
// 拼接备注字段(仿照系统代码逻辑,使用activityName和condolenceName字段)
|
||||||
if (cn.hutool.core.util.StrUtil.isNotBlank(item.getActivityName())) {
|
if (cn.hutool.core.util.StrUtil.isNotBlank(item.getActivityName())) {
|
||||||
|
|||||||
+3
-3
@@ -189,7 +189,7 @@ public class UnionReimburseMineController {
|
|||||||
@SaCheckPermission(value = {"unionReimburse.mine", "h5.unionReimburse.mine"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.mine", "h5.unionReimburse.mine"}, mode = SaMode.OR)
|
||||||
@SLog( tag = "删除工会报销", msg = "删除工会报销")
|
@SLog( tag = "删除工会报销", msg = "删除工会报销")
|
||||||
public Result delete(@Param("id") String id) {
|
public Result delete(@Param("id") String id) {
|
||||||
unionReimburseService.delete(id);
|
unionReimburseService.deleteApply(id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ public class UnionReimburseMineController {
|
|||||||
|
|
||||||
tempFile.deleteOnExit();
|
tempFile.deleteOnExit();
|
||||||
|
|
||||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd"));
|
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||||
docData.put("unitName", unionReimburse.getUnitName());
|
docData.put("unitName", unionReimburse.getUnitName());
|
||||||
docData.put("userName", unionReimburse.getUserName());
|
docData.put("userName", unionReimburse.getUserName());
|
||||||
docData.put("loginName", unionReimburse.getLoginName());
|
docData.put("loginName", unionReimburse.getLoginName());
|
||||||
@@ -309,7 +309,7 @@ public class UnionReimburseMineController {
|
|||||||
.create();
|
.create();
|
||||||
docData.put("qrcode", pictureRenderData);
|
docData.put("qrcode", pictureRenderData);
|
||||||
|
|
||||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd"));
|
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||||
docData.put("unitName", unionReimburse.getUnitName());
|
docData.put("unitName", unionReimburse.getUnitName());
|
||||||
docData.put("userName", unionReimburse.getUserName());
|
docData.put("userName", unionReimburse.getUserName());
|
||||||
docData.put("loginName", unionReimburse.getLoginName());
|
docData.put("loginName", unionReimburse.getLoginName());
|
||||||
|
|||||||
+2
-16
@@ -12,7 +12,6 @@ import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburse;
|
|||||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.service.UnionReimburseService;
|
import com.budwk.app.zhgh.dayofficework.unionReimburse.service.UnionReimburseService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
@@ -32,7 +31,6 @@ import java.util.List;
|
|||||||
@At("/platform/unionReimburse/review")
|
@At("/platform/unionReimburse/review")
|
||||||
@Ok("json:full")
|
@Ok("json:full")
|
||||||
@Api("工会报销审核")
|
@Api("工会报销审核")
|
||||||
@Slf4j
|
|
||||||
public class UnionReimburseReviewController {
|
public class UnionReimburseReviewController {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -110,19 +108,7 @@ public class UnionReimburseReviewController {
|
|||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
@SaCheckPermission(value = {"unionReimburse.review", "h5.unionReimburse.review"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"unionReimburse.review", "h5.unionReimburse.review"}, mode = SaMode.OR)
|
||||||
@SLog(tag = "工会报销审核", msg = "一键审核工会报销")
|
@SLog(tag = "工会报销审核", msg = "一键审核工会报销")
|
||||||
public Result allReview() {
|
public Result allReview(@Param("ids[]") String[] ids) {
|
||||||
try {
|
return unionReimburseService.batchReviewApply(ids);
|
||||||
List<UnionReimburse> reimbursements = unionReimburseService.query(Cnd.where("stateId", "=", 2));
|
|
||||||
for (UnionReimburse reimbursement : reimbursements) {
|
|
||||||
Result result = unionReimburseService.reviewApply(reimbursement.getId(), "通过", 3);
|
|
||||||
if (result.getCode() != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result.success("一键审核完成,共处理" + reimbursements.size() + "条记录");
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("一键审核失败", e);
|
|
||||||
return Result.error("一键审核失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-1
@@ -6,6 +6,7 @@ import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburse;
|
|||||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.param.UnionReimbursePageForm;
|
import com.budwk.app.zhgh.dayofficework.unionReimburse.param.UnionReimbursePageForm;
|
||||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.vo.UnionReimburseBankHistoryVO;
|
import com.budwk.app.zhgh.dayofficework.unionReimburse.vo.UnionReimburseBankHistoryVO;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -23,11 +24,26 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
|||||||
*/
|
*/
|
||||||
UnionReimburse getApplyForm(String id);
|
UnionReimburse getApplyForm(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除报销申请,并同步删除关联发票明细。
|
||||||
|
*/
|
||||||
|
void deleteApply(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询付款人的历史收款信息。
|
* 查询付款人的历史收款信息。
|
||||||
*/
|
*/
|
||||||
List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer);
|
List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询付款人候选人;协会经费按所选协会过滤,只返回该协会成员。
|
||||||
|
*
|
||||||
|
* @param keyword 姓名或工号关键字
|
||||||
|
* @param reimburseFundSource 当前选择的经费来源
|
||||||
|
* @param clubId 协会经费对应的协会ID
|
||||||
|
* @return 可选付款人列表
|
||||||
|
*/
|
||||||
|
List<NutMap> listPayerUser(String keyword, String reimburseFundSource, String clubId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验发票号码是否与历史报销记录重复。
|
* 校验发票号码是否与历史报销记录重复。
|
||||||
*/
|
*/
|
||||||
@@ -41,10 +57,23 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
|||||||
/**
|
/**
|
||||||
* 查询报销可用经费余额,同时校验是否已分配以及协会归属权限。
|
* 查询报销可用经费余额,同时校验是否已分配以及协会归属权限。
|
||||||
*/
|
*/
|
||||||
Result getBudgetBalance(String reimburseFundSource, String clubId);
|
Result getBudgetBalance(String reimburseFundSource, String clubId, String unionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 审核报销,审核通过时扣减对应预算并新增预算使用详情。
|
* 审核报销,审核通过时扣减对应预算并新增预算使用详情。
|
||||||
*/
|
*/
|
||||||
Result reviewApply(String reimburseId, String reviewOpinion, int submitType);
|
Result reviewApply(String reimburseId, String reviewOpinion, int submitType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员修改实际报销金额,已报销成功的数据需要同步调整经费预算管理台账。
|
||||||
|
*/
|
||||||
|
Result updateActuallyAmount(String id, Double realMoney);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量审核选中的待审核报销申请。
|
||||||
|
*
|
||||||
|
* @param reimburseIds 前端表格勾选的报销申请ID数组,只处理状态为待审核确认的数据
|
||||||
|
* @return Result,成功时返回本次实际审核通过的记录数量,失败时返回具体错误原因
|
||||||
|
*/
|
||||||
|
Result batchReviewApply(String[] reimburseIds);
|
||||||
}
|
}
|
||||||
|
|||||||
+307
-17
@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
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.result.Result;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.sys.models.Sys_file;
|
import com.budwk.app.sys.models.Sys_file;
|
||||||
@@ -122,7 +123,10 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
normalizeInvoiceDetails(unionReimburse);
|
normalizeInvoiceDetails(unionReimburse);
|
||||||
if (needInvoiceDetails(unionReimburse)) {
|
if (needInvoiceDetails(unionReimburse)) {
|
||||||
fillInvoiceSummary(unionReimburse);
|
fillInvoiceSummary(unionReimburse);
|
||||||
|
} else {
|
||||||
|
fillCondolenceInvoiceSummary(unionReimburse);
|
||||||
}
|
}
|
||||||
|
fillDefaultRealMoney(unionReimburse);
|
||||||
if (stateId == 2) {
|
if (stateId == 2) {
|
||||||
Result validateResult = validateBeforeSubmit(unionReimburse);
|
Result validateResult = validateBeforeSubmit(unionReimburse);
|
||||||
if (validateResult != null) {
|
if (validateResult != null) {
|
||||||
@@ -139,23 +143,29 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (oldRecord == null) {
|
if (oldRecord == null) {
|
||||||
unionReimburse.setCreateTime(DateUtil.date());
|
unionReimburse.setCreateTime(toSecondPrecision(DateUtil.date()));
|
||||||
unionReimburse.setDocumentNo(generateDocumentNo());
|
unionReimburse.setDocumentNo(generateDocumentNo());
|
||||||
} else {
|
} else {
|
||||||
unionReimburse.setCreateTime(oldRecord.getCreateTime());
|
unionReimburse.setCreateTime(toSecondPrecision(oldRecord.getCreateTime()));
|
||||||
unionReimburse.setDocumentNo(oldRecord.getDocumentNo());
|
unionReimburse.setDocumentNo(oldRecord.getDocumentNo());
|
||||||
}
|
}
|
||||||
unionReimburse.setStateId(stateId);
|
unionReimburse.setStateId(stateId);
|
||||||
if ("UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())) {
|
fillDefaultRealMoney(unionReimburse);
|
||||||
unionReimburse.setRealMoney(unionReimburse.getCondolenceMoney());
|
|
||||||
} else {
|
|
||||||
unionReimburse.setRealMoney(unionReimburse.getMoney());
|
|
||||||
}
|
|
||||||
this.dao().insertOrUpdate(unionReimburse);
|
this.dao().insertOrUpdate(unionReimburse);
|
||||||
saveInvoiceDetails(unionReimburse.getId(), unionReimburse.getInvoiceDetails());
|
saveInvoiceDetails(unionReimburse.getId(), unionReimburse.getInvoiceDetails());
|
||||||
return Result.success(stateId == 2 ? "提交成功" : "保存成功");
|
return Result.success(stateId == 2 ? "提交成功" : "保存成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请时间统一保存到秒,避免数据库和页面出现毫秒级时间。
|
||||||
|
*/
|
||||||
|
private Date toSecondPrecision(Date date) {
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Date((date.getTime() / 1000) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnionReimburse getApplyForm(String id) {
|
public UnionReimburse getApplyForm(String id) {
|
||||||
UnionReimburse unionReimburse = this.fetch(id);
|
UnionReimburse unionReimburse = this.fetch(id);
|
||||||
@@ -170,6 +180,16 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
return unionReimburse;
|
return unionReimburse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteApply(String id) {
|
||||||
|
if (StrUtil.isBlank(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 删除申请主记录时同步清理发票明细,避免遗留无归属的发票关联数据。
|
||||||
|
this.dao().clear(UnionReimburseInvoiceDetail.class, Cnd.where("reimburseId", "=", id));
|
||||||
|
this.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer) {
|
public List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer) {
|
||||||
if (StrUtil.isBlank(payer)) {
|
if (StrUtil.isBlank(payer)) {
|
||||||
@@ -199,6 +219,55 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
return this.listVO(sql, UnionReimburseBankHistoryVO.class);
|
return this.listVO(sql, UnionReimburseBankHistoryVO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 付款人查询要跟随经费来源;选择协会经费时,只允许从当前协会会员中选择付款人。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<NutMap> listPayerUser(String keyword, String reimburseFundSource, String clubId) {
|
||||||
|
boolean clubFundSource = "UNION_REIMBURSE_FUND_SOURCE_3".equals(reimburseFundSource);
|
||||||
|
if (clubFundSource && StrUtil.isBlank(clubId)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
String clubJoinSql = clubFundSource ? "INNER JOIN club_user cu ON cu.userId = u.id" : "";
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
u.id,
|
||||||
|
u.username AS userName,
|
||||||
|
u.loginname AS loginName,
|
||||||
|
u.sex,
|
||||||
|
u.mobile,
|
||||||
|
u.technicalTitle,
|
||||||
|
IFNULL(u.unitname, '暂无') AS unitName,
|
||||||
|
u.unitid AS unitId,
|
||||||
|
u.unionid AS unionId,
|
||||||
|
u.unionname AS unionName,
|
||||||
|
DATE(u.birthday) AS birthday,
|
||||||
|
u.idCard,
|
||||||
|
u.unionCode
|
||||||
|
FROM
|
||||||
|
vw_user u
|
||||||
|
%s
|
||||||
|
$condition
|
||||||
|
""".formatted(clubJoinSql));
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (StrUtil.isNotBlank(keyword)) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or("u.loginname", "like", "%" + keyword + "%");
|
||||||
|
seg.or("u.username", "like", "%" + keyword + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.and("u.id", "!=", SecurityUtil.getUserId());
|
||||||
|
if (clubFundSource) {
|
||||||
|
cnd.and("cu.clubId", "=", clubId);
|
||||||
|
} else if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||||
|
cnd.and("u.unionid", "=", SecurityUtil.getUnionId());
|
||||||
|
}
|
||||||
|
cnd.groupBy("u.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination pagination = this.listPageMap(1, 50, sql);
|
||||||
|
return pagination.getList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result checkInvoiceDuplicate(String invoiceNo, String reimburseId) {
|
public Result checkInvoiceDuplicate(String invoiceNo, String reimburseId) {
|
||||||
String currentInvoiceNo = StrUtil.blankToDefault(StrUtil.trim(invoiceNo), "");
|
String currentInvoiceNo = StrUtil.blankToDefault(StrUtil.trim(invoiceNo), "");
|
||||||
@@ -244,7 +313,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
* 按经费来源统一查询当前可用余额,未分配或权限不匹配时直接拦截。
|
* 按经费来源统一查询当前可用余额,未分配或权限不匹配时直接拦截。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
public Result getBudgetBalance(String reimburseFundSource, String clubId, String unionId) {
|
||||||
if (StrUtil.isBlank(reimburseFundSource)) {
|
if (StrUtil.isBlank(reimburseFundSource)) {
|
||||||
return Result.error("请选择经费来源");
|
return Result.error("请选择经费来源");
|
||||||
}
|
}
|
||||||
@@ -257,8 +326,9 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
return Result.success(formatMoney(outlayManageSchool.getTotalQuota().subtract(outlayManageSchool.getUsedQuota())));
|
return Result.success(formatMoney(outlayManageSchool.getTotalQuota().subtract(outlayManageSchool.getUsedQuota())));
|
||||||
}
|
}
|
||||||
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
||||||
|
String queryUnionId = StrUtil.blankToDefault(unionId, SecurityUtil.getUnionId());
|
||||||
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
||||||
Cnd.where("unionId", "=", SecurityUtil.getUnionId()).and("year", "=", DateUtil.thisYear()));
|
Cnd.where("unionId", "=", queryUnionId).and("year", "=", DateUtil.thisYear()));
|
||||||
if (outlayManageUnion == null) {
|
if (outlayManageUnion == null) {
|
||||||
return Result.error("分工会经费未分配");
|
return Result.error("分工会经费未分配");
|
||||||
}
|
}
|
||||||
@@ -315,6 +385,58 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量审核前只查询前端勾选且仍处于待审核确认状态的数据,避免误处理未勾选或状态已变化的申请。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Result batchReviewApply(String[] reimburseIds) {
|
||||||
|
if (reimburseIds == null || reimburseIds.length == 0) {
|
||||||
|
return Result.error("请选择需要审核的报销申请");
|
||||||
|
}
|
||||||
|
List<UnionReimburse> reimbursements = this.query(Cnd.where("id", "in", reimburseIds).and("stateId", "=", 2));
|
||||||
|
if (reimbursements.isEmpty()) {
|
||||||
|
return Result.error("所选记录中没有待审核的数据");
|
||||||
|
}
|
||||||
|
for (UnionReimburse reimbursement : reimbursements) {
|
||||||
|
Result result = this.reviewApply(reimbursement.getId(), "通过", 3);
|
||||||
|
if (result.getCode() != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result.success("一键审核完成,共处理" + reimbursements.size() + "条记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员修改实际金额时,报销成功的数据已经写入预算台账,需要按差额同步已使用额度和使用明细。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Result updateActuallyAmount(String id, Double realMoney) {
|
||||||
|
if (StrUtil.isBlank(id)) {
|
||||||
|
return Result.error("报销记录ID不能为空");
|
||||||
|
}
|
||||||
|
BigDecimal newMoney = normalizeActualMoney(realMoney);
|
||||||
|
if (newMoney == null || newMoney.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return Result.error("实际报销金额必须大于0");
|
||||||
|
}
|
||||||
|
UnionReimburse dbRecord = this.fetch(id);
|
||||||
|
if (dbRecord == null) {
|
||||||
|
return Result.error("未找到对应的报销记录");
|
||||||
|
}
|
||||||
|
if (Integer.valueOf(3).equals(dbRecord.getStateId())) {
|
||||||
|
OutlayUseDetail oldDetail = dao().fetch(OutlayUseDetail.class, Cnd.where("outlayReimburseId", "=", dbRecord.getId()));
|
||||||
|
BigDecimal oldMoney = oldDetail != null && oldDetail.getAdjustMoney() != null
|
||||||
|
? oldDetail.getAdjustMoney()
|
||||||
|
: getApplyMoney(dbRecord);
|
||||||
|
Result syncResult = syncApprovedActualAmount(dbRecord, oldDetail, oldMoney, newMoney);
|
||||||
|
if (syncResult != null && syncResult.getCode() != 0) {
|
||||||
|
return syncResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbRecord.setRealMoney(newMoney.doubleValue());
|
||||||
|
this.updateIgnoreNull(dbRecord);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
private void normalizeInvoiceDetails(UnionReimburse unionReimburse) {
|
private void normalizeInvoiceDetails(UnionReimburse unionReimburse) {
|
||||||
if (unionReimburse.getInvoiceDetails() == null) {
|
if (unionReimburse.getInvoiceDetails() == null) {
|
||||||
unionReimburse.setInvoiceDetails(new ArrayList<>());
|
unionReimburse.setInvoiceDetails(new ArrayList<>());
|
||||||
@@ -360,6 +482,36 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
unionReimburse.setInvoiceNumber(String.valueOf(invoiceFileCount));
|
unionReimburse.setInvoiceNumber(String.valueOf(invoiceFileCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 慰问类报销允许不填发票;有发票时按发票汇总金额申请,没有发票时按慰问金额申请。
|
||||||
|
*/
|
||||||
|
private void fillCondolenceInvoiceSummary(UnionReimburse unionReimburse) {
|
||||||
|
double totalMoney = 0D;
|
||||||
|
int invoiceFileCount = 0;
|
||||||
|
for (UnionReimburseInvoiceDetail detail : unionReimburse.getInvoiceDetails()) {
|
||||||
|
if (detail.getInvoiceAmount() != null) {
|
||||||
|
totalMoney = BigDecimal.valueOf(totalMoney)
|
||||||
|
.add(BigDecimal.valueOf(detail.getInvoiceAmount()))
|
||||||
|
.doubleValue();
|
||||||
|
}
|
||||||
|
if (Lang.isNotEmpty(detail.getInvoiceFiles())) {
|
||||||
|
invoiceFileCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Double applyMoney = invoiceFileCount > 0
|
||||||
|
? BigDecimal.valueOf(totalMoney).setScale(2, RoundingMode.HALF_UP).doubleValue()
|
||||||
|
: unionReimburse.getCondolenceMoney();
|
||||||
|
unionReimburse.setMoney(applyMoney);
|
||||||
|
unionReimburse.setInvoiceNumber(String.valueOf(invoiceFileCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认实际金额跟随申请金额,后续管理员可在汇总页按最终报销金额调整。
|
||||||
|
*/
|
||||||
|
private void fillDefaultRealMoney(UnionReimburse unionReimburse) {
|
||||||
|
unionReimburse.setRealMoney(getDeclaredApplyMoney(unionReimburse).doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交前补一层后端校验,防止前端绕过校验直接提交。
|
* 提交前补一层后端校验,防止前端绕过校验直接提交。
|
||||||
*/
|
*/
|
||||||
@@ -379,11 +531,8 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
// if (StrUtil.isBlank(unionReimburse.getBankOfDeposit())) {
|
// if (StrUtil.isBlank(unionReimburse.getBankOfDeposit())) {
|
||||||
// return Result.error("请填写开户行");
|
// return Result.error("请填写开户行");
|
||||||
// }
|
// }
|
||||||
if (StrUtil.isBlank(unionReimburse.getPaymentNotes())) {
|
|
||||||
return Result.error("请填写支付内容");
|
|
||||||
}
|
|
||||||
if (!needInvoiceDetails(unionReimburse)) {
|
if (!needInvoiceDetails(unionReimburse)) {
|
||||||
return null;
|
return validateInvoiceDetails(unionReimburse, false);
|
||||||
}
|
}
|
||||||
if (StrUtil.isBlank(unionReimburse.getActivityName())) {
|
if (StrUtil.isBlank(unionReimburse.getActivityName())) {
|
||||||
return Result.error("请填写活动名称");
|
return Result.error("请填写活动名称");
|
||||||
@@ -397,7 +546,17 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
if (Lang.isEmpty(unionReimburse.getFiles())) {
|
if (Lang.isEmpty(unionReimburse.getFiles())) {
|
||||||
return Result.error("请上传附件");
|
return Result.error("请上传附件");
|
||||||
}
|
}
|
||||||
|
return validateInvoiceDetails(unionReimburse, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发票明细提交校验:活动类必须至少一条,慰问类允许为空但填写后必须完整。
|
||||||
|
*/
|
||||||
|
private Result validateInvoiceDetails(UnionReimburse unionReimburse, boolean required) {
|
||||||
if (Lang.isEmpty(unionReimburse.getInvoiceDetails())) {
|
if (Lang.isEmpty(unionReimburse.getInvoiceDetails())) {
|
||||||
|
if (!required) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return Result.error("请至少维护一条发票明细");
|
return Result.error("请至少维护一条发票明细");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < unionReimburse.getInvoiceDetails().size(); i++) {
|
for (int i = 0; i < unionReimburse.getInvoiceDetails().size(); i++) {
|
||||||
@@ -426,7 +585,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
* 提交和审核前统一校验预算是否已分配、余额是否充足。
|
* 提交和审核前统一校验预算是否已分配、余额是否充足。
|
||||||
*/
|
*/
|
||||||
private Result validateFundSourceBeforeSubmit(UnionReimburse unionReimburse) {
|
private Result validateFundSourceBeforeSubmit(UnionReimburse unionReimburse) {
|
||||||
Result balanceResult = getBudgetBalance(unionReimburse.getReimburseFundSource(), unionReimburse.getClubId());
|
Result balanceResult = getBudgetBalance(unionReimburse.getReimburseFundSource(), unionReimburse.getClubId(), unionReimburse.getUnionId());
|
||||||
if (balanceResult == null || balanceResult.getCode() != 0) {
|
if (balanceResult == null || balanceResult.getCode() != 0) {
|
||||||
return balanceResult == null ? Result.error("经费余额校验失败") : balanceResult;
|
return balanceResult == null ? Result.error("经费余额校验失败") : balanceResult;
|
||||||
}
|
}
|
||||||
@@ -493,6 +652,117 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
return Result.error("不支持的经费来源");
|
return Result.error("不支持的经费来源");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已通过报销单修改实际金额时,用差额同步预算主表和使用明细,避免重复全量扣减。
|
||||||
|
*/
|
||||||
|
private Result syncApprovedActualAmount(UnionReimburse unionReimburse, OutlayUseDetail oldDetail,
|
||||||
|
BigDecimal oldMoney, BigDecimal newMoney) {
|
||||||
|
BigDecimal diffMoney = newMoney.subtract(safeMoney(oldMoney)).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
String reimburseFundSource = unionReimburse.getReimburseFundSource();
|
||||||
|
if ("UNION_REIMBURSE_FUND_SOURCE_1".equals(reimburseFundSource)) {
|
||||||
|
OutlayManageSchool outlayManageSchool = dao().fetch(OutlayManageSchool.class,
|
||||||
|
Cnd.where("year", "=", DateUtil.thisYear()));
|
||||||
|
if (outlayManageSchool == null) {
|
||||||
|
return Result.error("校工会经费未分配");
|
||||||
|
}
|
||||||
|
Result quotaResult = updateSchoolUsedQuota(outlayManageSchool, diffMoney);
|
||||||
|
if (quotaResult.getCode() != 0) {
|
||||||
|
return quotaResult;
|
||||||
|
}
|
||||||
|
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageSchool.getId(), newMoney);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
||||||
|
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
||||||
|
Cnd.where("unionId", "=", unionReimburse.getUnionId()).and("year", "=", DateUtil.thisYear()));
|
||||||
|
if (outlayManageUnion == null) {
|
||||||
|
return Result.error("分工会经费未分配");
|
||||||
|
}
|
||||||
|
Result quotaResult = updateUnionUsedQuota(outlayManageUnion, diffMoney);
|
||||||
|
if (quotaResult.getCode() != 0) {
|
||||||
|
return quotaResult;
|
||||||
|
}
|
||||||
|
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageUnion.getId(), newMoney);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
if ("UNION_REIMBURSE_FUND_SOURCE_3".equals(reimburseFundSource)) {
|
||||||
|
OutlayManageClub outlayManageClub = dao().fetch(OutlayManageClub.class,
|
||||||
|
Cnd.where("clubId", "=", unionReimburse.getClubId()).and("year", "=", DateUtil.thisYear()));
|
||||||
|
if (outlayManageClub == null) {
|
||||||
|
return Result.error("该协会本年度未生成预算记录,请先在协会预算分配中补分配");
|
||||||
|
}
|
||||||
|
Result quotaResult = updateClubUsedQuota(outlayManageClub, diffMoney);
|
||||||
|
if (quotaResult.getCode() != 0) {
|
||||||
|
return quotaResult;
|
||||||
|
}
|
||||||
|
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageClub.getId(), newMoney);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
return Result.error("不支持的经费来源");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result updateSchoolUsedQuota(OutlayManageSchool outlayManageSchool, BigDecimal diffMoney) {
|
||||||
|
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageSchool.getTotalQuota(), outlayManageSchool.getUsedQuota(), diffMoney, "校工会经费");
|
||||||
|
if (newUsedQuota == null) {
|
||||||
|
return Result.error("校工会经费余额不足");
|
||||||
|
}
|
||||||
|
outlayManageSchool.setUsedQuota(newUsedQuota);
|
||||||
|
dao().updateIgnoreNull(outlayManageSchool);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result updateUnionUsedQuota(OutlayManageUnion outlayManageUnion, BigDecimal diffMoney) {
|
||||||
|
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageUnion.getTotalQuota(), outlayManageUnion.getUsedQuota(), diffMoney, "分工会经费");
|
||||||
|
if (newUsedQuota == null) {
|
||||||
|
return Result.error("分工会经费余额不足");
|
||||||
|
}
|
||||||
|
outlayManageUnion.setUsedQuota(newUsedQuota);
|
||||||
|
dao().updateIgnoreNull(outlayManageUnion);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result updateClubUsedQuota(OutlayManageClub outlayManageClub, BigDecimal diffMoney) {
|
||||||
|
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageClub.getTotalQuota(), outlayManageClub.getUsedQuota(), diffMoney, "协会经费");
|
||||||
|
if (newUsedQuota == null) {
|
||||||
|
return Result.error("协会经费余额不足");
|
||||||
|
}
|
||||||
|
outlayManageClub.setUsedQuota(newUsedQuota);
|
||||||
|
dao().updateIgnoreNull(outlayManageClub);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算调整后的已使用额度,调增时不能超过总额度,调减时不能小于0。
|
||||||
|
*/
|
||||||
|
private BigDecimal buildNewUsedQuota(BigDecimal totalQuota, BigDecimal usedQuota, BigDecimal diffMoney, String outlayName) {
|
||||||
|
BigDecimal safeTotalQuota = safeMoney(totalQuota);
|
||||||
|
BigDecimal safeUsedQuota = safeMoney(usedQuota);
|
||||||
|
BigDecimal safeDiffMoney = safeMoney(diffMoney);
|
||||||
|
BigDecimal newUsedQuota = safeUsedQuota.add(safeDiffMoney).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
if (safeDiffMoney.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
return newUsedQuota;
|
||||||
|
}
|
||||||
|
if (newUsedQuota.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (newUsedQuota.compareTo(safeTotalQuota) > 0) {
|
||||||
|
log.warn("{}实际金额调增后超出预算,总额度:{}, 已使用:{}, 调整差额:{}", outlayName, safeTotalQuota, safeUsedQuota, diffMoney);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return newUsedQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveOrUpdateUseDetail(UnionReimburse unionReimburse, OutlayUseDetail oldDetail,
|
||||||
|
String outlayManageId, BigDecimal newMoney) {
|
||||||
|
if (oldDetail == null) {
|
||||||
|
insertUseDetail(unionReimburse, outlayManageId, newMoney);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
oldDetail.setOutlayManageId(outlayManageId);
|
||||||
|
oldDetail.setAdjustMoney(newMoney);
|
||||||
|
dao().updateIgnoreNull(oldDetail);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一张报销单只写入一条预算使用详情,避免重复通过或重复点击造成重复明细。
|
* 一张报销单只写入一条预算使用详情,避免重复通过或重复点击造成重复明细。
|
||||||
*/
|
*/
|
||||||
@@ -516,11 +786,31 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal getApplyMoney(UnionReimburse unionReimburse) {
|
private BigDecimal getApplyMoney(UnionReimburse unionReimburse) {
|
||||||
Double money = "UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())
|
if (unionReimburse.getRealMoney() != null) {
|
||||||
? unionReimburse.getCondolenceMoney() : unionReimburse.getMoney();
|
return BigDecimal.valueOf(unionReimburse.getRealMoney()).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
return getDeclaredApplyMoney(unionReimburse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getDeclaredApplyMoney(UnionReimburse unionReimburse) {
|
||||||
|
Double money = unionReimburse.getMoney();
|
||||||
|
if (money == null && "UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())) {
|
||||||
|
money = unionReimburse.getCondolenceMoney();
|
||||||
|
}
|
||||||
return BigDecimal.valueOf(money == null ? 0D : money).setScale(2, RoundingMode.HALF_UP);
|
return BigDecimal.valueOf(money == null ? 0D : money).setScale(2, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigDecimal normalizeActualMoney(Double realMoney) {
|
||||||
|
if (realMoney == null || realMoney.isNaN() || realMoney.isInfinite()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return realMoney == null ? null : BigDecimal.valueOf(realMoney).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal safeMoney(BigDecimal money) {
|
||||||
|
return money == null ? BigDecimal.ZERO : money.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
private String buildUseDetailProjectName(UnionReimburse unionReimburse) {
|
private String buildUseDetailProjectName(UnionReimburse unionReimburse) {
|
||||||
if (StrUtil.isNotBlank(unionReimburse.getActivityName())) {
|
if (StrUtil.isNotBlank(unionReimburse.getActivityName())) {
|
||||||
return unionReimburse.getActivityName();
|
return unionReimburse.getActivityName();
|
||||||
@@ -851,7 +1141,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前仅活动类报销维护发票明细,慰问类仍按原有逻辑处理金额。
|
* 非慰问类报销必须维护发票明细,慰问类发票明细为可选。
|
||||||
*/
|
*/
|
||||||
private boolean needInvoiceDetails(UnionReimburse unionReimburse) {
|
private boolean needInvoiceDetails(UnionReimburse unionReimburse) {
|
||||||
return unionReimburse != null && !"UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject());
|
return unionReimburse != null && !"UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject());
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ public class ProposalDashboardController {
|
|||||||
nodes.add(NutMap.NEW().addv("name", "提案总数").addv("id", "total").addv("type", "total").addv("count", 0));
|
nodes.add(NutMap.NEW().addv("name", "提案总数").addv("id", "total").addv("type", "total").addv("count", 0));
|
||||||
|
|
||||||
// 节点
|
// 节点
|
||||||
ProcessDefine define = processDefineService.getLastByName("JDHTA");
|
ProcessDefine define = processDefineService.getLastByName("JDHTA_NC");
|
||||||
ProcessModel processModel = processDefineService.processDefineToModel(define);
|
ProcessModel processModel = processDefineService.processDefineToModel(define);
|
||||||
List<TaskModel> taskModels = processModel.getTasks();
|
List<TaskModel> taskModels = processModel.getTasks();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -141,7 +141,7 @@ public class ProposalQueryChartController {
|
|||||||
FROM
|
FROM
|
||||||
wf_process_design
|
wf_process_design
|
||||||
WHERE
|
WHERE
|
||||||
NAME = 'JDHTA'
|
NAME = 'JDHTA_NC'
|
||||||
""");
|
""");
|
||||||
sql.setCallback(Sqls.callback.map());
|
sql.setCallback(Sqls.callback.map());
|
||||||
dao.execute(sql);
|
dao.execute(sql);
|
||||||
|
|||||||
+1
@@ -120,6 +120,7 @@ public class ProposalSecondedController {
|
|||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
|
|
||||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||||
|
cnd.and("info.createUserId", "!=", SecurityUtil.getUserId());
|
||||||
|
|
||||||
if (approval) {
|
if (approval) {
|
||||||
// 已附议页签只展示当前登录附议人已经处理过的记录。
|
// 已附议页签只展示当前登录附议人已经处理过的记录。
|
||||||
|
|||||||
+1
-1
@@ -179,7 +179,7 @@ public class TeacherCongressDelegatePushController {
|
|||||||
""");
|
""");
|
||||||
sql.setParam("sessionId", sessionId);
|
sql.setParam("sessionId", sessionId);
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
// cnd.and("u.member", "=", 1);
|
cnd.and("u.member", "=", 1);
|
||||||
cnd.and("u.username", "is not", null);
|
cnd.and("u.username", "is not", null);
|
||||||
cnd.andEX("u.id", "not in", userIds);
|
cnd.andEX("u.id", "not in", userIds);
|
||||||
cnd.and("tcd.userId", "is", null);
|
cnd.and("tcd.userId", "is", null);
|
||||||
|
|||||||
+9
@@ -12,6 +12,8 @@ import com.budwk.app.bpm.service.BpmService;
|
|||||||
import com.budwk.app.flow.engine.FlowEngine;
|
import com.budwk.app.flow.engine.FlowEngine;
|
||||||
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.staffmanage.member.constant.MemberChangeOrigin;
|
||||||
|
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||||
import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord;
|
import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord;
|
||||||
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm;
|
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm;
|
||||||
import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService;
|
import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService;
|
||||||
@@ -22,6 +24,7 @@ import org.nutz.dao.Cnd;
|
|||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.dao.util.cri.Static;
|
||||||
import org.nutz.ioc.aop.Aop;
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
@@ -111,6 +114,12 @@ public class MemberChangeMineController {
|
|||||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Filter manual input records created by member info input
|
||||||
|
cnd.and(new Static(
|
||||||
|
"(info.changeOrigin <> '" + MemberChangeOrigin.HAND_MOVEMENT.name()
|
||||||
|
+ "' OR info.changeOrigin IS NULL OR info.changeType <> '" + MemberChangeType.NEW.name()
|
||||||
|
+ "' OR info.changeType IS NULL)"
|
||||||
|
));
|
||||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
cnd.desc("info.applyDateTime");
|
cnd.desc("info.applyDateTime");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+37
@@ -46,6 +46,8 @@ import org.nutz.lang.Lang;
|
|||||||
import org.nutz.lang.random.R;
|
import org.nutz.lang.random.R;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -298,6 +300,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) {
|
public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) {
|
||||||
|
normalizeArrivalAtSchoolDate(record);
|
||||||
List<NutMap> changeList = getChangeInfos(record);
|
List<NutMap> changeList = getChangeInfos(record);
|
||||||
|
|
||||||
// 如果有工会关系人员,这个user用来存储数据
|
// 如果有工会关系人员,这个user用来存储数据
|
||||||
@@ -503,6 +506,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateChangeAndSetBasicData(MemberChangeRecord record, MemberChangeOrigin origin) {
|
public void validateChangeAndSetBasicData(MemberChangeRecord record, MemberChangeOrigin origin) {
|
||||||
|
normalizeArrivalAtSchoolDate(record);
|
||||||
// 校验有没有发生变更
|
// 校验有没有发生变更
|
||||||
List<NutMap> changeInfos = getChangeInfos(record);
|
List<NutMap> changeInfos = getChangeInfos(record);
|
||||||
if (Lang.isEmpty(changeInfos)) {
|
if (Lang.isEmpty(changeInfos)) {
|
||||||
@@ -521,6 +525,39 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一规范变更记录中的到校日期,避免 Date 对象复制后以英文字符串形式参与比较或直接落库。
|
||||||
|
*/
|
||||||
|
private void normalizeArrivalAtSchoolDate(MemberChangeRecord record) {
|
||||||
|
if (record == null || StrUtil.isBlank(record.getArrivalAtSchoolDate())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String arrivalAtSchoolDate = StrUtil.trim(record.getArrivalAtSchoolDate());
|
||||||
|
try {
|
||||||
|
Date parsedDate = parseArrivalAtSchoolDate(arrivalAtSchoolDate);
|
||||||
|
record.setArrivalAtSchoolDate(DateUtil.format(parsedDate, "yyyy-MM-dd"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BaseException("到校日期格式不正确,请使用yyyy-MM-dd格式");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兼容页面手工变更时从视图对象复制出的英文日期字符串。
|
||||||
|
*/
|
||||||
|
private Date parseArrivalAtSchoolDate(String arrivalAtSchoolDate) throws ParseException {
|
||||||
|
if (arrivalAtSchoolDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
|
||||||
|
return DateUtil.parseDate(arrivalAtSchoolDate);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return DateUtil.parse(arrivalAtSchoolDate);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
|
||||||
|
format.setLenient(false);
|
||||||
|
return format.parse(arrivalAtSchoolDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证申请或变更是否正在进行
|
* 验证申请或变更是否正在进行
|
||||||
* @param userId 用户id
|
* @param userId 用户id
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ public class WelfareProject extends BaseModel implements SysHomeConvert {
|
|||||||
sysHomeActivity.setH5Url("/platform/h5/welfare/userSelect/index?id=" + this.getId());
|
sysHomeActivity.setH5Url("/platform/h5/welfare/userSelect/index?id=" + this.getId());
|
||||||
sysHomeActivity.setStartDate(this.getChoiceTimeStart());
|
sysHomeActivity.setStartDate(this.getChoiceTimeStart());
|
||||||
sysHomeActivity.setEndDate(this.getChoiceTimeEnd());
|
sysHomeActivity.setEndDate(this.getChoiceTimeEnd());
|
||||||
sysHomeActivity.setAllowUserSql("select userId from welfare_list where projectId = '" + this.getId() + "' and userId = @userId");
|
sysHomeActivity.setAllowUserSql("select userId from welfare_list where projectId = (select id from welfare_project where id='" + this.getId() + "' and provideMode!=1) and userId = @userId ");
|
||||||
sysHomeActivity.setEnable(true);
|
sysHomeActivity.setEnable(true);
|
||||||
sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName());
|
sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName());
|
||||||
return sysHomeActivity;
|
return sysHomeActivity;
|
||||||
|
|||||||
@@ -48,6 +48,18 @@ const businessTool = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
listManageClubByRole() {
|
||||||
|
return commonUtil
|
||||||
|
.axiosService()
|
||||||
|
.post("/platform/club/common/listManageClubByRole", {})
|
||||||
|
.then((resp) => {
|
||||||
|
if (resp.code === 0) {
|
||||||
|
return resp.data
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 获取字典数据,不包含禁用
|
* 获取字典数据,不包含禁用
|
||||||
* @param code
|
* @param code
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
placeholder="输入工号或者姓名查询"
|
placeholder="输入工号或者姓名查询"
|
||||||
:remote-method="queryUser"
|
:remote-method="queryUser"
|
||||||
@change="doSearch"
|
@change="doSearch"
|
||||||
|
@clear="doSearch"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@@ -150,7 +151,7 @@
|
|||||||
<el-col class="query-content">
|
<el-col class="query-content">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="pageForm.unionIds"
|
v-model="pageForm.unionIds"
|
||||||
:clearable="is_A06 || is_sysadmin"
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
filterable
|
filterable
|
||||||
multiple
|
multiple
|
||||||
@@ -183,6 +184,7 @@
|
|||||||
placeholder="请选择角色"
|
placeholder="请选择角色"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="doSearch"
|
@change="doSearch"
|
||||||
|
@clear="doSearch"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in roleList"
|
v-for="item in roleList"
|
||||||
@@ -199,6 +201,7 @@
|
|||||||
placeholder="请选择教代会"
|
placeholder="请选择教代会"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="doSearch"
|
@change="doSearch"
|
||||||
|
@clear="doSearch"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in sessionOptions"
|
v-for="item in sessionOptions"
|
||||||
@@ -213,16 +216,17 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-row class="query-row" v-if="is_A06 || is_sysadmin || is_H02">
|
<el-row class="query-row" v-if="is_A06 || is_sysadmin || is_H02 || is_CLUB_PRESIDENT">
|
||||||
<el-col class="query-title">社团:</el-col>
|
<el-col class="query-title">社团:</el-col>
|
||||||
<el-col class="query-content">
|
<el-col class="query-content">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="pageForm.clubId"
|
v-model="pageForm.clubId"
|
||||||
:clearable="is_A06 || is_sysadmin || (is_H04 && is_H02)"
|
clearable
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择社团"
|
placeholder="请选择社团"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="doSearch"
|
@change="doSearch"
|
||||||
|
@clear="doSearch"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in clubOptions"
|
v-for="item in clubOptions"
|
||||||
@@ -243,6 +247,7 @@
|
|||||||
placeholder="请选择活动组别范围之外的人员"
|
placeholder="请选择活动组别范围之外的人员"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="handleActivityGroupChange"
|
@change="handleActivityGroupChange"
|
||||||
|
@clear="handleActivityGroupChange('')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in activityGroupList2"
|
v-for="item in activityGroupList2"
|
||||||
@@ -485,6 +490,9 @@ module.exports = {
|
|||||||
is_H02() {
|
is_H02() {
|
||||||
return this.roleData.is_H02
|
return this.roleData.is_H02
|
||||||
},
|
},
|
||||||
|
is_CLUB_PRESIDENT() {
|
||||||
|
return this.roleData.is_CLUB_PRESIDENT
|
||||||
|
},
|
||||||
is_sysadmin() {
|
is_sysadmin() {
|
||||||
return this.roleData.is_sysadmin
|
return this.roleData.is_sysadmin
|
||||||
},
|
},
|
||||||
@@ -509,7 +517,8 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
getInitialUnionIds() {
|
getInitialUnionIds() {
|
||||||
if ((this.is_sysadmin || this.is_A06 || this.is_H02) === false && this.is_H04 === true && this.unionid) {
|
// 分工会和社团双身份默认不带分工会筛选,保证初始列表走后端并集逻辑。
|
||||||
|
if ((this.is_sysadmin || this.is_A06 || this.is_H02 || this.is_CLUB_PRESIDENT) === false && this.is_H04 === true && this.unionid) {
|
||||||
return [this.unionid]
|
return [this.unionid]
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
@@ -711,14 +720,15 @@ module.exports = {
|
|||||||
async created() {
|
async created() {
|
||||||
this.listSession()
|
this.listSession()
|
||||||
await this.getRolesAndUnion()
|
await this.getRolesAndUnion()
|
||||||
this.clubOptions = await this.$businessTool.listClubByRole()
|
this.clubOptions = (this.is_sysadmin || this.is_A06)
|
||||||
|
? await this.$businessTool.listClubByRole()
|
||||||
|
: this.is_CLUB_PRESIDENT
|
||||||
|
? await this.$businessTool.listManageClubByRole()
|
||||||
|
: await this.$businessTool.listClubByRole()
|
||||||
this.unions = (this.is_sysadmin || this.is_A06 || this.is_H02)
|
this.unions = (this.is_sysadmin || this.is_A06 || this.is_H02)
|
||||||
? await this.$businessTool.listUnion()
|
? await this.$businessTool.listUnion()
|
||||||
: this.$businessTool.listUnion(this.unionid)
|
: this.$businessTool.listUnion(this.unionid)
|
||||||
this.pageForm.unionIds = this.getInitialUnionIds()
|
this.pageForm.unionIds = this.getInitialUnionIds()
|
||||||
if (!this.is_H04 && this.is_H02 && this.clubOptions.length > 0) {
|
|
||||||
this.$set(this.pageForm, "clubId", this.clubOptions[0].id)
|
|
||||||
}
|
|
||||||
await this.getActivityGroup()
|
await this.getActivityGroup()
|
||||||
this.personTypeOptions = await this.$businessTool.getDictOptions("USER_PERSON_TYPE")
|
this.personTypeOptions = await this.$businessTool.getDictOptions("USER_PERSON_TYPE")
|
||||||
this.userStateOptions = await this.$businessTool.getDictOptions("USER_STATE")
|
this.userStateOptions = await this.$businessTool.getDictOptions("USER_STATE")
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: "h5",
|
name: "h5-signature",
|
||||||
components: {
|
components: {
|
||||||
signature: httpVueLoader("/components/plugins/sysSignature/index.vue?v=" + new Date().getTime())
|
signature: httpVueLoader("/components/plugins/sysSignature/index.vue?v=" + new Date().getTime())
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ const user = {
|
|||||||
<el-table-column prop="sender" label="申请人" width="120">
|
<el-table-column prop="sender" label="申请人" width="120">
|
||||||
<template slot-scope="{row}">{{row.variable.initiatorName}}</template>
|
<template slot-scope="{row}">{{row.variable.initiatorName}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="taskName" label="当前流程节点" width="140" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column prop="date" label="发起日期" width="120">
|
<el-table-column prop="date" label="发起日期" width="120">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
{{$moment(row.createdAt).format('YYYY-MM-DD')}}
|
{{$moment(row.createdAt).format('YYYY-MM-DD')}}
|
||||||
|
|||||||
@@ -79,9 +79,19 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
</guava>
|
</guava>
|
||||||
<el-dialog :visible.sync="backDialogVisible" title="反馈附件" width="40%" top="2%">
|
<el-dialog :visible.sync="backDialogVisible" title="反馈附件" width="40%" top="2%">
|
||||||
<div style="width: 100%; text-align: center">
|
|
||||||
<file-preview :files="backFiles" complete_result></file-preview>
|
<el-dialog :visible.sync="backDialogVisible" title="反馈附件" width="40%" top="2%">
|
||||||
</div>
|
<el-form v-model="backFormData" ref="backFormRef" label-width="80px">
|
||||||
|
<el-form-item label="反馈附件" prop="files">
|
||||||
|
<div style="width: 100%; text-align: center">
|
||||||
|
<file-preview :files="backFiles" complete_result></file-preview>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="反馈内容" prop="backText">
|
||||||
|
<el-input v-model="backFormData.backText" type="textarea" :rows="4" max="500" readonly></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -108,7 +118,7 @@ layout("/layouts/platform.html"){
|
|||||||
readType: null
|
readType: null
|
||||||
},
|
},
|
||||||
unionList: [],
|
unionList: [],
|
||||||
unitList: []
|
unitList: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {},
|
components: {},
|
||||||
@@ -127,6 +137,9 @@ layout("/layouts/platform.html"){
|
|||||||
this.doSearch()
|
this.doSearch()
|
||||||
},
|
},
|
||||||
viewFiles(row) {
|
viewFiles(row) {
|
||||||
|
this.backFormData = {
|
||||||
|
...row
|
||||||
|
}
|
||||||
this.backFiles = row.backFiles
|
this.backFiles = row.backFiles
|
||||||
this.backDialogVisible = true
|
this.backDialogVisible = true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const UNIT_LEADER_MANAGE_TEMPLATE = {
|
|||||||
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
|
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
|
||||||
<el-form :model="formData" ref="form" size="small" label-width="60px">
|
<el-form :model="formData" ref="form" size="small" label-width="60px">
|
||||||
<el-form-item prop="roleCode" label="角色">
|
<el-form-item prop="roleCode" label="角色">
|
||||||
<dict-select placeholder="请选择角色" v-model="formData.roleCode" code="UNIT_ROLES"></dict-select>
|
<dict-select placeholder="请选择角色" v-model="formData.roleCode" code="UNIT_ROLES" @change="onRoleChange"></dict-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="userId" label="人员">
|
<el-form-item prop="userId" label="人员">
|
||||||
<user-select
|
<user-select
|
||||||
@@ -44,7 +44,7 @@ const UNIT_LEADER_MANAGE_TEMPLATE = {
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model="formData.userId"
|
v-model="formData.userId"
|
||||||
api="/platform/sys/unit/listUserSelect"
|
api="/platform/sys/unit/listUserSelect"
|
||||||
:api_params="{ unitId: currentData?.id }"
|
:api_params="{ unitId: currentData?.id, roleCode: formData.roleCode }"
|
||||||
:option_label_func="
|
:option_label_func="
|
||||||
(item) => {
|
(item) => {
|
||||||
return item.username + item.loginname + '(' + item.unitName + ')'
|
return item.username + item.loginname + '(' + item.unitName + ')'
|
||||||
@@ -86,6 +86,9 @@ const UNIT_LEADER_MANAGE_TEMPLATE = {
|
|||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
|
onRoleChange() {
|
||||||
|
this.$set(this.formData, "userId", "")
|
||||||
|
},
|
||||||
doDelete({ userId, roleCode }) {
|
doDelete({ userId, roleCode }) {
|
||||||
this.$confirm("您确定要删除吗?", "提示", {
|
this.$confirm("您确定要删除吗?", "提示", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
|
|||||||
@@ -85,6 +85,11 @@ const ACTIVITY_CULTURE_AUDIT_ACTIVITY = {
|
|||||||
<span v-else>-</span>
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template scope="{row}" v-else-if="column.prop=='tussueName'">
|
||||||
|
<span v-if="row.activity_type==40002">{{row.unionname?row.unionname:'暂无'}}</span>
|
||||||
|
<span v-if="row.activity_type==40003">{{row.clubName?row.clubName:'暂无'}}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column align="center" header-align="center" label="操作"
|
<el-table-column align="center" header-align="center" label="操作"
|
||||||
|
|||||||
@@ -23,12 +23,15 @@ const ACTIVITY_CULTURE_INFO_ACTIVITY = {
|
|||||||
<el-descriptions-item label="活动项目类型">
|
<el-descriptions-item label="活动项目类型">
|
||||||
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
|
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动类型" :span="2">
|
<el-descriptions-item label="活动类型" >
|
||||||
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ?
|
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ?
|
||||||
'分工会活动'
|
'分工会活动'
|
||||||
:
|
:
|
||||||
'社团/社团活动' }}
|
'社团/社团活动' }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="活动地点">
|
||||||
|
{{ viewData.address }}
|
||||||
|
</el-descriptions-item>
|
||||||
<!-- <el-descriptions-item label="活动计划时间">-->
|
<!-- <el-descriptions-item label="活动计划时间">-->
|
||||||
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
|
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
|
||||||
<!-- </el-descriptions-item>-->
|
<!-- </el-descriptions-item>-->
|
||||||
@@ -38,15 +41,13 @@ const ACTIVITY_CULTURE_INFO_ACTIVITY = {
|
|||||||
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
|
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
|
||||||
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
|
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动人数">
|
<!-- <el-descriptions-item label="活动人数">-->
|
||||||
{{ viewData.peopleNum || '暂无' }}
|
<!-- {{ viewData.peopleNum || '暂无' }}-->
|
||||||
</el-descriptions-item>
|
<!-- </el-descriptions-item>-->
|
||||||
<el-descriptions-item label="活动报名范围">
|
<el-descriptions-item label="活动报名范围">
|
||||||
{{ viewData.groupName || '暂无' }}
|
{{ viewData.groupName || '暂无' }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动地点">
|
|
||||||
{{ viewData.address }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="报名方式">
|
<el-descriptions-item label="报名方式">
|
||||||
<span v-if="viewData.signUpMethod===1">个人报名</span>
|
<span v-if="viewData.signUpMethod===1">个人报名</span>
|
||||||
<span v-else-if="viewData.signUpMethod===2">组队报名</span>
|
<span v-else-if="viewData.signUpMethod===2">组队报名</span>
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ const ACTIVITY_CULTURE_INFO_MANAGE = {
|
|||||||
<el-switch
|
<el-switch
|
||||||
@change="(val)=>{activityStatusChange(row.id,row.isUnseal)}"
|
@change="(val)=>{activityStatusChange(row.id,row.isUnseal)}"
|
||||||
active-color="#13ce66"
|
active-color="#13ce66"
|
||||||
|
:disabled="isUnsealDisabled(row)"
|
||||||
inactive-color="#ff4949"
|
inactive-color="#ff4949"
|
||||||
v-model="row.isUnseal">
|
v-model="row.isUnseal">
|
||||||
</el-switch>
|
</el-switch>
|
||||||
@@ -103,8 +104,7 @@ const ACTIVITY_CULTURE_INFO_MANAGE = {
|
|||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
||||||
<el-dropdown-item :command="{type:'edit',row}"
|
<el-dropdown-item :command="{type:'edit',row}"
|
||||||
v-if="row.taskKey === 'startTask' || !row.instanceId"
|
>
|
||||||
:disabled="row.projectTypeCode==50004">
|
|
||||||
编辑
|
编辑
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item u
|
<el-dropdown-item u
|
||||||
@@ -113,7 +113,7 @@ const ACTIVITY_CULTURE_INFO_MANAGE = {
|
|||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
||||||
<el-dropdown-item :command="{type:'delete',row}"
|
<el-dropdown-item :command="{type:'delete',row}"
|
||||||
v-if="row.taskKey === 'startTask' || !row.instanceId" >
|
v-if="(activity_type === 40001 && (row.taskKey === 'startTask' || !row.instanceId)) || (activity_type !== 40001 && $auth.hasRole('SYSADMIN'))" >
|
||||||
删除
|
删除
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item :command="{type:'openCode',row}">
|
<el-dropdown-item :command="{type:'openCode',row}">
|
||||||
@@ -195,6 +195,10 @@ const ACTIVITY_CULTURE_INFO_MANAGE = {
|
|||||||
this.$message.error(resp.msg)
|
this.$message.error(resp.msg)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
isUnsealDisabled(row) {
|
||||||
|
// 流程类活动只有在流程结束后才允许开启或关闭,非流程类活动保持原有开关逻辑。
|
||||||
|
return (row.activity_type === 40002 || row.activity_type === 40003) && row.instanceState !== 20
|
||||||
|
},
|
||||||
dropdownCommand(command) {
|
dropdownCommand(command) {
|
||||||
const {type, row} = command
|
const {type, row} = command
|
||||||
if (type === "view") {
|
if (type === "view") {
|
||||||
|
|||||||
@@ -17,14 +17,17 @@ const singleSignUp = {
|
|||||||
<el-descriptions-item label="活动编号">
|
<el-descriptions-item label="活动编号">
|
||||||
{{ viewData.activityCode }}
|
{{ viewData.activityCode }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动编号">
|
<el-descriptions-item label="活动项目类型">
|
||||||
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
|
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动类型" :span="2">
|
<el-descriptions-item label="活动类型">
|
||||||
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ? '分工会活动'
|
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ? '分工会活动'
|
||||||
:
|
:
|
||||||
'社团/社团活动' }}
|
'社团/社团活动' }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="活动地点">
|
||||||
|
{{ viewData.address }}
|
||||||
|
</el-descriptions-item>
|
||||||
<!-- <el-descriptions-item label="活动计划时间">-->
|
<!-- <el-descriptions-item label="活动计划时间">-->
|
||||||
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
|
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
|
||||||
<!-- </el-descriptions-item>-->
|
<!-- </el-descriptions-item>-->
|
||||||
@@ -34,12 +37,10 @@ const singleSignUp = {
|
|||||||
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
|
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
|
||||||
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
|
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="活动人数">
|
<!-- <el-descriptions-item label="活动人数">-->
|
||||||
{{ viewData.peopleNum || '暂无' }}
|
<!-- {{ viewData.peopleNum || '暂无' }}-->
|
||||||
</el-descriptions-item>
|
<!-- </el-descriptions-item>-->
|
||||||
<el-descriptions-item label="活动地点">
|
|
||||||
{{ viewData.address }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="报名方式">
|
<el-descriptions-item label="报名方式">
|
||||||
<span v-if="viewData.signUpMethod===1">个人报名</span>
|
<span v-if="viewData.signUpMethod===1">个人报名</span>
|
||||||
<span v-else-if="viewData.signUpMethod===2">组队报名</span>
|
<span v-else-if="viewData.signUpMethod===2">组队报名</span>
|
||||||
@@ -50,7 +51,7 @@ const singleSignUp = {
|
|||||||
<span v-if="viewData.isEnrollSystem">活动报名</span>
|
<span v-if="viewData.isEnrollSystem">活动报名</span>
|
||||||
<span v-else>活动管理</span>
|
<span v-else>活动管理</span>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="报名人数限制" span="3" v-if="viewData.signUpMethod!=null">
|
<el-descriptions-item label="报名人数限制" :span="2" v-if="viewData.signUpMethod!=null">
|
||||||
<span v-if="viewData.userNumberLimit===1">总人数限制({{
|
<span v-if="viewData.userNumberLimit===1">总人数限制({{
|
||||||
viewData.totalUserNumberLimit
|
viewData.totalUserNumberLimit
|
||||||
}}人)</span>
|
}}人)</span>
|
||||||
@@ -261,6 +262,16 @@ const singleSignUp = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 报名弹窗与查看弹窗统一使用同一套活动详情字段,避免展示口径不一致。
|
||||||
|
parseJsonField(value, defaultValue) {
|
||||||
|
if (value === null || value === undefined || value === "") {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return JSON.parse(value)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
},
|
||||||
onOpen(id) {
|
onOpen(id) {
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
this.id = id
|
this.id = id
|
||||||
@@ -506,12 +517,21 @@ const singleSignUp = {
|
|||||||
|
|
||||||
//活动信息
|
//活动信息
|
||||||
activityInfo() {
|
activityInfo() {
|
||||||
this.$axios.post("/platform/activity/culture/infoManage/activityInfo", {id: this.id}).then((res) => {
|
this.$axios.post("/platform/activity/culture/infoManage/findOne", {id: this.id}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.viewData = res.data
|
const data = res.data || {}
|
||||||
|
data.billFiles = this.parseJsonField(data.billFiles, [])
|
||||||
|
data.photoFiles = this.parseJsonField(data.photoFiles, [])
|
||||||
|
data.otherFiles = this.parseJsonField(data.otherFiles, [])
|
||||||
|
data.unionUserNumberLimit = this.parseJsonField(data.unionUserNumberLimit, [])
|
||||||
|
data.location = this.parseJsonField(data.location, [])
|
||||||
|
data.formConfig = this.parseJsonField(data.formConfig, null)
|
||||||
|
this.viewData = data
|
||||||
if (this.viewData.signUpMethod === 3) {
|
if (this.viewData.signUpMethod === 3) {
|
||||||
const union = this.viewData.unionUserNumberLimit.find(v => v.id === this.$store.state.user.union.id)
|
const union = this.viewData.unionUserNumberLimit.find(v => v.id === this.$store.state.user.union.id)
|
||||||
this.viewData.teamNum = union.limitNum
|
if (union) {
|
||||||
|
this.viewData.teamNum = union.limitNum
|
||||||
|
}
|
||||||
this.listTeamUserUnion()
|
this.listTeamUserUnion()
|
||||||
} else {
|
} else {
|
||||||
this.listTeamUser()
|
this.listTeamUser()
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card class="mt10" shadow="never">
|
<el-card class="mt10" shadow="never">
|
||||||
|
<table-tool label="分工会列表">
|
||||||
|
<template v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')">
|
||||||
|
<el-button @click="openImport" size="small" type="primary">导入报名人员</el-button>
|
||||||
|
<el-button @click="doExportByEnroll" size="small" type="primary">导出报名信息</el-button>
|
||||||
|
</template>
|
||||||
|
</table-tool>
|
||||||
<el-table :data="tableData" row-key="id" style="width: 100%">
|
<el-table :data="tableData" row-key="id" style="width: 100%">
|
||||||
<el-table-column type="expand">
|
<el-table-column type="expand">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
@@ -295,11 +301,20 @@ layout("/layouts/platform.html"){
|
|||||||
prop="num"></el-table-column>
|
prop="num"></el-table-column>
|
||||||
<el-table-column align="center" header-align="center" label="操作">
|
<el-table-column align="center" header-align="center" label="操作">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<el-button @click="doExportXlsx(row)" size="mini" type="primary">导出
|
<el-button v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')" @click="doExportXlsx(row)" size="mini" type="primary">导出
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<el-dialog title="导入报名人员" :visible.sync="importDialog" width="50%" :close-on-click-modal="false" :close-on-press-escape="false">
|
||||||
|
<file-import
|
||||||
|
ref="viewImport"
|
||||||
|
temp_url="/platform/activity/reading/downloadImportTemplate"
|
||||||
|
post_url="/platform/activity/reading/importUserActivitys"
|
||||||
|
:business_id="pageForm.id"
|
||||||
|
@flush="successImport"
|
||||||
|
></file-import>
|
||||||
|
</el-dialog>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
</guava>
|
</guava>
|
||||||
@@ -310,6 +325,9 @@ layout("/layouts/platform.html"){
|
|||||||
el: "#app",
|
el: "#app",
|
||||||
store,
|
store,
|
||||||
mixins: [initTableMixins],
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime())
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activityList: [],
|
activityList: [],
|
||||||
@@ -317,6 +335,7 @@ layout("/layouts/platform.html"){
|
|||||||
unions: [],
|
unions: [],
|
||||||
rootData: [],
|
rootData: [],
|
||||||
|
|
||||||
|
importDialog: false,
|
||||||
noneData: false,
|
noneData: false,
|
||||||
tabLoading: false,
|
tabLoading: false,
|
||||||
events: [],
|
events: [],
|
||||||
@@ -342,11 +361,40 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
doExportXlsx(row) {
|
doExportXlsx(row) {
|
||||||
this.$downLoad("/platform/activity/sports/info/mange/exportXlsx", {
|
this.$downLoad(loc() + "/doExportByEnroll", {
|
||||||
id: this.pageForm.id,
|
id: this.pageForm.id,
|
||||||
unionId: row.id
|
unionId: row.id
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
doExportByEnroll() {
|
||||||
|
if (!this.pageForm.id) {
|
||||||
|
this.notifyWarning("请先选择活动名称")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.pageForm.unionid) {
|
||||||
|
this.notifyWarning("请选择所属工会")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$downLoad(loc() + "/doExportByEnroll", {
|
||||||
|
id: this.pageForm.id,
|
||||||
|
unionId: this.pageForm.unionid
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openImport() {
|
||||||
|
if (!this.pageForm.id) {
|
||||||
|
this.notifyWarning("请先选择活动名称")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.importDialog = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.viewImport) {
|
||||||
|
this.$refs.viewImport.resetImportData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
successImport() {
|
||||||
|
this.pageData()
|
||||||
|
},
|
||||||
unionIdChange() {
|
unionIdChange() {
|
||||||
const tableData = clone(this.rootData)
|
const tableData = clone(this.rootData)
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
|
|||||||
@@ -126,11 +126,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-col class="pt5 pb5">
|
<el-col class="pt5 pb5">
|
||||||
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes" :key="worksType.id">
|
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes" :key="worksType.id">
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-col :span="4">
|
<el-col :span="2">
|
||||||
<span class="el-form-item__label" v-if="worksIndex === 0">作品类型</span>
|
<span class="el-form-item__label" v-if="worksIndex === 0">作品类型</span>
|
||||||
<span v-else> </span>
|
<span v-else> </span>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="20">
|
<el-col :span="22">
|
||||||
<el-input placeholder="请输入名称" v-model="worksType.worksTypeName"></el-input>
|
<el-input placeholder="请输入名称" v-model="worksType.worksTypeName"></el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
|
|
||||||
listActivity() {
|
listActivity() {
|
||||||
this.$axios.post("/platform/activity/worksCollection/upload/listPerMissionActivity").then((res) => {
|
this.$axios.post("/platform/activity/worksCollection/upload/listPerMissionActivity", {year: this.pageForm.year}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.activityOptions = res.data
|
this.activityOptions = res.data
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="applyTime" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="registerDate" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column label="旧身份" prop="oldRoleName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="旧身份" prop="oldRoleName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="新身份" prop="nowRoleName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="新身份" prop="nowRoleName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -128,10 +128,10 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="roleCode" label="身份">
|
<el-form-item prop="roleCode" label="身份">
|
||||||
<el-checkbox-group v-model="roleCodeFormData.roleCode">
|
<el-checkbox-group v-model="roleCodeFormData.roleCode">
|
||||||
<el-checkbox label="CLUB_PRESIDENT">社团会长</el-checkbox>
|
<el-checkbox label="CLUB_PRESIDENT" disabled>社团会长</el-checkbox>
|
||||||
<el-checkbox label="CLUB_VICE_PRESIDENT">社团副会长</el-checkbox>
|
<el-checkbox label="CLUB_VICE_PRESIDENT" disabled>社团副会长</el-checkbox>
|
||||||
<el-checkbox label="CLUB_SECRETARY">社团秘书长</el-checkbox>
|
<el-checkbox label="CLUB_SECRETARY" disabled>社团秘书长</el-checkbox>
|
||||||
<el-checkbox label="CLUB_VICE_SECRETARY">社团副秘书长</el-checkbox>
|
<el-checkbox label="CLUB_VICE_SECRETARY" disabled>社团副秘书长</el-checkbox>
|
||||||
<el-checkbox label="CLUB_OPERATOR">社团操作员</el-checkbox>
|
<el-checkbox label="CLUB_OPERATOR">社团操作员</el-checkbox>
|
||||||
<el-checkbox label="CLUB_REIMBURSEMENT_MANAGER">社团报销负责人</el-checkbox>
|
<el-checkbox label="CLUB_REIMBURSEMENT_MANAGER">社团报销负责人</el-checkbox>
|
||||||
<el-checkbox label="CLUB_MEMBER">社团会员</el-checkbox>
|
<el-checkbox label="CLUB_MEMBER">社团会员</el-checkbox>
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column label="申请人" prop="userName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请人" prop="userName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="申请时间" prop="creatTime" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="creatTime" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column label="申请人" prop="userName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请人" prop="userName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="申请时间" prop="creatTime" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="申请时间" prop="creatTime" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="applyDate" label="申请时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="applyDate" label="申请时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ layout("/layouts/platform.html"){
|
|||||||
this.$axios.post("/platform/club/join/apply/checkApplyClub", { clubId: row.id }).then((res) => {
|
this.$axios.post("/platform/club/join/apply/checkApplyClub", { clubId: row.id }).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
commonUtil.pjaxPush('/platform/club/join/apply?clubId=' + row.id)
|
commonUtil.pjaxPush('/platform/club/join/apply?clubId=' + row.id)
|
||||||
|
} else {
|
||||||
|
this.$message.warning(res.msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="applyDate" label="申请时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="applyDate" label="申请时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ layout("/layouts/platform.html"){
|
|||||||
<table-tool label="社团列表">
|
<table-tool label="社团列表">
|
||||||
<!-- <el-button @click="openAdd" size="medium" type="primary">社团注册</el-button>-->
|
<!-- <el-button @click="openAdd" size="medium" type="primary">社团注册</el-button>-->
|
||||||
</table-tool>
|
</table-tool>
|
||||||
<el-table :data="tableData" :size="tableSize">
|
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" :default-sort="{ prop: 'clubCode', order: 'ascending' }">
|
||||||
<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 label="社团编码" prop="clubCode" sortable></el-table-column>
|
<el-table-column label="社团编码" prop="clubCode" sortable></el-table-column>
|
||||||
<el-table-column label="社团名称" prop="clubName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="社团名称" prop="clubName" sortable show-overflow-tooltip></el-table-column>
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
<el-table-column label="发起人" prop="sponsorName" sortable show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
<el-table-column label="当前节点" prop="curTaskName" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<span>{{ row.finishTime ? $moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
<el-table-column label="流程状态" prop="instanceState" show-overflow-tooltip>
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{ row }">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
|||||||
@@ -800,18 +800,37 @@ const apply = {
|
|||||||
.filter(index => index > -1)
|
.filter(index => index > -1)
|
||||||
},
|
},
|
||||||
getBlockClass(block) {
|
getBlockClass(block) {
|
||||||
|
const expired = this.isExpiredAvailabilityBlock(block)
|
||||||
return {
|
return {
|
||||||
'apply-block': true,
|
'apply-block': true,
|
||||||
'apply-block--available': block.status === 'available' && !this.selectedBlockKeys.includes(block.key),
|
'apply-block--available': block.status === 'available' && !expired && !this.selectedBlockKeys.includes(block.key),
|
||||||
'apply-block--reserved': block.status === 'reserved',
|
'apply-block--reserved': block.status === 'reserved',
|
||||||
'apply-block--closed': block.status === 'closed',
|
'apply-block--closed': block.status === 'closed' || expired,
|
||||||
'apply-block--selected': this.selectedBlockKeys.includes(block.key),
|
'apply-block--selected': this.selectedBlockKeys.includes(block.key),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 前端按当天当前时间再做一层兜底判断,避免预约弹窗长时间停留后,
|
||||||
|
* 之前可选的全天候时间块在开始后仍被继续点选。
|
||||||
|
*/
|
||||||
|
isExpiredAvailabilityBlock(block) {
|
||||||
|
if (!block || !block.startDateTime) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const start = this.$moment(block.startDateTime)
|
||||||
|
if (!start.isValid()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return start.isSame(this.$moment(), 'day') && !start.isAfter(this.$moment())
|
||||||
|
},
|
||||||
onAvailabilityBlockClick(block) {
|
onAvailabilityBlockClick(block) {
|
||||||
if (!block || !block.key) {
|
if (!block || !block.key) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (this.isExpiredAvailabilityBlock(block) && !this.selectedBlockKeys.includes(block.key)) {
|
||||||
|
this.$message.warning('该时段开始时间已过,请选择其他时段')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (block.status !== 'available' && !this.selectedBlockKeys.includes(block.key)) {
|
if (block.status !== 'available' && !this.selectedBlockKeys.includes(block.key)) {
|
||||||
this.$message.warning(block.status === 'reserved' ? '该时段已被预约,请选择其他时段' : '该时段当前不可预约')
|
this.$message.warning(block.status === 'reserved' ? '该时段已被预约,请选择其他时段' : '该时段当前不可预约')
|
||||||
return
|
return
|
||||||
@@ -860,7 +879,7 @@ const apply = {
|
|||||||
}
|
}
|
||||||
for (let i = startIndex; i <= endIndex; i++) {
|
for (let i = startIndex; i <= endIndex; i++) {
|
||||||
const block = this.availabilityBlocks[i]
|
const block = this.availabilityBlocks[i]
|
||||||
if (!block || block.status !== 'available') {
|
if (!block || block.status !== 'available' || this.isExpiredAvailabilityBlock(block)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (i > startIndex) {
|
if (i > startIndex) {
|
||||||
|
|||||||
+85
-53
@@ -36,6 +36,13 @@ layout("/layouts/platform.html"){
|
|||||||
.invoice-file-name:hover {
|
.invoice-file-name:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invoice-field-title {
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
@@ -319,26 +326,6 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
|
|
||||||
<!-- <el-descriptions-item label="户名">-->
|
|
||||||
<!-- <el-form-item prop="bankUserName" label="户名">-->
|
|
||||||
<!-- <el-input v-model="formData.bankUserName" show-word-limit-->
|
|
||||||
<!-- placeholder="请输入户名"></el-input>-->
|
|
||||||
<!-- </el-form-item>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="银行账号">-->
|
|
||||||
<!-- <el-form-item prop="bankCardNumber" label="银行账号">-->
|
|
||||||
<!-- <el-input v-model="formData.bankCardNumber" show-word-limit-->
|
|
||||||
<!-- placeholder="请输入银行账号"></el-input>-->
|
|
||||||
<!-- </el-form-item>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="开户行">-->
|
|
||||||
<!-- <el-form-item prop="bankOfDeposit" label="开户行">-->
|
|
||||||
<!-- <el-input v-model="formData.bankOfDeposit" show-word-limit-->
|
|
||||||
<!-- placeholder="请输入开户行"></el-input>-->
|
|
||||||
<!-- </el-form-item>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
|
|
||||||
<el-descriptions-item label="活动名称" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
<el-descriptions-item label="活动名称" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
<el-form-item label="活动名称" prop="activityName">
|
<el-form-item label="活动名称" prop="activityName">
|
||||||
<el-input type="text" v-model="formData.activityName" placeholder="请输入活动名称"
|
<el-input type="text" v-model="formData.activityName" placeholder="请输入活动名称"
|
||||||
@@ -358,11 +345,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="报销金额" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
<!-- <el-descriptions-item label="报销金额" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">-->
|
||||||
<el-form-item label="报销金额" prop="money">
|
<!-- <el-form-item label="报销金额" prop="money">-->
|
||||||
<el-input v-model="formData.money" placeholder="自动汇总发票金额" readonly></el-input>
|
<!-- <el-input v-model="formData.money" placeholder="自动汇总发票金额" readonly></el-input>-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
</el-descriptions-item>
|
<!-- </el-descriptions-item>-->
|
||||||
|
|
||||||
<el-descriptions-item label="活动时间" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
<el-descriptions-item label="活动时间" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
<el-form-item label="活动时间" prop="activityTime">
|
<el-form-item label="活动时间" prop="activityTime">
|
||||||
@@ -372,6 +359,9 @@ layout("/layouts/platform.html"){
|
|||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1' && formData.reimburseFundSource !== 'UNION_REIMBURSE_FUND_SOURCE_3'">
|
||||||
|
|
||||||
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="慰问时间" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
<el-descriptions-item label="慰问时间" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
<el-form-item label="慰问时间" prop="condolenceTime">
|
<el-form-item label="慰问时间" prop="condolenceTime">
|
||||||
@@ -470,8 +460,6 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="2" v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'" style="display: none;">
|
|
||||||
</el-descriptions-item>
|
|
||||||
|
|
||||||
<el-descriptions-item label="参加随行人员" :span="2"
|
<el-descriptions-item label="参加随行人员" :span="2"
|
||||||
v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
@@ -492,8 +480,7 @@ layout("/layouts/platform.html"){
|
|||||||
type="textarea" :autosize="{ minRows: 4, maxRows: 8}"></el-input>
|
type="textarea" :autosize="{ minRows: 4, maxRows: 8}"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :span="2" v-if="formData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1' && formData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3'" style="display: none;">
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="2">
|
<el-descriptions-item :span="2">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
附件
|
附件
|
||||||
@@ -529,26 +516,23 @@ layout("/layouts/platform.html"){
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="报销金额" prop="money">
|
<el-form-item label="报销金额" prop="money">
|
||||||
|
<div class="invoice-field-title">报销金额</div>
|
||||||
<el-input v-model="formData.money" placeholder="自动汇总发票金额" readonly></el-input>
|
<el-input v-model="formData.money" placeholder="自动汇总发票金额" readonly></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="发票张数" prop="invoiceNumber">
|
<el-form-item label="发票张数" prop="invoiceNumber">
|
||||||
|
<div class="invoice-field-title">发票张数</div>
|
||||||
<el-input v-model="formData.invoiceNumber" placeholder="自动统计发票数量" readonly></el-input>
|
<el-input v-model="formData.invoiceNumber" placeholder="自动统计发票数量" readonly></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item prop="paymentNotes" label="支付内容">
|
<el-form-item prop="paymentNotes" label="支付内容">
|
||||||
|
<div class="invoice-field-title">支付内容</div>
|
||||||
<el-input maxlength="500" v-model="formData.paymentNotes" placeholder="请填写支付内容"
|
<el-input maxlength="500" v-model="formData.paymentNotes" placeholder="请填写支付内容"
|
||||||
type="textarea" :autosize="{ minRows: 4, maxRows: 8}"></el-input>
|
type="textarea" :autosize="{ minRows: 4, maxRows: 8}"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item prop="notes" label="备注">
|
|
||||||
<el-input maxlength="500" v-model="formData.notes" placeholder="补充说明"
|
|
||||||
type="textarea" :autosize="{ minRows: 3, maxRows: 6}"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<div class="invoice-toolbar">
|
<div class="invoice-toolbar">
|
||||||
<div>
|
<div>
|
||||||
@@ -734,7 +718,6 @@ layout("/layouts/platform.html"){
|
|||||||
condolenceTime: [{required: true, message: "请选择慰问时间", trigger: ["change", "blur"]}],
|
condolenceTime: [{required: true, message: "请选择慰问时间", trigger: ["change", "blur"]}],
|
||||||
// invoiceNumber: [{required: true, message: "请填写发票张数", trigger: ["change", "blur"]}],
|
// invoiceNumber: [{required: true, message: "请填写发票张数", trigger: ["change", "blur"]}],
|
||||||
// invoice: [{required: true, message: "请填写发票号码", trigger: ["change", "blur"]}],
|
// invoice: [{required: true, message: "请填写发票号码", trigger: ["change", "blur"]}],
|
||||||
paymentNotes: [{required: true, message: "请填写支付内容", trigger: ["change", "blur"]}],
|
|
||||||
activityName: [{required: true, message: "请填写活动名称", trigger: ["change", "blur"]}],
|
activityName: [{required: true, message: "请填写活动名称", trigger: ["change", "blur"]}],
|
||||||
money: [{required: true, message: "请填写报销金额", trigger: ["change", "blur"]}],
|
money: [{required: true, message: "请填写报销金额", trigger: ["change", "blur"]}],
|
||||||
mobile: [
|
mobile: [
|
||||||
@@ -776,7 +759,7 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showInvoiceTab() {
|
showInvoiceTab() {
|
||||||
return this.formData.reimburseProject !== "UNION_REIMBURSE_PROJECT_1"
|
return !!this.formData.reimburseProject
|
||||||
},
|
},
|
||||||
bankHistoryUserNames() {
|
bankHistoryUserNames() {
|
||||||
const userNameMap = {}
|
const userNameMap = {}
|
||||||
@@ -859,12 +842,46 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
selectQueryUserForPayer(keyword, options) {
|
selectQueryUserForPayer(keyword, options) {
|
||||||
options.length = 0
|
options.length = 0
|
||||||
this.$axios.post("/platform/unionReimburse/apply/listUser", {keyword: keyword}).then((res) => {
|
if (this.formData.reimburseFundSource === "UNION_REIMBURSE_FUND_SOURCE_3" && !this.formData.clubId) {
|
||||||
|
this.$message.warning("请先选择协会")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$axios.post("/platform/unionReimburse/apply/listPayerUser", {
|
||||||
|
keyword: keyword,
|
||||||
|
reimburseFundSource: this.formData.reimburseFundSource,
|
||||||
|
clubId: this.formData.clubId
|
||||||
|
}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
options.push(...res.data)
|
options.push(...res.data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
resetPayerInfo() {
|
||||||
|
this.$set(this.formData, "payer", null)
|
||||||
|
this.$set(this.formData, "payerName", null)
|
||||||
|
this.$set(this.formData, "payerLoginname", null)
|
||||||
|
this.$set(this.formData, "bankUserName", null)
|
||||||
|
this.$set(this.formData, "bankCardNumber", null)
|
||||||
|
this.$set(this.formData, "bankOfDeposit", null)
|
||||||
|
this.$set(this, "historyData", [])
|
||||||
|
this.$set(this, "payerOptions", [])
|
||||||
|
},
|
||||||
|
appendCurrentPayerOption() {
|
||||||
|
if (!this.formData.payer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const exists = this.payerOptions.some((item) => item.id === this.formData.payer)
|
||||||
|
if (exists) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 远程下拉编辑回显时需要先补齐当前付款人选项,否则 el-select 只能显示已保存的 id。
|
||||||
|
this.payerOptions.push({
|
||||||
|
id: this.formData.payer,
|
||||||
|
userName: this.formData.payerName || "",
|
||||||
|
loginName: this.formData.payerLoginname || "",
|
||||||
|
unitName: this.formData.unitName || "暂无"
|
||||||
|
})
|
||||||
|
},
|
||||||
createRemoteMethod(options) {
|
createRemoteMethod(options) {
|
||||||
return (keyword) => {
|
return (keyword) => {
|
||||||
this.selectQueryUser(keyword, options)
|
this.selectQueryUser(keyword, options)
|
||||||
@@ -933,7 +950,12 @@ layout("/layouts/platform.html"){
|
|||||||
if (this.formData.payer) {
|
if (this.formData.payer) {
|
||||||
await this.getUserBankHistory();
|
await this.getUserBankHistory();
|
||||||
} else {
|
} else {
|
||||||
this.historyData = []
|
this.$set(this, "historyData", [])
|
||||||
|
this.$set(this.formData, "payerName", null)
|
||||||
|
this.$set(this.formData, "payerLoginname", null)
|
||||||
|
this.$set(this.formData, "bankUserName", null)
|
||||||
|
this.$set(this.formData, "bankCardNumber", null)
|
||||||
|
this.$set(this.formData, "bankOfDeposit", null)
|
||||||
}
|
}
|
||||||
const user = this.payerOptions.find(o => o.id === this.formData.payer)
|
const user = this.payerOptions.find(o => o.id === this.formData.payer)
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -980,14 +1002,14 @@ layout("/layouts/platform.html"){
|
|||||||
this.$set(this.formData, "condolenceMoney", parseFloat(money).toFixed(2))
|
this.$set(this.formData, "condolenceMoney", parseFloat(money).toFixed(2))
|
||||||
this.$set(this.formData, "condolenceFilesNotes", uploadFileDesc)
|
this.$set(this.formData, "condolenceFilesNotes", uploadFileDesc)
|
||||||
this.$set(this.formData, "typeName", name)
|
this.$set(this.formData, "typeName", name)
|
||||||
|
this.rebuildInvoiceSummary()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleReimburseProjectChange(value) {
|
handleReimburseProjectChange(value) {
|
||||||
if (value === "UNION_REIMBURSE_PROJECT_1") {
|
if (value === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
this.$set(this, "activeTabName", "basic")
|
this.$set(this, "activeTabName", "basic")
|
||||||
this.$set(this.formData, "invoiceDetails", [])
|
|
||||||
this.$set(this.formData, "invoiceNumber", "")
|
|
||||||
this.$set(this.formData, "money", null)
|
this.$set(this.formData, "money", null)
|
||||||
|
this.rebuildInvoiceSummary()
|
||||||
} else {
|
} else {
|
||||||
this.rebuildInvoiceSummary()
|
this.rebuildInvoiceSummary()
|
||||||
this.normalizeFundBalance()
|
this.normalizeFundBalance()
|
||||||
@@ -1104,7 +1126,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.$set(this.detailForm, "invoiceCheckCode", data.invoiceCheckCode)
|
this.$set(this.detailForm, "invoiceCheckCode", data.invoiceCheckCode)
|
||||||
}
|
}
|
||||||
if (this.detailForm.invoiceNo) {
|
if (this.detailForm.invoiceNo) {
|
||||||
return this.validateInvoiceDuplicateBeforeSave()
|
return this.validateInvoiceDuplicateBeforeSave(true)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
@@ -1117,7 +1139,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.recognizingInvoice = false
|
this.recognizingInvoice = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async validateInvoiceDuplicateBeforeSave() {
|
async validateInvoiceDuplicateBeforeSave(checkHistory) {
|
||||||
const invoiceNo = this.detailForm.invoiceNo ? String(this.detailForm.invoiceNo).trim() : ""
|
const invoiceNo = this.detailForm.invoiceNo ? String(this.detailForm.invoiceNo).trim() : ""
|
||||||
if (!invoiceNo) {
|
if (!invoiceNo) {
|
||||||
return false
|
return false
|
||||||
@@ -1137,6 +1159,9 @@ layout("/layouts/platform.html"){
|
|||||||
this.$message.warning("发票号码【" + invoiceNo + "】与本次提交的第" + duplicateRows.join("、") + "条发票重复,不能保存")
|
this.$message.warning("发票号码【" + invoiceNo + "】与本次提交的第" + duplicateRows.join("、") + "条发票重复,不能保存")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (!checkHistory) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
const resp = await this.$axios.get("/platform/unionReimburse/apply/checkInvoiceDuplicate", {
|
const resp = await this.$axios.get("/platform/unionReimburse/apply/checkInvoiceDuplicate", {
|
||||||
params: {
|
params: {
|
||||||
invoiceNo: invoiceNo,
|
invoiceNo: invoiceNo,
|
||||||
@@ -1154,7 +1179,7 @@ layout("/layouts/platform.html"){
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const duplicateValid = await this.validateInvoiceDuplicateBeforeSave()
|
const duplicateValid = await this.validateInvoiceDuplicateBeforeSave(false)
|
||||||
if (!duplicateValid) {
|
if (!duplicateValid) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1179,9 +1204,6 @@ layout("/layouts/platform.html"){
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
rebuildInvoiceSummary() {
|
rebuildInvoiceSummary() {
|
||||||
if (this.formData.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let totalMoney = 0
|
let totalMoney = 0
|
||||||
let fileCount = 0
|
let fileCount = 0
|
||||||
const invoiceDetails = this.formData.invoiceDetails || []
|
const invoiceDetails = this.formData.invoiceDetails || []
|
||||||
@@ -1193,15 +1215,19 @@ layout("/layouts/platform.html"){
|
|||||||
fileCount = fileCount + 1
|
fileCount = fileCount + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$set(this.formData, "money", totalMoney ? totalMoney.toFixed(2) : "0.00")
|
// 慰问类发票为可选附件;有发票按发票汇总金额,没有发票按慰问金额。
|
||||||
|
if (this.formData.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
const condolenceMoney = this.formData.condolenceMoney
|
||||||
|
this.$set(this.formData, "money", fileCount > 0 ? (totalMoney ? totalMoney.toFixed(2) : "0.00") : condolenceMoney)
|
||||||
|
} else {
|
||||||
|
this.$set(this.formData, "money", totalMoney ? totalMoney.toFixed(2) : "0.00")
|
||||||
|
}
|
||||||
this.$set(this.formData, "invoiceNumber", String(fileCount))
|
this.$set(this.formData, "invoiceNumber", String(fileCount))
|
||||||
},
|
},
|
||||||
validateInvoiceDetailsBeforeSubmit() {
|
validateInvoiceDetailsBeforeSubmit() {
|
||||||
if (this.formData.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
const invoiceDetails = this.formData.invoiceDetails || []
|
const invoiceDetails = this.formData.invoiceDetails || []
|
||||||
if (!invoiceDetails.length) {
|
// 慰问类允许不填发票;如果填写了发票明细,则每条明细仍需完整。
|
||||||
|
if (!invoiceDetails.length && this.formData.reimburseProject !== "UNION_REIMBURSE_PROJECT_1") {
|
||||||
this.$message.warning("请至少维护一条发票明细")
|
this.$message.warning("请至少维护一条发票明细")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1262,6 +1288,7 @@ layout("/layouts/platform.html"){
|
|||||||
// 提交验证
|
// 提交验证
|
||||||
validateBeforeSubmit() {
|
validateBeforeSubmit() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
this.rebuildInvoiceSummary()
|
||||||
this.$refs.formRef.validate((valid) => {
|
this.$refs.formRef.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (this.formData.reimburseFundSource === "UNION_REIMBURSE_FUND_SOURCE_3" && !this.formData.clubId) {
|
if (this.formData.reimburseFundSource === "UNION_REIMBURSE_FUND_SOURCE_3" && !this.formData.clubId) {
|
||||||
@@ -1275,7 +1302,6 @@ layout("/layouts/platform.html"){
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.normalizeFundBalance()
|
this.normalizeFundBalance()
|
||||||
this.rebuildInvoiceSummary()
|
|
||||||
resolve(true)
|
resolve(true)
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning("请完善必填信息")
|
this.$message.warning("请完善必填信息")
|
||||||
@@ -1356,6 +1382,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.$set(this.formData, "clubId", this.clubOptions[0].id)
|
this.$set(this.formData, "clubId", this.clubOptions[0].id)
|
||||||
this.$set(this.formData, "clubName", this.clubOptions[0].clubName)
|
this.$set(this.formData, "clubName", this.clubOptions[0].clubName)
|
||||||
}
|
}
|
||||||
|
this.resetPayerInfo()
|
||||||
this.reimburseFundSourceChange()
|
this.reimburseFundSourceChange()
|
||||||
},
|
},
|
||||||
clubChange() {
|
clubChange() {
|
||||||
@@ -1364,11 +1391,13 @@ layout("/layouts/platform.html"){
|
|||||||
if (selectedClub) {
|
if (selectedClub) {
|
||||||
this.$set(this.formData, "clubName", selectedClub.clubName)
|
this.$set(this.formData, "clubName", selectedClub.clubName)
|
||||||
}
|
}
|
||||||
|
this.resetPayerInfo()
|
||||||
this.reimburseFundSourceChange()
|
this.reimburseFundSourceChange()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.$set(this.formData, "clubName", null)
|
this.$set(this.formData, "clubName", null)
|
||||||
this.$set(this.formData, "fundBalance", null)
|
this.$set(this.formData, "fundBalance", null)
|
||||||
|
this.resetPayerInfo()
|
||||||
this.fundBalanceText = "请选择协会"
|
this.fundBalanceText = "请选择协会"
|
||||||
},
|
},
|
||||||
// 经费来源查询
|
// 经费来源查询
|
||||||
@@ -1457,6 +1486,9 @@ layout("/layouts/platform.html"){
|
|||||||
this.$axios.post("/platform/unionReimburse/apply/info", {id: this.bizId}).then(async (res) => {
|
this.$axios.post("/platform/unionReimburse/apply/info", {id: this.bizId}).then(async (res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.formData = this.ensureFormData(res.data)
|
this.formData = this.ensureFormData(res.data)
|
||||||
|
this.appendCurrentPayerOption()
|
||||||
|
this.getUserBankHistory()
|
||||||
|
this.reimburseFundSourceChange()
|
||||||
await this.selectQueryUser(this.formData.certifierLoginName, this.userOptions)
|
await this.selectQueryUser(this.formData.certifierLoginName, this.userOptions)
|
||||||
this.rebuildInvoiceSummary()
|
this.rebuildInvoiceSummary()
|
||||||
// this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
|
// this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
|
||||||
|
|||||||
+8
-1
@@ -77,7 +77,11 @@ layout("/layouts/platform.html"){
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="money" label="金额"></el-table-column>
|
<el-table-column prop="money" label="金额"></el-table-column>
|
||||||
<el-table-column prop="createTime" label="申请时间" sortable="custom"></el-table-column>
|
<el-table-column prop="createTime" label="申请时间" sortable="custom">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
{{ formatCreateTime(row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
||||||
<el-table-column prop="instanceState" label="流程状态">
|
<el-table-column prop="instanceState" label="流程状态">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
@@ -157,6 +161,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.$refs.guava.edit(() => {
|
this.$refs.guava.edit(() => {
|
||||||
this.showApprovalForm = false
|
this.showApprovalForm = false
|
||||||
|
|||||||
+8
-1
@@ -55,7 +55,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column prop="userName" label="姓名"></el-table-column>
|
<el-table-column prop="userName" label="姓名"></el-table-column>
|
||||||
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="createTime" label="申请时间" sortable="custom"></el-table-column>
|
<el-table-column prop="createTime" label="申请时间" sortable="custom">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
{{ formatCreateTime(row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
||||||
@@ -150,6 +154,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.$refs.guava.edit(()=>{
|
this.$refs.guava.edit(()=>{
|
||||||
this.showApprovalForm = false
|
this.showApprovalForm = false
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ const unionReimburseInfo = {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showInvoiceTab() {
|
showInvoiceTab() {
|
||||||
return this.viewData.reimburseProject !== "UNION_REIMBURSE_PROJECT_1"
|
return !!this.viewData.reimburseProject
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column prop="userName" label="姓名"></el-table-column>
|
<el-table-column prop="userName" label="姓名"></el-table-column>
|
||||||
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="createTime" label="申请时间" sortable="custom"></el-table-column>
|
<el-table-column prop="createTime" label="申请时间" sortable="custom">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
{{ formatCreateTime(row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
||||||
@@ -125,6 +129,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.$refs.guava.view(() => {
|
this.$refs.guava.view(() => {
|
||||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||||
|
|||||||
+48
-18
@@ -46,19 +46,27 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<table-tool>
|
<table-tool>
|
||||||
<el-button @click="AllReview" size="small" type="primary">一键审核</el-button>
|
<el-button @click="AllReview" size="small" type="primary" :loading="formLoading"
|
||||||
|
:disabled="pageForm.approval">一键审核</el-button>
|
||||||
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
<el-radio-button :label="true">已审核</el-radio-button>
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
<el-radio-button :label="false">未审核</el-radio-button>
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</table-tool>
|
</table-tool>
|
||||||
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
<el-table ref="tableRef" :data="tableData" row-key="id" v-loading="tableLoading"
|
||||||
|
@selection-change="handleSelectionChange" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column v-if="!pageForm.approval" type="selection" width="55"
|
||||||
|
:reserve-selection="true" :selectable="(row) => row.stateId == 2"></el-table-column>
|
||||||
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
<el-table-column prop="loginName" label="经办人工号" sortable="custom"></el-table-column>
|
<el-table-column prop="loginName" label="经办人工号" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="userName" label="姓名"></el-table-column>
|
<el-table-column prop="userName" label="姓名"></el-table-column>
|
||||||
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
<el-table-column prop="unionName" label="所属工会" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
<el-table-column prop="unitName" label="所属单位" sortable="custom"></el-table-column>
|
||||||
<el-table-column prop="createTime" label="申请时间" sortable="custom"></el-table-column>
|
<el-table-column prop="createTime" label="申请时间" sortable="custom">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
{{ formatCreateTime(row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
<el-table-column prop="reimburseProject" label="报销项目" sortable="custom">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
<span v-if="row.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">慰问</span>
|
||||||
@@ -115,9 +123,9 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form>
|
</el-form>
|
||||||
<el-row type="flex" justify="end">
|
<el-row type="flex" justify="end">
|
||||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
<el-button @click="handleTaskAction(5)" size="small" type="info">退回到发起人</el-button>
|
<el-button @click="handleTaskAction(5)" size="small" type="info" :loading="formLoading">退回到发起人</el-button>
|
||||||
<el-button @click="handleTaskAction(4)" size="small" type="danger">拒绝申请</el-button>
|
<el-button @click="handleTaskAction(4)" size="small" type="danger" :loading="formLoading">拒绝申请</el-button>
|
||||||
<el-button @click="handleTaskAction(3)" size="small" type="primary">同意申请</el-button>
|
<el-button @click="handleTaskAction(3)" size="small" type="primary" :loading="formLoading">同意申请</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</union-reimburse-info>
|
</union-reimburse-info>
|
||||||
@@ -144,6 +152,7 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
formData: {},
|
formData: {},
|
||||||
showApprovalForm: false,
|
showApprovalForm: false,
|
||||||
|
multipleSelection: [],
|
||||||
unionOptions: [],
|
unionOptions: [],
|
||||||
unitOptions: []
|
unitOptions: []
|
||||||
}
|
}
|
||||||
@@ -154,6 +163,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.$refs.guava.edit(() => {
|
this.$refs.guava.edit(() => {
|
||||||
this.showApprovalForm = false
|
this.showApprovalForm = false
|
||||||
@@ -161,23 +173,38 @@ layout("/layouts/platform.html"){
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.multipleSelection = val
|
||||||
|
},
|
||||||
|
|
||||||
AllReview() {
|
AllReview() {
|
||||||
this.$confirm('确定所选申请都已通过线下审核了吗?', '提示', {
|
if (!this.multipleSelection || this.multipleSelection.length === 0) {
|
||||||
|
this.$message.warning('请至少选择一条记录进行审核')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const ids = this.multipleSelection.map((item) => item.id)
|
||||||
|
this.$confirm('确定所选的 ' + ids.length + ' 条申请都已通过线下审核了吗?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(async () => {
|
}).then(() => {
|
||||||
const resp = await $.post("/platform/unionReimburse/review/allReview");
|
this.formLoading = true
|
||||||
if (resp && resp.code === 0) {
|
this.$axios.post("/platform/unionReimburse/review/allReview", {
|
||||||
this.pageForm.approval = true
|
ids: ids
|
||||||
this.pageData();
|
}).then((res) => {
|
||||||
this.$message.success(resp.msg || '一键审核成功')
|
if (res.code === 0) {
|
||||||
} else {
|
this.multipleSelection = []
|
||||||
this.$message.error(resp.msg || '一键审核失败')
|
this.pageData()
|
||||||
}
|
this.$message.success(res.msg || '一键审核成功')
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || '一键审核失败')
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.formLoading = false
|
||||||
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// 用户取消操作
|
// 用户取消操作
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
openAudit(row) {
|
openAudit(row) {
|
||||||
@@ -199,8 +226,9 @@ layout("/layouts/platform.html"){
|
|||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning"
|
type: "warning"
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
this.formLoading = true
|
||||||
this.$axios.post("/platform/unionReimburse/review/reviewTask", {
|
this.$axios.post("/platform/unionReimburse/review/reviewTask", {
|
||||||
data: JSON.stringify({...this.formData}),
|
data: JSON.stringify(Object.assign({}, this.formData)),
|
||||||
submitType: val
|
submitType: val
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -208,6 +236,8 @@ layout("/layouts/platform.html"){
|
|||||||
this.$message.success(res.msg)
|
this.$message.success(res.msg)
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.formLoading = false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ layout("/layouts/platform.html"){
|
|||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
<template>
|
<template>
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<snaker-start slot="header" label="撰写提案" define_key="JDHTA">
|
<snaker-start slot="header" label="撰写提案" define_key="JDHTA_NC">
|
||||||
<template slot="header-right-label">
|
<template slot="header-right-label">
|
||||||
<el-link type="primary" @click="openImport" v-if="!formData.id" style="margin-right: 15px">导入提案</el-link>
|
<el-link type="primary" @click="openImport" v-if="!formData.id" style="margin-right: 15px">导入提案</el-link>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+5
@@ -108,6 +108,11 @@ layout("/layouts/platform.html"){
|
|||||||
<!-- </el-table-column>-->
|
<!-- </el-table-column>-->
|
||||||
<el-table-column label="代表类型" prop="representativeType"></el-table-column>
|
<el-table-column label="代表类型" prop="representativeType"></el-table-column>
|
||||||
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" width="160">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<span v-if="row.finishTime">{{$moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss')}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="instanceState" label="流程状态">
|
<el-table-column prop="instanceState" label="流程状态">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
|
||||||
|
|||||||
+5
@@ -105,6 +105,11 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="代表类型" prop="representativeType"></el-table-column>
|
<el-table-column label="代表类型" prop="representativeType"></el-table-column>
|
||||||
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
||||||
|
<el-table-column label="审核时间" prop="finishTime" width="160">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<span v-if="row.finishTime">{{$moment(row.finishTime).format('YYYY-MM-DD HH:mm:ss')}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="instanceState" label="流程状态">
|
<el-table-column prop="instanceState" label="流程状态">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
|
||||||
|
|||||||
@@ -290,7 +290,13 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
search(pageForm) {
|
search(pageForm) {
|
||||||
if (pageForm) {
|
if (pageForm) {
|
||||||
|
// 当前页的在职状态、人员类型使用标签数组筛选,公共查询组件回传的是字符串,
|
||||||
|
// 这里保留当前页数组,避免选择人员属性后把标签筛选状态覆盖掉。
|
||||||
|
const currentUserStates = this.pageForm.userStates
|
||||||
|
const currentPersonTypes = this.pageForm.personTypes
|
||||||
this.pageForm = {...this.pageForm, ...pageForm}
|
this.pageForm = {...this.pageForm, ...pageForm}
|
||||||
|
this.$set(this.pageForm, "userStates", currentUserStates)
|
||||||
|
this.$set(this.pageForm, "personTypes", currentPersonTypes)
|
||||||
}
|
}
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const optionSelect = {
|
|||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24" v-if="projectInfo.signMode === 2">
|
||||||
<el-form-item prop="sign" label="签字">
|
<el-form-item prop="sign" label="签字">
|
||||||
<pc-signature v-model="contactForm.userSign"></pc-signature>
|
<pc-signature v-model="contactForm.userSign"></pc-signature>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
+1279
-136
File diff suppressed because it is too large
Load Diff
+76
-16
@@ -2,6 +2,19 @@
|
|||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.state-primary {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-danger {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销统计" placeholder fixed></van-nav-bar>
|
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销统计" placeholder fixed></van-nav-bar>
|
||||||
<van-sticky offset-top="46px">
|
<van-sticky offset-top="46px">
|
||||||
@@ -22,31 +35,26 @@ layout("/layouts/platform_h5.html"){
|
|||||||
<table-list api="/platform/unionReimburse/collect/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
<table-list api="/platform/unionReimburse/collect/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||||
@ready="doSearch" >
|
@ready="doSearch" >
|
||||||
<template v-slot="{index,row}">
|
<template v-slot="{index,row}">
|
||||||
<table-column label="经办人">{{row.userName}}</table-column>
|
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||||
|
<table-column label="姓名">{{row.userName}}</table-column>
|
||||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||||
<table-column label="报销类别">
|
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
|
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||||
:value="row.reimburseType">
|
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||||
</dict-tag>
|
<table-column label="申请状态">
|
||||||
|
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||||
</table-column>
|
</table-column>
|
||||||
<table-column label="报销项目">
|
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
|
|
||||||
:value="row.reimburseProject">
|
|
||||||
</dict-tag>
|
|
||||||
</table-column>
|
|
||||||
<table-column label="金额">{{row.money}}</table-column>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{index,row}">
|
<template #actions="{index,row}">
|
||||||
<div class="action-btn" @click="onView(row)">
|
<div class="action-btn" @click="onView(row)">
|
||||||
<i class="fa fa-eye"></i>
|
<i class="fa fa-eye"></i>
|
||||||
<span>查看</span>
|
<span>查看</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn" @click="onEdit(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">
|
<!-- <div class="action-btn" @click="onEdit(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">-->
|
||||||
<i class="fa fa-edit"></i>
|
<!-- <i class="fa fa-edit"></i>-->
|
||||||
<span>编辑</span>
|
<!-- <span>编辑</span>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(item)">
|
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(item)">
|
||||||
<i class="fa fa-undo"></i>
|
<i class="fa fa-undo"></i>
|
||||||
<span>撤回</span>
|
<span>撤回</span>
|
||||||
@@ -85,6 +93,58 @@ layout("/layouts/platform_h5.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 手机端统计列表字段展示与我的报销列表保持一致。
|
||||||
|
getReimburseProjectName(reimburseProject) {
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "慰问"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_2") {
|
||||||
|
return "文体活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_3") {
|
||||||
|
return "日常活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_4") {
|
||||||
|
return "专项活动"
|
||||||
|
}
|
||||||
|
return reimburseProject || ""
|
||||||
|
},
|
||||||
|
getRemarkText(row) {
|
||||||
|
if (row.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "被慰问人:" + (row.condolenceUserName || "")
|
||||||
|
}
|
||||||
|
return "活动名称:" + (row.activityName || "")
|
||||||
|
},
|
||||||
|
getStateName(stateId) {
|
||||||
|
if (stateId == 1) {
|
||||||
|
return "待提交"
|
||||||
|
}
|
||||||
|
if (stateId == 2) {
|
||||||
|
return "待审核确认"
|
||||||
|
}
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "报销成功"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "拒绝"
|
||||||
|
}
|
||||||
|
if (stateId == 5) {
|
||||||
|
return "退回"
|
||||||
|
}
|
||||||
|
return stateId || ""
|
||||||
|
},
|
||||||
|
getStateClass(stateId) {
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "state-success"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "state-danger"
|
||||||
|
}
|
||||||
|
return "state-primary"
|
||||||
|
},
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.showApprovalForm = false
|
this.showApprovalForm = false
|
||||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||||
|
|||||||
@@ -5,18 +5,12 @@ const UNION_REIMBURSE_INFO = {
|
|||||||
<van-action-sheet v-model="visible" title="查看详情">
|
<van-action-sheet v-model="visible" title="查看详情">
|
||||||
<div class="detail-container">
|
<div class="detail-container">
|
||||||
<van-cell-group title="报销申请">
|
<van-cell-group title="报销申请">
|
||||||
<van-cell title="经办人">{{ viewData.userName }}</van-cell>
|
|
||||||
<van-cell title="工号">{{ viewData.loginName }}</van-cell>
|
<van-cell title="工号">{{ viewData.loginName }}</van-cell>
|
||||||
<van-cell title="单位">{{ viewData.unitName }}</van-cell>
|
<van-cell title="经办人">{{ viewData.userName }}</van-cell>
|
||||||
<van-cell title="工会">{{ viewData.unionName }}</van-cell>
|
<van-cell title="联系方式">{{ viewData.mobile }}</van-cell>
|
||||||
<van-cell title="报销类别">
|
<van-cell title="经费来源">
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
|
<dict-tag :options="dict.type.UNION_REIMBURSE_FUND_SOURCE"
|
||||||
:value="viewData.reimburseType">
|
:value="viewData.reimburseFundSource">
|
||||||
</dict-tag>
|
|
||||||
</van-cell>
|
|
||||||
<van-cell title="支付方式">
|
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_PAYMENT_WAY"
|
|
||||||
:value="viewData.paymentWay">
|
|
||||||
</dict-tag>
|
</dict-tag>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="报销项目">
|
<van-cell title="报销项目">
|
||||||
@@ -24,34 +18,114 @@ const UNION_REIMBURSE_INFO = {
|
|||||||
:value="viewData.reimburseProject">
|
:value="viewData.reimburseProject">
|
||||||
</dict-tag>
|
</dict-tag>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="联系方式">{{ viewData.mobile }}</van-cell>
|
<van-cell title="支付方式">
|
||||||
<van-cell title="证明人">{{viewData.certifierUserName}}({{viewData.certifierLoginName}})
|
<dict-tag :options="dict.type.UNION_REIMBURSE_PAYMENT_WAY"
|
||||||
|
:value="viewData.paymentWay">
|
||||||
|
</dict-tag>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="户名">{{ viewData.bankUserName }}</van-cell>
|
<van-cell title="所属协会" v-if="viewData.reimburseFundSource === 'UNION_REIMBURSE_FUND_SOURCE_3'">
|
||||||
<van-cell title="银行账号">{{ viewData.bankCardNumber }}</van-cell>
|
{{ viewData.clubName }}
|
||||||
<van-cell title="开户行">{{ viewData.bankOfDeposit }}</van-cell>
|
|
||||||
<van-cell title="活动名称">{{ viewData.activityName }}</van-cell>
|
|
||||||
<van-cell title="活动地点">{{ viewData.activityPlace || '暂无'}}</van-cell>
|
|
||||||
<van-cell title="报销金额(元)">{{ viewData.money }}</van-cell>
|
|
||||||
<van-cell title="活动时间">{{$moment(viewData.activityTime).format('YYYY-MM-DD')}}</van-cell>
|
|
||||||
<!-- <van-cell title="发票张数">{{ viewData.invoiceNumber }}</van-cell>-->
|
|
||||||
<van-cell title="支付内容">
|
|
||||||
<div style="white-space: pre-line">
|
|
||||||
{{ viewData.paymentNotes }}
|
|
||||||
</div>
|
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="签字">
|
<van-cell title="余额" v-if="viewData.reimburseFundSource">{{ formatMoney(viewData.fundBalance) }}</van-cell>
|
||||||
<template #label>
|
|
||||||
<van-image :src="viewData.userSign"
|
<template v-if="viewData.paymentWay === 'UNION_REIMBURSE_PAYMENT_WAY_2'">
|
||||||
style="width: 100%;height: 150px;"></van-image>
|
<van-cell title="付款人">{{ viewData.payerName }}</van-cell>
|
||||||
|
<van-cell title="户名">{{ viewData.bankUserName }}</van-cell>
|
||||||
|
<van-cell title="开户行">{{ viewData.bankOfDeposit }}</van-cell>
|
||||||
|
<van-cell title="银行卡号">{{ viewData.bankCardNumber }}</van-cell>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="viewData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
|
<van-cell title="慰问对象">{{ viewData.condolenceUserName }}</van-cell>
|
||||||
|
<van-cell title="性别">{{ viewData.condolenceSex }}</van-cell>
|
||||||
|
<van-cell title="生日">{{ formatDateText(viewData.condolenceBirthday) }}</van-cell>
|
||||||
|
<van-cell title="身份证号">{{ viewData.condolenceIdCard }}</van-cell>
|
||||||
|
<van-cell title="联系方式">{{ viewData.condolenceMobile }}</van-cell>
|
||||||
|
<van-cell title="慰问类型">{{ viewData.typeName || viewData.condolenceTypeName }}</van-cell>
|
||||||
|
<van-cell title="慰问方式">{{ viewData.way }}</van-cell>
|
||||||
|
<van-cell title="慰问金额">{{ formatMoney(viewData.condolenceMoney) }}</van-cell>
|
||||||
|
<van-cell title="慰问时间">{{ formatDateText(viewData.condolenceTime) }}</van-cell>
|
||||||
|
<van-cell title="结婚时间" v-if="isCondolenceType('cf4ce7af322d464f8f86d818fcc00203')">
|
||||||
|
{{ formatDateText(viewData.marryTime) }}
|
||||||
|
</van-cell>
|
||||||
|
<van-cell title="生育时间" v-if="isCondolenceType('c90cb10dce6542e99ae271bee6fe8cc0')">
|
||||||
|
{{ formatDateText(viewData.fertilityTime) }}
|
||||||
|
</van-cell>
|
||||||
|
<template v-if="isCondolenceType('4e316737e71047e0b01aea78524c1416')">
|
||||||
|
<van-cell title="住院病由">{{ viewData.hospitalCausation }}</van-cell>
|
||||||
|
<van-cell title="住院开始时间">{{ formatDateText(viewData.hospitalizationStartTime) }}</van-cell>
|
||||||
|
<van-cell title="住院结束时间">{{ formatDateText(viewData.hospitalizationEndTime) }}</van-cell>
|
||||||
|
<van-cell title="入住医院">{{ viewData.hospital }}</van-cell>
|
||||||
|
<van-cell title="当年次数">{{ viewData.hospitalCount }}</van-cell>
|
||||||
</template>
|
</template>
|
||||||
</van-cell>
|
<template v-if="isCondolenceType('60f03a87b62b4823855814afdbf5672a')">
|
||||||
|
<van-cell title="去逝时间">{{ formatDateText(viewData.deathTime) }}</van-cell>
|
||||||
|
<van-cell title="与被慰问人关系">{{ viewData.condolenceRelationship }}</van-cell>
|
||||||
|
</template>
|
||||||
|
<van-cell title="参加随行人员">
|
||||||
|
<div style="white-space: pre-line">{{ viewData.participants }}</div>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell title="报销事由">
|
||||||
|
<div style="white-space: pre-line">{{ viewData.paymentNotes }}</div>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell title="备注">
|
||||||
|
<div style="white-space: pre-line">{{ viewData.notes }}</div>
|
||||||
|
</van-cell>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="viewData.reimburseProject && viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
||||||
|
<van-cell title="活动名称">{{ viewData.activityName }}</van-cell>
|
||||||
|
<van-cell title="活动人数">{{ viewData.activityNumber }}</van-cell>
|
||||||
|
<van-cell title="活动地点">{{ viewData.activityPlace }}</van-cell>
|
||||||
|
<van-cell title="活动时间">{{ formatDateText(viewData.activityTime) }}</van-cell>
|
||||||
|
<van-cell title="支付内容">
|
||||||
|
<div style="white-space: pre-line">{{ viewData.paymentNotes }}</div>
|
||||||
|
</van-cell>
|
||||||
|
</template>
|
||||||
|
|
||||||
<van-cell title="附件">
|
<van-cell title="附件">
|
||||||
<template #label>
|
<template #label>
|
||||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
<file-preview :files="viewData.files" complete_result
|
||||||
|
v-if="viewData.files && viewData.files.length > 0"></file-preview>
|
||||||
|
<span v-else>暂无附件</span>
|
||||||
</template>
|
</template>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group title="电子发票" v-if="viewData.reimburseProject">
|
||||||
|
<van-cell title="报销金额">{{ formatMoney(viewData.money) }}</van-cell>
|
||||||
|
<van-cell title="发票张数">{{ viewData.invoiceNumber }}</van-cell>
|
||||||
|
<van-cell title="发票明细列表">
|
||||||
|
<template #label>
|
||||||
|
<template v-if="viewData.invoiceDetails && viewData.invoiceDetails.length > 0">
|
||||||
|
<div style="margin-top: 8px; padding: 10px 12px; border: 1px solid #ebedf0; border-radius: 6px; background: #fafafa;" v-for="(item, index) in viewData.invoiceDetails" :key="index">
|
||||||
|
<div style="margin-top: 4px; color: #323233;">第{{ index + 1 }}张发票</div>
|
||||||
|
<div style="margin-top: 4px;">发票号码:{{ item.invoiceNo || '未填写' }}</div>
|
||||||
|
<div style="margin-top: 4px;">发票金额:{{ formatMoney(item.invoiceAmount) }}</div>
|
||||||
|
<div style="margin-top: 4px;">销售方信息名称:{{ item.sellerName || '未填写' }}</div>
|
||||||
|
<div style="margin-top: 4px;">项目名称:{{ item.itemName || '未填写' }}</div>
|
||||||
|
<div style="margin-top: 4px;" v-if="item.remark">备注:{{ item.remark }}</div>
|
||||||
|
<file-preview :files="item.invoiceFiles" complete_result
|
||||||
|
v-if="item.invoiceFiles && item.invoiceFiles.length > 0"></file-preview>
|
||||||
|
<div style="margin-top: 4px;" v-else>文件:未上传</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<van-empty description="暂无发票明细" v-else></van-empty>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- <van-cell-group title="电子签名">-->
|
||||||
|
<!-- <van-cell title="签字">-->
|
||||||
|
<!-- <template #label>-->
|
||||||
|
<!-- <van-image :src="viewData.userSign"-->
|
||||||
|
<!-- style="width: 100%;height: 150px;"-->
|
||||||
|
<!-- v-if="viewData.userSign"></van-image>-->
|
||||||
|
<!-- <span v-else>暂无签名</span>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </van-cell>-->
|
||||||
|
<!-- </van-cell-group>-->
|
||||||
|
|
||||||
<template v-for="(task,index) in doneTasks">
|
<template v-for="(task,index) in doneTasks">
|
||||||
<div class="process-title">
|
<div class="process-title">
|
||||||
{{ task.displayName }}
|
{{ task.displayName }}
|
||||||
@@ -61,7 +135,7 @@ const UNION_REIMBURSE_INFO = {
|
|||||||
{{ task.ext.initiatorName}}({{task.ext.initiatorAccount}})
|
{{ task.ext.initiatorName}}({{task.ext.initiatorAccount}})
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="申请时间">
|
<van-cell title="申请时间">
|
||||||
{{ task.finishTime}}
|
{{ formatCreateTime(task.finishTime) }}
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="办理结果">
|
<van-cell title="办理结果">
|
||||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||||
@@ -73,7 +147,7 @@ const UNION_REIMBURSE_INFO = {
|
|||||||
{{ task.taskFormData.userName}}({{task.taskFormData.loginName}})
|
{{ task.taskFormData.userName}}({{task.taskFormData.loginName}})
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="办理时间">
|
<van-cell title="办理时间">
|
||||||
{{ task.finishTime}}
|
{{ formatCreateTime(task.finishTime) }}
|
||||||
</van-cell>
|
</van-cell>
|
||||||
<van-cell title="办理结果">
|
<van-cell title="办理结果">
|
||||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||||
@@ -118,6 +192,22 @@ const UNION_REIMBURSE_INFO = {
|
|||||||
onClose() {
|
onClose() {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
},
|
},
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
|
formatDateText(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD") : ""
|
||||||
|
},
|
||||||
|
formatMoney(value) {
|
||||||
|
if (value === null || value === undefined || value === "") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
const numberValue = Number(value)
|
||||||
|
return isNaN(numberValue) ? value : numberValue.toFixed(2)
|
||||||
|
},
|
||||||
|
isCondolenceType(typeId) {
|
||||||
|
return this.viewData.condolenceTypeId === typeId || this.viewData.condolenceType === typeId
|
||||||
|
},
|
||||||
// 获取申请信息
|
// 获取申请信息
|
||||||
getInfo() {
|
getInfo() {
|
||||||
this.$axios.post("/platform/unionReimburse/apply/info", { id: this.row.id }).then((res) => {
|
this.$axios.post("/platform/unionReimburse/apply/info", { id: this.row.id }).then((res) => {
|
||||||
|
|||||||
+77
-18
@@ -2,6 +2,19 @@
|
|||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.state-primary {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-danger {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的报销" placeholder fixed></van-nav-bar>
|
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的报销" placeholder fixed></van-nav-bar>
|
||||||
<van-sticky offset-top="46px">
|
<van-sticky offset-top="46px">
|
||||||
@@ -14,37 +27,31 @@ layout("/layouts/platform_h5.html"){
|
|||||||
<table-list api="/platform/unionReimburse/mine/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
<table-list api="/platform/unionReimburse/mine/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||||
@ready="doSearch" >
|
@ready="doSearch" >
|
||||||
<template v-slot="{index,row}">
|
<template v-slot="{index,row}">
|
||||||
<table-column label="经办人">{{row.userName}}</table-column>
|
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||||
|
<table-column label="姓名">{{row.userName}}</table-column>
|
||||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||||
<table-column label="证明人">{{row.certifierUserName}}({{row.certifierLoginName}})</table-column>
|
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||||
<table-column label="报销类别">
|
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
|
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||||
:value="row.reimburseType">
|
<table-column label="申请状态">
|
||||||
</dict-tag>
|
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||||
</table-column>
|
</table-column>
|
||||||
<table-column label="报销项目">
|
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
|
|
||||||
:value="row.reimburseProject">
|
|
||||||
</dict-tag>
|
|
||||||
</table-column>
|
|
||||||
<table-column label="金额(元)">{{row.money}}</table-column>
|
|
||||||
<table-column label="当前节点">{{row.taskName}}</table-column>
|
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{index,row}">
|
<template #actions="{index,row}">
|
||||||
<div class="action-btn" @click="onView(row)">
|
<div class="action-btn" @click="onView(row)">
|
||||||
<i class="fa fa-eye"></i>
|
<i class="fa fa-eye"></i>
|
||||||
<span>查看</span>
|
<span>查看</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn" @click="onEdit(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">
|
<div class="action-btn" @click="onEdit(row)" v-if="row.stateId == 1 || row.stateId == 5">
|
||||||
<i class="fa fa-edit"></i>
|
<i class="fa fa-edit"></i>
|
||||||
<span>编辑</span>
|
<span>编辑</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
<div class="action-btn delete" v-if="row.stateId == 2" @click="onRevoke(row)">
|
||||||
<i class="fa fa-undo"></i>
|
<i class="fa fa-undo"></i>
|
||||||
<span>撤回</span>
|
<span>撤回</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn delete" @click="onDelete(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">
|
<div class="action-btn delete" @click="onDelete(row)" v-if="row.stateId == 1">
|
||||||
<i class="fa fa-trash"></i>
|
<i class="fa fa-trash"></i>
|
||||||
<span>删除</span>
|
<span>删除</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,7 +66,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
const vue = new Vue({
|
const vue = new Vue({
|
||||||
el: "#app",
|
el: "#app",
|
||||||
store,
|
store,
|
||||||
dicts: ["UNION_REIMBURSE_TYPE","UNION_REIMBURSE_PROJECT"],
|
dicts: ["UNION_REIMBURSE_PROJECT"],
|
||||||
components: {
|
components: {
|
||||||
"union-reimburse-info":UNION_REIMBURSE_INFO
|
"union-reimburse-info":UNION_REIMBURSE_INFO
|
||||||
},
|
},
|
||||||
@@ -78,6 +85,58 @@ layout("/layouts/platform_h5.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 手机端列表的报销项目、备注、状态文案与 PC 端 mine 列表保持一致。
|
||||||
|
getReimburseProjectName(reimburseProject) {
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "慰问"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_2") {
|
||||||
|
return "文体活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_3") {
|
||||||
|
return "日常活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_4") {
|
||||||
|
return "专项活动"
|
||||||
|
}
|
||||||
|
return reimburseProject || ""
|
||||||
|
},
|
||||||
|
getRemarkText(row) {
|
||||||
|
if (row.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "被慰问人:" + (row.condolenceUserName || "")
|
||||||
|
}
|
||||||
|
return "活动名称:" + (row.activityName || "")
|
||||||
|
},
|
||||||
|
getStateName(stateId) {
|
||||||
|
if (stateId == 1) {
|
||||||
|
return "待提交"
|
||||||
|
}
|
||||||
|
if (stateId == 2) {
|
||||||
|
return "待审核确认"
|
||||||
|
}
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "报销成功"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "拒绝"
|
||||||
|
}
|
||||||
|
if (stateId == 5) {
|
||||||
|
return "退回"
|
||||||
|
}
|
||||||
|
return stateId || ""
|
||||||
|
},
|
||||||
|
getStateClass(stateId) {
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "state-success"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "state-danger"
|
||||||
|
}
|
||||||
|
return "state-primary"
|
||||||
|
},
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
onView(row) {
|
onView(row) {
|
||||||
this.showApprovalForm = false
|
this.showApprovalForm = false
|
||||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||||
@@ -93,7 +152,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
message: "您确定要撤销申请吗?"
|
message: "您确定要撤销申请吗?"
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((resp) => {
|
this.$axios.post("/platform/unionReimburse/mine/revokeTask", {id: row.id}).then((resp) => {
|
||||||
this.$toast.success(resp.msg)
|
this.$toast.success(resp.msg)
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
})
|
})
|
||||||
|
|||||||
+81
-33
@@ -2,6 +2,19 @@
|
|||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.state-primary {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-success {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-danger {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div id="app" v-cloak>
|
<div id="app" v-cloak>
|
||||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销审核" placeholder fixed></van-nav-bar>
|
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销审核" placeholder fixed></van-nav-bar>
|
||||||
<van-sticky offset-top="46px">
|
<van-sticky offset-top="46px">
|
||||||
@@ -24,28 +37,15 @@ layout("/layouts/platform_h5.html"){
|
|||||||
<table-list api="/platform/unionReimburse/review/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
<table-list api="/platform/unionReimburse/review/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||||
@ready="doSearch">
|
@ready="doSearch">
|
||||||
<template v-slot="{index,row}">
|
<template v-slot="{index,row}">
|
||||||
<table-column label="经办人">{{row.userName}}</table-column>
|
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||||
|
<table-column label="姓名">{{row.userName}}</table-column>
|
||||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||||
<table-column label="证明人">{{row.certifierUserName}}({{row.certifierLoginName}})</table-column>
|
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||||
<table-column label="报销类别">
|
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_TYPE"
|
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||||
:value="row.reimburseType">
|
|
||||||
</dict-tag>
|
|
||||||
</table-column>
|
|
||||||
<table-column label="报销项目">
|
|
||||||
<dict-tag :options="dict.type.UNION_REIMBURSE_PROJECT"
|
|
||||||
:value="row.reimburseProject">
|
|
||||||
</dict-tag>
|
|
||||||
</table-column>
|
|
||||||
<table-column label="金额(元)">{{row.money}}</table-column>
|
|
||||||
<table-column label="申请状态">
|
<table-column label="申请状态">
|
||||||
<span v-if="row.stateId == 1" style="color: #409eff;">待提交</span>
|
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||||
<span v-else-if="row.stateId == 2" style="color: #409eff;">待审核确认</span>
|
|
||||||
<span v-else-if="row.stateId == 3" style="color: #67c23a;">报销成功</span>
|
|
||||||
<span v-else-if="row.stateId == 4" style="color: #f56c6c;">拒绝</span>
|
|
||||||
<span v-else-if="row.stateId == 5" style="color: #409eff;">退回</span>
|
|
||||||
<span v-else>{{row.stateId}}</span>
|
|
||||||
</table-column>
|
</table-column>
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{index,row}">
|
<template #actions="{index,row}">
|
||||||
@@ -79,14 +79,14 @@ layout("/layouts/platform_h5.html"){
|
|||||||
class="more-text"
|
class="more-text"
|
||||||
placeholder="请填审批意见"></van-field>
|
placeholder="请填审批意见"></van-field>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
<van-cell-group title="电子签名" class="form-section">
|
<!-- <van-cell-group title="电子签名" class="form-section">-->
|
||||||
<van-field class="more-text" name="tf_userSign" label="" required
|
<!-- <van-field class="more-text" name="tf_userSign" label="" required-->
|
||||||
v-model="formData.reviewOpinion" :rules="[{ required: true,message:'请签名' }]">
|
<!-- v-model="formData.reviewOpinion" :rules="[{ required: true,message:'请签名' }]">-->
|
||||||
<template #input>
|
<!-- <template #input>-->
|
||||||
<h5-signature v-model="formData.tf_userSign" slot="input"></h5-signature>
|
<!-- <h5-signature v-model="formData.tf_userSign" slot="input"></h5-signature>-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</van-field>
|
<!-- </van-field>-->
|
||||||
</van-cell-group>
|
<!-- </van-cell-group>-->
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<van-button type="danger" @click="handleTaskAction(5)">退回到发起人</van-button>
|
<van-button type="danger" @click="handleTaskAction(5)">退回到发起人</van-button>
|
||||||
<van-button type="danger" @click="handleTaskAction(4)">拒绝申请</van-button>
|
<van-button type="danger" @click="handleTaskAction(4)">拒绝申请</van-button>
|
||||||
@@ -124,6 +124,58 @@ layout("/layouts/platform_h5.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 手机端审核列表字段展示与我的报销列表保持一致。
|
||||||
|
getReimburseProjectName(reimburseProject) {
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "慰问"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_2") {
|
||||||
|
return "文体活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_3") {
|
||||||
|
return "日常活动"
|
||||||
|
}
|
||||||
|
if (reimburseProject === "UNION_REIMBURSE_PROJECT_4") {
|
||||||
|
return "专项活动"
|
||||||
|
}
|
||||||
|
return reimburseProject || ""
|
||||||
|
},
|
||||||
|
getRemarkText(row) {
|
||||||
|
if (row.reimburseProject === "UNION_REIMBURSE_PROJECT_1") {
|
||||||
|
return "被慰问人:" + (row.condolenceUserName || "")
|
||||||
|
}
|
||||||
|
return "活动名称:" + (row.activityName || "")
|
||||||
|
},
|
||||||
|
getStateName(stateId) {
|
||||||
|
if (stateId == 1) {
|
||||||
|
return "待提交"
|
||||||
|
}
|
||||||
|
if (stateId == 2) {
|
||||||
|
return "待审核确认"
|
||||||
|
}
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "报销成功"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "拒绝"
|
||||||
|
}
|
||||||
|
if (stateId == 5) {
|
||||||
|
return "退回"
|
||||||
|
}
|
||||||
|
return stateId || ""
|
||||||
|
},
|
||||||
|
getStateClass(stateId) {
|
||||||
|
if (stateId == 3) {
|
||||||
|
return "state-success"
|
||||||
|
}
|
||||||
|
if (stateId == 4) {
|
||||||
|
return "state-danger"
|
||||||
|
}
|
||||||
|
return "state-primary"
|
||||||
|
},
|
||||||
|
formatCreateTime(value) {
|
||||||
|
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||||
|
},
|
||||||
handleTaskAction(val) {
|
handleTaskAction(val) {
|
||||||
this.$refs.formRef.validate().then(() => {
|
this.$refs.formRef.validate().then(() => {
|
||||||
this.$dialog.confirm({
|
this.$dialog.confirm({
|
||||||
@@ -131,10 +183,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
message: "您确定要提交吗?"
|
message: "您确定要提交吗?"
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$axios.post("/platform/unionReimburse/review/reviewTask", {
|
this.$axios.post("/platform/unionReimburse/review/reviewTask", {
|
||||||
data: JSON.stringify({
|
data: JSON.stringify(Object.assign({}, this.formData)),
|
||||||
id: this.formData.id,
|
|
||||||
reviewOpinion: this.formData.reviewOpinion
|
|
||||||
}),
|
|
||||||
submitType: val
|
submitType: val
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -155,8 +204,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
this.showApprovalForm = true
|
this.showApprovalForm = true
|
||||||
this.formData = {
|
this.formData = {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
reviewOpinion: null,
|
reviewOpinion: "通过"
|
||||||
tf_userSign: null
|
|
||||||
}
|
}
|
||||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class JugTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendMsg() {
|
public void sendMsg() {
|
||||||
smsService.send("20182040", "这是一条由智慧工会系统发出的测试消息。");
|
// smsService.send("20182040", "这是一条由智慧工会系统发出的测试消息。");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user