LAPTOP-SB56SG4Q\86185
3 years ago
19 changed files with 1017 additions and 1 deletions
Binary file not shown.
Binary file not shown.
@ -1,3 +1,6 @@
|
||||
# open-JSD-8415 |
||||
|
||||
JSD-8415 开源任务材料 |
||||
JSD-8415 定时任务OA推送\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin> |
||||
<id>com.fr.plugin.schedule.oa</id> |
||||
<name><![CDATA[定时调度推送]]></name> |
||||
<active>yes</active> |
||||
<version>1.4</version> |
||||
<env-version>10.0</env-version> |
||||
<jartime>2018-07-31</jartime> |
||||
<vendor>fr.open</vendor> |
||||
<description><![CDATA[定时调度推送]]></description> |
||||
<change-notes><![CDATA[ |
||||
[2021-08-17]【1.0】初始化插件。<br/> |
||||
[2021-08-17]【1.1】增加标题参数逻辑,修改提交表单的问题。<br/> |
||||
[2021-08-17]【1.2】增加标题参数逻辑,修改提交表单文本编码的问题。<br/> |
||||
[2021-08-17]【1.3】修改获取标题的逻辑,支持公式。<br/> |
||||
[2021-08-17]【1.4】增加支持多用户独立调度。<br/> |
||||
]]></change-notes> |
||||
<lifecycle-monitor class="com.fr.plugin.schedule.oa.OutputPluginLifecycleMonitor"/> |
||||
<extra-core> |
||||
<LocaleFinder class="com.fr.plugin.schedule.oa.config.PluginLocaleFinderBridge"/> |
||||
</extra-core> |
||||
<extra-decision> |
||||
<WebResourceProvider class="com.fr.plugin.schedule.oa.js.JSCSSBridge"/> |
||||
<DecisionDBAccessProvider class="com.fr.plugin.schedule.oa.OaOutputDBAccess"/> |
||||
</extra-decision> |
||||
<function-recorder class="com.fr.plugin.schedule.oa.js.JSCSSBridge"/> |
||||
</plugin> |
@ -0,0 +1,310 @@
|
||||
package com.fr.plugin.schedule.oa; |
||||
|
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.third.org.apache.http.HttpResponse; |
||||
import com.fr.third.org.apache.http.HttpStatus; |
||||
import com.fr.third.org.apache.http.client.HttpClient; |
||||
import com.fr.third.org.apache.http.client.methods.HttpPost; |
||||
import com.fr.third.org.apache.http.config.Registry; |
||||
import com.fr.third.org.apache.http.config.RegistryBuilder; |
||||
import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; |
||||
import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; |
||||
import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
||||
import com.fr.third.org.apache.http.entity.StringEntity; |
||||
import com.fr.third.org.apache.http.impl.client.HttpClients; |
||||
import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
||||
import com.fr.third.org.apache.http.util.EntityUtils; |
||||
|
||||
import javax.net.ssl.*; |
||||
import java.io.*; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.net.URLEncoder; |
||||
import java.security.cert.CertificateException; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class HttpUtil { |
||||
|
||||
private static HostnameVerifier hv = new HostnameVerifier() { |
||||
@Override |
||||
public boolean verify(String urlHostName, SSLSession session) { |
||||
System.out.println("Warning: URL Host: " + urlHostName + " vs. " |
||||
+ session.getPeerHost()); |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* 发送get请求 |
||||
* |
||||
* @param url |
||||
* @param param |
||||
* @param header |
||||
* @return |
||||
* @throws IOException |
||||
*/ |
||||
public static String sendGet(String url, Map<String, String> param, Map<String, String> header) { |
||||
String result = ""; |
||||
BufferedReader in = null; |
||||
String urlNameString = url; |
||||
try { |
||||
if (param != null) { |
||||
urlNameString += "?"; |
||||
urlNameString += param.entrySet() |
||||
.stream() |
||||
.map(entry -> entry.getKey() + "=" + entry.getValue()) |
||||
.collect(Collectors.joining("&")); |
||||
} |
||||
|
||||
URL realUrl = new URL(urlNameString); |
||||
// 打开和URL之间的连接
|
||||
HttpURLConnection connection; |
||||
if (url.startsWith("https")) { |
||||
trustAllHttpsCertificates(); |
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv); |
||||
connection = (HttpURLConnection) realUrl.openConnection(); |
||||
} else { |
||||
connection = (HttpURLConnection) realUrl.openConnection(); |
||||
} |
||||
//设置超时时间
|
||||
connection.setDoInput(true); |
||||
connection.setRequestMethod("GET"); |
||||
connection.setConnectTimeout(5000); |
||||
connection.setReadTimeout(15000); |
||||
// 设置通用的请求属性
|
||||
if (header != null) { |
||||
Iterator<Map.Entry<String, String>> it = header.entrySet().iterator(); |
||||
while (it.hasNext()) { |
||||
Map.Entry<String, String> entry = it.next(); |
||||
System.out.println(entry.getKey() + ":::" + entry.getValue()); |
||||
connection.setRequestProperty(entry.getKey(), entry.getValue()); |
||||
} |
||||
} |
||||
connection.setRequestProperty("accept", "*/*"); |
||||
connection.setRequestProperty("connection", "Keep-Alive"); |
||||
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); |
||||
// 建立实际的连接
|
||||
connection.connect(); |
||||
// 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); |
||||
String line; |
||||
while ((line = in.readLine()) != null) { |
||||
result += line; |
||||
} |
||||
if (in != null) { |
||||
in.close(); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e, "get url error ,url is:{},error is {}", urlNameString, e.getMessage()); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public static String sendPost(String url, Map<String, Object> header, JSONObject body) { |
||||
PrintWriter out = null; |
||||
BufferedReader in = null; |
||||
String result = null; |
||||
String res = null; |
||||
try { |
||||
String urlNameString = url; |
||||
|
||||
URL realUrl = new URL(urlNameString); |
||||
// 打开和URL之间的连接
|
||||
HttpURLConnection conn; |
||||
if (url.startsWith("https")) { |
||||
trustAllHttpsCertificates(); |
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv); |
||||
conn = (HttpURLConnection) realUrl.openConnection(); |
||||
} else { |
||||
conn = (HttpURLConnection) realUrl.openConnection(); |
||||
} |
||||
// 设置通用的请求属性
|
||||
conn.setRequestProperty("accept", "*/*"); |
||||
conn.setRequestProperty("connection", "Keep-Alive"); |
||||
// conn.setRequestProperty("user-agent",
|
||||
// "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
||||
if (header != null) { |
||||
header.forEach((k, v) -> { |
||||
conn.setRequestProperty(k, String.valueOf(v)); |
||||
}); |
||||
} |
||||
// 发送POST请求必须设置如下两行
|
||||
conn.setDoOutput(true); |
||||
conn.setDoInput(true); |
||||
//获取请求头
|
||||
|
||||
// 获取URLConnection对象对应的输出流
|
||||
out = new PrintWriter(conn.getOutputStream()); |
||||
// 发送请求参数
|
||||
if (body != null) { |
||||
FineLoggerFactory.getLogger().error("content data: {}", body.toString()); |
||||
FineLoggerFactory.getLogger().error("content cover data: {}", new String(body.toString().getBytes("UTF-8"), "UTF-8")); |
||||
out.print(new String(body.toString().getBytes("UTF-8"), "UTF-8")); |
||||
} |
||||
// flush输出流的缓冲
|
||||
out.flush(); |
||||
// 定义BufferedReader输入流来读取URL的响应
|
||||
in = new BufferedReader( |
||||
new InputStreamReader(conn.getInputStream(),"UTF-8")); |
||||
String line; |
||||
while ((line = in.readLine()) != null) { |
||||
result += line; |
||||
} |
||||
res = result; |
||||
if (res.startsWith("null")) { |
||||
res = res.replace("null", ""); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
//使用finally块来关闭输出流、输入流
|
||||
finally { |
||||
try { |
||||
if (out != null) { |
||||
out.close(); |
||||
} |
||||
if (in != null) { |
||||
in.close(); |
||||
} |
||||
} catch (IOException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
|
||||
public static String doPost(String url, Map<String, Object> header, JSONObject json) { |
||||
HttpClient client = HttpClients.createDefault(); |
||||
if (url.startsWith("https")) { |
||||
SSLContext sslcontext = createIgnoreVerifySSL(); |
||||
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() |
||||
.register("http", PlainConnectionSocketFactory.INSTANCE) |
||||
.register("https", new SSLConnectionSocketFactory(sslcontext)) |
||||
.build(); |
||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); |
||||
HttpClients.custom().setConnectionManager(connManager); |
||||
client = HttpClients.custom().setConnectionManager(connManager).build(); |
||||
} |
||||
HttpPost post = new HttpPost(url); |
||||
post.setHeader("accept", "*/*"); |
||||
post.setHeader("connection", "Keep-Alive"); |
||||
post.setHeader("Content-Type", "application/json"); |
||||
if (header != null) { |
||||
header.forEach((k, v) -> { |
||||
post.setHeader(k, String.valueOf(v)); |
||||
}); |
||||
} |
||||
try { |
||||
StringEntity s = new StringEntity(json.toString(),"UTF-8"); |
||||
s.setContentEncoding("UTF-8"); |
||||
s.setContentType("application/json; charset=UTF-8");//发送json数据需要设置contentType
|
||||
post.setEntity(s); |
||||
HttpResponse res = client.execute(post); |
||||
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { |
||||
String result = EntityUtils.toString(res.getEntity());// 返回json格式:
|
||||
return result; |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(),e); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static void trustAllHttpsCertificates() throws Exception { |
||||
TrustManager[] trustAllCerts = new TrustManager[1]; |
||||
TrustManager tm = new miTM(); |
||||
trustAllCerts[0] = tm; |
||||
SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE"); |
||||
sc.init(null, trustAllCerts, null); |
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* encode url by UTF-8 |
||||
* |
||||
* @param url url before encoding |
||||
* @return url after encoding |
||||
*/ |
||||
public static String encodeUrl(String url) { |
||||
String eurl = url; |
||||
try { |
||||
eurl = URLEncoder.encode(url, "UTF-8"); |
||||
} catch (UnsupportedEncodingException e) { |
||||
} |
||||
return eurl; |
||||
} |
||||
|
||||
private static class miTM implements TrustManager, |
||||
X509TrustManager { |
||||
@Override |
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
||||
return null; |
||||
} |
||||
|
||||
public boolean isServerTrusted( |
||||
java.security.cert.X509Certificate[] certs) { |
||||
return true; |
||||
} |
||||
|
||||
public boolean isClientTrusted( |
||||
java.security.cert.X509Certificate[] certs) { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void checkServerTrusted( |
||||
java.security.cert.X509Certificate[] certs, String authType) |
||||
throws CertificateException { |
||||
return; |
||||
} |
||||
|
||||
@Override |
||||
public void checkClientTrusted( |
||||
java.security.cert.X509Certificate[] certs, String authType) |
||||
throws CertificateException { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
public static SSLContext createIgnoreVerifySSL() { |
||||
try { |
||||
SSLContext sc = SSLContext.getInstance("SSLv3"); |
||||
|
||||
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
|
||||
X509TrustManager trustManager = new X509TrustManager() { |
||||
@Override |
||||
public void checkClientTrusted( |
||||
java.security.cert.X509Certificate[] paramArrayOfX509Certificate, |
||||
String paramString) throws CertificateException { |
||||
} |
||||
|
||||
@Override |
||||
public void checkServerTrusted( |
||||
java.security.cert.X509Certificate[] paramArrayOfX509Certificate, |
||||
String paramString) throws CertificateException { |
||||
} |
||||
|
||||
@Override |
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
||||
return null; |
||||
} |
||||
}; |
||||
|
||||
sc.init(null, new TrustManager[]{trustManager}, null); |
||||
return sc; |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
package com.fr.plugin.schedule.oa; |
||||
|
||||
import com.fr.plugin.schedule.oa.entity.OaOutPutEntity; |
||||
import com.fr.stable.db.dao.BaseDAO; |
||||
import com.fr.stable.db.session.DAOSession; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class OaOutPutDao extends BaseDAO<OaOutPutEntity> { |
||||
public OaOutPutDao(DAOSession daoSession) { |
||||
super(daoSession); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.fr.plugin.schedule.oa; |
||||
|
||||
import com.fr.decision.plugin.db.AbstractDecisionDBAccessProvider; |
||||
import com.fr.plugin.schedule.oa.entity.OaOutPutEntity; |
||||
import com.fr.stable.db.accessor.DBAccessor; |
||||
import com.fr.stable.db.dao.BaseDAO; |
||||
import com.fr.stable.db.dao.DAOProvider; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class OaOutputDBAccess extends AbstractDecisionDBAccessProvider { |
||||
|
||||
private static DBAccessor dbAccessor; |
||||
public DBAccessor getDbAccessor() { |
||||
return dbAccessor; |
||||
} |
||||
|
||||
@Override |
||||
public DAOProvider[] registerDAO() { |
||||
return new DAOProvider[]{ |
||||
new DAOProvider() { |
||||
@Override |
||||
public Class getEntityClass() { |
||||
return OaOutPutEntity.class; |
||||
} |
||||
|
||||
@Override |
||||
public Class<? extends BaseDAO> getDAOClass() { |
||||
return OaOutPutDao.class; |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
|
||||
@Override |
||||
public void onDBAvailable(DBAccessor dbAccessor) { |
||||
OaOutputDBAccess.dbAccessor = dbAccessor; |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
package com.fr.plugin.schedule.oa; |
||||
|
||||
import com.fr.plugin.context.PluginContext; |
||||
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||
import com.fr.plugin.schedule.oa.config.OutputSimpleConfig; |
||||
import com.fr.plugin.schedule.oa.entity.OaOutPutEntity; |
||||
import com.fr.plugin.schedule.oa.entity.OaOutputAction; |
||||
import com.fr.plugin.schedule.oa.format.PNGOutputFormat; |
||||
import com.fr.plugin.schedule.oa.handle.OaOutPutHandle; |
||||
import com.fr.schedule.extension.report.job.output.BaseOutputFormat; |
||||
import com.fr.schedule.feature.ScheduleOutputActionEntityRegister; |
||||
import com.fr.schedule.feature.output.OutputActionHandler; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class OutputPluginLifecycleMonitor extends AbstractPluginLifecycleMonitor { |
||||
@Override |
||||
public void afterRun(PluginContext pluginContext) { |
||||
OutputSimpleConfig.getInstance(); |
||||
BaseOutputFormat.registerOutputFormat(new PNGOutputFormat()); |
||||
OutputActionHandler.registerHandler(new OaOutPutHandle(), OaOutputAction.class.getName()); |
||||
ScheduleOutputActionEntityRegister.getInstance().addClass(OaOutPutEntity.class); |
||||
} |
||||
|
||||
@Override |
||||
public void beforeStop(PluginContext pluginContext) { |
||||
BaseOutputFormat.removeOutputFormat(PNGOutputFormat.CONVERT_TO_PNG); |
||||
OutputActionHandler.removeOutputHandler(OaOutputAction.class.getName()); |
||||
ScheduleOutputActionEntityRegister.getInstance().removeClass(OaOutPutEntity.class); |
||||
} |
||||
} |
@ -0,0 +1,117 @@
|
||||
package com.fr.plugin.schedule.oa.config; |
||||
|
||||
import com.fr.config.*; |
||||
import com.fr.config.holder.Conf; |
||||
import com.fr.config.holder.factory.Holders; |
||||
import com.fr.intelli.record.Focus; |
||||
import com.fr.intelli.record.Original; |
||||
import com.fr.record.analyzer.EnableMetrics; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
@Visualization(category = "Plugin-Config_Output") |
||||
@EnableMetrics |
||||
public class OutputSimpleConfig extends DefaultConfiguration { |
||||
|
||||
private static final String TOKEN_URL="{sfurl}/seeyon/rest/token/{username}/{password}?loginName={account}"; |
||||
|
||||
private static final String ATTACH_URL="{sfurl}/seeyon/rest/attachment"; |
||||
|
||||
private static final String FORM_URL="{sfurl}/seeyon/rest/initia/flowFrom"; |
||||
|
||||
private static volatile OutputSimpleConfig config = null; |
||||
@Identifier(value = "sfUrl", name = "Plugin-Config_Property_sfUrl", description = "Plugin-Config_Property_sfUrl_Description", status = Status.SHOW) |
||||
private Conf<String> sfUrl = Holders.simple(StringUtils.EMPTY); |
||||
@Identifier(value = "username", name = "Plugin-Config_Property_username", description = "Plugin-Config_Property_username_Description", status = Status.SHOW) |
||||
private Conf<String> username = Holders.simple(StringUtils.EMPTY); |
||||
|
||||
@Identifier(value = "password", name = "Plugin-Config_Property_password", description = "Plugin-Config_Property_password_Description", status = Status.SHOW) |
||||
private Conf<String> password = Holders.simple(StringUtils.EMPTY); |
||||
|
||||
@Identifier(value = "account", name = "Plugin-Config_Property_account", description = "Plugin-Config_Property_account_Description", status = Status.SHOW) |
||||
private Conf<String> account = Holders.simple(StringUtils.EMPTY); |
||||
|
||||
@Identifier(value = "tabledata", name = "Plugin-Config_Property_tabledata", description = "Plugin-Config_Property_tabledata_Description", status = Status.SHOW) |
||||
private Conf<String> tabledata = Holders.simple(StringUtils.EMPTY); |
||||
|
||||
|
||||
@Focus(id = "com.fr.plugin.schedule.oa", text = "Plugin-Config_Output", source = Original.PLUGIN) |
||||
public static OutputSimpleConfig getInstance() { |
||||
if (config == null) { |
||||
config = ConfigContext.getConfigInstance(OutputSimpleConfig.class); |
||||
} |
||||
return config; |
||||
} |
||||
|
||||
public String getSfUrl() { |
||||
return sfUrl.get(); |
||||
} |
||||
|
||||
public void setSfUrl(String sfUrl) { |
||||
this.sfUrl.set(sfUrl); |
||||
} |
||||
|
||||
public String getUsername() { |
||||
return username.get(); |
||||
} |
||||
|
||||
public void setUsername(String username) { |
||||
this.username.set(username); |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password.get(); |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password.set(password); |
||||
} |
||||
|
||||
public String getAccount() { |
||||
return account.get(); |
||||
} |
||||
|
||||
public void setAccount(String account) { |
||||
this.account.set(account); |
||||
} |
||||
|
||||
public String getTabledata() { |
||||
return tabledata.get(); |
||||
} |
||||
|
||||
public void setTabledata(String tabledata) { |
||||
this.tabledata.set(tabledata); |
||||
} |
||||
|
||||
public boolean isAccept() { |
||||
return StringUtils.isNotBlank(getSfUrl()) && StringUtils.isNotBlank(getUsername()) && StringUtils.isNotBlank(getPassword()) |
||||
&& StringUtils.isNotBlank(getAccount()) && StringUtils.isNotBlank(getTabledata()); |
||||
} |
||||
|
||||
public String tokenUrl(){ |
||||
return TOKEN_URL.replace("{sfurl}",getSfUrl()).replace("{username}",getUsername()).replace("{password}",getPassword()) |
||||
.replace("{account}",getAccount()); |
||||
} |
||||
|
||||
public String attachUrl(){ |
||||
return ATTACH_URL.replace("{sfurl}",getSfUrl()); |
||||
} |
||||
public String formUrl(){ |
||||
return FORM_URL.replace("{sfurl}",getSfUrl()); |
||||
} |
||||
|
||||
@Override |
||||
public Object clone() throws CloneNotSupportedException { |
||||
OutputSimpleConfig cloned = (OutputSimpleConfig) super.clone(); |
||||
cloned.sfUrl = (Conf<String>) sfUrl.clone(); |
||||
cloned.username = (Conf<String>) username.clone(); |
||||
cloned.password = (Conf<String>) password.clone(); |
||||
cloned.account = (Conf<String>) account.clone(); |
||||
cloned.tabledata = (Conf<String>) tabledata.clone(); |
||||
return cloned; |
||||
} |
||||
} |
@ -0,0 +1,14 @@
|
||||
package com.fr.plugin.schedule.oa.config; |
||||
|
||||
import com.fr.stable.fun.impl.AbstractLocaleFinder; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class PluginLocaleFinderBridge extends AbstractLocaleFinder { |
||||
@Override |
||||
public String find() { |
||||
return "com/fr/plugin/schedule/oa/locale/conf"; |
||||
} |
||||
} |
@ -0,0 +1,43 @@
|
||||
package com.fr.plugin.schedule.oa.entity; |
||||
|
||||
import com.fr.schedule.base.bean.BaseBean; |
||||
import com.fr.schedule.base.entity.AbstractScheduleEntity; |
||||
import com.fr.stable.db.entity.TableAssociation; |
||||
import com.fr.third.javax.persistence.Entity; |
||||
import com.fr.third.javax.persistence.Table; |
||||
|
||||
/** |
||||
* @Author fr.open |
||||
* @Date 2021/8/14 |
||||
* @Description |
||||
**/ |
||||
@Entity |
||||
@Table(name = "fine_output_oa") //表名
|
||||
@TableAssociation(associated = true) |
||||
public class OaOutPutEntity extends AbstractScheduleEntity { |
||||
|
||||
private Integer pushImg; |
||||
|
||||
@Override |
||||
public BaseBean createBean() { |
||||
return new OaOutputAction().id(this.getId()).pushImg(getPushImg()); |
||||
} |
||||
|
||||
public OaOutPutEntity id(String id) { |
||||
setId(id); |
||||
return this; |
||||
} |
||||
|
||||
public OaOutPutEntity pushImg(Integer pushImg) { |
||||
setPushImg(pushImg); |
||||
return this; |
||||
} |
||||
|
||||
public Integer getPushImg() { |
||||
return pushImg; |
||||
} |
||||
|
||||
public void setPushImg(Integer pushImg) { |
||||
this.pushImg = pushImg; |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
package com.fr.plugin.schedule.oa.entity; |
||||
|
||||
import com.fr.schedule.base.bean.output.BaseOutputAction; |
||||
import com.fr.schedule.base.entity.AbstractScheduleEntity; |
||||
import com.fr.schedule.base.type.RunType; |
||||
import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes; |
||||
|
||||
/** |
||||
* @Author fr.open |
||||
* @Date 2021/8/14 |
||||
* @Description |
||||
**/ |
||||
@JsonSubTypes.Type(value = OaOutputAction.class, name = "OaOutputAction") |
||||
public class OaOutputAction extends BaseOutputAction { |
||||
|
||||
private static final long serialVersionUID = -2455866100756916542L; |
||||
|
||||
private Integer pushImg; |
||||
|
||||
@Override |
||||
public boolean willExecuteByUser() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public RunType runType() { |
||||
return RunType.SEND_FILE; |
||||
} |
||||
|
||||
@Override |
||||
public OaOutputAction id(String id) { |
||||
setId(id); |
||||
return this; |
||||
} |
||||
|
||||
public OaOutputAction pushImg(Integer pushImg){ |
||||
setPushImg(pushImg); |
||||
return this; |
||||
} |
||||
|
||||
public Integer getPushImg() { |
||||
return pushImg; |
||||
} |
||||
|
||||
public void setPushImg(Integer pushImg) { |
||||
this.pushImg = pushImg; |
||||
} |
||||
|
||||
@Override |
||||
public Class<? extends AbstractScheduleEntity> outputActionEntityClass() { |
||||
return OaOutPutEntity.class; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractScheduleEntity createOutputActionEntity() { |
||||
return new OaOutPutEntity().id(this.getId()).pushImg(getPushImg()); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
package com.fr.plugin.schedule.oa.format; |
||||
|
||||
import com.fr.io.exporter.ImageExporter; |
||||
import com.fr.main.workbook.ResultWorkBook; |
||||
import com.fr.schedule.extension.report.job.output.BaseOutputFormat; |
||||
|
||||
import java.io.OutputStream; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class PNGOutputFormat extends BaseOutputFormat { |
||||
public static final int CONVERT_TO_PNG = 64; |
||||
|
||||
public PNGOutputFormat() { |
||||
} |
||||
|
||||
@Override |
||||
public int getFormat() { |
||||
return CONVERT_TO_PNG; |
||||
} |
||||
|
||||
@Override |
||||
public String getFileSuffix() { |
||||
return ".png"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean withParentPath() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void flushWithParentPath(OutputStream outputStream, ResultWorkBook workBook, String name, final List<String> list) throws Exception { |
||||
new ImageExporter("png", 96).export(outputStream, workBook); |
||||
} |
||||
} |
@ -0,0 +1,145 @@
|
||||
package com.fr.plugin.schedule.oa.handle; |
||||
|
||||
import com.fr.base.Formula; |
||||
import com.fr.base.TableData; |
||||
import com.fr.file.TableDataConfig; |
||||
import com.fr.general.data.DataModel; |
||||
import com.fr.general.http.HttpRequest; |
||||
import com.fr.general.http.HttpToolbox; |
||||
import com.fr.io.utils.ResourceIOUtils; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.schedule.oa.config.OutputSimpleConfig; |
||||
import com.fr.plugin.schedule.oa.entity.OaOutputAction; |
||||
import com.fr.schedule.base.constant.ScheduleConstants; |
||||
import com.fr.schedule.feature.output.OutputActionHandler; |
||||
import com.fr.script.Calculator; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.third.org.apache.http.entity.ContentType; |
||||
import com.fr.third.org.apache.http.entity.StringEntity; |
||||
import com.fr.third.org.apache.http.entity.mime.HttpMultipartMode; |
||||
import com.fr.third.org.apache.http.entity.mime.MultipartEntityBuilder; |
||||
|
||||
import java.nio.charset.Charset; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class OaOutPutHandle extends OutputActionHandler<OaOutputAction> { |
||||
|
||||
@Override |
||||
public void doAction(OaOutputAction output, Map<String, Object> map) throws Exception { |
||||
OutputSimpleConfig instance = OutputSimpleConfig.getInstance(); |
||||
//Object aaa = getTitle(map);
|
||||
if (!instance.isAccept()) { |
||||
FineLoggerFactory.getLogger().error("current task config is null"); |
||||
return; |
||||
} |
||||
String tokenRes = HttpToolbox.get(instance.tokenUrl()); |
||||
FineLoggerFactory.getLogger().info("get token res is {}", tokenRes); |
||||
JSONObject object = new JSONObject(tokenRes); |
||||
String token = object.getString("id"); |
||||
String[] files = (String[]) map.get(ScheduleConstants.OUTPUT_FILES); |
||||
List<String> ids = new ArrayList<>(); |
||||
String attach = instance.attachUrl() + "?token=" + token; |
||||
String imageFile = StringUtils.EMPTY; |
||||
for (String file : files) { |
||||
MultipartEntityBuilder entity = MultipartEntityBuilder.create(); |
||||
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); |
||||
entity.setCharset(Charset.forName("UTF-8")); |
||||
//内容类型,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件
|
||||
ContentType OCTEC_STREAM = ContentType.create("application/octet-stream", Charset.forName("UTF-8")); |
||||
//添加文件
|
||||
entity.addBinaryBody("file", ResourceIOUtils.readBytes(file), OCTEC_STREAM, file.substring(file.lastIndexOf("/")+ 1)); |
||||
String res = HttpToolbox.executeAndParse(HttpRequest.custom().url(attach).post(entity.build()).build()); |
||||
FineLoggerFactory.getLogger().info("upload attach res is {}", res); |
||||
JSONObject attachRes = new JSONObject(res); |
||||
String fileUrl = attachRes.getJSONArray("atts").getJSONObject(0).getString("fileUrl"); |
||||
if (file.endsWith(".png")) { |
||||
imageFile = fileUrl; |
||||
} else { |
||||
ids.add(fileUrl); |
||||
} |
||||
} |
||||
|
||||
String formUrl = instance.formUrl() + "?token=" + token; |
||||
String[] usernames = (String[]) map.get(ScheduleConstants.USERNAMES); |
||||
String username = (String) map.get(ScheduleConstants.USERNAME); |
||||
Set<String> users; |
||||
if (StringUtils.isNotBlank(username)) { |
||||
users = new HashSet<>(); |
||||
users.add(username); |
||||
} else { |
||||
users = new HashSet(Arrays.asList(usernames)); |
||||
} |
||||
Iterator<String> it = users.iterator(); |
||||
String tabledata = instance.getTabledata(); |
||||
TableData tableData = TableDataConfig.getInstance().getTableData(tabledata); |
||||
DataModel dataModel = tableData.createDataModel(Calculator.createCalculator()); |
||||
while (it.hasNext()) { |
||||
String next = it.next(); |
||||
String dept = getDept(dataModel, next); |
||||
if (StringUtils.isBlank(dept)) { |
||||
FineLoggerFactory.getLogger().warn("current user {} has not dept", next); |
||||
continue; |
||||
} |
||||
JSONObject formBody = new JSONObject(); |
||||
formBody.put("undertakeDept", dept).put("undertakeName", next) |
||||
.put("title",getTitle(map)); |
||||
if (StringUtils.isNotBlank(imageFile)) { |
||||
if (output.getPushImg() == 0) { |
||||
formBody.put("imageFile", imageFile); |
||||
} else if (output.getPushImg() == 1) { |
||||
ids.add(imageFile); |
||||
formBody.put("attacFile", com.fr.third.org.apache.commons.lang3.StringUtils.join(ids, ",")); |
||||
} else if (output.getPushImg() == 2) { |
||||
formBody.put("imageFile", imageFile); |
||||
ids.add(imageFile); |
||||
formBody.put("attacFile", com.fr.third.org.apache.commons.lang3.StringUtils.join(ids, ",")); |
||||
} |
||||
} |
||||
StringEntity entity = new StringEntity(formBody.toString(),"UTF-8"); |
||||
entity.setContentEncoding("UTF-8"); |
||||
entity.setContentType("application/json; charset=UTF-8"); |
||||
FineLoggerFactory.getLogger().info("send form url is{},body is {}", formUrl, formBody); |
||||
String res = HttpToolbox.executeAndParse(HttpRequest.custom().url(formUrl).post(entity).build()); |
||||
FineLoggerFactory.getLogger().info("send form res is {}", res); |
||||
FineLoggerFactory.getLogger().info("execute finish"); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
private Object getTitle(Map<String, Object> map) { |
||||
List<Map> list = (List) map.get(ScheduleConstants.RECORD_LIST); |
||||
Object title = StringUtils.EMPTY; |
||||
Object param = list.get(0).get("title"); |
||||
if(param instanceof Formula){ |
||||
Formula formula = (Formula)param; |
||||
title = formula.getResult(); |
||||
}else { |
||||
title = param; |
||||
} |
||||
if(title ==null || StringUtils.isBlank(title.toString())){ |
||||
title = (String) map.get(ScheduleConstants.TASK_NAME); |
||||
} |
||||
return title; |
||||
} |
||||
|
||||
private String getDept(DataModel dataModel, String username) { |
||||
try { |
||||
for (int i = 0; i < dataModel.getRowCount(); i++) { |
||||
Object valueAt = dataModel.getValueAt(i, 1); |
||||
if (valueAt != null && StringUtils.equals(String.valueOf(valueAt), username)) { |
||||
return String.valueOf(dataModel.getValueAt(i, 0)); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
|
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.fr.plugin.schedule.oa.js; |
||||
|
||||
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||
import com.fr.web.struct.Component; |
||||
import com.fr.web.struct.Filter; |
||||
import com.fr.web.struct.browser.RequestClient; |
||||
import com.fr.web.struct.category.ScriptPath; |
||||
import com.fr.web.struct.category.StylePath; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class FileDef extends Component { |
||||
public static final FileDef KEY = new FileDef(); |
||||
private FileDef(){} |
||||
/** |
||||
* 返回需要引入的JS脚本路径 |
||||
* @param client 请求客户端描述 |
||||
* @return JS脚本路径 |
||||
*/ |
||||
@Override |
||||
public ScriptPath script(RequestClient client ) { |
||||
//如果不需要就直接返回 ScriptPath.EMPTY
|
||||
return ScriptPath.build("com/fr/plugin/schedule/oa/theme.js"); |
||||
} |
||||
|
||||
/** |
||||
* 返回需要引入的CSS样式路径 |
||||
* @param client 请求客户端描述 |
||||
* @return CSS样式路径 |
||||
*/ |
||||
@Override |
||||
public StylePath style(RequestClient client ) { |
||||
//如果不需要就直接返回 StylePath.EMPTY;
|
||||
return StylePath.EMPTY; |
||||
} |
||||
|
||||
/** |
||||
* 通过给定的资源过滤器控制是否加载这个资源 |
||||
* @return 资源过滤器 |
||||
*/ |
||||
@ExecuteFunctionRecord |
||||
@Override |
||||
public Filter filter() { |
||||
return new Filter(){ |
||||
@Override |
||||
public boolean accept() { |
||||
//任何情况下我们都在平台组件加载时加载我们的组件
|
||||
return true; |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
package com.fr.plugin.schedule.oa.js; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractWebResourceProvider; |
||||
import com.fr.decision.web.MainComponent; |
||||
import com.fr.plugin.transform.FunctionRecorder; |
||||
import com.fr.web.struct.Atom; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
@FunctionRecorder |
||||
public class JSCSSBridge extends AbstractWebResourceProvider { |
||||
@Override |
||||
public Atom attach() { |
||||
//在平台主组件加载时添加我们自己的组件
|
||||
return MainComponent.KEY; |
||||
} |
||||
|
||||
@Override |
||||
public Atom client() { |
||||
//我们自己要引入的组件
|
||||
return FileDef.KEY; |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
Plugin-Config_Output=Plugin Schedule |
||||
Plugin-Config_Property_sfUrl=ip:port |
||||
Plugin-Config_Property_sfUrl_Description=ip port info example is http://xxxx:xxx |
||||
Plugin-Config_Property_username=username |
||||
Plugin-Config_Property_username_Description=get token username |
||||
Plugin-Config_Property_password=password |
||||
Plugin-Config_Property_password_Description=get token password |
||||
Plugin-Config_Property_account=get token account |
||||
Plugin-Config_Property_account_Description=account |
||||
Plugin-Config_Property_tabledata=user tabledata |
||||
Plugin-Config_Property_tabledata_Description=user tabledata |
@ -0,0 +1,11 @@
|
||||
Plugin-Config_Output=\u5B9A\u65F6\u8C03\u5EA6\u63A8\u9001 |
||||
Plugin-Config_Property_sfUrl=\u5730\u5740\u4FE1\u606F |
||||
Plugin-Config_Property_sfUrl_Description=\u63A8\u9001\u5730\u5740\u7AEF\u53E3\u4FE1\u606F \u4F8B\u5982http://xxx:xxx |
||||
Plugin-Config_Property_username=\u8D26\u53F7 |
||||
Plugin-Config_Property_username_Description=\u83B7\u53D6token\u7684\u8D26\u53F7 |
||||
Plugin-Config_Property_password=\u5BC6\u7801 |
||||
Plugin-Config_Property_password_Description=\u83B7\u53D6token\u7684\u5BC6\u7801 |
||||
Plugin-Config_Property_account=\u767B\u5F55\u540D |
||||
Plugin-Config_Property_account_Description=\u83B7\u53D6token\u7684\u767B\u5F55\u540D |
||||
Plugin-Config_Property_tabledata=\u6620\u5C04\u6570\u636E\u96C6 |
||||
Plugin-Config_Property_tabledata_Description=\u6620\u5C04\u7528\u6237\u5173\u7CFB\u6570\u636E\u96C6 |
@ -0,0 +1,71 @@
|
||||
!(function () { |
||||
BI.config("dec.provider.schedule", function (provider) { |
||||
provider.registerTaskAttached({ |
||||
value: 64, |
||||
text: "png" |
||||
}, [DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); |
||||
}); |
||||
|
||||
var Plugin = BI.inherit(BI.Widget, { |
||||
props: { |
||||
baseCls: "", |
||||
value: { |
||||
pushImg: 0, |
||||
} |
||||
}, |
||||
render: function () { |
||||
var t = this, |
||||
e = this.options.value[0]==undefined?{pushImg: 0}: this.options.value[0]; |
||||
return { |
||||
type: "bi.flex_vertical", |
||||
tgap: 15, |
||||
items: [{ |
||||
type: "dec.label.editor.item", |
||||
errorTop: 16, |
||||
textCls: "dec-font-weight-bold", |
||||
text: "pushImg", |
||||
textWidth: 115, |
||||
editorWidth: 300, |
||||
value: e.pushImg, |
||||
ref: function(e) { |
||||
t.pushImg = e |
||||
} |
||||
}] |
||||
}; |
||||
}, |
||||
/** |
||||
* |
||||
* |
||||
* @returns {boolean} |
||||
*/ |
||||
validation: function () { |
||||
var e = !0, |
||||
t = this.isVisible(); |
||||
return BI.isEmpty(this.pushImg.getValue()) && (t && this.pushImg.showError(BI.i18nText("Dec-Error_Null")), e = !1), |
||||
e |
||||
}, |
||||
/** |
||||
* |
||||
* outputActionList |
||||
* @returns {{}} |
||||
*/ |
||||
getValue: function() { |
||||
var _self= this; |
||||
return {OutputWebHook: BI.extend(_self.value,{ |
||||
"@class": "com.fr.plugin.schedule.oa.entity.OaOutputAction", |
||||
actionName: "com.fr.plugin.schedule.oa.entity.OaOutputAction", |
||||
pushImg: _self.pushImg.getValue(), |
||||
})} |
||||
}, |
||||
}); |
||||
BI.shortcut("dec.schedule.task.file.handling.plugin", Plugin); |
||||
|
||||
BI.config("dec.provider.schedule", function (provider) { |
||||
provider.registerHandingWay({ |
||||
text: "oa推送", |
||||
value: "com.fr.plugin.schedule.oa.entity.OaOutputAction", // actionName
|
||||
cardType: "dec.schedule.task.file.handling.plugin", |
||||
actions: [] // action
|
||||
}, [DecCst.Schedule.TaskType.DEFAULT, DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); |
||||
}); |
||||
}()); |
Loading…
Reference in new issue