33 changed files with 2342 additions and 1 deletions
@ -1,3 +1,6 @@
|
||||
# open-JSD-8016 |
||||
|
||||
JSD-8016 开源任务材料 |
||||
JSD-8016 开源任务代码\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<plugin> |
||||
<id>com.fr.plugin.sln5470</id> |
||||
<name><![CDATA[钉钉扫码多项目]]></name> |
||||
<active>yes</active> |
||||
<version>1.1.5</version> |
||||
<env-version>10.0</env-version> |
||||
<jartime>2021-01-01</jartime> |
||||
<vendor>fr.open</vendor> |
||||
<description><![CDATA[钉钉扫码登陆控件]]></description> |
||||
<function-recorder class="com.fr.plugin.ScanFunction"/> |
||||
<change-notes> |
||||
<![CDATA[ |
||||
<p>[2020-04-22]项目启动</p> |
||||
<p>[2020-11-19]修复路径404bug</p> |
||||
<p>[2020-11-19]只开启扫码功能</p> |
||||
<p>[2021-02-02]插件对于新版本钉钉插件依赖关系,必须要安装钉钉插件后才能使用。</p> |
||||
<p>[2021-05-26]适配新版本登录界面按钮。</p> |
||||
]]> |
||||
</change-notes> |
||||
<main-package>com.fr.plugin</main-package> |
||||
<!--插件生命周期接口--> |
||||
<lifecycle-monitor class="com.fr.plugin.SacnCycleMonitor"/> |
||||
<extra-decision> |
||||
<!--插件注入HttpHandler--> |
||||
<HttpHandlerProvider class="com.fr.plugin.ScanHttpHander"/> |
||||
<WebResourceProvider class="com.fr.plugin.ScanJSHander"/> |
||||
<WebResourceProvider class="com.fr.plugin.ConfigJSHander"/> |
||||
<!--注册Spring的Controller--> |
||||
<ControllerRegisterProvider class="com.fr.plugin.ScanControllerBridge"/> |
||||
</extra-decision> |
||||
<extra-core> |
||||
<DBAccessProvider class="com.fr.plugin.SCDBAccessProvider"/> |
||||
</extra-core> |
||||
<dependence> |
||||
<item type="plugin" key="com.fr.plugin.dingtalk"/> |
||||
</dependence> |
||||
</plugin> |
||||
|
@ -0,0 +1,59 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||
import com.fr.decision.webservice.Response; |
||||
import com.fr.plugin.beans.ScanConfigBean; |
||||
import com.fr.plugin.context.PluginContexts; |
||||
import com.fr.third.fasterxml.jackson.core.JsonGenerationException; |
||||
import com.fr.third.fasterxml.jackson.databind.JsonMappingException; |
||||
import com.fr.third.fasterxml.jackson.databind.ObjectMapper; |
||||
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.IOException; |
||||
import java.io.StringWriter; |
||||
import java.io.Writer; |
||||
import java.util.List; |
||||
|
||||
public class AllScanBeans extends BaseHttpHandler { |
||||
@Override |
||||
public RequestMethod getMethod() { |
||||
return RequestMethod.GET; |
||||
} |
||||
|
||||
@Override |
||||
public String getPath() { |
||||
return "/getConfigBean"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isPublic() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { |
||||
List<ScanConfigBean> beanList = SCDBAccessProvider.like(null); |
||||
for (ScanConfigBean scanConfigBean : beanList) { |
||||
scanConfigBean.setAppSecret(""); |
||||
scanConfigBean.setAppIdSecret(""); |
||||
scanConfigBean.setAppKey(""); |
||||
} |
||||
Response ok = Response.ok(beanList); |
||||
WebUtils.printAsString(httpServletResponse,serialize(ok)); |
||||
} |
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper(); |
||||
|
||||
public static String serialize(Object object) { |
||||
Writer write = new StringWriter(); |
||||
try { |
||||
objectMapper.writeValue(write, object); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return write.toString(); |
||||
} |
||||
} |
@ -0,0 +1,51 @@
|
||||
package com.fr.plugin; |
||||
|
||||
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.FileType; |
||||
import com.fr.web.struct.category.ScriptPath; |
||||
import com.fr.web.struct.category.StylePath; |
||||
|
||||
public class ConfigComponent extends Component { |
||||
public static final ConfigComponent KEY = new ConfigComponent(); |
||||
|
||||
/** |
||||
* 返回需要引入的JS脚本路径 |
||||
* |
||||
* @param client 请求客户端描述 |
||||
* @return JS脚本路径 |
||||
*/ |
||||
@Override |
||||
public ScriptPath script(RequestClient client) { |
||||
return ScriptPath.build("com/fr/plugin/web/dds/dds.js"); |
||||
} |
||||
|
||||
/** |
||||
* 返回需要引入的CSS样式路径 |
||||
* |
||||
* @param client 请求客户端描述 |
||||
* @return CSS样式路径 |
||||
*/ |
||||
@Override |
||||
public StylePath style(RequestClient client) { |
||||
//如果不需要就直接返回 StylePath.EMPTY;
|
||||
return StylePath.EMPTY; |
||||
} |
||||
|
||||
/** |
||||
* 通过给定的资源过滤器控制是否加载这个资源 |
||||
* |
||||
* @return 资源过滤器 |
||||
*/ |
||||
@Override |
||||
public Filter filter() { |
||||
return new Filter() { |
||||
@Override |
||||
public boolean accept() { |
||||
//任何情况下我们都在平台组件加载时加载我们的组件
|
||||
return true; |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractWebResourceProvider; |
||||
import com.fr.decision.web.MainComponent; |
||||
import com.fr.web.struct.Atom; |
||||
|
||||
public class ConfigJSHander extends AbstractWebResourceProvider { |
||||
|
||||
/** |
||||
* 需要附加到的主组件 |
||||
* |
||||
* @return 主组件 |
||||
*/ |
||||
|
||||
@Override |
||||
public Atom attach() { |
||||
return MainComponent.KEY; |
||||
} |
||||
|
||||
/** |
||||
* 客户端所需的组件 |
||||
* |
||||
* @return 组件 |
||||
*/ |
||||
@Override |
||||
public Atom client() { |
||||
return ConfigComponent.KEY; |
||||
} |
||||
|
||||
public Atom[] clients() { |
||||
return new Atom[]{this.client()}; |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||
import com.fr.plugin.context.PluginContexts; |
||||
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.util.HashMap; |
||||
|
||||
public class GetQRHandle extends BaseHttpHandler { |
||||
@Override |
||||
public RequestMethod getMethod() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getPath() { |
||||
return "/getQR"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isPublic() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { |
||||
ScanConfig instance = ScanConfig.getInstance(); |
||||
HashMap<String , Object> params = new HashMap<>(); |
||||
params.put("appId",instance.getAppId()); |
||||
params.put("callback",httpServletRequest.getParameter("callback")); |
||||
if (PluginContexts.currentContext().isAvailable()) { |
||||
// 做认证通过的事情
|
||||
WebUtils.writeOutTemplate("com/fr/new.html",httpServletResponse,params); |
||||
} else { |
||||
// 做认证未通过的事情
|
||||
WebUtils.writeOutTemplate("com/fr/buynew.html",httpServletResponse,params); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,128 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.dingtalk.api.DefaultDingTalkClient; |
||||
import com.dingtalk.api.DingTalkClient; |
||||
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest; |
||||
import com.dingtalk.api.request.OapiUserGetRequest; |
||||
import com.dingtalk.api.request.OapiUserGetUseridByUnionidRequest; |
||||
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse; |
||||
import com.dingtalk.api.response.OapiUserGetResponse; |
||||
import com.dingtalk.api.response.OapiUserGetUseridByUnionidResponse; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.third.javax.annotation.Nullable; |
||||
import com.taobao.api.ApiException; |
||||
|
||||
import java.io.*; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
|
||||
public class HtmlUtils { |
||||
public static String getUserUnid(String appId, String sercet, String code) { |
||||
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode"); |
||||
OapiSnsGetuserinfoBycodeRequest req = new OapiSnsGetuserinfoBycodeRequest(); |
||||
req.setTmpAuthCode(code); |
||||
try { |
||||
OapiSnsGetuserinfoBycodeResponse response = client.execute(req, appId, sercet); |
||||
FineLoggerFactory.getLogger().info("获取用户UNid详情:" + response.getBody()); |
||||
String unionid = response.getUserInfo().getUnionid(); |
||||
FineLoggerFactory.getLogger().info("获取用户unid:" + unionid); |
||||
return unionid; |
||||
} catch (ApiException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
public static OapiUserGetResponse getUserMobByUnid(String unid, String appId, String appKey) throws Exception { |
||||
|
||||
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getUseridByUnionid"); |
||||
OapiUserGetUseridByUnionidRequest request = new OapiUserGetUseridByUnionidRequest(); |
||||
request.setUnionid(unid); |
||||
request.setHttpMethod("GET"); |
||||
String accessToken = getAccessToken(appId, appKey); |
||||
OapiUserGetUseridByUnionidResponse response = client.execute(request, accessToken); |
||||
FineLoggerFactory.getLogger().info("获取用户userId详情:" + response.getBody()); |
||||
if (response.getErrcode() != 0) { |
||||
throw new Exception("访问接口报错:" + response.getErrmsg()); |
||||
} |
||||
String userid = response.getUserid(); |
||||
FineLoggerFactory.getLogger().info("获取用户UserId:" + userid); |
||||
OapiUserGetRequest userrequest = new OapiUserGetRequest(); |
||||
client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get"); |
||||
userrequest.setUserid(userid); |
||||
userrequest.setHttpMethod("GET"); |
||||
OapiUserGetResponse response1 = client.execute(userrequest, accessToken); |
||||
FineLoggerFactory.getLogger().info("获取用户mob详情:" + response1.getBody()); |
||||
String mobile = response1.getMobile(); |
||||
FineLoggerFactory.getLogger().info("获取用户手机号:" + mobile); |
||||
return response1; |
||||
} |
||||
|
||||
private static String getAccessToken(String appid, String appkey) { |
||||
String url = String.format("https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s", appid |
||||
, appkey); |
||||
JSONObject jsonObject = httpRequest(url, "GET", null); |
||||
if (jsonObject.getInt("errcode") == 0) { |
||||
return jsonObject.getString("access_token"); |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
private static void closeStream(Closeable var0) { |
||||
if (var0 != null) { |
||||
try { |
||||
var0.close(); |
||||
} catch (IOException var2) { |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
private static int CONNECTION_TIME_OUT = 120000; |
||||
private static int READ_TIME_OUT = 120000; |
||||
|
||||
@Nullable |
||||
public static JSONObject httpRequest(String var0, String var1, String var2) { |
||||
JSONObject var3 = null; |
||||
StringBuilder var4 = new StringBuilder(); |
||||
HttpURLConnection var5 = null; |
||||
|
||||
try { |
||||
URL var6 = new URL(var0); |
||||
var5 = (HttpURLConnection) var6.openConnection(); |
||||
var5.setUseCaches(false); |
||||
var5.setRequestMethod(var1); |
||||
var5.setConnectTimeout(CONNECTION_TIME_OUT); |
||||
var5.setReadTimeout(READ_TIME_OUT); |
||||
if (var2 != null) { |
||||
var5.setDoOutput(true); |
||||
var5.setRequestProperty("Content-Type", "application/json; charset=utf-8"); |
||||
OutputStream var7 = var5.getOutputStream(); |
||||
var7.write(var2.getBytes("UTF-8")); |
||||
closeStream(var7); |
||||
} |
||||
|
||||
InputStream var16 = var5.getInputStream(); |
||||
InputStreamReader var8 = new InputStreamReader(var16, "UTF-8"); |
||||
BufferedReader var9 = new BufferedReader(var8); |
||||
|
||||
String var10; |
||||
while ((var10 = var9.readLine()) != null) { |
||||
var4.append(var10); |
||||
} |
||||
|
||||
closeStream(var9); |
||||
closeStream(var8); |
||||
closeStream(var16); |
||||
var3 = new JSONObject(var4.toString()); |
||||
return var3; |
||||
} catch (Exception var14) { |
||||
} finally { |
||||
if (var5 != null) { |
||||
var5.disconnect(); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,10 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.stable.fun.impl.AbstractLocaleFinder; |
||||
|
||||
public class LDAPLocalFinder extends AbstractLocaleFinder { |
||||
@Override |
||||
public String find() { |
||||
return "/com/fr/plugin/i18n/lan"; |
||||
} |
||||
} |
@ -0,0 +1,21 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractEmbedRequestFilterProvider; |
||||
|
||||
import javax.servlet.FilterConfig; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
public class PluginInitializeFilterBridge extends AbstractEmbedRequestFilterProvider { |
||||
@Override |
||||
public void init(FilterConfig filterConfig) { |
||||
ScanConfig.getInstance(); |
||||
} |
||||
|
||||
@Override |
||||
public void filter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,153 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.db.fun.impl.AbstractDBAccessProvider; |
||||
import com.fr.decision.base.util.UUIDUtil; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.beans.ScanConfigBean; |
||||
import com.fr.plugin.dao.ScanConfigDao; |
||||
import com.fr.plugin.entitys.ScanConfigEntity; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.db.accessor.DBAccessor; |
||||
import com.fr.stable.db.action.DBAction; |
||||
import com.fr.stable.db.dao.DAOContext; |
||||
import com.fr.stable.db.dao.DAOProvider; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class SCDBAccessProvider extends AbstractDBAccessProvider { |
||||
|
||||
private static DBAccessor accessor; |
||||
@Override |
||||
public DAOProvider[] registerDAO() { |
||||
return new DAOProvider[]{ |
||||
ScanConfigDao.DAO |
||||
}; |
||||
} |
||||
|
||||
public static DBAccessor getAccessor() { |
||||
return accessor; |
||||
} |
||||
|
||||
public static void setAccessor(DBAccessor accessor) { |
||||
SCDBAccessProvider.accessor = accessor; |
||||
} |
||||
|
||||
@Override |
||||
public void onDBAvailable(DBAccessor dbAccessor) { |
||||
SCDBAccessProvider.accessor = dbAccessor; |
||||
} |
||||
|
||||
/** |
||||
* 业务对象——增 |
||||
* @param bean |
||||
*/ |
||||
public static void add( final ScanConfigBean bean ){ |
||||
try{ |
||||
accessor.runDMLAction(new DBAction<Boolean>() { |
||||
@Override |
||||
public Boolean run(DAOContext context) throws Exception { |
||||
context.getDAO(ScanConfigDao.class).add( loadScanConfigEntity(bean,true) ); |
||||
return true; |
||||
} |
||||
}); |
||||
}catch(Throwable e){ |
||||
FineLoggerFactory.getLogger().error(e,"Add ScanConfigBean Error:{}",e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 业务对象——删 |
||||
* @param id |
||||
*/ |
||||
public static ScanConfigBean delete( final String id ){ |
||||
try{ |
||||
return accessor.runDMLAction(new DBAction<ScanConfigBean>() { |
||||
@Override |
||||
public ScanConfigBean run(DAOContext context) throws Exception { |
||||
ScanConfigEntity entity = context.getDAO(ScanConfigDao.class).getById(id); |
||||
if( null == entity ){ |
||||
return null; |
||||
} |
||||
context.getDAO(ScanConfigDao.class).remove( id ); |
||||
return toScanConfigBean(entity); |
||||
} |
||||
}); |
||||
}catch(Throwable e){ |
||||
FineLoggerFactory.getLogger().error(e,"Delete ScanConfigBean[{}] Error:{}",id,e.getMessage()); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 业务对象——改 |
||||
* @param bean |
||||
*/ |
||||
public static void update( ScanConfigBean bean ){ |
||||
try{ |
||||
accessor.runDMLAction(new DBAction<Boolean>() { |
||||
@Override |
||||
public Boolean run(DAOContext context) throws Exception { |
||||
context.getDAO(ScanConfigDao.class).update( loadScanConfigEntity(bean,false) ); |
||||
return true; |
||||
} |
||||
}); |
||||
}catch(Throwable e){ |
||||
FineLoggerFactory.getLogger().error(e,"Update ScanConfigBean Error:{}",e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
|
||||
private static ScanConfigEntity loadScanConfigEntity( ScanConfigBean bean, boolean isAdd ){ |
||||
ScanConfigEntity entity = new ScanConfigEntity(); |
||||
if(isAdd || StringUtils.isEmpty( bean.getId() ) ){ |
||||
bean.setId(UUIDUtil.generate()); |
||||
} |
||||
entity.setId( bean.getId() ); |
||||
entity.setAppFlag( bean.getAppFlag() ); |
||||
entity.setAppId( bean.getAppId() ); |
||||
entity.setAppName( bean.getAppName() ); |
||||
entity.setAppKey( bean.getAppKey() ); |
||||
entity.setAppIdSecret( bean.getAppIdSecret() ); |
||||
entity.setAppSecret( bean.getAppSecret() ); |
||||
return entity; |
||||
} |
||||
|
||||
private static ScanConfigBean toScanConfigBean( ScanConfigEntity entity ){ |
||||
ScanConfigBean bean = new ScanConfigBean(); |
||||
bean.setId( entity.getId() ); |
||||
bean.setAppId( entity.getAppId() ); |
||||
bean.setAppName( entity.getAppName() ); |
||||
bean.setAppKey(entity.getAppKey()); |
||||
bean.setAppIdSecret(entity.getAppIdSecret()); |
||||
bean.setAppSecret(entity.getAppSecret()); |
||||
bean.setAppFlag(entity.getAppFlag()); |
||||
return bean; |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* 业务对象——查 |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public static List<ScanConfigBean> like(String key ){ |
||||
try{ |
||||
return accessor.runQueryAction(new DBAction<List<ScanConfigBean>>() { |
||||
@Override |
||||
public List<ScanConfigBean> run(DAOContext context) throws Exception { |
||||
List<ScanConfigBean> result = new ArrayList<ScanConfigBean>(); |
||||
List<ScanConfigEntity> list = context.getDAO(ScanConfigDao.class).likeByKey(key); |
||||
for (ScanConfigEntity scanConfigEntity : list) { |
||||
result.add(toScanConfigBean(scanConfigEntity)); |
||||
} |
||||
return result; |
||||
} |
||||
}); |
||||
}catch(Throwable e){ |
||||
FineLoggerFactory.getLogger().error(e,"Get ScanConfigBeans{} Error:{}",key,e.getMessage()); |
||||
} |
||||
return new ArrayList<ScanConfigBean>(); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.plugin.context.PluginContext; |
||||
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||
|
||||
public class SacnCycleMonitor extends AbstractPluginLifecycleMonitor { |
||||
@Override |
||||
public void afterRun(PluginContext pluginContext) { |
||||
ScanConfig instance = ScanConfig.getInstance(); |
||||
} |
||||
|
||||
@Override |
||||
public void beforeStop(PluginContext pluginContext) { |
||||
} |
||||
} |
@ -0,0 +1,292 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.dingtalk.api.response.OapiUserGetResponse; |
||||
import com.fr.base.TableData; |
||||
import com.fr.base.TemplateUtils; |
||||
import com.fr.data.NetworkHelper; |
||||
import com.fr.decision.authority.AuthorityContext; |
||||
import com.fr.decision.authority.data.User; |
||||
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||
import com.fr.decision.mobile.terminal.TerminalHandler; |
||||
import com.fr.decision.webservice.bean.authentication.OriginUrlResponseBean; |
||||
import com.fr.decision.webservice.utils.DecisionStatusService; |
||||
import com.fr.decision.webservice.v10.login.LoginService; |
||||
import com.fr.decision.webservice.v10.login.TokenResource; |
||||
import com.fr.file.DatasourceManager; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.data.DataModel; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.beans.ScanConfigBean; |
||||
import com.fr.plugin.dao.ScanConfigDao; |
||||
import com.fr.plugin.dingtalk.server.config.DingTalkConfig; |
||||
import com.fr.plugin.dingtalk.server.config.DingTalkMemberManagementConfig; |
||||
import com.fr.plugin.dingtalk.server.helper.DingTalkDecUserHelper; |
||||
import com.fr.plugin.dingtalk.server.helper.DingTalkUserHelper; |
||||
import com.fr.plugin.dingtalk.server.log.DingTalkLoggerFactory; |
||||
import com.fr.plugin.entitys.ScanConfigEntity; |
||||
import com.fr.script.Calculator; |
||||
import com.fr.security.JwtUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.db.action.DBAction; |
||||
import com.fr.stable.db.dao.DAOContext; |
||||
import com.fr.stable.query.QueryFactory; |
||||
import com.fr.stable.query.restriction.RestrictionFactory; |
||||
import com.fr.stable.web.Device; |
||||
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
||||
import com.fr.web.utils.WebUtils; |
||||
|
||||
import javax.servlet.http.Cookie; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
public class ScanCallBackHandle extends BaseHttpHandler { |
||||
@Override |
||||
public RequestMethod getMethod() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getPath() { |
||||
return "/scanLogin"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isPublic() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { |
||||
String code = WebUtils.getHTTPRequestParameter(httpServletRequest, "code"); |
||||
FineLoggerFactory.getLogger().info("鉴权成功!拿到的code为:" + code); |
||||
String state = WebUtils.getHTTPRequestParameter(httpServletRequest, "state"); |
||||
if (StringUtils.isBlank(code)) { |
||||
WebUtils.printAsString(httpServletResponse, "本接口仅限钉钉调用"); |
||||
return; |
||||
} |
||||
if (StringUtils.isNotBlank(state)) { |
||||
ScanConfigEntity entity = SCDBAccessProvider.getAccessor().runQueryAction(context -> { |
||||
List<ScanConfigEntity> entities = context.getDAO(ScanConfigDao.class).find(QueryFactory.create().addRestriction(RestrictionFactory.eq("appId", state))); |
||||
return entities.get(0); |
||||
}); |
||||
if (entity != null) { |
||||
String appId = entity.getAppId(); |
||||
String secret = entity.getAppIdSecret(); |
||||
String appKey = entity.getAppKey(); |
||||
String appSecret = entity.getAppSecret(); |
||||
String userUnid = HtmlUtils.getUserUnid(appId, secret, code); |
||||
OapiUserGetResponse userMob = HtmlUtils.getUserMobByUnid(userUnid,appKey,appSecret); |
||||
String userName = dingTalkUserToDecUser(userMob); |
||||
if (userName != null) { |
||||
if (isUserExist(userName)) { |
||||
String token = login(httpServletRequest, httpServletResponse, userName); |
||||
FineLoggerFactory.getLogger().debug("单点登录成功!生成token为:" + token); |
||||
String callBack = httpServletRequest.getParameter("redirectUrl"); |
||||
Cookie[] cookies = httpServletRequest.getCookies(); |
||||
for (Cookie cookie : cookies) { |
||||
if (StringUtils.equals(cookie.getName(), "myorgin")) { |
||||
String value = cookie.getValue(); |
||||
try { |
||||
cookie.setMaxAge(0);//删除cookies
|
||||
String originUrl = ((OriginUrlResponseBean) DecisionStatusService.originUrlStatusService().get(value)).getOriginUrl(); |
||||
httpServletResponse.addCookie(cookie); |
||||
sendRedirect(httpServletResponse, originUrl); |
||||
return; |
||||
} catch (Exception e) { |
||||
} |
||||
} |
||||
} |
||||
if (StringUtils.isNotBlank(callBack)) { |
||||
sendRedirect(httpServletResponse, callBack); |
||||
} else { |
||||
sendRedirect(httpServletResponse, getHomeURI(httpServletRequest)); |
||||
} |
||||
return; |
||||
} else { |
||||
FineLoggerFactory.getLogger().warn(String.format("平台用户中无%s用户!", userMob)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
WebUtils.printAsString(httpServletResponse, "扫码获取用户信息失败"); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 通过钉钉认证之后的响应 来获取用户名 |
||||
* |
||||
* @param userMob |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public static String dingTalkUserToDecUser(OapiUserGetResponse userMob) throws Exception { |
||||
DingTalkMemberManagementConfig config = DingTalkConfig.getInstance().getMemberManagementConfig(); |
||||
if (userMob != null && config != null) { |
||||
String jobNumber; |
||||
jobNumber = null; |
||||
String userid = userMob.getUserid(); |
||||
label65: |
||||
switch (config.getMatchingFSWay()) { |
||||
case 0: |
||||
FineLoggerFactory.getLogger().debug("当前匹配方式为工号匹配"); |
||||
jobNumber = userMob.getJobnumber(); |
||||
break; |
||||
case 1: |
||||
FineLoggerFactory.getLogger().debug("当前匹配方式为手机号匹配"); |
||||
String mobile = userMob.getMobile(); |
||||
if (StringUtils.isEmpty(mobile)) { |
||||
FineLoggerFactory.getLogger().warn("未能获取到该钉钉用户%s的手机号,请于钉钉管理后台中核查!"); |
||||
} else { |
||||
List var11 = AuthorityContext.getInstance().getUserController().find(QueryFactory.create().addRestriction(RestrictionFactory.eq("mobile", mobile))); |
||||
if (var11 != null && !var11.isEmpty()) { |
||||
Iterator var12 = var11.iterator(); |
||||
|
||||
while (true) { |
||||
if (!var12.hasNext()) { |
||||
break label65; |
||||
} |
||||
|
||||
User var13 = (User) var12.next(); |
||||
if (var13.isEnable()) { |
||||
jobNumber = var13.getUserName(); |
||||
break label65; |
||||
} |
||||
|
||||
FineLoggerFactory.getLogger().warn(String.format("当前平台用户%s被禁用,请在决策平台用户管理中设置!", var13.getUserName())); |
||||
} |
||||
} else { |
||||
FineLoggerFactory.getLogger().warn(String.format("没有在平台用户中找到手机号为%s的用户!", mobile)); |
||||
} |
||||
} |
||||
break; |
||||
case 2: |
||||
FineLoggerFactory.getLogger().debug("当前匹配方式为手动匹配"); |
||||
jobNumber = DingTalkUserHelper.getDecUserName(userid); |
||||
if (StringUtils.isEmpty(jobNumber)) { |
||||
FineLoggerFactory.getLogger().warn(String.format("请检查fine_dingtalk_user_relation表中是否存在dingTalkUser为%s的用户匹配关系", userid)); |
||||
} |
||||
break; |
||||
case 3: |
||||
FineLoggerFactory.getLogger().debug("当前匹配方式为数据集匹配"); |
||||
if (StringUtils.isNotEmpty(config.getDataSet())) { |
||||
TableData var5 = DatasourceManager.getInstance().getTableData(config.getDataSet()); |
||||
DataModel var6 = var5.createDataModel(Calculator.createCalculator()); |
||||
|
||||
for (int var7 = 0; var7 < var6.getRowCount(); ++var7) { |
||||
int var8 = config.getDataSetDingTalkUserIdColumn(); |
||||
if (ComparatorUtils.equals(var6.getValueAt(var7, var8).toString(), userid)) { |
||||
int var9 = config.getDataSetFsUserNameColumn(); |
||||
jobNumber = var6.getValueAt(var7, var9).toString(); |
||||
FineLoggerFactory.getLogger().debug(String.format("匹配第%s行第%s列的平台用户为:" + jobNumber, var7, var9)); |
||||
User var10 = DingTalkDecUserHelper.getDecUserByName(jobNumber); |
||||
if (var10 != null) { |
||||
if (var10.isEnable()) { |
||||
break; |
||||
} |
||||
|
||||
FineLoggerFactory.getLogger().warn(String.format("数据集中%s用户对应平台用户不可用", jobNumber)); |
||||
} else { |
||||
FineLoggerFactory.getLogger().warn(String.format("数据集中%s用户不在平台用户中", jobNumber)); |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
FineLoggerFactory.getLogger().warn("没有设置匹配数据集,请在钉钉管理中设置!"); |
||||
} |
||||
} |
||||
if (StringUtils.isEmpty(jobNumber)) { |
||||
FineLoggerFactory.getLogger().warn("钉钉用户匹配平台用户失败!"); |
||||
} else { |
||||
FineLoggerFactory.getLogger().debug("钉钉用户匹配平台用户结果为:" + jobNumber); |
||||
} |
||||
|
||||
return jobNumber; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 登录 |
||||
* |
||||
* @param req |
||||
* @param res |
||||
* @param username |
||||
* @return |
||||
*/ |
||||
private String login(HttpServletRequest req, HttpServletResponse res, String username) { |
||||
try { |
||||
String oldToken = TokenResource.COOKIE.getToken(req); |
||||
if ((oldToken == null) || (!checkTokenValid(req, oldToken, username))) { |
||||
String token = LoginService.getInstance().login(req, res, username); |
||||
req.setAttribute("fine_auth_token", token); |
||||
FineLoggerFactory.getLogger().error("fr CookieFilter is over with username is ###" + username); |
||||
return token; |
||||
} else { |
||||
FineLoggerFactory.getLogger().error("no need login: {}", username); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
/** |
||||
* 校验token是否有效 |
||||
*/ |
||||
public static boolean checkTokenValid(HttpServletRequest req, String token, String currentUserName) { |
||||
try { |
||||
//当前登录用户和token对应的用户名不同,需要重新生成token
|
||||
if (!ComparatorUtils.equals(currentUserName, JwtUtils.parseJWT(token).getSubject())) { |
||||
FineLoggerFactory.getLogger().info("username changed:" + currentUserName); |
||||
return false; |
||||
} |
||||
Device device = NetworkHelper.getDevice(req); |
||||
LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device)); |
||||
return true; |
||||
} catch (Exception ignore) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private User getUserByMob(String mob) throws Exception { |
||||
List<User> mobile = AuthorityContext.getInstance().getUserController().find(QueryFactory.create().addRestriction(RestrictionFactory.eq("mobile", mob))); |
||||
if (!mobile.isEmpty()) { |
||||
return mobile.get(0); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public boolean isUserExist(String var0) { |
||||
if (StringUtils.isEmpty(var0)) { |
||||
return false; |
||||
} else { |
||||
try { |
||||
List var1 = AuthorityContext.getInstance().getUserController().find(QueryFactory.create().addRestriction(RestrictionFactory.eq("userName", var0))); |
||||
return var1 != null && !var1.isEmpty(); |
||||
} catch (Exception var2) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void sendRedirect(HttpServletResponse res, String url) { |
||||
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); |
||||
res.setHeader("Location", url); |
||||
} |
||||
|
||||
private String getHomeURI(HttpServletRequest request) { |
||||
String url = "/"; |
||||
try { |
||||
url = TemplateUtils.render("${fineServletURL}"); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return url; |
||||
} |
||||
} |
@ -0,0 +1,51 @@
|
||||
package com.fr.plugin; |
||||
|
||||
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.FileType; |
||||
import com.fr.web.struct.category.ScriptPath; |
||||
import com.fr.web.struct.category.StylePath; |
||||
|
||||
public class ScanComponent extends Component { |
||||
public static final ScanComponent KEY = new ScanComponent(); |
||||
|
||||
/** |
||||
* 返回需要引入的JS脚本路径 |
||||
* |
||||
* @param client 请求客户端描述 |
||||
* @return JS脚本路径 |
||||
*/ |
||||
@Override |
||||
public ScriptPath script(RequestClient client) { |
||||
return ScriptPath.build("com.fr.plugin.ScanJS&time=" + System.currentTimeMillis(), FileType.CLASS); |
||||
} |
||||
|
||||
/** |
||||
* 返回需要引入的CSS样式路径 |
||||
* |
||||
* @param client 请求客户端描述 |
||||
* @return CSS样式路径 |
||||
*/ |
||||
@Override |
||||
public StylePath style(RequestClient client) { |
||||
//如果不需要就直接返回 StylePath.EMPTY;
|
||||
return StylePath.EMPTY; |
||||
} |
||||
|
||||
/** |
||||
* 通过给定的资源过滤器控制是否加载这个资源 |
||||
* |
||||
* @return 资源过滤器 |
||||
*/ |
||||
@Override |
||||
public Filter filter() { |
||||
return new Filter() { |
||||
@Override |
||||
public boolean accept() { |
||||
//任何情况下我们都在平台组件加载时加载我们的组件
|
||||
return true; |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,108 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.config.*; |
||||
import com.fr.config.holder.Conf; |
||||
import com.fr.config.holder.factory.Holders; |
||||
|
||||
@Visualization(category = "钉钉扫码配置") |
||||
public class ScanConfig extends DefaultConfiguration { |
||||
private static volatile ScanConfig config = null; |
||||
|
||||
public static ScanConfig getInstance() { |
||||
if (config == null) { |
||||
config = ConfigContext.getConfigInstance(ScanConfig.class); |
||||
} |
||||
return config; |
||||
} |
||||
|
||||
@Identifier(value = "AppId", name = "扫码AppID", description = "", status = Status.SHOW) |
||||
private Conf<String> appId = Holders.simple(""); |
||||
|
||||
@Identifier(value = "Secret", name = "扫码app_secret", description = "", status = Status.SHOW) |
||||
private Conf<String> secret = Holders.simple(""); |
||||
|
||||
// @Identifier(value = "loginKey", name = "登录AppKey", description = "", status = Status.SHOW)
|
||||
// private Conf<String> loginKey = Holders.simple("");
|
||||
//
|
||||
// @Identifier(value = "LoginSecret", name = "登录app_secret", description = "", status = Status.SHOW)
|
||||
// private Conf<String> loginSecret = Holders.simple("");
|
||||
|
||||
@Identifier(value = "openLogin", name = "登录界面启动开关", description = "", status = Status.SHOW) |
||||
private Conf<Boolean> openLogin = Holders.simple(true); |
||||
@Identifier(value = "defaultScan", name = "默认扫码登录", description = "", status = Status.SHOW) |
||||
private Conf<Boolean> defaultScan = Holders.simple(false); |
||||
@Identifier(value = "onlyScan", name = "只保留扫码登录", description = "", status = Status.SHOW) |
||||
private Conf<Boolean> onlyScan = Holders.simple(false); |
||||
|
||||
public Boolean getDefaultScan() { |
||||
return defaultScan.get(); |
||||
} |
||||
|
||||
public void setDefaultScan( Boolean defaultScan) { |
||||
this.defaultScan .set(defaultScan); |
||||
} |
||||
|
||||
public Boolean getOnlyScan() { |
||||
return onlyScan.get(); |
||||
} |
||||
|
||||
public void setOnlyScan( Boolean onlyScan) { |
||||
this.onlyScan .set(onlyScan); |
||||
} |
||||
|
||||
public String getAppId() { |
||||
return appId.get(); |
||||
} |
||||
|
||||
public void setAppId(String appId) { |
||||
this.appId.set(appId); |
||||
} |
||||
|
||||
public String getSecret() { |
||||
return secret.get(); |
||||
} |
||||
|
||||
public void setSecret(String secret) { |
||||
this.secret.set(secret); |
||||
} |
||||
//
|
||||
// public String getLoginKey() {
|
||||
// return loginKey.get();
|
||||
// }
|
||||
//
|
||||
// public void setLoginKey(String loginKey) {
|
||||
// this.loginKey.set(loginKey);
|
||||
// }
|
||||
//
|
||||
// public String getLoginSecret() {
|
||||
// return loginSecret.get();
|
||||
// }
|
||||
//
|
||||
// public void setLoginSecret(String loginSecret) {
|
||||
// this.loginSecret.set(loginSecret);
|
||||
// }
|
||||
|
||||
public Boolean getOpenLogin() { |
||||
return openLogin.get(); |
||||
} |
||||
|
||||
public void setOpenLogin(Boolean openLogin) { |
||||
this.openLogin.set(openLogin); |
||||
} |
||||
|
||||
@Override |
||||
public Object clone() throws CloneNotSupportedException { |
||||
ScanConfig cloned = (ScanConfig) super.clone(); |
||||
cloned.appId = (Conf<String>) appId.clone(); |
||||
cloned.secret = (Conf<String>) secret.clone(); |
||||
|
||||
// cloned.loginKey = (Conf<String>) loginKey.clone();
|
||||
// cloned.loginSecret = (Conf<String>) loginSecret.clone();
|
||||
//
|
||||
cloned.onlyScan = (Conf<Boolean>) onlyScan.clone(); |
||||
cloned.defaultScan = (Conf<Boolean>) defaultScan.clone(); |
||||
cloned.openLogin = (Conf<Boolean>) openLogin.clone(); |
||||
return cloned; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,11 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractControllerRegisterProvider; |
||||
import com.fr.plugin.web.controllers.ScanController; |
||||
|
||||
public class ScanControllerBridge extends AbstractControllerRegisterProvider { |
||||
@Override |
||||
public Class<?>[] getControllers() { |
||||
return new Class[]{ScanController.class}; |
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||
import com.fr.plugin.transform.FunctionRecorder; |
||||
|
||||
@FunctionRecorder(localeKey = "scan") |
||||
public class ScanFunction { |
||||
@ExecuteFunctionRecord |
||||
public String name() { |
||||
return "功能点检测"; |
||||
} |
||||
} |
@ -0,0 +1,19 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.HttpHandler; |
||||
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; |
||||
import com.fr.stable.fun.Authorize; |
||||
|
||||
|
||||
public class ScanHttpHander extends AbstractHttpHandlerProvider { |
||||
HttpHandler[] actions = new HttpHandler[]{ |
||||
new ScanCallBackHandle(), |
||||
new GetQRHandle(), |
||||
new AllScanBeans() |
||||
}; |
||||
|
||||
@Override |
||||
public HttpHandler[] registerHandlers() { |
||||
return actions; |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.base.TemplateUtils; |
||||
import com.fr.gen.TextGenerator; |
||||
import com.fr.plugin.context.PluginContexts; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
public class ScanJS implements TextGenerator { |
||||
|
||||
|
||||
public String text(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||
Map<String, Object> renderMap = new HashMap(); |
||||
ScanConfig instance = ScanConfig.getInstance(); |
||||
String appid = instance.getAppId(); |
||||
renderMap.put("openScan", instance.getOpenLogin()); |
||||
renderMap.put("defaultScan", instance.getDefaultScan()); |
||||
renderMap.put("onlyScan", instance.getOnlyScan()); |
||||
renderMap.put("appId", appid); |
||||
if (PluginContexts.currentContext().isAvailable()) { |
||||
// 做认证通过的事情
|
||||
return TemplateUtils.renderTemplate(this.template(), renderMap); |
||||
} else { |
||||
// 做认证未通过的事情
|
||||
return TemplateUtils.renderTemplate("/com/fr/plugin/scanBuy.tpl", renderMap); |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
public String mimeType() { |
||||
return "text/javascript"; |
||||
} |
||||
|
||||
public String template() { |
||||
return "/com/fr/plugin/scan.tpl"; |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
package com.fr.plugin; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractWebResourceProvider; |
||||
import com.fr.decision.web.LoginComponent; |
||||
import com.fr.web.struct.Atom; |
||||
|
||||
public class ScanJSHander extends AbstractWebResourceProvider { |
||||
|
||||
/** |
||||
* 需要附加到的主组件 |
||||
* |
||||
* @return 主组件 |
||||
*/ |
||||
|
||||
@Override |
||||
public Atom attach() { |
||||
return LoginComponent.KEY; |
||||
} |
||||
|
||||
/** |
||||
* 客户端所需的组件 |
||||
* |
||||
* @return 组件 |
||||
*/ |
||||
@Override |
||||
public Atom client() { |
||||
return ScanComponent.KEY; |
||||
} |
||||
public Atom[] clients() { |
||||
return new Atom[]{this.client()}; |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.fr.plugin.beans; |
||||
|
||||
public class ScanAllConfigBean { |
||||
private Boolean openLogin = false; |
||||
private Boolean defaultScan = false; |
||||
private Boolean onlyScan = false; |
||||
|
||||
public Boolean getOpenLogin() { |
||||
return openLogin; |
||||
} |
||||
|
||||
public void setOpenLogin(Boolean openLogin) { |
||||
this.openLogin = openLogin; |
||||
} |
||||
|
||||
public Boolean getDefaultScan() { |
||||
return defaultScan; |
||||
} |
||||
|
||||
public void setDefaultScan(Boolean defaultScan) { |
||||
this.defaultScan = defaultScan; |
||||
} |
||||
|
||||
public Boolean getOnlyScan() { |
||||
return onlyScan; |
||||
} |
||||
|
||||
public void setOnlyScan(Boolean onlyScan) { |
||||
this.onlyScan = onlyScan; |
||||
} |
||||
} |
@ -0,0 +1,71 @@
|
||||
package com.fr.plugin.beans; |
||||
|
||||
import com.fr.stable.db.entity.BaseEntity; |
||||
|
||||
public class ScanConfigBean extends BaseEntity { |
||||
private String id = ""; |
||||
private String appId = ""; |
||||
private String appIdSecret = ""; |
||||
private String appKey = ""; |
||||
private String appSecret = ""; |
||||
private String appName = ""; |
||||
private String appFlag = ""; |
||||
|
||||
public String getAppIdSecret() { |
||||
return appIdSecret; |
||||
} |
||||
|
||||
public void setAppIdSecret(String appIdSecret) { |
||||
this.appIdSecret = appIdSecret; |
||||
} |
||||
|
||||
public String getAppSecret() { |
||||
return appSecret; |
||||
} |
||||
|
||||
public void setAppSecret(String appSecret) { |
||||
this.appSecret = appSecret; |
||||
} |
||||
|
||||
@Override |
||||
public String getId() { |
||||
return id; |
||||
} |
||||
|
||||
@Override |
||||
public void setId(String id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getAppId() { |
||||
return appId; |
||||
} |
||||
|
||||
public void setAppId(String appId) { |
||||
this.appId = appId; |
||||
} |
||||
|
||||
public String getAppKey() { |
||||
return appKey; |
||||
} |
||||
|
||||
public void setAppKey(String appKey) { |
||||
this.appKey = appKey; |
||||
} |
||||
|
||||
public String getAppName() { |
||||
return appName; |
||||
} |
||||
|
||||
public void setAppName(String appName) { |
||||
this.appName = appName; |
||||
} |
||||
|
||||
public String getAppFlag() { |
||||
return appFlag; |
||||
} |
||||
|
||||
public void setAppFlag(String appFlag) { |
||||
this.appFlag = appFlag; |
||||
} |
||||
} |
@ -0,0 +1,61 @@
|
||||
package com.fr.plugin.dao; |
||||
|
||||
import com.fr.plugin.entitys.ScanConfigEntity; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.db.dao.BaseDAO; |
||||
import com.fr.stable.db.dao.DAOProvider; |
||||
import com.fr.stable.db.session.DAOSession; |
||||
import com.fr.stable.query.QueryFactory; |
||||
import com.fr.stable.query.condition.QueryCondition; |
||||
import com.fr.stable.query.restriction.RestrictionFactory; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class ScanConfigDao extends BaseDAO<ScanConfigEntity> { |
||||
public ScanConfigDao(DAOSession daoSession) { |
||||
super(daoSession); |
||||
} |
||||
|
||||
protected Class<ScanConfigEntity> getEntityClass() { |
||||
return ScanConfigEntity.class; |
||||
} |
||||
|
||||
public final static DAOProvider DAO = new DAOProvider() { |
||||
@Override |
||||
public Class getEntityClass() { |
||||
return ScanConfigEntity.class; |
||||
} |
||||
|
||||
@Override |
||||
public Class<? extends BaseDAO> getDAOClass() { |
||||
return ScanConfigDao.class; |
||||
} |
||||
}; |
||||
|
||||
public void add(ScanConfigEntity entity) throws Exception { |
||||
getSession().persist(entity); |
||||
} |
||||
|
||||
public void update(ScanConfigEntity entity) throws Exception { |
||||
getSession().merge(entity); |
||||
} |
||||
|
||||
public ScanConfigEntity getById(String id) throws Exception { |
||||
return getSession().getById(id, ScanConfigEntity.class); |
||||
} |
||||
|
||||
public void remove(String id) throws Exception { |
||||
getSession().remove(QueryFactory.create() |
||||
.addRestriction(RestrictionFactory.eq("id", id)), |
||||
this.getEntityClass()); |
||||
} |
||||
|
||||
public List<ScanConfigEntity> likeByKey(String key) throws Exception { |
||||
QueryCondition condition = QueryFactory.create(); |
||||
if (StringUtils.isNotBlank(key)) { |
||||
condition.addRestriction(RestrictionFactory.like("app_name", key)); |
||||
} |
||||
return find(condition); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,73 @@
|
||||
package com.fr.plugin.entitys; |
||||
|
||||
import com.fr.stable.db.entity.BaseEntity; |
||||
import com.fr.third.javax.persistence.Column; |
||||
import com.fr.third.javax.persistence.Entity; |
||||
import com.fr.third.javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table( |
||||
name = "fine_dd_scan_login_config" |
||||
) |
||||
public class ScanConfigEntity extends BaseEntity { |
||||
@Column(name = "app_id") |
||||
private String appId = ""; |
||||
@Column(name = "app_key") |
||||
private String appKey = ""; |
||||
@Column(name = "app_id_secret") |
||||
private String appIdSecret = ""; |
||||
@Column(name = "app_secret") |
||||
private String appSecret = ""; |
||||
@Column(name = "app_name") |
||||
private String appName = ""; |
||||
@Column(name = "app_flag") |
||||
private String appFlag = ""; |
||||
|
||||
public String getAppIdSecret() { |
||||
return appIdSecret; |
||||
} |
||||
|
||||
public void setAppIdSecret(String appIdSecret) { |
||||
this.appIdSecret = appIdSecret; |
||||
} |
||||
|
||||
public String getAppSecret() { |
||||
return appSecret; |
||||
} |
||||
|
||||
public void setAppSecret(String appSecret) { |
||||
this.appSecret = appSecret; |
||||
} |
||||
|
||||
public String getAppId() { |
||||
return appId; |
||||
} |
||||
|
||||
public void setAppId(String appId) { |
||||
this.appId = appId; |
||||
} |
||||
|
||||
public String getAppKey() { |
||||
return appKey; |
||||
} |
||||
|
||||
public void setAppKey(String appKey) { |
||||
this.appKey = appKey; |
||||
} |
||||
|
||||
public String getAppName() { |
||||
return appName; |
||||
} |
||||
|
||||
public void setAppName(String appName) { |
||||
this.appName = appName; |
||||
} |
||||
|
||||
public String getAppFlag() { |
||||
return appFlag; |
||||
} |
||||
|
||||
public void setAppFlag(String appFlag) { |
||||
this.appFlag = appFlag; |
||||
} |
||||
} |
@ -0,0 +1,69 @@
|
||||
package com.fr.plugin.web.controllers; |
||||
|
||||
import com.fr.decision.webservice.Response; |
||||
import com.fr.decision.webservice.annotation.LoginStatusChecker; |
||||
import com.fr.plugin.SCDBAccessProvider; |
||||
import com.fr.plugin.ScanConfig; |
||||
import com.fr.plugin.beans.ScanAllConfigBean; |
||||
import com.fr.plugin.beans.ScanConfigBean; |
||||
import com.fr.third.springframework.stereotype.Controller; |
||||
import com.fr.third.springframework.web.bind.annotation.*; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @version 10.0 |
||||
* Created by fr.open on 2021-06-26 |
||||
**/ |
||||
@Controller("ScanController") |
||||
@LoginStatusChecker(required = true) |
||||
@RequestMapping(value = "/ddScan/config") |
||||
public class ScanController { |
||||
|
||||
@RequestMapping(value = "/scan_entity", method = RequestMethod.POST) |
||||
@ResponseBody |
||||
public Response add(@RequestBody ScanConfigBean bean) throws Exception { |
||||
SCDBAccessProvider.add(bean); |
||||
return Response.ok(bean); |
||||
} |
||||
|
||||
@RequestMapping(value = "/scan_entity/{entity}", method = RequestMethod.DELETE) |
||||
@ResponseBody |
||||
public Response delete(@PathVariable("entity") String entity) throws Exception { |
||||
return Response.ok(SCDBAccessProvider.delete(entity)); |
||||
} |
||||
|
||||
@RequestMapping(value = "/scan_entity", method = RequestMethod.PUT) |
||||
@ResponseBody |
||||
public Response update(@RequestBody ScanConfigBean bean) throws Exception { |
||||
SCDBAccessProvider.update(bean); |
||||
return Response.ok(bean); |
||||
} |
||||
|
||||
@RequestMapping(value = "/scan_entity", method = RequestMethod.GET) |
||||
@ResponseBody |
||||
public Response like(@RequestParam(value = "key",required = false) String key) throws Exception { |
||||
return Response.ok(SCDBAccessProvider.like(key)); |
||||
} |
||||
|
||||
@RequestMapping(value = "/allDefConfig", method = RequestMethod.GET) |
||||
@ResponseBody |
||||
public Response allDefConfig() throws Exception { |
||||
ScanAllConfigBean bean = new ScanAllConfigBean(); |
||||
ScanConfig scanConfig = ScanConfig.getInstance(); |
||||
bean.setDefaultScan(scanConfig.getDefaultScan()); |
||||
bean.setOpenLogin(scanConfig.getOpenLogin()); |
||||
bean.setOnlyScan(scanConfig.getOnlyScan()); |
||||
return Response.ok(bean); |
||||
} |
||||
@RequestMapping(value = "/changeConfig", method = RequestMethod.PUT) |
||||
@ResponseBody |
||||
public Response changeConfig(@RequestBody ScanAllConfigBean bean) throws Exception { |
||||
if (bean != null) { |
||||
ScanConfig scanConfig = ScanConfig.getInstance(); |
||||
scanConfig.setDefaultScan(bean.getDefaultScan()); |
||||
scanConfig.setOpenLogin(bean.getOpenLogin()); |
||||
scanConfig.setOnlyScan(bean.getOnlyScan()); |
||||
} |
||||
return Response.ok(bean); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
||||
"http://www.w3.org/TR/html4/loose.dtd"> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>钉钉扫码</title> |
||||
</head> |
||||
|
||||
<script type="text/javascript"> |
||||
|
||||
</script> |
||||
<body> |
||||
<p style="text-align: center" id="scan"> |
||||
请购买授权后使用 |
||||
</p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
||||
"http://www.w3.org/TR/html4/loose.dtd"> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>钉钉扫码</title> |
||||
</head> |
||||
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script> |
||||
|
||||
<script type="text/javascript"> |
||||
|
||||
|
||||
|
||||
var host = window.location.protocol+"//"+window.location.host+"${fineServletURL}";//左良测试new |
||||
function login() { |
||||
var appId="${appId}"; |
||||
var callback="${callBack}"; |
||||
var target = encodeURIComponent(callback); |
||||
var callBack = encodeURIComponent(host + "/plugin/public/com.fr.plugin.sln5470/scanLogin?redirectUrl=" + target); |
||||
var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid='+appId+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=' + callBack); |
||||
/* |
||||
* 解释一下goto参数,参考以下例子: |
||||
* var url = encodeURIComponent('http://localhost.me/index.php?test=1&aa=2'); |
||||
* var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=appid&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+url) |
||||
*/ |
||||
var obj = DDLogin({ |
||||
id: "scan", |
||||
goto: goto, |
||||
style: "border:none;background-color:#FFFFFF;", |
||||
width: "365", |
||||
height: "400" |
||||
}); |
||||
|
||||
var handleMessage = function (event) { |
||||
var origin = event.origin; |
||||
console.log("origin", event.origin); |
||||
if( origin == "https://login.dingtalk.com" ) { //判断是否来自ddLogin扫码事件。 |
||||
var loginTmpCode = event.data; |
||||
var url="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="+appId+"&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="+callBack+"&loginTmpCode="+loginTmpCode; |
||||
console.log("loginTmpCode", loginTmpCode); |
||||
window.location.href=url; |
||||
} |
||||
}; |
||||
if (typeof window.addEventListener != 'undefined') { |
||||
window.addEventListener('message', handleMessage, false); |
||||
} else if (typeof window.attachEvent != 'undefined') { |
||||
window.attachEvent('onmessage', handleMessage); |
||||
} |
||||
} |
||||
|
||||
function setCookie(name, value) { |
||||
document.cookie = name + "=" + escape(value); |
||||
} |
||||
|
||||
function getCookie(name) { |
||||
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); |
||||
if (arr = document.cookie.match(reg)) { |
||||
return unescape(arr[2]); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
window.onload = login; |
||||
</script> |
||||
<body> |
||||
<p style="text-align: center" id="scan"></p> |
||||
</body> |
||||
</html> |
@ -0,0 +1,331 @@
|
||||
(function () { |
||||
// 为平台增加一个footer |
||||
BI.Plugin.registerObject("dec.login.login", function (widget) { |
||||
var openScan = eval("${openScan}"); |
||||
var defaultScan = eval("${defaultScan}"); |
||||
var onlyScan = eval("${onlyScan}"); |
||||
// if (openScan) { |
||||
// var target = $(widget.element).find(".bi-multi-select-item").parent(); |
||||
// var item = $("<div class=\"bi-left-right-vertical-adapt-layout bi-float-left-layout clearfix \" style=\"position: relative; margin-bottom: 30px;\"><div class=\"bi-flex-vertical-center-adapt-layout item-icon dir-font-14 bi-flex-horizontal-layout v-middle h-left\" style=\"width: 26px;position: absolute;top: 0px;bottom: 0px;right: 0px;\"><div class=\"bi-flex-center-adapt-layout\" style=\"position: relative; flex-shrink: 0;\"><i class=\"bi-single x-icon b-font horizon-center display-block\" style=\"position: relative; flex-shrink: 0; margin: 0px;\"></i></div></div></div>") |
||||
// item.click(function () { |
||||
// window.zxltabs.setSelect(DecCst.Login.Tabs.QR_LOGIN) |
||||
// }); |
||||
// item.insertAfter(target); |
||||
// } |
||||
if (openScan) { |
||||
var target = $(widget.element).find(".bi-multi-select-item").parent().parent(); |
||||
var item = $("<div class=\"bi-left-right-vertical-adapt-layout bi-float-left-layout clearfix \" style=\"position: relative; margin-bottom: 30px;\"><div class=\"bi-flex-vertical-center-adapt-layout item-icon dir-font-14 bi-flex-horizontal-layout v-middle h-left\" style=\"width: 26px;position: absolute;top: 0px;bottom: 0px;right: 0px;\"><div class=\"bi-flex-center-adapt-layout\" style=\"position: relative; flex-shrink: 0;\"><i class=\"bi-single x-icon b-font horizon-center display-block\" style=\"position: relative; flex-shrink: 0; margin: 0px;\"></i></div></div></div>") |
||||
item.click(function () { |
||||
window.zxltabs.setSelect(DecCst.Login.Tabs.QR_LOGIN) |
||||
}); |
||||
item.insertAfter(target); |
||||
} |
||||
}); |
||||
})(); |
||||
|
||||
var onlyScan = eval("${onlyScan}"); |
||||
var defaultScan = eval("${defaultScan}"); |
||||
if(getQueryString("isAdmin") === "1"){ |
||||
onlyScan=false; |
||||
defaultScan=false; |
||||
} |
||||
function setCookie(name, value) { |
||||
var Days = 1; |
||||
var exp = new Date(); |
||||
exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000); |
||||
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString(); |
||||
} |
||||
|
||||
function getQueryString(name) { |
||||
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); |
||||
var r = window.location.search.substr(1).match(reg); |
||||
if (r != null) { |
||||
return decodeURIComponent(r[2]); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
if (onlyScan) { |
||||
var tempScan = getQueryString("notScan"); |
||||
if (tempScan) { |
||||
onlyScan = false; |
||||
defaultScan = false; |
||||
} |
||||
} |
||||
DecCst = DecCst || {}; |
||||
DecCst.Login.Tabs.QR_LOGIN = "qr_login"; |
||||
(function () { |
||||
var e = BI.inherit(BI.Widget, { |
||||
props: { |
||||
baseCls: "dec-login-index" |
||||
}, |
||||
_store: function () { |
||||
return BI.Models.getModel("dec.model.login.index") |
||||
}, |
||||
watch: { |
||||
selectedTab: function (e) { |
||||
this.tab.setSelect(e) |
||||
} |
||||
}, |
||||
render: function () { |
||||
var t = this; |
||||
return { |
||||
type: "bi.tab", |
||||
cls: "bi-card", |
||||
single: !0, |
||||
cardCreator: BI.bind(this._createCard, this), |
||||
showIndex: this.model.selectedTab, |
||||
ref: function (e) { |
||||
t.tab = e |
||||
} |
||||
} |
||||
}, |
||||
mounted: function () { |
||||
this.store.initData() |
||||
window.zxltabs = this.tab; |
||||
//如果有一个notScan参数就,不是只扫码 |
||||
if (defaultScan) { |
||||
this.tab.setSelect(DecCst.Login.Tabs.QR_LOGIN) |
||||
} |
||||
}, |
||||
_createCard: function (e) { |
||||
var t = this; |
||||
|
||||
switch (e) { |
||||
case DecCst.Login.Tabs.LOGIN: |
||||
|
||||
if (onlyScan) { |
||||
return { |
||||
type: "dec.login.QR" |
||||
}; |
||||
} else { |
||||
return { |
||||
type: "dec.login.login", |
||||
listeners: [{ |
||||
eventName: "EVENT_LOGIN", |
||||
action: function (e) { |
||||
t.store.login(e) |
||||
} |
||||
}] |
||||
}; |
||||
} |
||||
case DecCst.Login.Tabs.FORGET_PASSWORD: |
||||
return { |
||||
type: "dec.login.forget" |
||||
}; |
||||
case DecCst.Login.Tabs.AUTHENTICATION: |
||||
return { |
||||
type: "dec.login.authentication", |
||||
listeners: [{ |
||||
eventName: "EVENT_LOGIN", |
||||
action: function (e) { |
||||
t.store.login(e) |
||||
} |
||||
}] |
||||
}; |
||||
case DecCst.Login.Tabs.PASSWORD_TOKEN: |
||||
return { |
||||
type: "dec.login.password", |
||||
listeners: [{ |
||||
eventName: "EVENT_SAVE", |
||||
action: function (e) { |
||||
t.store.toSuccess(e) |
||||
} |
||||
}] |
||||
}; |
||||
case DecCst.Login.Tabs.QR_LOGIN: |
||||
return { |
||||
type: "dec.login.QR" |
||||
}; |
||||
case DecCst.Login.Tabs.SUCCESS_PWD: |
||||
return { |
||||
type: "dec.login.password.success", |
||||
username: this.model.loginInfo.username, |
||||
pwd: this.model.userInfo.pwd, |
||||
loginValidity: this.model.loginInfo.validity, |
||||
listeners: [{ |
||||
eventName: "EVENT_LOGIN", |
||||
action: function (e) { |
||||
t.store.login(e) |
||||
} |
||||
}] |
||||
}; |
||||
case DecCst.Login.Tabs.SUCCESS_TOKEN: |
||||
return { |
||||
type: "dec.login.password.token", |
||||
listeners: [{ |
||||
eventName: "EVENT_LOGIN", |
||||
action: function (e) { |
||||
t.store.login(e) |
||||
} |
||||
}] |
||||
}; |
||||
case DecCst.Login.Tabs.PASSWORD_OLD: |
||||
return { |
||||
type: "dec.login.single", |
||||
username: this.model.loginInfo.username, |
||||
listeners: [{ |
||||
eventName: "EVENT_BACK", |
||||
action: function () { |
||||
t.store.setTab(DecCst.Login.Tabs.LOGIN) |
||||
} |
||||
}, { |
||||
eventName: "EVENT_SURE", |
||||
action: function (e) { |
||||
t.store.toSuccess(e) |
||||
} |
||||
}] |
||||
}; |
||||
case DecCst.Login.Tabs.VERIFY_BING: |
||||
return { |
||||
type: "dec.login.verify" |
||||
}; |
||||
case DecCst.Login.Tabs.LOCKED: |
||||
return { |
||||
type: "dec.login.locked" |
||||
}; |
||||
default: |
||||
return { |
||||
type: "bi.layout" |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
BI.shortcut("dec.login.index", e) |
||||
}()); |
||||
function getPath(path, isPublic) { |
||||
if (!path || path[0] !== '/') { |
||||
path = '/' + path; |
||||
} |
||||
return isPublic === true |
||||
? '/plugin/public/com.fr.plugin.sln5470' + path |
||||
: '/plugin/private/com.fr.plugin.sln5470' + path; |
||||
} |
||||
;(function () { |
||||
var e = BI.inherit(BI.Widget, { |
||||
props: { |
||||
baseCls: "" |
||||
}, |
||||
_store: function () { |
||||
return BI.Models.getModel("dec.model.login.login") |
||||
}, |
||||
beforeInit:function (callback){ |
||||
//初始化的时候先获取有哪些钉钉服务器可以选择 |
||||
var self = this; |
||||
Dec.reqGet(getPath("getConfigBean", true), {}, function (data) { |
||||
console.info(data) |
||||
self.datas = data.data; |
||||
callback(); |
||||
}) |
||||
}, |
||||
mounted: function () { |
||||
if(this.firstId){ |
||||
this.comb.setValue(this.firstId); |
||||
this.changeSelect(this.firstId); |
||||
} |
||||
}, |
||||
changeSelect:function ( value){ |
||||
var self=this; |
||||
var appId = value||self.comb.getValue()[0]; |
||||
var host = window.location.protocol + "//" + window.location.host;//左良测试 |
||||
var cal = host + "${fineServletURL}"; |
||||
var target = encodeURIComponent(cal); |
||||
//拿到loginTmpCode后就可以在这里构造跳转链接进行跳转了 |
||||
var orgin = getQueryString("origin") |
||||
if (orgin) { |
||||
setCookie("myorgin", orgin); |
||||
} |
||||
var callBack = encodeURIComponent(cal + "/plugin/public/com.fr.plugin.sln5470/scanLogin?redirectUrl=" + target); |
||||
var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=' + appId + '&response_type=code&scope=snsapi_login&redirect_uri=' + callBack); |
||||
var url = "https://login.dingtalk.com/login/qrcode.htm?&state="+appId+"&goto=" + goto + "&style=" + encodeURIComponent('border:none;background-color:#FFFFFF;'); |
||||
$(self.iframe.element).attr("src",url) |
||||
self.iframe.setVisible(true) |
||||
// self.comb.setVisible(false) |
||||
var handleMessage = function (event) { |
||||
var origin = event.origin; |
||||
var host = window.location.protocol + "//" + window.location.host;//左良测试 |
||||
var callback = host + "${fineServletURL}"; |
||||
console.log("origin", event.origin); |
||||
if (origin == "https://login.dingtalk.com") { //判断是否来自ddLogin扫码事件。 |
||||
var loginTmpCode = event.data; |
||||
var url = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="+appId+"&response_type=code&scope=snsapi_login&state="+appId+"&redirect_uri=" + callback + "&loginTmpCode=" + loginTmpCode; |
||||
window.location.href = url; |
||||
} |
||||
}; |
||||
if (typeof window.addEventListener != 'undefined') { |
||||
window.addEventListener('message', handleMessage, false); |
||||
} else if (typeof window.attachEvent != 'undefined') { |
||||
window.attachEvent('onmessage', handleMessage); |
||||
} |
||||
|
||||
}, |
||||
render: function () { |
||||
var t = this; |
||||
var url=""; |
||||
var items=BI.map(this.datas,function (i,v){ |
||||
return { |
||||
text: v.appName, |
||||
value: v.appId |
||||
} |
||||
}) |
||||
var vv=null; |
||||
if(items.length){ |
||||
t.firstId=items[0].value; |
||||
} |
||||
return { |
||||
type: "bi.absolute", |
||||
items: [ |
||||
{ |
||||
el:{ |
||||
css:{ |
||||
zIndex:999 |
||||
}, |
||||
type: "bi.text_value_combo", |
||||
ref: function (e) { |
||||
t.comb=e; |
||||
}, |
||||
value:vv, |
||||
text:"请选择登录的公司信息", |
||||
listeners: [{ |
||||
eventName: "EVENT_CHANGE", |
||||
action: function () { |
||||
t.changeSelect(); |
||||
} |
||||
}], |
||||
width: 201, |
||||
height:24, |
||||
items: items |
||||
}, |
||||
bottom: 30, |
||||
left:35 |
||||
}, |
||||
{ |
||||
el: { |
||||
type: "bi.default", |
||||
invisible:true, |
||||
ref:function (e){ |
||||
t.iframe=e; |
||||
}, |
||||
element: "<iframe scrolling=\"no\" frameborder='0' style=\"width:98%; overflow: hidden\" src=\"" + url + "\"></iframe>" |
||||
}, |
||||
top: 0, |
||||
height: "100%", |
||||
right: 0, |
||||
bottom: 0, |
||||
left: 0 |
||||
}, { |
||||
el: { |
||||
type: "bi.icon_button", |
||||
cls: "toast-error-font", |
||||
handler: function () { |
||||
window.zxltabs.setSelect(DecCst.Login.Tabs.LOGIN) |
||||
} |
||||
}, |
||||
top: 10, |
||||
right: 20 |
||||
}] |
||||
} |
||||
} |
||||
}); |
||||
BI.shortcut("dec.login.QR", e) |
||||
})(); |
@ -0,0 +1,3 @@
|
||||
;(function () { |
||||
alert("钉钉扫码插件授权过期或未授权") |
||||
})(); |
@ -0,0 +1,496 @@
|
||||
BI.config("dec.provider.management", function (provider) { |
||||
provider.inject({ |
||||
modules: [ |
||||
{ |
||||
value: "dd.scan.config", |
||||
id: "decision-management-custom-manage", |
||||
text: "钉钉扫码配置", |
||||
cardType: "dd.scan.config", |
||||
cls: "setting-font", |
||||
dev: true |
||||
} |
||||
] |
||||
}); |
||||
}); |
||||
|
||||
function getPath(path, isPublic) { |
||||
if (!path || path[0] !== '/') { |
||||
path = '/' + path; |
||||
} |
||||
return isPublic === true |
||||
? '//ddScan/config/' + path |
||||
: '/ddScan/config/' + path; |
||||
} |
||||
|
||||
// 组件实现,效果为使用绝对布局组件放置了一个iframe
|
||||
var Wid = BI.inherit(BI.Widget, { |
||||
|
||||
props: { |
||||
baseCls: "" |
||||
}, |
||||
|
||||
render: function () { |
||||
return { |
||||
type: "bi.vertical", |
||||
vgap: 30, |
||||
items: [ |
||||
{ |
||||
type: "dd.scan.top.row", |
||||
height: 300 |
||||
}, |
||||
{ |
||||
tgap:30, |
||||
type: "dd.scan.bottom.config.all.area" |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.config", Wid); |
||||
// 组件实现,效果为使用绝对布局组件放置了一个iframe
|
||||
var allConfigWid = BI.inherit(BI.Widget, { |
||||
|
||||
props: { |
||||
baseCls: "", |
||||
css: { |
||||
background: "#e3e3e3" |
||||
} |
||||
}, |
||||
beforeInit: function (callback) { |
||||
var self = this; |
||||
Dec.reqGet(getPath("allDefConfig", false), {}, function (data) { |
||||
console.info(data) |
||||
self.data = data.data; |
||||
callback(); |
||||
}) |
||||
}, |
||||
saveAction: function () { |
||||
var config = { |
||||
openLogin: this.openLogin.isSelected(), |
||||
onlyScan: this.onlyScan.isSelected(), |
||||
defaultScan: this.defaultScan.isSelected(), |
||||
} |
||||
Dec.reqPut(getPath("changeConfig", false), config, function (data) { |
||||
BI.Msg.toast("更新成功") |
||||
}); |
||||
}, |
||||
render: function () { |
||||
var self = this; |
||||
return { |
||||
type: "bi.vertical", |
||||
width:400, |
||||
hgap:40, |
||||
items: [ |
||||
{ |
||||
type: "bi.multi_select_item", |
||||
text: "默认开启扫码", |
||||
ref: function (e) { |
||||
self.defaultScan = e; |
||||
}, |
||||
selected: self.data.defaultScan, |
||||
}, |
||||
{ |
||||
type: "bi.multi_select_item", |
||||
text: "仅开启扫码(不保留密码登陆)", |
||||
ref: function (e) { |
||||
self.onlyScan = e; |
||||
}, |
||||
selected: self.data.onlyScan, |
||||
}, |
||||
{ |
||||
type: "bi.multi_select_item", |
||||
text: "打开扫码入口", |
||||
ref: function (e) { |
||||
self.openLogin = e; |
||||
}, |
||||
selected: self.data.openLogin, |
||||
}, |
||||
{ |
||||
type: "bi.right", |
||||
items: [ |
||||
{ |
||||
type: "bi.button", |
||||
text: "保存", |
||||
level: "info", |
||||
height: 30, |
||||
handler: function () { |
||||
self.saveAction(); |
||||
}, |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.bottom.config.all.area", allConfigWid); |
||||
// 组件实现,效果为使用绝对布局组件放置了一个iframe
|
||||
var toprow = BI.inherit(BI.Widget, { |
||||
|
||||
props: { |
||||
baseCls: "" |
||||
}, |
||||
beforeInit: function (callBack) { |
||||
var self = this; |
||||
Dec.reqGet(getPath("scan_entity", false), {}, function (data) { |
||||
console.info(data) |
||||
self.datas = data.data; |
||||
callBack(); |
||||
}) |
||||
}, |
||||
reloadList:function (){ |
||||
var self=this; |
||||
Dec.reqGet(getPath("scan_entity", false), {}, function (data) { |
||||
var da= data.data; |
||||
self.leftArea.populate(da); |
||||
}) |
||||
}, |
||||
saveAction: function () { |
||||
var self=this; |
||||
var value = this.rightArea.getValue(); |
||||
if(value.id){ |
||||
Dec.reqPut(getPath("scan_entity", false), value, function (data) { |
||||
console.info(data) |
||||
BI.Msg.toast("更新成功" + data.data.appName) |
||||
self.reloadList(); |
||||
}); |
||||
}else{ |
||||
Dec.reqPost(getPath("scan_entity", false), value, function (data) { |
||||
console.info(data) |
||||
self.reloadList(); |
||||
BI.Msg.toast("保存成功" + data.data.appName) |
||||
}); |
||||
} |
||||
}, |
||||
delAction: function (item) { |
||||
var self=this; |
||||
Dec.reqDelete(getPath("scan_entity/" + item.id, false), item, function (data) { |
||||
BI.Msg.toast("删除成功" + data.data.appName) |
||||
self.reloadList(); |
||||
}); |
||||
}, |
||||
changeAction: function (item) { |
||||
this.rightArea.setValue(item); |
||||
}, |
||||
createAction: function () { |
||||
this.rightArea.reset(); |
||||
}, |
||||
render: function () { |
||||
var self = this; |
||||
return { |
||||
type: "bi.horizontal", |
||||
vgap: 30, |
||||
items: [ |
||||
{ |
||||
type: "dd.scan.top.config.left.area", |
||||
height: 200, |
||||
lists: this.datas, |
||||
ref:function (e){ |
||||
self.leftArea=e; |
||||
}, |
||||
listeners: [{ |
||||
eventName: "CREATENEW", |
||||
action: function () { |
||||
self.createAction(); |
||||
} |
||||
}, { |
||||
eventName: "DELETED", |
||||
action: function (item) { |
||||
self.delAction(item); |
||||
} |
||||
}, { |
||||
eventName: "CLICKITEM", |
||||
action: function (item) { |
||||
self.changeAction(item); |
||||
} |
||||
},], |
||||
}, |
||||
{ |
||||
type: "dd.scan.top.config.right.area", |
||||
height: 400, |
||||
ref: function (e) { |
||||
self.rightArea = e; |
||||
}, |
||||
listeners: [{ |
||||
eventName: "SAVE", |
||||
action: function () { |
||||
self.saveAction(); |
||||
} |
||||
}], |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.top.row", toprow); |
||||
|
||||
// 这个组件需要编辑功能所以继承到BI.Single 这样可以继承到getValue和setValue
|
||||
var rightArea = BI.inherit(BI.Single, { |
||||
|
||||
props: { |
||||
//这个item是父级传下来的,如果有这个item 就表示这次是编辑而不是新建
|
||||
item: {} |
||||
}, |
||||
getValue: function () { |
||||
return { |
||||
id: this.options.item.id, |
||||
appName: this.appName.getValue(), |
||||
appId: this.appId.getValue(), |
||||
appKey: this.appKey.getValue(), |
||||
appIdSecret: this.appIdSecret.getValue(), |
||||
appSecret: this.appSecret.getValue(), |
||||
} |
||||
}, |
||||
setValue: function (item) { |
||||
this.options.item = item; |
||||
this.appName.setValue(item.appName); |
||||
this.appId.setValue(item.appId); |
||||
this.appSecret.setValue(item.appSecret); |
||||
this.appKey.setValue(item.appKey); |
||||
this.appIdSecret.setValue(item.appIdSecret); |
||||
}, |
||||
render: function () { |
||||
var self = this; |
||||
var item = this.options.item; |
||||
return { |
||||
type: "bi.vertical", |
||||
hgap: 10, |
||||
vgap:10, |
||||
items: [ |
||||
{ |
||||
type: "bi.horizontal_adapt", |
||||
height: 30, |
||||
width:300, |
||||
columnSize: [120, "fill"], |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "公司名称" |
||||
}, |
||||
{ |
||||
type: "bi.editor", cls: "bi-border", |
||||
value: item.appName, |
||||
width: 200, |
||||
height: 24, |
||||
ref: function (e) { |
||||
self.appName = e; |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
type: "bi.horizontal_adapt", |
||||
width:300, |
||||
columnSize: [120, "fill"], |
||||
height: 30, |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "appId" |
||||
}, |
||||
{ |
||||
type: "bi.editor", cls: "bi-border", |
||||
value: item.appId, |
||||
width: 200, |
||||
height: 24, |
||||
ref: function (e) { |
||||
self.appId = e; |
||||
} |
||||
} |
||||
] |
||||
},{ |
||||
type: "bi.horizontal_adapt", |
||||
width:300, |
||||
columnSize: [120, "fill"], |
||||
height: 30, |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "扫码的appSercet" |
||||
}, |
||||
{ |
||||
type: "bi.editor", cls: "bi-border", |
||||
value: item.appIdSecret, |
||||
width: 200, |
||||
height: 24, |
||||
ref: function (e) { |
||||
self.appIdSecret = e; |
||||
} |
||||
} |
||||
] |
||||
}, { |
||||
type: "bi.horizontal_adapt", |
||||
width:300, |
||||
columnSize: [120, "fill"], |
||||
height: 30, |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "appKey" |
||||
}, |
||||
{ |
||||
type: "bi.editor", cls: "bi-border", |
||||
value: item.appKey, |
||||
width: 200, |
||||
height: 24, |
||||
ref: function (e) { |
||||
self.appKey = e; |
||||
} |
||||
} |
||||
] |
||||
}, { |
||||
type: "bi.horizontal_adapt", |
||||
width:300, |
||||
columnSize: [120, "fill"], |
||||
height: 30, |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "应用的appSecret" |
||||
}, |
||||
{ |
||||
type: "bi.editor", cls: "bi-border", |
||||
width: 200, |
||||
height: 24, |
||||
value: item.appSecret, |
||||
ref: function (e) { |
||||
self.appSecret = e; |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
type: "bi.right", |
||||
items: [ |
||||
{ |
||||
type: "bi.button", |
||||
text: "保存", |
||||
level: "info", |
||||
height: 30, |
||||
handler: function () { |
||||
//这里只发送一个事件出去,由父级组件调用getValue来实现
|
||||
self.fireEvent("SAVE"); |
||||
}, |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.top.config.right.area", rightArea); |
||||
|
||||
// 组件实现,效果为使用绝对布局组件放置了一个iframe
|
||||
var topConfigWid = BI.inherit(BI.Widget, { |
||||
|
||||
props: { |
||||
lists: [] |
||||
}, |
||||
renderEditorItem: function (datas) { |
||||
var self = this; |
||||
return BI.map(datas, function (i, v) { |
||||
return { |
||||
type: "dd.scan.config.item", |
||||
item: v, |
||||
listeners: [{ |
||||
eventName: "DELETED", |
||||
action: function (item) { |
||||
self.fireEvent("DELETED", item); |
||||
}, |
||||
}, { |
||||
eventName: "CLICKITEM", |
||||
action: function (item) { |
||||
|
||||
self.fireEvent("CLICKITEM", item); |
||||
} |
||||
}] |
||||
} |
||||
}); |
||||
}, |
||||
populate:function (items){ |
||||
this.list.populate(this.renderEditorItem(items)) |
||||
}, |
||||
render: function () { |
||||
var self = this; |
||||
return { |
||||
type: "bi.vertical", |
||||
vgap: 10, |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "钉钉扫码配置列表" |
||||
}, |
||||
{ |
||||
type: "bi.button_group", |
||||
chooseType: BI.Selection.Single, |
||||
value: 2, |
||||
ref:function (e){ |
||||
self.list=e; |
||||
}, |
||||
items: this.renderEditorItem(this.options.lists), |
||||
layouts: [{ |
||||
vgap:10, |
||||
type: "bi.vertical", |
||||
}] |
||||
}, |
||||
{ |
||||
type: "bi.center_adapt", |
||||
items: [ |
||||
{ |
||||
type: "bi.button", |
||||
text: "新建", |
||||
level: "common", |
||||
height: 30, |
||||
width: 100, |
||||
handler: function () { |
||||
self.fireEvent("CREATENEW") |
||||
}, |
||||
|
||||
} |
||||
] |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.top.config.left.area", topConfigWid); |
||||
|
||||
|
||||
// 组件实现,效果为使用绝对布局组件放置了一个iframe
|
||||
var cofigItem = BI.inherit(BI.Widget, { |
||||
|
||||
props: { |
||||
item: { |
||||
appName: "", |
||||
id: "" |
||||
} |
||||
}, |
||||
|
||||
render: function () { |
||||
var self = this; |
||||
return { |
||||
type: "bi.horizontal_adapt", |
||||
width:300, |
||||
columnSize: [200, "fill"], |
||||
hgap: 30, |
||||
items: [ |
||||
{ |
||||
type: "bi.text_button", |
||||
text: this.options.item.appName, |
||||
handler: function () { |
||||
self.fireEvent("CLICKITEM", self.options.item) |
||||
} |
||||
}, |
||||
{ |
||||
type: "bi.button", |
||||
iconCls: "close-font", |
||||
height: 14, |
||||
handler: function () { |
||||
self.fireEvent("DELETED", self.options.item) |
||||
} |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
}); |
||||
BI.shortcut("dd.scan.config.item", cofigItem); |
Loading…
Reference in new issue