diff --git a/JSD-9034配置使用文档.docx b/JSD-9034配置使用文档.docx new file mode 100644 index 0000000..f93c6b0 Binary files /dev/null and b/JSD-9034配置使用文档.docx differ diff --git a/JSD-9034需求确认书.docx b/JSD-9034需求确认书.docx new file mode 100644 index 0000000..49a8a86 Binary files /dev/null and b/JSD-9034需求确认书.docx differ diff --git a/README.md b/README.md index ad3ebf9..4a885a7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-9034 -JSD-9034 报表导出到服务器 \ No newline at end of file +JSD-9034 报表导出到服务器\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/lib/hutool-all-5.7.9.jar b/lib/hutool-all-5.7.9.jar new file mode 100644 index 0000000..48a68d0 Binary files /dev/null and b/lib/hutool-all-5.7.9.jar differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..466aeff --- /dev/null +++ b/plugin.xml @@ -0,0 +1,30 @@ + + + com.fr.plugin.xxxx.ndsd.export + + yes + 1.7 + 10.0 + 2018-07-31 + fr.open + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/conf/ExcelExportConfig.java b/src/main/java/com/fr/plugin/holger/ndsd/export/conf/ExcelExportConfig.java new file mode 100644 index 0000000..54c1347 --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/conf/ExcelExportConfig.java @@ -0,0 +1,64 @@ +package com.fr.plugin.xxxx.ndsd.export.conf; + +import com.fr.config.*; +import com.fr.config.xxxx.Conf; +import com.fr.config.xxxx.factory.Holders; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.record.analyzer.EnableMetrics; + + +/** + * 2 * @Author: fr.open + * 3 * @Date: 2020/12/07 15:06 + * 4 + */ +@Visualization(category = "EXCEL导出配置") +@EnableMetrics +public class ExcelExportConfig extends DefaultConfiguration { + + private static volatile ExcelExportConfig config = null; + + @Focus(id="com.fr.plugin.xxxx.ndsd.export", text = "EXCEL导出配置", source = Original.PLUGIN) + public static ExcelExportConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(ExcelExportConfig.class); + } + return config; + } + + @Identifier(value = "debugSwitch", name = "插件调试开关", description = "日志调试模式", status = Status.SHOW) + private Conf debugSwitch = Holders.simple(true); + public Boolean getdebugSwitch() { return debugSwitch.get(); } + public void setdebugSwitch(Boolean debugSwitch) { this.debugSwitch.set(debugSwitch); } + + @Identifier(value = "api_process", name = "工序上传接口", description = "数据连接名称", status = Status.SHOW) + private Conf api_process = Holders.simple("http://xxxx/{organizationId}/rda-cell-file/process/file/upload"); + public String getapi_process() { + return api_process.get(); + } + public void setapi_process(String api_process) { + this.api_process.set(api_process); + } + + @Identifier(value = "api_testItem", name = "测试项上传接口", description = "数据连接名称", status = Status.SHOW) + private Conf api_testItem = Holders.simple("http://xxxx/{organizationId}/rda-cell-file/test/item/file/upload"); + public String getapi_testItem() { + return api_testItem.get(); + } + public void setapi_testItem(String api_testItem) { + this.api_testItem.set(api_testItem); + } + + @Override + public Object clone() throws CloneNotSupportedException { + ExcelExportConfig cloned = (ExcelExportConfig) super.clone(); + + cloned.debugSwitch = (Conf) debugSwitch.clone(); + cloned.api_process = (Conf) api_process.clone(); + cloned.api_testItem = (Conf) api_testItem.clone(); + return cloned; + } + + +} diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/handler/ExcelExportHandler.java b/src/main/java/com/fr/plugin/holger/ndsd/export/handler/ExcelExportHandler.java new file mode 100644 index 0000000..8df37b5 --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/handler/ExcelExportHandler.java @@ -0,0 +1,181 @@ +package com.fr.plugin.xxxx.ndsd.export.handler; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.http.HttpRequest; +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.io.TemplateWorkBookIO; +import com.fr.io.exporter.excel.stream.StreamExcel2007Exporter; +import com.fr.json.JSONObject; +import com.fr.main.impl.WorkBook; +import com.fr.plugin.xxxx.ndsd.export.conf.ExcelExportConfig; +import com.fr.plugin.xxxx.ndsd.export.utils.LogUtils; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.stable.PageActor; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.io.FilenameUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Pattern; + + +@FunctionRecorder +public class ExcelExportHandler extends BaseHttpHandler { + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/export"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + String cptName = req.getParameter("cptName"); + String type = req.getParameter("type"); + String organizationId = req.getParameter("organizationId"); + String token = req.getParameter("token"); + LogUtils.debug4plugin("参数[cptName]值为[{}]", cptName); + LogUtils.debug4plugin("参数[type]值为[{}]]", type); + LogUtils.debug4plugin("参数[organizationId]值为[{}]]", organizationId); + LogUtils.debug4plugin("参数[token]值为[{}]]", token); + + + if (StringUtils.isBlank(cptName)) { + LogUtils.error("参数[cptName]值为空"); + WebUtils.printAsJSON(res, getResultJson("error", "参数[cptName]值为空")); + return; + } + if (StringUtils.isBlank(type) || !PATTERN_TYPE.matcher(type).matches()) { + LogUtils.error("参数[type]值为空或不合法"); + WebUtils.printAsJSON(res, getResultJson("error", "参数[type]值为空或不合法")); + return; + } + if (StringUtils.isBlank(organizationId)) { + LogUtils.error("参数[organizationId]值为空或不合法"); + WebUtils.printAsJSON(res, getResultJson("error", "参数[organizationId]值为空")); + return; + } + if (StringUtils.isBlank(token)) { + LogUtils.error("参数[token]值为空或不合法"); + WebUtils.printAsJSON(res, getResultJson("error", "参数[token]值为空")); + return; + } + + String output = getOutputAddress(cptName); + LogUtils.debug4plugin("输出临时文件地址[{}]", output); + + Map params = getParams(req); + params.forEach((k, v) -> LogUtils.debug4plugin("其它参数[{}]:[{}]", k, v)); + + try (FileOutputStream os = new FileOutputStream(output)) { + WorkBook wb = (WorkBook) TemplateWorkBookIO.readTemplateWorkBook(cptName); + StreamExcel2007Exporter exporter = new StreamExcel2007Exporter<>(); + exporter.export(os, wb.execute(params, new PageActor())); + LogUtils.debug4plugin("文件生成成功[{}]", output); + } catch (Exception e) { + LogUtils.error("文件导出失败, Cause by: ", e); + WebUtils.printAsJSON(res, getResultJson("error", "文件导出失败, Cause by: " + e.getMessage())); + return; + } + + String result = submit(output, type, params, organizationId, token); + if (StringUtils.isNotBlank(result)) { + WebUtils.printAsJSON(res, getResultJson("success", result)); + } else { + WebUtils.printAsJSON(res, getResultJson("error", "文件上传失败[" + result + "]")); + } + + try { + Path outputPath = Paths.get(output); + Files.deleteIfExists(outputPath); + } catch (Exception e) { + LogUtils.error("临时文件清理失败", e); + } + + } + + + /** + * 构造响应json + * + * @param status + * @param msg + * @return + */ + private JSONObject getResultJson(String status, String msg) { + JSONObject jsonObject = JSONObject.create(); + jsonObject.put("status", status); + jsonObject.put("msg", msg); + return jsonObject; + } + + private static final Pattern PATTERN_TYPE = Pattern.compile("process|testItem"); + + private String getOutputAddress(String cptName) { + String address = System.getProperty("java.io.tmpdir"); + if (!address.endsWith("/")) { + address += "/"; + } + return String.format("%s%s(%s).xlsx", address, FilenameUtils.getBaseName(cptName), Instant.now().toEpochMilli()); + } + + private String getApiAddress(String type, String organizationId) { + String api = null; + if (StringUtils.equalsIgnoreCase("process", type)) { + api = ExcelExportConfig.getInstance().getapi_process(); + } else if (StringUtils.equalsIgnoreCase("testItem", type)) { + api = ExcelExportConfig.getInstance().getapi_testItem(); + } + api = api.replace("{organizationId}", organizationId); + LogUtils.debug4plugin("api处理后地址[{}]", api); + return api; + } + + private Map getParams(HttpServletRequest request) { + Map params = new HashMap<>(); + Enumeration names = request.getParameterNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + if ("cptName".equals(name) || "type".equals(name)) { + continue; + } + params.put(name, request.getParameter(name)); + } + return params; + } + + private String submit(String file, String type, Map params, String organizationId, String token) throws IOException { + String apiAddress = getApiAddress(type, organizationId); + LogUtils.debug4plugin("文件上传接口请求地址[{}]", apiAddress); + HashMap paramMap = new HashMap<>(); + params.forEach((k, v) -> { + paramMap.put(k, Objects.toString(v)); + }); + LogUtils.debug4plugin("文件上传接口请求参数[{}]", paramMap); + paramMap.put("file", FileUtil.file(file)); + String result = HttpRequest.post(apiAddress).form(paramMap).header("Authorization", "Bearer " + token).execute().body(); + LogUtils.debug4plugin("文件上传接口响应报文[{}]", result); + return result; + } + +} diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/HRGT.java b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/HRGT.java new file mode 100644 index 0000000..cdf9521 --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/HRGT.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xxxx.ndsd.export.rgt; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.plugin.xxxx.ndsd.export.handler.ExcelExportHandler; +import com.fr.plugin.transform.FunctionRecorder; + +/** + * 2 * @Author: fr.open + * 3 * @Date: 2020/12/19 9:36 + * 4 + */ +@FunctionRecorder +public class HRGT extends AbstractHttpHandlerProvider { + @Override + public HttpHandler[] registerHandlers() { + return new HttpHandler[]{ + new ExcelExportHandler(), + }; + } +} diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/LRGT.java b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/LRGT.java new file mode 100644 index 0000000..8f34d15 --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/LRGT.java @@ -0,0 +1,28 @@ +package com.fr.plugin.xxxx.ndsd.export.rgt; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.xxxx.ndsd.export.conf.ExcelExportConfig; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * 配置信息初始化 + */ + +public class LRGT extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + ExcelExportConfig.getInstance(); + + } + + @Override + public void beforeStop(PluginContext pluginContext) { + } + @Override + public void beforeUninstall(PluginContext pluginContext) { + } + + @Override + public void afterInstall(PluginContext var1) { + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/URGT.java b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/URGT.java new file mode 100644 index 0000000..b456f9c --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/rgt/URGT.java @@ -0,0 +1,19 @@ +package com.fr.plugin.xxxx.ndsd.export.rgt; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +/** + * 2 * @Author: fr.open + * 3 * @Date: 2020/12/19 9:38 + * 4 + */ +public class URGT extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/export","/export",true), + }; + } +} diff --git a/src/main/java/com/fr/plugin/holger/ndsd/export/utils/LogUtils.java b/src/main/java/com/fr/plugin/holger/ndsd/export/utils/LogUtils.java new file mode 100644 index 0000000..4d39dc0 --- /dev/null +++ b/src/main/java/com/fr/plugin/holger/ndsd/export/utils/LogUtils.java @@ -0,0 +1,117 @@ +package com.fr.plugin.xxxx.ndsd.export.utils; + +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xxxx.ndsd.export.conf.ExcelExportConfig; +import com.fr.stable.StringUtils; + +public final class LogUtils { + private static final String DEBUG_PREFIX = "[插件调试] "; + private static String LOG_PREFIX = "[EXCEL导出] "; + private static final String PLUGIN_VERSION; + + private static final FineLoggerProvider LOGGER = FineLoggerFactory.getLogger(); + + static { + String version = PluginContexts.currentContext().getMarker().getVersion(); + if (StringUtils.isNotBlank(version)) { + PLUGIN_VERSION = "[v" + version + "] "; + } else { + PLUGIN_VERSION = "[unknown version] "; + } + + LOG_PREFIX = LOG_PREFIX + PLUGIN_VERSION; + } + + public static void setPrefix(String prefix) { + if (prefix != null) { + LOG_PREFIX = prefix; + } + } + + public static boolean isDebugEnabled() { + return LOGGER.isDebugEnabled(); + } + + public static void debug(String s) { + LOGGER.debug(LOG_PREFIX + s); + } + + public static void debug(String s, Object... objects) { + LOGGER.debug(LOG_PREFIX + s, objects); + } + + public static void debug(String s, Throwable throwable) { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + + public static void debug4plugin(String s) { + if (ExcelExportConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s); + } else { + LOGGER.debug(LOG_PREFIX + s); + } + } + + public static void debug4plugin(String s, Object... objects) { + if (ExcelExportConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, objects); + } else { + LOGGER.debug(LOG_PREFIX + s, objects); + } + } + + public static void debug4plugin(String s, Throwable throwable) { + if (ExcelExportConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, throwable); + } else { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + } + + + public static boolean isInfoEnabled() { + return LOGGER.isInfoEnabled(); + } + + public static void info(String s) { + LOGGER.info(LOG_PREFIX + s); + } + + public static void info(String s, Object... objects) { + LOGGER.info(LOG_PREFIX + s, objects); + } + + public static void warn(String s) { + LOGGER.warn(LOG_PREFIX + s); + } + + public static void warn(String s, Object... objects) { + LOGGER.warn(LOG_PREFIX + s, objects); + } + + public static void warn(String s, Throwable throwable) { + LOGGER.warn(LOG_PREFIX + s, throwable); + } + + public static void warn(Throwable throwable, String s, Object... objects) { + LOGGER.warn(throwable, LOG_PREFIX + s, objects); + } + + public static void error(String s) { + LOGGER.error(LOG_PREFIX + s); + } + + public static void error(String s, Object... objects) { + LOGGER.error(LOG_PREFIX + s, objects); + } + + public static void error(String s, Throwable throwable) { + LOGGER.error(LOG_PREFIX + s, throwable); + } + + public static void error(Throwable throwable, String s, Object... objects) { + LOGGER.error(throwable, LOG_PREFIX + s, objects); + } +} diff --git a/src/main/resources/export.properties b/src/main/resources/export.properties new file mode 100644 index 0000000..0ab4934 --- /dev/null +++ b/src/main/resources/export.properties @@ -0,0 +1,3 @@ +api.organizationId=-1 +api.process=http://xxxx/{organizationId}/rda-cell-file/process/file/upload +api.testItem=http://xxxx/{organizationId}/rda-cell-file/test/item/file/upload \ No newline at end of file