Browse Source

DEC-22054 feat:短信平台解耦demo插件

master
Roger.Chen 2 years ago
commit
2e3c918958
  1. 5
      .gitignore
  2. 122
      build.gradle
  3. 13
      encrypt.xml
  4. 20
      plugin.xml
  5. 45
      pom.xml
  6. 28
      readme.md
  7. BIN
      screenshots/open.png
  8. BIN
      screenshots/open2.png
  9. BIN
      screenshots/open3.png
  10. BIN
      screenshots/open4.png
  11. 16
      src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsComponent.java
  12. 13
      src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsControllerProvider.java
  13. 11
      src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsLocaleFinder.java
  14. 131
      src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsServiceProvider.java
  15. 17
      src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsWebResourceProvider.java
  16. 29
      src/main/java/com/fr/plugin/decision/third/sms/controller/ThirdSmsController.java
  17. 73
      src/main/java/com/fr/plugin/decision/third/sms/fun/SMSXmlReader.java
  18. 106
      src/main/java/com/fr/plugin/decision/third/sms/fun/SmsClient.java
  19. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms.properties
  20. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_en.properties
  21. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_ja_JP.properties
  22. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_ko_KR.properties
  23. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_zh.properties
  24. 0
      src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_zh_TW.properties
  25. 236
      src/main/resources/com/fr/plugin/decision/third/sms/web/sms.js
  26. 10
      src/main/resources/com/fr/plugin/decision/third/sms/xml/sms_template.xml
  27. 6
      src/main/resources/com/fr/plugin/decision/third/sms/xml/sms_template_mapping.xml

5
.gitignore vendored

@ -0,0 +1,5 @@
*.iml
.idea/
lib/report/*.jar
target/
.DS_Store

122
build.gradle

@ -0,0 +1,122 @@
apply plugin: 'java'
ext {
/**
* jar的路径
* 1.jar需要打包到zip中,lib根目录下
* 2.jar仅仅是编译时需要lib下子目录下即可
*/
libPath = "$projectDir/../webroot/WEB-INF/lib"
/**
* class进行加密保护
*/
guard = false
def pluginInfo = getPluginInfo()
pluginPre = "fine-plugin"
pluginName = pluginInfo.id
pluginVersion = pluginInfo.version
outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes"
}
group = 'com.fr.plugin'
version = '10.0'
sourceCompatibility = '8'
sourceSets {
main {
java.outputDir = file(outputPath)
output.resourcesDir = file(outputPath)
}
}
ant.importBuild("encrypt.xml")
//ant变量
ant.projectDir = projectDir
ant.references["compile.classpath"] = ant.path {
fileset(dir: libPath, includes: '**/*.jar')
fileset(dir: ".",includes:"**/*.jar" )
}
classes.dependsOn('clean')
task copyFiles(type: Copy,dependsOn: 'classes'){
from outputPath
into "$projectDir/classes"
}
task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){
from "$projectDir/classes"
into "$projectDir/transform-classes"
include "**/*.*"
}
jar.dependsOn("preJar")
task makeJar(type: Jar,dependsOn: preJar){
from fileTree(dir: "$projectDir/transform-classes")
baseName pluginPre
appendix pluginName
version pluginVersion
destinationDir = file("$buildDir/libs")
doLast(){
delete file("$projectDir/classes")
delete file("$projectDir/transform-classes")
}
}
task copyFile(type: Copy,dependsOn: ["makeJar"]){
from "$buildDir/libs"
from("$projectDir/lib") {
include "*.jar"
}
from "$projectDir/plugin.xml"
into file("$buildDir/temp/plugin")
}
task zip(type:Zip,dependsOn:["copyFile"]){
from "$buildDir/temp/plugin"
destinationDir file("$buildDir/install")
baseName pluginPre
appendix pluginName
version pluginVersion
}
//build时包含哪些文件,
processResources {
// exclude everything
// *.css没效果
// exclude '**/*.css'
// except this file
// include 'xx.xml'
}
/*读取plugin.xml中的version*/
def getPluginInfo(){
def xmlFile = file("plugin.xml")
if (!xmlFile.exists()) {
return ["id":"none", "version":"1.0.0"]
}
def plugin = new XmlParser().parse(xmlFile)
def version = plugin.version[0].text()
def id = plugin.id[0].text()
return ["id":id,"version":version]
}
repositories {
mavenLocal()
maven {
url = uri('http://mvn.finedevelop.com/repository/maven-public/')
}
}
dependencies {
//使jar
implementation fileTree(dir: 'lib', include: ['**/*.jar'])
implementation fileTree(dir: libPath, include: ['**/*.jar'])
}

