This commit is contained in:
2026-03-08 13:45:51 +08:00
27 changed files with 926 additions and 249 deletions
+50 -5
View File
@@ -10,10 +10,10 @@
<mysql-connector-java.version>8.0.28</mysql-connector-java.version> <mysql-connector-java.version>8.0.28</mysql-connector-java.version>
<jaxb-api.version>2.3.1</jaxb-api.version> <jaxb-api.version>2.3.1</jaxb-api.version>
<slf4j.version>2.0.8</slf4j.version> <slf4j.version>2.0.8</slf4j.version>
<logback.version>1.5.8</logback.version> <logback.version>1.5.13</logback.version>
<sa-token.version>1.25.0</sa-token.version> <sa-token.version>1.25.0</sa-token.version>
<easy-captcha.version>1.6.2</easy-captcha.version> <easy-captcha.version>1.6.2</easy-captcha.version>
<commons-lang3.version>3.8.1</commons-lang3.version> <commons-lang3.version>3.18.0</commons-lang3.version>
<emoji-java.veision>4.0.0</emoji-java.veision> <emoji-java.veision>4.0.0</emoji-java.veision>
<jsoup.veision>1.15.3</jsoup.veision> <jsoup.veision>1.15.3</jsoup.veision>
<pinyin4j.veision>2.5.1</pinyin4j.veision> <pinyin4j.veision>2.5.1</pinyin4j.veision>
@@ -57,7 +57,7 @@
<version>4.35.37.ALL</version> <version>4.35.37.ALL</version>
</dependency> </dependency>
<dependency> <!--<dependency>
<groupId>org.apache.axis</groupId> <groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId> <artifactId>axis</artifactId>
<version>1.4</version> <version>1.4</version>
@@ -66,7 +66,7 @@
<groupId>org.apache.axis</groupId> <groupId>org.apache.axis</groupId>
<artifactId>axis-ant</artifactId> <artifactId>axis-ant</artifactId>
<version>1.4</version> <version>1.4</version>
</dependency> </dependency>-->
<dependency> <dependency>
<groupId>javax.xml</groupId> <groupId>javax.xml</groupId>
<artifactId>jaxrpc</artifactId> <artifactId>jaxrpc</artifactId>
@@ -102,6 +102,12 @@
<groupId>io.minio</groupId> <groupId>io.minio</groupId>
<artifactId>minio</artifactId> <artifactId>minio</artifactId>
<version>8.2.2</version> <version>8.2.2</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.activation</groupId> <groupId>javax.activation</groupId>
@@ -138,6 +144,17 @@
<groupId>org.nutz</groupId> <groupId>org.nutz</groupId>
<artifactId>nutzboot-core</artifactId> <artifactId>nutzboot-core</artifactId>
<version>${nutzboot.version}</version> <version>${nutzboot.version}</version>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.nutz</groupId> <groupId>org.nutz</groupId>
@@ -233,6 +250,18 @@
<groupId>net.unicon.cas</groupId> <groupId>net.unicon.cas</groupId>
<artifactId>cas-client-autoconfig-support</artifactId> <artifactId>cas-client-autoconfig-support</artifactId>
<version>2.3.0-GA</version> <version>2.3.0-GA</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.6.15</version>
<scope>compile</scope>
</dependency> </dependency>
<!-- html --> <!-- html -->
<dependency> <dependency>
@@ -319,12 +348,18 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.8.1</version> <version>2.9.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.uuid</groupId> <groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId> <artifactId>java-uuid-generator</artifactId>
<version>3.1.3</version> <version>3.1.3</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- <dependency> --> <!-- <dependency> -->
<!-- <groupId>org.dromara.warm</groupId> --> <!-- <groupId>org.dromara.warm</groupId> -->
@@ -376,8 +411,18 @@
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
</exclusion> </exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.0.1-jre</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
@@ -2,38 +2,138 @@ package com.budwk.app.base.sms;
import java.util.List; import java.util.List;
/**
* 短信/消息发送服务接口
* 保持参数直观可见,调用者无需查看实体类即可知晓参数含义
*/
public interface SmsService { public interface SmsService {
/** /**
* 单发 * 单发普通消息(无标题)
* @param loginName 工号 * @param loginName 接收人工号(必填)
* @param content 内容 * @param content 消息内容(必填)
* @return
*/ */
void send(String loginName, String content); void sendSingleMessage(String loginName, String content);
/** /**
* 单发 * 单发普通消息(带标题)
* @param loginName 工号 * @param loginName 接收人工号(必填)
* @param title 标题 * @param title 消息标题(可选,可为null
* @param content 内容 * @param content 消息内容(必填)
* @return
*/ */
void send(String loginName, String title, String content); void sendSingleMessage(String loginName, String title, String content);
/** /**
* 单发 * 单发文本卡片消息
* @param loginName 工号 * @param loginName 接收人工号(必填)
* @param title 标题 * @param content 卡片内容(必填)
* @param content 内容 * @param pcUrl PC端跳转链接(必填)
* @param link 链接 * @param mobileUrl 移动端跳转链接(必填)
* @return
*/ */
void send(String loginName, String title, String content, String link); void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl);
/** /**
* 群发 多人接收内容相同时使用该方法 * 单发文本卡片消息(带标题)
* @param loginNames 工号 * @param loginName 接收人工号(必填)
* @param title 标题 * @param title 卡片标题(可选,可为null
* @param content 内容 * @param content 卡片内容(必填)
* @param link 链接 * @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @return
*/ */
void massSend(List<String> loginNames, String title, String content, String link); void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl);
/**
* 单发图文卡片消息
* @param loginName 接收人工号(必填)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @param picUrl 图片链接(必填)
* @return
*/
void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl);
/**
* 单发图文卡片消息(带标题)
* @param loginName 接收人工号(必填)
* @param title 卡片标题(可选,可为null)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @param picUrl 图片链接(必填)
* @return
*/
void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl);
/**
* 群发普通消息(多人接收相同内容)
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 消息内容(必填)
* @return void
*/
void massSendMessage(List<String> loginNames, String content);
/**
* 群发普通消息(多人接收相同内容)
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param title 消息标题(可选,可为null)
* @param content 消息内容(必填)
* @return void
*/
void massSendMessage(List<String> loginNames, String title, String content);
/**
* 群发短信文本卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @return
*/
void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl);
/**
* 群发短信文本卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param title 卡片标题(可选,可为null)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @return
*/
void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl);
/**
* 群发图文卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @param picUrl 图片链接(必填)
* @return
*/
void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl);
/**
* 群发图文卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param title 卡片标题(可选,可为null)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @param picUrl 图片链接(必填)
* @return
*/
void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl);
/**
* 消息撤回
* @param msgId 消息Id
* @return
*/
void recallMsg(String msgId);
} }
@@ -1,21 +1,23 @@
package com.budwk.app.base.sms.impl.jshvc; 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 com.budwk.app.base.sms.SmsService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.todo.platform.TodoPlatformConfig;
import com.wisedu.casp.sdk.api.mc.ReceiverDto;
import com.wisedu.casp.sdk.api.mc.SendMsgRequest;
import com.wisedu.casp.sdk.api.mc.SendMsgResponse;
import com.wisedu.casp.sdk.api.mc.constants.MsgType_Constants;
import com.wisedu.casp.sdk.api.mc.constants.SendType_Constants;
import com.wisedu.casp.sdk.api.mc.constants.WxSendType_Constants;
import com.wisedu.casp.sdk.api.mc.recallMsg.RecallMsgRequest;
import com.wisedu.casp.sdk.api.mc.recallMsg.RecallMsgResponse;
import com.wisedu.casp.sdk.core.Client;
import com.wisedu.casp.sdk.core.DefaultClient;
import lombok.extern.slf4j.Slf4j; 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.ioc.loader.annotation.IocBean;
import org.nutz.json.Json; import org.nutz.json.Json;
import org.nutz.lang.Lang; import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @ClassName SmsJshvcServiceImpl * @ClassName SmsJshvcServiceImpl
@@ -28,128 +30,144 @@ import java.util.Map;
@IocBean @IocBean
public class SmsJshvcServiceImpl implements SmsService { public class SmsJshvcServiceImpl implements SmsService {
private static final String APPID = "1430576717768122368";
private static final String APP_SECRET = "19A0ACB03FBQHL4R4XQD";
private static final String TOKEN_URL = "https://gateway.jshvc.edu.cn/token/gateway/accessToken";
private static final String MSG_URL = "https://gateway.jshvc.edu.cn/mp/restful/v2/message/send";
private static final String REDIS_KEY_MSG_ACCESS_TOKEN = "msg:token:";
@Inject
private RedisService redisService;
@Override @Override
public void send(String loginName, String content) { public void sendSingleMessage(String loginName, String content) {
send(loginName, "智慧工会", content); this.sendSingleMessage(loginName, "智慧工会", content);
} }
@Override @Override
public void send(String loginName, String title, String content) { public void sendSingleMessage(String loginName, String title, String content) {
send(loginName, "智慧工会", content, null); this.massSendMessage(List.of(loginName), title, content);
} }
@Override @Override
public void send(String loginName, String title, String content, String link) { public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) {
Map<String, String> paramMap = Map.of("userId", loginName); this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl);
doSend(title, content, List.of(paramMap), link);
} }
@Override @Override
public void massSend(List<String> loginNames, String title, String content, String link) { public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) {
List<Map<String, String>> receivers = loginNames.stream() this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl);
.map(name -> Map.of("userId", name))
.toList();
doSend(title, content, receivers, link);
} }
/** @Override
* sign: 请求签名:accessToken + 第一个receivers 的userID )的32位小写的MD5加密值,其中如果相应部分没有则忽略 public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) {
* msgType: 0: 普通消息(默认) 1: 必读消息 2: 验证码(为验证码时消息一定不入收件箱) this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl);
* 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(!SecurityUtil.getUserLoginname().equals("superadmin")) {
return;
} }
@Override
public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendMessage(List<String> loginNames, String content) {
this.massSendMessage(loginNames, "智慧工会", content);
}
@Override
public void massSendMessage(List<String> loginNames, String title, String content) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT, list, title, content, null, null, null);
}
@Override
public void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl);
}
@Override
public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT_CARD, list, title, content, pcUrl, mobileUrl, null);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.NEWS, list, title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void recallMsg(String msgId) {
try {
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
RecallMsgRequest request = new RecallMsgRequest();
request.setMsgId(msgId);
log.info("撤回企业微信消息,请求参数:{}", Json.toJson(request));
RecallMsgResponse response = client.execute(request);
log.info("撤回企业微信消息,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) {
log.error("撤回企业微信消息失败", e);
}
}
private void doSend(String sendType,
List<ReceiverDto> receivers,
String title,
String content,
String pcUrl,
String mobileUrl,
String picUrl) {
if (Lang.isEmpty(receivers)) { if (Lang.isEmpty(receivers)) {
log.error("send fail by receivers is null"); log.error("send fail by receivers is null");
return; return;
} }
try {
// 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
SendMsgRequest request = new SendMsgRequest();
request.setSubject(title);
request.setContent(content);
request.setMsgType(MsgType_Constants.COMMON);
request.setSendType(SendType_Constants.WECHAT_ENTERPRISE);
request.setWxSendType(sendType);
request.setReceivers(receivers);
// 获取token if (WxSendType_Constants.TEXT_CARD.equals(sendType)) {
String accessToken = buildAccessToken(); request.setPcUrl(pcUrl);
// 获取第一个接收人的userID request.setMobileUrl(mobileUrl);
String firstUserId = receivers.get(0).get("userId"); request.setUrlDesc("查看详情");
// md5小写加密生成签名 }
String sign = DigestUtil.md5Hex(accessToken + firstUserId); if (WxSendType_Constants.NEWS.equals(sendType)) {
request.setPcUrl(pcUrl);
NutMap paramsMap = new NutMap(); request.setMobileUrl(mobileUrl);
paramsMap.put("sign", sign); request.setUrlDesc("查看详情");
paramsMap.put("msgType", "0"); request.setQyWeChatImgUrl(picUrl);
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)); log.info("发送企业微信通知,请求参数:{}", Json.toJson(request));
SendMsgResponse response = client.execute(request);
log.info("发送企业微信通知,接口响应数据:{}", Json.toJson(response));
HttpRequest request = HttpRequest.post(MSG_URL) if (response.isSuccess() && response.getStatus() == 200) {
.header("appId", APPID) // TODO 消息Id,后面可以存着,撤回要用到
.header("accessToken", accessToken) String msgId = response.getMsgId();
.body(Json.toJson(paramsMap)); log.info("发送企业微信通知成功: {}, msg: {}", response.getStatus(), response.getMsg());
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 { } else {
log.error("send error code: {}, msg: {}", bodyMap.getInt("status"), bodyMap.getString("msg")); log.info("发送企业微信通知失败:{}", response.getMsg());
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to send: {}", e.getMessage(), e); log.error("发送企业微信通知失败", 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 "";
}
} }
@@ -117,6 +117,7 @@ public class FlowTodoCenterController {
if (StrUtil.isNotBlank(searchKeyword)) { if (StrUtil.isNotBlank(searchKeyword)) {
cnd.where().andLike("ins.variable ->> '$.instanceName'", searchKeyword); cnd.where().andLike("ins.variable ->> '$.instanceName'", searchKeyword);
} }
cnd.and("t.taskName", "!=", "startTask");
cnd.desc("t.createdAt"); cnd.desc("t.createdAt");
sql.setCondition(cnd); sql.setCondition(cnd);
Pagination pagination = sysUserService.listPageMap(pageNumber, pageSize, sql); Pagination pagination = sysUserService.listPageMap(pageNumber, pageSize, sql);
@@ -1,6 +1,7 @@
package com.budwk.app.flow.listenter; package com.budwk.app.flow.listenter;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.budwk.app.flow.constant.FlowConst; import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.event.ProcessEvent; import com.budwk.app.flow.engine.event.ProcessEvent;
import com.budwk.app.flow.engine.event.ProcessEventListener; import com.budwk.app.flow.engine.event.ProcessEventListener;
@@ -9,6 +10,8 @@ import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor; import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.flow.enums.ProcessEventTypeEnum; import com.budwk.app.flow.enums.ProcessEventTypeEnum;
import com.budwk.app.todo.service.TodoService; import com.budwk.app.todo.service.TodoService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.commons.base.Globals;
import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService; import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
@@ -61,9 +64,15 @@ public class ProcessTaskStartEventListener implements ProcessEventListener {
for (ProcessTaskActor taskActor : taskActors) { for (ProcessTaskActor taskActor : taskActors) {
// 模拟发送消息 // 模拟发送消息
String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", taskActor.getActorName(), instanceName, taskDisplayName); String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", instanceName, taskDisplayName);
log.info(message); log.info(message);
globalMessageSendService.sendMessage(taskDisplayName, message, 2, List.of(taskActor.getActorId()), null); if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
break;
}
JSONObject config = new JSONObject();
config.set("pcUrl", Globals.AppDomain + task.getFormKey());
config.set("mobileUrl", Globals.AppDomain + task.getH5FormKey());
globalMessageSendService.sendMessage(taskDisplayName, message, 2, List.of(taskActor.getActorId()), config);
} }
todoService.saveTask(task); todoService.saveTask(task);
@@ -32,6 +32,8 @@ import com.budwk.app.flow.service.ProcessTaskService;
import com.budwk.app.flow.vo.HighLightVO; import com.budwk.app.flow.vo.HighLightVO;
import com.budwk.app.flow.vo.ProcessInstanceVO; import com.budwk.app.flow.vo.ProcessInstanceVO;
import com.budwk.app.flow.vo.ProcessTaskVO; import com.budwk.app.flow.vo.ProcessTaskVO;
import com.budwk.app.todo.service.TodoService;
import com.budwk.app.todo.service.impl.TodoServiceImpl;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain; import org.nutz.dao.Chain;
@@ -43,6 +45,7 @@ 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;
import org.nutz.mvc.Mvcs;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -558,6 +561,10 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
List<Long> taskIds = taskList.stream().map(ProcessTask::getId).toList(); List<Long> taskIds = taskList.stream().map(ProcessTask::getId).toList();
dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getId, "in", taskIds)); dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getId, "in", taskIds));
dao().clear(ProcessInstance.class, Cnd.where(ProcessInstance::getId, "=", processInstanceId)); dao().clear(ProcessInstance.class, Cnd.where(ProcessInstance::getId, "=", processInstanceId));
// 删除学校待办
TodoService todoService = Mvcs.getIoc().get(TodoServiceImpl.class);
todoService.deleteProcessInstance(processInstanceId.toString());
} }
@Override @Override
@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.RepeatSubmit; import com.budwk.app.base.annotation.RepeatSubmit;
import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
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.result.Result; import com.budwk.app.base.result.Result;
@@ -16,16 +17,23 @@ import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.services.SysMsgService; import com.budwk.app.sys.services.SysMsgService;
import com.budwk.app.sys.services.SysMsgUserService; import com.budwk.app.sys.services.SysMsgUserService;
import com.budwk.app.sys.services.SysUserService; import com.budwk.app.sys.services.SysUserService;
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.club.model.ClubUser;
import com.budwk.app.zhgh.club.model.SysClub;
import com.budwk.app.zhgh.club.service.SysClubService;
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 lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
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.Static; import org.nutz.dao.util.cri.Static;
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.Strings; import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
@@ -47,6 +55,8 @@ public class SysMsgController {
private SysMsgUserService sysMsgUserService; private SysMsgUserService sysMsgUserService;
@Inject @Inject
private SysUserService sysUserService; private SysUserService sysUserService;
@Inject
private SysClubService sysClubService;
@At({"/", "/list/?"}) @At({"/", "/list/?"})
@Ok("beetl:/platform/sys/msg/index.html") @Ok("beetl:/platform/sys/msg/index.html")
@@ -73,6 +83,9 @@ public class SysMsgController {
$condition $condition
"""); """);
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("msg.createdBy", "=", SecurityUtil.getUserId());
}
cnd.groupBy("msg.id"); cnd.groupBy("msg.id");
if (Strings.isNotBlank(searchType) && !"all".equals(searchType)) { if (Strings.isNotBlank(searchType) && !"all".equals(searchType)) {
cnd.and("msg.type", "=", searchType); cnd.and("msg.type", "=", searchType);
@@ -197,6 +210,28 @@ public class SysMsgController {
if (Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) { if (Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
} }
SqlExpressionGroup group = new SqlExpressionGroup();
if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
if(AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
group.or("u.unionId", "=", SecurityUtil.getUnionId());
}
if(AuthUtil.hasRoleOr(RoleConstant.CLUB_PRESIDENT.name(), RoleConstant.CLUB_MANAGER.name(),RoleConstant.CLUB_SECRETARY.name())) {
List<SysClub> myManageClub = sysClubService.getMyManageClub();
if(Lang.isNotEmpty(myManageClub)) {
List<String> list = myManageClub.stream().map(SysClub::getId).toList();
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where(ClubUser::getClubId, "in", list));
if(Lang.isNotEmpty(clubUsers)) {
List<String> clubUserList = clubUsers.stream().map(ClubUser::getUserId).distinct().toList();
group.or("u.id", "in", clubUserList);
}
}
}
}
if(!group.isEmpty()) {
cnd.and(group);
}
sql.setCondition(cnd); sql.setCondition(cnd);
return Result.success().addData(sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); return Result.success().addData(sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
} catch (Exception e) { } catch (Exception e) {
@@ -131,7 +131,7 @@ public class SysSignatureController {
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
public Result update(@Param("file") TempFile tempFile) { public Result update(@Param("file") TempFile tempFile) {
String url = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), tempFile); String url = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), tempFile);
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class); Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
if (ObjectUtil.isNull(sysUserSignature)) { if (ObjectUtil.isNull(sysUserSignature)) {
sysUserSignature = new Sys_user_signature(); sysUserSignature = new Sys_user_signature();
} }
@@ -365,6 +365,11 @@ public class SysUserController {
if (i > 0) { if (i > 0) {
pathname = pathname.substring(0, i); pathname = pathname.substring(0, i);
} }
if (pathname.contains("webvpn")) {
int platform = pathname.indexOf("/platform");
pathname = pathname.substring(platform);
}
// Sys_menu menu = sysMenuService.fetch(Cnd.where(Sys_menu::getHref, "like", pathname + "%")); // Sys_menu menu = sysMenuService.fetch(Cnd.where(Sys_menu::getHref, "like", pathname + "%"));
Sys_menu menu = sysMenuService.fetch(Cnd.where(Sys_menu::getHref, "=", pathname)); Sys_menu menu = sysMenuService.fetch(Cnd.where(Sys_menu::getHref, "=", pathname));
if (menu == null) { if (menu == null) {
@@ -57,6 +57,12 @@ public class Sys_msg extends BaseModel implements Serializable {
@Many(field = "msgId") @Many(field = "msgId")
private List<Sys_msg_user> userList; private List<Sys_msg_user> userList;
@Column
@Comment("同步企业微信")
@ColDefine(type = ColType.BOOLEAN)
@Default("0")
private Boolean wechatEnterprise;
@Column @Column
@Comment("是否需要反馈") @Comment("是否需要反馈")
@ColDefine(type = ColType.BOOLEAN) @ColDefine(type = ColType.BOOLEAN)
@@ -105,10 +105,12 @@ public class SysMsgServiceImpl extends BaseServiceImpl<Sys_msg> implements SysMs
// for (String loginName : loginNames) { // for (String loginName : loginNames) {
// smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote()); // smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote());
// } // }
if(sysMsg.getWechatEnterprise()) {
ThreadUtil.execute(() -> { ThreadUtil.execute(() -> {
//smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl()); //smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl());
smsService.massSendMessage(loginNames, HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")));
}); });
}
return sysMsg; return sysMsg;
} }
@@ -12,7 +12,9 @@ public class TodoPlatformConfig {
// token 获取 // token 获取
public static final String TOKEN_URL = "https://gateway.jshvc.edu.cn/token/gateway/accessToken"; public static final String TOKEN_URL = "https://gateway.jshvc.edu.cn/token/gateway/accessToken";
// 待办平台基础地址 // 待办平台基础地址
public static final String TODO_PLATFORM_BASE_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/saveOrUpdate"; public static final String TODO_PLATFORM_BASE_URL = "https://gateway.jshvc.edu.cn";
// 待办平台新增或者修改
public static final String TODO_PLATFORM_SAVE_OR_UPDATE_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/saveOrUpdate";
// 待办平台修改地址 // 待办平台修改地址
public static final String TODO_PLATFORM_MODIFY_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/modifyInfo"; public static final String TODO_PLATFORM_MODIFY_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/modifyInfo";
// 待办平台删除任务地址 // 待办平台删除任务地址
@@ -1,7 +1,6 @@
package com.budwk.app.todo.service; package com.budwk.app.todo.service;
import com.budwk.app.flow.entity.ProcessTask; import com.budwk.app.flow.entity.ProcessTask;
import com.wisedu.casp.sdk.api.BaseResponse;
/** /**
* @ClassName TodoService * @ClassName TodoService
@@ -12,7 +12,12 @@ import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.todo.platform.TodoPlatformConfig; import com.budwk.app.todo.platform.TodoPlatformConfig;
import com.budwk.app.todo.service.TodoService; import com.budwk.app.todo.service.TodoService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.commons.base.Globals;
import com.wisedu.casp.sdk.api.BaseResponse; import com.wisedu.casp.sdk.api.BaseResponse;
import com.wisedu.casp.sdk.api.mc.ChannelInfo;
import com.wisedu.casp.sdk.api.mc.GetEnableChannelByTypeRequest;
import com.wisedu.casp.sdk.api.mc.GetEnableChannelByTypeResponse;
import com.wisedu.casp.sdk.api.mc.constants.ChannelType_Constants;
import com.wisedu.casp.sdk.api.tdc.constants.*; import com.wisedu.casp.sdk.api.tdc.constants.*;
import com.wisedu.casp.sdk.api.tdc.model.*; import com.wisedu.casp.sdk.api.tdc.model.*;
import com.wisedu.casp.sdk.api.tdc.pushtask.ProcessInstanceRealDeleteRequest; import com.wisedu.casp.sdk.api.tdc.pushtask.ProcessInstanceRealDeleteRequest;
@@ -28,6 +33,7 @@ import org.nutz.integration.jedis.RedisService;
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;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap; import org.nutz.lang.util.NutMap;
import java.util.Arrays; import java.util.Arrays;
@@ -55,7 +61,7 @@ public class TodoServiceImpl implements TodoService {
@Override @Override
public void saveTask(ProcessTask task) { public void saveTask(ProcessTask task) {
if(!SecurityUtil.getUserLoginname().equals("superadmin")) { if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
return; return;
} }
log.info("新增待办任务,任务数据:{}", Json.toJson(task)); log.info("新增待办任务,任务数据:{}", Json.toJson(task));
@@ -66,6 +72,7 @@ public class TodoServiceImpl implements TodoService {
ProcessDefine define = dao.fetch(ProcessDefine.class, instance.getProcessDefineId()); ProcessDefine define = dao.fetch(ProcessDefine.class, instance.getProcessDefineId());
// 获取流程发起人 // 获取流程发起人
String initiatorAccount = Json.fromJson(NutMap.class, instance.getVariable()).getString(FlowConst.INITIATOR_ACCOUNT); String initiatorAccount = Json.fromJson(NutMap.class, instance.getVariable()).getString(FlowConst.INITIATOR_ACCOUNT);
String instanceName = Json.fromJson(NutMap.class, instance.getVariable()).getString("instanceName");
// 获取任务执行人 // 获取任务执行人
List<ProcessTaskActor> taskActors = dao.query(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId())); List<ProcessTaskActor> taskActors = dao.query(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId()));
List<Processor> processorList = taskActors.stream().map(o -> new Processor(o.getActorAccount())).toList(); List<Processor> processorList = taskActors.stream().map(o -> new Processor(o.getActorAccount())).toList();
@@ -79,25 +86,45 @@ public class TodoServiceImpl implements TodoService {
insertModel.setTaskId(task.getId().toString()); insertModel.setTaskId(task.getId().toString());
insertModel.setInitiatorId(initiatorAccount); insertModel.setInitiatorId(initiatorAccount);
insertModel.setInitiatorType(ProcessorType.USER_ACCOUNT); insertModel.setInitiatorType(ProcessorType.USER_ACCOUNT);
insertModel.setSubject(define.getDisplayName()); insertModel.setSubject(instanceName);
insertModel.setPriority(PriorityType.COMMON); insertModel.setPriority(PriorityType.COMMON);
insertModel.setTaskType(TaskType.COMMON); insertModel.setTaskType(TaskType.COMMON);
insertModel.setProcessors(processorList); insertModel.setProcessors(processorList);
insertModel.setProcessType(ProcessType.OR_SIGN); insertModel.setProcessType(ProcessType.OR_SIGN);
insertModel.setNodeId(task.getId().toString()); insertModel.setNodeId(task.getId().toString());
insertModel.setNodeName(task.getTaskName()); insertModel.setNodeName(task.getDisplayName());
insertModel.setPcViewUrl(task.getFormKey()); insertModel.setPcViewUrl(Globals.AppDomain + task.getFormKey());
insertModel.setH5ViewUrl(task.getH5FormKey()); insertModel.setH5ViewUrl(Globals.AppDomain + task.getH5FormKey());
// insertModel.setServiceId("xxx"); // insertModel.setServiceId("xxx");
// insertModel.setServiceName("xxx"); // insertModel.setServiceName("xxx");
// 任务关联的申请信息 // 任务关联的申请信息
ApplicationModel applicationModel = new ApplicationModel(); ApplicationModel applicationModel = new ApplicationModel();
applicationModel.setProcessInstanceId(instance.getId().toString()); applicationModel.setProcessInstanceId(instance.getId().toString());
applicationModel.setSubject(define.getDisplayName());
applicationModel.setProcessors(processorList);
applicationModel.setProcessInstanceStatus(ProcessInstanceStatusType.RUNNING);
applicationModel.setNodeId(task.getId().toString());
applicationModel.setNodeName(task.getDisplayName());
insertModel.setApplicationModel(applicationModel); insertModel.setApplicationModel(applicationModel);
request.setInsertModel(Collections.singletonList(insertModel)); request.setInsertModel(Collections.singletonList(insertModel));
/*Client channelClient = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
GetEnableChannelByTypeRequest channelByTypeRequest = new GetEnableChannelByTypeRequest();
channelByTypeRequest.setChannelType(ChannelType_Constants.QYWECHAT);
GetEnableChannelByTypeResponse channelByTypeResponse = channelClient.execute(channelByTypeRequest);
log.info("获取待办消息渠道,接口响应数据:{}", Json.toJson(channelByTypeResponse));
if (channelByTypeResponse.isSuccess()) {
List<ChannelInfo> list = channelByTypeResponse.getData();
if(Lang.isNotEmpty(list)) {
request.setIsSendMsg(1);
request.setSendChannels("1184803022838996992");
request.setWxSendType("textcard");
}
}*/
log.info("新增待办任务,请求参数:{}", Json.toJson(request));
BaseResponse response = client.execute(request); BaseResponse response = client.execute(request);
log.info("新增待办任务,接口响应数据:{}", Json.toJson(response)); log.info("新增待办任务,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) { } catch (Exception e) {
@@ -107,7 +134,7 @@ public class TodoServiceImpl implements TodoService {
@Override @Override
public void updateTask(ProcessTask task) { public void updateTask(ProcessTask task) {
if(!SecurityUtil.getUserLoginname().equals("superadmin")) { if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
return; return;
} }
log.info("更新待办任务,任务数据:{}", Json.toJson(task)); log.info("更新待办任务,任务数据:{}", Json.toJson(task));
@@ -123,7 +150,7 @@ public class TodoServiceImpl implements TodoService {
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId()); ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId());
// 创建客户端 // 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_MODIFY_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET); Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
// 创建请求对象 // 创建请求对象
SaveOrUpdateRequest request = new SaveOrUpdateRequest(); SaveOrUpdateRequest request = new SaveOrUpdateRequest();
@@ -142,11 +169,12 @@ public class TodoServiceImpl implements TodoService {
applyModel.setProcessInstanceId(instance.getId().toString()); applyModel.setProcessInstanceId(instance.getId().toString());
applyModel.setProcessInstanceStatus(ProcessInstanceStatusType.RUNNING); applyModel.setProcessInstanceStatus(ProcessInstanceStatusType.RUNNING);
applyModel.setNodeId(task.getId().toString()); applyModel.setNodeId(task.getId().toString());
applyModel.setNodeName(task.getTaskName()); applyModel.setNodeName(task.getDisplayName());
applyModel.setProcessors(processorList); applyModel.setProcessors(processorList);
updateModel.setApplyModels(Collections.singletonList(applyModel)); updateModel.setApplyModels(Collections.singletonList(applyModel));
request.setUpdateModel(updateModel); request.setUpdateModel(updateModel);
log.info("更新待办任务,请求参数:{}", Json.toJson(request));
BaseResponse response = client.execute(request); BaseResponse response = client.execute(request);
log.info("更新待办任务,接口响应数据:{}", Json.toJson(response)); log.info("更新待办任务,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) { } catch (Exception e) {
@@ -156,13 +184,13 @@ public class TodoServiceImpl implements TodoService {
@Override @Override
public void modifyInfo(ProcessTask task) { public void modifyInfo(ProcessTask task) {
if(!SecurityUtil.getUserLoginname().equals("superadmin")) { if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
return; return;
} }
log.info("修改待办任务,任务数据:{}", Json.toJson(task)); log.info("修改待办任务,任务数据:{}", Json.toJson(task));
try { try {
// 创建客户端 // 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_MODIFY_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET); Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
// 创建请求对象 // 创建请求对象
TaskModifyInfoRequest request = new TaskModifyInfoRequest(); TaskModifyInfoRequest request = new TaskModifyInfoRequest();
// 需要修改什么后面扩展吧 // 需要修改什么后面扩展吧
@@ -170,6 +198,7 @@ public class TodoServiceImpl implements TodoService {
request.setSubject("test"); request.setSubject("test");
request.setProcessors(Arrays.asList(new Processor("user01"), new Processor("user02"))); request.setProcessors(Arrays.asList(new Processor("user01"), new Processor("user02")));
log.info("修改待办任务,请求参数:{}", Json.toJson(request));
BaseResponse response = client.execute(request); BaseResponse response = client.execute(request);
log.info("修改待办任务,接口响应数据:{}", Json.toJson(response)); log.info("修改待办任务,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) { } catch (Exception e) {
@@ -179,16 +208,18 @@ public class TodoServiceImpl implements TodoService {
@Override @Override
public void deleteTask(String taskId) { public void deleteTask(String taskId) {
if(!SecurityUtil.getUserLoginname().equals("superadmin")) { if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
return; return;
} }
log.info("删除待办任务,任务ID{}", taskId); log.info("删除待办任务,任务ID{}", taskId);
try { try {
// 创建客户端 // 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_DELETE_TASK_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET); Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
// 创建请求对象 // 创建请求对象
TaskRealDeleteRequest request = new TaskRealDeleteRequest(); TaskRealDeleteRequest request = new TaskRealDeleteRequest();
request.setTaskId(taskId); request.setTaskId(taskId);
log.info("删除待办任务,请求参数:{}", Json.toJson(request));
BaseResponse response = client.execute(request); BaseResponse response = client.execute(request);
log.info("删除待办任务,接口响应数据:{}", Json.toJson(response)); log.info("删除待办任务,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) { } catch (Exception e) {
@@ -198,16 +229,18 @@ public class TodoServiceImpl implements TodoService {
@Override @Override
public void deleteProcessInstance(String processInstanceId) { public void deleteProcessInstance(String processInstanceId) {
if(!SecurityUtil.getUserLoginname().equals("superadmin")) { if (!List.of("superadmin" ,"CS2025015", "20182040").contains(SecurityUtil.getUserLoginname())) {
return; return;
} }
log.info("删除待办流程,实例ID{}", processInstanceId); log.info("删除待办流程,实例ID{}", processInstanceId);
try { try {
// 创建客户端 // 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_DELETE_INSTANCE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET); Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
// 创建请求对象 // 创建请求对象
ProcessInstanceRealDeleteRequest request = new ProcessInstanceRealDeleteRequest(); ProcessInstanceRealDeleteRequest request = new ProcessInstanceRealDeleteRequest();
request.setProcessInstanceId(processInstanceId); request.setProcessInstanceId(processInstanceId);
log.info("删除待办流程,请求参数:{}", Json.toJson(request));
BaseResponse response = client.execute(request); BaseResponse response = client.execute(request);
log.info("删除待办流程,接口响应数据:{}", Json.toJson(response)); log.info("删除待办流程,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) { } catch (Exception e) {
@@ -34,7 +34,7 @@ public class Globals {
//项目LOGO //项目LOGO
public static String AppLogo = ""; public static String AppLogo = "";
//项目域名 //项目域名
public static String AppDomain = "http://127.0.0.1"; public static String AppDomain = "https://zhgh.jshvc.edu.cn";
//文件访问域名 //文件访问域名
public static String AppFileDomain = ""; public static String AppFileDomain = "";
//学校代码 //学校代码
@@ -145,6 +145,7 @@ public class ActivityReimbursementApplyController {
args.set("outlayManageSource", activityReimbursementInfo.getOutlayManageSource()); args.set("outlayManageSource", activityReimbursementInfo.getOutlayManageSource());
args.set("actualMoney", activityReimbursementInfo.getActualMoney()); args.set("actualMoney", activityReimbursementInfo.getActualMoney());
args.set("next", activityReimbursementInfo.getReimbursementIdentity()); args.set("next", activityReimbursementInfo.getReimbursementIdentity());
args.set("clubId",activityReimbursementInfo.getClubId());
ProcessInstance instance = flowEngine.startProcessInstanceByKey("HDBX", activityReimbursementInfo.getId(), SecurityUtil.getUserId(), args); ProcessInstance instance = flowEngine.startProcessInstanceByKey("HDBX", activityReimbursementInfo.getId(), SecurityUtil.getUserId(), args);
// 自动完成第一个申请任务 // 自动完成第一个申请任务
@@ -5,14 +5,18 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.convert.NumberChineseFormatter; import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.convert.NumberWordFormatter; import cn.hutool.core.convert.NumberWordFormatter;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.annotation.SLog;
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;
import com.budwk.app.base.result.Result; import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil; import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.OfficePlusUtil;
import com.budwk.app.base.utils.PageUtil; import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.base.utils.SysOfficeTemplateUtil; import com.budwk.app.base.utils.SysOfficeTemplateUtil;
import com.budwk.app.flow.engine.FlowEngine; import com.budwk.app.flow.engine.FlowEngine;
@@ -39,6 +43,7 @@ import org.nutz.dao.util.cri.SqlExpressionGroup;
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;
import org.nutz.json.Json;
import org.nutz.lang.Lang; 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;
@@ -47,9 +52,12 @@ import org.nutz.mvc.annotation.Ok;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.*; import java.util.*;
/** /**
@@ -129,7 +137,7 @@ public class ActivityReimbursementMineController {
"""); """);
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
SqlExpressionGroup group = new SqlExpressionGroup(); SqlExpressionGroup group = new SqlExpressionGroup();
if (AuthUtil.hasPermission("activityReimbursement.apply.schoolHas")){ /*if (AuthUtil.hasPermission("activityReimbursement.apply.schoolHas")) {
group.or("info.reimbursementIdentity", "=", "school"); group.or("info.reimbursementIdentity", "=", "school");
} }
if (AuthUtil.hasPermission("activityReimbursement.apply.unionHas")) { if (AuthUtil.hasPermission("activityReimbursement.apply.unionHas")) {
@@ -143,8 +151,8 @@ public class ActivityReimbursementMineController {
clubGroup.and("info.clubId", "in", SecurityUtil.getClubIds()); clubGroup.and("info.clubId", "in", SecurityUtil.getClubIds());
clubGroup.and("info.reimbursementIdentity", "=", "club"); clubGroup.and("info.reimbursementIdentity", "=", "club");
group.or(clubGroup); group.or(clubGroup);
} }*/
if (Lang.isNotEmpty(group)){ if (!group.isEmpty()) {
cnd.and(group); cnd.and(group);
} else { } else {
cnd.and("info.userId", "=", SecurityUtil.getUserId()); cnd.and("info.userId", "=", SecurityUtil.getUserId());
@@ -207,9 +215,11 @@ public class ActivityReimbursementMineController {
Sql sql = Sqls.create(""" Sql sql = Sqls.create("""
SELECT SELECT
info.*, info.*,
us.mobile,
ins.id AS instanceId ins.id AS instanceId
FROM FROM
`activity_reimbursement_info` info `activity_reimbursement_info` info
LEFT JOIN sys_user us on us.id=info.userId
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
WHERE WHERE
ins.state = 20 AND info.id = @id ins.state = 20 AND info.id = @id
@@ -257,7 +267,13 @@ public class ActivityReimbursementMineController {
// 组合结果 // 组合结果
String actualMoneyChinese = integerChinese + decimalChinese; String actualMoneyChinese = integerChinese + decimalChinese;
info.put("actualMoney", actualMoneyChinese); info.put("bigActualMoney", actualMoneyChinese);
info.put("actualMoney", info.getString("actualMoney"));
info.put("sign", sysOfficeTemplateUtil.createPictureRenderData(info.getString("sign")));
info.put("applyTime", info.getString("applyTime").substring(0, 10));
List<NutMap> billFiles = Json.fromJsonAsList(NutMap.class, info.getString("billFiles"));
info.put("fileNum", billFiles.size());
docData.put("schoolName", Globals.AppName); docData.put("schoolName", Globals.AppName);
docData.put("info", info); docData.put("info", info);
@@ -325,68 +341,101 @@ public class ActivityReimbursementMineController {
doneTaskVos.add(taskVO); doneTaskVos.add(taskVO);
} }
List<NutMap> auditList = new ArrayList<>();
// 分工会审核 // 分工会审核
doneTaskVos.stream().filter(task -> "分工会审核".equals(task.getDisplayName())) doneTaskVos.stream().filter(task -> "分工会审核".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt)) .max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> { .ifPresent(v -> {
Dict taskFormData = v.getTaskFormData(); Dict taskFormData = v.getTaskFormData();
HashMap<String, Object> approval = new HashMap<>(); NutMap map = new NutMap();
map.put("unit", "分工会审核");
approval.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日")); map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
approval.put("user", taskFormData.getStr("tf_userName")); map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_sign"))) { if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
approval.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_sign"))); map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
} }
approval.put("opinion", taskFormData.getStr("tf_opinion")); map.put("opinion", taskFormData.getStr("tf_opinion"));
docData.put("fgh", approval); auditList.add(map);
}); });
// 协会负责人审核 // 协会负责人审核
doneTaskVos.stream().filter(task -> "协会负责人审核".equals(task.getDisplayName())) doneTaskVos.stream().filter(task -> "协会负责人审核".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt)) .max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> { .ifPresent(v -> {
Dict taskFormData = v.getTaskFormData(); Dict taskFormData = v.getTaskFormData();
HashMap<String, Object> approval = new HashMap<>(); NutMap map = new NutMap();
map.put("unit", "协会负责人审核");
approval.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日")); map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
approval.put("user", taskFormData.getStr("tf_userName")); map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_sign"))) { if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
approval.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_sign"))); map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
} }
approval.put("opinion", taskFormData.getStr("tf_opinion")); map.put("opinion", taskFormData.getStr("tf_opinion"));
docData.put("xh", approval); auditList.add(map);
}); });
// 校工会负责人审核 // 会负责人审核
doneTaskVos.stream().filter(task -> "校工会负责人审核".equals(task.getDisplayName())) doneTaskVos.stream().filter(task -> "校工会财务审核".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt)) .max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> { .ifPresent(v -> {
Dict taskFormData = v.getTaskFormData(); Dict taskFormData = v.getTaskFormData();
HashMap<String, Object> approval = new HashMap<>(); NutMap map = new NutMap();
map.put("unit", "校工会财务审核");
approval.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日")); map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
approval.put("user", taskFormData.getStr("tf_userName")); map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_sign"))) { if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
approval.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_sign"))); map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
} }
approval.put("opinion", taskFormData.getStr("tf_opinion")); map.put("opinion", taskFormData.getStr("tf_opinion"));
docData.put("xfzr", approval); auditList.add(map);
});
// 校工会负责人审核
doneTaskVos.stream().filter(task -> "校工会预审".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> {
Dict taskFormData = v.getTaskFormData();
NutMap map = new NutMap();
map.put("unit", "校工会预审");
map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
}
map.put("opinion", taskFormData.getStr("tf_opinion"));
auditList.add(map);
});
doneTaskVos.stream().filter(task -> "校工会副主席审核".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> {
Dict taskFormData = v.getTaskFormData();
NutMap map = new NutMap();
map.put("unit", "校工会副主席审核");
map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
}
map.put("opinion", taskFormData.getStr("tf_opinion"));
auditList.add(map);
}); });
// 校工会主席审核
doneTaskVos.stream().filter(task -> "校工会主席审核".equals(task.getDisplayName())) doneTaskVos.stream().filter(task -> "校工会主席审核".equals(task.getDisplayName()))
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt)) .max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
.ifPresent(v -> { .ifPresent(v -> {
Dict taskFormData = v.getTaskFormData(); Dict taskFormData = v.getTaskFormData();
HashMap<String, Object> approval = new HashMap<>(); NutMap map = new NutMap();
map.put("unit", "校工会主席审核");
approval.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日")); map.put("date", DateUtil.format(v.getFinishTime(), "yyyy年MM月dd日"));
approval.put("user", taskFormData.getStr("tf_userName")); map.put("userName", taskFormData.getStr("tf_userName"));
if (StrUtil.isNotBlank(taskFormData.getStr("tf_sign"))) { if (StrUtil.isNotBlank(taskFormData.getStr("tf_userSign"))) {
approval.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_sign"))); map.put("sign", sysOfficeTemplateUtil.createPictureRenderData(taskFormData.getStr("tf_userSign")));
} }
approval.put("opinion", taskFormData.getStr("tf_opinion")); map.put("opinion", taskFormData.getStr("tf_opinion"));
docData.put("xzx", approval); auditList.add(map);
}); });
String budgetsStr = info.getString("budgets"); String budgetsStr = info.getString("budgets");
@@ -396,17 +445,29 @@ public class ActivityReimbursementMineController {
} }
docData.put("budgets", list); docData.put("budgets", list);
docData.put("auditList", auditList);
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder() Configure config = Configure.builder()
.bind("budgets", policy) .bind("budgets", policy)
.bind("auditList", policy)
.build(); .build();
String fileName = Globals.AppName + "" + info.getString("activityName") + "】报销凭证表.docx"; String fileName = Globals.AppName + "" + info.getString("activityName") + "】报销凭证表.pdf";
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("activity_reimbursement_voucher"), config).render(docData).writeAndClose(byteArrayOutputStream); XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("activity_reimbursement_voucher"), config).render(docData).writeAndClose(byteArrayOutputStream);
CommonDownloadUtil.download(fileName, byteArrayOutputStream.toByteArray(), response);
byte[] bytes = byteArrayOutputStream.toByteArray();
File sourceFile = File.createTempFile("file_convert_origin", ".docx");
Files.write(sourceFile.toPath(), bytes, StandardOpenOption.WRITE);
File pdfFile = File.createTempFile("file_convert", ".pdf");
OfficePlusUtil.convert(sourceFile.getPath(), pdfFile.getPath());
CommonDownloadUtil.download(fileName, IoUtil.readBytes(FileUtil.getInputStream(pdfFile)), response);
// 删除临时文件
FileUtil.del(sourceFile);
FileUtil.del(pdfFile.toPath());
} catch (IOException e) { } catch (IOException e) {
log.error("报销凭证表导出失败,id:{},错误信息:{}", id, e.getMessage()); log.error("报销凭证表导出失败,id:{},错误信息:{}", id, e.getMessage());
} }
@@ -42,7 +42,7 @@ public class WechatEnterpriseMessageSendStrategy implements GlobalMessageSendStr
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return GlobalMessageSendStrategy.super.isEnabled(); return true;
} }
@Override @Override
@@ -82,6 +82,6 @@ public class WechatEnterpriseMessageSendStrategy implements GlobalMessageSendStr
return; return;
} }
List<String> list = users.stream().map(Sys_user::getLoginname).toList(); List<String> list = users.stream().map(Sys_user::getLoginname).toList();
smsService.massSend(list, title, content, ""); smsService.massSendTextCard(list, "智慧工会", content, config.getStr("pcUrl"), config.getStr("mobileUrl"));
} }
} }
@@ -1,20 +1,20 @@
<template> <template>
<div> <div>
<div class="file-preview-container" v-if="fileList && fileList.length > 0"> <div class="file-preview-container" v-if="fileList && fileList.length > 0">
<div class="file-item" title="点击查看" v-for="item in fileList" :key="item.id"> <div class="file-item" title="点击查看" v-for="(item, index) in fileList" :key="item.id">
<el-image <el-image
v-if="item.suffix === 'jpg' || item.suffix === 'png' || item.suffix === 'jpeg' || item.suffix === 'gif'" v-if="item.suffix === 'jpg' || item.suffix === 'png' || item.suffix === 'jpeg' || item.suffix === 'gif'"
:src="item.thumbnail" :src="item.thumbnail"
:fit="'cover'" :fit="'cover'"
:style="{ width: '100%', height: '100%' }" :style="{ width: '100%', height: '100%' }"
@click.stop="$commonUtil.previewFile(item)" @click.stop="onPreView(item, index)"
></el-image> ></el-image>
<el-image <el-image
v-else v-else
:src="$commonUtil.getFileItemShowIcon(item.suffix)" :src="$commonUtil.getFileItemShowIcon(item.suffix)"
:fit="'cover'" :fit="'cover'"
@click.stop="$commonUtil.previewFile(item)" @click.stop="onPreView(item, index)"
:style="{ width: '100%', height: '100%' }" :style="{ width: '100%', height: '100%' }"
></el-image> ></el-image>
@@ -25,6 +25,62 @@
</div> </div>
</div> </div>
<el-empty v-else description="暂无" :image-size="60"></el-empty> <el-empty v-else description="暂无" :image-size="60"></el-empty>
<el-drawer class="file-preview-drawer" title="附件查看" size="78%" :visible.sync="fileDialog" :append-to-body="true">
<div class="file-preview-title">附件数量{{ fileList.length }}</div>
<el-row>
<el-col :span="5">
<el-menu class="file-preview-menu" :default-active="defaultActive + ''" @select="menuSelect">
<el-menu-item v-for="(file, index) in fileList" :key="index" :index="index + ''">
<el-image
:src="$commonUtil.getFileItemShowIcon(file.suffix)"
fit="cover"
:style="{ width: '30px', height: '30px' }"
></el-image>
<span slot="title">{{ file.name }}</span>
</el-menu-item>
</el-menu>
</el-col>
<el-col :span="19" class="preview-content-col">
<div class="preview-content-wrapper">
<div class="preview-main-content" v-loading="officeLoading" element-loading-text="拼命加载中">
<el-image
v-if="file?.suffix === 'jpg' || file?.suffix === 'png' || file?.suffix === 'jpeg' || file?.suffix === 'gif'"
:src="file.downloadPath"
:fit="'cover'"
@click.stop="$commonUtil.previewFile(file)"
@load="officeLoading = false"
@error="officeLoading = false"
class="file-preview-image"
></el-image>
<div v-else style="height: 100%">
<iframe v-if="['doc', 'docx', 'xls', 'xlsx'].includes(file?.suffix)"
frameborder="0"
width="100%"
height="100%"
@load="officeLoading = false"
:src="'/assets/platform/plugins/pdfJs/web/viewer.html?file=/platform/sys/file/convertPDF?id=' + file.id"
></iframe>
<iframe v-if="['pdf'].includes(file?.suffix)"
frameborder="0"
width="100%"
height="100%"
@load="officeLoading = false"
:src="'/assets/platform/plugins/pdfJs/web/viewer.html?file=' + file.downloadPath"
></iframe>
</div>
</div>
<div class="preview-footer">
<el-button type="primary" size="small" @click="previous">上一个</el-button>
<el-button type="primary" size="small" @click="next">下一个</el-button>
<el-button type="primary" size="small" @click="fileDialog = false">关闭</el-button>
</div>
</div>
</el-col>
</el-row>
</el-drawer>
</div> </div>
</template> </template>
@@ -57,10 +113,46 @@ module.exports = {
}, },
data() { data() {
return { return {
fileList: [] fileList: [],
fileDialog: false,
defaultActive: 0,
file: {},
officeLoading: true,
} }
}, },
methods: { methods: {
next() {
this.defaultActive = Number(this.defaultActive)
if(this.defaultActive === this.fileList.length - 1) {
this.$message.error('已经是最后一个附件了')
return
}
this.defaultActive = this.defaultActive + 1
this.file = this.fileList[this.defaultActive]
},
previous() {
this.defaultActive = Number(this.defaultActive)
if(this.defaultActive === 0) {
this.$message.error('已经是第一个附件了')
return
}
this.defaultActive = this.defaultActive - 1
this.file = this.fileList[this.defaultActive]
},
menuSelect(index) {
index = Number(index)
this.defaultActive = Number(this.defaultActive)
if(index !== this.defaultActive) {
this.officeLoading = true
}
this.defaultActive = index
this.file = this.fileList[index]
},
onPreView(item, index) {
this.file = item
this.defaultActive = index
this.fileDialog = true
},
buildEchoFileObject(val) { buildEchoFileObject(val) {
let ids = [] let ids = []
if (this.complete_result) { if (this.complete_result) {
@@ -111,6 +203,76 @@ module.exports = {
} }
</script> </script>
<style>
.file-preview-drawer .el-row {
margin: 0;
height: calc(100vh - 43px - 32px - 20px - 10px);
}
.file-preview-drawer .el-col {
height: 100%;
padding: 0;
}
.file-preview-title {
padding-left: 20px;
font-weight: bold;
margin-bottom: 10px;
}
.file-preview-menu {
height: 100%;
padding-left: 10px;
}
.file-preview-menu .el-menu-item,
.file-preview-menu .el-submenu__title {
height: 40px;
line-height: 40px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.file-preview-drawer iframe {
vertical-align: bottom;
display: block;
}
.preview-content-col {
/*padding: 0 20px 10px;*/
}
.preview-content-wrapper {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.preview-main-content {
flex: 1;
overflow: auto;
margin: 0 10px 10px;
box-sizing: border-box;
}
.preview-main-content .file-preview-image {
margin: 0 auto;
max-width: 80%;
display: block;
}
.preview-footer {
line-height: 60px;
padding: 0 10px;
border-top: 1px solid #e6e6e6;
background-color: white;
text-align: right;
box-sizing: border-box;
/* position: sticky;
bottom: 0; */
}
.file-preview-drawer .el-menu-item.is-active {
font-weight: bold;
}
.file-preview-drawer .el-drawer__body {
padding: 0;
}
</style>
<style scoped> <style scoped>
.file-preview-container { .file-preview-container {
position: relative; position: relative;
@@ -0,0 +1,169 @@
<template>
<div>
<div class="file-preview-container" v-if="fileList && fileList.length > 0">
<div class="file-item" title="点击查看" v-for="item in fileList" :key="item.id">
<el-image
v-if="item.suffix === 'jpg' || item.suffix === 'png' || item.suffix === 'jpeg' || item.suffix === 'gif'"
:src="item.thumbnail"
:fit="'cover'"
:style="{ width: '100%', height: '100%' }"
@click.stop="$commonUtil.previewFile(item)"
></el-image>
<el-image
v-else
:src="$commonUtil.getFileItemShowIcon(item.suffix)"
:fit="'cover'"
@click.stop="$commonUtil.previewFile(item)"
:style="{ width: '100%', height: '100%' }"
></el-image>
<div class="file-download" title="点击下载" @click="$downLoad(item.downloadPath)">
<i class="el-icon-download"></i>
{{ item.name }}
</div>
</div>
</div>
<el-empty v-else description="暂无" :image-size="60"></el-empty>
</div>
</template>
<script>
module.exports = {
name: "sysFilePreview",
props: {
files: {
type: [String, Array],
default: undefined,
required: false
},
complete_result: {
type: Boolean,
default: false,
required: false
}
},
watch: {
files: {
handler(val) {
if (val) {
this.buildEchoFileObject(val)
} else {
this.fileList = []
}
},
immediate: true
}
},
data() {
return {
fileList: []
}
},
methods: {
buildEchoFileObject(val) {
let ids = []
if (this.complete_result) {
if (Array.isArray(val)) {
ids = val.map((item) => {
if (item.response.data.includes("=")) {
return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1)
} else {
return item?.response?.data
}
})
} else {
try {
ids = JSON.parse(val).map((item) => {
if (item.response.data.includes("=")) {
return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1)
} else {
return item?.response?.data
}
})
} catch (err) {
this.fileList = []
}
}
} else {
//那就是链接 没有直接存id的吧。。
if (Array.isArray(val)) {
ids = val.map((item) => {
return item.substring(item.lastIndexOf("=") + 1)
})
} else {
ids = val.split(",").map((item) => {
return item.substring(item.lastIndexOf("=") + 1)
})
}
}
this.requestFullFile(ids)
},
requestFullFile(ids) {
this.$axios.post("/platform/sys/file/previewFileData", { ids: JSON.stringify(ids) }).then((res) => {
if (res.code === 0) {
this.fileList = res.data
}
})
}
}
}
</script>
<style scoped>
.file-preview-container {
position: relative;
display: flex;
width: 100%;
flex-direction: row;
flex-wrap: wrap;
column-gap: 10px;
}
.file-preview-container .file-item {
width: 118px;
height: 118px;
position: relative;
transition: all 500ms;
border-radius: 5px;
cursor: pointer;
text-align: center;
column-gap: 15px;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.file-preview-container .file-item:hover {
background: rgb(230, 230, 230);
}
.file-preview-container .file-item .el-image {
width: 90px !important;
height: 100%;
transform: translateY(10px);
}
.file-preview-container .file-item .file-download {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 24px;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: white;
background-color: rgb(160, 160, 160);
border-radius: 2px;
opacity: 0.95;
}
.el-empty {
padding: 0;
}
</style>
@@ -70,10 +70,10 @@
<script src="${base!}/assets/platform/plugins/g2plot/g2plot.min.js"></script> <script src="${base!}/assets/platform/plugins/g2plot/g2plot.min.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/goober@2.1.10/dist/goober.umd.js"></script>--> <!-- <script src="https://cdn.jsdelivr.net/npm/goober@2.1.10/dist/goober.umd.js"></script>-->
<script <!--<script
type="text/javascript" type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation" src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation"
></script> ></script>-->
<script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script> <script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script>
<script nonce="${cspNonce!}"> <script nonce="${cspNonce!}">
@@ -284,9 +284,11 @@ layout("/layouts/v4/baseLayout.html"){
<!-- 表格展示 --> <!-- 表格展示 -->
<el-table v-loading="loading" :data="tasks" style="width: 100%" :key="activeTab" <el-table v-loading="loading" :data="tasks" style="width: 100%" :key="activeTab"
:header-cell-style="{backgroundColor: '#f5f7fa'}"> :header-cell-style="{backgroundColor: '#f5f7fa'}">
<el-table-column prop="instanceName" label="流程名称" min-width="180" show-overflow-tooltip></el-table-column> <el-table-column prop="instanceName" label="流程名称" min-width="180"
show-overflow-tooltip></el-table-column>
<el-table-column prop="taskName" label="任务节点" min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="taskName" label="任务节点" min-width="150" show-overflow-tooltip></el-table-column>
<el-table-column prop="categoryName" label="流程分类" min-width="150" show-overflow-tooltip></el-table-column> <el-table-column prop="categoryName" label="流程分类" min-width="150"
show-overflow-tooltip></el-table-column>
<el-table-column prop="initiatorName" label="申请人" min-width="120"> <el-table-column prop="initiatorName" label="申请人" min-width="120">
<template slot-scope="{row}">{{row.variable.initiatorName}}</template> <template slot-scope="{row}">{{row.variable.initiatorName}}</template>
</el-table-column> </el-table-column>
@@ -464,7 +466,14 @@ layout("/layouts/v4/baseLayout.html"){
this.$message.warning("当前流程没有配置地址") this.$message.warning("当前流程没有配置地址")
return return
} }
if (this.activeTab === "todo") {
window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey) window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey)
} else if (this.activeTab === "done") {
window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey)
} else {
window.open(formKey)
}
}, },
// 获取空状态文本 // 获取空状态文本
@@ -7,6 +7,15 @@ const MSG_FORM_TEMPLATE = {
</el-form-item> </el-form-item>
<el-form-item prop="url" label="链接地址"> <el-form-item prop="url" label="链接地址">
<el-input placeholder="请输入链接地址" v-model="formData.url"></el-input> <el-input placeholder="请输入链接地址" v-model="formData.url"></el-input>
</el-form-item>
<el-form-item prop="wechatEnterprise" label="同步企业微信">
<div style="color: grey; font-size: 13px">
(温馨提醒:如选择是,将会同步发送到企业微信,同时“链接地址”、“是否需要反馈”、“消息附件”可无需填写。)
</div>
<el-radio-group v-model="formData.wechatEnterprise" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item prop="needBack" label="是否需要反馈"> <el-form-item prop="needBack" label="是否需要反馈">
<el-radio-group v-model="formData.needBack" size="small"> <el-radio-group v-model="formData.needBack" size="small">
@@ -31,10 +40,9 @@ const MSG_FORM_TEMPLATE = {
<el-table-column prop="sex" label="性别" width="50"></el-table-column> <el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column> <el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="教职工类别" width="120"></el-table-column> <el-table-column prop="personType" label="教职工类别" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="编制类别" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column> <el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column> <el-table-column prop="unitname" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column> <el-table-column prop="unionname" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table> </el-table>
<p style="color: var(--color-primary)">总计:{{userTableData.length}}人</p> <p style="color: var(--color-primary)">总计:{{userTableData.length}}人</p>
</el-form-item> </el-form-item>
@@ -58,7 +66,7 @@ const MSG_FORM_TEMPLATE = {
<el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="65%" append-to-body top="2%"> <el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="65%" append-to-body top="2%">
<div class="btn-group tool-button"> <div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 300px"> <el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 240px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px"> <el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option> <el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option> <el-option label="姓名" value="u.username"></el-option>
@@ -94,10 +102,9 @@ const MSG_FORM_TEMPLATE = {
<el-table-column prop="sex" label="性别" width="50"></el-table-column> <el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column> <el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="教职工类别" width="120"></el-table-column> <el-table-column prop="personType" label="教职工类别" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="编制类别" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column> <el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column> <el-table-column prop="unitname" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column> <el-table-column prop="unionname" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table> </el-table>
<!--#include("/layouts/pagination.html"){}#--> <!--#include("/layouts/pagination.html"){}#-->
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
@@ -136,6 +143,7 @@ const MSG_FORM_TEMPLATE = {
title: [{ required: true, message: "必填", trigger: ["blur", "change"] }], title: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
note: [{ required: true, message: "必填", trigger: ["blur", "change"] }], note: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
needBack: [{ required: true, message: "必填", trigger: ["blur", "change"] }], needBack: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
wechatEnterprise: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
type: [{ required: true, message: "必填", trigger: ["blur", "change"] }] type: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
}, },
selectDialogVisible: false, selectDialogVisible: false,
@@ -216,7 +224,8 @@ const MSG_FORM_TEMPLATE = {
this.formData = { this.formData = {
id: "", id: "",
type: "user", type: "user",
needBack: false needBack: false,
wechatEnterprise: false,
} }
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields() if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
}, },
@@ -3,7 +3,7 @@ const VIEW_USER_TEMPLATE = {
<div> <div>
<el-dialog :title="viewUserTitle" :visible.sync="viewDialogVisible" width="65%" top="2%"> <el-dialog :title="viewUserTitle" :visible.sync="viewDialogVisible" width="65%" top="2%">
<div class="btn-group tool-button"> <div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" size="small" @keyup.enter.native="doSearch" style="width: 300px"> <el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" size="small" @keyup.enter.native="doSearch" style="width: 240px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px"> <el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option> <el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option> <el-option label="姓名" value="u.username"></el-option>
@@ -28,8 +28,8 @@ const VIEW_USER_TEMPLATE = {
<el-table-column prop="username" label="姓名" width="120"></el-table-column> <el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="120"></el-table-column> <el-table-column prop="sex" label="性别" width="120"></el-table-column>
<el-table-column prop="mobile" label="联系方式"></el-table-column> <el-table-column prop="mobile" label="联系方式"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column> <el-table-column prop="unitname" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column> <el-table-column prop="unionname" label="所属工会"></el-table-column>
</el-table> </el-table>
<!--#include("/layouts/pagination.html"){}#--> <!--#include("/layouts/pagination.html"){}#-->
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
@@ -186,7 +186,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
placeholder="请选择主办单位" placeholder="请选择主办单位"
style="width: 100%"> style="width: 100%">
<el-option <el-option
v-for="item in unitOptions" v-for="item in hostUnitOptions"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id"> :value="item.id">
@@ -618,6 +618,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
{prop: "unionName", label: "所属工会"} {prop: "unionName", label: "所属工会"}
], ],
hostUnitOptions: [],
unitOptions: [], unitOptions: [],
clubOptions: [], clubOptions: [],
} }
@@ -978,8 +979,11 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
this.clubOptions.map((v) => { this.clubOptions.map((v) => {
v.name = v.clubName v.name = v.clubName
}) })
const unions = await this.$businessTool.listUnion()
this.unitOptions = this.clubOptions.concat(unions)
const units = await this.$businessTool.listUnit() const units = await this.$businessTool.listUnit()
this.unitOptions = this.clubOptions.concat(units) this.hostUnitOptions = this.clubOptions.concat(units)
}, },
async queryUserByIds(ids) { async queryUserByIds(ids) {
const {data} = await this.$axios.post("/platform/activity/culture/applyActivity/queryUserByIds", {ids: JSON.stringify(ids)}) const {data} = await this.$axios.post("/platform/activity/culture/applyActivity/queryUserByIds", {ids: JSON.stringify(ids)})
@@ -255,7 +255,7 @@ layout("/layouts/platform.html"){
<el-form-item prop="billFiles" label="发票等"> <el-form-item prop="billFiles" label="发票等">
<file-upload :value.sync="formData.billFiles" <file-upload :value.sync="formData.billFiles"
upload_mode="drag" upload_mode="drag"
:upload_number="10" upload_result_category="array" :upload_number="20" upload_result_category="array"
accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png" accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png"
complete_result></file-upload> complete_result></file-upload>
</el-form-item> </el-form-item>
@@ -265,7 +265,7 @@ layout("/layouts/platform.html"){
<el-form-item prop="photoFiles" label="活动报道照片/总结/链接"> <el-form-item prop="photoFiles" label="活动报道照片/总结/链接">
<file-upload :value.sync="formData.photoFiles" <file-upload :value.sync="formData.photoFiles"
upload_mode="drag" upload_mode="drag"
:upload_number="10" upload_result_category="array" :upload_number="20" upload_result_category="array"
accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png" accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png"
complete_result></file-upload> complete_result></file-upload>
</el-form-item> </el-form-item>
@@ -275,7 +275,7 @@ layout("/layouts/platform.html"){
<el-form-item prop="otherFiles" label="奖品/纪念品/服装/道具等活动人员名单"> <el-form-item prop="otherFiles" label="奖品/纪念品/服装/道具等活动人员名单">
<file-upload :value.sync="formData.otherFiles" <file-upload :value.sync="formData.otherFiles"
upload_mode="drag" upload_mode="drag"
:upload_number="10" upload_result_category="array" :upload_number="20" upload_result_category="array"
accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png" accept=".doc, .docx, .xls, .xlsx, .pdf, .ppt, .jpg, .jpeg, .png"
complete_result></file-upload> complete_result></file-upload>
</el-form-item> </el-form-item>
@@ -100,7 +100,7 @@ layout("/layouts/platform.html"){
size="mini" type="danger">删除 size="mini" type="danger">删除
</el-button> </el-button>
<el-button @click="doExportDeclare(row)" size="mini" type="primary">申请表导出</el-button> <!-- <el-button @click="doExportDeclare(row)" size="mini" type="primary">申请表导出</el-button>-->
<el-button v-if="row.instanceState === 20" @click="doExportReimbursement(row)" size="mini" <el-button v-if="row.instanceState === 20" @click="doExportReimbursement(row)" size="mini"
type="primary">报销凭证导出 type="primary">报销凭证导出
</el-button> </el-button>
@@ -155,7 +155,7 @@ layout("/layouts/platform.html"){
methods: { methods: {
// 导出示例 // 导出示例
doExportDeclare(row) { doExportDeclare(row) {
this.$downLoad('/platform/activityDeclare/mine/doExportDeclare?id=' + row.declareId) this.$downLoad('/platform/activityDeclare/mine/doExportDeclare?id=' + row.id)
}, },
// 导出报销凭证 // 导出报销凭证
doExportReimbursement(row) { doExportReimbursement(row) {