diff --git a/README.md b/README.md index bc5580e..d962401 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-8491 -JSD-8491 平台功能扩展 开源任务材料 \ No newline at end of file +JSD-8491 平台功能扩展 开源任务材料\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/lib/finekit-10.0.jar b/lib/finekit-10.0.jar new file mode 100644 index 0000000..611c8f5 Binary files /dev/null and b/lib/finekit-10.0.jar differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..0b9a3be --- /dev/null +++ b/plugin.xml @@ -0,0 +1,21 @@ + + com.fr.plugin.third.party.jsdiejb + + yes + 0.8 + 10.0 + 2019-01-01 + fr.open + + + + * + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/components/FileDef.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/components/FileDef.java new file mode 100644 index 0000000..324101f --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/components/FileDef.java @@ -0,0 +1,54 @@ +package com.fr.plugin.third.party.jsdiejb.components; + +import com.fanruan.api.log.LogKit; +import com.fr.plugin.context.PluginContexts; +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; + + +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) { + return ScriptPath.build("com/fr/plugin/third/party/jsdiejb/web/main.js"); + } + + /** + * 返回需要引入的CSS样式路径 + * @param client 请求客户端描述 + * @return CSS样式路径 + */ + @Override + public StylePath style(RequestClient client) { +// //如果不需要就直接返回 StylePath.EMPTY; + return StylePath.build("com/fr/plugin/third/party/jsdiejb/web/main.css"); + //return StylePath.EMPTY; + } + + + @Override + public Filter filter() { + return new Filter(){ + public boolean accept() { + //添加认证 + if (!PluginContexts.currentContext().isAvailable()) { + LogKit.error("The jsdiejb plugin trial is over, please purchase a license"); + return false; + } + //任何情况下我们都在平台组件加载时加载我们的组件 + return true; + } + }; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/components/WebResourceProvider.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/components/WebResourceProvider.java new file mode 100644 index 0000000..7076946 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/components/WebResourceProvider.java @@ -0,0 +1,18 @@ +package com.fr.plugin.third.party.jsdiejb.components; + +import com.fr.decision.fun.impl.AbstractWebResourceProvider; +import com.fr.decision.web.MainComponent; +import com.fr.stable.fun.Authorize; +import com.fr.web.struct.Atom; +@Authorize(callSignKey = "com.fr.plugin.third.party.jsdiejb") +public class WebResourceProvider extends AbstractWebResourceProvider { + @Override + public Atom attach() { + return MainComponent.KEY; + } + + @Override + public Atom client() { + return FileDef.KEY; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/config/CustomDataConfig.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/config/CustomDataConfig.java new file mode 100644 index 0000000..f79f668 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/config/CustomDataConfig.java @@ -0,0 +1,117 @@ +package com.fr.plugin.third.party.jsdiejb.config; + + +import com.fanruan.api.util.StringKit; +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; + +/** + * 配置数据保存 + */ +@Visualization(category = "悬浮球配置") +public class CustomDataConfig extends DefaultConfiguration { + public String getNameSpace() { + return this.getClass().getName(); + } + + private static volatile CustomDataConfig config = null; + + public static CustomDataConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(CustomDataConfig.class); + } + return config; + } + + @Identifier(value = "reportTitle", name = "报表标题", description = "", status = Status.SHOW) + private Conf reportTitle = Holders.simple(StringKit.EMPTY); + + @Identifier(value = "reportUrl", name = "报表链接", description = "", status = Status.SHOW) + private Conf reportUrl = Holders.simple(StringKit.EMPTY); + + + @Identifier(value = "reportWidth", name = "报表显示宽度", description = "", status = Status.SHOW) + private Conf reportWidth = Holders.simple(800); + + + @Identifier(value = "reportHeight", name = "报表显示高度", description = "", status = Status.SHOW) + private Conf reportHeight = Holders.simple(600); + + + @Identifier(value = "iconWidth", name = "图标宽度", description = "", status = Status.SHOW) + private Conf iconWidth = Holders.simple(40); + + @Identifier(value = "iconName", name = "图标名称", description = "", status = Status.HIDE) + private Conf iconName = Holders.simple(StringKit.EMPTY); + + public String getIconName() { + return iconName.get(); + } + + public void setIconName(String iconName) { + this.iconName.set(iconName); + } + + public Integer getIconWidth() { + return iconWidth.get(); + } + + public void setIconWidth(Integer iconWidth) { + this.iconWidth.set(iconWidth); + } + + public String getReportTitle() { + return trimStr(reportTitle.get()); + } + + public void setReportTitle(String reportTitle) { + this.reportTitle.set(reportTitle); + } + + public String getReportUrl() { + return trimStr(reportUrl.get()); + } + + public void setReportUrl(String reportUrl) { + this.reportUrl.set(reportUrl); + } + + public Integer getReportWidth() { + return reportWidth.get(); + } + + public void setReportWidth(Integer reportWidth) { + this.reportWidth.set(reportWidth); + } + + public Integer getReportHeight() { + return reportHeight.get(); + } + + public void setReportHeight(Integer reportHeight) { + this.reportHeight.set(reportHeight); + } + + + @Override + public Object clone() throws CloneNotSupportedException { + CustomDataConfig cloned = (CustomDataConfig) super.clone(); + cloned.reportTitle = (Conf) reportTitle.clone(); + cloned.reportUrl = (Conf) reportUrl.clone(); + cloned.reportWidth = (Conf) reportWidth.clone(); + cloned.reportHeight = (Conf) reportHeight.clone(); + cloned.iconWidth = (Conf) iconWidth.clone(); + cloned.iconName = (Conf) iconName.clone(); + return cloned; + } + + private String trimStr(String value) { + if (StringKit.isEmpty(value)) { + return ""; + } + String tempValue = value.trim(); + return tempValue; + } + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/config/DataConfigInitializeMonitor.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/config/DataConfigInitializeMonitor.java new file mode 100644 index 0000000..154f3fb --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/config/DataConfigInitializeMonitor.java @@ -0,0 +1,23 @@ +package com.fr.plugin.third.party.jsdiejb.config; + +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; +import com.fr.plugin.third.party.jsdiejb.config.CustomDataConfig; +import com.fr.record.analyzer.EnableMetrics; + + +@EnableMetrics +public class DataConfigInitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + @Focus(id = "com.fr.plugin.third.party.jsdiejb", text = "plugin-jsd-iejb", source = Original.PLUGIN) + public void afterRun(PluginContext pluginContext) { + CustomDataConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomConfigHttpHandler.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomConfigHttpHandler.java new file mode 100644 index 0000000..ea20ae3 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomConfigHttpHandler.java @@ -0,0 +1,53 @@ +package com.fr.plugin.third.party.jsdiejb.http; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.decision.webservice.bean.user.UserDataSetBean; +import com.fr.decision.webservice.v10.config.ConfigService; +import com.fr.decision.webservice.v10.user.SyncService; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.json.JSONObject; +import com.fr.plugin.third.party.jsdiejb.config.CustomDataConfig; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.controller.common.ResourcesRequestService; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + */ +public class CustomConfigHttpHandler extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/jsdiejb/config"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + res.setContentType("application/json; charset=utf-8"); + JSONObject configJson = new JSONObject(); + configJson.put("reportTitle", CustomDataConfig.getInstance().getReportTitle()); + configJson.put("reportUrl", CustomDataConfig.getInstance().getReportUrl()); + configJson.put("reportWidth", CustomDataConfig.getInstance().getReportWidth()); + configJson.put("reportHeight", CustomDataConfig.getInstance().getReportHeight()); + configJson.put("iconWidth", CustomDataConfig.getInstance().getIconWidth()); + //configJson.put("iconName", CustomDataConfig.getInstance().getIconName()); + WebUtils.printAsJSON(res, configJson); + } + + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomHttpHandlerProvider.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomHttpHandlerProvider.java new file mode 100644 index 0000000..f895452 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomHttpHandlerProvider.java @@ -0,0 +1,14 @@ +package com.fr.plugin.third.party.jsdiejb.http; + +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.decision.fun.impl.BaseHttpHandler; + +public class CustomHttpHandlerProvider extends AbstractHttpHandlerProvider { + @Override + public BaseHttpHandler[] registerHandlers() { + return new BaseHttpHandler[]{ + new CustomConfigHttpHandler(), + new ResourcesHttpHandler() + }; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomURLAliasProvider.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomURLAliasProvider.java new file mode 100644 index 0000000..8a9e3f6 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/CustomURLAliasProvider.java @@ -0,0 +1,15 @@ +package com.fr.plugin.third.party.jsdiejb.http; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +public class CustomURLAliasProvider extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/jsdiejb/config", "/jsdiejb/config", true), + URLAliasFactory.createPluginAlias("/jsdiejb/resources", "/jsdiejb/resources", true) + }; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdiejb/http/ResourcesHttpHandler.java b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/ResourcesHttpHandler.java new file mode 100644 index 0000000..42515e0 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdiejb/http/ResourcesHttpHandler.java @@ -0,0 +1,101 @@ +package com.fr.plugin.third.party.jsdiejb.http; + +import com.fr.base.TemplateUtils; +import com.fr.base.Utils; +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.decision.webservice.utils.WebServiceUtils; +import com.fr.general.IOUtils; +import com.fr.json.JSONObject; +import com.fr.plugin.third.party.jsdiejb.config.CustomDataConfig; +import com.fr.stable.StableUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.ResourceType; +import com.fr.web.controller.common.ResourceUtils; +import com.fr.web.core.gzip.GZIPResponseWrapper; +import com.fr.web.utils.WebUtils; +import com.fr.workspace.WorkContext; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.util.Collections; + +/** + * + */ +public class ResourcesHttpHandler extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/jsdiejb/resources"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + String path = WebUtils.getHTTPRequestParameter(req, "path"); + if (path != null) { + path = path.endsWith("?") ? path.substring(0, path.length() - 1) : path; + } + + ResourceType var4 = WebUtils.setResourceContentType(path, (HttpServletResponse) res); + if (var4 == ResourceType.FILE || var4 == ResourceType.OTHER) { + GZIPResponseWrapper var5 = WebServiceUtils.getGZIPResponseWrapper(req, (HttpServletResponse) res); + if (var5 != null) { + res = var5; + } + InputStream var6 = readResourceByWeb(path); + if (var6 != null) { + switch (var4) { + case FILE: + PrintWriter var7 = WebUtils.createPrintWriter((HttpServletResponse) res); + TemplateUtils.dealWithTemplate(var6, "UTF-8", var7, Collections.EMPTY_MAP); + var7.flush(); + var7.close(); + break; + case OTHER: + ServletOutputStream var8 = ((HttpServletResponse) res).getOutputStream(); + Utils.copyBinaryTo(var6, var8); + var8.flush(); + var8.close(); + } + + var6.close(); + if (var5 != null) { + var5.finishResponse(); + } + + } + } + } + + public static InputStream readResourceByWeb(String path) throws Exception { + if ((path == null) || (path.length() <= 0)) { + return null; + } + File var1 = new File(path); + if (var1.exists()) { + String var4 = WorkContext.getCurrent().getPath(); + String var3 = (new File(var4)).getParent(); + return var1.getAbsolutePath().startsWith(var3) ? new FileInputStream(var1) : null; + } + path = path.startsWith("/") ? path : "/" + path; + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(WorkContext.getWorkResource().readFully(StableUtils.pathJoin(new String[]{"resources", path}))); + if (byteArrayInputStream.available() >= 1) { + return byteArrayInputStream; + } + + InputStream inputStream = IOUtils.readResource(path); + return inputStream; + } +} diff --git a/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.css b/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.css new file mode 100644 index 0000000..441b676 --- /dev/null +++ b/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.css @@ -0,0 +1,29 @@ +.jsdiejb-ball { + position: absolute; + width: 50px; + height: 50px; + background-repeat: no-repeat; + background-size: cover; + z-index: 100001; + top: 80px; + right: 0px; +} + +.jsdiejb-report-content { + position: absolute; + width: 800px; + height: 600px; + z-index: 100000; + top: 25%; + left: 25%; + display: none; + background-color: white; + border-width: 0px; + overflow: hidden; +} + +.jsdiejb-report-iframe { + width: 100%; + height: 100%; + border-width: 0px; +} \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.js b/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.js new file mode 100644 index 0000000..85fb38e --- /dev/null +++ b/src/main/resources/com/fr/plugin/third/party/jsdiejb/web/main.js @@ -0,0 +1,173 @@ +Dec.Utils = Dec.Utils || {}; +Dec.Utils.jsdiejb = Dec.Utils.jsdiejb || {}; + +Dec.Utils.jsdiejb.config = {}; +Dec.Utils.jsdiejb.openOption = 0; +Dec.Utils.jsdiejb.openOptionSrc = 0; + +BI.extend(Dec.Utils.jsdiejb, { + getConfig: function (e) { + Dec.reqGet("/url/jsdiejb/config", "", e) + }, + dragendBall: function (e) { + e.preventDefault ? e.preventDefault() : (e.returnValue = false); + //debugger; + //console.log(e); + var x = e.clientX; + var y = e.clientY; + + var maxLeft = $('body').width() - 100; + var maxTop = $('body').height() - 100; + if (maxLeft <= 0) { + maxLeft = 0; + } + if (maxTop <= 0) { + maxTop = 0; + } + var leftValue = x; + var topValue = y; + if (leftValue <= 0) { + leftValue = 0; + } + if (topValue <= 0) { + topValue = 0; + } + + if (leftValue > maxLeft) { + leftValue = maxLeft; + } + + if (topValue > maxTop) { + topValue = maxTop; + } + + $('.jsdiejb-ball').css("left", leftValue + "px"); + $('.jsdiejb-ball').css("top", topValue + "px"); + }, + resizeBall: function () { + //debugger; + var maxLeft = $('body').width() - 100; + var maxTop = $('body').height() - 100; + if (maxLeft <= 0) { + maxLeft = 0; + } + if (maxTop <= 0) { + maxTop = 0; + } + var leftValue = $('.jsdiejb-ball').position().left; + var topValue = $('.jsdiejb-ball').position().top; + if (leftValue <= 0) { + leftValue = 0; + } + if (topValue <= 0) { + topValue = 0; + } + + if (leftValue > maxLeft) { + leftValue = maxLeft; + } + + if (topValue > maxTop) { + topValue = maxTop; + } + + $('.jsdiejb-ball').css("left", leftValue + "px"); + $('.jsdiejb-ball').css("top", topValue + "px"); + }, + openUrl: function (e) { + //if (e.button != 2) { + // return; + //} + e.preventDefault ? e.preventDefault() : (e.returnValue = false); + e.cancelBubble = true + e.returnValue = false; + + + if (Dec.Utils.jsdiejb.openOption == 1) { + Dec.Utils.jsdiejb.openOption = 0; + $('.jsdiejb-report-content').css('display', "none"); + return; + } + var url = Dec.Utils.jsdiejb.config.reportUrl; + var width = Dec.Utils.jsdiejb.config.reportWidth; + var height = Dec.Utils.jsdiejb.config.reportHeight; + if (width < 0) { + width = 800; + } + if (height < 0) { + height = 600; + } + var widthValue = width + "px"; + var heightValue = height + "px"; + + var left = ($('body').width() - width) / 2; + var top = ($('body').height() - height) / 2; + + left = $('.jsdiejb-ball').position().left - width; + top = $('.jsdiejb-ball').position().top; + if (left < 0) { + left = 0; + } + if (top < 0) { + top = 0; + } + var leftValue = left + "px"; + var topValue = top + "px"; + if ((url != undefined) && (url.length > 0)) { + Dec.Utils.jsdiejb.openOption = 1; + $('.jsdiejb-report-content').css('display', "block"); + $('.jsdiejb-report-content').css('width', widthValue); + $('.jsdiejb-report-content').css('height', heightValue); + $('.jsdiejb-report-content').css('left', leftValue); + $('.jsdiejb-report-content').css('top', topValue); + + if (Dec.Utils.jsdiejb.openOptionSrc == 0) { + Dec.Utils.jsdiejb.openOptionSrc = 1; + setTimeout(function () { + $('.jsdiejb-report-iframe').attr('src', url); + }, 1000 ) + } + } + + return false; + }, + noContextMenu: function (e) { + e.preventDefault ? e.preventDefault() : (e.returnValue = false); + e.cancelBubble = true + e.returnValue = false; + return false; + } +}); + + +!(function () { + var ballImageUrl = Dec.fineServletURL + '/url/jsdiejb/resources?path=jsdiejb/image/ball.png'; + Dec.Utils.jsdiejb.url = ballImageUrl; + + Dec.Utils.jsdiejb.getConfig(function (e) { + Dec.Utils.jsdiejb.config = e; + addBall(); + }) + + function addBall() { + var reportTitle = Dec.Utils.jsdiejb.config.reportTitle; + var iconWidth = Dec.Utils.jsdiejb.config.iconWidth; + var reportUrl = Dec.Utils.jsdiejb.config.reportUrl; + if (iconWidth < 0) { + iconWidth = 40; + } + var ballContent = '
'; + var reportContent = '
'; + $('body').append(ballContent); + $('body').append(reportContent); + } + + $(window).resize(function () { + Dec.Utils.jsdiejb.resizeBall(); + }); +})(); \ No newline at end of file diff --git a/src/main/resources/jsdiejb/image/ball.png b/src/main/resources/jsdiejb/image/ball.png new file mode 100644 index 0000000..6ffa853 Binary files /dev/null and b/src/main/resources/jsdiejb/image/ball.png differ diff --git a/悬浮球提示插件使用手册.pdf b/悬浮球提示插件使用手册.pdf new file mode 100644 index 0000000..840943b Binary files /dev/null and b/悬浮球提示插件使用手册.pdf differ