13
encrypt.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<target name="compile_encrypt_javas" depends="copyFiles">
<echo message="加密文件"/>
<echo message="${projectDir}"/>
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask">
<classpath refid="compile.classpath"/>
</taskdef>
<pretreatment baseDir="${projectDir}"/>
</target>
<target name="compile_plain_javas" depends="copyFiles">
</target>
</project>

20
plugin.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.decision.third.sms.v11</id>
<name><![CDATA[新第三方短信插件]]></name>
<active>yes</active>
<version>1.0</version>
<env-version>11.0</env-version>
<jartime>2019-11-06</jartime>
<vendor>Lanlan</vendor>
<description><![CDATA[新第三方短信插件]]></description>
<extra-core>
<SMSServiceProvider class="com.fr.plugin.decision.third.sms.ThirdSmsServiceProvider"/>
<LocaleFinder class="com.fr.plugin.decision.third.sms.ThirdSmsLocaleFinder"/>
</extra-core>
<extra-decision>
<ControllerRegisterProvider class="com.fr.plugin.decision.third.sms.ThirdSmsControllerProvider"/>
<WebResourceProvider class="com.fr.plugin.decision.third.sms.ThirdSmsWebResourceProvider"/>
</extra-decision>
<function-recorder class="com.fr.plugin.decision.third.sms.ThirdSmsServiceProvider"/>
</plugin>

45
pom.xml

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>plugin</artifactId>
<groupId>com.fr.maven</groupId>
<version>10.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>fine-decision-sms-new-demo</artifactId>
<build>
<!---如果要更改调试插件,改这里的配置就可以了-->
<outputDirectory>
${web-inf-path}/plugins/plugin-com.fr.plugin.decision.third.sms.v11-2.0/classes
</outputDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.fr.core</groupId>
<artifactId>core-plugin-interface</artifactId>
<version>10.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fr.core</groupId>
<artifactId>core-project-plugin-interface</artifactId>
<version>10.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

28
readme.md

@ -0,0 +1,28 @@
# 第三方短信平台插件
## 开启短信
使用该插件可以不使用帆软内置的短信平台,只需要在购买短信功能点后,通过插件使用自己的短信平台即可,为了方便展示客户自己的账号信息,可以自己在插件中提供短信配置信息的接口,如下图所示:
![open](screenshots/open.png)
给管理员绑定手机号:
![open2](screenshots/open2.png)
绑定好后如图:
![open3](screenshots/open3.png)
开启短信验证密码:
![open4](screenshots/open4.png)
## 测试方式
可以在登录决策平台后,访问管理系统->系统管理->短信,点击信息测试处的发送测试短信。
## 测试时获取验证码
可以直接在日志中看到要短信发送的内容。

BIN
screenshots/open.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
screenshots/open2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
screenshots/open3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
screenshots/open4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

16
src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsComponent.java

@ -0,0 +1,16 @@
package com.fr.plugin.decision.third.sms;
import com.fr.web.struct.Component;
import com.fr.web.struct.browser.RequestClient;
import com.fr.web.struct.category.ParserType;
import com.fr.web.struct.category.ScriptPath;
public class ThirdSmsComponent extends Component {
public static final ThirdSmsComponent KEY = new ThirdSmsComponent();
@Override
public ScriptPath script(RequestClient req) {
return ScriptPath.build("com/fr/plugin/decision/third/sms/web/sms.js", ParserType.PLAIN);
}
}

13
src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsControllerProvider.java

@ -0,0 +1,13 @@
package com.fr.plugin.decision.third.sms;
import com.fr.decision.fun.impl.AbstractControllerRegisterProvider;
import com.fr.plugin.decision.third.sms.controller.ThirdSmsController;
public class ThirdSmsControllerProvider extends AbstractControllerRegisterProvider {
@Override
public Class<?>[] getControllers() {
return new Class[] {
ThirdSmsController.class
};
}
}

11
src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsLocaleFinder.java

@ -0,0 +1,11 @@
package com.fr.plugin.decision.third.sms;
import com.fr.stable.fun.impl.AbstractLocaleFinder;
public class ThirdSmsLocaleFinder extends AbstractLocaleFinder {
@Override
public String find() {
return "com/fr/plugin/decision/third/sms/locale/sms";
}
}

131
src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsServiceProvider.java

@ -0,0 +1,131 @@
package com.fr.plugin.decision.third.sms;
import com.fr.base.sms.SMSContext;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.decision.third.sms.fun.SMSXmlReader;
import com.fr.plugin.decision.third.sms.fun.SmsClient;
import com.fr.plugin.transform.ExecuteFunctionRecord;
import com.fr.plugin.transform.FunctionRecorder;
import com.fr.stable.fun.impl.AbstractSMSServiceProvider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@FunctionRecorder
public class ThirdSmsServiceProvider extends AbstractSMSServiceProvider {
private static final String SMS_PUBLIC_MODEL = "public-model";
private static final String SMS_PRIVATE_MODEL = "private-model";
public ThirdSmsServiceProvider() {
startListener();
}
@Override
public String sign() {
return SmsClient.getInstance().getSign();
}
/**
* 必须大于1,且跟js文件中的优先级保持一致
* @return
*/
@Override
public int priority() {
return 20;
}
@Override
public boolean isSMSAvailable() {
//根据具体情况看短信服务是否可用
return true;
}
/**
* 这里解析sms_template.xml文件中的模板返回实际获取短信服务的模板
*
* @return
*/
@Override
public Map<String, List<SMSTemplateBean>> getSMSTemplate() {
Map<String, List<SMSTemplateBean>> result = new HashMap<>();
Map<String, Map<String, Object>> smsTemplates = SmsClient.getInstance().getSMSTemplate();
result.put("publicModel", convertSMSTemplateBeanList(smsTemplates.get(SMS_PUBLIC_MODEL)));
result.put("privateModel", convertSMSTemplateBeanList(smsTemplates.get(SMS_PRIVATE_MODEL)));
return result;
}
/**
* 读取sms_template_mapping.xml配置文件中的映射规则
* @return
*/
@Override
public Map<String, String> mapping() {
Map<String, String> map = new HashMap<>();
Map<String, Object> templateMappings = SMSXmlReader.getSMSTemplateMappings();
for (Map.Entry<String, Object> entry : templateMappings.entrySet()) {
JSONObject jsonObject = JSONObject.mapFrom(entry.getValue());
if (jsonObject == null) {
continue;
}
map.put(entry.getKey(), jsonObject.getString("content"));
}
return map;
}
@Override
public Response sendTest(String mobile) {
SmsClient.getInstance().send(mobile);
return Response.create(Response.RES_STATUS_SUCCESS, "新插件发送测试短信成功", JSONObject.create());
}
@Override
@ExecuteFunctionRecord
public Response send(String template, String mobile, JSONObject para, String receiver) throws Exception {
SmsClient.getInstance().send(template, mobile, para, receiver);
FineLoggerFactory.getLogger().info("短信模板:{}, 手机号:{},参数:{}", template, mobile, para);
return Response.create(Response.RES_STATUS_SUCCESS, "新插件发送普通短信成功", JSONObject.create());
}
@Override
public Response batchSendSMS(String template, List<String> mobiles, JSONArray params, List<String> receivers) throws Exception {
SmsClient.getInstance().batchSend(template, mobiles, params, receivers);
return Response.create(Response.RES_STATUS_SUCCESS, "新插件发送批量短信成功", JSONObject.create());
}
/**
* 启动发送短信的监听器
*/
private void startListener() {
SMSContext.addSmsListener(new Listener() {
@Override
public void beforeSend(String text, List<String> mobiles, JSONArray params, List<String> receivers) {
System.out.println("发送短信前监听事件");
FineLoggerFactory.getLogger().info("发送短信前监听事件");
}
@Override
public void afterSend(String text, List<String> mobiles, JSONArray params, List<String> receivers, Response response) {
System.out.println("发送短信后监听事件");
FineLoggerFactory.getLogger().info("发送短信后监听事件");
}
});
}
private List<SMSTemplateBean> convertSMSTemplateBeanList(Map<String, Object> map) {
List<SMSTemplateBean> beanList = new ArrayList<>();
for (Object data : map.values()) {
JSONObject json = JSONObject.mapFrom(data);
if (json == null) {
continue;
}
beanList.add(SMSTemplateBean.create(json.getString("id"), json.getString("content"), json.getString("language")));
}
return beanList;
}
}

17
src/main/java/com/fr/plugin/decision/third/sms/ThirdSmsWebResourceProvider.java

@ -0,0 +1,17 @@
package com.fr.plugin.decision.third.sms;
import com.fr.decision.fun.impl.AbstractWebResourceProvider;
import com.fr.decision.web.MainComponent;
import com.fr.web.struct.Atom;
public class ThirdSmsWebResourceProvider extends AbstractWebResourceProvider {
@Override
public Atom attach() {
return MainComponent.KEY;
}
@Override
public Atom client() {
return ThirdSmsComponent.KEY;
}
}

29
src/main/java/com/fr/plugin/decision/third/sms/controller/ThirdSmsController.java

@ -0,0 +1,29 @@
package com.fr.plugin.decision.third.sms.controller;
import com.fr.decision.webservice.Response;
import com.fr.decision.webservice.annotation.VisitRefer;
import com.fr.plugin.decision.third.sms.fun.SmsClient;
import com.fr.third.springframework.stereotype.Controller;
import com.fr.third.springframework.web.bind.annotation.PathVariable;
import com.fr.third.springframework.web.bind.annotation.RequestMapping;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.third.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/{version}/third/sms")
public class ThirdSmsController {
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@VisitRefer(required = false)
public Response getSMSConfig(HttpServletRequest req,
HttpServletResponse res,
@PathVariable("version") String version) throws Exception {
return Response.ok(SmsClient.getInstance().getSmsConfig());
}
}

73
src/main/java/com/fr/plugin/decision/third/sms/fun/SMSXmlReader.java

@ -0,0 +1,73 @@
package com.fr.plugin.decision.third.sms.fun;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SMSXmlReader {
private static final Map<String, Map<String, Object>> SMS_TEMPLATES_MAP = new ConcurrentHashMap<>();
private static final String SMS_PUBLIC_MODEL = "public-model";
private static final String SMS_PRIVATE_MODEL = "private-model";
private static final String SMS_TEMPLATE_XML = "sms_template.xml";
private static final String SMS_TEMPLATE_MAPPING_XML = "sms_template_mapping.xml";
public static Map<String, Object> getPublicSMSTemplates() {
return getSMSTemplates(SMS_TEMPLATE_XML, SMS_PUBLIC_MODEL);
}
public static Map<String, Object> getPrivateSMSTemplates() {
return getSMSTemplates(SMS_TEMPLATE_XML, SMS_PRIVATE_MODEL);
}
public static Map<String, Object> getSMSTemplateMappings() {
return getSMSTemplates(SMS_TEMPLATE_MAPPING_XML, SMS_PUBLIC_MODEL);
}
public static Map<String, Object> getSMSTemplates(String xmlPath, String type) {
if (!SMS_TEMPLATES_MAP.containsKey(type)) {
synchronized (com.fr.base.sms.SMSXmlReader.class) {
Map<String, Object> map = new ConcurrentHashMap<>();
readXML(map, xmlPath, type);
if (!map.isEmpty()) {
SMS_TEMPLATES_MAP.put(type, map);
}
}
}
return SMS_TEMPLATES_MAP.get(type);
}
private static void readXML(Map<String, Object> map, String xmlFile, String nodeName) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String xmlPath = "com/fr/plugin/decision/third/sms/xml/".concat(xmlFile);
try {
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(SMSXmlReader.class.getClassLoader().getResourceAsStream(xmlPath));
NodeList bookList = document.getElementsByTagName(nodeName);
for (int i = 0; i < bookList.getLength(); i++) {
Node node = bookList.item(i);
String id = node.getAttributes().getNamedItem("id").getTextContent();
JSONObject jsonObject = JSONObject.create();
jsonObject.put("id", id);
jsonObject.put("content", node.getAttributes().getNamedItem("content").getTextContent());
jsonObject.put("language", node.getAttributes().getNamedItem("language").getTextContent());
map.put(id, jsonObject);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}

106
src/main/java/com/fr/plugin/decision/third/sms/fun/SmsClient.java

@ -0,0 +1,106 @@
package com.fr.plugin.decision.third.sms.fun;
import com.fr.base.sms.SMSTemplateType;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.SMSServiceProvider;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/11/8
* 这个是短信发送的客户端调用各家实际短信发送平台这里只通过输出日志的方式提供一个示例
*/
public class SmsClient {
private static final SmsClient instance = new SmsClient();
private static final String SMS_PUBLIC_MODEL = "public-model";
private static final String SMS_PRIVATE_MODEL = "private-model";
public static SmsClient getInstance() {
return instance;
}
public String getSign() {
return "第三方短信";
}
/**
* 获取短信配置信息
*
* @return 短信配置信息
*/
public Map<String, Object> getSmsConfig() {
Map<String, Object> result = new HashMap<>();
result.put("username", "优先级20");
result.put("balance", 102.20);
result.put("isSmsAvailable", true);
result.put("accountType", 1);
result.put("publicModel", JSONArray.create(SMSXmlReader.getPublicSMSTemplates()));
result.put("privateModel", JSONArray.create(SMSXmlReader.getPrivateSMSTemplates()));
result.put("sign", getSign());
initSmsModels(result, "publicModel");
initSmsModels(result, "privateModel");
return result;
}
public boolean send(String mobile) {
System.out.println("新插件(20)发送测试短信成功");
FineLoggerFactory.getLogger().info("新插件(20)发送测试短信成功");
return true;
}
public boolean send(String template, String mobile, JSONObject para, String receiver) {
System.out.println("新插件(20)发送普通短信成功");
FineLoggerFactory.getLogger().info("新插件(20)发送普通短信成功");
return true;
}
public boolean batchSend(String template, List<String> mobiles, JSONArray params, List<String> receivers) {
System.out.println("新插件(20)发送批量短信成功");
FineLoggerFactory.getLogger().info("新插件(20)发送批量短信成功");
return true;
}
private void initSmsModels(Map<String, Object> result, String key) {
if (result.containsKey(key)) {
List<Map<String, Object>> smsModels = new ArrayList<Map<String, Object>>();
JSONArray ja = (JSONArray) result.get(key);
for (int i = 0; i < ja.length(); i++) {
JSONObject jo = ja.optJSONObject(i);
Map<String, Object> map = new HashMap<String, Object>();
String language = jo.optString("language");
if (StringUtils.isNotEmpty(language) && StringUtils.equals(key, "publicModel") && !StringUtils.equals(language, SMSTemplateType.MAINLAND_SMS_TEMPLATE.getLanguage())) {
continue;
}
map.put("id", jo.optString("id"));
map.put("content", jo.optString("content"));
map.put("language", language);
smsModels.add(map);
}
result.put(key, smsModels);
}
}
public Map<String, Map<String, Object>> getSMSTemplate() {
Map<String, Map<String, Object>> result = new HashMap<>();
result.put(SMS_PUBLIC_MODEL, SMSXmlReader.getPublicSMSTemplates());
result.put(SMS_PRIVATE_MODEL, SMSXmlReader.getPrivateSMSTemplates());
return result;
}
}

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms.properties

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_en.properties

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_ja_JP.properties

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_ko_KR.properties

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_zh.properties

0
src/main/resources/com/fr/plugin/decision/third/sms/locale/sms_zh_TW.properties

236
src/main/resources/com/fr/plugin/decision/third/sms/web/sms.js

@ -0,0 +1,236 @@
// 邮箱配置组件的注册过程一共分为4步:
// 1.基础配置
var PRIORITY = 20; // 优先级(需要跟ThirdSmsServiceProvider#priority方法返回值一致),必须大于1,当有多个组件注册时,只有优先级最高的组件才会起作用
var WIDGET_TYPE = 'demo.system.sms.config'; // 组件名称
var MODEL_TYPE = 'demo.model.system.sms.config'; // 模型名称
// 2.定义组件
var LAYOUT = {
ITEM_HEIGHT: 24,
ITEM_GAP: 15,
LABEL_WIDTH: 120,
};
var Widget = BI.inherit(BI.Pane, {
props: {
baseCls: 'demo-system-sms-config',
},
_store: function () {
return BI.Models.getModel(MODEL_TYPE);
},
watch: {
'config.balance': function (value) {
this.balanceLabel.setText(config.balance + BI.i18nText('Dec-Basic_RMB'));
this.testButton.setEnable(value > 0);
},
},
beforeRender: function (callback) {
var self = this;
self.loading();
this.store.requestGetConfig(function () {
callback();
self.loaded();
});
},
render: function () {
var self = this;
var config = self.model.config;
return {
type: 'bi.vertical',
bgap: LAYOUT.ITEM_GAP,
items: [
// 账号绑定
{
type: 'bi.vertical_adapt',
height: LAYOUT.ITEM_HEIGHT,
items: [
{
type: 'bi.label',
cls: 'dec-font-weight-bold',
width: LAYOUT.LABEL_WIDTH,
text: BI.i18nText('Dec-System_SMS_Account_Bind'),
textAlign: 'left',
title: BI.i18nText('Dec-System_SMS_Account_Bind'),
},
{
type: 'bi.label',
text: config.username,
textAlign: 'left',
},
],
},
// 账号余额
{
type: 'bi.vertical_adapt',
height: LAYOUT.ITEM_HEIGHT,
items: [
{
type: 'bi.label',
cls: 'dec-font-weight-bold',
width: LAYOUT.LABEL_WIDTH,
text: BI.i18nText('Dec-System_SMS_Account_Balance'),
textAlign: 'left',
title: BI.i18nText('Dec-System_SMS_Account_Balance'),
},
{
type: 'bi.label',
ref: function (_ref) {
self.balanceLabel = _ref;
},
text: config.balance + BI.i18nText('Dec-Basic_RMB'),
textAlign: 'left',
},
],
},
// 短信签名
{
type: 'bi.vertical_adapt',
height: LAYOUT.ITEM_HEIGHT,
items: [
{
type: 'bi.label',
cls: 'dec-font-weight-bold',
width: LAYOUT.LABEL_WIDTH,
text: BI.i18nText('Dec-System_SMS_Signatures'),
textAlign: 'left',
title: BI.i18nText('Dec-System_SMS_Signatures'),
},
{
type: 'bi.label',
text: config.sign,
textAlign: 'left',
},
],
},
// 信息测试
{
type: 'bi.vertical_adapt',
height: LAYOUT.ITEM_HEIGHT,
items: [
{
type: 'bi.label',
cls: 'dec-font-weight-bold',
width: LAYOUT.LABEL_WIDTH,
text: BI.i18nText('Dec-System_SMS_Test'),
textAlign: 'left',
title: BI.i18nText('Dec-System_SMS_Test'),
},
{
type: 'bi.button',
ref: function (_ref) {
self.testButton = _ref;
},
text: BI.i18nText('Dec-System_Send_Test_SMS'),
textAlign: 'left',
clear: true,
disabled: config.balance <= 0,
handler: function () {
self._sendTestMessage();
},
},
],
},
],
};
},
/**
* 发送测试短信
*/
_sendTestMessage: function () {
var self = this;
var popoverName = BI.UUID();
BI.Popovers.create(popoverName, {
type: 'bi.popover',
width: 450,
height: 220,
header: BI.i18nText('Dec-System_Send_Test_Sms'),
body: {
type: 'dec.send.test.msg.dialog',
listeners: [
{
eventName: BI.Popover.EVENT_CONFIRM,
action: function (phone) {
self.store.requsetSendTestMessage(phone);
},
},
{
eventName: BI.Popover.EVENT_CLOSE,
action: function () {
BI.Popovers.remove(popoverName);
},
},
],
},
});
BI.Popovers.show(popoverName);
},
});
// 3.定义模型
var Model = BI.inherit(Fix.Model, {
state: function () {
return {
config: {
isSmsAvailable: true,
accountType: 1,
username: '',
balance: 0,
sign: '',
publicModel: [],
privateModel: [],
},
};
},
actions: {
/**
* 获取邮箱配置
* @param {Function} callback beforeRender的回调
*/
requestGetConfig: function (callback) {
var self = this;
// 发送请求,获取配置
Dec.reqGetHandle('/v10/third/sms', '', function (data) {
self.model.config = data;
BI.isFunction(callback) && callback();
});
},
/**
* 发送测试邮件
* @param {string} phone 收件人号码
*/
requsetSendTestMessage: function (phone) {
var self = this;
Dec.reqPost(
'/v10/config/sms/test',
{
mobile: phone,
},
function (result) {
if (result && result.data && result.data.code === 'success') {
BI.Msg.toast(BI.i18nText('Dec-Send_Success'), { level: 'success' });
} else {
BI.Msg.toast(BI.i18nText('Dec-System_SMS_Send_Fail'), {
level: 'error',
});
}
self.requestGetConfig();
}
);
},
},
});
// 4.注册组件
BI.shortcut(WIDGET_TYPE, Widget); // 注册组件
BI.model(MODEL_TYPE, Model); // 注册模型
BI.config('dec.provider.system', function (provider) {
provider.registerSmsConfigWidget(WIDGET_TYPE, PRIORITY); // 注册邮箱配置组件
});

10
src/main/resources/com/fr/plugin/decision/third/sms/xml/sms_template.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<sms-template>
<public-model id="10" content="【信息平台】尊敬的管理员,#taskname#于#time#运行失败,请知晓。" language="zh_CN"/>
<public-model id="306" content="【信息平台】尊敬的管理員,#taskname#於#time#運行失敗,請知曉。" language="zh_TW"/>
<public-model id="329" content="【信息平台】Dear administrator, #taskname# failed to run at #time#." language="en_US"/>
<public-model id="1005" content="【信息平台】Dear administrator" language="en_US"/>
<private-model id="101" content="【第三方短信】私人短信" language="zh_CN"/>
<private-model id="102" content="【第三方短信】私人短信2" language="zh_CN"/>
</sms-template>

6
src/main/resources/com/fr/plugin/decision/third/sms/xml/sms_template_mapping.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<sms-template>
<public-model id="10" content="【我的短信映射】尊敬的管理员,#taskname#于#time#运行失败,请知晓。" language="zh_CN"/>
<public-model id="306" content="【我的短信映射】尊敬的管理員,#taskname#於#time#運行失敗,請知曉。" language="zh_TW"/>
<public-model id="329" content="【我的短信映射】Dear administrator, #taskname# failed to run at #time#." language="en_US"/>
</sms-template>
Loading…
Cancel
Save